16 struct charseq
*vp_charseq
;
17 union value_pointer (*vp_builtin
)(struct environment
*env
,
19 char const *vp_opaque
;
24 union value_pointer value
;
28 struct binding
**variables
;
31 struct environment
*parent
;
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";
43 union value_pointer constant_true
, constant_false
;
45 void pointer_mark(union value_pointer
*v
, int type
)
47 int pointer_bits
= v
->vp_int
;
52 v
->vp_int
= pointer_bits
;
55 int pointer_type(union value_pointer v
)
57 return (v
.vp_int
& 3);
60 int get_integer(union value_pointer v
)
62 return (v
.vp_int
>> 2);
65 struct pair
*get_pair(union value_pointer v
)
71 struct charseq
*get_charseq(union value_pointer v
)
77 size_t get_charseq_length(union value_pointer v
)
86 char *get_charseq_chars(union value_pointer v
)
95 struct environment
*environment_new(struct environment
*parent
)
97 struct environment
*env
;
99 env
= malloc(sizeof (*env
));
100 env
->variables
= NULL
;
101 env
->variables_used
= 0;
102 env
->variables_size
= 0;
103 env
->parent
= parent
;
108 struct charseq
*charseq_new(char const *s
, size_t len
)
112 cs
= malloc(sizeof (*cs
));
114 cs
->s
= malloc(len
+ 1);
115 memcpy(cs
->s
, s
, len
);
121 struct pair
*pair_new(void)
125 p
= malloc(sizeof (*p
));
126 p
->cdr
.vp_pair
= NULL
;
127 pointer_mark(&p
->cdr
, 3);
132 void pair_free(struct pair
*p
)
137 union value_pointer
lisp_car(union value_pointer v
)
139 return get_pair(v
)->car
;
142 struct binding
*binding_new(struct environment
*env
,
144 union value_pointer value
)
148 b
= malloc(sizeof (*b
));
150 b
->name
= charseq_new(name
, strlen(name
));
154 if (env
->variables_used
>= env
->variables_size
) {
155 int newsize
= env
->variables_used
* 2 + 16;
157 env
->variables
= realloc(env
->variables
,
158 sizeof (*env
->variables
) * newsize
);
159 env
->variables_size
= newsize
;
162 env
->variables
[env
->variables_used
++] = b
;
167 void binding_builtin(struct environment
*env
,
169 char const *opaque_type
,
170 union value_pointer (*builtin
)(struct environment
*env
,
173 union value_pointer v
;
174 struct pair
*type_dot_value
;
176 type_dot_value
= pair_new();
177 type_dot_value
->car
.vp_opaque
= opaque_type
;
178 type_dot_value
->cdr
.vp_builtin
= builtin
;
179 v
.vp_pair
= type_dot_value
;
182 binding_new(env
, name
, v
);
185 size_t parse_word(union value_pointer
*vp
, char const *buf
, size_t len
)
190 for (n
= 0, i
= 0; i
< len
; i
++) {
191 if (buf
[i
] < '0' || buf
[i
] > '9') {
194 n
= n
*10 + buf
[i
] - '0';
207 for (i
++; i
< len
; i
++) {
220 vp
->vp_charseq
= charseq_new(buf
, i
);
230 size_t parse_string(union value_pointer
*vp
, char const *buf
, size_t len
)
234 for (i
= 1; i
< len
; i
++) {
240 vp
->vp_charseq
= charseq_new(buf
+ 1, i
- 1);
246 size_t parse_forms(char const *buf
, size_t len
, union value_pointer
*form
)
250 for (i
= 0; i
< len
; i
++) {
251 char const c
= buf
[i
];
252 union value_pointer u
, v
;
259 v
.vp_pair
= pair_new();
262 n
= parse_forms(buf
+ i
+ 1, len
- i
- 1, &u
) + 1;
266 pointer_mark(form
, 3);
267 form
= &v
.vp_pair
->cdr
;
275 v
.vp_pair
= pair_new();
276 n
= parse_string(&v
.vp_pair
->car
, buf
+ i
, len
- i
);
279 pointer_mark(form
, 3);
280 form
= &v
.vp_pair
->cdr
;
283 v
.vp_pair
= pair_new();
284 n
= parse_word(&v
.vp_pair
->car
, buf
+ i
, len
- i
);
287 pointer_mark(form
, 3);
288 form
= &v
.vp_pair
->cdr
;
300 void pretty_print(union value_pointer v
)
302 union value_pointer i
;
305 switch (pointer_type(v
)) {
307 printf("%d", get_integer(v
));
310 printf("%s", get_charseq_chars(v
));
313 printf("\"%s\"", get_charseq_chars(v
));
318 (p
->car
.vp_opaque
== opaque_builtin_function
||
319 p
->car
.vp_opaque
== opaque_builtin_macro
||
320 p
->car
.vp_opaque
== opaque_user_function
||
321 p
->car
.vp_opaque
== opaque_user_macro
)) {
322 printf("%s", p
->car
.vp_opaque
);
327 for (i
= v
; pointer_type(i
) == 3 && get_pair(i
) != NULL
; i
= get_pair(i
)->cdr
) {
328 if (i
.vp_pair
!= v
.vp_pair
) {
331 pretty_print(lisp_car(i
));
333 if (pointer_type(i
) != 3) {
342 union value_pointer
builtin_eval(struct environment
*env
,
345 union value_pointer retval
, function
, args
;
346 union value_pointer
*arglink
;
347 char const *symbol_name
;
348 struct pair
*list
, *closure
;
349 struct pair
*subeval_arg
;
352 switch (pointer_type(rest
->car
)) {
358 symbol_name
= get_charseq_chars(rest
->car
);
360 for (i
= 0; i
< env
->variables_used
; i
++) {
361 if (strcmp(env
->variables
[i
]->name
->s
,
363 return env
->variables
[i
]->value
;
367 } while (env
!= NULL
);
370 list
= get_pair(rest
->car
);
371 subeval_arg
= pair_new();
372 subeval_arg
->car
= list
->car
;
374 args
.vp_pair
= pair_new();
375 args
.vp_pair
->car
= builtin_eval(env
, subeval_arg
);
377 if (lisp_car(args
.vp_pair
->car
).vp_opaque
== opaque_builtin_function
) {
378 arglink
= &args
.vp_pair
->cdr
;
380 for (list
= get_pair(list
->cdr
); list
!= NULL
; list
= get_pair(list
->cdr
)) {
381 union value_pointer element
;
383 subeval_arg
= pair_new();
384 subeval_arg
->car
= list
->car
;
386 element
.vp_pair
= pair_new();
387 element
.vp_pair
->car
= builtin_eval(env
, subeval_arg
);
388 pair_free(subeval_arg
);
391 pointer_mark(arglink
, 3);
392 arglink
= &element
.vp_pair
->cdr
;
395 args
.vp_pair
->cdr
= list
->cdr
;
398 pointer_mark(&args
, 3);
399 list
= get_pair(args
);
400 function
= list
->car
;
403 closure
= get_pair(function
);
404 if (closure
->car
.vp_opaque
== opaque_builtin_function
||
405 closure
->car
.vp_opaque
== opaque_builtin_macro
) {
406 retval
= (*closure
->cdr
.vp_builtin
)(env
, get_pair(args
));
407 } else if (closure
->car
.vp_opaque
== opaque_user_function
) {
408 union value_pointer formal_args
, function_body
;
409 struct pair
*p
, *sexpr
;
410 struct environment
*call_env
;
412 p
= get_pair(closure
->cdr
);
413 formal_args
= p
->car
;
414 function_body
= p
->cdr
;
416 call_env
= environment_new(env
);
417 for (p
= get_pair(formal_args
), rest
= get_pair(args
);
418 p
!= NULL
&& rest
!= NULL
;
419 p
= get_pair(p
->cdr
), rest
= get_pair(rest
->cdr
)) {
420 binding_new(call_env
, get_charseq_chars(p
->car
), rest
->car
);
423 for (p
= get_pair(function_body
); p
!= NULL
; p
= get_pair(p
->cdr
)) {
426 retval
= builtin_eval(call_env
, sexpr
);
436 union value_pointer
builtin_car(struct environment
*env
,
439 union value_pointer retval
;
441 retval
= lisp_car(rest
->car
);
446 union value_pointer
builtin_cdr(struct environment
*env
,
449 union value_pointer retval
;
451 retval
= get_pair(rest
->car
)->cdr
;
456 union value_pointer
builtin_cons(struct environment
*env
,
459 union value_pointer retval
;
461 retval
.vp_pair
= pair_new();
462 retval
.vp_pair
->car
= rest
->car
;
463 retval
.vp_pair
->cdr
= lisp_car(rest
->cdr
);
464 pointer_mark(&retval
, 3);
469 union value_pointer
builtin_eq_p(struct environment
*env
,
472 union value_pointer a
, b
;
475 b
= lisp_car(rest
->cdr
);
477 if (pointer_type(a
) != pointer_type(b
)) {
478 return constant_false
;
481 switch (pointer_type(a
)) {
483 if (get_integer(a
) != get_integer(b
)) {
484 return constant_false
;
488 if (strcmp(get_charseq_chars(a
), get_charseq_chars(b
))) {
489 return constant_false
;
493 if (get_charseq(a
) != get_charseq(b
)) {
494 return constant_false
;
498 if (a
.vp_pair
!= b
.vp_pair
) {
499 return constant_false
;
504 return constant_true
;
507 union value_pointer
builtin_if(struct environment
*env
,
510 union value_pointer retval
;
511 union value_pointer condition
, consequent
, alternate
;
514 retval
.vp_pair
= NULL
;
515 pointer_mark(&retval
, 3);
517 condition
= rest
->car
;
518 consequent
= lisp_car(rest
->cdr
);
519 alternate
= get_pair(rest
->cdr
)->cdr
;
523 condition
= builtin_eval(env
, p
);
525 if (pointer_type(condition
) != 1 ||
526 condition
.vp_charseq
!= constant_false
.vp_charseq
) {
528 } else if (get_pair(alternate
) != NULL
) {
529 p
->car
= lisp_car(alternate
);
535 retval
= builtin_eval(env
, p
);
541 union value_pointer
builtin_lambda(struct environment
*env
,
544 union value_pointer retval
;
546 retval
.vp_pair
= pair_new();
547 retval
.vp_pair
->car
.vp_opaque
= opaque_user_function
;
548 retval
.vp_pair
->cdr
.vp_pair
= rest
;
549 pointer_mark(&retval
.vp_pair
->cdr
, 3);
550 pointer_mark(&retval
, 3);
555 union value_pointer
builtin_quote(struct environment
*env
,
558 union value_pointer retval
;
565 union value_pointer
builtin_plus(struct environment
*env
,
568 union value_pointer retval
;
571 for (sum
= 0; rest
!= NULL
; rest
= get_pair(rest
->cdr
)) {
572 sum
+= get_integer(rest
->car
);
575 retval
.vp_int
= sum
<< 2;
576 pointer_mark(&retval
, 0);
587 union value_pointer form
;
589 struct environment
*top_env
;
591 while (!feof(stdin
) && !ferror(stdin
)) {
594 if (bufused
>= bufsize
) {
595 buf
= realloc(buf
, bufsize
* 2 + 16);
599 bufsize
= bufsize
* 2 + 16;
601 n
= fread(buf
+ bufused
, 1, bufsize
- bufused
, stdin
);
605 top_env
= environment_new(NULL
);
607 constant_true
.vp_charseq
= charseq_new("#t", 2);
608 pointer_mark(&constant_true
, 1);
610 constant_false
.vp_charseq
= charseq_new("#f", 2);
611 pointer_mark(&constant_false
, 1);
613 binding_new(top_env
, "#t", constant_true
);
614 binding_new(top_env
, "#f", constant_false
);
616 binding_builtin(top_env
, "car", opaque_builtin_function
, builtin_car
);
617 binding_builtin(top_env
, "cdr", opaque_builtin_function
, builtin_cdr
);
618 binding_builtin(top_env
, "cons", opaque_builtin_function
, builtin_cons
);
619 binding_builtin(top_env
, "eq?", opaque_builtin_function
, builtin_eq_p
);
621 binding_builtin(top_env
, "if", opaque_builtin_macro
, builtin_if
);
622 binding_builtin(top_env
, "lambda", opaque_builtin_macro
, builtin_lambda
);
623 binding_builtin(top_env
, "quote", opaque_builtin_macro
, builtin_quote
);
625 binding_builtin(top_env
, "+", opaque_builtin_function
, builtin_plus
);
628 pointer_mark(&form
, 3);
630 formsize
= parse_forms(buf
, bufused
, &form
);
632 if (formsize
!= bufused
) {
633 printf("this stuff left over: \"%.*s\"\n",
634 bufused
- formsize
, buf
+ formsize
);
637 for (i
= get_pair(form
); i
!= NULL
; i
= get_pair(i
->cdr
)) {
643 pretty_print(i
->car
);
645 pretty_print(builtin_eval(top_env
, rest
));