blob: e87b9d1bd14b3b7e2e48c59c788aa1f1f8f6eb50 [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>
swissChili7e1393c2021-07-07 12:59:12 -07009#include <stdarg.h>
swissChili7a6f5eb2021-04-13 16:46:02 -070010
swissChili9e57da42021-06-15 22:22:46 -070011struct alloc *first_a = NULL, *last_a = NULL;
swissChili7a6f5eb2021-04-13 16:46:02 -070012
swissChili8cfb7c42021-04-18 21:17:58 -070013value_t nil = 0b00101111; // magic ;)
swissChili923b5362021-05-09 20:31:43 -070014value_t t = 1 << 3;
swissChilibed80922021-04-13 21:58:05 -070015
swissChilib8fd4712021-06-23 15:32:04 -070016unsigned char max_pool = 0, current_pool = 0;
17
swissChili15f1cae2021-07-05 19:08:47 -070018__attribute__((noreturn)) void err(const char *msg)
swissChilibed80922021-04-13 21:58:05 -070019{
swissChili53472e82021-05-08 16:06:32 -070020 fprintf(stderr, "ERROR: %s\n", msg);
21 exit(1);
swissChilibed80922021-04-13 21:58:05 -070022}
23
swissChili7e1393c2021-07-07 12:59:12 -070024__attribute__((noreturn)) void err_at(value_t form, const char *msg, ...)
25{
26 int line = cons_line(form);
27 char *file = cons_file(form);
28
29 fprintf(stderr, "\033[31merror at\033[0m %s:%d\n", file, line);
30
31 va_list list;
32 va_start(list, msg);
33 vfprintf(stderr, msg, list);
34 va_end(list);
35 fprintf(stderr, "\n");
36
37 exit(1);
38}
39
swissChili53472e82021-05-08 16:06:32 -070040value_t intval(int i)
swissChili7a6f5eb2021-04-13 16:46:02 -070041{
swissChili8cfb7c42021-04-18 21:17:58 -070042 i <<= 2;
43 i |= INT_TAG;
44 return i;
45}
46
swissChilif1ba8c12021-07-02 18:45:38 -070047void add_this_alloc(struct alloc *a, int tag)
48{
49 a->type_tag = tag;
50 a->pool = current_pool;
51
52 if (last_a)
53 {
54 a->prev = last_a;
55 last_a->next = a;
56 a->next = NULL;
57 last_a = a;
58 }
59 else
60 {
61 a->prev = a->next = NULL;
62 first_a = last_a = a;
63 }
64}
65
swissChili53472e82021-05-08 16:06:32 -070066value_t cons(value_t car, value_t cdr)
swissChili8cfb7c42021-04-18 21:17:58 -070067{
swissChili9e57da42021-06-15 22:22:46 -070068 struct cons_alloc *item = malloc_aligned(sizeof(struct cons_alloc));
69 struct cons *c = &item->cons;
swissChili7a6f5eb2021-04-13 16:46:02 -070070
swissChilibed80922021-04-13 21:58:05 -070071 c->car = car;
72 c->cdr = cdr;
swissChili2999dd12021-07-02 14:19:53 -070073 c->line = 0;
74 c->name = NULL;
swissChilibed80922021-04-13 21:58:05 -070075
swissChilib3ca4fb2021-04-20 10:33:00 -070076 value_t v = (value_t)c;
swissChili8cfb7c42021-04-18 21:17:58 -070077 v |= CONS_TAG;
swissChili7a6f5eb2021-04-13 16:46:02 -070078
swissChilif1ba8c12021-07-02 18:45:38 -070079 add_this_alloc(&item->alloc, CONS_TAG);
80
swissChili7a6f5eb2021-04-13 16:46:02 -070081 return v;
82}
83
swissChili53472e82021-05-08 16:06:32 -070084void skipws(struct istream *is)
swissChili7a6f5eb2021-04-13 16:46:02 -070085{
swissChilib8fd4712021-06-23 15:32:04 -070086start:
swissChili53472e82021-05-08 16:06:32 -070087 while (isspace(is->peek(is)))
88 is->get(is);
swissChilib8fd4712021-06-23 15:32:04 -070089
90 if (is->peek(is) == ';')
91 {
92 while (is->get(is) != '\n')
swissChiliddc97542021-07-04 11:47:42 -070093 {
94 }
swissChilib8fd4712021-06-23 15:32:04 -070095
96 // Only time I ever use labels is for stuff like this. Compiler would
97 // probably optimize this if I used recursion but I don't want to
98 // bother.
99 goto start;
100 }
swissChili7a6f5eb2021-04-13 16:46:02 -0700101}
102
swissChili53472e82021-05-08 16:06:32 -0700103bool isallowedchar(char c)
swissChili7a6f5eb2021-04-13 16:46:02 -0700104{
swissChilibed80922021-04-13 21:58:05 -0700105 return (c >= '#' && c <= '\'') || (c >= '*' && c <= '/') ||
106 (c >= '>' && c <= '@');
swissChili7a6f5eb2021-04-13 16:46:02 -0700107}
108
swissChili53472e82021-05-08 16:06:32 -0700109bool issymstart(char c)
swissChili7a6f5eb2021-04-13 16:46:02 -0700110{
swissChili53472e82021-05-08 16:06:32 -0700111 return isalpha(c) || isallowedchar(c);
swissChili7a6f5eb2021-04-13 16:46:02 -0700112}
113
swissChili53472e82021-05-08 16:06:32 -0700114bool issym(char c)
swissChili7a6f5eb2021-04-13 16:46:02 -0700115{
swissChili53472e82021-05-08 16:06:32 -0700116 return isalpha(c) || isallowedchar(c) || isdigit(c);
swissChili7a6f5eb2021-04-13 16:46:02 -0700117}
118
swissChili53472e82021-05-08 16:06:32 -0700119bool readsym(struct istream *is, value_t *val)
swissChili7a6f5eb2021-04-13 16:46:02 -0700120{
swissChili53472e82021-05-08 16:06:32 -0700121 skipws(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700122
swissChili53472e82021-05-08 16:06:32 -0700123 if (!issymstart(is->peek(is)))
swissChili7a6f5eb2021-04-13 16:46:02 -0700124 return false;
125
126 int size = 8;
swissChilif1ba8c12021-07-02 18:45:38 -0700127 struct alloc *a = malloc_aligned(size + sizeof(struct alloc));
128 add_this_alloc(a, SYMBOL_TAG);
129
130 char *s = (char *)(a + 1);
swissChili7a6f5eb2021-04-13 16:46:02 -0700131
swissChili53472e82021-05-08 16:06:32 -0700132 s[0] = is->get(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700133
swissChili53472e82021-05-08 16:06:32 -0700134 for (int i = 1;; i++)
swissChili7a6f5eb2021-04-13 16:46:02 -0700135 {
swissChili53472e82021-05-08 16:06:32 -0700136 if (issym(is->peek(is)))
swissChili7a6f5eb2021-04-13 16:46:02 -0700137 {
swissChili53472e82021-05-08 16:06:32 -0700138 if (i >= size)
swissChili7a6f5eb2021-04-13 16:46:02 -0700139 {
140 size *= 2;
swissChilif1ba8c12021-07-02 18:45:38 -0700141 a = realloc_aligned(a, size + sizeof(struct alloc));
142 s = (char *)(a + 1);
swissChili7a6f5eb2021-04-13 16:46:02 -0700143 }
144
swissChili53472e82021-05-08 16:06:32 -0700145 s[i] = is->get(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700146 }
147 else
148 {
swissChili53472e82021-05-08 16:06:32 -0700149 s[i] = 0;
swissChilib3ca4fb2021-04-20 10:33:00 -0700150 *val = (value_t)s;
swissChili8cfb7c42021-04-18 21:17:58 -0700151 *val |= SYMBOL_TAG;
swissChili7a6f5eb2021-04-13 16:46:02 -0700152
153 return true;
154 }
155 }
156}
157
swissChili53472e82021-05-08 16:06:32 -0700158bool readstr(struct istream *is, value_t *val)
swissChili7a6f5eb2021-04-13 16:46:02 -0700159{
swissChili53472e82021-05-08 16:06:32 -0700160 skipws(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700161
swissChili53472e82021-05-08 16:06:32 -0700162 if (is->peek(is) != '"')
swissChili7a6f5eb2021-04-13 16:46:02 -0700163 return false;
164
165 bool escape = false;
166 int size = 8;
swissChilif1ba8c12021-07-02 18:45:38 -0700167
168 struct alloc *a = malloc_aligned(size + sizeof(struct alloc));
169 add_this_alloc(a, STRING_TAG);
170
171 char *s = (char *)(a + 1);
swissChili7a6f5eb2021-04-13 16:46:02 -0700172
swissChili53472e82021-05-08 16:06:32 -0700173 (void)is->get(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700174
swissChili53472e82021-05-08 16:06:32 -0700175 for (int i = 0;; i++)
swissChili7a6f5eb2021-04-13 16:46:02 -0700176 {
swissChili53472e82021-05-08 16:06:32 -0700177 if (is->peek(is) != '"')
swissChili7a6f5eb2021-04-13 16:46:02 -0700178 {
swissChili53472e82021-05-08 16:06:32 -0700179 if (i >= size)
swissChili7a6f5eb2021-04-13 16:46:02 -0700180 {
swissChilibed80922021-04-13 21:58:05 -0700181 size *= 2;
swissChilif1ba8c12021-07-02 18:45:38 -0700182 a = realloc_aligned(a, size + sizeof(struct alloc));
183 s = (char *)(a + 1);
swissChili7a6f5eb2021-04-13 16:46:02 -0700184 }
swissChilibed80922021-04-13 21:58:05 -0700185
swissChili53472e82021-05-08 16:06:32 -0700186 char c = is->get(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700187
swissChili53472e82021-05-08 16:06:32 -0700188 if (escape && c == 'n')
swissChili7a6f5eb2021-04-13 16:46:02 -0700189 c = '\n';
swissChili53472e82021-05-08 16:06:32 -0700190 else if (escape && c == '\\')
swissChili7a6f5eb2021-04-13 16:46:02 -0700191 c = '\\';
192
swissChili53472e82021-05-08 16:06:32 -0700193 if (c == '\\' && !escape)
swissChili7a6f5eb2021-04-13 16:46:02 -0700194 {
195 escape = true;
196 i--; // will be incremented again, UGLY.
197 }
198 else
199 {
200 escape = false;
swissChili53472e82021-05-08 16:06:32 -0700201 s[i] = c;
swissChili7a6f5eb2021-04-13 16:46:02 -0700202 }
203 }
204 else
205 {
swissChili7e1393c2021-07-07 12:59:12 -0700206 s[i] = '\0';
swissChili53472e82021-05-08 16:06:32 -0700207 is->get(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700208
swissChilib3ca4fb2021-04-20 10:33:00 -0700209 *val = (value_t)s;
swissChili8cfb7c42021-04-18 21:17:58 -0700210 *val |= STRING_TAG;
swissChili7a6f5eb2021-04-13 16:46:02 -0700211
212 return true;
213 }
214 }
215}
216
swissChili53472e82021-05-08 16:06:32 -0700217void printval(value_t v, int depth)
swissChili7a6f5eb2021-04-13 16:46:02 -0700218{
swissChili53472e82021-05-08 16:06:32 -0700219 for (int i = 0; i < depth; i++)
220 printf(" ");
swissChili7a6f5eb2021-04-13 16:46:02 -0700221
swissChili53472e82021-05-08 16:06:32 -0700222 if (symbolp(v))
swissChili7a6f5eb2021-04-13 16:46:02 -0700223 {
swissChili53472e82021-05-08 16:06:32 -0700224 printf("'%s\n", (char *)(v ^ SYMBOL_TAG));
swissChili8cfb7c42021-04-18 21:17:58 -0700225 }
swissChili53472e82021-05-08 16:06:32 -0700226 else if (stringp(v))
swissChili8cfb7c42021-04-18 21:17:58 -0700227 {
swissChili53472e82021-05-08 16:06:32 -0700228 printf("\"%s\"\n", (char *)(v ^ STRING_TAG));
swissChili8cfb7c42021-04-18 21:17:58 -0700229 }
swissChili53472e82021-05-08 16:06:32 -0700230 else if (integerp(v))
swissChili6eee4f92021-04-20 09:34:30 -0700231 {
swissChili53472e82021-05-08 16:06:32 -0700232 printf("%d\n", v >> 2);
swissChili6eee4f92021-04-20 09:34:30 -0700233 }
swissChili53472e82021-05-08 16:06:32 -0700234 else if (consp(v))
swissChili8cfb7c42021-04-18 21:17:58 -0700235 {
swissChili53472e82021-05-08 16:06:32 -0700236 if (listp(v))
swissChilibed80922021-04-13 21:58:05 -0700237 {
swissChili53472e82021-05-08 16:06:32 -0700238 printf("list:\n");
swissChilibed80922021-04-13 21:58:05 -0700239
swissChili53472e82021-05-08 16:06:32 -0700240 for (value_t n = v; !nilp(n); n = cdr(n))
swissChilibed80922021-04-13 21:58:05 -0700241 {
swissChili53472e82021-05-08 16:06:32 -0700242 printval(car(n), depth + 1);
swissChilibed80922021-04-13 21:58:05 -0700243 }
244 }
245 else
246 {
swissChili53472e82021-05-08 16:06:32 -0700247 printf("cons:\n");
248 printval(car(v), depth + 1);
249 printval(cdr(v), depth + 1);
swissChilibed80922021-04-13 21:58:05 -0700250 }
swissChili8cfb7c42021-04-18 21:17:58 -0700251 }
swissChili53472e82021-05-08 16:06:32 -0700252 else if (nilp(v))
swissChili8cfb7c42021-04-18 21:17:58 -0700253 {
swissChili53472e82021-05-08 16:06:32 -0700254 printf("nil\n");
swissChili8cfb7c42021-04-18 21:17:58 -0700255 }
swissChiliddc97542021-07-04 11:47:42 -0700256 else if (closurep(v))
257 {
258 struct closure *c = (void *)(v ^ CLOSURE_TAG);
259 printf("closure %p taking %d argument(s) and capturing %d value(s)\n",
swissChili15f1cae2021-07-05 19:08:47 -0700260 c->function, c->args->num_required, c->num_captured);
swissChiliddc97542021-07-04 11:47:42 -0700261 }
swissChili8cfb7c42021-04-18 21:17:58 -0700262 else
263 {
swissChili53472e82021-05-08 16:06:32 -0700264 printf("<unknown %d>\n", v);
swissChili7a6f5eb2021-04-13 16:46:02 -0700265 }
266}
267
swissChili53472e82021-05-08 16:06:32 -0700268bool readlist(struct istream *is, value_t *val)
swissChilibed80922021-04-13 21:58:05 -0700269{
swissChili53472e82021-05-08 16:06:32 -0700270 skipws(is);
swissChilibed80922021-04-13 21:58:05 -0700271
swissChili53472e82021-05-08 16:06:32 -0700272 if (is->peek(is) != '(')
swissChilibed80922021-04-13 21:58:05 -0700273 return false;
274
swissChili53472e82021-05-08 16:06:32 -0700275 is->get(is);
swissChilibed80922021-04-13 21:58:05 -0700276
swissChili53472e82021-05-08 16:06:32 -0700277 *val = readn(is);
swissChilibed80922021-04-13 21:58:05 -0700278
swissChili53472e82021-05-08 16:06:32 -0700279 if (is->peek(is) != ')')
swissChilibed80922021-04-13 21:58:05 -0700280 {
swissChili53472e82021-05-08 16:06:32 -0700281 is->showpos(is, stderr);
282 err("Unterminated list");
swissChilibed80922021-04-13 21:58:05 -0700283 return false;
284 }
swissChili53472e82021-05-08 16:06:32 -0700285 is->get(is);
swissChilibed80922021-04-13 21:58:05 -0700286
287 return true;
288}
289
swissChili53472e82021-05-08 16:06:32 -0700290bool readint(struct istream *is, value_t *val)
swissChili6eee4f92021-04-20 09:34:30 -0700291{
swissChilib6c858c2021-06-30 21:12:43 -0700292 skipws(is);
293
swissChili6eee4f92021-04-20 09:34:30 -0700294 int number = 0;
295
swissChili53472e82021-05-08 16:06:32 -0700296 if (!isdigit(is->peek(is)))
swissChili6eee4f92021-04-20 09:34:30 -0700297 return false;
298
swissChili53472e82021-05-08 16:06:32 -0700299 while (isdigit(is->peek(is)))
swissChili6eee4f92021-04-20 09:34:30 -0700300 {
301 number *= 10;
swissChili53472e82021-05-08 16:06:32 -0700302 number += is->get(is) - '0';
swissChili6eee4f92021-04-20 09:34:30 -0700303 }
304
swissChili53472e82021-05-08 16:06:32 -0700305 *val = intval(number);
swissChili6eee4f92021-04-20 09:34:30 -0700306 return true;
307}
308
swissChilib6c858c2021-06-30 21:12:43 -0700309bool readquote(struct istream *is, value_t *val)
310{
311 skipws(is);
312
313 char c = is->peek(is);
314
swissChili74348422021-07-04 13:23:24 -0700315 if (c == '\'' || c == '`' || c == ',' || c == '#')
swissChilib6c858c2021-06-30 21:12:43 -0700316 {
317 is->get(is);
318
swissChili74348422021-07-04 13:23:24 -0700319 if (c == ',' && is->peek(is) == '@')
swissChilib6c858c2021-06-30 21:12:43 -0700320 {
321 // This is actually a splice
322 is->get(is);
323 c = '@';
324 }
swissChili74348422021-07-04 13:23:24 -0700325 else if (c == '#' && is->peek(is) == '\'')
326 {
327 is->get(is);
328 }
swissChilib6c858c2021-06-30 21:12:43 -0700329
330 // Read the next form and wrap it in the appropriate function
331
332 value_t wrapped;
333 bool has_next = read1(is, &wrapped);
334
335 if (!has_next)
336 {
337 fprintf(stderr, "Expected a form after reader macro char %c\n", c);
338 is->showpos(is, stderr);
339 err("Invalid reader macro");
340 return false;
341 }
342
343 value_t symbol = nil;
344
345 switch (c)
346 {
347 case '\'':
348 symbol = symval("quote");
349 break;
350 case '`':
351 symbol = symval("backquote");
352 break;
353 case ',':
354 symbol = symval("unquote");
355 break;
356 case '@':
swissChili6b47b6d2021-06-30 22:08:55 -0700357 symbol = symval("unquote-splice");
swissChilib6c858c2021-06-30 21:12:43 -0700358 break;
swissChili74348422021-07-04 13:23:24 -0700359 case '#':
360 symbol = symval("function");
361 break;
362 default:
363 is->showpos(is, stderr);
364 err("Something went wrong parsing a reader macro");
swissChilib6c858c2021-06-30 21:12:43 -0700365 }
366
367 *val = cons(symbol, cons(wrapped, nil));
368
369 return true;
370 }
371 else
372 {
373 return false;
374 }
375}
376
swissChili53472e82021-05-08 16:06:32 -0700377bool read1(struct istream *is, value_t *val)
swissChili7a6f5eb2021-04-13 16:46:02 -0700378{
swissChilib6c858c2021-06-30 21:12:43 -0700379 // This could all be one big short-circuiting || but that is ugly.
380 if (readquote(is, val))
381 return true;
382
swissChili53472e82021-05-08 16:06:32 -0700383 if (readsym(is, val))
swissChili7a6f5eb2021-04-13 16:46:02 -0700384 return true;
385
swissChili53472e82021-05-08 16:06:32 -0700386 if (readstr(is, val))
swissChili7a6f5eb2021-04-13 16:46:02 -0700387 return true;
388
swissChili53472e82021-05-08 16:06:32 -0700389 if (readint(is, val))
swissChili6eee4f92021-04-20 09:34:30 -0700390 return true;
391
swissChili53472e82021-05-08 16:06:32 -0700392 if (readlist(is, val))
swissChilibed80922021-04-13 21:58:05 -0700393 return true;
394
swissChili7a6f5eb2021-04-13 16:46:02 -0700395 return false;
396}
397
swissChili2999dd12021-07-02 14:19:53 -0700398void set_cons_info(value_t cons, int line, char *name)
399{
400 if (!consp(cons))
401 return;
402
403 struct cons *ca = (void *)(cons ^ CONS_TAG);
404
405 ca->line = line;
406 ca->name = name;
407}
408
swissChili53472e82021-05-08 16:06:32 -0700409value_t readn(struct istream *is)
swissChilibed80922021-04-13 21:58:05 -0700410{
swissChili8cfb7c42021-04-18 21:17:58 -0700411 value_t first = nil;
412 value_t *last = &first;
swissChilibed80922021-04-13 21:58:05 -0700413
swissChili8cfb7c42021-04-18 21:17:58 -0700414 value_t read_val;
swissChilibed80922021-04-13 21:58:05 -0700415
swissChili53472e82021-05-08 16:06:32 -0700416 while (read1(is, &read_val))
swissChilibed80922021-04-13 21:58:05 -0700417 {
swissChili2999dd12021-07-02 14:19:53 -0700418 int line;
419 char *file;
420
421 is->getpos(is, &line, &file);
swissChili53472e82021-05-08 16:06:32 -0700422 *last = cons(read_val, nil);
swissChili2999dd12021-07-02 14:19:53 -0700423 set_cons_info(*last, line, file);
424
swissChili53472e82021-05-08 16:06:32 -0700425 last = cdrref(*last);
swissChilibed80922021-04-13 21:58:05 -0700426 }
427
428 return first;
429}
430
swissChili53472e82021-05-08 16:06:32 -0700431bool startswith(struct istream *s, char *pattern)
swissChili7a6f5eb2021-04-13 16:46:02 -0700432{
swissChili53472e82021-05-08 16:06:32 -0700433 char *check = strdup(pattern);
434 s->read(s, check, strlen(pattern));
swissChili7a6f5eb2021-04-13 16:46:02 -0700435
swissChili53472e82021-05-08 16:06:32 -0700436 bool res = strcmp(check, pattern) == 0;
437 free(check);
swissChili7a6f5eb2021-04-13 16:46:02 -0700438
439 return res;
440}
swissChilibed80922021-04-13 21:58:05 -0700441
swissChilif1ba8c12021-07-02 18:45:38 -0700442static value_t strptrval(char *str, int tag)
swissChilibed80922021-04-13 21:58:05 -0700443{
swissChili8cfb7c42021-04-18 21:17:58 -0700444 value_t v;
445
swissChilif1ba8c12021-07-02 18:45:38 -0700446 struct alloc *al = malloc_aligned(strlen(str) + 1 + sizeof(struct alloc));
447 add_this_alloc(al, SYMBOL_TAG);
448
449 char *a = (char *)(al + 1);
450
swissChilib6c858c2021-06-30 21:12:43 -0700451 strcpy(a, str);
swissChilib3ca4fb2021-04-20 10:33:00 -0700452 v = (value_t)a;
swissChilif1ba8c12021-07-02 18:45:38 -0700453 v |= tag;
swissChilibed80922021-04-13 21:58:05 -0700454
455 return v;
456}
457
swissChilif1ba8c12021-07-02 18:45:38 -0700458value_t strval(char *str)
459{
460 return strptrval(str, STRING_TAG);
461}
462
swissChilib6c858c2021-06-30 21:12:43 -0700463value_t symval(char *str)
464{
swissChilif1ba8c12021-07-02 18:45:38 -0700465 return strptrval(str, SYMBOL_TAG);
swissChilib6c858c2021-06-30 21:12:43 -0700466}
467
swissChili53472e82021-05-08 16:06:32 -0700468bool integerp(value_t v)
swissChilibed80922021-04-13 21:58:05 -0700469{
swissChili8cfb7c42021-04-18 21:17:58 -0700470 return (v & INT_MASK) == INT_TAG;
471}
swissChilibed80922021-04-13 21:58:05 -0700472
swissChili53472e82021-05-08 16:06:32 -0700473bool symbolp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700474{
475 return (v & HEAP_MASK) == SYMBOL_TAG;
476}
477
swissChili53472e82021-05-08 16:06:32 -0700478bool stringp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700479{
480 return (v & HEAP_MASK) == STRING_TAG;
481}
482
swissChili53472e82021-05-08 16:06:32 -0700483bool consp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700484{
485 return (v & HEAP_MASK) == CONS_TAG;
486}
487
swissChili9e57da42021-06-15 22:22:46 -0700488bool heapp(value_t v)
489{
swissChiliddc97542021-07-04 11:47:42 -0700490 return consp(v) || stringp(v) || symbolp(v) || closurep(v);
491}
492
493bool closurep(value_t v)
494{
495 return (v & HEAP_MASK) == CLOSURE_TAG;
swissChili9e57da42021-06-15 22:22:46 -0700496}
497
swissChili53472e82021-05-08 16:06:32 -0700498bool listp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700499{
500 value_t next = v;
501
swissChili53472e82021-05-08 16:06:32 -0700502 while (consp(next))
swissChilibed80922021-04-13 21:58:05 -0700503 {
swissChili53472e82021-05-08 16:06:32 -0700504 next = cdr(next);
swissChilibed80922021-04-13 21:58:05 -0700505 }
506
swissChili53472e82021-05-08 16:06:32 -0700507 return nilp(next);
swissChilibed80922021-04-13 21:58:05 -0700508}
509
swissChili53472e82021-05-08 16:06:32 -0700510value_t car(value_t v)
swissChilibed80922021-04-13 21:58:05 -0700511{
swissChili53472e82021-05-08 16:06:32 -0700512 if (!consp(v))
swissChilibed80922021-04-13 21:58:05 -0700513 return nil;
514
swissChili53472e82021-05-08 16:06:32 -0700515 return *carref(v);
swissChilibed80922021-04-13 21:58:05 -0700516}
517
swissChili53472e82021-05-08 16:06:32 -0700518value_t cdr(value_t v)
swissChilibed80922021-04-13 21:58:05 -0700519{
swissChili53472e82021-05-08 16:06:32 -0700520 if (!consp(v))
swissChilibed80922021-04-13 21:58:05 -0700521 return nil;
522
swissChili53472e82021-05-08 16:06:32 -0700523 return *cdrref(v);
swissChilibed80922021-04-13 21:58:05 -0700524}
525
swissChili53472e82021-05-08 16:06:32 -0700526value_t *carref(value_t v)
swissChilibed80922021-04-13 21:58:05 -0700527{
swissChili53472e82021-05-08 16:06:32 -0700528 if (!consp(v))
swissChili8cfb7c42021-04-18 21:17:58 -0700529 return NULL;
530
swissChilib3ca4fb2021-04-20 10:33:00 -0700531 struct cons *c = (void *)(v ^ CONS_TAG);
swissChili8cfb7c42021-04-18 21:17:58 -0700532 return &c->car;
swissChilibed80922021-04-13 21:58:05 -0700533}
swissChilica107a02021-04-14 12:07:30 -0700534
swissChili53472e82021-05-08 16:06:32 -0700535value_t *cdrref(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700536{
swissChili53472e82021-05-08 16:06:32 -0700537 if (!consp(v))
swissChili8cfb7c42021-04-18 21:17:58 -0700538 return NULL;
539
swissChilib3ca4fb2021-04-20 10:33:00 -0700540 struct cons *c = (void *)(v ^ CONS_TAG);
swissChili8cfb7c42021-04-18 21:17:58 -0700541 return &c->cdr;
542}
543
swissChili53472e82021-05-08 16:06:32 -0700544bool nilp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700545{
546 return v == nil;
547}
548
swissChili53472e82021-05-08 16:06:32 -0700549int length(value_t v)
swissChilica107a02021-04-14 12:07:30 -0700550{
551 int i = 0;
552
swissChili53472e82021-05-08 16:06:32 -0700553 for (; !nilp(v); v = cdr(v))
swissChilica107a02021-04-14 12:07:30 -0700554 i++;
555
556 return i;
557}
swissChilib3ca4fb2021-04-20 10:33:00 -0700558
swissChili53472e82021-05-08 16:06:32 -0700559value_t elt(value_t v, int index)
swissChilib3ca4fb2021-04-20 10:33:00 -0700560{
swissChili53472e82021-05-08 16:06:32 -0700561 for (int i = 0; i < index; i++)
swissChilib3ca4fb2021-04-20 10:33:00 -0700562 {
swissChili53472e82021-05-08 16:06:32 -0700563 v = cdr(v);
swissChilib3ca4fb2021-04-20 10:33:00 -0700564 }
565
swissChili53472e82021-05-08 16:06:32 -0700566 return car(v);
swissChilib3ca4fb2021-04-20 10:33:00 -0700567}
swissChili8fc5e2f2021-04-22 13:45:10 -0700568
swissChili53472e82021-05-08 16:06:32 -0700569bool symstreq(value_t sym, char *str)
swissChili8fc5e2f2021-04-22 13:45:10 -0700570{
swissChili53472e82021-05-08 16:06:32 -0700571 if ((sym & HEAP_MASK) != SYMBOL_TAG)
swissChili8fc5e2f2021-04-22 13:45:10 -0700572 return false;
573
swissChili53472e82021-05-08 16:06:32 -0700574 return strcmp((char *)(sym ^ SYMBOL_TAG), str) == 0;
swissChili8fc5e2f2021-04-22 13:45:10 -0700575}
swissChilib8fd4712021-06-23 15:32:04 -0700576
577unsigned char make_pool()
578{
579 return ++max_pool;
580}
581
582unsigned char push_pool(unsigned char pool)
583{
584 unsigned char old = current_pool;
585 current_pool = pool;
586 return old;
587}
588
589void pop_pool(unsigned char pool)
590{
591 current_pool = pool;
592}
593
594bool pool_alive(unsigned char pool)
595{
596 return pool != 0;
597}
swissChilif1ba8c12021-07-02 18:45:38 -0700598
599int cons_line(value_t val)
600{
601 if (!consp(val))
602 return 0;
603
604 struct cons *c = (void *)(val ^ CONS_TAG);
605
606 return c->line;
607}
608
609char *cons_file(value_t val)
610{
611 if (!consp(val))
612 return NULL;
613
614 struct cons *c = (void *)(val ^ CONS_TAG);
615
616 return c->name;
617}
swissChiliddc97542021-07-04 11:47:42 -0700618
swissChili15f1cae2021-07-05 19:08:47 -0700619value_t create_closure(void *code, struct args *args, int ncaptures)
swissChiliddc97542021-07-04 11:47:42 -0700620{
621 struct closure_alloc *ca = malloc_aligned(sizeof(struct closure_alloc) +
622 ncaptures * sizeof(value_t));
623
624 ca->closure.function = code;
swissChili15f1cae2021-07-05 19:08:47 -0700625 ca->closure.args = args;
swissChiliddc97542021-07-04 11:47:42 -0700626 ca->closure.num_captured = ncaptures;
627
628 add_this_alloc(&ca->alloc, CLOSURE_TAG);
629
630 return (value_t)(&ca->closure) | CLOSURE_TAG;
631}
632
633void set_closure_capture_variable(int index, value_t value, value_t closure)
634{
635 if (!closurep(closure))
636 return;
637
638 struct closure *c = (void *)(closure ^ CLOSURE_TAG);
639
640 c->data[index] = value;
641}
swissChili15f1cae2021-07-05 19:08:47 -0700642
643value_t cxdr(value_t v, int index)
644{
645 if (!listp(v) || index >= length(v))
646 return nil;
647
648 for (int i = 0; i < index; i++)
649 {
650 v = cdr(v);
651 }
652
653 return v;
654}
655
656value_t *cxdrref(value_t *v, int index)
657{
658 if (!listp(*v) || index >= length(*v))
659 return NULL;
660
661 value_t *p = v;
662
663 for (int i = 0; i < index; i++)
664 {
665 p = cdrref(*p);
666 }
667
668 return p;
669}
670
671value_t deep_copy(value_t val)
672{
673 if (integerp(val) || val == nil || val == t)
674 {
675 return val;
676 }
677 else if (symbolp(val))
678 {
679 return symval((char *)(val ^ SYMBOL_TAG));
680 }
681 else if (stringp(val))
682 {
683 return strval((char *)(val ^ STRING_TAG));
684 }
685 else if (consp(val))
686 {
687 return cons(deep_copy(car(val)), deep_copy(cdr(val)));
688 }
689 else if (closurep(val))
690 {
691 struct closure *c = (void *)(val ^ CLOSURE_TAG);
692 value_t new = create_closure(c->function, c->args, c->num_captured);
693 struct closure *new_c = (void *)(new ^ CLOSURE_TAG);
694
695 for (int i = 0; i < c->num_captured; i++)
696 {
697 new_c->data[i] = deep_copy(c->data[i]);
698 }
699
700 return new;
701 }
702 else
703 {
704 err("Don't know how to deep copy this, sorry... please report this bug :)");
705 }
706}