19 union value_pointer (*vp_builtin
)(struct stack_slot
*top_of_stack
,
20 struct environment
*env
,
21 union value_pointer rest
);
22 char const *vp_opaque
;
26 union value_pointer name
;
27 union value_pointer value
;
30 struct resource_pool
{
38 struct resource_pool variables
;
39 struct environment
*parent
;
43 union value_pointer car
;
44 union value_pointer cdr
;
49 struct environment
*env
;
50 union value_pointer rest
;
51 union value_pointer retval
;
52 union value_pointer function
;
53 union value_pointer sexpr
;
54 union value_pointer args
;
55 union value_pointer list
;
56 union value_pointer p
;
57 union value_pointer subeval_arg
;
58 union value_pointer
*arglink
;
59 struct environment
*call_env
;
64 struct stack_slot
*prev
;
67 void *resource_get(struct resource_pool
*rp
, int i
);
68 union value_pointer
builtin_lambda(struct stack_slot
*top_of_stack
,
69 struct environment
*env
,
70 union value_pointer rest
);
71 void gc_protect(union value_pointer v
);
72 union value_pointer
gc_unprotect(union value_pointer v
);
74 char const opaque_builtin_function
[] = "builtin-function";
75 char const opaque_builtin_macro
[] = "builtin-macro";
76 char const opaque_user_function
[] = "user-function";
77 char const opaque_user_macro
[] = "user-macro";
78 union value_pointer constant_true
, constant_false
, constant_nil
;
80 struct resource_pool bindings
, charseqs
, environments
, pairs
;
82 void pointer_mark(union value_pointer
*v
, int type
)
84 int pointer_bits
= v
->vp_int
;
89 v
->vp_int
= pointer_bits
;
92 int pointer_type(union value_pointer v
)
94 return (v
.vp_int
& 3);
97 int get_integer(union value_pointer v
)
99 return (v
.vp_int
>> 2);
102 struct pair
*get_pair(union value_pointer v
)
104 return resource_get(&pairs
, v
.vp_pair
>> 2);
107 struct charseq
*get_charseq(union value_pointer v
)
109 return resource_get(&charseqs
, v
.vp_charseq
>> 2);
112 char *get_charseq_chars(union value_pointer v
)
121 size_t get_charseq_len(union value_pointer v
)
130 void resource_pool_init(struct resource_pool
*rp
, size_t sz
)
132 rp
->resources
= NULL
;
133 rp
->resources_used
= 0;
134 rp
->resources_size
= 0;
138 void resource_pool_free(struct resource_pool
*rp
)
142 for (i
= 0; i
< rp
->resources_used
; i
++) {
143 free(rp
->resources
[i
]);
148 int resource_add(struct resource_pool
*rp
, void *r
)
152 if (rp
->resources_used
>= rp
->resources_size
) {
153 int newsize
= rp
->resources_used
* 2 + 16;
155 rp
->resources
= realloc(rp
->resources
,
156 sizeof (*rp
->resources
) * newsize
);
157 rp
->resources_size
= newsize
;
160 i
= rp
->resources_used
++;
161 rp
->resources
[i
] = r
;
166 int resource_count(struct resource_pool
*rp
)
168 return rp
->resources_used
;
171 void *resource_get(struct resource_pool
*rp
, int i
)
173 return rp
->resources
[i
];
176 void resource_free(struct resource_pool
*rp
, int i
)
178 free(rp
->resources
[i
]);
179 rp
->resources
[i
] = NULL
;
182 int resource_new_i(struct resource_pool
*rp
)
184 return resource_add(rp
, malloc(rp
->alloc_size
));
187 void *resource_new(struct resource_pool
*rp
)
191 i
= resource_new_i(rp
);
193 return rp
->resources
[i
];
196 struct environment
*environment_new(struct environment
*parent
)
198 struct environment
*env
;
200 env
= resource_new(&environments
);
201 resource_pool_init(&env
->variables
, 0);
202 env
->parent
= parent
;
207 void environment_free(struct environment
*env
)
209 resource_pool_free(&env
->variables
);
213 union value_pointer
charseq_new(char const *s
, size_t len
, int kind
)
215 union value_pointer retval
;
221 for (i
= 0; i
< resource_count(&charseqs
); i
++) {
222 cs
= resource_get(&charseqs
, i
);
223 if (cs
&& len
== cs
->len
&& strncmp(s
, cs
->s
, len
) == 0) {
224 retval
.vp_charseq
= i
<< 2;
225 pointer_mark(&retval
, kind
);
232 retval
.vp_charseq
= resource_new_i(&charseqs
) << 2;
233 pointer_mark(&retval
, kind
);
235 cs
= get_charseq(retval
);
237 cs
->s
= malloc(len
+ 1);
238 memcpy(cs
->s
, s
, len
);
245 union value_pointer
pair_new(void)
247 union value_pointer retval
;
249 retval
.vp_pair
= resource_new_i(&pairs
) << 2;
250 pointer_mark(&retval
, 3);
251 get_pair(retval
)->cdr
= constant_nil
;
252 get_pair(retval
)->gc
= 2;
257 union value_pointer
lisp_car(union value_pointer v
)
259 return get_pair(v
)->car
;
262 union value_pointer
lisp_cdr(union value_pointer v
)
264 return get_pair(v
)->cdr
;
267 union value_pointer
lisp_cons(union value_pointer left
, union value_pointer right
)
269 union value_pointer retval
;
272 get_pair(retval
)->car
= left
;
273 get_pair(retval
)->cdr
= right
;
274 pointer_mark(&retval
, 3);
276 if (left
.vp_opaque
!= opaque_builtin_function
&&
277 left
.vp_opaque
!= opaque_builtin_macro
) {
278 if (left
.vp_opaque
!= opaque_user_function
&&
279 left
.vp_opaque
!= opaque_user_macro
) {
288 union value_pointer
lisp_integer(int n
)
290 union value_pointer retval
;
292 retval
.vp_int
= n
<< 2;
293 pointer_mark(&retval
, 0);
298 union value_pointer
lisp_opaque(char const *cookie
)
300 union value_pointer retval
;
302 retval
.vp_opaque
= cookie
;
307 union value_pointer
lisp_builtin(union value_pointer (*builtin
)(struct stack_slot
*top_of_stack
,
308 struct environment
*env
,
309 union value_pointer rest
))
311 union value_pointer retval
;
313 retval
.vp_builtin
= builtin
;
318 struct binding
*binding_new(struct environment
*env
,
320 union value_pointer value
)
324 b
= resource_new(&bindings
);
325 b
->name
= charseq_new(name
, strlen(name
), 1);
328 resource_add(&env
->variables
, b
);
330 gc_unprotect(b
->name
);
331 gc_unprotect(b
->value
);
336 union value_pointer
builtin_new(char const *opaque_type
,
337 union value_pointer (*builtin
)(struct stack_slot
*top_of_stack
,
338 struct environment
*env
,
339 union value_pointer rest
))
341 return lisp_cons(lisp_opaque(opaque_type
),
342 lisp_builtin(builtin
));
345 size_t parse_word(union value_pointer
*vp
, char const *buf
, size_t len
)
350 for (n
= 0, i
= 0; i
< len
; i
++) {
351 if (buf
[i
] < '0' || buf
[i
] > '9') {
354 n
= n
*10 + buf
[i
] - '0';
367 for (i
++; i
< len
; i
++) {
380 *vp
= charseq_new(buf
, i
, 1);
390 size_t parse_string(union value_pointer
*vp
, char const *buf
, size_t len
)
396 for (backslash
= n
= 0, i
= 1; i
< len
; i
++) {
400 } else if (buf
[i
] == '"') {
402 } else if (buf
[i
] == '\\') {
410 *vp
= charseq_new(buf
+ 1, n
, 2);
413 for (backslash
= 0, i
= 1, s
= get_charseq_chars(*vp
); i
< len
; i
++) {
424 } else if (buf
[i
] == '\\') {
434 size_t parse_forms(char const *buf
, size_t len
, union value_pointer
*form
)
439 for (i
= 0; i
< len
; i
++) {
440 char const c
= buf
[i
];
441 union value_pointer u
, v
;
448 n
= parse_forms(buf
+ i
+ 1, len
- i
- 1, &u
) + 1;
453 v
= lisp_cons(u
, constant_nil
);
456 form
= &get_pair(*form
)->cdr
;
466 n
= parse_string(&get_pair(v
)->car
, buf
+ i
, len
- i
);
470 pointer_mark(form
, 3);
471 form
= &get_pair(v
)->cdr
;
474 n
= parse_word(&u
, buf
+ i
, len
- i
);
475 if (pointer_type(u
) == 1 &&
476 strcmp(get_charseq_chars(u
), ".") == 0) {
482 *form
= lisp_cons(u
, constant_nil
);
484 form
= &get_pair(*form
)->cdr
;
499 void pretty_print(union value_pointer v
)
501 union value_pointer i
;
504 switch (pointer_type(v
)) {
506 printf("%d", get_integer(v
));
509 printf("%s", get_charseq_chars(v
));
512 printf("\"%s\"", get_charseq_chars(v
));
516 if (p
!= get_pair(constant_nil
) &&
517 (p
->car
.vp_opaque
== opaque_builtin_function
||
518 p
->car
.vp_opaque
== opaque_builtin_macro
||
519 p
->car
.vp_opaque
== opaque_user_function
||
520 p
->car
.vp_opaque
== opaque_user_macro
)) {
521 printf("%s", p
->car
.vp_opaque
);
527 pointer_type(i
) == 3 && get_pair(i
) != get_pair(constant_nil
);
529 if (i
.vp_pair
!= v
.vp_pair
) {
532 pretty_print(lisp_car(i
));
534 if (pointer_type(i
) != 3) {
543 struct stack_slot
*stack_call(struct stack_slot
*top_of_stack
,
544 struct environment
*env
,
545 union value_pointer rest
)
547 struct stack_slot
*slot
;
549 slot
= malloc(sizeof (*slot
));
550 slot
->evaluating
= 1;
551 slot
->return_path
= 4040;
554 slot
->prev
= top_of_stack
;
560 struct stack_slot
*stack_return(struct stack_slot
*top_of_stack
)
562 struct stack_slot
*slot
;
564 slot
= top_of_stack
->prev
;
571 union value_pointer
eval_symbol(struct environment
*env
, union value_pointer sym
)
573 char const *symbol_name
;
576 symbol_name
= get_charseq_chars(sym
);
578 for (i
= 0; i
< resource_count(&env
->variables
); i
++) {
581 b
= resource_get(&env
->variables
, i
);
582 if (strcmp(get_charseq_chars(b
->name
), symbol_name
) == 0) {
587 } while (env
!= NULL
);
592 union value_pointer
builtin_eval(struct stack_slot
*caller
,
593 struct environment
*env_toplevel
,
594 union value_pointer rest_toplevel
)
596 struct stack_slot
*top_of_stack
;
597 union value_pointer element
;
598 union value_pointer retval
;
599 struct pair
*closure
;
601 top_of_stack
= stack_call(caller
, env_toplevel
, rest_toplevel
);
602 top_of_stack
->return_path
= 0;
605 if (top_of_stack
->evaluating
) {
606 switch (pointer_type(lisp_car(top_of_stack
->rest
))) {
609 top_of_stack
->retval
= lisp_car(top_of_stack
->rest
);
612 top_of_stack
->retval
= eval_symbol(top_of_stack
->env
,
613 lisp_car(top_of_stack
->rest
));
616 top_of_stack
->list
= lisp_car(top_of_stack
->rest
);
617 top_of_stack
->subeval_arg
= lisp_cons(lisp_car(top_of_stack
->list
), constant_nil
);
619 top_of_stack
= stack_call(top_of_stack
,
621 top_of_stack
->subeval_arg
);
622 top_of_stack
->return_path
= 3;
626 switch (top_of_stack
->return_path
) {
628 retval
= top_of_stack
->retval
;
629 stack_return(top_of_stack
);
632 retval
= top_of_stack
->retval
;
633 top_of_stack
= stack_return(top_of_stack
);
634 top_of_stack
->retval
= retval
;
635 gc_unprotect(top_of_stack
->sexpr
);
636 top_of_stack
->p
= lisp_cdr(top_of_stack
->p
);
637 if (get_pair(top_of_stack
->p
) != get_pair(constant_nil
)) {
638 top_of_stack
->sexpr
= lisp_cons(lisp_car(top_of_stack
->p
), constant_nil
);
639 top_of_stack
= stack_call(top_of_stack
,
640 top_of_stack
->call_env
,
641 top_of_stack
->sexpr
);
642 top_of_stack
->return_path
= 1;
645 environment_free(top_of_stack
->call_env
);
646 gc_unprotect(top_of_stack
->list
);
649 top_of_stack
->prev
->args
= lisp_cons(top_of_stack
->retval
, constant_nil
);
650 top_of_stack
= stack_return(top_of_stack
);
651 gc_unprotect(top_of_stack
->subeval_arg
);
653 if (lisp_car(lisp_car(top_of_stack
->args
)).vp_opaque
== opaque_builtin_function
||
654 lisp_car(lisp_car(top_of_stack
->args
)).vp_opaque
== opaque_user_function
) {
655 top_of_stack
->arglink
= &get_pair(top_of_stack
->args
)->cdr
;
657 top_of_stack
->list
= lisp_cdr(top_of_stack
->list
);
661 element
= lisp_cons(top_of_stack
->retval
, constant_nil
);
662 top_of_stack
= stack_return(top_of_stack
);
663 gc_unprotect(top_of_stack
->subeval_arg
);
665 *top_of_stack
->arglink
= element
;
666 top_of_stack
->arglink
= &get_pair(element
)->cdr
;
668 gc_unprotect(element
);
669 top_of_stack
->list
= lisp_cdr(top_of_stack
->list
);
671 if (get_pair(top_of_stack
->list
) != get_pair(constant_nil
)) {
672 top_of_stack
->subeval_arg
= lisp_cons(lisp_car(top_of_stack
->list
),
675 top_of_stack
= stack_call(top_of_stack
,
677 top_of_stack
->subeval_arg
);
678 top_of_stack
->return_path
= 4;
682 get_pair(top_of_stack
->args
)->cdr
= lisp_cdr(top_of_stack
->list
);
685 top_of_stack
->list
= top_of_stack
->args
;
686 top_of_stack
->function
= lisp_car(top_of_stack
->list
);
687 top_of_stack
->args
= lisp_cdr(top_of_stack
->list
);
689 closure
= get_pair(top_of_stack
->function
);
690 if (closure
->car
.vp_opaque
== opaque_builtin_function
||
691 closure
->car
.vp_opaque
== opaque_builtin_macro
) {
692 top_of_stack
= stack_call(top_of_stack
,
695 top_of_stack
->return_path
= 6;
696 top_of_stack
->retval
= (*closure
->cdr
.vp_builtin
)(top_of_stack
,
697 top_of_stack
->prev
->env
,
698 top_of_stack
->prev
->args
);
700 } else if (closure
->car
.vp_opaque
== opaque_user_function
) {
701 union value_pointer formal_args
;
702 union value_pointer function_body
;
704 top_of_stack
->p
= closure
->cdr
;
705 formal_args
= lisp_car(top_of_stack
->p
);
706 function_body
= lisp_cdr(top_of_stack
->p
);
708 top_of_stack
->call_env
= environment_new(top_of_stack
->env
);
709 for (top_of_stack
->p
= formal_args
;
710 (pointer_type(top_of_stack
->p
) == 3 &&
711 get_pair(top_of_stack
->p
) != get_pair(constant_nil
) &&
712 get_pair(top_of_stack
->args
) != get_pair(constant_nil
));
713 top_of_stack
->p
= lisp_cdr(top_of_stack
->p
),
714 top_of_stack
->args
= lisp_cdr(top_of_stack
->args
)) {
715 binding_new(top_of_stack
->call_env
,
716 get_charseq_chars(lisp_car(top_of_stack
->p
)),
717 lisp_car(top_of_stack
->args
));
719 if (pointer_type(top_of_stack
->p
) == 1) {
720 binding_new(top_of_stack
->call_env
,
721 get_charseq_chars(top_of_stack
->p
),
725 top_of_stack
->p
= function_body
;
726 if (get_pair(top_of_stack
->p
) != get_pair(constant_nil
)) {
727 top_of_stack
->sexpr
= lisp_cons(lisp_car(top_of_stack
->p
), constant_nil
);
728 top_of_stack
= stack_call(top_of_stack
,
729 top_of_stack
->call_env
,
730 top_of_stack
->sexpr
);
731 top_of_stack
->return_path
= 1;
734 environment_free(top_of_stack
->call_env
);
737 gc_unprotect(top_of_stack
->list
);
740 retval
= top_of_stack
->retval
;
741 top_of_stack
= stack_return(top_of_stack
);
742 top_of_stack
->retval
= retval
;
743 gc_unprotect(top_of_stack
->list
);
746 top_of_stack
->evaluating
= 0;
750 union value_pointer
builtin_string_to_list(struct stack_slot
*top_of_stack
,
751 struct environment
*env
,
752 union value_pointer rest
)
754 union value_pointer retval
;
755 union value_pointer
*v
;
759 s
= get_charseq_chars(lisp_car(rest
));
760 n
= get_charseq_len(lisp_car(rest
));
761 retval
= lisp_cons(constant_nil
, constant_nil
);
762 v
= &get_pair(retval
)->cdr
;
763 for (i
= 0; i
< n
; i
++) {
764 *v
= lisp_cons(lisp_integer(s
[i
]), constant_nil
);
766 v
= &get_pair(*v
)->cdr
;
768 v
= &get_pair(retval
)->cdr
;
770 gc_unprotect(retval
);
776 union value_pointer
builtin_car(struct stack_slot
*top_of_stack
,
777 struct environment
*env
,
778 union value_pointer rest
)
780 return lisp_car(lisp_car(rest
));
783 union value_pointer
builtin_cdr(struct stack_slot
*top_of_stack
,
784 struct environment
*env
,
785 union value_pointer rest
)
787 return lisp_cdr(lisp_car(rest
));
790 union value_pointer
builtin_cons(struct stack_slot
*top_of_stack
,
791 struct environment
*env
,
792 union value_pointer rest
)
794 return gc_unprotect(lisp_cons(lisp_car(rest
), lisp_car(lisp_cdr(rest
))));
797 union value_pointer
builtin_eq_p(struct stack_slot
*top_of_stack
,
798 struct environment
*env
,
799 union value_pointer rest
)
801 union value_pointer a
, b
;
804 b
= lisp_car(lisp_cdr(rest
));
806 if (pointer_type(a
) != pointer_type(b
)) {
807 return constant_false
;
810 switch (pointer_type(a
)) {
812 if (get_integer(a
) != get_integer(b
)) {
813 return constant_false
;
818 if (get_charseq(a
) != get_charseq(b
)) {
819 return constant_false
;
823 if (a
.vp_pair
!= b
.vp_pair
) {
824 return constant_false
;
829 return constant_true
;
832 union value_pointer
builtin_display(struct stack_slot
*top_of_stack
,
833 struct environment
*env
,
834 union value_pointer rest
)
836 pretty_print(lisp_car(rest
));
838 return constant_true
;
841 union value_pointer
builtin_list_p_helper(union value_pointer v
)
843 if (pointer_type(v
) == 3) {
844 if (get_pair(v
) == get_pair(constant_nil
)) {
845 return constant_true
;
847 return builtin_list_p_helper(lisp_cdr(v
));
850 return constant_false
;
854 union value_pointer
builtin_list_p(struct stack_slot
*top_of_stack
,
855 struct environment
*env
,
856 union value_pointer rest
)
858 return builtin_list_p_helper(lisp_car(rest
));
861 union value_pointer
builtin_define(struct stack_slot
*top_of_stack
,
862 struct environment
*env
,
863 union value_pointer rest
)
865 union value_pointer name_and_args
, definition
;
866 union value_pointer lambda_args
, function
;
868 name_and_args
= lisp_car(rest
);
869 definition
= lisp_car(lisp_cdr(rest
));
871 lambda_args
= lisp_cons(lisp_cdr(name_and_args
), lisp_cons(definition
, constant_nil
));
873 function
= builtin_lambda(top_of_stack
, env
, lambda_args
);
874 gc_unprotect(lambda_args
);
876 binding_new(env
, get_charseq_chars(lisp_car(name_and_args
)), function
);
881 union value_pointer
builtin_if(struct stack_slot
*top_of_stack
,
882 struct environment
*env
,
883 union value_pointer rest
)
885 union value_pointer retval
;
886 union value_pointer condition
, consequent
, alternate
;
887 union value_pointer v
;
889 retval
= constant_nil
;
891 condition
= lisp_car(rest
);
892 consequent
= lisp_car(lisp_cdr(rest
));
893 alternate
= lisp_cdr(lisp_cdr(rest
));
895 v
= lisp_cons(condition
, constant_nil
);
896 condition
= builtin_eval(top_of_stack
, env
, v
);
899 if (pointer_type(condition
) != 1 ||
900 condition
.vp_charseq
!= constant_false
.vp_charseq
) {
901 v
= lisp_cons(consequent
, constant_nil
);
902 } else if (get_pair(alternate
) != get_pair(constant_nil
)) {
903 v
= lisp_cons(lisp_car(alternate
), constant_nil
);
908 gc_unprotect(condition
);
909 retval
= builtin_eval(top_of_stack
, env
, v
);
915 union value_pointer
builtin_lambda(struct stack_slot
*top_of_stack
,
916 struct environment
*env
,
917 union value_pointer rest
)
919 union value_pointer retval
;
921 retval
= lisp_cons(lisp_opaque(opaque_user_function
), rest
);
922 pointer_mark(&retval
, 3);
927 union value_pointer
builtin_quote(struct stack_slot
*top_of_stack
,
928 struct environment
*env
,
929 union value_pointer rest
)
931 return lisp_car(rest
);
934 union value_pointer
builtin_plus(struct stack_slot
*top_of_stack
,
935 struct environment
*env
,
936 union value_pointer rest
)
938 union value_pointer retval
;
941 for (sum
= 0; get_pair(rest
) != get_pair(constant_nil
); rest
= lisp_cdr(rest
)) {
942 sum
+= get_integer(lisp_car(rest
));
945 retval
.vp_int
= sum
<< 2;
946 pointer_mark(&retval
, 0);
951 union value_pointer
builtin_minus(struct stack_slot
*top_of_stack
,
952 struct environment
*env
,
953 union value_pointer rest
)
955 union value_pointer retval
;
956 union value_pointer lhs
;
959 lhs
= lisp_car(rest
);
960 rest
= lisp_cdr(rest
);
961 difference
= get_integer(lhs
);
962 if (get_pair(rest
) != get_pair(constant_nil
)) {
963 for (difference
= get_integer(lhs
);
964 get_pair(rest
) != get_pair(constant_nil
);
965 rest
= lisp_cdr(rest
)) {
966 difference
-= get_integer(lisp_car(rest
));
969 difference
= -get_integer(lhs
);
972 retval
.vp_int
= difference
<< 2;
973 pointer_mark(&retval
, 0);
977 void gc_mark(union value_pointer v
)
979 switch (pointer_type(v
)) {
983 get_charseq(v
)->gc
|= 1;
991 if (p
->car
.vp_opaque
!= opaque_builtin_function
&&
992 p
->car
.vp_opaque
!= opaque_builtin_macro
) {
993 if (p
->car
.vp_opaque
!= opaque_user_function
&&
994 p
->car
.vp_opaque
!= opaque_user_macro
) {
995 gc_mark(lisp_car(v
));
997 gc_mark(lisp_cdr(v
));
1003 void gc_protect(union value_pointer v
)
1005 switch (pointer_type(v
)) {
1009 get_charseq(v
)->gc
|= 2;
1019 union value_pointer
gc_unprotect(union value_pointer v
)
1021 switch (pointer_type(v
)) {
1025 get_charseq(v
)->gc
&= ~2;
1036 void gc_unmark_all(void)
1040 for (j
= 0; j
< resource_count(&charseqs
); j
++) {
1041 struct charseq
*cs
= resource_get(&charseqs
, j
);
1046 for (j
= 0; j
< resource_count(&pairs
); j
++) {
1047 struct pair
*p
= resource_get(&pairs
, j
);
1052 for (j
= 0; j
< resource_count(&pairs
); j
++) {
1053 struct pair
*p
= resource_get(&pairs
, j
);
1055 if (p
->car
.vp_opaque
!= opaque_builtin_function
&&
1056 p
->car
.vp_opaque
!= opaque_builtin_macro
) {
1057 if (p
->car
.vp_opaque
!= opaque_user_function
&&
1058 p
->car
.vp_opaque
!= opaque_user_macro
) {
1067 void gc_collect(struct environment
*env
)
1073 for (; env
; env
= env
->parent
) {
1074 for (j
= 0; j
< resource_count(&env
->variables
); j
++) {
1075 struct binding
*b
= resource_get(&env
->variables
, j
);
1084 for (j
= 0; j
< resource_count(&charseqs
); j
++) {
1085 struct charseq
*cs
= resource_get(&charseqs
, j
);
1086 if (cs
&& cs
->gc
== 0) {
1088 resource_free(&charseqs
, j
);
1091 for (j
= 0; j
< resource_count(&pairs
); j
++) {
1092 struct pair
*p
= resource_get(&pairs
, j
);
1093 if (p
&& p
->gc
== 0) {
1094 resource_free(&pairs
, j
);
1105 union value_pointer i
, form
;
1106 struct environment
*top_env
;
1109 resource_pool_init(&bindings
, sizeof (struct binding
));
1110 resource_pool_init(&charseqs
, sizeof (struct charseq
));
1111 resource_pool_init(&environments
, sizeof (struct environment
));
1112 resource_pool_init(&pairs
, sizeof (struct pair
));
1114 constant_nil
= pair_new();
1115 get_pair(constant_nil
)->car
= constant_nil
;
1116 get_pair(constant_nil
)->cdr
= constant_nil
;
1118 while (!feof(stdin
) && !ferror(stdin
)) {
1121 if (bufused
>= bufsize
) {
1122 buf
= realloc(buf
, bufsize
* 2 + 16);
1126 bufsize
= bufsize
* 2 + 16;
1128 n
= fread(buf
+ bufused
, 1, bufsize
- bufused
, stdin
);
1132 top_env
= environment_new(NULL
);
1134 constant_true
= charseq_new("#t", 2, 1);
1135 constant_false
= charseq_new("#f", 2, 1);
1137 binding_new(top_env
, "#t", constant_true
);
1138 binding_new(top_env
, "#f", constant_false
);
1140 binding_new(top_env
, "car", builtin_new(opaque_builtin_function
, builtin_car
));
1141 binding_new(top_env
, "cdr", builtin_new(opaque_builtin_function
, builtin_cdr
));
1142 binding_new(top_env
, "cons", builtin_new(opaque_builtin_function
, builtin_cons
));
1143 binding_new(top_env
, "eq?", builtin_new(opaque_builtin_function
, builtin_eq_p
));
1144 binding_new(top_env
, "display", builtin_new(opaque_builtin_function
, builtin_display
));
1145 binding_new(top_env
, "list?", builtin_new(opaque_builtin_function
, builtin_list_p
));
1146 binding_new(top_env
, "primitive-eval", builtin_new(opaque_builtin_function
, builtin_eval
));
1147 binding_new(top_env
, "string->list", builtin_new(opaque_builtin_function
, builtin_string_to_list
));
1149 binding_new(top_env
, "define", builtin_new(opaque_builtin_macro
, builtin_define
));
1150 binding_new(top_env
, "if", builtin_new(opaque_builtin_macro
, builtin_if
));
1151 binding_new(top_env
, "lambda", builtin_new(opaque_builtin_macro
, builtin_lambda
));
1152 binding_new(top_env
, "quote", builtin_new(opaque_builtin_macro
, builtin_quote
));
1154 binding_new(top_env
, "+", builtin_new(opaque_builtin_function
, builtin_plus
));
1155 binding_new(top_env
, "-", builtin_new(opaque_builtin_function
, builtin_minus
));
1157 form
= lisp_cons(constant_nil
, constant_nil
);
1159 formsize
= parse_forms(buf
, bufused
, &get_pair(form
)->cdr
);
1161 form
= lisp_cdr(form
);
1165 if (formsize
!= bufused
) {
1166 printf("this stuff left over: \"%.*s\"\n",
1167 bufused
- formsize
, buf
+ formsize
);
1170 for (i
= form
; get_pair(i
) != get_pair(constant_nil
); i
= form
) {
1171 union value_pointer rest
, retval
;
1173 rest
= lisp_cons(lisp_car(i
), constant_nil
);
1175 pretty_print(lisp_car(i
));
1177 retval
= builtin_eval(NULL
, top_env
, rest
);
1179 pretty_print(retval
);
1180 gc_unprotect(retval
);
1187 gc_collect(top_env
);
1190 environment_free(top_env
);
1192 gc_unprotect(constant_nil
);
1195 resource_pool_free(&charseqs
);
1196 resource_pool_free(&pairs
);
1197 free(bindings
.resources
);
1198 free(environments
.resources
);