blob: ac6470decda533e99bbc06e23fe4300ad1bfea33 [file] [log] [blame]
swissChili7a6f5eb2021-04-13 16:46:02 -07001#include "lisp.h"
swissChili6d02af42021-08-05 19:49:01 -07002#include "error.h"
swissChili8cfb7c42021-04-18 21:17:58 -07003#include "plat/plat.h"
4
swissChili7a6f5eb2021-04-13 16:46:02 -07005#include <ctype.h>
6#include <stdbool.h>
7#include <stdio.h>
swissChilibed80922021-04-13 21:58:05 -07008#include <stdlib.h>
9#include <string.h>
swissChili7e1393c2021-07-07 12:59:12 -070010#include <stdarg.h>
swissChili7a6f5eb2021-04-13 16:46:02 -070011
swissChili9e57da42021-06-15 22:22:46 -070012struct alloc *first_a = NULL, *last_a = NULL;
swissChili7a6f5eb2021-04-13 16:46:02 -070013
swissChili8cfb7c42021-04-18 21:17:58 -070014value_t nil = 0b00101111; // magic ;)
swissChili923b5362021-05-09 20:31:43 -070015value_t t = 1 << 3;
swissChilibed80922021-04-13 21:58:05 -070016
swissChilib8fd4712021-06-23 15:32:04 -070017unsigned char max_pool = 0, current_pool = 0;
18
swissChili53472e82021-05-08 16:06:32 -070019value_t intval(int i)
swissChili7a6f5eb2021-04-13 16:46:02 -070020{
swissChili8cfb7c42021-04-18 21:17:58 -070021 i <<= 2;
22 i |= INT_TAG;
23 return i;
24}
25
swissChilif1ba8c12021-07-02 18:45:38 -070026void add_this_alloc(struct alloc *a, int tag)
27{
28 a->type_tag = tag;
29 a->pool = current_pool;
30
31 if (last_a)
32 {
33 a->prev = last_a;
34 last_a->next = a;
35 a->next = NULL;
36 last_a = a;
37 }
38 else
39 {
40 a->prev = a->next = NULL;
41 first_a = last_a = a;
42 }
43}
44
swissChili53472e82021-05-08 16:06:32 -070045value_t cons(value_t car, value_t cdr)
swissChili8cfb7c42021-04-18 21:17:58 -070046{
swissChili9e57da42021-06-15 22:22:46 -070047 struct cons_alloc *item = malloc_aligned(sizeof(struct cons_alloc));
48 struct cons *c = &item->cons;
swissChili7a6f5eb2021-04-13 16:46:02 -070049
swissChilibed80922021-04-13 21:58:05 -070050 c->car = car;
51 c->cdr = cdr;
swissChili2999dd12021-07-02 14:19:53 -070052 c->line = 0;
53 c->name = NULL;
swissChilibed80922021-04-13 21:58:05 -070054
swissChilib3ca4fb2021-04-20 10:33:00 -070055 value_t v = (value_t)c;
swissChili8cfb7c42021-04-18 21:17:58 -070056 v |= CONS_TAG;
swissChili7a6f5eb2021-04-13 16:46:02 -070057
swissChilif1ba8c12021-07-02 18:45:38 -070058 add_this_alloc(&item->alloc, CONS_TAG);
59
swissChili7a6f5eb2021-04-13 16:46:02 -070060 return v;
61}
62
swissChili53472e82021-05-08 16:06:32 -070063void skipws(struct istream *is)
swissChili7a6f5eb2021-04-13 16:46:02 -070064{
swissChilib8fd4712021-06-23 15:32:04 -070065start:
swissChili53472e82021-05-08 16:06:32 -070066 while (isspace(is->peek(is)))
67 is->get(is);
swissChilib8fd4712021-06-23 15:32:04 -070068
69 if (is->peek(is) == ';')
70 {
71 while (is->get(is) != '\n')
swissChiliddc97542021-07-04 11:47:42 -070072 {
73 }
swissChilib8fd4712021-06-23 15:32:04 -070074
75 // Only time I ever use labels is for stuff like this. Compiler would
76 // probably optimize this if I used recursion but I don't want to
77 // bother.
78 goto start;
79 }
swissChili7a6f5eb2021-04-13 16:46:02 -070080}
81
swissChili53472e82021-05-08 16:06:32 -070082bool isallowedchar(char c)
swissChili7a6f5eb2021-04-13 16:46:02 -070083{
swissChilibed80922021-04-13 21:58:05 -070084 return (c >= '#' && c <= '\'') || (c >= '*' && c <= '/') ||
swissChili53e7cd12021-08-02 21:55:53 -070085 (c >= '<' && c <= '@');
swissChili7a6f5eb2021-04-13 16:46:02 -070086}
87
swissChili53472e82021-05-08 16:06:32 -070088bool issymstart(char c)
swissChili7a6f5eb2021-04-13 16:46:02 -070089{
swissChili53472e82021-05-08 16:06:32 -070090 return isalpha(c) || isallowedchar(c);
swissChili7a6f5eb2021-04-13 16:46:02 -070091}
92
swissChili53472e82021-05-08 16:06:32 -070093bool issym(char c)
swissChili7a6f5eb2021-04-13 16:46:02 -070094{
swissChili53472e82021-05-08 16:06:32 -070095 return isalpha(c) || isallowedchar(c) || isdigit(c);
swissChili7a6f5eb2021-04-13 16:46:02 -070096}
97
swissChili6d02af42021-08-05 19:49:01 -070098struct error readsym(struct istream *is, value_t *val)
swissChili7a6f5eb2021-04-13 16:46:02 -070099{
swissChili6d02af42021-08-05 19:49:01 -0700100 E_INIT();
101
swissChili53472e82021-05-08 16:06:32 -0700102 skipws(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700103
swissChili53472e82021-05-08 16:06:32 -0700104 if (!issymstart(is->peek(is)))
swissChili6d02af42021-08-05 19:49:01 -0700105 THROWSAFE(EEXPECTED);
swissChili7a6f5eb2021-04-13 16:46:02 -0700106
107 int size = 8;
swissChilif1ba8c12021-07-02 18:45:38 -0700108 struct alloc *a = malloc_aligned(size + sizeof(struct alloc));
swissChilif1ba8c12021-07-02 18:45:38 -0700109
110 char *s = (char *)(a + 1);
swissChili7a6f5eb2021-04-13 16:46:02 -0700111
swissChili53472e82021-05-08 16:06:32 -0700112 s[0] = is->get(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700113
swissChili53472e82021-05-08 16:06:32 -0700114 for (int i = 1;; i++)
swissChili7a6f5eb2021-04-13 16:46:02 -0700115 {
swissChili53e7cd12021-08-02 21:55:53 -0700116 if (i >= size)
117 {
118 size *= 2;
119 a = realloc_aligned(a, size + sizeof(struct alloc));
120 s = (char *)(a + 1);
121 }
122
swissChili53472e82021-05-08 16:06:32 -0700123 if (issym(is->peek(is)))
swissChili7a6f5eb2021-04-13 16:46:02 -0700124 {
swissChili53472e82021-05-08 16:06:32 -0700125 s[i] = is->get(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700126 }
127 else
128 {
swissChili53472e82021-05-08 16:06:32 -0700129 s[i] = 0;
swissChilib3ca4fb2021-04-20 10:33:00 -0700130 *val = (value_t)s;
swissChili8cfb7c42021-04-18 21:17:58 -0700131 *val |= SYMBOL_TAG;
swissChili7a6f5eb2021-04-13 16:46:02 -0700132
swissChili53e7cd12021-08-02 21:55:53 -0700133 add_this_alloc(a, SYMBOL_TAG);
swissChili6d02af42021-08-05 19:49:01 -0700134
135 OKAY();
swissChili7a6f5eb2021-04-13 16:46:02 -0700136 }
137 }
138}
139
swissChili6d02af42021-08-05 19:49:01 -0700140struct error readstr(struct istream *is, value_t *val)
swissChili7a6f5eb2021-04-13 16:46:02 -0700141{
swissChili6d02af42021-08-05 19:49:01 -0700142 E_INIT();
143
swissChili53472e82021-05-08 16:06:32 -0700144 skipws(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700145
swissChili53472e82021-05-08 16:06:32 -0700146 if (is->peek(is) != '"')
swissChili6d02af42021-08-05 19:49:01 -0700147 THROWSAFE(EEXPECTED);
swissChili7a6f5eb2021-04-13 16:46:02 -0700148
149 bool escape = false;
150 int size = 8;
swissChilif1ba8c12021-07-02 18:45:38 -0700151
152 struct alloc *a = malloc_aligned(size + sizeof(struct alloc));
swissChilif1ba8c12021-07-02 18:45:38 -0700153
154 char *s = (char *)(a + 1);
swissChili7a6f5eb2021-04-13 16:46:02 -0700155
swissChili53472e82021-05-08 16:06:32 -0700156 (void)is->get(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700157
swissChili53472e82021-05-08 16:06:32 -0700158 for (int i = 0;; i++)
swissChili7a6f5eb2021-04-13 16:46:02 -0700159 {
swissChili53472e82021-05-08 16:06:32 -0700160 if (is->peek(is) != '"')
swissChili7a6f5eb2021-04-13 16:46:02 -0700161 {
swissChili53472e82021-05-08 16:06:32 -0700162 if (i >= size)
swissChili7a6f5eb2021-04-13 16:46:02 -0700163 {
swissChilibed80922021-04-13 21:58:05 -0700164 size *= 2;
swissChilif1ba8c12021-07-02 18:45:38 -0700165 a = realloc_aligned(a, size + sizeof(struct alloc));
166 s = (char *)(a + 1);
swissChili7a6f5eb2021-04-13 16:46:02 -0700167 }
swissChilibed80922021-04-13 21:58:05 -0700168
swissChili53472e82021-05-08 16:06:32 -0700169 char c = is->get(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700170
swissChili53472e82021-05-08 16:06:32 -0700171 if (escape && c == 'n')
swissChili7a6f5eb2021-04-13 16:46:02 -0700172 c = '\n';
swissChili53472e82021-05-08 16:06:32 -0700173 else if (escape && c == '\\')
swissChili7a6f5eb2021-04-13 16:46:02 -0700174 c = '\\';
175
swissChili53472e82021-05-08 16:06:32 -0700176 if (c == '\\' && !escape)
swissChili7a6f5eb2021-04-13 16:46:02 -0700177 {
178 escape = true;
179 i--; // will be incremented again, UGLY.
180 }
181 else
182 {
183 escape = false;
swissChili53472e82021-05-08 16:06:32 -0700184 s[i] = c;
swissChili7a6f5eb2021-04-13 16:46:02 -0700185 }
186 }
187 else
188 {
swissChili7e1393c2021-07-07 12:59:12 -0700189 s[i] = '\0';
swissChili53472e82021-05-08 16:06:32 -0700190 is->get(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700191
swissChilib3ca4fb2021-04-20 10:33:00 -0700192 *val = (value_t)s;
swissChili8cfb7c42021-04-18 21:17:58 -0700193 *val |= STRING_TAG;
swissChili7a6f5eb2021-04-13 16:46:02 -0700194
swissChili53e7cd12021-08-02 21:55:53 -0700195 add_this_alloc(a, STRING_TAG);
swissChili6d02af42021-08-05 19:49:01 -0700196
197 OKAY();
swissChili7a6f5eb2021-04-13 16:46:02 -0700198 }
199 }
200}
201
swissChilie0d4b902022-07-30 17:32:01 -0700202void printval_ol(value_t v)
swissChili7a6f5eb2021-04-13 16:46:02 -0700203{
swissChilie0d4b902022-07-30 17:32:01 -0700204// for (int i = 0; i < depth; i++)
205// printf(" ");
swissChili7a6f5eb2021-04-13 16:46:02 -0700206
swissChili53472e82021-05-08 16:06:32 -0700207 if (symbolp(v))
swissChili7a6f5eb2021-04-13 16:46:02 -0700208 {
swissChilie0d4b902022-07-30 17:32:01 -0700209 printf("%s", (char *)(v ^ SYMBOL_TAG));
swissChili8cfb7c42021-04-18 21:17:58 -0700210 }
swissChili53472e82021-05-08 16:06:32 -0700211 else if (stringp(v))
swissChili8cfb7c42021-04-18 21:17:58 -0700212 {
swissChilie0d4b902022-07-30 17:32:01 -0700213 printf("\"%s\"", (char *)(v ^ STRING_TAG));
swissChili8cfb7c42021-04-18 21:17:58 -0700214 }
swissChili53472e82021-05-08 16:06:32 -0700215 else if (integerp(v))
swissChili6eee4f92021-04-20 09:34:30 -0700216 {
swissChilie0d4b902022-07-30 17:32:01 -0700217 printf("%d", v >> 2);
swissChili6eee4f92021-04-20 09:34:30 -0700218 }
swissChili53472e82021-05-08 16:06:32 -0700219 else if (consp(v))
swissChili8cfb7c42021-04-18 21:17:58 -0700220 {
swissChili53472e82021-05-08 16:06:32 -0700221 if (listp(v))
swissChilibed80922021-04-13 21:58:05 -0700222 {
swissChilie0d4b902022-07-30 17:32:01 -0700223 printf("(");
224 printval_ol(car(v));
swissChilibed80922021-04-13 21:58:05 -0700225
swissChilie0d4b902022-07-30 17:32:01 -0700226 for (value_t n = cdr(v); !nilp(n); n = cdr(n))
swissChilibed80922021-04-13 21:58:05 -0700227 {
swissChilie0d4b902022-07-30 17:32:01 -0700228 printf(" ");
229 printval_ol(car(n));
swissChilibed80922021-04-13 21:58:05 -0700230 }
swissChilie0d4b902022-07-30 17:32:01 -0700231
232 printf(")");
swissChilibed80922021-04-13 21:58:05 -0700233 }
234 else
235 {
swissChilie0d4b902022-07-30 17:32:01 -0700236 printf("(");
237 printval_ol(car(v));
238 printf(" . ");
239 printval_ol(cdr(v));
240 printf(")");
swissChilibed80922021-04-13 21:58:05 -0700241 }
swissChili8cfb7c42021-04-18 21:17:58 -0700242 }
swissChili53472e82021-05-08 16:06:32 -0700243 else if (nilp(v))
swissChili8cfb7c42021-04-18 21:17:58 -0700244 {
swissChili53472e82021-05-08 16:06:32 -0700245 printf("nil\n");
swissChili8cfb7c42021-04-18 21:17:58 -0700246 }
swissChiliddc97542021-07-04 11:47:42 -0700247 else if (closurep(v))
248 {
249 struct closure *c = (void *)(v ^ CLOSURE_TAG);
swissChilie0d4b902022-07-30 17:32:01 -0700250 printf("<closure %p (%d) %d>",
swissChili15f1cae2021-07-05 19:08:47 -0700251 c->function, c->args->num_required, c->num_captured);
swissChiliddc97542021-07-04 11:47:42 -0700252 }
swissChili8cfb7c42021-04-18 21:17:58 -0700253 else
254 {
swissChilie0d4b902022-07-30 17:32:01 -0700255 printf("<unknown %d>", v);
swissChili7a6f5eb2021-04-13 16:46:02 -0700256 }
257}
258
swissChilie0d4b902022-07-30 17:32:01 -0700259void printval(value_t v, int depth)
260{
261 UNUSED(depth);
262 printval_ol(v);
263 printf("\n");
264}
265
swissChili6d02af42021-08-05 19:49:01 -0700266struct error readlist(struct istream *is, value_t *val)
swissChilibed80922021-04-13 21:58:05 -0700267{
swissChili6d02af42021-08-05 19:49:01 -0700268 E_INIT();
269 NEARIS(is);
270
swissChili53472e82021-05-08 16:06:32 -0700271 skipws(is);
swissChilibed80922021-04-13 21:58:05 -0700272
swissChili53472e82021-05-08 16:06:32 -0700273 if (is->peek(is) != '(')
swissChili6d02af42021-08-05 19:49:01 -0700274 THROWSAFE(EEXPECTED);
swissChilibed80922021-04-13 21:58:05 -0700275
swissChili53472e82021-05-08 16:06:32 -0700276 is->get(is);
swissChilibed80922021-04-13 21:58:05 -0700277
swissChili53472e82021-05-08 16:06:32 -0700278 *val = readn(is);
swissChilibed80922021-04-13 21:58:05 -0700279
swissChili53e7cd12021-08-02 21:55:53 -0700280 skipws(is);
281
swissChili53472e82021-05-08 16:06:32 -0700282 if (is->peek(is) != ')')
swissChilibed80922021-04-13 21:58:05 -0700283 {
swissChili6d02af42021-08-05 19:49:01 -0700284 NEARIS(is);
285 THROW(EEXPECTED, "Unterminated list");
swissChilibed80922021-04-13 21:58:05 -0700286 }
swissChili53472e82021-05-08 16:06:32 -0700287 is->get(is);
swissChilibed80922021-04-13 21:58:05 -0700288
swissChili6d02af42021-08-05 19:49:01 -0700289 OKAY();
swissChilibed80922021-04-13 21:58:05 -0700290}
291
swissChili6d02af42021-08-05 19:49:01 -0700292struct error readint(struct istream *is, value_t *val)
swissChili6eee4f92021-04-20 09:34:30 -0700293{
swissChili6d02af42021-08-05 19:49:01 -0700294 E_INIT();
295
swissChilib6c858c2021-06-30 21:12:43 -0700296 skipws(is);
297
swissChili6eee4f92021-04-20 09:34:30 -0700298 int number = 0;
299
swissChili53472e82021-05-08 16:06:32 -0700300 if (!isdigit(is->peek(is)))
swissChili6d02af42021-08-05 19:49:01 -0700301 THROWSAFE(EEXPECTED);
swissChili6eee4f92021-04-20 09:34:30 -0700302
swissChili53472e82021-05-08 16:06:32 -0700303 while (isdigit(is->peek(is)))
swissChili6eee4f92021-04-20 09:34:30 -0700304 {
305 number *= 10;
swissChili53472e82021-05-08 16:06:32 -0700306 number += is->get(is) - '0';
swissChili6eee4f92021-04-20 09:34:30 -0700307 }
308
swissChili53472e82021-05-08 16:06:32 -0700309 *val = intval(number);
swissChili6d02af42021-08-05 19:49:01 -0700310 OKAY();
swissChili6eee4f92021-04-20 09:34:30 -0700311}
312
swissChili6d02af42021-08-05 19:49:01 -0700313struct error readquote(struct istream *is, value_t *val)
swissChilib6c858c2021-06-30 21:12:43 -0700314{
swissChili6d02af42021-08-05 19:49:01 -0700315 E_INIT();
316
swissChilib6c858c2021-06-30 21:12:43 -0700317 skipws(is);
318
319 char c = is->peek(is);
320
swissChili74348422021-07-04 13:23:24 -0700321 if (c == '\'' || c == '`' || c == ',' || c == '#')
swissChilib6c858c2021-06-30 21:12:43 -0700322 {
323 is->get(is);
324
swissChili74348422021-07-04 13:23:24 -0700325 if (c == ',' && is->peek(is) == '@')
swissChilib6c858c2021-06-30 21:12:43 -0700326 {
327 // This is actually a splice
328 is->get(is);
329 c = '@';
330 }
swissChili74348422021-07-04 13:23:24 -0700331 else if (c == '#' && is->peek(is) == '\'')
332 {
333 is->get(is);
334 }
swissChilib6c858c2021-06-30 21:12:43 -0700335
336 // Read the next form and wrap it in the appropriate function
337
338 value_t wrapped;
swissChili6d02af42021-08-05 19:49:01 -0700339 NEARIS(is);
swissChilib6c858c2021-06-30 21:12:43 -0700340
swissChili36f2c692021-08-08 14:31:44 -0700341 struct error read_error = read1(is, &wrapped);
342 TRY_ELSE(read_error, EEXPECTED, "Expected a form after reader macro char %c", c);
swissChilib6c858c2021-06-30 21:12:43 -0700343
344 value_t symbol = nil;
345
346 switch (c)
347 {
348 case '\'':
349 symbol = symval("quote");
350 break;
351 case '`':
352 symbol = symval("backquote");
353 break;
354 case ',':
355 symbol = symval("unquote");
356 break;
357 case '@':
swissChili6b47b6d2021-06-30 22:08:55 -0700358 symbol = symval("unquote-splice");
swissChilib6c858c2021-06-30 21:12:43 -0700359 break;
swissChili74348422021-07-04 13:23:24 -0700360 case '#':
361 symbol = symval("function");
362 break;
363 default:
swissChili6d02af42021-08-05 19:49:01 -0700364 NEARIS(is);
365 THROW(EINVALID, "Invalid reader macro char %c", c);
swissChilib6c858c2021-06-30 21:12:43 -0700366 }
367
368 *val = cons(symbol, cons(wrapped, nil));
369
swissChili6d02af42021-08-05 19:49:01 -0700370 OKAY();
swissChilib6c858c2021-06-30 21:12:43 -0700371 }
372 else
373 {
swissChili6d02af42021-08-05 19:49:01 -0700374 THROWSAFE(EEXPECTED);
swissChilib6c858c2021-06-30 21:12:43 -0700375 }
376}
377
swissChili6d02af42021-08-05 19:49:01 -0700378struct error read1(struct istream *is, value_t *val)
swissChili7a6f5eb2021-04-13 16:46:02 -0700379{
swissChili6d02af42021-08-05 19:49:01 -0700380 E_INIT();
swissChilib6c858c2021-06-30 21:12:43 -0700381
swissChili6d02af42021-08-05 19:49:01 -0700382 NEARIS(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700383
swissChili6d02af42021-08-05 19:49:01 -0700384 OKAY_IF(readquote(is, val));
385 OKAY_IF(readsym(is, val));
386 OKAY_IF(readstr(is, val));
387 OKAY_IF(readint(is, val));
388 OKAY_IF(readlist(is, val));
swissChili7a6f5eb2021-04-13 16:46:02 -0700389
swissChili6d02af42021-08-05 19:49:01 -0700390 THROWSAFE(EEXPECTED);
swissChili7a6f5eb2021-04-13 16:46:02 -0700391}
392
swissChili2999dd12021-07-02 14:19:53 -0700393void set_cons_info(value_t cons, int line, char *name)
394{
395 if (!consp(cons))
396 return;
397
398 struct cons *ca = (void *)(cons ^ CONS_TAG);
399
400 ca->line = line;
401 ca->name = name;
402}
403
swissChili53472e82021-05-08 16:06:32 -0700404value_t readn(struct istream *is)
swissChilibed80922021-04-13 21:58:05 -0700405{
swissChili8cfb7c42021-04-18 21:17:58 -0700406 value_t first = nil;
407 value_t *last = &first;
swissChilibed80922021-04-13 21:58:05 -0700408
swissChili8cfb7c42021-04-18 21:17:58 -0700409 value_t read_val;
swissChilibed80922021-04-13 21:58:05 -0700410
swissChili6d02af42021-08-05 19:49:01 -0700411 while (IS_OKAY(read1(is, &read_val)))
swissChilibed80922021-04-13 21:58:05 -0700412 {
swissChili2999dd12021-07-02 14:19:53 -0700413 int line;
414 char *file;
415
416 is->getpos(is, &line, &file);
swissChili53472e82021-05-08 16:06:32 -0700417 *last = cons(read_val, nil);
swissChili2999dd12021-07-02 14:19:53 -0700418 set_cons_info(*last, line, file);
419
swissChili53472e82021-05-08 16:06:32 -0700420 last = cdrref(*last);
swissChilibed80922021-04-13 21:58:05 -0700421 }
422
423 return first;
424}
425
swissChili53472e82021-05-08 16:06:32 -0700426bool startswith(struct istream *s, char *pattern)
swissChili7a6f5eb2021-04-13 16:46:02 -0700427{
swissChili53472e82021-05-08 16:06:32 -0700428 char *check = strdup(pattern);
429 s->read(s, check, strlen(pattern));
swissChili7a6f5eb2021-04-13 16:46:02 -0700430
swissChili53472e82021-05-08 16:06:32 -0700431 bool res = strcmp(check, pattern) == 0;
432 free(check);
swissChili7a6f5eb2021-04-13 16:46:02 -0700433
434 return res;
435}
swissChilibed80922021-04-13 21:58:05 -0700436
swissChilif1ba8c12021-07-02 18:45:38 -0700437static value_t strptrval(char *str, int tag)
swissChilibed80922021-04-13 21:58:05 -0700438{
swissChili8cfb7c42021-04-18 21:17:58 -0700439 value_t v;
440
swissChilif1ba8c12021-07-02 18:45:38 -0700441 struct alloc *al = malloc_aligned(strlen(str) + 1 + sizeof(struct alloc));
442 add_this_alloc(al, SYMBOL_TAG);
443
444 char *a = (char *)(al + 1);
445
swissChilib6c858c2021-06-30 21:12:43 -0700446 strcpy(a, str);
swissChilib3ca4fb2021-04-20 10:33:00 -0700447 v = (value_t)a;
swissChilif1ba8c12021-07-02 18:45:38 -0700448 v |= tag;
swissChilibed80922021-04-13 21:58:05 -0700449
450 return v;
451}
452
swissChilif1ba8c12021-07-02 18:45:38 -0700453value_t strval(char *str)
454{
455 return strptrval(str, STRING_TAG);
456}
457
swissChilib6c858c2021-06-30 21:12:43 -0700458value_t symval(char *str)
459{
swissChilif1ba8c12021-07-02 18:45:38 -0700460 return strptrval(str, SYMBOL_TAG);
swissChilib6c858c2021-06-30 21:12:43 -0700461}
462
swissChili53472e82021-05-08 16:06:32 -0700463bool integerp(value_t v)
swissChilibed80922021-04-13 21:58:05 -0700464{
swissChili8cfb7c42021-04-18 21:17:58 -0700465 return (v & INT_MASK) == INT_TAG;
466}
swissChilibed80922021-04-13 21:58:05 -0700467
swissChili53472e82021-05-08 16:06:32 -0700468bool symbolp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700469{
470 return (v & HEAP_MASK) == SYMBOL_TAG;
471}
472
swissChili53472e82021-05-08 16:06:32 -0700473bool stringp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700474{
475 return (v & HEAP_MASK) == STRING_TAG;
476}
477
swissChili53472e82021-05-08 16:06:32 -0700478bool consp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700479{
480 return (v & HEAP_MASK) == CONS_TAG;
481}
482
swissChili9e57da42021-06-15 22:22:46 -0700483bool heapp(value_t v)
484{
swissChiliddc97542021-07-04 11:47:42 -0700485 return consp(v) || stringp(v) || symbolp(v) || closurep(v);
486}
487
488bool closurep(value_t v)
489{
490 return (v & HEAP_MASK) == CLOSURE_TAG;
swissChili9e57da42021-06-15 22:22:46 -0700491}
492
swissChili53472e82021-05-08 16:06:32 -0700493bool listp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700494{
495 value_t next = v;
496
swissChili53472e82021-05-08 16:06:32 -0700497 while (consp(next))
swissChilibed80922021-04-13 21:58:05 -0700498 {
swissChili53472e82021-05-08 16:06:32 -0700499 next = cdr(next);
swissChilibed80922021-04-13 21:58:05 -0700500 }
501
swissChili53472e82021-05-08 16:06:32 -0700502 return nilp(next);
swissChilibed80922021-04-13 21:58:05 -0700503}
504
swissChili53472e82021-05-08 16:06:32 -0700505value_t car(value_t v)
swissChilibed80922021-04-13 21:58:05 -0700506{
swissChili53472e82021-05-08 16:06:32 -0700507 if (!consp(v))
swissChilibed80922021-04-13 21:58:05 -0700508 return nil;
509
swissChili53472e82021-05-08 16:06:32 -0700510 return *carref(v);
swissChilibed80922021-04-13 21:58:05 -0700511}
512
swissChili53472e82021-05-08 16:06:32 -0700513value_t cdr(value_t v)
swissChilibed80922021-04-13 21:58:05 -0700514{
swissChili53472e82021-05-08 16:06:32 -0700515 if (!consp(v))
swissChilibed80922021-04-13 21:58:05 -0700516 return nil;
517
swissChili53472e82021-05-08 16:06:32 -0700518 return *cdrref(v);
swissChilibed80922021-04-13 21:58:05 -0700519}
520
swissChili53472e82021-05-08 16:06:32 -0700521value_t *carref(value_t v)
swissChilibed80922021-04-13 21:58:05 -0700522{
swissChili53472e82021-05-08 16:06:32 -0700523 if (!consp(v))
swissChili8cfb7c42021-04-18 21:17:58 -0700524 return NULL;
525
swissChilib3ca4fb2021-04-20 10:33:00 -0700526 struct cons *c = (void *)(v ^ CONS_TAG);
swissChili8cfb7c42021-04-18 21:17:58 -0700527 return &c->car;
swissChilibed80922021-04-13 21:58:05 -0700528}
swissChilica107a02021-04-14 12:07:30 -0700529
swissChili53472e82021-05-08 16:06:32 -0700530value_t *cdrref(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700531{
swissChili53472e82021-05-08 16:06:32 -0700532 if (!consp(v))
swissChili8cfb7c42021-04-18 21:17:58 -0700533 return NULL;
534
swissChilib3ca4fb2021-04-20 10:33:00 -0700535 struct cons *c = (void *)(v ^ CONS_TAG);
swissChili8cfb7c42021-04-18 21:17:58 -0700536 return &c->cdr;
537}
538
swissChili53472e82021-05-08 16:06:32 -0700539bool nilp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700540{
541 return v == nil;
542}
543
swissChili53472e82021-05-08 16:06:32 -0700544int length(value_t v)
swissChilica107a02021-04-14 12:07:30 -0700545{
546 int i = 0;
547
swissChili53472e82021-05-08 16:06:32 -0700548 for (; !nilp(v); v = cdr(v))
swissChilica107a02021-04-14 12:07:30 -0700549 i++;
550
551 return i;
552}
swissChilib3ca4fb2021-04-20 10:33:00 -0700553
swissChili53472e82021-05-08 16:06:32 -0700554value_t elt(value_t v, int index)
swissChilib3ca4fb2021-04-20 10:33:00 -0700555{
swissChili53472e82021-05-08 16:06:32 -0700556 for (int i = 0; i < index; i++)
swissChilib3ca4fb2021-04-20 10:33:00 -0700557 {
swissChili53472e82021-05-08 16:06:32 -0700558 v = cdr(v);
swissChilib3ca4fb2021-04-20 10:33:00 -0700559 }
560
swissChili53472e82021-05-08 16:06:32 -0700561 return car(v);
swissChilib3ca4fb2021-04-20 10:33:00 -0700562}
swissChili8fc5e2f2021-04-22 13:45:10 -0700563
swissChili53472e82021-05-08 16:06:32 -0700564bool symstreq(value_t sym, char *str)
swissChili8fc5e2f2021-04-22 13:45:10 -0700565{
swissChili53472e82021-05-08 16:06:32 -0700566 if ((sym & HEAP_MASK) != SYMBOL_TAG)
swissChili8fc5e2f2021-04-22 13:45:10 -0700567 return false;
568
swissChili53472e82021-05-08 16:06:32 -0700569 return strcmp((char *)(sym ^ SYMBOL_TAG), str) == 0;
swissChili8fc5e2f2021-04-22 13:45:10 -0700570}
swissChilib8fd4712021-06-23 15:32:04 -0700571
572unsigned char make_pool()
573{
574 return ++max_pool;
575}
576
577unsigned char push_pool(unsigned char pool)
578{
579 unsigned char old = current_pool;
580 current_pool = pool;
581 return old;
582}
583
584void pop_pool(unsigned char pool)
585{
586 current_pool = pool;
587}
588
589bool pool_alive(unsigned char pool)
590{
591 return pool != 0;
592}
swissChilif1ba8c12021-07-02 18:45:38 -0700593
swissChili36f2c692021-08-08 14:31:44 -0700594void add_to_pool(value_t form)
595{
596 if (!heapp(form))
597 return;
598
599 struct alloc *a = (void *)(form & ~0b111);
600 a[-1].pool = current_pool;
601}
602
swissChilif1ba8c12021-07-02 18:45:38 -0700603int cons_line(value_t val)
604{
605 if (!consp(val))
606 return 0;
607
608 struct cons *c = (void *)(val ^ CONS_TAG);
609
610 return c->line;
611}
612
613char *cons_file(value_t val)
614{
615 if (!consp(val))
616 return NULL;
617
618 struct cons *c = (void *)(val ^ CONS_TAG);
619
620 return c->name;
621}
swissChiliddc97542021-07-04 11:47:42 -0700622
swissChili15f1cae2021-07-05 19:08:47 -0700623value_t create_closure(void *code, struct args *args, int ncaptures)
swissChiliddc97542021-07-04 11:47:42 -0700624{
625 struct closure_alloc *ca = malloc_aligned(sizeof(struct closure_alloc) +
626 ncaptures * sizeof(value_t));
627
628 ca->closure.function = code;
swissChili15f1cae2021-07-05 19:08:47 -0700629 ca->closure.args = args;
swissChiliddc97542021-07-04 11:47:42 -0700630 ca->closure.num_captured = ncaptures;
631
632 add_this_alloc(&ca->alloc, CLOSURE_TAG);
633
634 return (value_t)(&ca->closure) | CLOSURE_TAG;
635}
636
637void set_closure_capture_variable(int index, value_t value, value_t closure)
638{
639 if (!closurep(closure))
640 return;
641
642 struct closure *c = (void *)(closure ^ CLOSURE_TAG);
643
644 c->data[index] = value;
645}
swissChili15f1cae2021-07-05 19:08:47 -0700646
647value_t cxdr(value_t v, int index)
648{
649 if (!listp(v) || index >= length(v))
650 return nil;
651
652 for (int i = 0; i < index; i++)
653 {
654 v = cdr(v);
655 }
656
657 return v;
658}
659
660value_t *cxdrref(value_t *v, int index)
661{
662 if (!listp(*v) || index >= length(*v))
663 return NULL;
664
665 value_t *p = v;
666
667 for (int i = 0; i < index; i++)
668 {
669 p = cdrref(*p);
670 }
671
672 return p;
673}
674
675value_t deep_copy(value_t val)
676{
677 if (integerp(val) || val == nil || val == t)
678 {
679 return val;
680 }
681 else if (symbolp(val))
682 {
683 return symval((char *)(val ^ SYMBOL_TAG));
684 }
685 else if (stringp(val))
686 {
687 return strval((char *)(val ^ STRING_TAG));
688 }
689 else if (consp(val))
690 {
691 return cons(deep_copy(car(val)), deep_copy(cdr(val)));
692 }
693 else if (closurep(val))
694 {
695 struct closure *c = (void *)(val ^ CLOSURE_TAG);
696 value_t new = create_closure(c->function, c->args, c->num_captured);
697 struct closure *new_c = (void *)(new ^ CLOSURE_TAG);
698
699 for (int i = 0; i < c->num_captured; i++)
700 {
701 new_c->data[i] = deep_copy(c->data[i]);
702 }
703
704 return new;
705 }
706 else
707 {
swissChili6d02af42021-08-05 19:49:01 -0700708 fprintf(stderr, "Don't know how to deep copy this, sorry... please report this bug :)");
709 return nil;
swissChili15f1cae2021-07-05 19:08:47 -0700710 }
711}
swissChilia7568dc2021-08-08 16:52:52 -0700712
713value_t *nilptr(value_t val)
714{
715 if (!listp(val))
716 return NULL;
717
718 if (nilp(val))
719 return NULL;
720
721 value_t *p;
722
723 for (p = cdrref(val); !nilp(*p); p = cdrref(*p))
724 {
725 }
726
727 return p;
728}
729
730value_t merge2(value_t front, value_t back)
731{
swissChilifc5c9412021-08-08 19:08:26 -0700732 if (!listp(front) && listp(back))
733 return cons(front, back);
swissChilia7568dc2021-08-08 16:52:52 -0700734
swissChilifc5c9412021-08-08 19:08:26 -0700735 if (listp(front) && !listp(back))
736 back = cons(back, nil);
737
738 *nilptr(front) = back;
swissChilia7568dc2021-08-08 16:52:52 -0700739
740 return front;
741}