15 struct charseq
*vp_charseq
;
16 union value_pointer (*vp_builtin
)(union value_pointer rest
);
21 union value_pointer type_dot_value
;
25 struct binding
**variables
;
28 struct environment
*parent
;
32 union value_pointer car
;
33 union value_pointer cdr
;
36 void pointer_mark(union value_pointer
*v
, int type
)
38 int pointer_bits
= v
->vp_int
;
43 v
->vp_int
= pointer_bits
;
46 int pointer_type(union value_pointer v
)
48 return (v
.vp_int
& 3);
51 int get_integer(union value_pointer v
)
53 return (v
.vp_int
>> 2);
56 struct pair
*get_pair(union value_pointer v
)
62 struct charseq
*get_charseq(union value_pointer v
)
68 size_t get_charseq_length(union value_pointer v
)
77 char *get_charseq_chars(union value_pointer v
)
86 struct charseq
*charseq_new(void)
88 return malloc(sizeof (struct charseq
));
91 struct pair
*pair_new(void)
93 return malloc(sizeof (struct pair
));
96 struct binding
*binding_new(char const *name
,
97 union value_pointer type_dot_value
)
101 b
= malloc(sizeof (*b
));
103 b
->name
= charseq_new();
104 b
->name
->len
= strlen(name
);
105 b
->name
->s
= strdup(name
);
107 b
->type_dot_value
= type_dot_value
;
112 void binding_builtin(struct environment
*env
,
114 union value_pointer (*builtin
)(union value_pointer rest
))
116 union value_pointer v
;
117 struct pair
*type_dot_value
;
119 if (env
->variables_used
>= env
->variables_size
) {
120 int newsize
= env
->variables_used
* 2 + 16;
122 env
->variables
= realloc(env
->variables
,
123 sizeof (*env
->variables
) * newsize
);
124 env
->variables_size
= newsize
;
127 type_dot_value
= pair_new();
128 type_dot_value
->car
.vp_int
= 1 << 2;
129 pointer_mark(&type_dot_value
->car
, 0);
130 type_dot_value
->cdr
.vp_builtin
= builtin
;
131 v
.vp_pair
= type_dot_value
;
134 env
->variables
[env
->variables_used
++] = binding_new(name
, v
);
137 size_t parse_word(union value_pointer
*vp
, char const *buf
, size_t len
)
142 for (n
= 0, i
= 0; i
< len
; i
++) {
143 if (buf
[i
] < '0' || buf
[i
] > '9') {
146 n
= n
*10 + buf
[i
] - '0';
159 for (i
++; i
< len
; i
++) {
169 vp
->vp_charseq
= charseq_new();
170 vp
->vp_charseq
->len
= i
;
171 vp
->vp_charseq
->s
= malloc(i
+ 1);
172 memcpy(vp
->vp_charseq
->s
, buf
, i
);
173 vp
->vp_charseq
->s
[i
] = 0;
183 size_t parse_string(union value_pointer
*vp
, char const *buf
, size_t len
)
187 for (i
= 1; i
< len
; i
++) {
193 vp
->vp_charseq
= charseq_new();
194 vp
->vp_charseq
->len
= i
- 1;
195 vp
->vp_charseq
->s
= malloc(i
);
196 memcpy(vp
->vp_charseq
->s
, buf
+ 1, i
- 1);
197 vp
->vp_charseq
->s
[i
-1] = 0;
203 size_t parse_form(char const *buf
, size_t len
, union value_pointer
*form
)
208 for (i
= 0; i
< len
; i
++) {
209 char const c
= buf
[i
];
210 union value_pointer u
, v
;
214 v
.vp_pair
= pair_new();
215 v
.vp_pair
->car
.vp_pair
= NULL
;
216 pointer_mark(&v
.vp_pair
->car
, 3);
217 i
+= parse_form(buf
+ i
+ 1, len
- i
- 1, &v
.vp_pair
->car
) + 1;
218 v
.vp_pair
->cdr
.vp_pair
= NULL
;
219 pointer_mark(&v
.vp_pair
->cdr
, 3);
221 pointer_mark(form
, 3);
222 form
= &v
.vp_pair
->cdr
;
228 if (word_start
!= -1) {
229 v
.vp_pair
= pair_new();
230 parse_word(&v
.vp_pair
->car
, buf
+ word_start
, i
- word_start
);
231 v
.vp_pair
->cdr
.vp_pair
= NULL
;
232 pointer_mark(&v
.vp_pair
->cdr
, 3);
234 pointer_mark(form
, 3);
235 form
= &v
.vp_pair
->cdr
;
240 v
.vp_pair
= pair_new();
241 n
= parse_string(&v
.vp_pair
->car
, buf
+ i
, len
- i
);
243 v
.vp_pair
->cdr
.vp_pair
= NULL
;
244 pointer_mark(&v
.vp_pair
->cdr
, 3);
246 pointer_mark(form
, 3);
247 form
= &v
.vp_pair
->cdr
;
250 if (word_start
== -1) {
264 void pretty_print(union value_pointer v
)
266 union value_pointer i
;
268 switch (pointer_type(v
)) {
270 printf("%d", get_integer(v
));
273 printf("%s", get_charseq_chars(v
));
276 printf("\"%s\"", get_charseq_chars(v
));
280 for (i
= v
; i
.vp_int
!= 3; i
= get_pair(i
)->cdr
) {
281 if (i
.vp_pair
!= v
.vp_pair
) {
284 pretty_print(get_pair(i
)->car
);
291 union value_pointer
eval(struct environment
*env
, union value_pointer v
)
293 union value_pointer retval
, function
, rest
;
294 union value_pointer
*args
;
295 char const *symbol_name
;
296 struct pair
*list
, *closure
;
299 switch (pointer_type(v
)) {
305 symbol_name
= get_charseq_chars(v
);
307 for (i
= 0; i
< env
->variables_used
; i
++) {
308 if (strcmp(env
->variables
[i
]->name
->s
,
310 return env
->variables
[i
]->type_dot_value
;
314 } while (env
!= NULL
);
318 pointer_mark(&rest
, 3);
320 for (list
= get_pair(v
); list
!= NULL
; list
= get_pair(list
->cdr
)) {
321 union value_pointer element
;
323 element
.vp_pair
= pair_new();
324 element
.vp_pair
->car
= eval(env
, list
->car
);
325 element
.vp_pair
->cdr
.vp_pair
= NULL
;
326 pointer_mark(&element
.vp_pair
->cdr
, 3);
329 pointer_mark(args
, 3);
330 args
= &element
.vp_pair
->cdr
;
333 list
= get_pair(rest
);
334 function
= list
->car
;
337 closure
= get_pair(function
);
338 switch (get_integer(closure
->car
)) {
340 retval
= (*closure
->cdr
.vp_builtin
)(rest
);
350 union value_pointer
builtin_plus(union value_pointer rest
)
353 union value_pointer retval
;
356 for (sum
= 0, i
= get_pair(rest
); i
!= NULL
; i
= get_pair(i
->cdr
)) {
357 sum
+= get_integer(i
->car
);
360 retval
.vp_int
= sum
<< 2;
361 pointer_mark(&retval
, 0);
372 union value_pointer form
;
374 struct environment top_env
;
376 while (!feof(stdin
) && !ferror(stdin
)) {
379 if (bufused
>= bufsize
) {
380 buf
= realloc(buf
, bufsize
* 2 + 16);
384 bufsize
= bufsize
* 2 + 16;
386 n
= fread(buf
+ bufused
, 1, bufsize
- bufused
, stdin
);
390 top_env
.variables
= NULL
;
391 top_env
.variables_used
= 0;
392 top_env
.variables_size
= 0;
393 top_env
.parent
= NULL
;
395 binding_builtin(&top_env
, "+", builtin_plus
);
396 form
.vp_pair
= pair_new();
397 pointer_mark(&form
, 3);
399 formsize
= parse_form(buf
, bufused
, &form
);
401 if (formsize
!= bufused
) {
402 printf("this stuff left over: \"%.*s\"\n",
403 bufused
- formsize
, buf
+ formsize
);
406 for (i
= get_pair(form
); i
!= NULL
; i
= get_pair(i
->cdr
)) {
407 pretty_print(i
->car
);
409 pretty_print(eval(&top_env
, i
->car
));