blob: 0d305f210fc67d266ce11626293f382e0536b720 [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
swissChili53472e82021-05-08 16:06:32 -070030value_t cons(value_t car, value_t cdr)
swissChili8cfb7c42021-04-18 21:17:58 -070031{
swissChili9e57da42021-06-15 22:22:46 -070032 struct cons_alloc *item = malloc_aligned(sizeof(struct cons_alloc));
33 struct cons *c = &item->cons;
swissChili7a6f5eb2021-04-13 16:46:02 -070034
swissChilibed80922021-04-13 21:58:05 -070035 c->car = car;
36 c->cdr = cdr;
swissChili2999dd12021-07-02 14:19:53 -070037 c->line = 0;
38 c->name = NULL;
swissChilibed80922021-04-13 21:58:05 -070039
swissChilie9fec8b2021-06-22 13:59:33 -070040 item->alloc.type_tag = CONS_TAG;
swissChilib8fd4712021-06-23 15:32:04 -070041 item->alloc.pool = current_pool;
swissChili7a6f5eb2021-04-13 16:46:02 -070042
swissChili53472e82021-05-08 16:06:32 -070043 if (last_a)
swissChili7a6f5eb2021-04-13 16:46:02 -070044 {
swissChili9e57da42021-06-15 22:22:46 -070045 item->alloc.prev = last_a;
swissChili7a6f5eb2021-04-13 16:46:02 -070046 last_a->next = item;
swissChili9e57da42021-06-15 22:22:46 -070047 item->alloc.next = NULL;
swissChilie9fec8b2021-06-22 13:59:33 -070048 last_a = item;
swissChili7a6f5eb2021-04-13 16:46:02 -070049 }
50 else
51 {
swissChili9e57da42021-06-15 22:22:46 -070052 item->alloc.prev = item->alloc.next = NULL;
swissChili7a6f5eb2021-04-13 16:46:02 -070053 first_a = last_a = item;
54 }
55
swissChilib3ca4fb2021-04-20 10:33:00 -070056 value_t v = (value_t)c;
swissChili8cfb7c42021-04-18 21:17:58 -070057 v |= CONS_TAG;
swissChili7a6f5eb2021-04-13 16:46:02 -070058
59 return v;
60}
61
swissChili53472e82021-05-08 16:06:32 -070062void skipws(struct istream *is)
swissChili7a6f5eb2021-04-13 16:46:02 -070063{
swissChilib8fd4712021-06-23 15:32:04 -070064start:
swissChili53472e82021-05-08 16:06:32 -070065 while (isspace(is->peek(is)))
66 is->get(is);
swissChilib8fd4712021-06-23 15:32:04 -070067
68 if (is->peek(is) == ';')
69 {
70 while (is->get(is) != '\n')
71 {}
72
73 // Only time I ever use labels is for stuff like this. Compiler would
74 // probably optimize this if I used recursion but I don't want to
75 // bother.
76 goto start;
77 }
swissChili7a6f5eb2021-04-13 16:46:02 -070078}
79
swissChili53472e82021-05-08 16:06:32 -070080bool isallowedchar(char c)
swissChili7a6f5eb2021-04-13 16:46:02 -070081{
swissChilibed80922021-04-13 21:58:05 -070082 return (c >= '#' && c <= '\'') || (c >= '*' && c <= '/') ||
83 (c >= '>' && c <= '@');
swissChili7a6f5eb2021-04-13 16:46:02 -070084}
85
swissChili53472e82021-05-08 16:06:32 -070086bool issymstart(char c)
swissChili7a6f5eb2021-04-13 16:46:02 -070087{
swissChili53472e82021-05-08 16:06:32 -070088 return isalpha(c) || isallowedchar(c);
swissChili7a6f5eb2021-04-13 16:46:02 -070089}
90
swissChili53472e82021-05-08 16:06:32 -070091bool issym(char c)
swissChili7a6f5eb2021-04-13 16:46:02 -070092{
swissChili53472e82021-05-08 16:06:32 -070093 return isalpha(c) || isallowedchar(c) || isdigit(c);
swissChili7a6f5eb2021-04-13 16:46:02 -070094}
95
swissChili53472e82021-05-08 16:06:32 -070096bool readsym(struct istream *is, value_t *val)
swissChili7a6f5eb2021-04-13 16:46:02 -070097{
swissChili53472e82021-05-08 16:06:32 -070098 skipws(is);
swissChili7a6f5eb2021-04-13 16:46:02 -070099
swissChili53472e82021-05-08 16:06:32 -0700100 if (!issymstart(is->peek(is)))
swissChili7a6f5eb2021-04-13 16:46:02 -0700101 return false;
102
103 int size = 8;
swissChili53472e82021-05-08 16:06:32 -0700104 char *s = malloc_aligned(size);
swissChili7a6f5eb2021-04-13 16:46:02 -0700105
swissChili53472e82021-05-08 16:06:32 -0700106 s[0] = is->get(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700107
swissChili53472e82021-05-08 16:06:32 -0700108 for (int i = 1;; i++)
swissChili7a6f5eb2021-04-13 16:46:02 -0700109 {
swissChili53472e82021-05-08 16:06:32 -0700110 if (issym(is->peek(is)))
swissChili7a6f5eb2021-04-13 16:46:02 -0700111 {
swissChili53472e82021-05-08 16:06:32 -0700112 if (i >= size)
swissChili7a6f5eb2021-04-13 16:46:02 -0700113 {
114 size *= 2;
swissChili53472e82021-05-08 16:06:32 -0700115 s = realloc_aligned(s, size);
swissChili7a6f5eb2021-04-13 16:46:02 -0700116 }
117
swissChili53472e82021-05-08 16:06:32 -0700118 s[i] = is->get(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700119 }
120 else
121 {
swissChili53472e82021-05-08 16:06:32 -0700122 s[i] = 0;
swissChilib3ca4fb2021-04-20 10:33:00 -0700123 *val = (value_t)s;
swissChili8cfb7c42021-04-18 21:17:58 -0700124 *val |= SYMBOL_TAG;
swissChili7a6f5eb2021-04-13 16:46:02 -0700125
126 return true;
127 }
128 }
129}
130
swissChili53472e82021-05-08 16:06:32 -0700131bool readstr(struct istream *is, value_t *val)
swissChili7a6f5eb2021-04-13 16:46:02 -0700132{
swissChili53472e82021-05-08 16:06:32 -0700133 skipws(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700134
swissChili53472e82021-05-08 16:06:32 -0700135 if (is->peek(is) != '"')
swissChili7a6f5eb2021-04-13 16:46:02 -0700136 return false;
137
138 bool escape = false;
139 int size = 8;
swissChili53472e82021-05-08 16:06:32 -0700140 char *s = malloc_aligned(size);
swissChili7a6f5eb2021-04-13 16:46:02 -0700141
swissChili53472e82021-05-08 16:06:32 -0700142 (void)is->get(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700143
swissChili53472e82021-05-08 16:06:32 -0700144 for (int i = 0;; i++)
swissChili7a6f5eb2021-04-13 16:46:02 -0700145 {
swissChili53472e82021-05-08 16:06:32 -0700146 if (is->peek(is) != '"')
swissChili7a6f5eb2021-04-13 16:46:02 -0700147 {
swissChili53472e82021-05-08 16:06:32 -0700148 if (i >= size)
swissChili7a6f5eb2021-04-13 16:46:02 -0700149 {
swissChilibed80922021-04-13 21:58:05 -0700150 size *= 2;
swissChili53472e82021-05-08 16:06:32 -0700151 s = realloc_aligned(s, size);
swissChili7a6f5eb2021-04-13 16:46:02 -0700152 }
swissChilibed80922021-04-13 21:58:05 -0700153
swissChili53472e82021-05-08 16:06:32 -0700154 char c = is->get(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700155
swissChili53472e82021-05-08 16:06:32 -0700156 if (escape && c == 'n')
swissChili7a6f5eb2021-04-13 16:46:02 -0700157 c = '\n';
swissChili53472e82021-05-08 16:06:32 -0700158 else if (escape && c == '\\')
swissChili7a6f5eb2021-04-13 16:46:02 -0700159 c = '\\';
160
swissChili53472e82021-05-08 16:06:32 -0700161 if (c == '\\' && !escape)
swissChili7a6f5eb2021-04-13 16:46:02 -0700162 {
163 escape = true;
164 i--; // will be incremented again, UGLY.
165 }
166 else
167 {
168 escape = false;
swissChili53472e82021-05-08 16:06:32 -0700169 s[i] = c;
swissChili7a6f5eb2021-04-13 16:46:02 -0700170 }
171 }
172 else
173 {
swissChili53472e82021-05-08 16:06:32 -0700174 is->get(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700175
swissChilib3ca4fb2021-04-20 10:33:00 -0700176 *val = (value_t)s;
swissChili8cfb7c42021-04-18 21:17:58 -0700177 *val |= STRING_TAG;
swissChili7a6f5eb2021-04-13 16:46:02 -0700178
179 return true;
180 }
181 }
182}
183
swissChili53472e82021-05-08 16:06:32 -0700184void printval(value_t v, int depth)
swissChili7a6f5eb2021-04-13 16:46:02 -0700185{
swissChili53472e82021-05-08 16:06:32 -0700186 for (int i = 0; i < depth; i++)
187 printf(" ");
swissChili7a6f5eb2021-04-13 16:46:02 -0700188
swissChili53472e82021-05-08 16:06:32 -0700189 if (symbolp(v))
swissChili7a6f5eb2021-04-13 16:46:02 -0700190 {
swissChili53472e82021-05-08 16:06:32 -0700191 printf("'%s\n", (char *)(v ^ SYMBOL_TAG));
swissChili8cfb7c42021-04-18 21:17:58 -0700192 }
swissChili53472e82021-05-08 16:06:32 -0700193 else if (stringp(v))
swissChili8cfb7c42021-04-18 21:17:58 -0700194 {
swissChili53472e82021-05-08 16:06:32 -0700195 printf("\"%s\"\n", (char *)(v ^ STRING_TAG));
swissChili8cfb7c42021-04-18 21:17:58 -0700196 }
swissChili53472e82021-05-08 16:06:32 -0700197 else if (integerp(v))
swissChili6eee4f92021-04-20 09:34:30 -0700198 {
swissChili53472e82021-05-08 16:06:32 -0700199 printf("%d\n", v >> 2);
swissChili6eee4f92021-04-20 09:34:30 -0700200 }
swissChili53472e82021-05-08 16:06:32 -0700201 else if (consp(v))
swissChili8cfb7c42021-04-18 21:17:58 -0700202 {
swissChili53472e82021-05-08 16:06:32 -0700203 if (listp(v))
swissChilibed80922021-04-13 21:58:05 -0700204 {
swissChili53472e82021-05-08 16:06:32 -0700205 printf("list:\n");
swissChilibed80922021-04-13 21:58:05 -0700206
swissChili53472e82021-05-08 16:06:32 -0700207 for (value_t n = v; !nilp(n); n = cdr(n))
swissChilibed80922021-04-13 21:58:05 -0700208 {
swissChili53472e82021-05-08 16:06:32 -0700209 printval(car(n), depth + 1);
swissChilibed80922021-04-13 21:58:05 -0700210 }
211 }
212 else
213 {
swissChili53472e82021-05-08 16:06:32 -0700214 printf("cons:\n");
215 printval(car(v), depth + 1);
216 printval(cdr(v), depth + 1);
swissChilibed80922021-04-13 21:58:05 -0700217 }
swissChili8cfb7c42021-04-18 21:17:58 -0700218 }
swissChili53472e82021-05-08 16:06:32 -0700219 else if (nilp(v))
swissChili8cfb7c42021-04-18 21:17:58 -0700220 {
swissChili53472e82021-05-08 16:06:32 -0700221 printf("nil\n");
swissChili8cfb7c42021-04-18 21:17:58 -0700222 }
223 else
224 {
swissChili53472e82021-05-08 16:06:32 -0700225 printf("<unknown %d>\n", v);
swissChili7a6f5eb2021-04-13 16:46:02 -0700226 }
227}
228
swissChili53472e82021-05-08 16:06:32 -0700229bool readlist(struct istream *is, value_t *val)
swissChilibed80922021-04-13 21:58:05 -0700230{
swissChili53472e82021-05-08 16:06:32 -0700231 skipws(is);
swissChilibed80922021-04-13 21:58:05 -0700232
swissChili53472e82021-05-08 16:06:32 -0700233 if (is->peek(is) != '(')
swissChilibed80922021-04-13 21:58:05 -0700234 return false;
235
swissChili53472e82021-05-08 16:06:32 -0700236 is->get(is);
swissChilibed80922021-04-13 21:58:05 -0700237
swissChili53472e82021-05-08 16:06:32 -0700238 *val = readn(is);
swissChilibed80922021-04-13 21:58:05 -0700239
swissChili53472e82021-05-08 16:06:32 -0700240 if (is->peek(is) != ')')
swissChilibed80922021-04-13 21:58:05 -0700241 {
swissChili53472e82021-05-08 16:06:32 -0700242 is->showpos(is, stderr);
243 err("Unterminated list");
swissChilibed80922021-04-13 21:58:05 -0700244 return false;
245 }
swissChili53472e82021-05-08 16:06:32 -0700246 is->get(is);
swissChilibed80922021-04-13 21:58:05 -0700247
248 return true;
249}
250
swissChili53472e82021-05-08 16:06:32 -0700251bool readint(struct istream *is, value_t *val)
swissChili6eee4f92021-04-20 09:34:30 -0700252{
swissChilib6c858c2021-06-30 21:12:43 -0700253 skipws(is);
254
swissChili6eee4f92021-04-20 09:34:30 -0700255 int number = 0;
256
swissChili53472e82021-05-08 16:06:32 -0700257 if (!isdigit(is->peek(is)))
swissChili6eee4f92021-04-20 09:34:30 -0700258 return false;
259
swissChili53472e82021-05-08 16:06:32 -0700260 while (isdigit(is->peek(is)))
swissChili6eee4f92021-04-20 09:34:30 -0700261 {
262 number *= 10;
swissChili53472e82021-05-08 16:06:32 -0700263 number += is->get(is) - '0';
swissChili6eee4f92021-04-20 09:34:30 -0700264 }
265
swissChili53472e82021-05-08 16:06:32 -0700266 *val = intval(number);
swissChili6eee4f92021-04-20 09:34:30 -0700267 return true;
268}
269
swissChilib6c858c2021-06-30 21:12:43 -0700270bool readquote(struct istream *is, value_t *val)
271{
272 skipws(is);
273
274 char c = is->peek(is);
275
276 if (c == '\'' || c == '`' || c == ',')
277 {
278 is->get(is);
279
280 if (c == '`' && is->peek(is) == '@')
281 {
282 // This is actually a splice
283 is->get(is);
284 c = '@';
285 }
286
287 // Read the next form and wrap it in the appropriate function
288
289 value_t wrapped;
290 bool has_next = read1(is, &wrapped);
291
292 if (!has_next)
293 {
294 fprintf(stderr, "Expected a form after reader macro char %c\n", c);
295 is->showpos(is, stderr);
296 err("Invalid reader macro");
297 return false;
298 }
299
300 value_t symbol = nil;
301
302 switch (c)
303 {
304 case '\'':
305 symbol = symval("quote");
306 break;
307 case '`':
308 symbol = symval("backquote");
309 break;
310 case ',':
311 symbol = symval("unquote");
312 break;
313 case '@':
swissChili6b47b6d2021-06-30 22:08:55 -0700314 symbol = symval("unquote-splice");
swissChilib6c858c2021-06-30 21:12:43 -0700315 break;
316 }
317
318 *val = cons(symbol, cons(wrapped, nil));
319
320 return true;
321 }
322 else
323 {
324 return false;
325 }
326}
327
swissChili53472e82021-05-08 16:06:32 -0700328bool read1(struct istream *is, value_t *val)
swissChili7a6f5eb2021-04-13 16:46:02 -0700329{
swissChilib6c858c2021-06-30 21:12:43 -0700330 // This could all be one big short-circuiting || but that is ugly.
331 if (readquote(is, val))
332 return true;
333
swissChili53472e82021-05-08 16:06:32 -0700334 if (readsym(is, val))
swissChili7a6f5eb2021-04-13 16:46:02 -0700335 return true;
336
swissChili53472e82021-05-08 16:06:32 -0700337 if (readstr(is, val))
swissChili7a6f5eb2021-04-13 16:46:02 -0700338 return true;
339
swissChili53472e82021-05-08 16:06:32 -0700340 if (readint(is, val))
swissChili6eee4f92021-04-20 09:34:30 -0700341 return true;
342
swissChili53472e82021-05-08 16:06:32 -0700343 if (readlist(is, val))
swissChilibed80922021-04-13 21:58:05 -0700344 return true;
345
swissChili7a6f5eb2021-04-13 16:46:02 -0700346 return false;
347}
348
swissChili2999dd12021-07-02 14:19:53 -0700349void set_cons_info(value_t cons, int line, char *name)
350{
351 if (!consp(cons))
352 return;
353
354 struct cons *ca = (void *)(cons ^ CONS_TAG);
355
356 ca->line = line;
357 ca->name = name;
358}
359
swissChili53472e82021-05-08 16:06:32 -0700360value_t readn(struct istream *is)
swissChilibed80922021-04-13 21:58:05 -0700361{
swissChili8cfb7c42021-04-18 21:17:58 -0700362 value_t first = nil;
363 value_t *last = &first;
swissChilibed80922021-04-13 21:58:05 -0700364
swissChili8cfb7c42021-04-18 21:17:58 -0700365 value_t read_val;
swissChilibed80922021-04-13 21:58:05 -0700366
swissChili53472e82021-05-08 16:06:32 -0700367 while (read1(is, &read_val))
swissChilibed80922021-04-13 21:58:05 -0700368 {
swissChili2999dd12021-07-02 14:19:53 -0700369 int line;
370 char *file;
371
372 is->getpos(is, &line, &file);
swissChili53472e82021-05-08 16:06:32 -0700373 *last = cons(read_val, nil);
swissChili2999dd12021-07-02 14:19:53 -0700374 set_cons_info(*last, line, file);
375
swissChili53472e82021-05-08 16:06:32 -0700376 last = cdrref(*last);
swissChilibed80922021-04-13 21:58:05 -0700377 }
378
379 return first;
380}
381
swissChili53472e82021-05-08 16:06:32 -0700382bool startswith(struct istream *s, char *pattern)
swissChili7a6f5eb2021-04-13 16:46:02 -0700383{
swissChili53472e82021-05-08 16:06:32 -0700384 char *check = strdup(pattern);
385 s->read(s, check, strlen(pattern));
swissChili7a6f5eb2021-04-13 16:46:02 -0700386
swissChili53472e82021-05-08 16:06:32 -0700387 bool res = strcmp(check, pattern) == 0;
388 free(check);
swissChili7a6f5eb2021-04-13 16:46:02 -0700389
390 return res;
391}
swissChilibed80922021-04-13 21:58:05 -0700392
swissChili53472e82021-05-08 16:06:32 -0700393value_t strval(char *str)
swissChilibed80922021-04-13 21:58:05 -0700394{
swissChili8cfb7c42021-04-18 21:17:58 -0700395 value_t v;
396
swissChili53472e82021-05-08 16:06:32 -0700397 char *a = malloc_aligned(strlen(str) + 1);
swissChilib6c858c2021-06-30 21:12:43 -0700398 strcpy(a, str);
swissChilib3ca4fb2021-04-20 10:33:00 -0700399 v = (value_t)a;
swissChili8cfb7c42021-04-18 21:17:58 -0700400 v |= STRING_TAG;
swissChilibed80922021-04-13 21:58:05 -0700401
402 return v;
403}
404
swissChilib6c858c2021-06-30 21:12:43 -0700405value_t symval(char *str)
406{
407 value_t v;
408
409 char *a = malloc_aligned(strlen(str) + 1);
410 strcpy(a, str);
411 v = (value_t)a;
412 v |= SYMBOL_TAG;
413
414 return v;
415}
416
swissChili53472e82021-05-08 16:06:32 -0700417bool integerp(value_t v)
swissChilibed80922021-04-13 21:58:05 -0700418{
swissChili8cfb7c42021-04-18 21:17:58 -0700419 return (v & INT_MASK) == INT_TAG;
420}
swissChilibed80922021-04-13 21:58:05 -0700421
swissChili53472e82021-05-08 16:06:32 -0700422bool symbolp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700423{
424 return (v & HEAP_MASK) == SYMBOL_TAG;
425}
426
swissChili53472e82021-05-08 16:06:32 -0700427bool stringp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700428{
429 return (v & HEAP_MASK) == STRING_TAG;
430}
431
swissChili53472e82021-05-08 16:06:32 -0700432bool consp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700433{
434 return (v & HEAP_MASK) == CONS_TAG;
435}
436
swissChili9e57da42021-06-15 22:22:46 -0700437bool heapp(value_t v)
438{
439 return consp(v) || stringp(v) || symbolp(v);
440}
441
swissChili53472e82021-05-08 16:06:32 -0700442bool listp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700443{
444 value_t next = v;
445
swissChili53472e82021-05-08 16:06:32 -0700446 while (consp(next))
swissChilibed80922021-04-13 21:58:05 -0700447 {
swissChili53472e82021-05-08 16:06:32 -0700448 next = cdr(next);
swissChilibed80922021-04-13 21:58:05 -0700449 }
450
swissChili53472e82021-05-08 16:06:32 -0700451 return nilp(next);
swissChilibed80922021-04-13 21:58:05 -0700452}
453
swissChili53472e82021-05-08 16:06:32 -0700454value_t car(value_t v)
swissChilibed80922021-04-13 21:58:05 -0700455{
swissChili53472e82021-05-08 16:06:32 -0700456 if (!consp(v))
swissChilibed80922021-04-13 21:58:05 -0700457 return nil;
458
swissChili53472e82021-05-08 16:06:32 -0700459 return *carref(v);
swissChilibed80922021-04-13 21:58:05 -0700460}
461
swissChili53472e82021-05-08 16:06:32 -0700462value_t cdr(value_t v)
swissChilibed80922021-04-13 21:58:05 -0700463{
swissChili53472e82021-05-08 16:06:32 -0700464 if (!consp(v))
swissChilibed80922021-04-13 21:58:05 -0700465 return nil;
466
swissChili53472e82021-05-08 16:06:32 -0700467 return *cdrref(v);
swissChilibed80922021-04-13 21:58:05 -0700468}
469
swissChili53472e82021-05-08 16:06:32 -0700470value_t *carref(value_t v)
swissChilibed80922021-04-13 21:58:05 -0700471{
swissChili53472e82021-05-08 16:06:32 -0700472 if (!consp(v))
swissChili8cfb7c42021-04-18 21:17:58 -0700473 return NULL;
474
swissChilib3ca4fb2021-04-20 10:33:00 -0700475 struct cons *c = (void *)(v ^ CONS_TAG);
swissChili8cfb7c42021-04-18 21:17:58 -0700476 return &c->car;
swissChilibed80922021-04-13 21:58:05 -0700477}
swissChilica107a02021-04-14 12:07:30 -0700478
swissChili53472e82021-05-08 16:06:32 -0700479value_t *cdrref(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700480{
swissChili53472e82021-05-08 16:06:32 -0700481 if (!consp(v))
swissChili8cfb7c42021-04-18 21:17:58 -0700482 return NULL;
483
swissChilib3ca4fb2021-04-20 10:33:00 -0700484 struct cons *c = (void *)(v ^ CONS_TAG);
swissChili8cfb7c42021-04-18 21:17:58 -0700485 return &c->cdr;
486}
487
swissChili53472e82021-05-08 16:06:32 -0700488bool nilp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700489{
490 return v == nil;
491}
492
swissChili53472e82021-05-08 16:06:32 -0700493int length(value_t v)
swissChilica107a02021-04-14 12:07:30 -0700494{
495 int i = 0;
496
swissChili53472e82021-05-08 16:06:32 -0700497 for (; !nilp(v); v = cdr(v))
swissChilica107a02021-04-14 12:07:30 -0700498 i++;
499
500 return i;
501}
swissChilib3ca4fb2021-04-20 10:33:00 -0700502
swissChili53472e82021-05-08 16:06:32 -0700503value_t elt(value_t v, int index)
swissChilib3ca4fb2021-04-20 10:33:00 -0700504{
swissChili53472e82021-05-08 16:06:32 -0700505 for (int i = 0; i < index; i++)
swissChilib3ca4fb2021-04-20 10:33:00 -0700506 {
swissChili53472e82021-05-08 16:06:32 -0700507 v = cdr(v);
swissChilib3ca4fb2021-04-20 10:33:00 -0700508 }
509
swissChili53472e82021-05-08 16:06:32 -0700510 return car(v);
swissChilib3ca4fb2021-04-20 10:33:00 -0700511}
swissChili8fc5e2f2021-04-22 13:45:10 -0700512
swissChili53472e82021-05-08 16:06:32 -0700513bool symstreq(value_t sym, char *str)
swissChili8fc5e2f2021-04-22 13:45:10 -0700514{
swissChili53472e82021-05-08 16:06:32 -0700515 if ((sym & HEAP_MASK) != SYMBOL_TAG)
swissChili8fc5e2f2021-04-22 13:45:10 -0700516 return false;
517
swissChili53472e82021-05-08 16:06:32 -0700518 return strcmp((char *)(sym ^ SYMBOL_TAG), str) == 0;
swissChili8fc5e2f2021-04-22 13:45:10 -0700519}
swissChilib8fd4712021-06-23 15:32:04 -0700520
521unsigned char make_pool()
522{
523 return ++max_pool;
524}
525
526unsigned char push_pool(unsigned char pool)
527{
528 unsigned char old = current_pool;
529 current_pool = pool;
530 return old;
531}
532
533void pop_pool(unsigned char pool)
534{
535 current_pool = pool;
536}
537
538bool pool_alive(unsigned char pool)
539{
540 return pool != 0;
541}