16 struct charseq
*vp_charseq
;
17 union value_pointer (*vp_builtin
)(struct environment
*env
,
19 char const *vp_opaque
;
24 union value_pointer type_dot_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 charseq
*charseq_new(char const *s
, size_t len
)
98 cs
= malloc(sizeof (*cs
));
100 cs
->s
= malloc(len
+ 1);
101 memcpy(cs
->s
, s
, len
);
107 struct pair
*pair_new(void)
111 p
= malloc(sizeof (*p
));
112 p
->cdr
.vp_pair
= NULL
;
113 pointer_mark(&p
->cdr
, 3);
118 void pair_free(struct pair
*p
)
123 struct binding
*binding_new(struct environment
*env
,
125 union value_pointer type_dot_value
)
129 b
= malloc(sizeof (*b
));
131 b
->name
= charseq_new(name
, strlen(name
));
133 b
->type_dot_value
= type_dot_value
;
135 if (env
->variables_used
>= env
->variables_size
) {
136 int newsize
= env
->variables_used
* 2 + 16;
138 env
->variables
= realloc(env
->variables
,
139 sizeof (*env
->variables
) * newsize
);
140 env
->variables_size
= newsize
;
143 env
->variables
[env
->variables_used
++] = b
;
148 void binding_builtin(struct environment
*env
,
150 char const *opaque_type
,
151 union value_pointer (*builtin
)(struct environment
*env
,
154 union value_pointer v
;
155 struct pair
*type_dot_value
;
157 type_dot_value
= pair_new();
158 type_dot_value
->car
.vp_opaque
= opaque_type
;
159 type_dot_value
->cdr
.vp_builtin
= builtin
;
160 v
.vp_pair
= type_dot_value
;
163 binding_new(env
, name
, v
);
166 size_t parse_word(union value_pointer
*vp
, char const *buf
, size_t len
)
171 for (n
= 0, i
= 0; i
< len
; i
++) {
172 if (buf
[i
] < '0' || buf
[i
] > '9') {
175 n
= n
*10 + buf
[i
] - '0';
188 for (i
++; i
< len
; i
++) {
201 vp
->vp_charseq
= charseq_new(buf
, i
);
211 size_t parse_string(union value_pointer
*vp
, char const *buf
, size_t len
)
215 for (i
= 1; i
< len
; i
++) {
221 vp
->vp_charseq
= charseq_new(buf
+ 1, i
- 1);
227 size_t parse_forms(char const *buf
, size_t len
, union value_pointer
*form
)
231 for (i
= 0; i
< len
; i
++) {
232 char const c
= buf
[i
];
233 union value_pointer u
, v
;
237 v
.vp_pair
= pair_new();
238 v
.vp_pair
->car
.vp_pair
= NULL
;
239 pointer_mark(&v
.vp_pair
->car
, 3);
240 i
+= parse_forms(buf
+ i
+ 1, len
- i
- 1, &v
.vp_pair
->car
) + 1;
242 pointer_mark(form
, 3);
243 form
= &v
.vp_pair
->cdr
;
251 v
.vp_pair
= pair_new();
252 n
= parse_string(&v
.vp_pair
->car
, buf
+ i
, len
- i
);
255 pointer_mark(form
, 3);
256 form
= &v
.vp_pair
->cdr
;
259 v
.vp_pair
= pair_new();
260 n
= parse_word(&v
.vp_pair
->car
, buf
+ i
, len
- i
);
263 pointer_mark(form
, 3);
264 form
= &v
.vp_pair
->cdr
;
276 void pretty_print(union value_pointer v
)
278 union value_pointer i
;
281 switch (pointer_type(v
)) {
283 printf("%d", get_integer(v
));
286 printf("%s", get_charseq_chars(v
));
289 printf("\"%s\"", get_charseq_chars(v
));
293 if (p
->car
.vp_opaque
== opaque_builtin_function
||
294 p
->car
.vp_opaque
== opaque_builtin_macro
||
295 p
->car
.vp_opaque
== opaque_user_function
||
296 p
->car
.vp_opaque
== opaque_user_macro
) {
297 printf("%s", p
->car
.vp_opaque
);
302 for (i
= v
; pointer_type(i
) == 3 && get_pair(i
) != NULL
; i
= get_pair(i
)->cdr
) {
303 if (i
.vp_pair
!= v
.vp_pair
) {
306 pretty_print(get_pair(i
)->car
);
308 if (pointer_type(i
) != 3) {
317 union value_pointer
builtin_eval(struct environment
*env
,
320 union value_pointer retval
, function
, args
;
321 union value_pointer
*arglink
;
322 char const *symbol_name
;
323 struct pair
*list
, *closure
;
324 struct pair
*subeval_arg
;
327 switch (pointer_type(rest
->car
)) {
333 symbol_name
= get_charseq_chars(rest
->car
);
335 for (i
= 0; i
< env
->variables_used
; i
++) {
336 if (strcmp(env
->variables
[i
]->name
->s
,
338 return env
->variables
[i
]->type_dot_value
;
342 } while (env
!= NULL
);
345 list
= get_pair(rest
->car
);
346 subeval_arg
= pair_new();
347 subeval_arg
->car
= list
->car
;
349 args
.vp_pair
= pair_new();
350 args
.vp_pair
->car
= builtin_eval(env
, subeval_arg
);
352 if (get_pair(args
.vp_pair
->car
)->car
.vp_opaque
== opaque_builtin_function
) {
353 arglink
= &args
.vp_pair
->cdr
;
355 for (list
= get_pair(list
->cdr
); list
!= NULL
; list
= get_pair(list
->cdr
)) {
356 union value_pointer element
;
358 subeval_arg
= pair_new();
359 subeval_arg
->car
= list
->car
;
361 element
.vp_pair
= pair_new();
362 element
.vp_pair
->car
= builtin_eval(env
, subeval_arg
);
363 pair_free(subeval_arg
);
366 pointer_mark(arglink
, 3);
367 arglink
= &element
.vp_pair
->cdr
;
370 args
.vp_pair
->cdr
= list
->cdr
;
373 pointer_mark(&args
, 3);
374 list
= get_pair(args
);
375 function
= list
->car
;
378 closure
= get_pair(function
);
379 if (closure
->car
.vp_opaque
== opaque_builtin_function
||
380 closure
->car
.vp_opaque
== opaque_builtin_macro
) {
381 retval
= (*closure
->cdr
.vp_builtin
)(env
, get_pair(args
));
390 union value_pointer
builtin_car(struct environment
*env
,
393 union value_pointer retval
;
395 retval
= get_pair(rest
->car
)->car
;
400 union value_pointer
builtin_cdr(struct environment
*env
,
403 union value_pointer retval
;
405 retval
= get_pair(rest
->car
)->cdr
;
410 union value_pointer
builtin_cons(struct environment
*env
,
413 union value_pointer retval
;
415 retval
.vp_pair
= pair_new();
416 retval
.vp_pair
->car
= rest
->car
;
417 retval
.vp_pair
->cdr
= get_pair(rest
->cdr
)->car
;
418 pointer_mark(&retval
, 3);
423 union value_pointer
builtin_lambda(struct environment
*env
,
426 union value_pointer retval
;
429 retval
.vp_pair
= rest
;
430 pointer_mark(&retval
, 3);
431 pretty_print(retval
);
433 retval
.vp_int
= 42 << 2;
434 pointer_mark(&retval
, 0);
439 union value_pointer
builtin_plus(struct environment
*env
,
442 union value_pointer retval
;
445 for (sum
= 0; rest
!= NULL
; rest
= get_pair(rest
->cdr
)) {
446 sum
+= get_integer(rest
->car
);
449 retval
.vp_int
= sum
<< 2;
450 pointer_mark(&retval
, 0);
461 union value_pointer form
;
462 union value_pointer constant_true
, constant_false
;
464 struct environment top_env
;
466 while (!feof(stdin
) && !ferror(stdin
)) {
469 if (bufused
>= bufsize
) {
470 buf
= realloc(buf
, bufsize
* 2 + 16);
474 bufsize
= bufsize
* 2 + 16;
476 n
= fread(buf
+ bufused
, 1, bufsize
- bufused
, stdin
);
480 top_env
.variables
= NULL
;
481 top_env
.variables_used
= 0;
482 top_env
.variables_size
= 0;
483 top_env
.parent
= NULL
;
485 constant_true
.vp_charseq
= charseq_new("#t", 2);
486 pointer_mark(&constant_true
, 1);
488 constant_false
.vp_charseq
= charseq_new("#f", 2);
489 pointer_mark(&constant_false
, 1);
491 binding_new(&top_env
, "#t", constant_true
);
492 binding_new(&top_env
, "#f", constant_false
);
494 binding_builtin(&top_env
, "car", opaque_builtin_function
, builtin_car
);
495 binding_builtin(&top_env
, "cdr", opaque_builtin_function
, builtin_cdr
);
496 binding_builtin(&top_env
, "cons", opaque_builtin_function
, builtin_cons
);
497 binding_builtin(&top_env
, "lambda", opaque_builtin_macro
, builtin_lambda
);
498 binding_builtin(&top_env
, "+", opaque_builtin_function
, builtin_plus
);
499 form
.vp_pair
= pair_new();
500 pointer_mark(&form
, 3);
502 formsize
= parse_forms(buf
, bufused
, &form
);
504 if (formsize
!= bufused
) {
505 printf("this stuff left over: \"%.*s\"\n",
506 bufused
- formsize
, buf
+ formsize
);
509 for (i
= get_pair(form
); i
!= NULL
; i
= get_pair(i
->cdr
)) {
515 pretty_print(i
->car
);
517 pretty_print(builtin_eval(&top_env
, rest
));