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";
44 void pointer_mark(union value_pointer
*v
, int type
)
46 int pointer_bits
= v
->vp_int
;
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
)
70 struct charseq
*get_charseq(union value_pointer v
)
76 size_t get_charseq_length(union value_pointer v
)
85 char *get_charseq_chars(union value_pointer v
)
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
;
107 struct charseq
*charseq_new(char const *s
, size_t len
)
111 cs
= malloc(sizeof (*cs
));
113 cs
->s
= malloc(len
+ 1);
114 memcpy(cs
->s
, s
, len
);
120 struct pair
*pair_new(void)
124 p
= malloc(sizeof (*p
));
125 p
->cdr
.vp_pair
= NULL
;
126 pointer_mark(&p
->cdr
, 3);
131 void pair_free(struct pair
*p
)
136 struct binding
*binding_new(struct environment
*env
,
138 union value_pointer value
)
142 b
= malloc(sizeof (*b
));
144 b
->name
= charseq_new(name
, strlen(name
));
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
;
161 void binding_builtin(struct environment
*env
,
163 char const *opaque_type
,
164 union value_pointer (*builtin
)(struct environment
*env
,
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
;
176 binding_new(env
, name
, v
);
179 size_t parse_word(union value_pointer
*vp
, char const *buf
, size_t len
)
184 for (n
= 0, i
= 0; i
< len
; i
++) {
185 if (buf
[i
] < '0' || buf
[i
] > '9') {
188 n
= n
*10 + buf
[i
] - '0';
201 for (i
++; i
< len
; i
++) {
214 vp
->vp_charseq
= charseq_new(buf
, i
);
224 size_t parse_string(union value_pointer
*vp
, char const *buf
, size_t len
)
228 for (i
= 1; i
< len
; i
++) {
234 vp
->vp_charseq
= charseq_new(buf
+ 1, i
- 1);
240 size_t parse_forms(char const *buf
, size_t len
, union value_pointer
*form
)
244 for (i
= 0; i
< len
; i
++) {
245 char const c
= buf
[i
];
246 union value_pointer u
, v
;
253 v
.vp_pair
= pair_new();
256 i
+= parse_forms(buf
+ i
+ 1, len
- i
- 1, &u
) + 1;
259 pointer_mark(form
, 3);
260 form
= &v
.vp_pair
->cdr
;
268 v
.vp_pair
= pair_new();
269 n
= parse_string(&v
.vp_pair
->car
, buf
+ i
, len
- i
);
272 pointer_mark(form
, 3);
273 form
= &v
.vp_pair
->cdr
;
276 v
.vp_pair
= pair_new();
277 n
= parse_word(&v
.vp_pair
->car
, buf
+ i
, len
- i
);
280 pointer_mark(form
, 3);
281 form
= &v
.vp_pair
->cdr
;
293 void pretty_print(union value_pointer v
)
295 union value_pointer i
;
298 switch (pointer_type(v
)) {
300 printf("%d", get_integer(v
));
303 printf("%s", get_charseq_chars(v
));
306 printf("\"%s\"", get_charseq_chars(v
));
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
);
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
) {
324 pretty_print(get_pair(i
)->car
);
326 if (pointer_type(i
) != 3) {
335 union value_pointer
builtin_eval(struct environment
*env
,
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
;
345 switch (pointer_type(rest
->car
)) {
351 symbol_name
= get_charseq_chars(rest
->car
);
353 for (i
= 0; i
< env
->variables_used
; i
++) {
354 if (strcmp(env
->variables
[i
]->name
->s
,
356 return env
->variables
[i
]->value
;
360 } while (env
!= NULL
);
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
);
384 pointer_mark(arglink
, 3);
385 arglink
= &element
.vp_pair
->cdr
;
388 args
.vp_pair
->cdr
= list
->cdr
;
391 pointer_mark(&args
, 3);
392 list
= get_pair(args
);
393 function
= list
->car
;
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
)) {
419 retval
= builtin_eval(call_env
, sexpr
);
429 union value_pointer
builtin_car(struct environment
*env
,
432 union value_pointer retval
;
434 retval
= get_pair(rest
->car
)->car
;
439 union value_pointer
builtin_cdr(struct environment
*env
,
442 union value_pointer retval
;
444 retval
= get_pair(rest
->car
)->cdr
;
449 union value_pointer
builtin_cons(struct environment
*env
,
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);
462 union value_pointer
builtin_lambda(struct environment
*env
,
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);
476 union value_pointer
builtin_quote(struct environment
*env
,
479 union value_pointer retval
;
486 union value_pointer
builtin_plus(struct environment
*env
,
489 union value_pointer retval
;
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);
508 union value_pointer form
;
509 union value_pointer constant_true
, constant_false
;
511 struct environment
*top_env
;
513 while (!feof(stdin
) && !ferror(stdin
)) {
516 if (bufused
>= bufsize
) {
517 buf
= realloc(buf
, bufsize
* 2 + 16);
521 bufsize
= bufsize
* 2 + 16;
523 n
= fread(buf
+ bufused
, 1, bufsize
- bufused
, stdin
);
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
);
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
)) {
560 pretty_print(i
->car
);
562 pretty_print(builtin_eval(top_env
, rest
));