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
;
31 struct resource_pool
{
39 struct resource_pool variables
;
40 struct environment
*parent
;
45 union value_pointer car
;
46 union value_pointer cdr
;
51 struct environment
*env
;
52 union value_pointer rest
;
53 union value_pointer retval
;
54 union value_pointer function
;
55 union value_pointer sexpr
;
56 union value_pointer args
;
57 union value_pointer list
;
58 union value_pointer p
;
59 union value_pointer subeval_arg
;
60 union value_pointer
*arglink
;
61 struct environment
*call_env
;
66 struct stack_slot
*prev
;
69 void *resource_get(struct resource_pool
*rp
, int i
);
70 union value_pointer
builtin_lambda(struct stack_slot
*top_of_stack
,
71 struct environment
*env
,
72 union value_pointer rest
);
73 void gc_protect(union value_pointer v
);
74 union value_pointer
gc_unprotect(union value_pointer v
);
76 char const opaque_builtin_function
[] = "builtin-function";
77 char const opaque_builtin_macro
[] = "builtin-macro";
78 char const opaque_user_function
[] = "user-function";
79 char const opaque_user_macro
[] = "user-macro";
80 union value_pointer constant_true
, constant_false
, constant_nil
;
82 struct resource_pool bindings
, charseqs
, environments
, pairs
, stack_slots
;
84 void pointer_mark(union value_pointer
*v
, int type
)
86 int pointer_bits
= v
->vp_int
;
91 v
->vp_int
= pointer_bits
;
94 int pointer_type(union value_pointer v
)
96 return (v
.vp_int
& 3);
99 int get_integer(union value_pointer v
)
101 return (v
.vp_int
>> 2);
104 struct pair
*get_pair(union value_pointer v
)
106 return resource_get(&pairs
, v
.vp_pair
>> 2);
109 struct charseq
*get_charseq(union value_pointer v
)
111 return resource_get(&charseqs
, v
.vp_charseq
>> 2);
114 char *get_charseq_chars(union value_pointer v
)
123 size_t get_charseq_len(union value_pointer v
)
132 void resource_pool_init(struct resource_pool
*rp
, size_t sz
)
134 rp
->resources
= NULL
;
135 rp
->resources_used
= 0;
136 rp
->resources_size
= 0;
140 void resource_pool_free(struct resource_pool
*rp
)
144 for (i
= 0; i
< rp
->resources_used
; i
++) {
145 free(rp
->resources
[i
]);
150 int resource_add(struct resource_pool
*rp
, void *r
)
154 if (rp
->resources_used
>= rp
->resources_size
) {
155 int newsize
= rp
->resources_used
* 2 + 16;
157 for (i
= 0; i
< rp
->resources_used
; i
++) {
158 if (rp
->resources
[i
] == NULL
) {
159 rp
->resources
[i
] = r
;
164 rp
->resources
= realloc(rp
->resources
,
165 sizeof (*rp
->resources
) * newsize
);
166 rp
->resources_size
= newsize
;
169 i
= rp
->resources_used
++;
170 rp
->resources
[i
] = r
;
175 int resource_count(struct resource_pool
*rp
)
177 return rp
->resources_used
;
180 void *resource_get(struct resource_pool
*rp
, int i
)
182 return rp
->resources
[i
];
185 void resource_free(struct resource_pool
*rp
, int i
)
187 free(rp
->resources
[i
]);
188 rp
->resources
[i
] = NULL
;
191 int resource_new_i(struct resource_pool
*rp
)
193 return resource_add(rp
, malloc(rp
->alloc_size
));
196 struct environment
*environment_new(struct environment
*parent
)
198 struct environment
*env
;
201 envnum
= resource_new_i(&environments
);
202 env
= resource_get(&environments
, envnum
);
203 env
->resource_num
= envnum
;
204 resource_pool_init(&env
->variables
, 0);
205 env
->parent
= parent
;
210 void environment_free(struct environment
*env
)
212 resource_pool_free(&env
->variables
);
213 resource_free(&environments
, env
->resource_num
);
216 union value_pointer
charseq_new(char const *s
, size_t len
, size_t size
, int kind
)
218 union value_pointer retval
;
224 for (i
= 0; i
< resource_count(&charseqs
); i
++) {
225 cs
= resource_get(&charseqs
, i
);
226 if (cs
&& len
== cs
->len
&& strncmp(s
, cs
->s
, len
) == 0) {
227 retval
.vp_charseq
= i
<< 2;
228 pointer_mark(&retval
, kind
);
235 retval
.vp_charseq
= resource_new_i(&charseqs
) << 2;
236 pointer_mark(&retval
, kind
);
238 cs
= get_charseq(retval
);
240 cs
->s
= malloc(size
+ 1);
241 memcpy(cs
->s
, s
, len
);
248 union value_pointer
pair_new(void)
250 union value_pointer retval
;
252 retval
.vp_pair
= resource_new_i(&pairs
) << 2;
253 pointer_mark(&retval
, 3);
254 get_pair(retval
)->cdr
= constant_nil
;
255 get_pair(retval
)->gc
= 2;
260 union value_pointer
lisp_car(union value_pointer v
)
262 return get_pair(v
)->car
;
265 union value_pointer
lisp_cdr(union value_pointer v
)
267 return get_pair(v
)->cdr
;
270 union value_pointer
lisp_cons(union value_pointer left
, union value_pointer right
)
272 union value_pointer retval
;
275 get_pair(retval
)->car
= left
;
276 get_pair(retval
)->cdr
= right
;
277 pointer_mark(&retval
, 3);
279 if (left
.vp_opaque
!= opaque_builtin_function
&&
280 left
.vp_opaque
!= opaque_builtin_macro
) {
281 if (left
.vp_opaque
!= opaque_user_function
&&
282 left
.vp_opaque
!= opaque_user_macro
) {
291 union value_pointer
lisp_integer(int n
)
293 union value_pointer retval
;
295 retval
.vp_int
= n
<< 2;
296 pointer_mark(&retval
, 0);
301 union value_pointer
lisp_opaque(char const *cookie
)
303 union value_pointer retval
;
305 retval
.vp_opaque
= cookie
;
310 union value_pointer
lisp_builtin(union value_pointer (*builtin
)(struct stack_slot
*top_of_stack
,
311 struct environment
*env
,
312 union value_pointer rest
))
314 union value_pointer retval
;
316 retval
.vp_builtin
= builtin
;
321 struct binding
*binding_new(struct environment
*env
,
323 union value_pointer value
)
328 bnum
= resource_new_i(&bindings
);
329 b
= resource_get(&bindings
, bnum
);
330 b
->resource_num
= bnum
;
331 b
->name
= charseq_new(name
, strlen(name
), strlen(name
), 1);
334 resource_add(&env
->variables
, b
);
336 gc_unprotect(b
->name
);
337 gc_unprotect(b
->value
);
342 union value_pointer
builtin_new(char const *opaque_type
,
343 union value_pointer (*builtin
)(struct stack_slot
*top_of_stack
,
344 struct environment
*env
,
345 union value_pointer rest
))
347 return lisp_cons(lisp_opaque(opaque_type
),
348 lisp_builtin(builtin
));
351 size_t parse_word(union value_pointer
*vp
, char const *buf
, size_t len
)
356 for (n
= 0, i
= 0; i
< len
; i
++) {
357 if (buf
[i
] < '0' || buf
[i
] > '9') {
360 n
= n
*10 + buf
[i
] - '0';
373 for (i
++; i
< len
; i
++) {
386 *vp
= charseq_new(buf
, i
, i
, 1);
396 size_t parse_string(union value_pointer
*vp
, char const *buf
, size_t len
)
402 for (backslash
= n
= 0, i
= 1; i
< len
; i
++) {
406 } else if (buf
[i
] == '"') {
408 } else if (buf
[i
] == '\\') {
416 *vp
= charseq_new(buf
+ 1, n
, n
, 2);
419 for (backslash
= 0, i
= 1, s
= get_charseq_chars(*vp
); i
< len
; i
++) {
430 } else if (buf
[i
] == '\\') {
440 size_t parse_forms(char const *buf
, size_t len
, union value_pointer
*form
)
445 for (i
= 0; i
< len
; i
++) {
446 char const c
= buf
[i
];
447 union value_pointer u
, v
;
454 n
= parse_forms(buf
+ i
+ 1, len
- i
- 1, &u
) + 1;
459 v
= lisp_cons(u
, constant_nil
);
462 form
= &get_pair(*form
)->cdr
;
472 n
= parse_string(&get_pair(v
)->car
, buf
+ i
, len
- i
);
476 pointer_mark(form
, 3);
477 form
= &get_pair(v
)->cdr
;
480 n
= parse_word(&u
, buf
+ i
, len
- i
);
481 if (pointer_type(u
) == 1 &&
482 strcmp(get_charseq_chars(u
), ".") == 0) {
488 *form
= lisp_cons(u
, constant_nil
);
490 form
= &get_pair(*form
)->cdr
;
505 void pretty_print(union value_pointer v
)
507 union value_pointer i
;
510 switch (pointer_type(v
)) {
512 printf("%d", get_integer(v
));
515 printf("%s", get_charseq_chars(v
));
518 printf("\"%s\"", get_charseq_chars(v
));
522 if (p
!= get_pair(constant_nil
) &&
523 (p
->car
.vp_opaque
== opaque_builtin_function
||
524 p
->car
.vp_opaque
== opaque_builtin_macro
||
525 p
->car
.vp_opaque
== opaque_user_function
||
526 p
->car
.vp_opaque
== opaque_user_macro
)) {
527 printf("%s", p
->car
.vp_opaque
);
533 pointer_type(i
) == 3 && get_pair(i
) != get_pair(constant_nil
);
535 if (i
.vp_pair
!= v
.vp_pair
) {
538 pretty_print(lisp_car(i
));
540 if (pointer_type(i
) != 3) {
549 struct stack_slot
*stack_call(struct stack_slot
*top_of_stack
,
550 struct environment
*env
,
551 union value_pointer rest
)
553 struct stack_slot
*slot
;
556 slotnum
= resource_new_i(&stack_slots
);
557 slot
= resource_get(&stack_slots
, slotnum
);
558 slot
->resource_num
= slotnum
;
559 slot
->evaluating
= 1;
560 slot
->return_path
= 4040;
563 slot
->prev
= top_of_stack
;
569 struct stack_slot
*stack_return(struct stack_slot
*top_of_stack
)
571 struct stack_slot
*slot
;
573 slot
= top_of_stack
->prev
;
575 resource_free(&stack_slots
, top_of_stack
->resource_num
);
580 union value_pointer
eval_symbol(struct environment
*env
, union value_pointer sym
)
582 char const *symbol_name
;
585 symbol_name
= get_charseq_chars(sym
);
587 for (i
= 0; i
< resource_count(&env
->variables
); i
++) {
590 b
= resource_get(&env
->variables
, i
);
591 if (strcmp(get_charseq_chars(b
->name
), symbol_name
) == 0) {
596 } while (env
!= NULL
);
601 union value_pointer
builtin_eval(struct stack_slot
*caller
,
602 struct environment
*env_toplevel
,
603 union value_pointer rest_toplevel
)
605 struct stack_slot
*top_of_stack
;
606 union value_pointer element
;
607 union value_pointer consequent
, alternate
;
608 union value_pointer retval
;
609 struct pair
*closure
;
611 top_of_stack
= stack_call(caller
, env_toplevel
, rest_toplevel
);
612 top_of_stack
->return_path
= 0;
615 if (top_of_stack
->evaluating
) {
616 switch (pointer_type(lisp_car(top_of_stack
->rest
))) {
619 top_of_stack
->retval
= lisp_car(top_of_stack
->rest
);
622 top_of_stack
->retval
= eval_symbol(top_of_stack
->env
,
623 lisp_car(top_of_stack
->rest
));
626 top_of_stack
->list
= lisp_car(top_of_stack
->rest
);
627 top_of_stack
->subeval_arg
= lisp_cons(lisp_car(top_of_stack
->list
), constant_nil
);
629 top_of_stack
= stack_call(top_of_stack
,
631 top_of_stack
->subeval_arg
);
632 top_of_stack
->return_path
= 3;
636 switch (top_of_stack
->return_path
) {
638 retval
= top_of_stack
->retval
;
639 stack_return(top_of_stack
);
642 retval
= top_of_stack
->retval
;
643 top_of_stack
= stack_return(top_of_stack
);
644 top_of_stack
->retval
= retval
;
645 gc_unprotect(top_of_stack
->sexpr
);
646 top_of_stack
->p
= lisp_cdr(top_of_stack
->p
);
647 if (get_pair(top_of_stack
->p
) != get_pair(constant_nil
)) {
648 top_of_stack
->sexpr
= lisp_cons(lisp_car(top_of_stack
->p
), constant_nil
);
649 if (get_pair(lisp_cdr(top_of_stack
->p
)) == get_pair(constant_nil
)) {
650 top_of_stack
->env
= top_of_stack
->call_env
;
651 top_of_stack
->rest
= top_of_stack
->sexpr
;
654 top_of_stack
= stack_call(top_of_stack
,
655 top_of_stack
->call_env
,
656 top_of_stack
->sexpr
);
657 top_of_stack
->return_path
= 1;
660 environment_free(top_of_stack
->call_env
);
661 gc_unprotect(top_of_stack
->list
);
664 top_of_stack
->prev
->args
= lisp_cons(top_of_stack
->retval
, constant_nil
);
665 top_of_stack
= stack_return(top_of_stack
);
666 gc_unprotect(top_of_stack
->subeval_arg
);
668 if (lisp_car(lisp_car(top_of_stack
->args
)).vp_opaque
== opaque_builtin_function
||
669 lisp_car(lisp_car(top_of_stack
->args
)).vp_opaque
== opaque_user_function
) {
670 top_of_stack
->arglink
= &get_pair(top_of_stack
->args
)->cdr
;
672 top_of_stack
->list
= lisp_cdr(top_of_stack
->list
);
676 element
= lisp_cons(top_of_stack
->retval
, constant_nil
);
677 top_of_stack
= stack_return(top_of_stack
);
678 gc_unprotect(top_of_stack
->subeval_arg
);
680 *top_of_stack
->arglink
= element
;
681 top_of_stack
->arglink
= &get_pair(element
)->cdr
;
683 gc_unprotect(element
);
684 top_of_stack
->list
= lisp_cdr(top_of_stack
->list
);
686 if (get_pair(top_of_stack
->list
) != get_pair(constant_nil
)) {
687 top_of_stack
->subeval_arg
= lisp_cons(lisp_car(top_of_stack
->list
),
690 top_of_stack
= stack_call(top_of_stack
,
692 top_of_stack
->subeval_arg
);
693 top_of_stack
->return_path
= 4;
697 get_pair(top_of_stack
->args
)->cdr
= lisp_cdr(top_of_stack
->list
);
700 top_of_stack
->list
= top_of_stack
->args
;
701 top_of_stack
->function
= lisp_car(top_of_stack
->list
);
702 top_of_stack
->args
= lisp_cdr(top_of_stack
->list
);
704 closure
= get_pair(top_of_stack
->function
);
705 if (closure
->car
.vp_opaque
== opaque_builtin_function
||
706 closure
->car
.vp_opaque
== opaque_builtin_macro
) {
707 top_of_stack
= stack_call(top_of_stack
,
710 top_of_stack
->return_path
= 6;
711 top_of_stack
->retval
= (*closure
->cdr
.vp_builtin
)(top_of_stack
,
712 top_of_stack
->prev
->env
,
713 top_of_stack
->prev
->args
);
715 } else if (closure
->car
.vp_opaque
== opaque_user_function
) {
716 union value_pointer function_env
;
717 union value_pointer formal_args
;
718 union value_pointer function_body
;
719 struct environment
*lambda_env
;
721 top_of_stack
->p
= closure
->cdr
;
722 function_env
= lisp_car(top_of_stack
->p
);
723 formal_args
= lisp_car(lisp_cdr(top_of_stack
->p
));
724 function_body
= lisp_cdr(lisp_cdr(top_of_stack
->p
));
726 lambda_env
= resource_get(&environments
,
727 get_integer(function_env
));
728 top_of_stack
->call_env
= environment_new(lambda_env
);
729 for (top_of_stack
->p
= formal_args
;
730 (pointer_type(top_of_stack
->p
) == 3 &&
731 get_pair(top_of_stack
->p
) != get_pair(constant_nil
) &&
732 get_pair(top_of_stack
->args
) != get_pair(constant_nil
));
733 top_of_stack
->p
= lisp_cdr(top_of_stack
->p
),
734 top_of_stack
->args
= lisp_cdr(top_of_stack
->args
)) {
735 binding_new(top_of_stack
->call_env
,
736 get_charseq_chars(lisp_car(top_of_stack
->p
)),
737 lisp_car(top_of_stack
->args
));
739 if (pointer_type(top_of_stack
->p
) == 1) {
740 binding_new(top_of_stack
->call_env
,
741 get_charseq_chars(top_of_stack
->p
),
745 top_of_stack
->p
= function_body
;
746 if (get_pair(top_of_stack
->p
) != get_pair(constant_nil
)) {
747 top_of_stack
->sexpr
= lisp_cons(lisp_car(top_of_stack
->p
), constant_nil
);
748 if (get_pair(lisp_cdr(top_of_stack
->p
)) == get_pair(constant_nil
)) {
749 top_of_stack
->env
= top_of_stack
->call_env
;
750 top_of_stack
->rest
= top_of_stack
->sexpr
;
753 top_of_stack
= stack_call(top_of_stack
,
754 top_of_stack
->call_env
,
755 top_of_stack
->sexpr
);
756 top_of_stack
->return_path
= 1;
759 environment_free(top_of_stack
->call_env
);
762 gc_unprotect(top_of_stack
->list
);
765 retval
= top_of_stack
->retval
;
766 top_of_stack
= stack_return(top_of_stack
);
767 top_of_stack
->retval
= retval
;
768 gc_unprotect(top_of_stack
->list
);
771 top_of_stack
->return_path
= 8;
772 top_of_stack
->evaluating
= 1;
775 retval
= top_of_stack
->retval
;
776 gc_unprotect(top_of_stack
->rest
);
777 top_of_stack
= stack_return(top_of_stack
);
779 consequent
= lisp_car(lisp_cdr(lisp_cdr(lisp_car(top_of_stack
->rest
))));
780 alternate
= lisp_cdr(lisp_cdr(lisp_cdr(lisp_car(top_of_stack
->rest
))));
781 if (pointer_type(retval
) != 1 ||
782 retval
.vp_charseq
!= constant_false
.vp_charseq
) {
783 element
= lisp_cons(consequent
, constant_nil
);
784 } else if (get_pair(alternate
) != get_pair(constant_nil
)) {
785 element
= lisp_cons(lisp_car(alternate
), constant_nil
);
787 top_of_stack
->retval
= constant_nil
;
791 gc_unprotect(retval
);
792 top_of_stack
->rest
= element
;
793 top_of_stack
->evaluating
= 1;
796 top_of_stack
->evaluating
= 0;
800 union value_pointer
builtin_string_to_list(struct stack_slot
*top_of_stack
,
801 struct environment
*env
,
802 union value_pointer rest
)
804 union value_pointer retval
;
805 union value_pointer
*v
;
809 s
= get_charseq_chars(lisp_car(rest
));
810 n
= get_charseq_len(lisp_car(rest
));
811 retval
= lisp_cons(constant_nil
, constant_nil
);
812 v
= &get_pair(retval
)->cdr
;
813 for (i
= 0; i
< n
; i
++) {
814 *v
= lisp_cons(lisp_integer(s
[i
]), constant_nil
);
816 v
= &get_pair(*v
)->cdr
;
818 v
= &get_pair(retval
)->cdr
;
820 gc_unprotect(retval
);
826 union value_pointer
builtin_car(struct stack_slot
*top_of_stack
,
827 struct environment
*env
,
828 union value_pointer rest
)
830 return lisp_car(lisp_car(rest
));
833 union value_pointer
builtin_cdr(struct stack_slot
*top_of_stack
,
834 struct environment
*env
,
835 union value_pointer rest
)
837 return lisp_cdr(lisp_car(rest
));
840 union value_pointer
builtin_cons(struct stack_slot
*top_of_stack
,
841 struct environment
*env
,
842 union value_pointer rest
)
844 return gc_unprotect(lisp_cons(lisp_car(rest
), lisp_car(lisp_cdr(rest
))));
847 union value_pointer
builtin_eq_p(struct stack_slot
*top_of_stack
,
848 struct environment
*env
,
849 union value_pointer rest
)
851 union value_pointer a
, b
;
854 b
= lisp_car(lisp_cdr(rest
));
856 if (pointer_type(a
) != pointer_type(b
)) {
857 return constant_false
;
860 switch (pointer_type(a
)) {
862 if (get_integer(a
) != get_integer(b
)) {
863 return constant_false
;
868 if (get_charseq(a
) != get_charseq(b
)) {
869 return constant_false
;
873 if (a
.vp_pair
!= b
.vp_pair
) {
874 return constant_false
;
879 return constant_true
;
882 union value_pointer
builtin_display(struct stack_slot
*top_of_stack
,
883 struct environment
*env
,
884 union value_pointer rest
)
886 pretty_print(lisp_car(rest
));
888 return constant_true
;
891 union value_pointer
builtin_list_p_helper(union value_pointer v
)
893 if (pointer_type(v
) == 3) {
894 if (get_pair(v
) == get_pair(constant_nil
)) {
895 return constant_true
;
897 return builtin_list_p_helper(lisp_cdr(v
));
900 return constant_false
;
904 union value_pointer
builtin_list_p(struct stack_slot
*top_of_stack
,
905 struct environment
*env
,
906 union value_pointer rest
)
908 return builtin_list_p_helper(lisp_car(rest
));
911 union value_pointer
builtin_define(struct stack_slot
*top_of_stack
,
912 struct environment
*env
,
913 union value_pointer rest
)
915 union value_pointer name_and_args
, definition
;
916 union value_pointer lambda_args
, function
;
918 name_and_args
= lisp_car(rest
);
919 definition
= lisp_car(lisp_cdr(rest
));
921 lambda_args
= lisp_cons(lisp_cdr(name_and_args
), lisp_cons(definition
, constant_nil
));
923 function
= builtin_lambda(top_of_stack
, env
, lambda_args
);
924 gc_unprotect(lambda_args
);
926 binding_new(env
, get_charseq_chars(lisp_car(name_and_args
)), function
);
931 union value_pointer
builtin_if(struct stack_slot
*top_of_stack
,
932 struct environment
*env
,
933 union value_pointer rest
)
935 union value_pointer retval
;
936 union value_pointer condition
, consequent
, alternate
;
937 union value_pointer v
;
939 retval
= constant_nil
;
941 condition
= lisp_car(rest
);
942 consequent
= lisp_car(lisp_cdr(rest
));
943 alternate
= lisp_cdr(lisp_cdr(rest
));
945 v
= lisp_cons(condition
, constant_nil
);
947 top_of_stack
->rest
= v
;
948 top_of_stack
->return_path
= 7;
951 condition
= builtin_eval(top_of_stack
, env
, v
);
954 if (pointer_type(condition
) != 1 ||
955 condition
.vp_charseq
!= constant_false
.vp_charseq
) {
956 v
= lisp_cons(consequent
, constant_nil
);
957 } else if (get_pair(alternate
) != get_pair(constant_nil
)) {
958 v
= lisp_cons(lisp_car(alternate
), constant_nil
);
963 gc_unprotect(condition
);
964 retval
= builtin_eval(top_of_stack
, env
, v
);
970 union value_pointer
builtin_lambda(struct stack_slot
*top_of_stack
,
971 struct environment
*env
,
972 union value_pointer rest
)
974 union value_pointer retval
;
976 retval
= lisp_cons(lisp_opaque(opaque_user_function
),
977 lisp_cons(lisp_integer(env
->resource_num
), rest
));
978 pointer_mark(&retval
, 3);
983 union value_pointer
builtin_quote(struct stack_slot
*top_of_stack
,
984 struct environment
*env
,
985 union value_pointer rest
)
987 return lisp_car(rest
);
990 union value_pointer
builtin_plus(struct stack_slot
*top_of_stack
,
991 struct environment
*env
,
992 union value_pointer rest
)
994 union value_pointer retval
;
997 for (sum
= 0; get_pair(rest
) != get_pair(constant_nil
); rest
= lisp_cdr(rest
)) {
998 sum
+= get_integer(lisp_car(rest
));
1001 retval
.vp_int
= sum
<< 2;
1002 pointer_mark(&retval
, 0);
1007 union value_pointer
builtin_minus(struct stack_slot
*top_of_stack
,
1008 struct environment
*env
,
1009 union value_pointer rest
)
1011 union value_pointer retval
;
1012 union value_pointer lhs
;
1015 lhs
= lisp_car(rest
);
1016 rest
= lisp_cdr(rest
);
1017 difference
= get_integer(lhs
);
1018 if (get_pair(rest
) != get_pair(constant_nil
)) {
1019 for (difference
= get_integer(lhs
);
1020 get_pair(rest
) != get_pair(constant_nil
);
1021 rest
= lisp_cdr(rest
)) {
1022 difference
-= get_integer(lisp_car(rest
));
1025 difference
= -get_integer(lhs
);
1028 retval
.vp_int
= difference
<< 2;
1029 pointer_mark(&retval
, 0);
1033 void gc_mark(union value_pointer v
)
1035 switch (pointer_type(v
)) {
1039 get_charseq(v
)->gc
|= 1;
1047 if (p
->car
.vp_opaque
!= opaque_builtin_function
&&
1048 p
->car
.vp_opaque
!= opaque_builtin_macro
) {
1049 if (p
->car
.vp_opaque
!= opaque_user_function
&&
1050 p
->car
.vp_opaque
!= opaque_user_macro
) {
1051 gc_mark(lisp_car(v
));
1053 gc_mark(lisp_cdr(v
));
1059 void gc_protect(union value_pointer v
)
1061 switch (pointer_type(v
)) {
1065 get_charseq(v
)->gc
|= 2;
1075 union value_pointer
gc_unprotect(union value_pointer v
)
1077 switch (pointer_type(v
)) {
1081 get_charseq(v
)->gc
&= ~2;
1092 void gc_unmark_all(void)
1096 for (j
= 0; j
< resource_count(&charseqs
); j
++) {
1097 struct charseq
*cs
= resource_get(&charseqs
, j
);
1102 for (j
= 0; j
< resource_count(&pairs
); j
++) {
1103 struct pair
*p
= resource_get(&pairs
, j
);
1108 for (j
= 0; j
< resource_count(&pairs
); j
++) {
1109 struct pair
*p
= resource_get(&pairs
, j
);
1111 if (p
->car
.vp_opaque
!= opaque_builtin_function
&&
1112 p
->car
.vp_opaque
!= opaque_builtin_macro
) {
1113 if (p
->car
.vp_opaque
!= opaque_user_function
&&
1114 p
->car
.vp_opaque
!= opaque_user_macro
) {
1123 void gc_collect(struct environment
*env
)
1129 for (; env
; env
= env
->parent
) {
1130 for (j
= 0; j
< resource_count(&env
->variables
); j
++) {
1131 struct binding
*b
= resource_get(&env
->variables
, j
);
1140 for (j
= 0; j
< resource_count(&charseqs
); j
++) {
1141 struct charseq
*cs
= resource_get(&charseqs
, j
);
1142 if (cs
&& cs
->gc
== 0) {
1144 resource_free(&charseqs
, j
);
1147 for (j
= 0; j
< resource_count(&pairs
); j
++) {
1148 struct pair
*p
= resource_get(&pairs
, j
);
1149 if (p
&& p
->gc
== 0) {
1150 resource_free(&pairs
, j
);
1161 union value_pointer i
, form
;
1162 struct environment
*top_env
;
1165 resource_pool_init(&bindings
, sizeof (struct binding
));
1166 resource_pool_init(&charseqs
, sizeof (struct charseq
));
1167 resource_pool_init(&environments
, sizeof (struct environment
));
1168 resource_pool_init(&pairs
, sizeof (struct pair
));
1169 resource_pool_init(&stack_slots
, sizeof (struct stack_slot
));
1171 constant_nil
= pair_new();
1172 get_pair(constant_nil
)->car
= constant_nil
;
1173 get_pair(constant_nil
)->cdr
= constant_nil
;
1175 while (!feof(stdin
) && !ferror(stdin
)) {
1178 if (bufused
>= bufsize
) {
1179 buf
= realloc(buf
, bufsize
* 2 + 16);
1183 bufsize
= bufsize
* 2 + 16;
1185 n
= fread(buf
+ bufused
, 1, bufsize
- bufused
, stdin
);
1189 top_env
= environment_new(NULL
);
1191 constant_true
= charseq_new("#t", 2, 2, 1);
1192 constant_false
= charseq_new("#f", 2, 2, 1);
1194 binding_new(top_env
, "#t", constant_true
);
1195 binding_new(top_env
, "#f", constant_false
);
1197 binding_new(top_env
, "car", builtin_new(opaque_builtin_function
, builtin_car
));
1198 binding_new(top_env
, "cdr", builtin_new(opaque_builtin_function
, builtin_cdr
));
1199 binding_new(top_env
, "cons", builtin_new(opaque_builtin_function
, builtin_cons
));
1200 binding_new(top_env
, "eq?", builtin_new(opaque_builtin_function
, builtin_eq_p
));
1201 binding_new(top_env
, "display", builtin_new(opaque_builtin_function
, builtin_display
));
1202 binding_new(top_env
, "list?", builtin_new(opaque_builtin_function
, builtin_list_p
));
1203 binding_new(top_env
, "primitive-eval", builtin_new(opaque_builtin_function
, builtin_eval
));
1204 binding_new(top_env
, "string->list", builtin_new(opaque_builtin_function
, builtin_string_to_list
));
1206 binding_new(top_env
, "define", builtin_new(opaque_builtin_macro
, builtin_define
));
1207 binding_new(top_env
, "if", builtin_new(opaque_builtin_macro
, builtin_if
));
1208 binding_new(top_env
, "lambda", builtin_new(opaque_builtin_macro
, builtin_lambda
));
1209 binding_new(top_env
, "quote", builtin_new(opaque_builtin_macro
, builtin_quote
));
1211 binding_new(top_env
, "+", builtin_new(opaque_builtin_function
, builtin_plus
));
1212 binding_new(top_env
, "-", builtin_new(opaque_builtin_function
, builtin_minus
));
1214 form
= lisp_cons(constant_nil
, constant_nil
);
1216 formsize
= parse_forms(buf
, bufused
, &get_pair(form
)->cdr
);
1218 form
= lisp_cdr(form
);
1222 if (formsize
!= bufused
) {
1223 printf("this stuff left over: \"%.*s\"\n",
1224 bufused
- formsize
, buf
+ formsize
);
1227 for (i
= form
; get_pair(i
) != get_pair(constant_nil
); i
= form
) {
1228 union value_pointer rest
, retval
;
1230 rest
= lisp_cons(lisp_car(i
), constant_nil
);
1232 pretty_print(lisp_car(i
));
1234 retval
= builtin_eval(NULL
, top_env
, rest
);
1236 pretty_print(retval
);
1237 gc_unprotect(retval
);
1244 gc_collect(top_env
);
1247 environment_free(top_env
);
1249 gc_unprotect(constant_nil
);
1252 resource_pool_free(&charseqs
);
1253 resource_pool_free(&pairs
);
1254 free(bindings
.resources
);
1255 free(environments
.resources
);