blob: d1ae05944d5fde5124e72d38a8b91a23e7320a96 [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
swissChilibed80922021-04-13 21:58:05 -070010#define MIN(a, b) (a) > (b) ? (b) : (a)
swissChili7a6f5eb2021-04-13 16:46:02 -070011
12struct alloc_list *first_a = NULL, *last_a = NULL;
13
swissChili8cfb7c42021-04-18 21:17:58 -070014value_t nil = 0b00101111; // magic ;)
swissChilibed80922021-04-13 21:58:05 -070015
16void err (const char *msg)
17{
18 fprintf (stderr, "ERROR: %s\n", msg);
19}
20
swissChili8cfb7c42021-04-18 21:17:58 -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
28value_t cons (value_t car, value_t cdr)
29{
30 struct cons *c = malloc_aligned (sizeof (struct cons));
swissChili7a6f5eb2021-04-13 16:46:02 -070031
swissChilibed80922021-04-13 21:58:05 -070032 c->car = car;
33 c->cdr = cdr;
34
swissChili7a6f5eb2021-04-13 16:46:02 -070035 struct alloc_list *item = malloc (sizeof (struct alloc_list));
36 item->type = T_CONS;
swissChili8cfb7c42021-04-18 21:17:58 -070037 item->cons_val = c;
swissChili7a6f5eb2021-04-13 16:46:02 -070038
39 if ( last_a )
40 {
41 item->prev = last_a;
42 last_a->next = item;
43 item->next = NULL;
44 }
45 else
46 {
47 item->prev = item->next = NULL;
48 first_a = last_a = item;
49 }
50
swissChili8cfb7c42021-04-18 21:17:58 -070051 value_t v = (value_t) c;
52 v |= CONS_TAG;
swissChili7a6f5eb2021-04-13 16:46:02 -070053
54 return v;
55}
56
57void skipws (struct istream *is)
58{
59 while ( isspace (is->peek (is)) )
60 is->get (is);
61}
62
63bool isallowedchar (char c)
64{
swissChilibed80922021-04-13 21:58:05 -070065 return (c >= '#' && c <= '\'') || (c >= '*' && c <= '/') ||
66 (c >= '>' && c <= '@');
swissChili7a6f5eb2021-04-13 16:46:02 -070067}
68
69bool issymstart (char c)
70{
71 return isalpha (c) || isallowedchar (c);
72}
73
74bool issym (char c)
75{
76 return isalpha (c) || isallowedchar (c) || isdigit (c);
77}
78
swissChili8cfb7c42021-04-18 21:17:58 -070079bool readsym (struct istream *is, value_t *val)
swissChili7a6f5eb2021-04-13 16:46:02 -070080{
81 skipws (is);
82
83 if ( !issymstart (is->peek (is)) )
84 return false;
85
86 int size = 8;
swissChili8cfb7c42021-04-18 21:17:58 -070087 char *s = malloc_aligned (size);
swissChili7a6f5eb2021-04-13 16:46:02 -070088
swissChilibed80922021-04-13 21:58:05 -070089 s[ 0 ] = is->get (is);
swissChili7a6f5eb2021-04-13 16:46:02 -070090
swissChilibed80922021-04-13 21:58:05 -070091 for ( int i = 1;; i++ )
swissChili7a6f5eb2021-04-13 16:46:02 -070092 {
93 if ( issym (is->peek (is)) )
94 {
95 if ( i >= size )
96 {
97 size *= 2;
swissChili8cfb7c42021-04-18 21:17:58 -070098 s = realloc_aligned (s, size);
swissChili7a6f5eb2021-04-13 16:46:02 -070099 }
100
swissChilibed80922021-04-13 21:58:05 -0700101 s[ i ] = is->get (is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700102 }
103 else
104 {
swissChilibed80922021-04-13 21:58:05 -0700105 s[ i ] = 0;
swissChili8cfb7c42021-04-18 21:17:58 -0700106 *val = (value_t) s;
107 *val |= SYMBOL_TAG;
swissChili7a6f5eb2021-04-13 16:46:02 -0700108
109 return true;
110 }
111 }
112}
113
swissChili8cfb7c42021-04-18 21:17:58 -0700114bool readstr (struct istream *is, value_t *val)
swissChili7a6f5eb2021-04-13 16:46:02 -0700115{
116 skipws (is);
117
118 if ( is->peek (is) != '"' )
119 return false;
120
121 bool escape = false;
122 int size = 8;
swissChili8cfb7c42021-04-18 21:17:58 -0700123 char *s = malloc_aligned (size);
swissChili7a6f5eb2021-04-13 16:46:02 -0700124
swissChilibed80922021-04-13 21:58:05 -0700125 (void)is->get (is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700126
swissChilibed80922021-04-13 21:58:05 -0700127 for ( int i = 0;; i++ )
swissChili7a6f5eb2021-04-13 16:46:02 -0700128 {
129 if ( is->peek (is) != '"' )
130 {
131 if ( i >= size )
132 {
swissChilibed80922021-04-13 21:58:05 -0700133 size *= 2;
swissChili8cfb7c42021-04-18 21:17:58 -0700134 s = realloc_aligned (s, size);
swissChili7a6f5eb2021-04-13 16:46:02 -0700135 }
swissChilibed80922021-04-13 21:58:05 -0700136
swissChili7a6f5eb2021-04-13 16:46:02 -0700137 char c = is->get (is);
138
139 if ( escape && c == 'n' )
140 c = '\n';
141 else if ( escape && c == '\\' )
142 c = '\\';
143
144 if ( c == '\\' && !escape )
145 {
146 escape = true;
147 i--; // will be incremented again, UGLY.
148 }
149 else
150 {
151 escape = false;
swissChilibed80922021-04-13 21:58:05 -0700152 s[ i ] = c;
swissChili7a6f5eb2021-04-13 16:46:02 -0700153 }
154 }
155 else
156 {
157 is->get (is);
158
swissChili8cfb7c42021-04-18 21:17:58 -0700159 *val = (value_t) s;
160 *val |= STRING_TAG;
swissChili7a6f5eb2021-04-13 16:46:02 -0700161
162 return true;
163 }
164 }
165}
166
swissChili8cfb7c42021-04-18 21:17:58 -0700167void printval (value_t v, int depth)
swissChili7a6f5eb2021-04-13 16:46:02 -0700168{
169 for ( int i = 0; i < depth; i++ )
swissChilibed80922021-04-13 21:58:05 -0700170 printf (" ");
swissChili7a6f5eb2021-04-13 16:46:02 -0700171
swissChili8cfb7c42021-04-18 21:17:58 -0700172 if ( symbolp (v) )
swissChili7a6f5eb2021-04-13 16:46:02 -0700173 {
swissChili8cfb7c42021-04-18 21:17:58 -0700174 printf ("'%s\n", (char *) (v ^ SYMBOL_TAG));
175 }
176 else if ( stringp (v) )
177 {
178 printf ("\"%s\"\n", (char *) (v ^ STRING_TAG));
179 }
180 else if ( consp (v) )
181 {
swissChilibed80922021-04-13 21:58:05 -0700182 if ( listp (v) )
183 {
184 printf ("list:\n");
185
swissChili8cfb7c42021-04-18 21:17:58 -0700186 for ( value_t n = v; !nilp (n); n = cdr (n) )
swissChilibed80922021-04-13 21:58:05 -0700187 {
188 printval (car (n), depth + 1);
189 }
190 }
191 else
192 {
193 printf ("cons:\n");
swissChili8cfb7c42021-04-18 21:17:58 -0700194 printval (car (v), depth + 1);
195 printval (cdr (v), depth + 1);
swissChilibed80922021-04-13 21:58:05 -0700196 }
swissChili8cfb7c42021-04-18 21:17:58 -0700197 }
198 else if ( nilp (v) )
199 {
swissChilibed80922021-04-13 21:58:05 -0700200 printf ("nil\n");
swissChili8cfb7c42021-04-18 21:17:58 -0700201 }
202 else
203 {
204 printf ("<unknown %d>\n", v);
swissChili7a6f5eb2021-04-13 16:46:02 -0700205 }
206}
207
swissChili8cfb7c42021-04-18 21:17:58 -0700208bool readlist (struct istream *is, value_t *val)
swissChilibed80922021-04-13 21:58:05 -0700209{
210 skipws (is);
211
212 if ( is->peek (is) != '(' )
213 return false;
214
215 is->get (is);
216
217 *val = readn (is);
218
219 if ( is->peek (is) != ')' )
220 {
221 is->showpos (is, stderr);
222 err ("Unterminated list");
223 return false;
224 }
225 is->get (is);
226
227 return true;
228}
229
swissChili8cfb7c42021-04-18 21:17:58 -0700230bool read1 (struct istream *is, value_t *val)
swissChili7a6f5eb2021-04-13 16:46:02 -0700231{
232 if ( readsym (is, val) )
233 return true;
234
235 if ( readstr (is, val) )
236 return true;
237
swissChilibed80922021-04-13 21:58:05 -0700238 if ( readlist (is, val) )
239 return true;
240
swissChili7a6f5eb2021-04-13 16:46:02 -0700241 return false;
242}
243
swissChili8cfb7c42021-04-18 21:17:58 -0700244value_t readn (struct istream *is)
swissChilibed80922021-04-13 21:58:05 -0700245{
swissChili8cfb7c42021-04-18 21:17:58 -0700246 value_t first = nil;
247 value_t *last = &first;
swissChilibed80922021-04-13 21:58:05 -0700248
swissChili8cfb7c42021-04-18 21:17:58 -0700249 value_t read_val;
swissChilibed80922021-04-13 21:58:05 -0700250
251 while ( read1 (is, &read_val) )
252 {
253 *last = cons (read_val, nil);
swissChili8cfb7c42021-04-18 21:17:58 -0700254 last = cdrref (*last);
swissChilibed80922021-04-13 21:58:05 -0700255 }
256
257 return first;
258}
259
swissChili7a6f5eb2021-04-13 16:46:02 -0700260struct stristream_private
261{
262 char *val;
263 int i;
264 int length;
swissChilibed80922021-04-13 21:58:05 -0700265 int line;
266 int fromleft;
267 int linestart;
swissChili7a6f5eb2021-04-13 16:46:02 -0700268};
269
270int stristream_peek (struct istream *is)
271{
272 struct stristream_private *p = is->data;
273
274 if ( p->i < p->length )
275 return p->val[ p->i ];
276 else
277 return -1;
278}
279
280int stristream_get (struct istream *is)
281{
282 struct stristream_private *p = is->data;
283
284 if ( p->i < p->length )
swissChilibed80922021-04-13 21:58:05 -0700285 {
286 char c = p->val[ p->i++ ];
287
288 p->fromleft++;
289
290 if ( c == '\n' )
291 {
292 p->fromleft = 1;
293 p->line++;
294 p->linestart = p->i;
295 }
296
297 return c;
298 }
swissChili7a6f5eb2021-04-13 16:46:02 -0700299 else
300 return -1;
swissChili7a6f5eb2021-04-13 16:46:02 -0700301}
302
303int stristream_read (struct istream *s, char *buffer, int size)
304{
305 struct stristream_private *p = s->data;
306
307 int len = MIN (size, p->length - p->i);
308 memcpy (buffer, p->val, len);
309 return len;
310}
311
swissChilibed80922021-04-13 21:58:05 -0700312void stristream_showpos (struct istream *s, FILE *out)
313{
314 struct stristream_private *p = s->data;
315
316 fprintf (out, "line: %d, char %d\n", p->line, p->fromleft);
317
318 int end = p->length;
319
320 for ( int i = p->linestart; i < p->length; i++ )
321 {
322 if ( p->val[ i ] == '\n' )
323 {
324 end = i;
325 break;
326 }
327 }
328
329 fprintf (out, " | %.*s\n", end - p->linestart, p->val + p->linestart);
330 fprintf (out, " | ");
331 for ( int i = 0; i < p->fromleft - 1; i++ )
332 fprintf (out, " ");
333
334 fprintf (out, "\033[31m^\033[0m\n");
335}
336
swissChili7a6f5eb2021-04-13 16:46:02 -0700337struct istream *new_stristream (char *str, int length)
338{
339 struct istream *is = malloc (sizeof (struct istream));
340 struct stristream_private *p = malloc (sizeof (struct stristream_private));
341
342 p->val = strndup (str, length);
343 p->i = 0;
344 p->length = length;
swissChilibed80922021-04-13 21:58:05 -0700345 p->line = 1;
346 p->fromleft = 1;
347 p->linestart = 0;
swissChili7a6f5eb2021-04-13 16:46:02 -0700348
349 is->data = p;
350 is->get = stristream_get;
351 is->peek = stristream_peek;
352 is->read = stristream_read;
swissChilibed80922021-04-13 21:58:05 -0700353 is->showpos = stristream_showpos;
swissChili7a6f5eb2021-04-13 16:46:02 -0700354
355 return is;
356}
357
swissChilibed80922021-04-13 21:58:05 -0700358void del_stristream (struct istream *stristream)
swissChili7a6f5eb2021-04-13 16:46:02 -0700359{
360 struct stristream_private *p = stristream->data;
361 free (p->val);
362 free (p);
363 free (stristream);
364}
365
366struct istream *new_stristream_nt (char *str)
367{
swissChilibed80922021-04-13 21:58:05 -0700368 return new_stristream (str, strlen (str));
swissChili7a6f5eb2021-04-13 16:46:02 -0700369}
370
swissChilibed80922021-04-13 21:58:05 -0700371bool startswith (struct istream *s, char *pattern)
swissChili7a6f5eb2021-04-13 16:46:02 -0700372{
swissChilibed80922021-04-13 21:58:05 -0700373 char *check = strdup (pattern);
swissChili7a6f5eb2021-04-13 16:46:02 -0700374 s->read (s, check, strlen (pattern));
375
376 bool res = strcmp (check, pattern) == 0;
377 free (check);
378
379 return res;
380}
swissChilibed80922021-04-13 21:58:05 -0700381
swissChili8cfb7c42021-04-18 21:17:58 -0700382value_t strval (char *str)
swissChilibed80922021-04-13 21:58:05 -0700383{
swissChili8cfb7c42021-04-18 21:17:58 -0700384 value_t v;
385
386 char *a = malloc_aligned (strlen (str) + 1);
387 v = (value_t) a;
388 v |= STRING_TAG;
swissChilibed80922021-04-13 21:58:05 -0700389
390 return v;
391}
392
swissChili8cfb7c42021-04-18 21:17:58 -0700393bool integerp (value_t v)
swissChilibed80922021-04-13 21:58:05 -0700394{
swissChili8cfb7c42021-04-18 21:17:58 -0700395 return (v & INT_MASK) == INT_TAG;
396}
swissChilibed80922021-04-13 21:58:05 -0700397
swissChili8cfb7c42021-04-18 21:17:58 -0700398bool symbolp (value_t v)
399{
400 return (v & HEAP_MASK) == SYMBOL_TAG;
401}
402
403bool stringp (value_t v)
404{
405 return (v & HEAP_MASK) == STRING_TAG;
406}
407
408bool consp (value_t v)
409{
410 return (v & HEAP_MASK) == CONS_TAG;
411}
412
413bool listp (value_t v)
414{
415 value_t next = v;
416
417 while ( consp (next) )
swissChilibed80922021-04-13 21:58:05 -0700418 {
swissChili8cfb7c42021-04-18 21:17:58 -0700419 next = cdr (next);
swissChilibed80922021-04-13 21:58:05 -0700420 }
421
swissChili8cfb7c42021-04-18 21:17:58 -0700422 return nilp (next);
swissChilibed80922021-04-13 21:58:05 -0700423}
424
swissChili8cfb7c42021-04-18 21:17:58 -0700425value_t car (value_t v)
swissChilibed80922021-04-13 21:58:05 -0700426{
swissChili8cfb7c42021-04-18 21:17:58 -0700427 if ( !consp (v) )
swissChilibed80922021-04-13 21:58:05 -0700428 return nil;
429
swissChili8cfb7c42021-04-18 21:17:58 -0700430 return *carref (v);
swissChilibed80922021-04-13 21:58:05 -0700431}
432
swissChili8cfb7c42021-04-18 21:17:58 -0700433value_t cdr (value_t v)
swissChilibed80922021-04-13 21:58:05 -0700434{
swissChili8cfb7c42021-04-18 21:17:58 -0700435 if ( !consp (v) )
swissChilibed80922021-04-13 21:58:05 -0700436 return nil;
437
swissChili8cfb7c42021-04-18 21:17:58 -0700438 return *cdrref (v);
swissChilibed80922021-04-13 21:58:05 -0700439}
440
swissChili8cfb7c42021-04-18 21:17:58 -0700441value_t *carref (value_t v)
swissChilibed80922021-04-13 21:58:05 -0700442{
swissChili8cfb7c42021-04-18 21:17:58 -0700443 if ( !consp (v) )
444 return NULL;
445
446 struct cons *c = (void *) (v ^ CONS_TAG);
447 return &c->car;
swissChilibed80922021-04-13 21:58:05 -0700448}
swissChilica107a02021-04-14 12:07:30 -0700449
swissChili8cfb7c42021-04-18 21:17:58 -0700450value_t *cdrref (value_t v)
451{
452 if ( !consp (v) )
453 return NULL;
454
455 struct cons *c = (void *) (v ^ CONS_TAG);
456 return &c->cdr;
457}
458
459bool nilp (value_t v)
460{
461 return v == nil;
462}
463
464int length (value_t v)
swissChilica107a02021-04-14 12:07:30 -0700465{
466 int i = 0;
467
468 FOREACH (item, v)
swissChili8cfb7c42021-04-18 21:17:58 -0700469 {
470 (void) item;
swissChilica107a02021-04-14 12:07:30 -0700471 i++;
swissChili8cfb7c42021-04-18 21:17:58 -0700472 }
swissChilica107a02021-04-14 12:07:30 -0700473
474 return i;
475}