blob: b61903395bb49aac5769f0df1e85b8bd75b6ee39 [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
297 if (c == '\'' || c == '`' || c == ',')
298 {
299 is->get(is);
300
301 if (c == '`' && is->peek(is) == '@')
302 {
303 // This is actually a splice
304 is->get(is);
305 c = '@';
306 }
307
308 // Read the next form and wrap it in the appropriate function
309
310 value_t wrapped;
311 bool has_next = read1(is, &wrapped);
312
313 if (!has_next)
314 {
315 fprintf(stderr, "Expected a form after reader macro char %c\n", c);
316 is->showpos(is, stderr);
317 err("Invalid reader macro");
318 return false;
319 }
320
321 value_t symbol = nil;
322
323 switch (c)
324 {
325 case '\'':
326 symbol = symval("quote");
327 break;
328 case '`':
329 symbol = symval("backquote");
330 break;
331 case ',':
332 symbol = symval("unquote");
333 break;
334 case '@':
swissChili6b47b6d2021-06-30 22:08:55 -0700335 symbol = symval("unquote-splice");
swissChilib6c858c2021-06-30 21:12:43 -0700336 break;
337 }
338
339 *val = cons(symbol, cons(wrapped, nil));
340
341 return true;
342 }
343 else
344 {
345 return false;
346 }
347}
348
swissChili53472e82021-05-08 16:06:32 -0700349bool read1(struct istream *is, value_t *val)
swissChili7a6f5eb2021-04-13 16:46:02 -0700350{
swissChilib6c858c2021-06-30 21:12:43 -0700351 // This could all be one big short-circuiting || but that is ugly.
352 if (readquote(is, val))
353 return true;
354
swissChili53472e82021-05-08 16:06:32 -0700355 if (readsym(is, val))
swissChili7a6f5eb2021-04-13 16:46:02 -0700356 return true;
357
swissChili53472e82021-05-08 16:06:32 -0700358 if (readstr(is, val))
swissChili7a6f5eb2021-04-13 16:46:02 -0700359 return true;
360
swissChili53472e82021-05-08 16:06:32 -0700361 if (readint(is, val))
swissChili6eee4f92021-04-20 09:34:30 -0700362 return true;
363
swissChili53472e82021-05-08 16:06:32 -0700364 if (readlist(is, val))
swissChilibed80922021-04-13 21:58:05 -0700365 return true;
366
swissChili7a6f5eb2021-04-13 16:46:02 -0700367 return false;
368}
369
swissChili2999dd12021-07-02 14:19:53 -0700370void set_cons_info(value_t cons, int line, char *name)
371{
372 if (!consp(cons))
373 return;
374
375 struct cons *ca = (void *)(cons ^ CONS_TAG);
376
377 ca->line = line;
378 ca->name = name;
379}
380
swissChili53472e82021-05-08 16:06:32 -0700381value_t readn(struct istream *is)
swissChilibed80922021-04-13 21:58:05 -0700382{
swissChili8cfb7c42021-04-18 21:17:58 -0700383 value_t first = nil;
384 value_t *last = &first;
swissChilibed80922021-04-13 21:58:05 -0700385
swissChili8cfb7c42021-04-18 21:17:58 -0700386 value_t read_val;
swissChilibed80922021-04-13 21:58:05 -0700387
swissChili53472e82021-05-08 16:06:32 -0700388 while (read1(is, &read_val))
swissChilibed80922021-04-13 21:58:05 -0700389 {
swissChili2999dd12021-07-02 14:19:53 -0700390 int line;
391 char *file;
392
393 is->getpos(is, &line, &file);
swissChili53472e82021-05-08 16:06:32 -0700394 *last = cons(read_val, nil);
swissChili2999dd12021-07-02 14:19:53 -0700395 set_cons_info(*last, line, file);
396
swissChili53472e82021-05-08 16:06:32 -0700397 last = cdrref(*last);
swissChilibed80922021-04-13 21:58:05 -0700398 }
399
400 return first;
401}
402
swissChili53472e82021-05-08 16:06:32 -0700403bool startswith(struct istream *s, char *pattern)
swissChili7a6f5eb2021-04-13 16:46:02 -0700404{
swissChili53472e82021-05-08 16:06:32 -0700405 char *check = strdup(pattern);
406 s->read(s, check, strlen(pattern));
swissChili7a6f5eb2021-04-13 16:46:02 -0700407
swissChili53472e82021-05-08 16:06:32 -0700408 bool res = strcmp(check, pattern) == 0;
409 free(check);
swissChili7a6f5eb2021-04-13 16:46:02 -0700410
411 return res;
412}
swissChilibed80922021-04-13 21:58:05 -0700413
swissChilif1ba8c12021-07-02 18:45:38 -0700414static value_t strptrval(char *str, int tag)
swissChilibed80922021-04-13 21:58:05 -0700415{
swissChili8cfb7c42021-04-18 21:17:58 -0700416 value_t v;
417
swissChilif1ba8c12021-07-02 18:45:38 -0700418 struct alloc *al = malloc_aligned(strlen(str) + 1 + sizeof(struct alloc));
419 add_this_alloc(al, SYMBOL_TAG);
420
421 char *a = (char *)(al + 1);
422
swissChilib6c858c2021-06-30 21:12:43 -0700423 strcpy(a, str);
swissChilib3ca4fb2021-04-20 10:33:00 -0700424 v = (value_t)a;
swissChilif1ba8c12021-07-02 18:45:38 -0700425 v |= tag;
swissChilibed80922021-04-13 21:58:05 -0700426
427 return v;
428}
429
swissChilif1ba8c12021-07-02 18:45:38 -0700430value_t strval(char *str)
431{
432 return strptrval(str, STRING_TAG);
433}
434
swissChilib6c858c2021-06-30 21:12:43 -0700435value_t symval(char *str)
436{
swissChilif1ba8c12021-07-02 18:45:38 -0700437 return strptrval(str, SYMBOL_TAG);
swissChilib6c858c2021-06-30 21:12:43 -0700438}
439
swissChili53472e82021-05-08 16:06:32 -0700440bool integerp(value_t v)
swissChilibed80922021-04-13 21:58:05 -0700441{
swissChili8cfb7c42021-04-18 21:17:58 -0700442 return (v & INT_MASK) == INT_TAG;
443}
swissChilibed80922021-04-13 21:58:05 -0700444
swissChili53472e82021-05-08 16:06:32 -0700445bool symbolp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700446{
447 return (v & HEAP_MASK) == SYMBOL_TAG;
448}
449
swissChili53472e82021-05-08 16:06:32 -0700450bool stringp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700451{
452 return (v & HEAP_MASK) == STRING_TAG;
453}
454
swissChili53472e82021-05-08 16:06:32 -0700455bool consp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700456{
457 return (v & HEAP_MASK) == CONS_TAG;
458}
459
swissChili9e57da42021-06-15 22:22:46 -0700460bool heapp(value_t v)
461{
swissChiliddc97542021-07-04 11:47:42 -0700462 return consp(v) || stringp(v) || symbolp(v) || closurep(v);
463}
464
465bool closurep(value_t v)
466{
467 return (v & HEAP_MASK) == CLOSURE_TAG;
swissChili9e57da42021-06-15 22:22:46 -0700468}
469
swissChili53472e82021-05-08 16:06:32 -0700470bool listp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700471{
472 value_t next = v;
473
swissChili53472e82021-05-08 16:06:32 -0700474 while (consp(next))
swissChilibed80922021-04-13 21:58:05 -0700475 {
swissChili53472e82021-05-08 16:06:32 -0700476 next = cdr(next);
swissChilibed80922021-04-13 21:58:05 -0700477 }
478
swissChili53472e82021-05-08 16:06:32 -0700479 return nilp(next);
swissChilibed80922021-04-13 21:58:05 -0700480}
481
swissChili53472e82021-05-08 16:06:32 -0700482value_t car(value_t v)
swissChilibed80922021-04-13 21:58:05 -0700483{
swissChili53472e82021-05-08 16:06:32 -0700484 if (!consp(v))
swissChilibed80922021-04-13 21:58:05 -0700485 return nil;
486
swissChili53472e82021-05-08 16:06:32 -0700487 return *carref(v);
swissChilibed80922021-04-13 21:58:05 -0700488}
489
swissChili53472e82021-05-08 16:06:32 -0700490value_t cdr(value_t v)
swissChilibed80922021-04-13 21:58:05 -0700491{
swissChili53472e82021-05-08 16:06:32 -0700492 if (!consp(v))
swissChilibed80922021-04-13 21:58:05 -0700493 return nil;
494
swissChili53472e82021-05-08 16:06:32 -0700495 return *cdrref(v);
swissChilibed80922021-04-13 21:58:05 -0700496}
497
swissChili53472e82021-05-08 16:06:32 -0700498value_t *carref(value_t v)
swissChilibed80922021-04-13 21:58:05 -0700499{
swissChili53472e82021-05-08 16:06:32 -0700500 if (!consp(v))
swissChili8cfb7c42021-04-18 21:17:58 -0700501 return NULL;
502
swissChilib3ca4fb2021-04-20 10:33:00 -0700503 struct cons *c = (void *)(v ^ CONS_TAG);
swissChili8cfb7c42021-04-18 21:17:58 -0700504 return &c->car;
swissChilibed80922021-04-13 21:58:05 -0700505}
swissChilica107a02021-04-14 12:07:30 -0700506
swissChili53472e82021-05-08 16:06:32 -0700507value_t *cdrref(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700508{
swissChili53472e82021-05-08 16:06:32 -0700509 if (!consp(v))
swissChili8cfb7c42021-04-18 21:17:58 -0700510 return NULL;
511
swissChilib3ca4fb2021-04-20 10:33:00 -0700512 struct cons *c = (void *)(v ^ CONS_TAG);
swissChili8cfb7c42021-04-18 21:17:58 -0700513 return &c->cdr;
514}
515
swissChili53472e82021-05-08 16:06:32 -0700516bool nilp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700517{
518 return v == nil;
519}
520
swissChili53472e82021-05-08 16:06:32 -0700521int length(value_t v)
swissChilica107a02021-04-14 12:07:30 -0700522{
523 int i = 0;
524
swissChili53472e82021-05-08 16:06:32 -0700525 for (; !nilp(v); v = cdr(v))
swissChilica107a02021-04-14 12:07:30 -0700526 i++;
527
528 return i;
529}
swissChilib3ca4fb2021-04-20 10:33:00 -0700530
swissChili53472e82021-05-08 16:06:32 -0700531value_t elt(value_t v, int index)
swissChilib3ca4fb2021-04-20 10:33:00 -0700532{
swissChili53472e82021-05-08 16:06:32 -0700533 for (int i = 0; i < index; i++)
swissChilib3ca4fb2021-04-20 10:33:00 -0700534 {
swissChili53472e82021-05-08 16:06:32 -0700535 v = cdr(v);
swissChilib3ca4fb2021-04-20 10:33:00 -0700536 }
537
swissChili53472e82021-05-08 16:06:32 -0700538 return car(v);
swissChilib3ca4fb2021-04-20 10:33:00 -0700539}
swissChili8fc5e2f2021-04-22 13:45:10 -0700540
swissChili53472e82021-05-08 16:06:32 -0700541bool symstreq(value_t sym, char *str)
swissChili8fc5e2f2021-04-22 13:45:10 -0700542{
swissChili53472e82021-05-08 16:06:32 -0700543 if ((sym & HEAP_MASK) != SYMBOL_TAG)
swissChili8fc5e2f2021-04-22 13:45:10 -0700544 return false;
545
swissChili53472e82021-05-08 16:06:32 -0700546 return strcmp((char *)(sym ^ SYMBOL_TAG), str) == 0;
swissChili8fc5e2f2021-04-22 13:45:10 -0700547}
swissChilib8fd4712021-06-23 15:32:04 -0700548
549unsigned char make_pool()
550{
551 return ++max_pool;
552}
553
554unsigned char push_pool(unsigned char pool)
555{
556 unsigned char old = current_pool;
557 current_pool = pool;
558 return old;
559}
560
561void pop_pool(unsigned char pool)
562{
563 current_pool = pool;
564}
565
566bool pool_alive(unsigned char pool)
567{
568 return pool != 0;
569}
swissChilif1ba8c12021-07-02 18:45:38 -0700570
571int cons_line(value_t val)
572{
573 if (!consp(val))
574 return 0;
575
576 struct cons *c = (void *)(val ^ CONS_TAG);
577
578 return c->line;
579}
580
581char *cons_file(value_t val)
582{
583 if (!consp(val))
584 return NULL;
585
586 struct cons *c = (void *)(val ^ CONS_TAG);
587
588 return c->name;
589}
swissChiliddc97542021-07-04 11:47:42 -0700590
591value_t create_closure(void *code, int nargs, int ncaptures)
592{
593 struct closure_alloc *ca = malloc_aligned(sizeof(struct closure_alloc) +
594 ncaptures * sizeof(value_t));
595
596 ca->closure.function = code;
597 ca->closure.num_args = nargs;
598 ca->closure.num_captured = ncaptures;
599
600 add_this_alloc(&ca->alloc, CLOSURE_TAG);
601
602 return (value_t)(&ca->closure) | CLOSURE_TAG;
603}
604
605void set_closure_capture_variable(int index, value_t value, value_t closure)
606{
607 if (!closurep(closure))
608 return;
609
610 struct closure *c = (void *)(closure ^ CLOSURE_TAG);
611
612 c->data[index] = value;
613}