blob: efb3efe3d1182fcc30175fb84bcb33fb3faca88c [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 }
swissChili6eee4f92021-04-20 09:34:30 -0700180 else if ( integerp (v) )
181 {
182 printf ("%d\n", v >> 2);
183 }
swissChili8cfb7c42021-04-18 21:17:58 -0700184 else if ( consp (v) )
185 {
swissChilibed80922021-04-13 21:58:05 -0700186 if ( listp (v) )
187 {
188 printf ("list:\n");
189
swissChili8cfb7c42021-04-18 21:17:58 -0700190 for ( value_t n = v; !nilp (n); n = cdr (n) )
swissChilibed80922021-04-13 21:58:05 -0700191 {
192 printval (car (n), depth + 1);
193 }
194 }
195 else
196 {
197 printf ("cons:\n");
swissChili8cfb7c42021-04-18 21:17:58 -0700198 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 }
202 else if ( nilp (v) )
203 {
swissChilibed80922021-04-13 21:58:05 -0700204 printf ("nil\n");
swissChili8cfb7c42021-04-18 21:17:58 -0700205 }
206 else
207 {
208 printf ("<unknown %d>\n", v);
swissChili7a6f5eb2021-04-13 16:46:02 -0700209 }
210}
211
swissChili8cfb7c42021-04-18 21:17:58 -0700212bool readlist (struct istream *is, value_t *val)
swissChilibed80922021-04-13 21:58:05 -0700213{
214 skipws (is);
215
216 if ( is->peek (is) != '(' )
217 return false;
218
219 is->get (is);
220
221 *val = readn (is);
222
223 if ( is->peek (is) != ')' )
224 {
225 is->showpos (is, stderr);
226 err ("Unterminated list");
227 return false;
228 }
229 is->get (is);
230
231 return true;
232}
233
swissChili6eee4f92021-04-20 09:34:30 -0700234bool readint (struct istream *is, value_t *val)
235{
236 int number = 0;
237
238 if ( !isdigit (is->peek (is)) )
239 return false;
240
241 while ( isdigit (is->peek (is)) )
242 {
243 number *= 10;
244 number += is->get (is) - '0';
245 }
246
247 *val = intval (number);
248 return true;
249}
250
swissChili8cfb7c42021-04-18 21:17:58 -0700251bool read1 (struct istream *is, value_t *val)
swissChili7a6f5eb2021-04-13 16:46:02 -0700252{
253 if ( readsym (is, val) )
254 return true;
255
256 if ( readstr (is, val) )
257 return true;
258
swissChili6eee4f92021-04-20 09:34:30 -0700259 if ( readint (is, val) )
260 return true;
261
swissChilibed80922021-04-13 21:58:05 -0700262 if ( readlist (is, val) )
263 return true;
264
swissChili7a6f5eb2021-04-13 16:46:02 -0700265 return false;
266}
267
swissChili8cfb7c42021-04-18 21:17:58 -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
275 while ( read1 (is, &read_val) )
276 {
277 *last = cons (read_val, nil);
swissChili8cfb7c42021-04-18 21:17:58 -0700278 last = cdrref (*last);
swissChilibed80922021-04-13 21:58:05 -0700279 }
280
281 return first;
282}
283
swissChili7a6f5eb2021-04-13 16:46:02 -0700284struct stristream_private
285{
286 char *val;
287 int i;
288 int length;
swissChilibed80922021-04-13 21:58:05 -0700289 int line;
290 int fromleft;
291 int linestart;
swissChili7a6f5eb2021-04-13 16:46:02 -0700292};
293
294int stristream_peek (struct istream *is)
295{
296 struct stristream_private *p = is->data;
297
298 if ( p->i < p->length )
299 return p->val[ p->i ];
300 else
301 return -1;
302}
303
304int stristream_get (struct istream *is)
305{
306 struct stristream_private *p = is->data;
307
308 if ( p->i < p->length )
swissChilibed80922021-04-13 21:58:05 -0700309 {
310 char c = p->val[ p->i++ ];
311
312 p->fromleft++;
313
314 if ( c == '\n' )
315 {
316 p->fromleft = 1;
317 p->line++;
318 p->linestart = p->i;
319 }
320
321 return c;
322 }
swissChili7a6f5eb2021-04-13 16:46:02 -0700323 else
324 return -1;
swissChili7a6f5eb2021-04-13 16:46:02 -0700325}
326
327int stristream_read (struct istream *s, char *buffer, int size)
328{
329 struct stristream_private *p = s->data;
330
331 int len = MIN (size, p->length - p->i);
332 memcpy (buffer, p->val, len);
333 return len;
334}
335
swissChilibed80922021-04-13 21:58:05 -0700336void stristream_showpos (struct istream *s, FILE *out)
337{
338 struct stristream_private *p = s->data;
339
340 fprintf (out, "line: %d, char %d\n", p->line, p->fromleft);
341
342 int end = p->length;
343
344 for ( int i = p->linestart; i < p->length; i++ )
345 {
346 if ( p->val[ i ] == '\n' )
347 {
348 end = i;
349 break;
350 }
351 }
352
353 fprintf (out, " | %.*s\n", end - p->linestart, p->val + p->linestart);
354 fprintf (out, " | ");
355 for ( int i = 0; i < p->fromleft - 1; i++ )
356 fprintf (out, " ");
357
358 fprintf (out, "\033[31m^\033[0m\n");
359}
360
swissChili7a6f5eb2021-04-13 16:46:02 -0700361struct istream *new_stristream (char *str, int length)
362{
363 struct istream *is = malloc (sizeof (struct istream));
364 struct stristream_private *p = malloc (sizeof (struct stristream_private));
365
366 p->val = strndup (str, length);
367 p->i = 0;
368 p->length = length;
swissChilibed80922021-04-13 21:58:05 -0700369 p->line = 1;
370 p->fromleft = 1;
371 p->linestart = 0;
swissChili7a6f5eb2021-04-13 16:46:02 -0700372
373 is->data = p;
374 is->get = stristream_get;
375 is->peek = stristream_peek;
376 is->read = stristream_read;
swissChilibed80922021-04-13 21:58:05 -0700377 is->showpos = stristream_showpos;
swissChili7a6f5eb2021-04-13 16:46:02 -0700378
379 return is;
380}
381
swissChilibed80922021-04-13 21:58:05 -0700382void del_stristream (struct istream *stristream)
swissChili7a6f5eb2021-04-13 16:46:02 -0700383{
384 struct stristream_private *p = stristream->data;
385 free (p->val);
386 free (p);
387 free (stristream);
388}
389
390struct istream *new_stristream_nt (char *str)
391{
swissChilibed80922021-04-13 21:58:05 -0700392 return new_stristream (str, strlen (str));
swissChili7a6f5eb2021-04-13 16:46:02 -0700393}
394
swissChilibed80922021-04-13 21:58:05 -0700395bool startswith (struct istream *s, char *pattern)
swissChili7a6f5eb2021-04-13 16:46:02 -0700396{
swissChilibed80922021-04-13 21:58:05 -0700397 char *check = strdup (pattern);
swissChili7a6f5eb2021-04-13 16:46:02 -0700398 s->read (s, check, strlen (pattern));
399
400 bool res = strcmp (check, pattern) == 0;
401 free (check);
402
403 return res;
404}
swissChilibed80922021-04-13 21:58:05 -0700405
swissChili8cfb7c42021-04-18 21:17:58 -0700406value_t strval (char *str)
swissChilibed80922021-04-13 21:58:05 -0700407{
swissChili8cfb7c42021-04-18 21:17:58 -0700408 value_t v;
409
410 char *a = malloc_aligned (strlen (str) + 1);
411 v = (value_t) a;
412 v |= STRING_TAG;
swissChilibed80922021-04-13 21:58:05 -0700413
414 return v;
415}
416
swissChili8cfb7c42021-04-18 21:17:58 -0700417bool integerp (value_t v)
swissChilibed80922021-04-13 21:58:05 -0700418{
swissChili8cfb7c42021-04-18 21:17:58 -0700419 return (v & INT_MASK) == INT_TAG;
420}
swissChilibed80922021-04-13 21:58:05 -0700421
swissChili8cfb7c42021-04-18 21:17:58 -0700422bool symbolp (value_t v)
423{
424 return (v & HEAP_MASK) == SYMBOL_TAG;
425}
426
427bool stringp (value_t v)
428{
429 return (v & HEAP_MASK) == STRING_TAG;
430}
431
432bool consp (value_t v)
433{
434 return (v & HEAP_MASK) == CONS_TAG;
435}
436
437bool listp (value_t v)
438{
439 value_t next = v;
440
441 while ( consp (next) )
swissChilibed80922021-04-13 21:58:05 -0700442 {
swissChili8cfb7c42021-04-18 21:17:58 -0700443 next = cdr (next);
swissChilibed80922021-04-13 21:58:05 -0700444 }
445
swissChili8cfb7c42021-04-18 21:17:58 -0700446 return nilp (next);
swissChilibed80922021-04-13 21:58:05 -0700447}
448
swissChili8cfb7c42021-04-18 21:17:58 -0700449value_t car (value_t v)
swissChilibed80922021-04-13 21:58:05 -0700450{
swissChili8cfb7c42021-04-18 21:17:58 -0700451 if ( !consp (v) )
swissChilibed80922021-04-13 21:58:05 -0700452 return nil;
453
swissChili8cfb7c42021-04-18 21:17:58 -0700454 return *carref (v);
swissChilibed80922021-04-13 21:58:05 -0700455}
456
swissChili8cfb7c42021-04-18 21:17:58 -0700457value_t cdr (value_t v)
swissChilibed80922021-04-13 21:58:05 -0700458{
swissChili8cfb7c42021-04-18 21:17:58 -0700459 if ( !consp (v) )
swissChilibed80922021-04-13 21:58:05 -0700460 return nil;
461
swissChili8cfb7c42021-04-18 21:17:58 -0700462 return *cdrref (v);
swissChilibed80922021-04-13 21:58:05 -0700463}
464
swissChili8cfb7c42021-04-18 21:17:58 -0700465value_t *carref (value_t v)
swissChilibed80922021-04-13 21:58:05 -0700466{
swissChili8cfb7c42021-04-18 21:17:58 -0700467 if ( !consp (v) )
468 return NULL;
469
470 struct cons *c = (void *) (v ^ CONS_TAG);
471 return &c->car;
swissChilibed80922021-04-13 21:58:05 -0700472}
swissChilica107a02021-04-14 12:07:30 -0700473
swissChili8cfb7c42021-04-18 21:17:58 -0700474value_t *cdrref (value_t v)
475{
476 if ( !consp (v) )
477 return NULL;
478
479 struct cons *c = (void *) (v ^ CONS_TAG);
480 return &c->cdr;
481}
482
483bool nilp (value_t v)
484{
485 return v == nil;
486}
487
488int length (value_t v)
swissChilica107a02021-04-14 12:07:30 -0700489{
490 int i = 0;
491
492 FOREACH (item, v)
swissChili8cfb7c42021-04-18 21:17:58 -0700493 {
494 (void) item;
swissChilica107a02021-04-14 12:07:30 -0700495 i++;
swissChili8cfb7c42021-04-18 21:17:58 -0700496 }
swissChilica107a02021-04-14 12:07:30 -0700497
498 return i;
499}