blob: 1056db7686adf9a9e026ba307ecddb1900baeca8 [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')
76 {}
77
78 // Only time I ever use labels is for stuff like this. Compiler would
79 // probably optimize this if I used recursion but I don't want to
80 // bother.
81 goto start;
82 }
swissChili7a6f5eb2021-04-13 16:46:02 -070083}
84
swissChili53472e82021-05-08 16:06:32 -070085bool isallowedchar(char c)
swissChili7a6f5eb2021-04-13 16:46:02 -070086{
swissChilibed80922021-04-13 21:58:05 -070087 return (c >= '#' && c <= '\'') || (c >= '*' && c <= '/') ||
88 (c >= '>' && c <= '@');
swissChili7a6f5eb2021-04-13 16:46:02 -070089}
90
swissChili53472e82021-05-08 16:06:32 -070091bool issymstart(char c)
swissChili7a6f5eb2021-04-13 16:46:02 -070092{
swissChili53472e82021-05-08 16:06:32 -070093 return isalpha(c) || isallowedchar(c);
swissChili7a6f5eb2021-04-13 16:46:02 -070094}
95
swissChili53472e82021-05-08 16:06:32 -070096bool issym(char c)
swissChili7a6f5eb2021-04-13 16:46:02 -070097{
swissChili53472e82021-05-08 16:06:32 -070098 return isalpha(c) || isallowedchar(c) || isdigit(c);
swissChili7a6f5eb2021-04-13 16:46:02 -070099}
100
swissChili53472e82021-05-08 16:06:32 -0700101bool readsym(struct istream *is, value_t *val)
swissChili7a6f5eb2021-04-13 16:46:02 -0700102{
swissChili53472e82021-05-08 16:06:32 -0700103 skipws(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700104
swissChili53472e82021-05-08 16:06:32 -0700105 if (!issymstart(is->peek(is)))
swissChili7a6f5eb2021-04-13 16:46:02 -0700106 return false;
107
108 int size = 8;
swissChilif1ba8c12021-07-02 18:45:38 -0700109 struct alloc *a = malloc_aligned(size + sizeof(struct alloc));
110 add_this_alloc(a, SYMBOL_TAG);
111
112 char *s = (char *)(a + 1);
swissChili7a6f5eb2021-04-13 16:46:02 -0700113
swissChili53472e82021-05-08 16:06:32 -0700114 s[0] = is->get(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700115
swissChili53472e82021-05-08 16:06:32 -0700116 for (int i = 1;; i++)
swissChili7a6f5eb2021-04-13 16:46:02 -0700117 {
swissChili53472e82021-05-08 16:06:32 -0700118 if (issym(is->peek(is)))
swissChili7a6f5eb2021-04-13 16:46:02 -0700119 {
swissChili53472e82021-05-08 16:06:32 -0700120 if (i >= size)
swissChili7a6f5eb2021-04-13 16:46:02 -0700121 {
122 size *= 2;
swissChilif1ba8c12021-07-02 18:45:38 -0700123 a = realloc_aligned(a, size + sizeof(struct alloc));
124 s = (char *)(a + 1);
swissChili7a6f5eb2021-04-13 16:46:02 -0700125 }
126
swissChili53472e82021-05-08 16:06:32 -0700127 s[i] = is->get(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700128 }
129 else
130 {
swissChili53472e82021-05-08 16:06:32 -0700131 s[i] = 0;
swissChilib3ca4fb2021-04-20 10:33:00 -0700132 *val = (value_t)s;
swissChili8cfb7c42021-04-18 21:17:58 -0700133 *val |= SYMBOL_TAG;
swissChili7a6f5eb2021-04-13 16:46:02 -0700134
135 return true;
136 }
137 }
138}
139
swissChili53472e82021-05-08 16:06:32 -0700140bool readstr(struct istream *is, value_t *val)
swissChili7a6f5eb2021-04-13 16:46:02 -0700141{
swissChili53472e82021-05-08 16:06:32 -0700142 skipws(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700143
swissChili53472e82021-05-08 16:06:32 -0700144 if (is->peek(is) != '"')
swissChili7a6f5eb2021-04-13 16:46:02 -0700145 return false;
146
147 bool escape = false;
148 int size = 8;
swissChilif1ba8c12021-07-02 18:45:38 -0700149
150 struct alloc *a = malloc_aligned(size + sizeof(struct alloc));
151 add_this_alloc(a, STRING_TAG);
152
153 char *s = (char *)(a + 1);
swissChili7a6f5eb2021-04-13 16:46:02 -0700154
swissChili53472e82021-05-08 16:06:32 -0700155 (void)is->get(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700156
swissChili53472e82021-05-08 16:06:32 -0700157 for (int i = 0;; i++)
swissChili7a6f5eb2021-04-13 16:46:02 -0700158 {
swissChili53472e82021-05-08 16:06:32 -0700159 if (is->peek(is) != '"')
swissChili7a6f5eb2021-04-13 16:46:02 -0700160 {
swissChili53472e82021-05-08 16:06:32 -0700161 if (i >= size)
swissChili7a6f5eb2021-04-13 16:46:02 -0700162 {
swissChilibed80922021-04-13 21:58:05 -0700163 size *= 2;
swissChilif1ba8c12021-07-02 18:45:38 -0700164 a = realloc_aligned(a, size + sizeof(struct alloc));
165 s = (char *)(a + 1);
swissChili7a6f5eb2021-04-13 16:46:02 -0700166 }
swissChilibed80922021-04-13 21:58:05 -0700167
swissChili53472e82021-05-08 16:06:32 -0700168 char c = is->get(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700169
swissChili53472e82021-05-08 16:06:32 -0700170 if (escape && c == 'n')
swissChili7a6f5eb2021-04-13 16:46:02 -0700171 c = '\n';
swissChili53472e82021-05-08 16:06:32 -0700172 else if (escape && c == '\\')
swissChili7a6f5eb2021-04-13 16:46:02 -0700173 c = '\\';
174
swissChili53472e82021-05-08 16:06:32 -0700175 if (c == '\\' && !escape)
swissChili7a6f5eb2021-04-13 16:46:02 -0700176 {
177 escape = true;
178 i--; // will be incremented again, UGLY.
179 }
180 else
181 {
182 escape = false;
swissChili53472e82021-05-08 16:06:32 -0700183 s[i] = c;
swissChili7a6f5eb2021-04-13 16:46:02 -0700184 }
185 }
186 else
187 {
swissChili53472e82021-05-08 16:06:32 -0700188 is->get(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700189
swissChilib3ca4fb2021-04-20 10:33:00 -0700190 *val = (value_t)s;
swissChili8cfb7c42021-04-18 21:17:58 -0700191 *val |= STRING_TAG;
swissChili7a6f5eb2021-04-13 16:46:02 -0700192
193 return true;
194 }
195 }
196}
197
swissChili53472e82021-05-08 16:06:32 -0700198void printval(value_t v, int depth)
swissChili7a6f5eb2021-04-13 16:46:02 -0700199{
swissChili53472e82021-05-08 16:06:32 -0700200 for (int i = 0; i < depth; i++)
201 printf(" ");
swissChili7a6f5eb2021-04-13 16:46:02 -0700202
swissChili53472e82021-05-08 16:06:32 -0700203 if (symbolp(v))
swissChili7a6f5eb2021-04-13 16:46:02 -0700204 {
swissChili53472e82021-05-08 16:06:32 -0700205 printf("'%s\n", (char *)(v ^ SYMBOL_TAG));
swissChili8cfb7c42021-04-18 21:17:58 -0700206 }
swissChili53472e82021-05-08 16:06:32 -0700207 else if (stringp(v))
swissChili8cfb7c42021-04-18 21:17:58 -0700208 {
swissChili53472e82021-05-08 16:06:32 -0700209 printf("\"%s\"\n", (char *)(v ^ STRING_TAG));
swissChili8cfb7c42021-04-18 21:17:58 -0700210 }
swissChili53472e82021-05-08 16:06:32 -0700211 else if (integerp(v))
swissChili6eee4f92021-04-20 09:34:30 -0700212 {
swissChili53472e82021-05-08 16:06:32 -0700213 printf("%d\n", v >> 2);
swissChili6eee4f92021-04-20 09:34:30 -0700214 }
swissChili53472e82021-05-08 16:06:32 -0700215 else if (consp(v))
swissChili8cfb7c42021-04-18 21:17:58 -0700216 {
swissChili53472e82021-05-08 16:06:32 -0700217 if (listp(v))
swissChilibed80922021-04-13 21:58:05 -0700218 {
swissChili53472e82021-05-08 16:06:32 -0700219 printf("list:\n");
swissChilibed80922021-04-13 21:58:05 -0700220
swissChili53472e82021-05-08 16:06:32 -0700221 for (value_t n = v; !nilp(n); n = cdr(n))
swissChilibed80922021-04-13 21:58:05 -0700222 {
swissChili53472e82021-05-08 16:06:32 -0700223 printval(car(n), depth + 1);
swissChilibed80922021-04-13 21:58:05 -0700224 }
225 }
226 else
227 {
swissChili53472e82021-05-08 16:06:32 -0700228 printf("cons:\n");
229 printval(car(v), depth + 1);
230 printval(cdr(v), depth + 1);
swissChilibed80922021-04-13 21:58:05 -0700231 }
swissChili8cfb7c42021-04-18 21:17:58 -0700232 }
swissChili53472e82021-05-08 16:06:32 -0700233 else if (nilp(v))
swissChili8cfb7c42021-04-18 21:17:58 -0700234 {
swissChili53472e82021-05-08 16:06:32 -0700235 printf("nil\n");
swissChili8cfb7c42021-04-18 21:17:58 -0700236 }
237 else
238 {
swissChili53472e82021-05-08 16:06:32 -0700239 printf("<unknown %d>\n", v);
swissChili7a6f5eb2021-04-13 16:46:02 -0700240 }
241}
242
swissChili53472e82021-05-08 16:06:32 -0700243bool readlist(struct istream *is, value_t *val)
swissChilibed80922021-04-13 21:58:05 -0700244{
swissChili53472e82021-05-08 16:06:32 -0700245 skipws(is);
swissChilibed80922021-04-13 21:58:05 -0700246
swissChili53472e82021-05-08 16:06:32 -0700247 if (is->peek(is) != '(')
swissChilibed80922021-04-13 21:58:05 -0700248 return false;
249
swissChili53472e82021-05-08 16:06:32 -0700250 is->get(is);
swissChilibed80922021-04-13 21:58:05 -0700251
swissChili53472e82021-05-08 16:06:32 -0700252 *val = readn(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 {
swissChili53472e82021-05-08 16:06:32 -0700256 is->showpos(is, stderr);
257 err("Unterminated list");
swissChilibed80922021-04-13 21:58:05 -0700258 return false;
259 }
swissChili53472e82021-05-08 16:06:32 -0700260 is->get(is);
swissChilibed80922021-04-13 21:58:05 -0700261
262 return true;
263}
264
swissChili53472e82021-05-08 16:06:32 -0700265bool readint(struct istream *is, value_t *val)
swissChili6eee4f92021-04-20 09:34:30 -0700266{
swissChilib6c858c2021-06-30 21:12:43 -0700267 skipws(is);
268
swissChili6eee4f92021-04-20 09:34:30 -0700269 int number = 0;
270
swissChili53472e82021-05-08 16:06:32 -0700271 if (!isdigit(is->peek(is)))
swissChili6eee4f92021-04-20 09:34:30 -0700272 return false;
273
swissChili53472e82021-05-08 16:06:32 -0700274 while (isdigit(is->peek(is)))
swissChili6eee4f92021-04-20 09:34:30 -0700275 {
276 number *= 10;
swissChili53472e82021-05-08 16:06:32 -0700277 number += is->get(is) - '0';
swissChili6eee4f92021-04-20 09:34:30 -0700278 }
279
swissChili53472e82021-05-08 16:06:32 -0700280 *val = intval(number);
swissChili6eee4f92021-04-20 09:34:30 -0700281 return true;
282}
283
swissChilib6c858c2021-06-30 21:12:43 -0700284bool readquote(struct istream *is, value_t *val)
285{
286 skipws(is);
287
288 char c = is->peek(is);
289
290 if (c == '\'' || c == '`' || c == ',')
291 {
292 is->get(is);
293
294 if (c == '`' && is->peek(is) == '@')
295 {
296 // This is actually a splice
297 is->get(is);
298 c = '@';
299 }
300
301 // Read the next form and wrap it in the appropriate function
302
303 value_t wrapped;
304 bool has_next = read1(is, &wrapped);
305
306 if (!has_next)
307 {
308 fprintf(stderr, "Expected a form after reader macro char %c\n", c);
309 is->showpos(is, stderr);
310 err("Invalid reader macro");
311 return false;
312 }
313
314 value_t symbol = nil;
315
316 switch (c)
317 {
318 case '\'':
319 symbol = symval("quote");
320 break;
321 case '`':
322 symbol = symval("backquote");
323 break;
324 case ',':
325 symbol = symval("unquote");
326 break;
327 case '@':
swissChili6b47b6d2021-06-30 22:08:55 -0700328 symbol = symval("unquote-splice");
swissChilib6c858c2021-06-30 21:12:43 -0700329 break;
330 }
331
332 *val = cons(symbol, cons(wrapped, nil));
333
334 return true;
335 }
336 else
337 {
338 return false;
339 }
340}
341
swissChili53472e82021-05-08 16:06:32 -0700342bool read1(struct istream *is, value_t *val)
swissChili7a6f5eb2021-04-13 16:46:02 -0700343{
swissChilib6c858c2021-06-30 21:12:43 -0700344 // This could all be one big short-circuiting || but that is ugly.
345 if (readquote(is, val))
346 return true;
347
swissChili53472e82021-05-08 16:06:32 -0700348 if (readsym(is, val))
swissChili7a6f5eb2021-04-13 16:46:02 -0700349 return true;
350
swissChili53472e82021-05-08 16:06:32 -0700351 if (readstr(is, val))
swissChili7a6f5eb2021-04-13 16:46:02 -0700352 return true;
353
swissChili53472e82021-05-08 16:06:32 -0700354 if (readint(is, val))
swissChili6eee4f92021-04-20 09:34:30 -0700355 return true;
356
swissChili53472e82021-05-08 16:06:32 -0700357 if (readlist(is, val))
swissChilibed80922021-04-13 21:58:05 -0700358 return true;
359
swissChili7a6f5eb2021-04-13 16:46:02 -0700360 return false;
361}
362
swissChili2999dd12021-07-02 14:19:53 -0700363void set_cons_info(value_t cons, int line, char *name)
364{
365 if (!consp(cons))
366 return;
367
368 struct cons *ca = (void *)(cons ^ CONS_TAG);
369
370 ca->line = line;
371 ca->name = name;
372}
373
swissChili53472e82021-05-08 16:06:32 -0700374value_t readn(struct istream *is)
swissChilibed80922021-04-13 21:58:05 -0700375{
swissChili8cfb7c42021-04-18 21:17:58 -0700376 value_t first = nil;
377 value_t *last = &first;
swissChilibed80922021-04-13 21:58:05 -0700378
swissChili8cfb7c42021-04-18 21:17:58 -0700379 value_t read_val;
swissChilibed80922021-04-13 21:58:05 -0700380
swissChili53472e82021-05-08 16:06:32 -0700381 while (read1(is, &read_val))
swissChilibed80922021-04-13 21:58:05 -0700382 {
swissChili2999dd12021-07-02 14:19:53 -0700383 int line;
384 char *file;
385
386 is->getpos(is, &line, &file);
swissChili53472e82021-05-08 16:06:32 -0700387 *last = cons(read_val, nil);
swissChili2999dd12021-07-02 14:19:53 -0700388 set_cons_info(*last, line, file);
389
swissChili53472e82021-05-08 16:06:32 -0700390 last = cdrref(*last);
swissChilibed80922021-04-13 21:58:05 -0700391 }
392
393 return first;
394}
395
swissChili53472e82021-05-08 16:06:32 -0700396bool startswith(struct istream *s, char *pattern)
swissChili7a6f5eb2021-04-13 16:46:02 -0700397{
swissChili53472e82021-05-08 16:06:32 -0700398 char *check = strdup(pattern);
399 s->read(s, check, strlen(pattern));
swissChili7a6f5eb2021-04-13 16:46:02 -0700400
swissChili53472e82021-05-08 16:06:32 -0700401 bool res = strcmp(check, pattern) == 0;
402 free(check);
swissChili7a6f5eb2021-04-13 16:46:02 -0700403
404 return res;
405}
swissChilibed80922021-04-13 21:58:05 -0700406
swissChilif1ba8c12021-07-02 18:45:38 -0700407static value_t strptrval(char *str, int tag)
swissChilibed80922021-04-13 21:58:05 -0700408{
swissChili8cfb7c42021-04-18 21:17:58 -0700409 value_t v;
410
swissChilif1ba8c12021-07-02 18:45:38 -0700411 struct alloc *al = malloc_aligned(strlen(str) + 1 + sizeof(struct alloc));
412 add_this_alloc(al, SYMBOL_TAG);
413
414 char *a = (char *)(al + 1);
415
swissChilib6c858c2021-06-30 21:12:43 -0700416 strcpy(a, str);
swissChilib3ca4fb2021-04-20 10:33:00 -0700417 v = (value_t)a;
swissChilif1ba8c12021-07-02 18:45:38 -0700418 v |= tag;
swissChilibed80922021-04-13 21:58:05 -0700419
420 return v;
421}
422
swissChilif1ba8c12021-07-02 18:45:38 -0700423value_t strval(char *str)
424{
425 return strptrval(str, STRING_TAG);
426}
427
swissChilib6c858c2021-06-30 21:12:43 -0700428value_t symval(char *str)
429{
swissChilif1ba8c12021-07-02 18:45:38 -0700430 return strptrval(str, SYMBOL_TAG);
swissChilib6c858c2021-06-30 21:12:43 -0700431}
432
swissChili53472e82021-05-08 16:06:32 -0700433bool integerp(value_t v)
swissChilibed80922021-04-13 21:58:05 -0700434{
swissChili8cfb7c42021-04-18 21:17:58 -0700435 return (v & INT_MASK) == INT_TAG;
436}
swissChilibed80922021-04-13 21:58:05 -0700437
swissChili53472e82021-05-08 16:06:32 -0700438bool symbolp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700439{
440 return (v & HEAP_MASK) == SYMBOL_TAG;
441}
442
swissChili53472e82021-05-08 16:06:32 -0700443bool stringp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700444{
445 return (v & HEAP_MASK) == STRING_TAG;
446}
447
swissChili53472e82021-05-08 16:06:32 -0700448bool consp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700449{
450 return (v & HEAP_MASK) == CONS_TAG;
451}
452
swissChili9e57da42021-06-15 22:22:46 -0700453bool heapp(value_t v)
454{
455 return consp(v) || stringp(v) || symbolp(v);
456}
457
swissChili53472e82021-05-08 16:06:32 -0700458bool listp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700459{
460 value_t next = v;
461
swissChili53472e82021-05-08 16:06:32 -0700462 while (consp(next))
swissChilibed80922021-04-13 21:58:05 -0700463 {
swissChili53472e82021-05-08 16:06:32 -0700464 next = cdr(next);
swissChilibed80922021-04-13 21:58:05 -0700465 }
466
swissChili53472e82021-05-08 16:06:32 -0700467 return nilp(next);
swissChilibed80922021-04-13 21:58:05 -0700468}
469
swissChili53472e82021-05-08 16:06:32 -0700470value_t car(value_t v)
swissChilibed80922021-04-13 21:58:05 -0700471{
swissChili53472e82021-05-08 16:06:32 -0700472 if (!consp(v))
swissChilibed80922021-04-13 21:58:05 -0700473 return nil;
474
swissChili53472e82021-05-08 16:06:32 -0700475 return *carref(v);
swissChilibed80922021-04-13 21:58:05 -0700476}
477
swissChili53472e82021-05-08 16:06:32 -0700478value_t cdr(value_t v)
swissChilibed80922021-04-13 21:58:05 -0700479{
swissChili53472e82021-05-08 16:06:32 -0700480 if (!consp(v))
swissChilibed80922021-04-13 21:58:05 -0700481 return nil;
482
swissChili53472e82021-05-08 16:06:32 -0700483 return *cdrref(v);
swissChilibed80922021-04-13 21:58:05 -0700484}
485
swissChili53472e82021-05-08 16:06:32 -0700486value_t *carref(value_t v)
swissChilibed80922021-04-13 21:58:05 -0700487{
swissChili53472e82021-05-08 16:06:32 -0700488 if (!consp(v))
swissChili8cfb7c42021-04-18 21:17:58 -0700489 return NULL;
490
swissChilib3ca4fb2021-04-20 10:33:00 -0700491 struct cons *c = (void *)(v ^ CONS_TAG);
swissChili8cfb7c42021-04-18 21:17:58 -0700492 return &c->car;
swissChilibed80922021-04-13 21:58:05 -0700493}
swissChilica107a02021-04-14 12:07:30 -0700494
swissChili53472e82021-05-08 16:06:32 -0700495value_t *cdrref(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700496{
swissChili53472e82021-05-08 16:06:32 -0700497 if (!consp(v))
swissChili8cfb7c42021-04-18 21:17:58 -0700498 return NULL;
499
swissChilib3ca4fb2021-04-20 10:33:00 -0700500 struct cons *c = (void *)(v ^ CONS_TAG);
swissChili8cfb7c42021-04-18 21:17:58 -0700501 return &c->cdr;
502}
503
swissChili53472e82021-05-08 16:06:32 -0700504bool nilp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700505{
506 return v == nil;
507}
508
swissChili53472e82021-05-08 16:06:32 -0700509int length(value_t v)
swissChilica107a02021-04-14 12:07:30 -0700510{
511 int i = 0;
512
swissChili53472e82021-05-08 16:06:32 -0700513 for (; !nilp(v); v = cdr(v))
swissChilica107a02021-04-14 12:07:30 -0700514 i++;
515
516 return i;
517}
swissChilib3ca4fb2021-04-20 10:33:00 -0700518
swissChili53472e82021-05-08 16:06:32 -0700519value_t elt(value_t v, int index)
swissChilib3ca4fb2021-04-20 10:33:00 -0700520{
swissChili53472e82021-05-08 16:06:32 -0700521 for (int i = 0; i < index; i++)
swissChilib3ca4fb2021-04-20 10:33:00 -0700522 {
swissChili53472e82021-05-08 16:06:32 -0700523 v = cdr(v);
swissChilib3ca4fb2021-04-20 10:33:00 -0700524 }
525
swissChili53472e82021-05-08 16:06:32 -0700526 return car(v);
swissChilib3ca4fb2021-04-20 10:33:00 -0700527}
swissChili8fc5e2f2021-04-22 13:45:10 -0700528
swissChili53472e82021-05-08 16:06:32 -0700529bool symstreq(value_t sym, char *str)
swissChili8fc5e2f2021-04-22 13:45:10 -0700530{
swissChili53472e82021-05-08 16:06:32 -0700531 if ((sym & HEAP_MASK) != SYMBOL_TAG)
swissChili8fc5e2f2021-04-22 13:45:10 -0700532 return false;
533
swissChili53472e82021-05-08 16:06:32 -0700534 return strcmp((char *)(sym ^ SYMBOL_TAG), str) == 0;
swissChili8fc5e2f2021-04-22 13:45:10 -0700535}
swissChilib8fd4712021-06-23 15:32:04 -0700536
537unsigned char make_pool()
538{
539 return ++max_pool;
540}
541
542unsigned char push_pool(unsigned char pool)
543{
544 unsigned char old = current_pool;
545 current_pool = pool;
546 return old;
547}
548
549void pop_pool(unsigned char pool)
550{
551 current_pool = pool;
552}
553
554bool pool_alive(unsigned char pool)
555{
556 return pool != 0;
557}
swissChilif1ba8c12021-07-02 18:45:38 -0700558
559int cons_line(value_t val)
560{
561 if (!consp(val))
562 return 0;
563
564 struct cons *c = (void *)(val ^ CONS_TAG);
565
566 return c->line;
567}
568
569char *cons_file(value_t val)
570{
571 if (!consp(val))
572 return NULL;
573
574 struct cons *c = (void *)(val ^ CONS_TAG);
575
576 return c->name;
577}