Implement quote as a built-in macro.
[berndj-bootstrap.git] / lisp / lisp.c
blob62df56eebbcb1ef2e1fb1e975bd0e40447c72d82
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
5 struct environment;
6 struct pair;
8 struct charseq {
9 size_t len;
10 char *s;
13 union value_pointer {
14 int vp_int;
15 struct pair *vp_pair;
16 struct charseq *vp_charseq;
17 union value_pointer (*vp_builtin)(struct environment *env,
18 struct pair *rest);
19 char const *vp_opaque;
22 struct binding {
23 struct charseq *name;
24 union value_pointer value;
27 struct environment {
28 struct binding **variables;
29 int variables_used;
30 int variables_size;
31 struct environment *parent;
34 struct pair {
35 union value_pointer car;
36 union value_pointer cdr;
39 char const opaque_builtin_function[] = "builtin-function";
40 char const opaque_builtin_macro[] = "builtin-macro";
41 char const opaque_user_function[] = "user-function";
42 char const opaque_user_macro[] = "user-macro";
44 void pointer_mark(union value_pointer *v, int type)
46 int pointer_bits = v->vp_int;
48 pointer_bits &= ~3;
49 pointer_bits |= type;
51 v->vp_int = pointer_bits;
54 int pointer_type(union value_pointer v)
56 return (v.vp_int & 3);
59 int get_integer(union value_pointer v)
61 return (v.vp_int >> 2);
64 struct pair *get_pair(union value_pointer v)
66 v.vp_int &= ~3;
67 return v.vp_pair;
70 struct charseq *get_charseq(union value_pointer v)
72 v.vp_int &= ~3;
73 return v.vp_charseq;
76 size_t get_charseq_length(union value_pointer v)
78 struct charseq *cs;
80 cs = get_charseq(v);
82 return cs->len;
85 char *get_charseq_chars(union value_pointer v)
87 struct charseq *cs;
89 cs = get_charseq(v);
91 return cs->s;
94 struct environment *environment_new(struct environment *parent)
96 struct environment *env;
98 env = malloc(sizeof (*env));
99 env->variables = NULL;
100 env->variables_used = 0;
101 env->variables_size = 0;
102 env->parent = parent;
104 return env;
107 struct charseq *charseq_new(char const *s, size_t len)
109 struct charseq *cs;
111 cs = malloc(sizeof (*cs));
112 cs->len = len;
113 cs->s = malloc(len + 1);
114 memcpy(cs->s, s, len);
115 cs->s[len] = 0;
117 return cs;
120 struct pair *pair_new(void)
122 struct pair *p;
124 p = malloc(sizeof (*p));
125 p->cdr.vp_pair = NULL;
126 pointer_mark(&p->cdr, 3);
128 return p;
131 void pair_free(struct pair *p)
133 free(p);
136 struct binding *binding_new(struct environment *env,
137 char const *name,
138 union value_pointer value)
140 struct binding *b;
142 b = malloc(sizeof (*b));
144 b->name = charseq_new(name, strlen(name));
146 b->value = value;
148 if (env->variables_used >= env->variables_size) {
149 int newsize = env->variables_used * 2 + 16;
151 env->variables = realloc(env->variables,
152 sizeof (*env->variables) * newsize);
153 env->variables_size = newsize;
156 env->variables[env->variables_used++] = b;
158 return b;
161 void binding_builtin(struct environment *env,
162 char const *name,
163 char const *opaque_type,
164 union value_pointer (*builtin)(struct environment *env,
165 struct pair *rest))
167 union value_pointer v;
168 struct pair *type_dot_value;
170 type_dot_value = pair_new();
171 type_dot_value->car.vp_opaque = opaque_type;
172 type_dot_value->cdr.vp_builtin = builtin;
173 v.vp_pair = type_dot_value;
174 pointer_mark(&v, 3);
176 binding_new(env, name, v);
179 size_t parse_word(union value_pointer *vp, char const *buf, size_t len)
181 size_t i;
182 int n;
184 for (n = 0, i = 0; i < len; i++) {
185 if (buf[i] < '0' || buf[i] > '9') {
186 break;
188 n = n*10 + buf[i] - '0';
191 if (i < len) {
192 char *symbol;
194 switch (buf[i]) {
195 case ')':
196 case ' ':
197 case '\n':
198 case '\t':
199 break;
200 default:
201 for (i++; i < len; i++) {
202 switch (buf[i]) {
203 case ')':
204 case ' ':
205 case '\n':
206 case '\t':
207 len = i + 1;
208 break;
209 default:
210 continue;
212 break;
214 vp->vp_charseq = charseq_new(buf, i);
215 pointer_mark(vp, 1);
216 return i;
219 vp->vp_int = n << 2;
220 pointer_mark(vp, 0);
221 return i;
224 size_t parse_string(union value_pointer *vp, char const *buf, size_t len)
226 size_t i;
228 for (i = 1; i < len; i++) {
229 if (buf[i] == '"') {
230 break;
234 vp->vp_charseq = charseq_new(buf + 1, i - 1);
235 pointer_mark(vp, 2);
237 return i + 1;
240 size_t parse_forms(char const *buf, size_t len, union value_pointer *form)
242 size_t i, n;
244 for (i = 0; i < len; i++) {
245 char const c = buf[i];
246 union value_pointer u, v;
248 v.vp_pair = NULL;
249 pointer_mark(&v, 3);
251 switch (c) {
252 case '(':
253 v.vp_pair = pair_new();
254 u.vp_pair = NULL;
255 pointer_mark(&u, 3);
256 i += parse_forms(buf + i + 1, len - i - 1, &u) + 1;
257 v.vp_pair->car = u;
258 *form = v;
259 pointer_mark(form, 3);
260 form = &v.vp_pair->cdr;
261 break;
262 case ')':
263 case ' ':
264 case '\n':
265 case '\t':
266 break;
267 case '"':
268 v.vp_pair = pair_new();
269 n = parse_string(&v.vp_pair->car, buf + i, len - i);
270 i += n;
271 *form = v;
272 pointer_mark(form, 3);
273 form = &v.vp_pair->cdr;
274 break;
275 default:
276 v.vp_pair = pair_new();
277 n = parse_word(&v.vp_pair->car, buf + i, len - i);
278 i += n - 1;
279 *form = v;
280 pointer_mark(form, 3);
281 form = &v.vp_pair->cdr;
282 break;
285 if (c == ')') {
286 break;
290 return i;
293 void pretty_print(union value_pointer v)
295 union value_pointer i;
296 struct pair *p;
298 switch (pointer_type(v)) {
299 case 0:
300 printf("%d", get_integer(v));
301 break;
302 case 1:
303 printf("%s", get_charseq_chars(v));
304 break;
305 case 2:
306 printf("\"%s\"", get_charseq_chars(v));
307 break;
308 case 3:
309 p = get_pair(v);
310 if (p != NULL &&
311 (p->car.vp_opaque == opaque_builtin_function ||
312 p->car.vp_opaque == opaque_builtin_macro ||
313 p->car.vp_opaque == opaque_user_function ||
314 p->car.vp_opaque == opaque_user_macro)) {
315 printf("%s", p->car.vp_opaque);
316 break;
319 printf("(");
320 for (i = v; pointer_type(i) == 3 && get_pair(i) != NULL; i = get_pair(i)->cdr) {
321 if (i.vp_pair != v.vp_pair) {
322 printf(" ");
324 pretty_print(get_pair(i)->car);
326 if (pointer_type(i) != 3) {
327 printf(" . ");
328 pretty_print(i);
330 printf(")");
331 break;
335 union value_pointer builtin_eval(struct environment *env,
336 struct pair *rest)
338 union value_pointer retval, function, args;
339 union value_pointer *arglink;
340 char const *symbol_name;
341 struct pair *list, *closure;
342 struct pair *subeval_arg;
343 int i;
345 switch (pointer_type(rest->car)) {
346 case 0:
347 case 2:
348 retval = rest->car;
349 break;
350 case 1:
351 symbol_name = get_charseq_chars(rest->car);
352 do {
353 for (i = 0; i < env->variables_used; i++) {
354 if (strcmp(env->variables[i]->name->s,
355 symbol_name) == 0) {
356 return env->variables[i]->value;
359 env = env->parent;
360 } while (env != NULL);
361 break;
362 case 3:
363 list = get_pair(rest->car);
364 subeval_arg = pair_new();
365 subeval_arg->car = list->car;
367 args.vp_pair = pair_new();
368 args.vp_pair->car = builtin_eval(env, subeval_arg);
370 if (get_pair(args.vp_pair->car)->car.vp_opaque == opaque_builtin_function) {
371 arglink = &args.vp_pair->cdr;
373 for (list = get_pair(list->cdr); list != NULL; list = get_pair(list->cdr)) {
374 union value_pointer element;
376 subeval_arg = pair_new();
377 subeval_arg->car = list->car;
379 element.vp_pair = pair_new();
380 element.vp_pair->car = builtin_eval(env, subeval_arg);
381 pair_free(subeval_arg);
383 *arglink = element;
384 pointer_mark(arglink, 3);
385 arglink = &element.vp_pair->cdr;
387 } else {
388 args.vp_pair->cdr = list->cdr;
391 pointer_mark(&args, 3);
392 list = get_pair(args);
393 function = list->car;
394 args = list->cdr;
396 closure = get_pair(function);
397 if (closure->car.vp_opaque == opaque_builtin_function ||
398 closure->car.vp_opaque == opaque_builtin_macro) {
399 retval = (*closure->cdr.vp_builtin)(env, get_pair(args));
400 } else if (closure->car.vp_opaque == opaque_user_function) {
401 union value_pointer formal_args, function_body;
402 struct pair *p, *sexpr;
403 struct environment *call_env;
405 p = get_pair(closure->cdr);
406 formal_args = p->car;
407 function_body = p->cdr;
409 call_env = environment_new(env);
410 for (p = get_pair(formal_args), rest = get_pair(args);
411 p != NULL && rest != NULL;
412 p = get_pair(p->cdr), rest = get_pair(rest->cdr)) {
413 binding_new(call_env, get_charseq_chars(p->car), rest->car);
416 for (p = get_pair(function_body); p != NULL; p = get_pair(p->cdr)) {
417 sexpr = pair_new();
418 sexpr->car = p->car;
419 retval = builtin_eval(call_env, sexpr);
423 break;
426 return retval;
429 union value_pointer builtin_car(struct environment *env,
430 struct pair *rest)
432 union value_pointer retval;
434 retval = get_pair(rest->car)->car;
436 return retval;
439 union value_pointer builtin_cdr(struct environment *env,
440 struct pair *rest)
442 union value_pointer retval;
444 retval = get_pair(rest->car)->cdr;
446 return retval;
449 union value_pointer builtin_cons(struct environment *env,
450 struct pair *rest)
452 union value_pointer retval;
454 retval.vp_pair = pair_new();
455 retval.vp_pair->car = rest->car;
456 retval.vp_pair->cdr = get_pair(rest->cdr)->car;
457 pointer_mark(&retval, 3);
459 return retval;
462 union value_pointer builtin_lambda(struct environment *env,
463 struct pair *rest)
465 union value_pointer retval;
467 retval.vp_pair = pair_new();
468 retval.vp_pair->car.vp_opaque = opaque_user_function;
469 retval.vp_pair->cdr.vp_pair = rest;
470 pointer_mark(&retval.vp_pair->cdr, 3);
471 pointer_mark(&retval, 3);
473 return retval;
476 union value_pointer builtin_quote(struct environment *env,
477 struct pair *rest)
479 union value_pointer retval;
481 retval = rest->car;
483 return retval;
486 union value_pointer builtin_plus(struct environment *env,
487 struct pair *rest)
489 union value_pointer retval;
490 int sum;
492 for (sum = 0; rest != NULL; rest = get_pair(rest->cdr)) {
493 sum += get_integer(rest->car);
496 retval.vp_int = sum << 2;
497 pointer_mark(&retval, 0);
499 return retval;
502 int main()
504 char *buf = NULL;
505 size_t bufused = 0;
506 size_t bufsize = 0;
507 size_t formsize;
508 union value_pointer form;
509 union value_pointer constant_true, constant_false;
510 struct pair *i;
511 struct environment *top_env;
513 while (!feof(stdin) && !ferror(stdin)) {
514 size_t n;
516 if (bufused >= bufsize) {
517 buf = realloc(buf, bufsize * 2 + 16);
518 if (buf == NULL) {
519 abort();
521 bufsize = bufsize * 2 + 16;
523 n = fread(buf + bufused, 1, bufsize - bufused, stdin);
524 bufused += n;
527 top_env = environment_new(NULL);
529 constant_true.vp_charseq = charseq_new("#t", 2);
530 pointer_mark(&constant_true, 1);
532 constant_false.vp_charseq = charseq_new("#f", 2);
533 pointer_mark(&constant_false, 1);
535 binding_new(top_env, "#t", constant_true);
536 binding_new(top_env, "#f", constant_false);
538 binding_builtin(top_env, "car", opaque_builtin_function, builtin_car);
539 binding_builtin(top_env, "cdr", opaque_builtin_function, builtin_cdr);
540 binding_builtin(top_env, "cons", opaque_builtin_function, builtin_cons);
541 binding_builtin(top_env, "lambda", opaque_builtin_macro, builtin_lambda);
542 binding_builtin(top_env, "quote", opaque_builtin_macro, builtin_quote);
543 binding_builtin(top_env, "+", opaque_builtin_function, builtin_plus);
544 form.vp_pair = NULL;
545 pointer_mark(&form, 3);
547 formsize = parse_forms(buf, bufused, &form);
549 if (formsize != bufused) {
550 printf("this stuff left over: \"%.*s\"\n",
551 bufused - formsize, buf + formsize);
554 for (i = get_pair(form); i != NULL; i = get_pair(i->cdr)) {
555 struct pair *rest;
557 rest = pair_new();
558 rest->car = i->car;
560 pretty_print(i->car);
561 printf(" -> ");
562 pretty_print(builtin_eval(top_env, rest));
563 printf("\n");
566 return 0;