blob: a305430f2602d1107f15822fa073c5b05fcb54f5 [file] [log] [blame]
swissChili7a6f5eb2021-04-13 16:46:02 -07001#include "lisp.h"
swissChili6d02af42021-08-05 19:49:01 -07002#include "error.h"
swissChili8cfb7c42021-04-18 21:17:58 -07003#include "plat/plat.h"
4
swissChili7a6f5eb2021-04-13 16:46:02 -07005#include <ctype.h>
6#include <stdbool.h>
7#include <stdio.h>
swissChilibed80922021-04-13 21:58:05 -07008#include <stdlib.h>
9#include <string.h>
swissChili7e1393c2021-07-07 12:59:12 -070010#include <stdarg.h>
swissChili7a6f5eb2021-04-13 16:46:02 -070011
swissChili9e57da42021-06-15 22:22:46 -070012struct alloc *first_a = NULL, *last_a = NULL;
swissChili7a6f5eb2021-04-13 16:46:02 -070013
swissChili8cfb7c42021-04-18 21:17:58 -070014value_t nil = 0b00101111; // magic ;)
swissChili923b5362021-05-09 20:31:43 -070015value_t t = 1 << 3;
swissChilibed80922021-04-13 21:58:05 -070016
swissChilib8fd4712021-06-23 15:32:04 -070017unsigned char max_pool = 0, current_pool = 0;
18
swissChili8b5ec7a2022-08-05 22:26:17 -070019int valint(value_t i)
20{
21 if (!integerp(i))
22 return 0;
23
24 return i >> 2;
25}
26
swissChili53472e82021-05-08 16:06:32 -070027value_t intval(int i)
swissChili7a6f5eb2021-04-13 16:46:02 -070028{
swissChili8cfb7c42021-04-18 21:17:58 -070029 i <<= 2;
30 i |= INT_TAG;
31 return i;
32}
33
swissChilif1ba8c12021-07-02 18:45:38 -070034void add_this_alloc(struct alloc *a, int tag)
35{
swissChilic0acce42022-07-31 13:38:17 -070036 a->mark = -1;
swissChilif1ba8c12021-07-02 18:45:38 -070037 a->type_tag = tag;
38 a->pool = current_pool;
39
40 if (last_a)
41 {
42 a->prev = last_a;
43 last_a->next = a;
44 a->next = NULL;
45 last_a = a;
46 }
47 else
48 {
49 a->prev = a->next = NULL;
50 first_a = last_a = a;
51 }
52}
53
swissChili53472e82021-05-08 16:06:32 -070054value_t cons(value_t car, value_t cdr)
swissChili8cfb7c42021-04-18 21:17:58 -070055{
swissChili9e57da42021-06-15 22:22:46 -070056 struct cons_alloc *item = malloc_aligned(sizeof(struct cons_alloc));
57 struct cons *c = &item->cons;
swissChili7a6f5eb2021-04-13 16:46:02 -070058
swissChilibed80922021-04-13 21:58:05 -070059 c->car = car;
60 c->cdr = cdr;
swissChili2999dd12021-07-02 14:19:53 -070061 c->line = 0;
62 c->name = NULL;
swissChilibed80922021-04-13 21:58:05 -070063
swissChilib3ca4fb2021-04-20 10:33:00 -070064 value_t v = (value_t)c;
swissChili8cfb7c42021-04-18 21:17:58 -070065 v |= CONS_TAG;
swissChili7a6f5eb2021-04-13 16:46:02 -070066
swissChilif1ba8c12021-07-02 18:45:38 -070067 add_this_alloc(&item->alloc, CONS_TAG);
68
swissChili7a6f5eb2021-04-13 16:46:02 -070069 return v;
70}
71
swissChili53472e82021-05-08 16:06:32 -070072void skipws(struct istream *is)
swissChili7a6f5eb2021-04-13 16:46:02 -070073{
swissChilib8fd4712021-06-23 15:32:04 -070074start:
swissChili53472e82021-05-08 16:06:32 -070075 while (isspace(is->peek(is)))
76 is->get(is);
swissChilib8fd4712021-06-23 15:32:04 -070077
78 if (is->peek(is) == ';')
79 {
80 while (is->get(is) != '\n')
swissChiliddc97542021-07-04 11:47:42 -070081 {
82 }
swissChilib8fd4712021-06-23 15:32:04 -070083
84 // Only time I ever use labels is for stuff like this. Compiler would
85 // probably optimize this if I used recursion but I don't want to
86 // bother.
87 goto start;
88 }
swissChili7a6f5eb2021-04-13 16:46:02 -070089}
90
swissChili53472e82021-05-08 16:06:32 -070091bool isallowedchar(char c)
swissChili7a6f5eb2021-04-13 16:46:02 -070092{
swissChilibed80922021-04-13 21:58:05 -070093 return (c >= '#' && c <= '\'') || (c >= '*' && c <= '/') ||
swissChili53e7cd12021-08-02 21:55:53 -070094 (c >= '<' && c <= '@');
swissChili7a6f5eb2021-04-13 16:46:02 -070095}
96
swissChili53472e82021-05-08 16:06:32 -070097bool issymstart(char c)
swissChili7a6f5eb2021-04-13 16:46:02 -070098{
swissChili53472e82021-05-08 16:06:32 -070099 return isalpha(c) || isallowedchar(c);
swissChili7a6f5eb2021-04-13 16:46:02 -0700100}
101
swissChili53472e82021-05-08 16:06:32 -0700102bool issym(char c)
swissChili7a6f5eb2021-04-13 16:46:02 -0700103{
swissChili53472e82021-05-08 16:06:32 -0700104 return isalpha(c) || isallowedchar(c) || isdigit(c);
swissChili7a6f5eb2021-04-13 16:46:02 -0700105}
106
swissChili6d02af42021-08-05 19:49:01 -0700107struct error readsym(struct istream *is, value_t *val)
swissChili7a6f5eb2021-04-13 16:46:02 -0700108{
swissChili6d02af42021-08-05 19:49:01 -0700109 E_INIT();
110
swissChili53472e82021-05-08 16:06:32 -0700111 skipws(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700112
swissChili53472e82021-05-08 16:06:32 -0700113 if (!issymstart(is->peek(is)))
swissChili6d02af42021-08-05 19:49:01 -0700114 THROWSAFE(EEXPECTED);
swissChili7a6f5eb2021-04-13 16:46:02 -0700115
116 int size = 8;
swissChilif1ba8c12021-07-02 18:45:38 -0700117 struct alloc *a = malloc_aligned(size + sizeof(struct alloc));
swissChilif1ba8c12021-07-02 18:45:38 -0700118
119 char *s = (char *)(a + 1);
swissChili7a6f5eb2021-04-13 16:46:02 -0700120
swissChili53472e82021-05-08 16:06:32 -0700121 s[0] = is->get(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700122
swissChili53472e82021-05-08 16:06:32 -0700123 for (int i = 1;; i++)
swissChili7a6f5eb2021-04-13 16:46:02 -0700124 {
swissChili53e7cd12021-08-02 21:55:53 -0700125 if (i >= size)
126 {
127 size *= 2;
128 a = realloc_aligned(a, size + sizeof(struct alloc));
129 s = (char *)(a + 1);
130 }
131
swissChili53472e82021-05-08 16:06:32 -0700132 if (issym(is->peek(is)))
swissChili7a6f5eb2021-04-13 16:46:02 -0700133 {
swissChili53472e82021-05-08 16:06:32 -0700134 s[i] = is->get(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700135 }
136 else
137 {
swissChili53472e82021-05-08 16:06:32 -0700138 s[i] = 0;
swissChilib3ca4fb2021-04-20 10:33:00 -0700139 *val = (value_t)s;
swissChili8cfb7c42021-04-18 21:17:58 -0700140 *val |= SYMBOL_TAG;
swissChili7a6f5eb2021-04-13 16:46:02 -0700141
swissChili53e7cd12021-08-02 21:55:53 -0700142 add_this_alloc(a, SYMBOL_TAG);
swissChili6d02af42021-08-05 19:49:01 -0700143
144 OKAY();
swissChili7a6f5eb2021-04-13 16:46:02 -0700145 }
146 }
147}
148
swissChili6d02af42021-08-05 19:49:01 -0700149struct error readstr(struct istream *is, value_t *val)
swissChili7a6f5eb2021-04-13 16:46:02 -0700150{
swissChili6d02af42021-08-05 19:49:01 -0700151 E_INIT();
152
swissChili53472e82021-05-08 16:06:32 -0700153 skipws(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700154
swissChili53472e82021-05-08 16:06:32 -0700155 if (is->peek(is) != '"')
swissChili6d02af42021-08-05 19:49:01 -0700156 THROWSAFE(EEXPECTED);
swissChili7a6f5eb2021-04-13 16:46:02 -0700157
158 bool escape = false;
159 int size = 8;
swissChilif1ba8c12021-07-02 18:45:38 -0700160
161 struct alloc *a = malloc_aligned(size + sizeof(struct alloc));
swissChilif1ba8c12021-07-02 18:45:38 -0700162
163 char *s = (char *)(a + 1);
swissChili7a6f5eb2021-04-13 16:46:02 -0700164
swissChili53472e82021-05-08 16:06:32 -0700165 (void)is->get(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700166
swissChili53472e82021-05-08 16:06:32 -0700167 for (int i = 0;; i++)
swissChili7a6f5eb2021-04-13 16:46:02 -0700168 {
swissChili53472e82021-05-08 16:06:32 -0700169 if (is->peek(is) != '"')
swissChili7a6f5eb2021-04-13 16:46:02 -0700170 {
swissChili53472e82021-05-08 16:06:32 -0700171 if (i >= size)
swissChili7a6f5eb2021-04-13 16:46:02 -0700172 {
swissChilibed80922021-04-13 21:58:05 -0700173 size *= 2;
swissChilif1ba8c12021-07-02 18:45:38 -0700174 a = realloc_aligned(a, size + sizeof(struct alloc));
175 s = (char *)(a + 1);
swissChili7a6f5eb2021-04-13 16:46:02 -0700176 }
swissChilibed80922021-04-13 21:58:05 -0700177
swissChili53472e82021-05-08 16:06:32 -0700178 char c = is->get(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700179
swissChili53472e82021-05-08 16:06:32 -0700180 if (escape && c == 'n')
swissChili7a6f5eb2021-04-13 16:46:02 -0700181 c = '\n';
swissChili53472e82021-05-08 16:06:32 -0700182 else if (escape && c == '\\')
swissChili7a6f5eb2021-04-13 16:46:02 -0700183 c = '\\';
184
swissChili53472e82021-05-08 16:06:32 -0700185 if (c == '\\' && !escape)
swissChili7a6f5eb2021-04-13 16:46:02 -0700186 {
187 escape = true;
188 i--; // will be incremented again, UGLY.
189 }
190 else
191 {
192 escape = false;
swissChili53472e82021-05-08 16:06:32 -0700193 s[i] = c;
swissChili7a6f5eb2021-04-13 16:46:02 -0700194 }
195 }
196 else
197 {
swissChili7e1393c2021-07-07 12:59:12 -0700198 s[i] = '\0';
swissChili53472e82021-05-08 16:06:32 -0700199 is->get(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700200
swissChilib3ca4fb2021-04-20 10:33:00 -0700201 *val = (value_t)s;
swissChili8cfb7c42021-04-18 21:17:58 -0700202 *val |= STRING_TAG;
swissChili7a6f5eb2021-04-13 16:46:02 -0700203
swissChili53e7cd12021-08-02 21:55:53 -0700204 add_this_alloc(a, STRING_TAG);
swissChili6d02af42021-08-05 19:49:01 -0700205
206 OKAY();
swissChili7a6f5eb2021-04-13 16:46:02 -0700207 }
208 }
209}
210
swissChilie0d4b902022-07-30 17:32:01 -0700211void printval_ol(value_t v)
swissChili7a6f5eb2021-04-13 16:46:02 -0700212{
swissChilie0d4b902022-07-30 17:32:01 -0700213// for (int i = 0; i < depth; i++)
214// printf(" ");
swissChili7a6f5eb2021-04-13 16:46:02 -0700215
swissChili53472e82021-05-08 16:06:32 -0700216 if (symbolp(v))
swissChili7a6f5eb2021-04-13 16:46:02 -0700217 {
swissChilie0d4b902022-07-30 17:32:01 -0700218 printf("%s", (char *)(v ^ SYMBOL_TAG));
swissChili8cfb7c42021-04-18 21:17:58 -0700219 }
swissChili53472e82021-05-08 16:06:32 -0700220 else if (stringp(v))
swissChili8cfb7c42021-04-18 21:17:58 -0700221 {
swissChilie0d4b902022-07-30 17:32:01 -0700222 printf("\"%s\"", (char *)(v ^ STRING_TAG));
swissChili8cfb7c42021-04-18 21:17:58 -0700223 }
swissChili53472e82021-05-08 16:06:32 -0700224 else if (integerp(v))
swissChili6eee4f92021-04-20 09:34:30 -0700225 {
swissChilie0d4b902022-07-30 17:32:01 -0700226 printf("%d", v >> 2);
swissChili6eee4f92021-04-20 09:34:30 -0700227 }
swissChili53472e82021-05-08 16:06:32 -0700228 else if (consp(v))
swissChili8cfb7c42021-04-18 21:17:58 -0700229 {
swissChili53472e82021-05-08 16:06:32 -0700230 if (listp(v))
swissChilibed80922021-04-13 21:58:05 -0700231 {
swissChilie0d4b902022-07-30 17:32:01 -0700232 printf("(");
233 printval_ol(car(v));
swissChilibed80922021-04-13 21:58:05 -0700234
swissChilie0d4b902022-07-30 17:32:01 -0700235 for (value_t n = cdr(v); !nilp(n); n = cdr(n))
swissChilibed80922021-04-13 21:58:05 -0700236 {
swissChilie0d4b902022-07-30 17:32:01 -0700237 printf(" ");
238 printval_ol(car(n));
swissChilibed80922021-04-13 21:58:05 -0700239 }
swissChilie0d4b902022-07-30 17:32:01 -0700240
241 printf(")");
swissChilibed80922021-04-13 21:58:05 -0700242 }
243 else
244 {
swissChilie0d4b902022-07-30 17:32:01 -0700245 printf("(");
246 printval_ol(car(v));
247 printf(" . ");
248 printval_ol(cdr(v));
249 printf(")");
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 {
swissChili8b5ec7a2022-08-05 22:26:17 -0700254 printf("nil");
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);
swissChilie0d4b902022-07-30 17:32:01 -0700259 printf("<closure %p (%d) %d>",
swissChili15f1cae2021-07-05 19:08:47 -0700260 c->function, c->args->num_required, c->num_captured);
swissChiliddc97542021-07-04 11:47:42 -0700261 }
swissChili8b5ec7a2022-08-05 22:26:17 -0700262 else if (classp(v))
263 {
264 struct class *c = (void *)(v ^ CLASS_TAG);
265 printf("<class %s", (char *)(c->type ^ SYMBOL_TAG));
266
267 for (int i = 0; i < c->num_members; i++)
268 {
269 printf(" ");
270 printval_ol(c->members[i]);
271 }
272
273 printf(">");
274 }
swissChili8cfb7c42021-04-18 21:17:58 -0700275 else
276 {
swissChilie0d4b902022-07-30 17:32:01 -0700277 printf("<unknown %d>", v);
swissChili7a6f5eb2021-04-13 16:46:02 -0700278 }
279}
280
swissChilie0d4b902022-07-30 17:32:01 -0700281void printval(value_t v, int depth)
282{
283 UNUSED(depth);
284 printval_ol(v);
285 printf("\n");
286}
287
swissChili6d02af42021-08-05 19:49:01 -0700288struct error readlist(struct istream *is, value_t *val)
swissChilibed80922021-04-13 21:58:05 -0700289{
swissChili6d02af42021-08-05 19:49:01 -0700290 E_INIT();
291 NEARIS(is);
292
swissChili53472e82021-05-08 16:06:32 -0700293 skipws(is);
swissChilibed80922021-04-13 21:58:05 -0700294
swissChili53472e82021-05-08 16:06:32 -0700295 if (is->peek(is) != '(')
swissChili6d02af42021-08-05 19:49:01 -0700296 THROWSAFE(EEXPECTED);
swissChilibed80922021-04-13 21:58:05 -0700297
swissChili53472e82021-05-08 16:06:32 -0700298 is->get(is);
swissChilibed80922021-04-13 21:58:05 -0700299
swissChili53472e82021-05-08 16:06:32 -0700300 *val = readn(is);
swissChilibed80922021-04-13 21:58:05 -0700301
swissChili53e7cd12021-08-02 21:55:53 -0700302 skipws(is);
303
swissChili53472e82021-05-08 16:06:32 -0700304 if (is->peek(is) != ')')
swissChilibed80922021-04-13 21:58:05 -0700305 {
swissChili6d02af42021-08-05 19:49:01 -0700306 NEARIS(is);
307 THROW(EEXPECTED, "Unterminated list");
swissChilibed80922021-04-13 21:58:05 -0700308 }
swissChili53472e82021-05-08 16:06:32 -0700309 is->get(is);
swissChilibed80922021-04-13 21:58:05 -0700310
swissChili6d02af42021-08-05 19:49:01 -0700311 OKAY();
swissChilibed80922021-04-13 21:58:05 -0700312}
313
swissChili6d02af42021-08-05 19:49:01 -0700314struct error readint(struct istream *is, value_t *val)
swissChili6eee4f92021-04-20 09:34:30 -0700315{
swissChili6d02af42021-08-05 19:49:01 -0700316 E_INIT();
317
swissChilib6c858c2021-06-30 21:12:43 -0700318 skipws(is);
319
swissChili6eee4f92021-04-20 09:34:30 -0700320 int number = 0;
321
swissChili53472e82021-05-08 16:06:32 -0700322 if (!isdigit(is->peek(is)))
swissChili6d02af42021-08-05 19:49:01 -0700323 THROWSAFE(EEXPECTED);
swissChili6eee4f92021-04-20 09:34:30 -0700324
swissChili53472e82021-05-08 16:06:32 -0700325 while (isdigit(is->peek(is)))
swissChili6eee4f92021-04-20 09:34:30 -0700326 {
327 number *= 10;
swissChili53472e82021-05-08 16:06:32 -0700328 number += is->get(is) - '0';
swissChili6eee4f92021-04-20 09:34:30 -0700329 }
330
swissChili53472e82021-05-08 16:06:32 -0700331 *val = intval(number);
swissChili6d02af42021-08-05 19:49:01 -0700332 OKAY();
swissChili6eee4f92021-04-20 09:34:30 -0700333}
334
swissChili6d02af42021-08-05 19:49:01 -0700335struct error readquote(struct istream *is, value_t *val)
swissChilib6c858c2021-06-30 21:12:43 -0700336{
swissChili6d02af42021-08-05 19:49:01 -0700337 E_INIT();
338
swissChilib6c858c2021-06-30 21:12:43 -0700339 skipws(is);
340
341 char c = is->peek(is);
342
swissChili74348422021-07-04 13:23:24 -0700343 if (c == '\'' || c == '`' || c == ',' || c == '#')
swissChilib6c858c2021-06-30 21:12:43 -0700344 {
345 is->get(is);
346
swissChili74348422021-07-04 13:23:24 -0700347 if (c == ',' && is->peek(is) == '@')
swissChilib6c858c2021-06-30 21:12:43 -0700348 {
349 // This is actually a splice
350 is->get(is);
351 c = '@';
352 }
swissChili74348422021-07-04 13:23:24 -0700353 else if (c == '#' && is->peek(is) == '\'')
354 {
355 is->get(is);
356 }
swissChilib6c858c2021-06-30 21:12:43 -0700357
358 // Read the next form and wrap it in the appropriate function
359
360 value_t wrapped;
swissChili6d02af42021-08-05 19:49:01 -0700361 NEARIS(is);
swissChilib6c858c2021-06-30 21:12:43 -0700362
swissChili36f2c692021-08-08 14:31:44 -0700363 struct error read_error = read1(is, &wrapped);
364 TRY_ELSE(read_error, EEXPECTED, "Expected a form after reader macro char %c", c);
swissChilib6c858c2021-06-30 21:12:43 -0700365
366 value_t symbol = nil;
367
368 switch (c)
369 {
370 case '\'':
371 symbol = symval("quote");
372 break;
373 case '`':
374 symbol = symval("backquote");
375 break;
376 case ',':
377 symbol = symval("unquote");
378 break;
379 case '@':
swissChili6b47b6d2021-06-30 22:08:55 -0700380 symbol = symval("unquote-splice");
swissChilib6c858c2021-06-30 21:12:43 -0700381 break;
swissChili74348422021-07-04 13:23:24 -0700382 case '#':
383 symbol = symval("function");
384 break;
385 default:
swissChili6d02af42021-08-05 19:49:01 -0700386 NEARIS(is);
387 THROW(EINVALID, "Invalid reader macro char %c", c);
swissChilib6c858c2021-06-30 21:12:43 -0700388 }
389
390 *val = cons(symbol, cons(wrapped, nil));
391
swissChili6d02af42021-08-05 19:49:01 -0700392 OKAY();
swissChilib6c858c2021-06-30 21:12:43 -0700393 }
394 else
395 {
swissChili6d02af42021-08-05 19:49:01 -0700396 THROWSAFE(EEXPECTED);
swissChilib6c858c2021-06-30 21:12:43 -0700397 }
398}
399
swissChili6d02af42021-08-05 19:49:01 -0700400struct error read1(struct istream *is, value_t *val)
swissChili7a6f5eb2021-04-13 16:46:02 -0700401{
swissChili6d02af42021-08-05 19:49:01 -0700402 E_INIT();
swissChilib6c858c2021-06-30 21:12:43 -0700403
swissChili6d02af42021-08-05 19:49:01 -0700404 NEARIS(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700405
swissChili6d02af42021-08-05 19:49:01 -0700406 OKAY_IF(readquote(is, val));
407 OKAY_IF(readsym(is, val));
408 OKAY_IF(readstr(is, val));
409 OKAY_IF(readint(is, val));
410 OKAY_IF(readlist(is, val));
swissChili7a6f5eb2021-04-13 16:46:02 -0700411
swissChili6d02af42021-08-05 19:49:01 -0700412 THROWSAFE(EEXPECTED);
swissChili7a6f5eb2021-04-13 16:46:02 -0700413}
414
swissChili2999dd12021-07-02 14:19:53 -0700415void set_cons_info(value_t cons, int line, char *name)
416{
417 if (!consp(cons))
418 return;
419
420 struct cons *ca = (void *)(cons ^ CONS_TAG);
421
422 ca->line = line;
423 ca->name = name;
424}
425
swissChili53472e82021-05-08 16:06:32 -0700426value_t readn(struct istream *is)
swissChilibed80922021-04-13 21:58:05 -0700427{
swissChili8cfb7c42021-04-18 21:17:58 -0700428 value_t first = nil;
429 value_t *last = &first;
swissChilibed80922021-04-13 21:58:05 -0700430
swissChili8cfb7c42021-04-18 21:17:58 -0700431 value_t read_val;
swissChilibed80922021-04-13 21:58:05 -0700432
swissChili6d02af42021-08-05 19:49:01 -0700433 while (IS_OKAY(read1(is, &read_val)))
swissChilibed80922021-04-13 21:58:05 -0700434 {
swissChili2999dd12021-07-02 14:19:53 -0700435 int line;
436 char *file;
437
438 is->getpos(is, &line, &file);
swissChili53472e82021-05-08 16:06:32 -0700439 *last = cons(read_val, nil);
swissChili2999dd12021-07-02 14:19:53 -0700440 set_cons_info(*last, line, file);
441
swissChili53472e82021-05-08 16:06:32 -0700442 last = cdrref(*last);
swissChilibed80922021-04-13 21:58:05 -0700443 }
444
445 return first;
446}
447
swissChili53472e82021-05-08 16:06:32 -0700448bool startswith(struct istream *s, char *pattern)
swissChili7a6f5eb2021-04-13 16:46:02 -0700449{
swissChili53472e82021-05-08 16:06:32 -0700450 char *check = strdup(pattern);
451 s->read(s, check, strlen(pattern));
swissChili7a6f5eb2021-04-13 16:46:02 -0700452
swissChili53472e82021-05-08 16:06:32 -0700453 bool res = strcmp(check, pattern) == 0;
454 free(check);
swissChili7a6f5eb2021-04-13 16:46:02 -0700455
456 return res;
457}
swissChilibed80922021-04-13 21:58:05 -0700458
swissChilif1ba8c12021-07-02 18:45:38 -0700459static value_t strptrval(char *str, int tag)
swissChilibed80922021-04-13 21:58:05 -0700460{
swissChili8cfb7c42021-04-18 21:17:58 -0700461 value_t v;
462
swissChilif1ba8c12021-07-02 18:45:38 -0700463 struct alloc *al = malloc_aligned(strlen(str) + 1 + sizeof(struct alloc));
464 add_this_alloc(al, SYMBOL_TAG);
465
466 char *a = (char *)(al + 1);
467
swissChilib6c858c2021-06-30 21:12:43 -0700468 strcpy(a, str);
swissChilib3ca4fb2021-04-20 10:33:00 -0700469 v = (value_t)a;
swissChilif1ba8c12021-07-02 18:45:38 -0700470 v |= tag;
swissChilibed80922021-04-13 21:58:05 -0700471
472 return v;
473}
474
swissChilif1ba8c12021-07-02 18:45:38 -0700475value_t strval(char *str)
476{
477 return strptrval(str, STRING_TAG);
478}
479
swissChilib6c858c2021-06-30 21:12:43 -0700480value_t symval(char *str)
481{
swissChilif1ba8c12021-07-02 18:45:38 -0700482 return strptrval(str, SYMBOL_TAG);
swissChilib6c858c2021-06-30 21:12:43 -0700483}
484
swissChili53472e82021-05-08 16:06:32 -0700485bool integerp(value_t v)
swissChilibed80922021-04-13 21:58:05 -0700486{
swissChili8cfb7c42021-04-18 21:17:58 -0700487 return (v & INT_MASK) == INT_TAG;
488}
swissChilibed80922021-04-13 21:58:05 -0700489
swissChili53472e82021-05-08 16:06:32 -0700490bool symbolp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700491{
492 return (v & HEAP_MASK) == SYMBOL_TAG;
493}
494
swissChili53472e82021-05-08 16:06:32 -0700495bool stringp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700496{
497 return (v & HEAP_MASK) == STRING_TAG;
498}
499
swissChili53472e82021-05-08 16:06:32 -0700500bool consp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700501{
502 return (v & HEAP_MASK) == CONS_TAG;
503}
504
swissChili8b5ec7a2022-08-05 22:26:17 -0700505bool classp(value_t v)
506{
507 return (v & HEAP_MASK) == CLASS_TAG;
508}
509
swissChili9e57da42021-06-15 22:22:46 -0700510bool heapp(value_t v)
511{
swissChiliddc97542021-07-04 11:47:42 -0700512 return consp(v) || stringp(v) || symbolp(v) || closurep(v);
513}
514
515bool closurep(value_t v)
516{
517 return (v & HEAP_MASK) == CLOSURE_TAG;
swissChili9e57da42021-06-15 22:22:46 -0700518}
519
swissChili53472e82021-05-08 16:06:32 -0700520bool listp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700521{
522 value_t next = v;
523
swissChili53472e82021-05-08 16:06:32 -0700524 while (consp(next))
swissChilibed80922021-04-13 21:58:05 -0700525 {
swissChili53472e82021-05-08 16:06:32 -0700526 next = cdr(next);
swissChilibed80922021-04-13 21:58:05 -0700527 }
528
swissChili53472e82021-05-08 16:06:32 -0700529 return nilp(next);
swissChilibed80922021-04-13 21:58:05 -0700530}
531
swissChili53472e82021-05-08 16:06:32 -0700532value_t car(value_t v)
swissChilibed80922021-04-13 21:58:05 -0700533{
swissChili53472e82021-05-08 16:06:32 -0700534 if (!consp(v))
swissChilibed80922021-04-13 21:58:05 -0700535 return nil;
536
swissChili53472e82021-05-08 16:06:32 -0700537 return *carref(v);
swissChilibed80922021-04-13 21:58:05 -0700538}
539
swissChili53472e82021-05-08 16:06:32 -0700540value_t cdr(value_t v)
swissChilibed80922021-04-13 21:58:05 -0700541{
swissChili53472e82021-05-08 16:06:32 -0700542 if (!consp(v))
swissChilibed80922021-04-13 21:58:05 -0700543 return nil;
544
swissChili53472e82021-05-08 16:06:32 -0700545 return *cdrref(v);
swissChilibed80922021-04-13 21:58:05 -0700546}
547
swissChili53472e82021-05-08 16:06:32 -0700548value_t *carref(value_t v)
swissChilibed80922021-04-13 21:58:05 -0700549{
swissChili53472e82021-05-08 16:06:32 -0700550 if (!consp(v))
swissChili8cfb7c42021-04-18 21:17:58 -0700551 return NULL;
552
swissChilib3ca4fb2021-04-20 10:33:00 -0700553 struct cons *c = (void *)(v ^ CONS_TAG);
swissChili8cfb7c42021-04-18 21:17:58 -0700554 return &c->car;
swissChilibed80922021-04-13 21:58:05 -0700555}
swissChilica107a02021-04-14 12:07:30 -0700556
swissChili53472e82021-05-08 16:06:32 -0700557value_t *cdrref(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700558{
swissChili53472e82021-05-08 16:06:32 -0700559 if (!consp(v))
swissChili8cfb7c42021-04-18 21:17:58 -0700560 return NULL;
561
swissChilib3ca4fb2021-04-20 10:33:00 -0700562 struct cons *c = (void *)(v ^ CONS_TAG);
swissChili8cfb7c42021-04-18 21:17:58 -0700563 return &c->cdr;
564}
565
swissChili53472e82021-05-08 16:06:32 -0700566bool nilp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700567{
568 return v == nil;
569}
570
swissChili53472e82021-05-08 16:06:32 -0700571int length(value_t v)
swissChilica107a02021-04-14 12:07:30 -0700572{
573 int i = 0;
574
swissChili53472e82021-05-08 16:06:32 -0700575 for (; !nilp(v); v = cdr(v))
swissChilica107a02021-04-14 12:07:30 -0700576 i++;
577
578 return i;
579}
swissChilib3ca4fb2021-04-20 10:33:00 -0700580
swissChili53472e82021-05-08 16:06:32 -0700581value_t elt(value_t v, int index)
swissChilib3ca4fb2021-04-20 10:33:00 -0700582{
swissChili53472e82021-05-08 16:06:32 -0700583 for (int i = 0; i < index; i++)
swissChilib3ca4fb2021-04-20 10:33:00 -0700584 {
swissChili53472e82021-05-08 16:06:32 -0700585 v = cdr(v);
swissChilib3ca4fb2021-04-20 10:33:00 -0700586 }
587
swissChili53472e82021-05-08 16:06:32 -0700588 return car(v);
swissChilib3ca4fb2021-04-20 10:33:00 -0700589}
swissChili8fc5e2f2021-04-22 13:45:10 -0700590
swissChili53472e82021-05-08 16:06:32 -0700591bool symstreq(value_t sym, char *str)
swissChili8fc5e2f2021-04-22 13:45:10 -0700592{
swissChili53472e82021-05-08 16:06:32 -0700593 if ((sym & HEAP_MASK) != SYMBOL_TAG)
swissChili8fc5e2f2021-04-22 13:45:10 -0700594 return false;
595
swissChili53472e82021-05-08 16:06:32 -0700596 return strcmp((char *)(sym ^ SYMBOL_TAG), str) == 0;
swissChili8fc5e2f2021-04-22 13:45:10 -0700597}
swissChilib8fd4712021-06-23 15:32:04 -0700598
599unsigned char make_pool()
600{
601 return ++max_pool;
602}
603
604unsigned char push_pool(unsigned char pool)
605{
606 unsigned char old = current_pool;
607 current_pool = pool;
608 return old;
609}
610
611void pop_pool(unsigned char pool)
612{
613 current_pool = pool;
614}
615
616bool pool_alive(unsigned char pool)
617{
618 return pool != 0;
619}
swissChilif1ba8c12021-07-02 18:45:38 -0700620
swissChili36f2c692021-08-08 14:31:44 -0700621void add_to_pool(value_t form)
622{
623 if (!heapp(form))
624 return;
625
626 struct alloc *a = (void *)(form & ~0b111);
627 a[-1].pool = current_pool;
628}
629
swissChilic0acce42022-07-31 13:38:17 -0700630void del_alloc(struct alloc *alloc)
631{
swissChili9d428a82022-08-01 20:47:40 -0700632 /* if (alloc->type_tag == CLOSURE_TAG) */
633 /* { */
634 /* fprintf(stderr, "del_alloc closure\n"); */
635 /* struct closure_alloc *ca = alloc; */
636 /* free(ca->closure.args); */
637 /* } */
swissChilic0acce42022-07-31 13:38:17 -0700638
639 free_aligned(alloc);
640}
641
swissChilif1ba8c12021-07-02 18:45:38 -0700642int cons_line(value_t val)
643{
644 if (!consp(val))
645 return 0;
646
647 struct cons *c = (void *)(val ^ CONS_TAG);
648
649 return c->line;
650}
651
652char *cons_file(value_t val)
653{
654 if (!consp(val))
655 return NULL;
656
657 struct cons *c = (void *)(val ^ CONS_TAG);
658
659 return c->name;
660}
swissChiliddc97542021-07-04 11:47:42 -0700661
swissChili15f1cae2021-07-05 19:08:47 -0700662value_t create_closure(void *code, struct args *args, int ncaptures)
swissChiliddc97542021-07-04 11:47:42 -0700663{
664 struct closure_alloc *ca = malloc_aligned(sizeof(struct closure_alloc) +
665 ncaptures * sizeof(value_t));
666
667 ca->closure.function = code;
swissChili15f1cae2021-07-05 19:08:47 -0700668 ca->closure.args = args;
swissChiliddc97542021-07-04 11:47:42 -0700669 ca->closure.num_captured = ncaptures;
670
671 add_this_alloc(&ca->alloc, CLOSURE_TAG);
672
673 return (value_t)(&ca->closure) | CLOSURE_TAG;
674}
675
676void set_closure_capture_variable(int index, value_t value, value_t closure)
677{
678 if (!closurep(closure))
679 return;
680
681 struct closure *c = (void *)(closure ^ CLOSURE_TAG);
682
683 c->data[index] = value;
684}
swissChili15f1cae2021-07-05 19:08:47 -0700685
686value_t cxdr(value_t v, int index)
687{
688 if (!listp(v) || index >= length(v))
689 return nil;
690
691 for (int i = 0; i < index; i++)
692 {
693 v = cdr(v);
694 }
695
696 return v;
697}
698
699value_t *cxdrref(value_t *v, int index)
700{
701 if (!listp(*v) || index >= length(*v))
702 return NULL;
703
704 value_t *p = v;
705
706 for (int i = 0; i < index; i++)
707 {
708 p = cdrref(*p);
709 }
710
711 return p;
712}
713
714value_t deep_copy(value_t val)
715{
716 if (integerp(val) || val == nil || val == t)
717 {
718 return val;
719 }
720 else if (symbolp(val))
721 {
722 return symval((char *)(val ^ SYMBOL_TAG));
723 }
724 else if (stringp(val))
725 {
726 return strval((char *)(val ^ STRING_TAG));
727 }
728 else if (consp(val))
729 {
730 return cons(deep_copy(car(val)), deep_copy(cdr(val)));
731 }
732 else if (closurep(val))
733 {
734 struct closure *c = (void *)(val ^ CLOSURE_TAG);
735 value_t new = create_closure(c->function, c->args, c->num_captured);
736 struct closure *new_c = (void *)(new ^ CLOSURE_TAG);
737
738 for (int i = 0; i < c->num_captured; i++)
739 {
740 new_c->data[i] = deep_copy(c->data[i]);
741 }
742
743 return new;
744 }
745 else
746 {
swissChili6d02af42021-08-05 19:49:01 -0700747 fprintf(stderr, "Don't know how to deep copy this, sorry... please report this bug :)");
748 return nil;
swissChili15f1cae2021-07-05 19:08:47 -0700749 }
750}
swissChilia7568dc2021-08-08 16:52:52 -0700751
swissChili9d428a82022-08-01 20:47:40 -0700752value_t *nilptr(value_t *val)
swissChilia7568dc2021-08-08 16:52:52 -0700753{
swissChili9d428a82022-08-01 20:47:40 -0700754 if (!val)
swissChilia7568dc2021-08-08 16:52:52 -0700755 return NULL;
756
swissChili9d428a82022-08-01 20:47:40 -0700757 if (!listp(*val))
swissChilia7568dc2021-08-08 16:52:52 -0700758 return NULL;
759
swissChili9d428a82022-08-01 20:47:40 -0700760 if (nilp(*val))
761 return val;
762
swissChilia7568dc2021-08-08 16:52:52 -0700763 value_t *p;
764
swissChili9d428a82022-08-01 20:47:40 -0700765 for (p = cdrref(*val); !nilp(*p); p = cdrref(*p))
swissChilia7568dc2021-08-08 16:52:52 -0700766 {
767 }
768
769 return p;
770}
771
772value_t merge2(value_t front, value_t back)
773{
swissChilifc5c9412021-08-08 19:08:26 -0700774 if (!listp(front) && listp(back))
775 return cons(front, back);
swissChilia7568dc2021-08-08 16:52:52 -0700776
swissChilifc5c9412021-08-08 19:08:26 -0700777 if (listp(front) && !listp(back))
778 back = cons(back, nil);
779
swissChili9d428a82022-08-01 20:47:40 -0700780 *nilptr(&front) = back;
swissChilia7568dc2021-08-08 16:52:52 -0700781
782 return front;
783}