blob: 6ed3fb9e312639996c6bc7b2ea771da7d3d61a0a [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 <= '/') ||
swissChili53e7cd12021-08-02 21:55:53 -0700106 (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));
swissChilif1ba8c12021-07-02 18:45:38 -0700128
129 char *s = (char *)(a + 1);
swissChili7a6f5eb2021-04-13 16:46:02 -0700130
swissChili53472e82021-05-08 16:06:32 -0700131 s[0] = is->get(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700132
swissChili53472e82021-05-08 16:06:32 -0700133 for (int i = 1;; i++)
swissChili7a6f5eb2021-04-13 16:46:02 -0700134 {
swissChili53e7cd12021-08-02 21:55:53 -0700135 if (i >= size)
136 {
137 size *= 2;
138 a = realloc_aligned(a, size + sizeof(struct alloc));
139 s = (char *)(a + 1);
140 }
141
swissChili53472e82021-05-08 16:06:32 -0700142 if (issym(is->peek(is)))
swissChili7a6f5eb2021-04-13 16:46:02 -0700143 {
swissChili53472e82021-05-08 16:06:32 -0700144 s[i] = is->get(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700145 }
146 else
147 {
swissChili53472e82021-05-08 16:06:32 -0700148 s[i] = 0;
swissChilib3ca4fb2021-04-20 10:33:00 -0700149 *val = (value_t)s;
swissChili8cfb7c42021-04-18 21:17:58 -0700150 *val |= SYMBOL_TAG;
swissChili7a6f5eb2021-04-13 16:46:02 -0700151
swissChili53e7cd12021-08-02 21:55:53 -0700152 add_this_alloc(a, SYMBOL_TAG);
swissChili7a6f5eb2021-04-13 16:46:02 -0700153 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));
swissChilif1ba8c12021-07-02 18:45:38 -0700169
170 char *s = (char *)(a + 1);
swissChili7a6f5eb2021-04-13 16:46:02 -0700171
swissChili53472e82021-05-08 16:06:32 -0700172 (void)is->get(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700173
swissChili53472e82021-05-08 16:06:32 -0700174 for (int i = 0;; i++)
swissChili7a6f5eb2021-04-13 16:46:02 -0700175 {
swissChili53472e82021-05-08 16:06:32 -0700176 if (is->peek(is) != '"')
swissChili7a6f5eb2021-04-13 16:46:02 -0700177 {
swissChili53472e82021-05-08 16:06:32 -0700178 if (i >= size)
swissChili7a6f5eb2021-04-13 16:46:02 -0700179 {
swissChilibed80922021-04-13 21:58:05 -0700180 size *= 2;
swissChilif1ba8c12021-07-02 18:45:38 -0700181 a = realloc_aligned(a, size + sizeof(struct alloc));
182 s = (char *)(a + 1);
swissChili7a6f5eb2021-04-13 16:46:02 -0700183 }
swissChilibed80922021-04-13 21:58:05 -0700184
swissChili53472e82021-05-08 16:06:32 -0700185 char c = is->get(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700186
swissChili53472e82021-05-08 16:06:32 -0700187 if (escape && c == 'n')
swissChili7a6f5eb2021-04-13 16:46:02 -0700188 c = '\n';
swissChili53472e82021-05-08 16:06:32 -0700189 else if (escape && c == '\\')
swissChili7a6f5eb2021-04-13 16:46:02 -0700190 c = '\\';
191
swissChili53472e82021-05-08 16:06:32 -0700192 if (c == '\\' && !escape)
swissChili7a6f5eb2021-04-13 16:46:02 -0700193 {
194 escape = true;
195 i--; // will be incremented again, UGLY.
196 }
197 else
198 {
199 escape = false;
swissChili53472e82021-05-08 16:06:32 -0700200 s[i] = c;
swissChili7a6f5eb2021-04-13 16:46:02 -0700201 }
202 }
203 else
204 {
swissChili7e1393c2021-07-07 12:59:12 -0700205 s[i] = '\0';
swissChili53472e82021-05-08 16:06:32 -0700206 is->get(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700207
swissChilib3ca4fb2021-04-20 10:33:00 -0700208 *val = (value_t)s;
swissChili8cfb7c42021-04-18 21:17:58 -0700209 *val |= STRING_TAG;
swissChili7a6f5eb2021-04-13 16:46:02 -0700210
swissChili53e7cd12021-08-02 21:55:53 -0700211 add_this_alloc(a, STRING_TAG);
swissChili7a6f5eb2021-04-13 16:46:02 -0700212 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
swissChili53e7cd12021-08-02 21:55:53 -0700279 skipws(is);
280
swissChili53472e82021-05-08 16:06:32 -0700281 if (is->peek(is) != ')')
swissChilibed80922021-04-13 21:58:05 -0700282 {
swissChili53472e82021-05-08 16:06:32 -0700283 is->showpos(is, stderr);
284 err("Unterminated list");
swissChilibed80922021-04-13 21:58:05 -0700285 return false;
286 }
swissChili53472e82021-05-08 16:06:32 -0700287 is->get(is);
swissChilibed80922021-04-13 21:58:05 -0700288
289 return true;
290}
291
swissChili53472e82021-05-08 16:06:32 -0700292bool readint(struct istream *is, value_t *val)
swissChili6eee4f92021-04-20 09:34:30 -0700293{
swissChilib6c858c2021-06-30 21:12:43 -0700294 skipws(is);
295
swissChili6eee4f92021-04-20 09:34:30 -0700296 int number = 0;
297
swissChili53472e82021-05-08 16:06:32 -0700298 if (!isdigit(is->peek(is)))
swissChili6eee4f92021-04-20 09:34:30 -0700299 return false;
300
swissChili53472e82021-05-08 16:06:32 -0700301 while (isdigit(is->peek(is)))
swissChili6eee4f92021-04-20 09:34:30 -0700302 {
303 number *= 10;
swissChili53472e82021-05-08 16:06:32 -0700304 number += is->get(is) - '0';
swissChili6eee4f92021-04-20 09:34:30 -0700305 }
306
swissChili53472e82021-05-08 16:06:32 -0700307 *val = intval(number);
swissChili6eee4f92021-04-20 09:34:30 -0700308 return true;
309}
310
swissChilib6c858c2021-06-30 21:12:43 -0700311bool readquote(struct istream *is, value_t *val)
312{
313 skipws(is);
314
315 char c = is->peek(is);
316
swissChili74348422021-07-04 13:23:24 -0700317 if (c == '\'' || c == '`' || c == ',' || c == '#')
swissChilib6c858c2021-06-30 21:12:43 -0700318 {
319 is->get(is);
320
swissChili74348422021-07-04 13:23:24 -0700321 if (c == ',' && is->peek(is) == '@')
swissChilib6c858c2021-06-30 21:12:43 -0700322 {
323 // This is actually a splice
324 is->get(is);
325 c = '@';
326 }
swissChili74348422021-07-04 13:23:24 -0700327 else if (c == '#' && is->peek(is) == '\'')
328 {
329 is->get(is);
330 }
swissChilib6c858c2021-06-30 21:12:43 -0700331
332 // Read the next form and wrap it in the appropriate function
333
334 value_t wrapped;
335 bool has_next = read1(is, &wrapped);
336
337 if (!has_next)
338 {
339 fprintf(stderr, "Expected a form after reader macro char %c\n", c);
340 is->showpos(is, stderr);
341 err("Invalid reader macro");
342 return false;
343 }
344
345 value_t symbol = nil;
346
347 switch (c)
348 {
349 case '\'':
350 symbol = symval("quote");
351 break;
352 case '`':
353 symbol = symval("backquote");
354 break;
355 case ',':
356 symbol = symval("unquote");
357 break;
358 case '@':
swissChili6b47b6d2021-06-30 22:08:55 -0700359 symbol = symval("unquote-splice");
swissChilib6c858c2021-06-30 21:12:43 -0700360 break;
swissChili74348422021-07-04 13:23:24 -0700361 case '#':
362 symbol = symval("function");
363 break;
364 default:
365 is->showpos(is, stderr);
366 err("Something went wrong parsing a reader macro");
swissChilib6c858c2021-06-30 21:12:43 -0700367 }
368
369 *val = cons(symbol, cons(wrapped, nil));
370
371 return true;
372 }
373 else
374 {
375 return false;
376 }
377}
378
swissChili53472e82021-05-08 16:06:32 -0700379bool read1(struct istream *is, value_t *val)
swissChili7a6f5eb2021-04-13 16:46:02 -0700380{
swissChilib6c858c2021-06-30 21:12:43 -0700381 // This could all be one big short-circuiting || but that is ugly.
382 if (readquote(is, val))
383 return true;
384
swissChili53472e82021-05-08 16:06:32 -0700385 if (readsym(is, val))
swissChili7a6f5eb2021-04-13 16:46:02 -0700386 return true;
387
swissChili53472e82021-05-08 16:06:32 -0700388 if (readstr(is, val))
swissChili7a6f5eb2021-04-13 16:46:02 -0700389 return true;
390
swissChili53472e82021-05-08 16:06:32 -0700391 if (readint(is, val))
swissChili6eee4f92021-04-20 09:34:30 -0700392 return true;
393
swissChili53472e82021-05-08 16:06:32 -0700394 if (readlist(is, val))
swissChilibed80922021-04-13 21:58:05 -0700395 return true;
396
swissChili7a6f5eb2021-04-13 16:46:02 -0700397 return false;
398}
399
swissChili2999dd12021-07-02 14:19:53 -0700400void set_cons_info(value_t cons, int line, char *name)
401{
402 if (!consp(cons))
403 return;
404
405 struct cons *ca = (void *)(cons ^ CONS_TAG);
406
407 ca->line = line;
408 ca->name = name;
409}
410
swissChili53472e82021-05-08 16:06:32 -0700411value_t readn(struct istream *is)
swissChilibed80922021-04-13 21:58:05 -0700412{
swissChili8cfb7c42021-04-18 21:17:58 -0700413 value_t first = nil;
414 value_t *last = &first;
swissChilibed80922021-04-13 21:58:05 -0700415
swissChili8cfb7c42021-04-18 21:17:58 -0700416 value_t read_val;
swissChilibed80922021-04-13 21:58:05 -0700417
swissChili53472e82021-05-08 16:06:32 -0700418 while (read1(is, &read_val))
swissChilibed80922021-04-13 21:58:05 -0700419 {
swissChili2999dd12021-07-02 14:19:53 -0700420 int line;
421 char *file;
422
423 is->getpos(is, &line, &file);
swissChili53472e82021-05-08 16:06:32 -0700424 *last = cons(read_val, nil);
swissChili2999dd12021-07-02 14:19:53 -0700425 set_cons_info(*last, line, file);
426
swissChili53472e82021-05-08 16:06:32 -0700427 last = cdrref(*last);
swissChilibed80922021-04-13 21:58:05 -0700428 }
429
430 return first;
431}
432
swissChili53472e82021-05-08 16:06:32 -0700433bool startswith(struct istream *s, char *pattern)
swissChili7a6f5eb2021-04-13 16:46:02 -0700434{
swissChili53472e82021-05-08 16:06:32 -0700435 char *check = strdup(pattern);
436 s->read(s, check, strlen(pattern));
swissChili7a6f5eb2021-04-13 16:46:02 -0700437
swissChili53472e82021-05-08 16:06:32 -0700438 bool res = strcmp(check, pattern) == 0;
439 free(check);
swissChili7a6f5eb2021-04-13 16:46:02 -0700440
441 return res;
442}
swissChilibed80922021-04-13 21:58:05 -0700443
swissChilif1ba8c12021-07-02 18:45:38 -0700444static value_t strptrval(char *str, int tag)
swissChilibed80922021-04-13 21:58:05 -0700445{
swissChili8cfb7c42021-04-18 21:17:58 -0700446 value_t v;
447
swissChilif1ba8c12021-07-02 18:45:38 -0700448 struct alloc *al = malloc_aligned(strlen(str) + 1 + sizeof(struct alloc));
449 add_this_alloc(al, SYMBOL_TAG);
450
451 char *a = (char *)(al + 1);
452
swissChilib6c858c2021-06-30 21:12:43 -0700453 strcpy(a, str);
swissChilib3ca4fb2021-04-20 10:33:00 -0700454 v = (value_t)a;
swissChilif1ba8c12021-07-02 18:45:38 -0700455 v |= tag;
swissChilibed80922021-04-13 21:58:05 -0700456
457 return v;
458}
459
swissChilif1ba8c12021-07-02 18:45:38 -0700460value_t strval(char *str)
461{
462 return strptrval(str, STRING_TAG);
463}
464
swissChilib6c858c2021-06-30 21:12:43 -0700465value_t symval(char *str)
466{
swissChilif1ba8c12021-07-02 18:45:38 -0700467 return strptrval(str, SYMBOL_TAG);
swissChilib6c858c2021-06-30 21:12:43 -0700468}
469
swissChili53472e82021-05-08 16:06:32 -0700470bool integerp(value_t v)
swissChilibed80922021-04-13 21:58:05 -0700471{
swissChili8cfb7c42021-04-18 21:17:58 -0700472 return (v & INT_MASK) == INT_TAG;
473}
swissChilibed80922021-04-13 21:58:05 -0700474
swissChili53472e82021-05-08 16:06:32 -0700475bool symbolp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700476{
477 return (v & HEAP_MASK) == SYMBOL_TAG;
478}
479
swissChili53472e82021-05-08 16:06:32 -0700480bool stringp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700481{
482 return (v & HEAP_MASK) == STRING_TAG;
483}
484
swissChili53472e82021-05-08 16:06:32 -0700485bool consp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700486{
487 return (v & HEAP_MASK) == CONS_TAG;
488}
489
swissChili9e57da42021-06-15 22:22:46 -0700490bool heapp(value_t v)
491{
swissChiliddc97542021-07-04 11:47:42 -0700492 return consp(v) || stringp(v) || symbolp(v) || closurep(v);
493}
494
495bool closurep(value_t v)
496{
497 return (v & HEAP_MASK) == CLOSURE_TAG;
swissChili9e57da42021-06-15 22:22:46 -0700498}
499
swissChili53472e82021-05-08 16:06:32 -0700500bool listp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700501{
502 value_t next = v;
503
swissChili53472e82021-05-08 16:06:32 -0700504 while (consp(next))
swissChilibed80922021-04-13 21:58:05 -0700505 {
swissChili53472e82021-05-08 16:06:32 -0700506 next = cdr(next);
swissChilibed80922021-04-13 21:58:05 -0700507 }
508
swissChili53472e82021-05-08 16:06:32 -0700509 return nilp(next);
swissChilibed80922021-04-13 21:58:05 -0700510}
511
swissChili53472e82021-05-08 16:06:32 -0700512value_t car(value_t v)
swissChilibed80922021-04-13 21:58:05 -0700513{
swissChili53472e82021-05-08 16:06:32 -0700514 if (!consp(v))
swissChilibed80922021-04-13 21:58:05 -0700515 return nil;
516
swissChili53472e82021-05-08 16:06:32 -0700517 return *carref(v);
swissChilibed80922021-04-13 21:58:05 -0700518}
519
swissChili53472e82021-05-08 16:06:32 -0700520value_t cdr(value_t v)
swissChilibed80922021-04-13 21:58:05 -0700521{
swissChili53472e82021-05-08 16:06:32 -0700522 if (!consp(v))
swissChilibed80922021-04-13 21:58:05 -0700523 return nil;
524
swissChili53472e82021-05-08 16:06:32 -0700525 return *cdrref(v);
swissChilibed80922021-04-13 21:58:05 -0700526}
527
swissChili53472e82021-05-08 16:06:32 -0700528value_t *carref(value_t v)
swissChilibed80922021-04-13 21:58:05 -0700529{
swissChili53472e82021-05-08 16:06:32 -0700530 if (!consp(v))
swissChili8cfb7c42021-04-18 21:17:58 -0700531 return NULL;
532
swissChilib3ca4fb2021-04-20 10:33:00 -0700533 struct cons *c = (void *)(v ^ CONS_TAG);
swissChili8cfb7c42021-04-18 21:17:58 -0700534 return &c->car;
swissChilibed80922021-04-13 21:58:05 -0700535}
swissChilica107a02021-04-14 12:07:30 -0700536
swissChili53472e82021-05-08 16:06:32 -0700537value_t *cdrref(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700538{
swissChili53472e82021-05-08 16:06:32 -0700539 if (!consp(v))
swissChili8cfb7c42021-04-18 21:17:58 -0700540 return NULL;
541
swissChilib3ca4fb2021-04-20 10:33:00 -0700542 struct cons *c = (void *)(v ^ CONS_TAG);
swissChili8cfb7c42021-04-18 21:17:58 -0700543 return &c->cdr;
544}
545
swissChili53472e82021-05-08 16:06:32 -0700546bool nilp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700547{
548 return v == nil;
549}
550
swissChili53472e82021-05-08 16:06:32 -0700551int length(value_t v)
swissChilica107a02021-04-14 12:07:30 -0700552{
553 int i = 0;
554
swissChili53472e82021-05-08 16:06:32 -0700555 for (; !nilp(v); v = cdr(v))
swissChilica107a02021-04-14 12:07:30 -0700556 i++;
557
558 return i;
559}
swissChilib3ca4fb2021-04-20 10:33:00 -0700560
swissChili53472e82021-05-08 16:06:32 -0700561value_t elt(value_t v, int index)
swissChilib3ca4fb2021-04-20 10:33:00 -0700562{
swissChili53472e82021-05-08 16:06:32 -0700563 for (int i = 0; i < index; i++)
swissChilib3ca4fb2021-04-20 10:33:00 -0700564 {
swissChili53472e82021-05-08 16:06:32 -0700565 v = cdr(v);
swissChilib3ca4fb2021-04-20 10:33:00 -0700566 }
567
swissChili53472e82021-05-08 16:06:32 -0700568 return car(v);
swissChilib3ca4fb2021-04-20 10:33:00 -0700569}
swissChili8fc5e2f2021-04-22 13:45:10 -0700570
swissChili53472e82021-05-08 16:06:32 -0700571bool symstreq(value_t sym, char *str)
swissChili8fc5e2f2021-04-22 13:45:10 -0700572{
swissChili53472e82021-05-08 16:06:32 -0700573 if ((sym & HEAP_MASK) != SYMBOL_TAG)
swissChili8fc5e2f2021-04-22 13:45:10 -0700574 return false;
575
swissChili53472e82021-05-08 16:06:32 -0700576 return strcmp((char *)(sym ^ SYMBOL_TAG), str) == 0;
swissChili8fc5e2f2021-04-22 13:45:10 -0700577}
swissChilib8fd4712021-06-23 15:32:04 -0700578
579unsigned char make_pool()
580{
581 return ++max_pool;
582}
583
584unsigned char push_pool(unsigned char pool)
585{
586 unsigned char old = current_pool;
587 current_pool = pool;
588 return old;
589}
590
591void pop_pool(unsigned char pool)
592{
593 current_pool = pool;
594}
595
596bool pool_alive(unsigned char pool)
597{
598 return pool != 0;
599}
swissChilif1ba8c12021-07-02 18:45:38 -0700600
601int cons_line(value_t val)
602{
603 if (!consp(val))
604 return 0;
605
606 struct cons *c = (void *)(val ^ CONS_TAG);
607
608 return c->line;
609}
610
611char *cons_file(value_t val)
612{
613 if (!consp(val))
614 return NULL;
615
616 struct cons *c = (void *)(val ^ CONS_TAG);
617
618 return c->name;
619}
swissChiliddc97542021-07-04 11:47:42 -0700620
swissChili15f1cae2021-07-05 19:08:47 -0700621value_t create_closure(void *code, struct args *args, int ncaptures)
swissChiliddc97542021-07-04 11:47:42 -0700622{
623 struct closure_alloc *ca = malloc_aligned(sizeof(struct closure_alloc) +
624 ncaptures * sizeof(value_t));
625
626 ca->closure.function = code;
swissChili15f1cae2021-07-05 19:08:47 -0700627 ca->closure.args = args;
swissChiliddc97542021-07-04 11:47:42 -0700628 ca->closure.num_captured = ncaptures;
629
630 add_this_alloc(&ca->alloc, CLOSURE_TAG);
631
632 return (value_t)(&ca->closure) | CLOSURE_TAG;
633}
634
635void set_closure_capture_variable(int index, value_t value, value_t closure)
636{
637 if (!closurep(closure))
638 return;
639
640 struct closure *c = (void *)(closure ^ CLOSURE_TAG);
641
642 c->data[index] = value;
643}
swissChili15f1cae2021-07-05 19:08:47 -0700644
645value_t cxdr(value_t v, int index)
646{
647 if (!listp(v) || index >= length(v))
648 return nil;
649
650 for (int i = 0; i < index; i++)
651 {
652 v = cdr(v);
653 }
654
655 return v;
656}
657
658value_t *cxdrref(value_t *v, int index)
659{
660 if (!listp(*v) || index >= length(*v))
661 return NULL;
662
663 value_t *p = v;
664
665 for (int i = 0; i < index; i++)
666 {
667 p = cdrref(*p);
668 }
669
670 return p;
671}
672
673value_t deep_copy(value_t val)
674{
675 if (integerp(val) || val == nil || val == t)
676 {
677 return val;
678 }
679 else if (symbolp(val))
680 {
681 return symval((char *)(val ^ SYMBOL_TAG));
682 }
683 else if (stringp(val))
684 {
685 return strval((char *)(val ^ STRING_TAG));
686 }
687 else if (consp(val))
688 {
689 return cons(deep_copy(car(val)), deep_copy(cdr(val)));
690 }
691 else if (closurep(val))
692 {
693 struct closure *c = (void *)(val ^ CLOSURE_TAG);
694 value_t new = create_closure(c->function, c->args, c->num_captured);
695 struct closure *new_c = (void *)(new ^ CLOSURE_TAG);
696
697 for (int i = 0; i < c->num_captured; i++)
698 {
699 new_c->data[i] = deep_copy(c->data[i]);
700 }
701
702 return new;
703 }
704 else
705 {
706 err("Don't know how to deep copy this, sorry... please report this bug :)");
707 }
708}