blob: a015d4e473aa7c813bc81f6b25578ef1d604e9ed [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
swissChili53472e82021-05-08 16:06:32 -070015void err(const char *msg)
swissChilibed80922021-04-13 21:58:05 -070016{
swissChili53472e82021-05-08 16:06:32 -070017 fprintf(stderr, "ERROR: %s\n", msg);
18 exit(1);
swissChilibed80922021-04-13 21:58:05 -070019}
20
swissChili53472e82021-05-08 16:06:32 -070021value_t intval(int i)
swissChili7a6f5eb2021-04-13 16:46:02 -070022{
swissChili8cfb7c42021-04-18 21:17:58 -070023 i <<= 2;
24 i |= INT_TAG;
25 return i;
26}
27
swissChili53472e82021-05-08 16:06:32 -070028value_t cons(value_t car, value_t cdr)
swissChili8cfb7c42021-04-18 21:17:58 -070029{
swissChili9e57da42021-06-15 22:22:46 -070030 struct cons_alloc *item = malloc_aligned(sizeof(struct cons_alloc));
31 struct cons *c = &item->cons;
swissChili7a6f5eb2021-04-13 16:46:02 -070032
swissChilibed80922021-04-13 21:58:05 -070033 c->car = car;
34 c->cdr = cdr;
35
swissChilie9fec8b2021-06-22 13:59:33 -070036 item->alloc.type_tag = CONS_TAG;
swissChili7a6f5eb2021-04-13 16:46:02 -070037
swissChili53472e82021-05-08 16:06:32 -070038 if (last_a)
swissChili7a6f5eb2021-04-13 16:46:02 -070039 {
swissChili9e57da42021-06-15 22:22:46 -070040 item->alloc.prev = last_a;
swissChili7a6f5eb2021-04-13 16:46:02 -070041 last_a->next = item;
swissChili9e57da42021-06-15 22:22:46 -070042 item->alloc.next = NULL;
swissChilie9fec8b2021-06-22 13:59:33 -070043 last_a = item;
swissChili7a6f5eb2021-04-13 16:46:02 -070044 }
45 else
46 {
swissChili9e57da42021-06-15 22:22:46 -070047 item->alloc.prev = item->alloc.next = NULL;
swissChili7a6f5eb2021-04-13 16:46:02 -070048 first_a = last_a = item;
49 }
50
swissChilib3ca4fb2021-04-20 10:33:00 -070051 value_t v = (value_t)c;
swissChili8cfb7c42021-04-18 21:17:58 -070052 v |= CONS_TAG;
swissChili7a6f5eb2021-04-13 16:46:02 -070053
54 return v;
55}
56
swissChili53472e82021-05-08 16:06:32 -070057void skipws(struct istream *is)
swissChili7a6f5eb2021-04-13 16:46:02 -070058{
swissChili53472e82021-05-08 16:06:32 -070059 while (isspace(is->peek(is)))
60 is->get(is);
swissChili7a6f5eb2021-04-13 16:46:02 -070061}
62
swissChili53472e82021-05-08 16:06:32 -070063bool isallowedchar(char c)
swissChili7a6f5eb2021-04-13 16:46:02 -070064{
swissChilibed80922021-04-13 21:58:05 -070065 return (c >= '#' && c <= '\'') || (c >= '*' && c <= '/') ||
66 (c >= '>' && c <= '@');
swissChili7a6f5eb2021-04-13 16:46:02 -070067}
68
swissChili53472e82021-05-08 16:06:32 -070069bool issymstart(char c)
swissChili7a6f5eb2021-04-13 16:46:02 -070070{
swissChili53472e82021-05-08 16:06:32 -070071 return isalpha(c) || isallowedchar(c);
swissChili7a6f5eb2021-04-13 16:46:02 -070072}
73
swissChili53472e82021-05-08 16:06:32 -070074bool issym(char c)
swissChili7a6f5eb2021-04-13 16:46:02 -070075{
swissChili53472e82021-05-08 16:06:32 -070076 return isalpha(c) || isallowedchar(c) || isdigit(c);
swissChili7a6f5eb2021-04-13 16:46:02 -070077}
78
swissChili53472e82021-05-08 16:06:32 -070079bool readsym(struct istream *is, value_t *val)
swissChili7a6f5eb2021-04-13 16:46:02 -070080{
swissChili53472e82021-05-08 16:06:32 -070081 skipws(is);
swissChili7a6f5eb2021-04-13 16:46:02 -070082
swissChili53472e82021-05-08 16:06:32 -070083 if (!issymstart(is->peek(is)))
swissChili7a6f5eb2021-04-13 16:46:02 -070084 return false;
85
86 int size = 8;
swissChili53472e82021-05-08 16:06:32 -070087 char *s = malloc_aligned(size);
swissChili7a6f5eb2021-04-13 16:46:02 -070088
swissChili53472e82021-05-08 16:06:32 -070089 s[0] = is->get(is);
swissChili7a6f5eb2021-04-13 16:46:02 -070090
swissChili53472e82021-05-08 16:06:32 -070091 for (int i = 1;; i++)
swissChili7a6f5eb2021-04-13 16:46:02 -070092 {
swissChili53472e82021-05-08 16:06:32 -070093 if (issym(is->peek(is)))
swissChili7a6f5eb2021-04-13 16:46:02 -070094 {
swissChili53472e82021-05-08 16:06:32 -070095 if (i >= size)
swissChili7a6f5eb2021-04-13 16:46:02 -070096 {
97 size *= 2;
swissChili53472e82021-05-08 16:06:32 -070098 s = realloc_aligned(s, size);
swissChili7a6f5eb2021-04-13 16:46:02 -070099 }
100
swissChili53472e82021-05-08 16:06:32 -0700101 s[i] = is->get(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700102 }
103 else
104 {
swissChili53472e82021-05-08 16:06:32 -0700105 s[i] = 0;
swissChilib3ca4fb2021-04-20 10:33:00 -0700106 *val = (value_t)s;
swissChili8cfb7c42021-04-18 21:17:58 -0700107 *val |= SYMBOL_TAG;
swissChili7a6f5eb2021-04-13 16:46:02 -0700108
109 return true;
110 }
111 }
112}
113
swissChili53472e82021-05-08 16:06:32 -0700114bool readstr(struct istream *is, value_t *val)
swissChili7a6f5eb2021-04-13 16:46:02 -0700115{
swissChili53472e82021-05-08 16:06:32 -0700116 skipws(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700117
swissChili53472e82021-05-08 16:06:32 -0700118 if (is->peek(is) != '"')
swissChili7a6f5eb2021-04-13 16:46:02 -0700119 return false;
120
121 bool escape = false;
122 int size = 8;
swissChili53472e82021-05-08 16:06:32 -0700123 char *s = malloc_aligned(size);
swissChili7a6f5eb2021-04-13 16:46:02 -0700124
swissChili53472e82021-05-08 16:06:32 -0700125 (void)is->get(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700126
swissChili53472e82021-05-08 16:06:32 -0700127 for (int i = 0;; i++)
swissChili7a6f5eb2021-04-13 16:46:02 -0700128 {
swissChili53472e82021-05-08 16:06:32 -0700129 if (is->peek(is) != '"')
swissChili7a6f5eb2021-04-13 16:46:02 -0700130 {
swissChili53472e82021-05-08 16:06:32 -0700131 if (i >= size)
swissChili7a6f5eb2021-04-13 16:46:02 -0700132 {
swissChilibed80922021-04-13 21:58:05 -0700133 size *= 2;
swissChili53472e82021-05-08 16:06:32 -0700134 s = realloc_aligned(s, size);
swissChili7a6f5eb2021-04-13 16:46:02 -0700135 }
swissChilibed80922021-04-13 21:58:05 -0700136
swissChili53472e82021-05-08 16:06:32 -0700137 char c = is->get(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700138
swissChili53472e82021-05-08 16:06:32 -0700139 if (escape && c == 'n')
swissChili7a6f5eb2021-04-13 16:46:02 -0700140 c = '\n';
swissChili53472e82021-05-08 16:06:32 -0700141 else if (escape && c == '\\')
swissChili7a6f5eb2021-04-13 16:46:02 -0700142 c = '\\';
143
swissChili53472e82021-05-08 16:06:32 -0700144 if (c == '\\' && !escape)
swissChili7a6f5eb2021-04-13 16:46:02 -0700145 {
146 escape = true;
147 i--; // will be incremented again, UGLY.
148 }
149 else
150 {
151 escape = false;
swissChili53472e82021-05-08 16:06:32 -0700152 s[i] = c;
swissChili7a6f5eb2021-04-13 16:46:02 -0700153 }
154 }
155 else
156 {
swissChili53472e82021-05-08 16:06:32 -0700157 is->get(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700158
swissChilib3ca4fb2021-04-20 10:33:00 -0700159 *val = (value_t)s;
swissChili8cfb7c42021-04-18 21:17:58 -0700160 *val |= STRING_TAG;
swissChili7a6f5eb2021-04-13 16:46:02 -0700161
162 return true;
163 }
164 }
165}
166
swissChili53472e82021-05-08 16:06:32 -0700167void printval(value_t v, int depth)
swissChili7a6f5eb2021-04-13 16:46:02 -0700168{
swissChili53472e82021-05-08 16:06:32 -0700169 for (int i = 0; i < depth; i++)
170 printf(" ");
swissChili7a6f5eb2021-04-13 16:46:02 -0700171
swissChili53472e82021-05-08 16:06:32 -0700172 if (symbolp(v))
swissChili7a6f5eb2021-04-13 16:46:02 -0700173 {
swissChili53472e82021-05-08 16:06:32 -0700174 printf("'%s\n", (char *)(v ^ SYMBOL_TAG));
swissChili8cfb7c42021-04-18 21:17:58 -0700175 }
swissChili53472e82021-05-08 16:06:32 -0700176 else if (stringp(v))
swissChili8cfb7c42021-04-18 21:17:58 -0700177 {
swissChili53472e82021-05-08 16:06:32 -0700178 printf("\"%s\"\n", (char *)(v ^ STRING_TAG));
swissChili8cfb7c42021-04-18 21:17:58 -0700179 }
swissChili53472e82021-05-08 16:06:32 -0700180 else if (integerp(v))
swissChili6eee4f92021-04-20 09:34:30 -0700181 {
swissChili53472e82021-05-08 16:06:32 -0700182 printf("%d\n", v >> 2);
swissChili6eee4f92021-04-20 09:34:30 -0700183 }
swissChili53472e82021-05-08 16:06:32 -0700184 else if (consp(v))
swissChili8cfb7c42021-04-18 21:17:58 -0700185 {
swissChili53472e82021-05-08 16:06:32 -0700186 if (listp(v))
swissChilibed80922021-04-13 21:58:05 -0700187 {
swissChili53472e82021-05-08 16:06:32 -0700188 printf("list:\n");
swissChilibed80922021-04-13 21:58:05 -0700189
swissChili53472e82021-05-08 16:06:32 -0700190 for (value_t n = v; !nilp(n); n = cdr(n))
swissChilibed80922021-04-13 21:58:05 -0700191 {
swissChili53472e82021-05-08 16:06:32 -0700192 printval(car(n), depth + 1);
swissChilibed80922021-04-13 21:58:05 -0700193 }
194 }
195 else
196 {
swissChili53472e82021-05-08 16:06:32 -0700197 printf("cons:\n");
198 printval(car(v), depth + 1);
199 printval(cdr(v), depth + 1);
swissChilibed80922021-04-13 21:58:05 -0700200 }
swissChili8cfb7c42021-04-18 21:17:58 -0700201 }
swissChili53472e82021-05-08 16:06:32 -0700202 else if (nilp(v))
swissChili8cfb7c42021-04-18 21:17:58 -0700203 {
swissChili53472e82021-05-08 16:06:32 -0700204 printf("nil\n");
swissChili8cfb7c42021-04-18 21:17:58 -0700205 }
206 else
207 {
swissChili53472e82021-05-08 16:06:32 -0700208 printf("<unknown %d>\n", v);
swissChili7a6f5eb2021-04-13 16:46:02 -0700209 }
210}
211
swissChili53472e82021-05-08 16:06:32 -0700212bool readlist(struct istream *is, value_t *val)
swissChilibed80922021-04-13 21:58:05 -0700213{
swissChili53472e82021-05-08 16:06:32 -0700214 skipws(is);
swissChilibed80922021-04-13 21:58:05 -0700215
swissChili53472e82021-05-08 16:06:32 -0700216 if (is->peek(is) != '(')
swissChilibed80922021-04-13 21:58:05 -0700217 return false;
218
swissChili53472e82021-05-08 16:06:32 -0700219 is->get(is);
swissChilibed80922021-04-13 21:58:05 -0700220
swissChili53472e82021-05-08 16:06:32 -0700221 *val = readn(is);
swissChilibed80922021-04-13 21:58:05 -0700222
swissChili53472e82021-05-08 16:06:32 -0700223 if (is->peek(is) != ')')
swissChilibed80922021-04-13 21:58:05 -0700224 {
swissChili53472e82021-05-08 16:06:32 -0700225 is->showpos(is, stderr);
226 err("Unterminated list");
swissChilibed80922021-04-13 21:58:05 -0700227 return false;
228 }
swissChili53472e82021-05-08 16:06:32 -0700229 is->get(is);
swissChilibed80922021-04-13 21:58:05 -0700230
231 return true;
232}
233
swissChili53472e82021-05-08 16:06:32 -0700234bool readint(struct istream *is, value_t *val)
swissChili6eee4f92021-04-20 09:34:30 -0700235{
236 int number = 0;
237
swissChili53472e82021-05-08 16:06:32 -0700238 if (!isdigit(is->peek(is)))
swissChili6eee4f92021-04-20 09:34:30 -0700239 return false;
240
swissChili53472e82021-05-08 16:06:32 -0700241 while (isdigit(is->peek(is)))
swissChili6eee4f92021-04-20 09:34:30 -0700242 {
243 number *= 10;
swissChili53472e82021-05-08 16:06:32 -0700244 number += is->get(is) - '0';
swissChili6eee4f92021-04-20 09:34:30 -0700245 }
246
swissChili53472e82021-05-08 16:06:32 -0700247 *val = intval(number);
swissChili6eee4f92021-04-20 09:34:30 -0700248 return true;
249}
250
swissChili53472e82021-05-08 16:06:32 -0700251bool read1(struct istream *is, value_t *val)
swissChili7a6f5eb2021-04-13 16:46:02 -0700252{
swissChili53472e82021-05-08 16:06:32 -0700253 if (readsym(is, val))
swissChili7a6f5eb2021-04-13 16:46:02 -0700254 return true;
255
swissChili53472e82021-05-08 16:06:32 -0700256 if (readstr(is, val))
swissChili7a6f5eb2021-04-13 16:46:02 -0700257 return true;
258
swissChili53472e82021-05-08 16:06:32 -0700259 if (readint(is, val))
swissChili6eee4f92021-04-20 09:34:30 -0700260 return true;
261
swissChili53472e82021-05-08 16:06:32 -0700262 if (readlist(is, val))
swissChilibed80922021-04-13 21:58:05 -0700263 return true;
264
swissChili7a6f5eb2021-04-13 16:46:02 -0700265 return false;
266}
267
swissChili53472e82021-05-08 16:06:32 -0700268value_t readn(struct istream *is)
swissChilibed80922021-04-13 21:58:05 -0700269{
swissChili8cfb7c42021-04-18 21:17:58 -0700270 value_t first = nil;
271 value_t *last = &first;
swissChilibed80922021-04-13 21:58:05 -0700272
swissChili8cfb7c42021-04-18 21:17:58 -0700273 value_t read_val;
swissChilibed80922021-04-13 21:58:05 -0700274
swissChili53472e82021-05-08 16:06:32 -0700275 while (read1(is, &read_val))
swissChilibed80922021-04-13 21:58:05 -0700276 {
swissChili53472e82021-05-08 16:06:32 -0700277 *last = cons(read_val, nil);
278 last = cdrref(*last);
swissChilibed80922021-04-13 21:58:05 -0700279 }
280
281 return first;
282}
283
swissChili53472e82021-05-08 16:06:32 -0700284bool startswith(struct istream *s, char *pattern)
swissChili7a6f5eb2021-04-13 16:46:02 -0700285{
swissChili53472e82021-05-08 16:06:32 -0700286 char *check = strdup(pattern);
287 s->read(s, check, strlen(pattern));
swissChili7a6f5eb2021-04-13 16:46:02 -0700288
swissChili53472e82021-05-08 16:06:32 -0700289 bool res = strcmp(check, pattern) == 0;
290 free(check);
swissChili7a6f5eb2021-04-13 16:46:02 -0700291
292 return res;
293}
swissChilibed80922021-04-13 21:58:05 -0700294
swissChili53472e82021-05-08 16:06:32 -0700295value_t strval(char *str)
swissChilibed80922021-04-13 21:58:05 -0700296{
swissChili8cfb7c42021-04-18 21:17:58 -0700297 value_t v;
298
swissChili53472e82021-05-08 16:06:32 -0700299 char *a = malloc_aligned(strlen(str) + 1);
swissChilib3ca4fb2021-04-20 10:33:00 -0700300 v = (value_t)a;
swissChili8cfb7c42021-04-18 21:17:58 -0700301 v |= STRING_TAG;
swissChilibed80922021-04-13 21:58:05 -0700302
303 return v;
304}
305
swissChili53472e82021-05-08 16:06:32 -0700306bool integerp(value_t v)
swissChilibed80922021-04-13 21:58:05 -0700307{
swissChili8cfb7c42021-04-18 21:17:58 -0700308 return (v & INT_MASK) == INT_TAG;
309}
swissChilibed80922021-04-13 21:58:05 -0700310
swissChili53472e82021-05-08 16:06:32 -0700311bool symbolp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700312{
313 return (v & HEAP_MASK) == SYMBOL_TAG;
314}
315
swissChili53472e82021-05-08 16:06:32 -0700316bool stringp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700317{
318 return (v & HEAP_MASK) == STRING_TAG;
319}
320
swissChili53472e82021-05-08 16:06:32 -0700321bool consp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700322{
323 return (v & HEAP_MASK) == CONS_TAG;
324}
325
swissChili9e57da42021-06-15 22:22:46 -0700326bool heapp(value_t v)
327{
328 return consp(v) || stringp(v) || symbolp(v);
329}
330
swissChili53472e82021-05-08 16:06:32 -0700331bool listp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700332{
333 value_t next = v;
334
swissChili53472e82021-05-08 16:06:32 -0700335 while (consp(next))
swissChilibed80922021-04-13 21:58:05 -0700336 {
swissChili53472e82021-05-08 16:06:32 -0700337 next = cdr(next);
swissChilibed80922021-04-13 21:58:05 -0700338 }
339
swissChili53472e82021-05-08 16:06:32 -0700340 return nilp(next);
swissChilibed80922021-04-13 21:58:05 -0700341}
342
swissChili53472e82021-05-08 16:06:32 -0700343value_t car(value_t v)
swissChilibed80922021-04-13 21:58:05 -0700344{
swissChili53472e82021-05-08 16:06:32 -0700345 if (!consp(v))
swissChilibed80922021-04-13 21:58:05 -0700346 return nil;
347
swissChili53472e82021-05-08 16:06:32 -0700348 return *carref(v);
swissChilibed80922021-04-13 21:58:05 -0700349}
350
swissChili53472e82021-05-08 16:06:32 -0700351value_t cdr(value_t v)
swissChilibed80922021-04-13 21:58:05 -0700352{
swissChili53472e82021-05-08 16:06:32 -0700353 if (!consp(v))
swissChilibed80922021-04-13 21:58:05 -0700354 return nil;
355
swissChili53472e82021-05-08 16:06:32 -0700356 return *cdrref(v);
swissChilibed80922021-04-13 21:58:05 -0700357}
358
swissChili53472e82021-05-08 16:06:32 -0700359value_t *carref(value_t v)
swissChilibed80922021-04-13 21:58:05 -0700360{
swissChili53472e82021-05-08 16:06:32 -0700361 if (!consp(v))
swissChili8cfb7c42021-04-18 21:17:58 -0700362 return NULL;
363
swissChilib3ca4fb2021-04-20 10:33:00 -0700364 struct cons *c = (void *)(v ^ CONS_TAG);
swissChili8cfb7c42021-04-18 21:17:58 -0700365 return &c->car;
swissChilibed80922021-04-13 21:58:05 -0700366}
swissChilica107a02021-04-14 12:07:30 -0700367
swissChili53472e82021-05-08 16:06:32 -0700368value_t *cdrref(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700369{
swissChili53472e82021-05-08 16:06:32 -0700370 if (!consp(v))
swissChili8cfb7c42021-04-18 21:17:58 -0700371 return NULL;
372
swissChilib3ca4fb2021-04-20 10:33:00 -0700373 struct cons *c = (void *)(v ^ CONS_TAG);
swissChili8cfb7c42021-04-18 21:17:58 -0700374 return &c->cdr;
375}
376
swissChili53472e82021-05-08 16:06:32 -0700377bool nilp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700378{
379 return v == nil;
380}
381
swissChili53472e82021-05-08 16:06:32 -0700382int length(value_t v)
swissChilica107a02021-04-14 12:07:30 -0700383{
384 int i = 0;
385
swissChili53472e82021-05-08 16:06:32 -0700386 for (; !nilp(v); v = cdr(v))
swissChilica107a02021-04-14 12:07:30 -0700387 i++;
388
389 return i;
390}
swissChilib3ca4fb2021-04-20 10:33:00 -0700391
swissChili53472e82021-05-08 16:06:32 -0700392value_t elt(value_t v, int index)
swissChilib3ca4fb2021-04-20 10:33:00 -0700393{
swissChili53472e82021-05-08 16:06:32 -0700394 for (int i = 0; i < index; i++)
swissChilib3ca4fb2021-04-20 10:33:00 -0700395 {
swissChili53472e82021-05-08 16:06:32 -0700396 v = cdr(v);
swissChilib3ca4fb2021-04-20 10:33:00 -0700397 }
398
swissChili53472e82021-05-08 16:06:32 -0700399 return car(v);
swissChilib3ca4fb2021-04-20 10:33:00 -0700400}
swissChili8fc5e2f2021-04-22 13:45:10 -0700401
swissChili53472e82021-05-08 16:06:32 -0700402bool symstreq(value_t sym, char *str)
swissChili8fc5e2f2021-04-22 13:45:10 -0700403{
swissChili53472e82021-05-08 16:06:32 -0700404 if ((sym & HEAP_MASK) != SYMBOL_TAG)
swissChili8fc5e2f2021-04-22 13:45:10 -0700405 return false;
406
swissChili53472e82021-05-08 16:06:32 -0700407 return strcmp((char *)(sym ^ SYMBOL_TAG), str) == 0;
swissChili8fc5e2f2021-04-22 13:45:10 -0700408}