blob: 7a7d6cbe03986677f0cbbc8e4dd8945fb802892d [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
swissChili53472e82021-05-08 16:06:32 -070016void err(const char *msg)
swissChilibed80922021-04-13 21:58:05 -070017{
swissChili53472e82021-05-08 16:06:32 -070018 fprintf(stderr, "ERROR: %s\n", msg);
19 exit(1);
swissChilibed80922021-04-13 21:58:05 -070020}
21
swissChili53472e82021-05-08 16:06:32 -070022value_t intval(int i)
swissChili7a6f5eb2021-04-13 16:46:02 -070023{
swissChili8cfb7c42021-04-18 21:17:58 -070024 i <<= 2;
25 i |= INT_TAG;
26 return i;
27}
28
swissChili53472e82021-05-08 16:06:32 -070029value_t cons(value_t car, value_t cdr)
swissChili8cfb7c42021-04-18 21:17:58 -070030{
swissChili53472e82021-05-08 16:06:32 -070031 struct cons *c = malloc_aligned(sizeof(struct cons));
swissChili7a6f5eb2021-04-13 16:46:02 -070032
swissChilibed80922021-04-13 21:58:05 -070033 c->car = car;
34 c->cdr = cdr;
35
swissChili53472e82021-05-08 16:06:32 -070036 struct alloc_list *item = malloc(sizeof(struct alloc_list));
swissChili7a6f5eb2021-04-13 16:46:02 -070037 item->type = T_CONS;
swissChili8cfb7c42021-04-18 21:17:58 -070038 item->cons_val = c;
swissChili7a6f5eb2021-04-13 16:46:02 -070039
swissChili53472e82021-05-08 16:06:32 -070040 if (last_a)
swissChili7a6f5eb2021-04-13 16:46:02 -070041 {
42 item->prev = last_a;
43 last_a->next = item;
44 item->next = NULL;
45 }
46 else
47 {
48 item->prev = item->next = NULL;
49 first_a = last_a = item;
50 }
51
swissChilib3ca4fb2021-04-20 10:33:00 -070052 value_t v = (value_t)c;
swissChili8cfb7c42021-04-18 21:17:58 -070053 v |= CONS_TAG;
swissChili7a6f5eb2021-04-13 16:46:02 -070054
55 return v;
56}
57
swissChili53472e82021-05-08 16:06:32 -070058void skipws(struct istream *is)
swissChili7a6f5eb2021-04-13 16:46:02 -070059{
swissChili53472e82021-05-08 16:06:32 -070060 while (isspace(is->peek(is)))
61 is->get(is);
swissChili7a6f5eb2021-04-13 16:46:02 -070062}
63
swissChili53472e82021-05-08 16:06:32 -070064bool isallowedchar(char c)
swissChili7a6f5eb2021-04-13 16:46:02 -070065{
swissChilibed80922021-04-13 21:58:05 -070066 return (c >= '#' && c <= '\'') || (c >= '*' && c <= '/') ||
67 (c >= '>' && c <= '@');
swissChili7a6f5eb2021-04-13 16:46:02 -070068}
69
swissChili53472e82021-05-08 16:06:32 -070070bool issymstart(char c)
swissChili7a6f5eb2021-04-13 16:46:02 -070071{
swissChili53472e82021-05-08 16:06:32 -070072 return isalpha(c) || isallowedchar(c);
swissChili7a6f5eb2021-04-13 16:46:02 -070073}
74
swissChili53472e82021-05-08 16:06:32 -070075bool issym(char c)
swissChili7a6f5eb2021-04-13 16:46:02 -070076{
swissChili53472e82021-05-08 16:06:32 -070077 return isalpha(c) || isallowedchar(c) || isdigit(c);
swissChili7a6f5eb2021-04-13 16:46:02 -070078}
79
swissChili53472e82021-05-08 16:06:32 -070080bool readsym(struct istream *is, value_t *val)
swissChili7a6f5eb2021-04-13 16:46:02 -070081{
swissChili53472e82021-05-08 16:06:32 -070082 skipws(is);
swissChili7a6f5eb2021-04-13 16:46:02 -070083
swissChili53472e82021-05-08 16:06:32 -070084 if (!issymstart(is->peek(is)))
swissChili7a6f5eb2021-04-13 16:46:02 -070085 return false;
86
87 int size = 8;
swissChili53472e82021-05-08 16:06:32 -070088 char *s = malloc_aligned(size);
swissChili7a6f5eb2021-04-13 16:46:02 -070089
swissChili53472e82021-05-08 16:06:32 -070090 s[0] = is->get(is);
swissChili7a6f5eb2021-04-13 16:46:02 -070091
swissChili53472e82021-05-08 16:06:32 -070092 for (int i = 1;; i++)
swissChili7a6f5eb2021-04-13 16:46:02 -070093 {
swissChili53472e82021-05-08 16:06:32 -070094 if (issym(is->peek(is)))
swissChili7a6f5eb2021-04-13 16:46:02 -070095 {
swissChili53472e82021-05-08 16:06:32 -070096 if (i >= size)
swissChili7a6f5eb2021-04-13 16:46:02 -070097 {
98 size *= 2;
swissChili53472e82021-05-08 16:06:32 -070099 s = realloc_aligned(s, size);
swissChili7a6f5eb2021-04-13 16:46:02 -0700100 }
101
swissChili53472e82021-05-08 16:06:32 -0700102 s[i] = is->get(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700103 }
104 else
105 {
swissChili53472e82021-05-08 16:06:32 -0700106 s[i] = 0;
swissChilib3ca4fb2021-04-20 10:33:00 -0700107 *val = (value_t)s;
swissChili8cfb7c42021-04-18 21:17:58 -0700108 *val |= SYMBOL_TAG;
swissChili7a6f5eb2021-04-13 16:46:02 -0700109
110 return true;
111 }
112 }
113}
114
swissChili53472e82021-05-08 16:06:32 -0700115bool readstr(struct istream *is, value_t *val)
swissChili7a6f5eb2021-04-13 16:46:02 -0700116{
swissChili53472e82021-05-08 16:06:32 -0700117 skipws(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700118
swissChili53472e82021-05-08 16:06:32 -0700119 if (is->peek(is) != '"')
swissChili7a6f5eb2021-04-13 16:46:02 -0700120 return false;
121
122 bool escape = false;
123 int size = 8;
swissChili53472e82021-05-08 16:06:32 -0700124 char *s = malloc_aligned(size);
swissChili7a6f5eb2021-04-13 16:46:02 -0700125
swissChili53472e82021-05-08 16:06:32 -0700126 (void)is->get(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700127
swissChili53472e82021-05-08 16:06:32 -0700128 for (int i = 0;; i++)
swissChili7a6f5eb2021-04-13 16:46:02 -0700129 {
swissChili53472e82021-05-08 16:06:32 -0700130 if (is->peek(is) != '"')
swissChili7a6f5eb2021-04-13 16:46:02 -0700131 {
swissChili53472e82021-05-08 16:06:32 -0700132 if (i >= size)
swissChili7a6f5eb2021-04-13 16:46:02 -0700133 {
swissChilibed80922021-04-13 21:58:05 -0700134 size *= 2;
swissChili53472e82021-05-08 16:06:32 -0700135 s = realloc_aligned(s, size);
swissChili7a6f5eb2021-04-13 16:46:02 -0700136 }
swissChilibed80922021-04-13 21:58:05 -0700137
swissChili53472e82021-05-08 16:06:32 -0700138 char c = is->get(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700139
swissChili53472e82021-05-08 16:06:32 -0700140 if (escape && c == 'n')
swissChili7a6f5eb2021-04-13 16:46:02 -0700141 c = '\n';
swissChili53472e82021-05-08 16:06:32 -0700142 else if (escape && c == '\\')
swissChili7a6f5eb2021-04-13 16:46:02 -0700143 c = '\\';
144
swissChili53472e82021-05-08 16:06:32 -0700145 if (c == '\\' && !escape)
swissChili7a6f5eb2021-04-13 16:46:02 -0700146 {
147 escape = true;
148 i--; // will be incremented again, UGLY.
149 }
150 else
151 {
152 escape = false;
swissChili53472e82021-05-08 16:06:32 -0700153 s[i] = c;
swissChili7a6f5eb2021-04-13 16:46:02 -0700154 }
155 }
156 else
157 {
swissChili53472e82021-05-08 16:06:32 -0700158 is->get(is);
swissChili7a6f5eb2021-04-13 16:46:02 -0700159
swissChilib3ca4fb2021-04-20 10:33:00 -0700160 *val = (value_t)s;
swissChili8cfb7c42021-04-18 21:17:58 -0700161 *val |= STRING_TAG;
swissChili7a6f5eb2021-04-13 16:46:02 -0700162
163 return true;
164 }
165 }
166}
167
swissChili53472e82021-05-08 16:06:32 -0700168void printval(value_t v, int depth)
swissChili7a6f5eb2021-04-13 16:46:02 -0700169{
swissChili53472e82021-05-08 16:06:32 -0700170 for (int i = 0; i < depth; i++)
171 printf(" ");
swissChili7a6f5eb2021-04-13 16:46:02 -0700172
swissChili53472e82021-05-08 16:06:32 -0700173 if (symbolp(v))
swissChili7a6f5eb2021-04-13 16:46:02 -0700174 {
swissChili53472e82021-05-08 16:06:32 -0700175 printf("'%s\n", (char *)(v ^ SYMBOL_TAG));
swissChili8cfb7c42021-04-18 21:17:58 -0700176 }
swissChili53472e82021-05-08 16:06:32 -0700177 else if (stringp(v))
swissChili8cfb7c42021-04-18 21:17:58 -0700178 {
swissChili53472e82021-05-08 16:06:32 -0700179 printf("\"%s\"\n", (char *)(v ^ STRING_TAG));
swissChili8cfb7c42021-04-18 21:17:58 -0700180 }
swissChili53472e82021-05-08 16:06:32 -0700181 else if (integerp(v))
swissChili6eee4f92021-04-20 09:34:30 -0700182 {
swissChili53472e82021-05-08 16:06:32 -0700183 printf("%d\n", v >> 2);
swissChili6eee4f92021-04-20 09:34:30 -0700184 }
swissChili53472e82021-05-08 16:06:32 -0700185 else if (consp(v))
swissChili8cfb7c42021-04-18 21:17:58 -0700186 {
swissChili53472e82021-05-08 16:06:32 -0700187 if (listp(v))
swissChilibed80922021-04-13 21:58:05 -0700188 {
swissChili53472e82021-05-08 16:06:32 -0700189 printf("list:\n");
swissChilibed80922021-04-13 21:58:05 -0700190
swissChili53472e82021-05-08 16:06:32 -0700191 for (value_t n = v; !nilp(n); n = cdr(n))
swissChilibed80922021-04-13 21:58:05 -0700192 {
swissChili53472e82021-05-08 16:06:32 -0700193 printval(car(n), depth + 1);
swissChilibed80922021-04-13 21:58:05 -0700194 }
195 }
196 else
197 {
swissChili53472e82021-05-08 16:06:32 -0700198 printf("cons:\n");
199 printval(car(v), depth + 1);
200 printval(cdr(v), depth + 1);
swissChilibed80922021-04-13 21:58:05 -0700201 }
swissChili8cfb7c42021-04-18 21:17:58 -0700202 }
swissChili53472e82021-05-08 16:06:32 -0700203 else if (nilp(v))
swissChili8cfb7c42021-04-18 21:17:58 -0700204 {
swissChili53472e82021-05-08 16:06:32 -0700205 printf("nil\n");
swissChili8cfb7c42021-04-18 21:17:58 -0700206 }
207 else
208 {
swissChili53472e82021-05-08 16:06:32 -0700209 printf("<unknown %d>\n", v);
swissChili7a6f5eb2021-04-13 16:46:02 -0700210 }
211}
212
swissChili53472e82021-05-08 16:06:32 -0700213bool readlist(struct istream *is, value_t *val)
swissChilibed80922021-04-13 21:58:05 -0700214{
swissChili53472e82021-05-08 16:06:32 -0700215 skipws(is);
swissChilibed80922021-04-13 21:58:05 -0700216
swissChili53472e82021-05-08 16:06:32 -0700217 if (is->peek(is) != '(')
swissChilibed80922021-04-13 21:58:05 -0700218 return false;
219
swissChili53472e82021-05-08 16:06:32 -0700220 is->get(is);
swissChilibed80922021-04-13 21:58:05 -0700221
swissChili53472e82021-05-08 16:06:32 -0700222 *val = readn(is);
swissChilibed80922021-04-13 21:58:05 -0700223
swissChili53472e82021-05-08 16:06:32 -0700224 if (is->peek(is) != ')')
swissChilibed80922021-04-13 21:58:05 -0700225 {
swissChili53472e82021-05-08 16:06:32 -0700226 is->showpos(is, stderr);
227 err("Unterminated list");
swissChilibed80922021-04-13 21:58:05 -0700228 return false;
229 }
swissChili53472e82021-05-08 16:06:32 -0700230 is->get(is);
swissChilibed80922021-04-13 21:58:05 -0700231
232 return true;
233}
234
swissChili53472e82021-05-08 16:06:32 -0700235bool readint(struct istream *is, value_t *val)
swissChili6eee4f92021-04-20 09:34:30 -0700236{
237 int number = 0;
238
swissChili53472e82021-05-08 16:06:32 -0700239 if (!isdigit(is->peek(is)))
swissChili6eee4f92021-04-20 09:34:30 -0700240 return false;
241
swissChili53472e82021-05-08 16:06:32 -0700242 while (isdigit(is->peek(is)))
swissChili6eee4f92021-04-20 09:34:30 -0700243 {
244 number *= 10;
swissChili53472e82021-05-08 16:06:32 -0700245 number += is->get(is) - '0';
swissChili6eee4f92021-04-20 09:34:30 -0700246 }
247
swissChili53472e82021-05-08 16:06:32 -0700248 *val = intval(number);
swissChili6eee4f92021-04-20 09:34:30 -0700249 return true;
250}
251
swissChili53472e82021-05-08 16:06:32 -0700252bool read1(struct istream *is, value_t *val)
swissChili7a6f5eb2021-04-13 16:46:02 -0700253{
swissChili53472e82021-05-08 16:06:32 -0700254 if (readsym(is, val))
swissChili7a6f5eb2021-04-13 16:46:02 -0700255 return true;
256
swissChili53472e82021-05-08 16:06:32 -0700257 if (readstr(is, val))
swissChili7a6f5eb2021-04-13 16:46:02 -0700258 return true;
259
swissChili53472e82021-05-08 16:06:32 -0700260 if (readint(is, val))
swissChili6eee4f92021-04-20 09:34:30 -0700261 return true;
262
swissChili53472e82021-05-08 16:06:32 -0700263 if (readlist(is, val))
swissChilibed80922021-04-13 21:58:05 -0700264 return true;
265
swissChili7a6f5eb2021-04-13 16:46:02 -0700266 return false;
267}
268
swissChili53472e82021-05-08 16:06:32 -0700269value_t readn(struct istream *is)
swissChilibed80922021-04-13 21:58:05 -0700270{
swissChili8cfb7c42021-04-18 21:17:58 -0700271 value_t first = nil;
272 value_t *last = &first;
swissChilibed80922021-04-13 21:58:05 -0700273
swissChili8cfb7c42021-04-18 21:17:58 -0700274 value_t read_val;
swissChilibed80922021-04-13 21:58:05 -0700275
swissChili53472e82021-05-08 16:06:32 -0700276 while (read1(is, &read_val))
swissChilibed80922021-04-13 21:58:05 -0700277 {
swissChili53472e82021-05-08 16:06:32 -0700278 *last = cons(read_val, nil);
279 last = cdrref(*last);
swissChilibed80922021-04-13 21:58:05 -0700280 }
281
282 return first;
283}
284
swissChili7a6f5eb2021-04-13 16:46:02 -0700285struct stristream_private
286{
287 char *val;
288 int i;
289 int length;
swissChilibed80922021-04-13 21:58:05 -0700290 int line;
291 int fromleft;
292 int linestart;
swissChili7a6f5eb2021-04-13 16:46:02 -0700293};
294
swissChili53472e82021-05-08 16:06:32 -0700295int stristream_peek(struct istream *is)
swissChili7a6f5eb2021-04-13 16:46:02 -0700296{
297 struct stristream_private *p = is->data;
298
swissChili53472e82021-05-08 16:06:32 -0700299 if (p->i < p->length)
300 return p->val[p->i];
swissChili7a6f5eb2021-04-13 16:46:02 -0700301 else
302 return -1;
303}
304
swissChili53472e82021-05-08 16:06:32 -0700305int stristream_get(struct istream *is)
swissChili7a6f5eb2021-04-13 16:46:02 -0700306{
307 struct stristream_private *p = is->data;
308
swissChili53472e82021-05-08 16:06:32 -0700309 if (p->i < p->length)
swissChilibed80922021-04-13 21:58:05 -0700310 {
swissChili53472e82021-05-08 16:06:32 -0700311 char c = p->val[p->i++];
swissChilibed80922021-04-13 21:58:05 -0700312
313 p->fromleft++;
314
swissChili53472e82021-05-08 16:06:32 -0700315 if (c == '\n')
swissChilibed80922021-04-13 21:58:05 -0700316 {
317 p->fromleft = 1;
318 p->line++;
319 p->linestart = p->i;
320 }
321
322 return c;
323 }
swissChili7a6f5eb2021-04-13 16:46:02 -0700324 else
325 return -1;
swissChili7a6f5eb2021-04-13 16:46:02 -0700326}
327
swissChili53472e82021-05-08 16:06:32 -0700328int stristream_read(struct istream *s, char *buffer, int size)
swissChili7a6f5eb2021-04-13 16:46:02 -0700329{
330 struct stristream_private *p = s->data;
331
swissChili53472e82021-05-08 16:06:32 -0700332 int len = MIN(size, p->length - p->i);
333 memcpy(buffer, p->val, len);
swissChili7a6f5eb2021-04-13 16:46:02 -0700334 return len;
335}
336
swissChili53472e82021-05-08 16:06:32 -0700337void stristream_showpos(struct istream *s, FILE *out)
swissChilibed80922021-04-13 21:58:05 -0700338{
339 struct stristream_private *p = s->data;
340
swissChili53472e82021-05-08 16:06:32 -0700341 fprintf(out, "line: %d, char %d\n", p->line, p->fromleft);
swissChilibed80922021-04-13 21:58:05 -0700342
343 int end = p->length;
344
swissChili53472e82021-05-08 16:06:32 -0700345 for (int i = p->linestart; i < p->length; i++)
swissChilibed80922021-04-13 21:58:05 -0700346 {
swissChili53472e82021-05-08 16:06:32 -0700347 if (p->val[i] == '\n')
swissChilibed80922021-04-13 21:58:05 -0700348 {
349 end = i;
350 break;
351 }
352 }
353
swissChili53472e82021-05-08 16:06:32 -0700354 fprintf(out, " | %.*s\n", end - p->linestart, p->val + p->linestart);
355 fprintf(out, " | ");
356 for (int i = 0; i < p->fromleft - 1; i++)
357 fprintf(out, " ");
swissChilibed80922021-04-13 21:58:05 -0700358
swissChili53472e82021-05-08 16:06:32 -0700359 fprintf(out, "\033[31m^\033[0m\n");
swissChilibed80922021-04-13 21:58:05 -0700360}
361
swissChili53472e82021-05-08 16:06:32 -0700362struct istream *new_stristream(char *str, int length)
swissChili7a6f5eb2021-04-13 16:46:02 -0700363{
swissChili53472e82021-05-08 16:06:32 -0700364 struct istream *is = malloc(sizeof(struct istream));
365 struct stristream_private *p = malloc(sizeof(struct stristream_private));
swissChili7a6f5eb2021-04-13 16:46:02 -0700366
swissChili53472e82021-05-08 16:06:32 -0700367 p->val = strndup(str, length);
swissChili7a6f5eb2021-04-13 16:46:02 -0700368 p->i = 0;
369 p->length = length;
swissChilibed80922021-04-13 21:58:05 -0700370 p->line = 1;
371 p->fromleft = 1;
372 p->linestart = 0;
swissChili7a6f5eb2021-04-13 16:46:02 -0700373
374 is->data = p;
375 is->get = stristream_get;
376 is->peek = stristream_peek;
377 is->read = stristream_read;
swissChilibed80922021-04-13 21:58:05 -0700378 is->showpos = stristream_showpos;
swissChili7a6f5eb2021-04-13 16:46:02 -0700379
380 return is;
381}
382
swissChili53472e82021-05-08 16:06:32 -0700383void del_stristream(struct istream *stristream)
swissChili7a6f5eb2021-04-13 16:46:02 -0700384{
385 struct stristream_private *p = stristream->data;
swissChili53472e82021-05-08 16:06:32 -0700386 free(p->val);
387 free(p);
388 free(stristream);
swissChili7a6f5eb2021-04-13 16:46:02 -0700389}
390
swissChili53472e82021-05-08 16:06:32 -0700391struct istream *new_stristream_nt(char *str)
swissChili7a6f5eb2021-04-13 16:46:02 -0700392{
swissChili53472e82021-05-08 16:06:32 -0700393 return new_stristream(str, strlen(str));
swissChili7a6f5eb2021-04-13 16:46:02 -0700394}
395
swissChili53472e82021-05-08 16:06:32 -0700396bool startswith(struct istream *s, char *pattern)
swissChili7a6f5eb2021-04-13 16:46:02 -0700397{
swissChili53472e82021-05-08 16:06:32 -0700398 char *check = strdup(pattern);
399 s->read(s, check, strlen(pattern));
swissChili7a6f5eb2021-04-13 16:46:02 -0700400
swissChili53472e82021-05-08 16:06:32 -0700401 bool res = strcmp(check, pattern) == 0;
402 free(check);
swissChili7a6f5eb2021-04-13 16:46:02 -0700403
404 return res;
405}
swissChilibed80922021-04-13 21:58:05 -0700406
swissChili53472e82021-05-08 16:06:32 -0700407value_t strval(char *str)
swissChilibed80922021-04-13 21:58:05 -0700408{
swissChili8cfb7c42021-04-18 21:17:58 -0700409 value_t v;
410
swissChili53472e82021-05-08 16:06:32 -0700411 char *a = malloc_aligned(strlen(str) + 1);
swissChilib3ca4fb2021-04-20 10:33:00 -0700412 v = (value_t)a;
swissChili8cfb7c42021-04-18 21:17:58 -0700413 v |= STRING_TAG;
swissChilibed80922021-04-13 21:58:05 -0700414
415 return v;
416}
417
swissChili53472e82021-05-08 16:06:32 -0700418bool integerp(value_t v)
swissChilibed80922021-04-13 21:58:05 -0700419{
swissChili8cfb7c42021-04-18 21:17:58 -0700420 return (v & INT_MASK) == INT_TAG;
421}
swissChilibed80922021-04-13 21:58:05 -0700422
swissChili53472e82021-05-08 16:06:32 -0700423bool symbolp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700424{
425 return (v & HEAP_MASK) == SYMBOL_TAG;
426}
427
swissChili53472e82021-05-08 16:06:32 -0700428bool stringp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700429{
430 return (v & HEAP_MASK) == STRING_TAG;
431}
432
swissChili53472e82021-05-08 16:06:32 -0700433bool consp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700434{
435 return (v & HEAP_MASK) == CONS_TAG;
436}
437
swissChili53472e82021-05-08 16:06:32 -0700438bool listp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700439{
440 value_t next = v;
441
swissChili53472e82021-05-08 16:06:32 -0700442 while (consp(next))
swissChilibed80922021-04-13 21:58:05 -0700443 {
swissChili53472e82021-05-08 16:06:32 -0700444 next = cdr(next);
swissChilibed80922021-04-13 21:58:05 -0700445 }
446
swissChili53472e82021-05-08 16:06:32 -0700447 return nilp(next);
swissChilibed80922021-04-13 21:58:05 -0700448}
449
swissChili53472e82021-05-08 16:06:32 -0700450value_t car(value_t v)
swissChilibed80922021-04-13 21:58:05 -0700451{
swissChili53472e82021-05-08 16:06:32 -0700452 if (!consp(v))
swissChilibed80922021-04-13 21:58:05 -0700453 return nil;
454
swissChili53472e82021-05-08 16:06:32 -0700455 return *carref(v);
swissChilibed80922021-04-13 21:58:05 -0700456}
457
swissChili53472e82021-05-08 16:06:32 -0700458value_t cdr(value_t v)
swissChilibed80922021-04-13 21:58:05 -0700459{
swissChili53472e82021-05-08 16:06:32 -0700460 if (!consp(v))
swissChilibed80922021-04-13 21:58:05 -0700461 return nil;
462
swissChili53472e82021-05-08 16:06:32 -0700463 return *cdrref(v);
swissChilibed80922021-04-13 21:58:05 -0700464}
465
swissChili53472e82021-05-08 16:06:32 -0700466value_t *carref(value_t v)
swissChilibed80922021-04-13 21:58:05 -0700467{
swissChili53472e82021-05-08 16:06:32 -0700468 if (!consp(v))
swissChili8cfb7c42021-04-18 21:17:58 -0700469 return NULL;
470
swissChilib3ca4fb2021-04-20 10:33:00 -0700471 struct cons *c = (void *)(v ^ CONS_TAG);
swissChili8cfb7c42021-04-18 21:17:58 -0700472 return &c->car;
swissChilibed80922021-04-13 21:58:05 -0700473}
swissChilica107a02021-04-14 12:07:30 -0700474
swissChili53472e82021-05-08 16:06:32 -0700475value_t *cdrref(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700476{
swissChili53472e82021-05-08 16:06:32 -0700477 if (!consp(v))
swissChili8cfb7c42021-04-18 21:17:58 -0700478 return NULL;
479
swissChilib3ca4fb2021-04-20 10:33:00 -0700480 struct cons *c = (void *)(v ^ CONS_TAG);
swissChili8cfb7c42021-04-18 21:17:58 -0700481 return &c->cdr;
482}
483
swissChili53472e82021-05-08 16:06:32 -0700484bool nilp(value_t v)
swissChili8cfb7c42021-04-18 21:17:58 -0700485{
486 return v == nil;
487}
488
swissChili53472e82021-05-08 16:06:32 -0700489int length(value_t v)
swissChilica107a02021-04-14 12:07:30 -0700490{
491 int i = 0;
492
swissChili53472e82021-05-08 16:06:32 -0700493 for (; !nilp(v); v = cdr(v))
swissChilica107a02021-04-14 12:07:30 -0700494 i++;
495
496 return i;
497}
swissChilib3ca4fb2021-04-20 10:33:00 -0700498
swissChili53472e82021-05-08 16:06:32 -0700499value_t elt(value_t v, int index)
swissChilib3ca4fb2021-04-20 10:33:00 -0700500{
swissChili53472e82021-05-08 16:06:32 -0700501 for (int i = 0; i < index; i++)
swissChilib3ca4fb2021-04-20 10:33:00 -0700502 {
swissChili53472e82021-05-08 16:06:32 -0700503 v = cdr(v);
swissChilib3ca4fb2021-04-20 10:33:00 -0700504 }
505
swissChili53472e82021-05-08 16:06:32 -0700506 return car(v);
swissChilib3ca4fb2021-04-20 10:33:00 -0700507}
swissChili8fc5e2f2021-04-22 13:45:10 -0700508
swissChili53472e82021-05-08 16:06:32 -0700509bool symstreq(value_t sym, char *str)
swissChili8fc5e2f2021-04-22 13:45:10 -0700510{
swissChili53472e82021-05-08 16:06:32 -0700511 if ((sym & HEAP_MASK) != SYMBOL_TAG)
swissChili8fc5e2f2021-04-22 13:45:10 -0700512 return false;
513
swissChili53472e82021-05-08 16:06:32 -0700514 return strcmp((char *)(sym ^ SYMBOL_TAG), str) == 0;
swissChili8fc5e2f2021-04-22 13:45:10 -0700515}