blob: c606e297a37dcb04e933a16c91fe361115f2eef9 [file] [log] [blame]
swissChili7a6f5eb2021-04-13 16:46:02 -07001#include "lisp.h"
swissChili8cfb7c42021-04-18 21:17:58 -07002#include "plat/plat.h"
3
swissChili7a6f5eb2021-04-13 16:46:02 -07004#include <ctype.h>
5#include <stdbool.h>
6#include <stdio.h>
swissChilibed80922021-04-13 21:58:05 -07007#include <stdlib.h>
8#include <string.h>
swissChili7a6f5eb2021-04-13 16:46:02 -07009
swissChili9e57da42021-06-15 22:22:46 -070010struct alloc *first_a = NULL, *last_a = NULL;
swissChili7a6f5eb2021-04-13 16:46:02 -070011
swissChili8cfb7c42021-04-18 21:17:58 -070012value_t nil = 0b00101111; // magic ;)
swissChili923b5362021-05-09 20:31:43 -070013value_t t = 1 << 3;
swissChilibed80922021-04-13 21:58:05 -070014
swissChilib8fd4712021-06-23 15:32:04 -070015unsigned char max_pool = 0, current_pool = 0;
16
swissChili53472e82021-05-08 16:06:32 -070017void err(const char *msg)
swissChilibed80922021-04-13 21:58:05 -070018{
swissChili53472e82021-05-08 16:06:32 -070019 fprintf(stderr, "ERROR: %s\n", msg);
20 exit(1);
swissChilibed80922021-04-13 21:58:05 -070021}
22
swissChili53472e82021-05-08 16:06:32 -070023value_t intval(int i)
swissChili7a6f5eb2021-04-13 16:46:02 -070024{
swissChili8cfb7c42021-04-18 21:17:58 -070025 i <<= 2;
26 i |= INT_TAG;
27 return i;
28}
29
swissChilif1ba8c12021-07-02 18:45:38 -070030void add_this_alloc(struct alloc *a, int tag)
31{
32 a->type_tag = tag;
33 a->pool = current_pool;
34
35 if (last_a)
36 {
37 a->prev = last_a;
38 last_a->next = a;
39 a->next = NULL;
40 last_a = a;
41 }
42 else
43 {
44 a->prev = a->next = NULL;
45 first_a = last_a = a;
46 }
47}
48
swissChili53472e82021-05-08 16:06:32 -070049value_t cons(value_t car, value_t cdr)
swissChili8cfb7c42021-04-18 21:17:58 -070050{
swissChili9e57da42021-06-15 22:22:46 -070051 struct cons_alloc *item = malloc_aligned(sizeof(struct cons_alloc));
52 struct cons *c = &item->cons;
swissChili7a6f5eb2021-04-13 16:46:02 -070053
swissChilibed80922021-04-13 21:58:05 -070054 c->car = car;
55 c->cdr = cdr;
swissChili2999dd12021-07-02 14:19:53 -070056 c->line = 0;
57 c->name = NULL;
swissChilibed80922021-04-13 21:58:05 -070058
swissChilib3ca4fb2021-04-20 10:33:00 -070059 value_t v = (value_t)c;
swissChili8cfb7c42021-04-18 21:17:58 -070060 v |= CONS_TAG;
swissChili7a6f5eb2021-04-13 16:46:02 -070061
swissChilif1ba8c12021-07-02 18:45:38 -070062 add_this_alloc(&item->alloc, CONS_TAG);
63
swissChili7a6f5eb2021-04-13 16:46:02 -070064 return v;
65}
66
swissChili53472e82021-05-08 16:06:32 -070067void skipws(struct istream *is)
swissChili7a6f5eb2021-04-13 16:46:02 -070068{
swissChilib8fd4712021-06-23 15:32:04 -070069start:
swissChili53472e82021-05-08 16:06:32 -070070 while (isspace(is->peek(is)))
71 is->get(is);
swissChilib8fd4712021-06-23 15:32:04 -070072
73 if (is->peek(is) == ';')
74 {
75 while (is->get(is) != '\n')
swissChiliddc97542021-07-04 11:47:42 -070076 {
77 }
swissChilib8fd4712021-06-23 15:32:04 -070078
79 // Only time I ever use labels is for stuff like this. Compiler would
80 // probably optimize this if I used recursion but I don't want to
81 // bother.
82 goto start;
83 }
swissChili7a6f5eb2021-04-13 16:46:02 -070084}
85
swissChili53472e82021-05-08 16:06:32 -070086bool isallowedchar(char c)
swissChili7a6f5eb2021-04-13 16:46:02 -070087{
swissChilibed80922021-04-13 21:58:05 -070088 return (c >= '#' && c <= '\'') || (c >= '*' && c <= '/') ||
89 (c >= '>' && c <= '@');
swissChili7a6f5eb2021-04-13 16:46:02 -070090}
91
swissChili53472e82021-05-08 16:06:32 -070092bool issymstart(char c)
swissChili7a6f5eb2021-04-13 16:46:02 -070093{
swissChili53472e82021-05-08 16:06:32 -070094 return isalpha(c) || isallowedchar(c);
swissChili7a6f5eb2021-04-13 16:46:02 -070095}
96
swissChili53472e82021-05-08 16:06:32 -070097bool issym(char c)
swissChili7a6f5eb2021-04-13 16:46:02 -070098{
swissChili53472e82021-05-08 16:06:32 -070099 return isalpha(c) || isallowedchar(c) || isdigit(c);
swissChili7a6f5eb2021-04-13 16:46:02 -0700100}
101
swissChili53472e82021-05-08 16:06:32 -0700102bool readsym(struct istream *is, value_t *val)
swissChili7a6f5eb2021-04-13 16:46:02 -0700103{
swissChili53472e82021-05-08 16:06:32 -0700104 skipws(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700105
swissChili53472e82021-05-08 16:06:32 -0700106 if (!issymstart(is->peek(is)))
swissChili7a6f5eb2021-04-13 16:46:02 -0700107 return false;
108
109 int size = 8;
swissChilif1ba8c12021-07-02 18:45:38 -0700110 struct alloc *a = malloc_aligned(size + sizeof(struct alloc));
111 add_this_alloc(a, SYMBOL_TAG);
112
113 char *s = (char *)(a + 1);
swissChili7a6f5eb2021-04-13 16:46:02 -0700114
swissChili53472e82021-05-08 16:06:32 -0700115 s[0] = is->get(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700116
swissChili53472e82021-05-08 16:06:32 -0700117 for (int i = 1;; i++)
swissChili7a6f5eb2021-04-13 16:46:02 -0700118 {
swissChili53472e82021-05-08 16:06:32 -0700119 if (issym(is->peek(is)))
swissChili7a6f5eb2021-04-13 16:46:02 -0700120 {
swissChili53472e82021-05-08 16:06:32 -0700121 if (i >= size)
swissChili7a6f5eb2021-04-13 16:46:02 -0700122 {
123 size *= 2;
swissChilif1ba8c12021-07-02 18:45:38 -0700124 a = realloc_aligned(a, size + sizeof(struct alloc));
125 s = (char *)(a + 1);
swissChili7a6f5eb2021-04-13 16:46:02 -0700126 }
127
swissChili53472e82021-05-08 16:06:32 -0700128 s[i] = is->get(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700129 }
130 else
131 {
swissChili53472e82021-05-08 16:06:32 -0700132 s[i] = 0;
swissChilib3ca4fb2021-04-20 10:33:00 -0700133 *val = (value_t)s;
swissChili8cfb7c42021-04-18 21:17:58 -0700134 *val |= SYMBOL_TAG;
swissChili7a6f5eb2021-04-13 16:46:02 -0700135
136 return true;
137 }
138 }
139}
140
swissChili53472e82021-05-08 16:06:32 -0700141bool readstr(struct istream *is, value_t *val)
swissChili7a6f5eb2021-04-13 16:46:02 -0700142{
swissChili53472e82021-05-08 16:06:32 -0700143 skipws(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700144
swissChili53472e82021-05-08 16:06:32 -0700145 if (is->peek(is) != '"')
swissChili7a6f5eb2021-04-13 16:46:02 -0700146 return false;
147
148 bool escape = false;
149 int size = 8;
swissChilif1ba8c12021-07-02 18:45:38 -0700150
151 struct alloc *a = malloc_aligned(size + sizeof(struct alloc));
152 add_this_alloc(a, STRING_TAG);
153
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 {
swissChili53472e82021-05-08 16:06:32 -0700189 is->get(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700190
swissChilib3ca4fb2021-04-20 10:33:00 -0700191 *val = (value_t)s;
swissChili8cfb7c42021-04-18 21:17:58 -0700192 *val |= STRING_TAG;
swissChili7a6f5eb2021-04-13 16:46:02 -0700193
194 return true;
195 }
196 }
197}
198
swissChili53472e82021-05-08 16:06:32 -0700199void printval(value_t v, int depth)
swissChili7a6f5eb2021-04-13 16:46:02 -0700200{
swissChili53472e82021-05-08 16:06:32 -0700201 for (int i = 0; i < depth; i++)
202 printf(" ");
swissChili7a6f5eb2021-04-13 16:46:02 -0700203
swissChili53472e82021-05-08 16:06:32 -0700204 if (symbolp(v))
swissChili7a6f5eb2021-04-13 16:46:02 -0700205 {
swissChili53472e82021-05-08 16:06:32 -0700206 printf("'%s\n", (char *)(v ^ SYMBOL_TAG));
swissChili8cfb7c42021-04-18 21:17:58 -0700207 }
swissChili53472e82021-05-08 16:06:32 -0700208 else if (stringp(v))
swissChili8cfb7c42021-04-18 21:17:58 -0700209 {
swissChili53472e82021-05-08 16:06:32 -0700210 printf("\"%s\"\n", (char *)(v ^ STRING_TAG));
swissChili8cfb7c42021-04-18 21:17:58 -0700211 }
swissChili53472e82021-05-08 16:06:32 -0700212 else if (integerp(v))
swissChili6eee4f92021-04-20 09:34:30 -0700213 {
swissChili53472e82021-05-08 16:06:32 -0700214 printf("%d\n", v >> 2);
swissChili6eee4f92021-04-20 09:34:30 -0700215 }
swissChili53472e82021-05-08 16:06:32 -0700216 else if (consp(v))
swissChili8cfb7c42021-04-18 21:17:58 -0700217 {
swissChili53472e82021-05-08 16:06:32 -0700218 if (listp(v))
swissChilibed80922021-04-13 21:58:05 -0700219 {
swissChili53472e82021-05-08 16:06:32 -0700220 printf("list:\n");
swissChilibed80922021-04-13 21:58:05 -0700221
swissChili53472e82021-05-08 16:06:32 -0700222 for (value_t n = v; !nilp(n); n = cdr(n))
swissChilibed80922021-04-13 21:58:05 -0700223 {
swissChili53472e82021-05-08 16:06:32 -0700224 printval(car(n), depth + 1);
swissChilibed80922021-04-13 21:58:05 -0700225 }
226 }
227 else
228 {
swissChili53472e82021-05-08 16:06:32 -0700229 printf("cons:\n");
230 printval(car(v), depth + 1);
231 printval(cdr(v), depth + 1);
swissChilibed80922021-04-13 21:58:05 -0700232 }
swissChili8cfb7c42021-04-18 21:17:58 -0700233 }
swissChili53472e82021-05-08 16:06:32 -0700234 else if (nilp(v))
swissChili8cfb7c42021-04-18 21:17:58 -0700235 {
swissChili53472e82021-05-08 16:06:32 -0700236 printf("nil\n");
swissChili8cfb7c42021-04-18 21:17:58 -0700237 }
swissChiliddc97542021-07-04 11:47:42 -0700238 else if (closurep(v))
239 {
240 struct closure *c = (void *)(v ^ CLOSURE_TAG);
241 printf("closure %p taking %d argument(s) and capturing %d value(s)\n",
242 c->function, c->num_args, c->num_captured);
243 }
swissChili8cfb7c42021-04-18 21:17:58 -0700244 else
245 {
swissChili53472e82021-05-08 16:06:32 -0700246 printf("<unknown %d>\n", v);
swissChili7a6f5eb2021-04-13 16:46:02 -0700247 }
248}
249
swissChili53472e82021-05-08 16:06:32 -0700250bool readlist(struct istream *is, value_t *val)
swissChilibed80922021-04-13 21:58:05 -0700251{
swissChili53472e82021-05-08 16:06:32 -0700252 skipws(is);
swissChilibed80922021-04-13 21:58:05 -0700253
swissChili53472e82021-05-08 16:06:32 -0700254 if (is->peek(is) != '(')
swissChilibed80922021-04-13 21:58:05 -0700255 return false;
256
swissChili53472e82021-05-08 16:06:32 -0700257 is->get(is);
swissChilibed80922021-04-13 21:58:05 -0700258
swissChili53472e82021-05-08 16:06:32 -0700259 *val = readn(is);
swissChilibed80922021-04-13 21:58:05 -0700260
swissChili53472e82021-05-08 16:06:32 -0700261 if (is->peek(is) != ')')
swissChilibed80922021-04-13 21:58:05 -0700262 {
swissChili53472e82021-05-08 16:06:32 -0700263 is->showpos(is, stderr);
264 err("Unterminated list");
swissChilibed80922021-04-13 21:58:05 -0700265 return false;
266 }
swissChili53472e82021-05-08 16:06:32 -0700267 is->get(is);
swissChilibed80922021-04-13 21:58:05 -0700268
269 return true;
270}
271
swissChili53472e82021-05-08 16:06:32 -0700272bool readint(struct istream *is, value_t *val)
swissChili6eee4f92021-04-20 09:34:30 -0700273{
swissChilib6c858c2021-06-30 21:12:43 -0700274 skipws(is);
275
swissChili6eee4f92021-04-20 09:34:30 -0700276 int number = 0;
277
swissChili53472e82021-05-08 16:06:32 -0700278 if (!isdigit(is->peek(is)))
swissChili6eee4f92021-04-20 09:34:30 -0700279 return false;
280
swissChili53472e82021-05-08 16:06:32 -0700281 while (isdigit(is->peek(is)))
swissChili6eee4f92021-04-20 09:34:30 -0700282 {
283 number *= 10;
swissChili53472e82021-05-08 16:06:32 -0700284 number += is->get(is) - '0';
swissChili6eee4f92021-04-20 09:34:30 -0700285 }
286
swissChili53472e82021-05-08 16:06:32 -0700287 *val = intval(number);
swissChili6eee4f92021-04-20 09:34:30 -0700288 return true;
289}
290
swissChilib6c858c2021-06-30 21:12:43 -0700291bool readquote(struct istream *is, value_t *val)
292{
293 skipws(is);
294
295 char c = is->peek(is);
296
swissChili74348422021-07-04 13:23:24 -0700297 if (c == '\'' || c == '`' || c == ',' || c == '#')
swissChilib6c858c2021-06-30 21:12:43 -0700298 {
299 is->get(is);
300
swissChili74348422021-07-04 13:23:24 -0700301 if (c == ',' && is->peek(is) == '@')
swissChilib6c858c2021-06-30 21:12:43 -0700302 {
303 // This is actually a splice
304 is->get(is);
305 c = '@';
306 }
swissChili74348422021-07-04 13:23:24 -0700307 else if (c == '#' && is->peek(is) == '\'')
308 {
309 is->get(is);
310 }
swissChilib6c858c2021-06-30 21:12:43 -0700311
312 // Read the next form and wrap it in the appropriate function
313
314 value_t wrapped;
315 bool has_next = read1(is, &wrapped);
316
317 if (!has_next)
318 {
319 fprintf(stderr, "Expected a form after reader macro char %c\n", c);
320 is->showpos(is, stderr);
321 err("Invalid reader macro");
322 return false;
323 }
324
325 value_t symbol = nil;
326
327 switch (c)
328 {
329 case '\'':
330 symbol = symval("quote");
331 break;
332 case '`':
333 symbol = symval("backquote");
334 break;
335 case ',':
336 symbol = symval("unquote");
337 break;
338 case '@':
swissChili6b47b6d2021-06-30 22:08:55 -0700339 symbol = symval("unquote-splice");
swissChilib6c858c2021-06-30 21:12:43 -0700340 break;
swissChili74348422021-07-04 13:23:24 -0700341 case '#':
342 symbol = symval("function");
343 break;
344 default:
345 is->showpos(is, stderr);
346 err("Something went wrong parsing a reader macro");
swissChilib6c858c2021-06-30 21:12:43 -0700347 }
348
349 *val = cons(symbol, cons(wrapped, nil));
350
351 return true;
352 }
353 else
354 {
355 return false;
356 }
357}
358
swissChili53472e82021-05-08 16:06:32 -0700359bool read1(struct istream *is, value_t *val)
swissChili7a6f5eb2021-04-13 16:46:02 -0700360{
swissChilib6c858c2021-06-30 21:12:43 -0700361 // This could all be one big short-circuiting || but that is ugly.
362 if (readquote(is, val))
363 return true;
364
swissChili53472e82021-05-08 16:06:32 -0700365 if (readsym(is, val))
swissChili7a6f5eb2021-04-13 16:46:02 -0700366 return true;
367
swissChili53472e82021-05-08 16:06:32 -0700368 if (readstr(is, val))
swissChili7a6f5eb2021-04-13 16:46:02 -0700369 return true;
370
swissChili53472e82021-05-08 16:06:32 -0700371 if (readint(is, val))
swissChili6eee4f92021-04-20 09:34:30 -0700372 return true;
373
swissChili53472e82021-05-08 16:06:32 -0700374 if (readlist(is, val))
swissChilibed80922021-04-13 21:58:05 -0700375 return true;
376
swissChili7a6f5eb2021-04-13 16:46:02 -0700377 return false;
378}
379
swissChili2999dd12021-07-02 14:19:53 -0700380void set_cons_info(value_t cons, int line, char *name)
381{
382 if (!consp(cons))
383 return;
384
385 struct cons *ca = (void *)(cons ^ CONS_TAG);
386
387 ca->line = line;
388 ca->name = name;
389}
390
swissChili53472e82021-05-08 16:06:32 -0700391value_t readn(struct istream *is)
swissChilibed80922021-04-13 21:58:05 -0700392{
swissChili8cfb7c42021-04-18 21:17:58 -0700393 value_t first = nil;
394 value_t *last = &first;
swissChilibed80922021-04-13 21:58:05 -0700395
swissChili8cfb7c42021-04-18 21:17:58 -0700396 value_t read_val;
swissChilibed80922021-04-13 21:58:05 -0700397
swissChili53472e82021-05-08 16:06:32 -0700398 while (read1(is, &read_val))
swissChilibed80922021-04-13 21:58:05 -0700399 {
swissChili2999dd12021-07-02 14:19:53 -0700400 int line;
401 char *file;
402
403 is->getpos(is, &line, &file);
swissChili53472e82021-05-08 16:06:32 -0700404 *last = cons(read_val, nil);
swissChili2999dd12021-07-02 14:19:53 -0700405 set_cons_info(*last, line, file);
406
swissChili53472e82021-05-08 16:06:32 -0700407 last = cdrref(*last);
swissChilibed80922021-04-13 21:58:05 -0700408 }
409
410 return first;
411}
412
swissChili53472e82021-05-08 16:06:32 -0700413bool startswith(struct istream *s, char *pattern)
swissChili7a6f5eb2021-04-13 16:46:02 -0700414{
swissChili53472e82021-05-08 16:06:32 -0700415 char *check = strdup(pattern);
416 s->read(s, check, strlen(pattern));
swissChili7a6f5eb2021-04-13 16:46:02 -0700417
swissChili53472e82021-05-08 16:06:32 -0700418 bool res = strcmp(check, pattern) == 0;
419 free(check);
swissChili7a6f5eb2021-04-13 16:46:02 -0700420
421 return res;
422}
swissChilibed80922021-04-13 21:58:05 -0700423
swissChilif1ba8c12021-07-02 18:45:38 -0700424static value_t strptrval(char *str, int tag)
swissChilibed80922021-04-13 21:58:05 -0700425{
swissChili8cfb7c42021-04-18 21:17:58 -0700426 value_t v;
427
swissChilif1ba8c12021-07-02 18:45:38 -0700428 struct alloc *al = malloc_aligned(strlen(str) + 1 + sizeof(struct alloc));
429 add_this_alloc(al, SYMBOL_TAG);
430
431 char *a = (char *)(al + 1);
432
swissChilib6c858c2021-06-30 21:12:43 -0700433 strcpy(a, str);
swissChilib3ca4fb2021-04-20 10:33:00 -0700434 v = (value_t)a;
swissChilif1ba8c12021-07-02 18:45:38 -0700435 v |= tag;
swissChilibed80922021-04-13 21:58:05 -0700436
437 return v;
438}
439
swissChilif1ba8c12021-07-02 18:45:38 -0700440value_t strval(char *str)
441{
442 return strptrval(str, STRING_TAG);
443}
444
swissChilib6c858c2021-06-30 21:12:43 -0700445value_t symval(char *str)
446{
swissChilif1ba8c12021-07-02 18:45:38 -0700447 return strptrval(str, SYMBOL_TAG);
swissChilib6c858c2021-06-30 21:12:43 -0700448}
449
swissChili53472e82021-05-08 16:06:32 -0700450bool integerp(value_t v)
swissChilibed80922021-04-13 21:58:05 -0700451{
swissChili8cfb7c42021-04-18 21:17:58 -0700452 return (v & INT_MASK) == INT_TAG;
453}
swissChilibed80922021-04-13 21:58:05 -0700454
swissChili53472e82021-05-08 16:06:32 -0700455bool symbolp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700456{
457 return (v & HEAP_MASK) == SYMBOL_TAG;
458}
459
swissChili53472e82021-05-08 16:06:32 -0700460bool stringp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700461{
462 return (v & HEAP_MASK) == STRING_TAG;
463}
464
swissChili53472e82021-05-08 16:06:32 -0700465bool consp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700466{
467 return (v & HEAP_MASK) == CONS_TAG;
468}
469
swissChili9e57da42021-06-15 22:22:46 -0700470bool heapp(value_t v)
471{
swissChiliddc97542021-07-04 11:47:42 -0700472 return consp(v) || stringp(v) || symbolp(v) || closurep(v);
473}
474
475bool closurep(value_t v)
476{
477 return (v & HEAP_MASK) == CLOSURE_TAG;
swissChili9e57da42021-06-15 22:22:46 -0700478}
479
swissChili53472e82021-05-08 16:06:32 -0700480bool listp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700481{
482 value_t next = v;
483
swissChili53472e82021-05-08 16:06:32 -0700484 while (consp(next))
swissChilibed80922021-04-13 21:58:05 -0700485 {
swissChili53472e82021-05-08 16:06:32 -0700486 next = cdr(next);
swissChilibed80922021-04-13 21:58:05 -0700487 }
488
swissChili53472e82021-05-08 16:06:32 -0700489 return nilp(next);
swissChilibed80922021-04-13 21:58:05 -0700490}
491
swissChili53472e82021-05-08 16:06:32 -0700492value_t car(value_t v)
swissChilibed80922021-04-13 21:58:05 -0700493{
swissChili53472e82021-05-08 16:06:32 -0700494 if (!consp(v))
swissChilibed80922021-04-13 21:58:05 -0700495 return nil;
496
swissChili53472e82021-05-08 16:06:32 -0700497 return *carref(v);
swissChilibed80922021-04-13 21:58:05 -0700498}
499
swissChili53472e82021-05-08 16:06:32 -0700500value_t cdr(value_t v)
swissChilibed80922021-04-13 21:58:05 -0700501{
swissChili53472e82021-05-08 16:06:32 -0700502 if (!consp(v))
swissChilibed80922021-04-13 21:58:05 -0700503 return nil;
504
swissChili53472e82021-05-08 16:06:32 -0700505 return *cdrref(v);
swissChilibed80922021-04-13 21:58:05 -0700506}
507
swissChili53472e82021-05-08 16:06:32 -0700508value_t *carref(value_t v)
swissChilibed80922021-04-13 21:58:05 -0700509{
swissChili53472e82021-05-08 16:06:32 -0700510 if (!consp(v))
swissChili8cfb7c42021-04-18 21:17:58 -0700511 return NULL;
512
swissChilib3ca4fb2021-04-20 10:33:00 -0700513 struct cons *c = (void *)(v ^ CONS_TAG);
swissChili8cfb7c42021-04-18 21:17:58 -0700514 return &c->car;
swissChilibed80922021-04-13 21:58:05 -0700515}
swissChilica107a02021-04-14 12:07:30 -0700516
swissChili53472e82021-05-08 16:06:32 -0700517value_t *cdrref(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700518{
swissChili53472e82021-05-08 16:06:32 -0700519 if (!consp(v))
swissChili8cfb7c42021-04-18 21:17:58 -0700520 return NULL;
521
swissChilib3ca4fb2021-04-20 10:33:00 -0700522 struct cons *c = (void *)(v ^ CONS_TAG);
swissChili8cfb7c42021-04-18 21:17:58 -0700523 return &c->cdr;
524}
525
swissChili53472e82021-05-08 16:06:32 -0700526bool nilp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700527{
528 return v == nil;
529}
530
swissChili53472e82021-05-08 16:06:32 -0700531int length(value_t v)
swissChilica107a02021-04-14 12:07:30 -0700532{
533 int i = 0;
534
swissChili53472e82021-05-08 16:06:32 -0700535 for (; !nilp(v); v = cdr(v))
swissChilica107a02021-04-14 12:07:30 -0700536 i++;
537
538 return i;
539}
swissChilib3ca4fb2021-04-20 10:33:00 -0700540
swissChili53472e82021-05-08 16:06:32 -0700541value_t elt(value_t v, int index)
swissChilib3ca4fb2021-04-20 10:33:00 -0700542{
swissChili53472e82021-05-08 16:06:32 -0700543 for (int i = 0; i < index; i++)
swissChilib3ca4fb2021-04-20 10:33:00 -0700544 {
swissChili53472e82021-05-08 16:06:32 -0700545 v = cdr(v);
swissChilib3ca4fb2021-04-20 10:33:00 -0700546 }
547
swissChili53472e82021-05-08 16:06:32 -0700548 return car(v);
swissChilib3ca4fb2021-04-20 10:33:00 -0700549}
swissChili8fc5e2f2021-04-22 13:45:10 -0700550
swissChili53472e82021-05-08 16:06:32 -0700551bool symstreq(value_t sym, char *str)
swissChili8fc5e2f2021-04-22 13:45:10 -0700552{
swissChili53472e82021-05-08 16:06:32 -0700553 if ((sym & HEAP_MASK) != SYMBOL_TAG)
swissChili8fc5e2f2021-04-22 13:45:10 -0700554 return false;
555
swissChili53472e82021-05-08 16:06:32 -0700556 return strcmp((char *)(sym ^ SYMBOL_TAG), str) == 0;
swissChili8fc5e2f2021-04-22 13:45:10 -0700557}
swissChilib8fd4712021-06-23 15:32:04 -0700558
559unsigned char make_pool()
560{
561 return ++max_pool;
562}
563
564unsigned char push_pool(unsigned char pool)
565{
566 unsigned char old = current_pool;
567 current_pool = pool;
568 return old;
569}
570
571void pop_pool(unsigned char pool)
572{
573 current_pool = pool;
574}
575
576bool pool_alive(unsigned char pool)
577{
578 return pool != 0;
579}
swissChilif1ba8c12021-07-02 18:45:38 -0700580
581int cons_line(value_t val)
582{
583 if (!consp(val))
584 return 0;
585
586 struct cons *c = (void *)(val ^ CONS_TAG);
587
588 return c->line;
589}
590
591char *cons_file(value_t val)
592{
593 if (!consp(val))
594 return NULL;
595
596 struct cons *c = (void *)(val ^ CONS_TAG);
597
598 return c->name;
599}
swissChiliddc97542021-07-04 11:47:42 -0700600
601value_t create_closure(void *code, int nargs, int ncaptures)
602{
603 struct closure_alloc *ca = malloc_aligned(sizeof(struct closure_alloc) +
604 ncaptures * sizeof(value_t));
605
606 ca->closure.function = code;
607 ca->closure.num_args = nargs;
608 ca->closure.num_captured = ncaptures;
609
610 add_this_alloc(&ca->alloc, CLOSURE_TAG);
611
612 return (value_t)(&ca->closure) | CLOSURE_TAG;
613}
614
615void set_closure_capture_variable(int index, value_t value, value_t closure)
616{
617 if (!closurep(closure))
618 return;
619
620 struct closure *c = (void *)(closure ^ CLOSURE_TAG);
621
622 c->data[index] = value;
623}