2 * Copyright © 2016 Keith Packard <keithp@keithp.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
18 struct ao_lisp_stack *ao_lisp_stack;
20 uint8_t ao_lisp_skip_cons_free;
23 ao_lisp_set_cond(struct ao_lisp_cons *c)
25 ao_lisp_stack->state = eval_cond;
26 ao_lisp_stack->sexprs = ao_lisp_cons_poly(c);
31 func_type(ao_poly func)
33 if (func == AO_LISP_NIL)
34 return ao_lisp_error(AO_LISP_INVALID, "func is nil");
35 switch (ao_lisp_poly_type(func)) {
37 return ao_lisp_poly_builtin(func)->args & AO_LISP_FUNC_MASK;
39 return ao_lisp_poly_lambda(func)->args;
41 return AO_LISP_FUNC_LAMBDA;
43 ao_lisp_error(AO_LISP_INVALID, "not a func");
49 * Flattened eval to avoid stack issues
53 * Evaluate an s-expression
55 * For a list, evaluate all of the elements and
56 * then execute the resulting function call.
58 * Each element of the list is evaluated in
59 * a clean stack context.
61 * The current stack state is set to 'formal' so that
62 * when the evaluation is complete, the value
63 * will get appended to the values list.
65 * For other types, compute the value directly.
69 ao_lisp_eval_sexpr(void)
71 DBGI("sexpr: "); DBG_POLY(ao_lisp_v); DBG("\n");
72 switch (ao_lisp_poly_type(ao_lisp_v)) {
74 if (ao_lisp_v == AO_LISP_NIL) {
75 if (!ao_lisp_stack->values) {
77 * empty list evaluates to empty list
79 ao_lisp_v = AO_LISP_NIL;
80 ao_lisp_stack->state = eval_val;
83 * done with arguments, go execute it
85 ao_lisp_v = ao_lisp_poly_cons(ao_lisp_stack->values)->car;
86 ao_lisp_stack->state = eval_exec;
89 if (!ao_lisp_stack->values)
90 ao_lisp_stack->list = ao_lisp_v;
92 * Evaluate another argument and then switch
93 * to 'formal' to add the value to the values
96 ao_lisp_stack->sexprs = ao_lisp_v;
97 ao_lisp_stack->state = eval_formal;
98 if (!ao_lisp_stack_push())
101 * push will reset the state to 'sexpr', which
102 * will evaluate the expression
104 ao_lisp_v = ao_lisp_poly_cons(ao_lisp_v)->car;
108 DBGI("..frame "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n");
109 ao_lisp_v = ao_lisp_atom_get(ao_lisp_v);
116 case AO_LISP_BUILTIN:
118 ao_lisp_stack->state = eval_val;
121 DBGI(".. result "); DBG_POLY(ao_lisp_v); DBG("\n");
126 * A value has been computed.
128 * If the value was computed from a macro,
129 * then we want to reset the current context
130 * to evaluate the macro result again.
132 * If not a macro, then pop the stack.
133 * If the stack is empty, we're done.
134 * Otherwise, the stack will contain
139 ao_lisp_eval_val(void)
141 DBGI("val: "); DBG_POLY(ao_lisp_v); DBG("\n");
143 * Value computed, pop the stack
144 * to figure out what to do with the value
147 DBGI("..state %d\n", ao_lisp_stack ? ao_lisp_stack->state : -1);
152 * A formal has been computed.
154 * If this is the first formal, then check to see if we've got a
155 * lamda/lexpr or macro/nlambda.
157 * For lambda/lexpr, go compute another formal. This will terminate
158 * when the sexpr state sees nil.
160 * For macro/nlambda, we're done, so move the sexprs into the values
163 * Macros have an additional step of saving a stack frame holding the
164 * macro value execution context, which then gets the result of the
169 ao_lisp_eval_formal(void)
172 struct ao_lisp_stack *prev;
174 DBGI("formal: "); DBG_POLY(ao_lisp_v); DBG("\n");
176 /* Check what kind of function we've got */
177 if (!ao_lisp_stack->values) {
178 switch (func_type(ao_lisp_v)) {
179 case AO_LISP_FUNC_LAMBDA:
180 case AO_LISP_FUNC_LEXPR:
181 DBGI(".. lambda or lexpr\n");
183 case AO_LISP_FUNC_MACRO:
184 /* Evaluate the result once more */
185 ao_lisp_stack->state = eval_macro;
186 if (!ao_lisp_stack_push())
189 /* After the function returns, take that
190 * value and re-evaluate it
192 prev = ao_lisp_poly_stack(ao_lisp_stack->prev);
193 ao_lisp_stack->sexprs = prev->sexprs;
195 DBGI(".. start macro\n");
196 DBGI(".. sexprs "); DBG_POLY(ao_lisp_stack->sexprs); DBG("\n");
197 DBGI(".. values "); DBG_POLY(ao_lisp_stack->values); DBG("\n");
200 /* fall through ... */
201 case AO_LISP_FUNC_NLAMBDA:
202 DBGI(".. nlambda or macro\n");
204 /* use the raw sexprs as values */
205 ao_lisp_stack->values = ao_lisp_stack->sexprs;
206 ao_lisp_stack->values_tail = AO_LISP_NIL;
207 ao_lisp_stack->state = eval_exec;
209 /* ready to execute now */
216 /* Append formal to list of values */
217 formal = ao_lisp__cons(ao_lisp_v, AO_LISP_NIL);
221 if (ao_lisp_stack->values_tail)
222 ao_lisp_poly_cons(ao_lisp_stack->values_tail)->cdr = formal;
224 ao_lisp_stack->values = formal;
225 ao_lisp_stack->values_tail = formal;
227 DBGI(".. values "); DBG_POLY(ao_lisp_stack->values); DBG("\n");
230 * Step to the next argument, if this is last, then
231 * 'sexpr' will end up switching to 'exec'
233 ao_lisp_v = ao_lisp_poly_cons(ao_lisp_stack->sexprs)->cdr;
235 ao_lisp_stack->state = eval_sexpr;
237 DBGI(".. "); DBG_POLY(ao_lisp_v); DBG("\n");
242 * Start executing a function call
244 * Most builtins are easy, just call the function.
245 * 'cond' is magic; it sticks the list of clauses
246 * in 'sexprs' and switches to 'cond' state. That
247 * bit of magic is done in ao_lisp_set_cond.
249 * Lambdas build a new frame to hold the locals and
250 * then re-use the current stack context to evaluate
251 * the s-expression from the lambda.
255 ao_lisp_eval_exec(void)
258 struct ao_lisp_builtin *builtin;
260 DBGI("exec: "); DBG_POLY(ao_lisp_v); DBG(" values "); DBG_POLY(ao_lisp_stack->values); DBG ("\n");
261 ao_lisp_stack->sexprs = AO_LISP_NIL;
262 switch (ao_lisp_poly_type(ao_lisp_v)) {
263 case AO_LISP_BUILTIN:
264 ao_lisp_stack->state = eval_val;
265 builtin = ao_lisp_poly_builtin(ao_lisp_v);
266 v = ao_lisp_func(builtin) (
267 ao_lisp_poly_cons(ao_lisp_poly_cons(ao_lisp_stack->values)->cdr));
268 DBG_DO(if (!ao_lisp_exception && ao_lisp_poly_builtin(ao_lisp_v)->func == builtin_set) {
269 struct ao_lisp_cons *cons = ao_lisp_poly_cons(ao_lisp_stack->values);
270 ao_poly atom = ao_lisp_arg(cons, 1);
271 ao_poly val = ao_lisp_arg(cons, 2);
272 DBGI("set "); DBG_POLY(atom); DBG(" = "); DBG_POLY(val); DBG("\n");
274 builtin = ao_lisp_poly_builtin(ao_lisp_v);
275 if (builtin && builtin->args & AO_LISP_FUNC_FREE_ARGS && !ao_lisp_stack_marked(ao_lisp_stack) && !ao_lisp_skip_cons_free)
276 ao_lisp_cons_free(ao_lisp_poly_cons(ao_lisp_stack->values));
279 ao_lisp_stack->values = AO_LISP_NIL;
280 ao_lisp_stack->values_tail = AO_LISP_NIL;
281 DBGI(".. result "); DBG_POLY(ao_lisp_v); DBG ("\n");
282 DBGI(".. frame "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n");
285 DBGI(".. frame "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n");
286 ao_lisp_stack->state = eval_begin;
287 v = ao_lisp_lambda_eval();
288 ao_lisp_stack->sexprs = v;
289 ao_lisp_stack->values = AO_LISP_NIL;
290 ao_lisp_stack->values_tail = AO_LISP_NIL;
291 DBGI(".. sexprs "); DBG_POLY(ao_lisp_stack->sexprs); DBG("\n");
292 DBGI(".. frame "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n");
295 DBGI(".. stack "); DBG_POLY(ao_lisp_v); DBG("\n");
296 ao_lisp_v = ao_lisp_stack_eval();
297 DBGI(".. value "); DBG_POLY(ao_lisp_v); DBG("\n");
298 DBGI(".. frame "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n");
301 ao_lisp_skip_cons_free = 0;
306 * Finish setting up the apply evaluation
308 * The value is the list to execute
311 ao_lisp_eval_apply(void)
313 struct ao_lisp_cons *cons = ao_lisp_poly_cons(ao_lisp_v);
314 struct ao_lisp_cons *cdr, *prev;
316 /* Glue the arguments into the right shape. That's all but the last
317 * concatenated onto the last
322 cdr = ao_lisp_poly_cons(prev->cdr);
323 if (cdr->cdr == AO_LISP_NIL)
326 DBGI("before mangling: "); DBG_POLY(ao_lisp_v); DBG("\n");
327 prev->cdr = cdr->car;
328 ao_lisp_stack->values = ao_lisp_v;
329 ao_lisp_v = ao_lisp_poly_cons(ao_lisp_stack->values)->car;
330 DBGI("apply: "); DBG_POLY(ao_lisp_stack->values); DBG ("\n");
331 ao_lisp_stack->state = eval_exec;
332 ao_lisp_skip_cons_free = 1;
337 * Start evaluating the next cond clause
339 * If the list of clauses is empty, then
340 * the result of the cond is nil.
342 * Otherwise, set the current stack state to 'cond_test' and create a
343 * new stack context to evaluate the test s-expression. Once that's
344 * complete, we'll land in 'cond_test' to finish the clause.
347 ao_lisp_eval_cond(void)
349 DBGI("cond: "); DBG_POLY(ao_lisp_stack->sexprs); DBG("\n");
350 DBGI(".. frame "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n");
351 DBGI(".. saved frame "); DBG_POLY(ao_lisp_stack->frame); DBG("\n");
352 if (!ao_lisp_stack->sexprs) {
353 ao_lisp_v = _ao_lisp_bool_false;
354 ao_lisp_stack->state = eval_val;
356 ao_lisp_v = ao_lisp_poly_cons(ao_lisp_stack->sexprs)->car;
357 if (!ao_lisp_v || ao_lisp_poly_type(ao_lisp_v) != AO_LISP_CONS) {
358 ao_lisp_error(AO_LISP_INVALID, "invalid cond clause");
361 ao_lisp_v = ao_lisp_poly_cons(ao_lisp_v)->car;
362 if (ao_lisp_v == _ao_lisp_atom_else)
363 ao_lisp_v = _ao_lisp_bool_true;
364 ao_lisp_stack->state = eval_cond_test;
365 if (!ao_lisp_stack_push())
372 * Finish a cond clause.
374 * Check the value from the test expression, if
375 * non-nil, then set up to evaluate the value expression.
377 * Otherwise, step to the next clause and go back to the 'cond'
381 ao_lisp_eval_cond_test(void)
383 DBGI("cond_test: "); DBG_POLY(ao_lisp_v); DBG(" sexprs "); DBG_POLY(ao_lisp_stack->sexprs); DBG("\n");
384 DBGI(".. frame "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n");
385 DBGI(".. saved frame "); DBG_POLY(ao_lisp_stack->frame); DBG("\n");
386 if (ao_lisp_v != _ao_lisp_bool_false) {
387 struct ao_lisp_cons *car = ao_lisp_poly_cons(ao_lisp_poly_cons(ao_lisp_stack->sexprs)->car);
388 ao_poly c = car->cdr;
391 ao_lisp_stack->state = eval_begin;
392 ao_lisp_stack->sexprs = c;
394 ao_lisp_stack->state = eval_val;
396 ao_lisp_stack->sexprs = ao_lisp_poly_cons(ao_lisp_stack->sexprs)->cdr;
397 DBGI("next cond: "); DBG_POLY(ao_lisp_stack->sexprs); DBG("\n");
398 ao_lisp_stack->state = eval_cond;
404 * Evaluate a list of sexprs, returning the value from the last one.
406 * ao_lisp_begin records the list in stack->sexprs, so we just need to
407 * walk that list. Set ao_lisp_v to the car of the list and jump to
408 * eval_sexpr. When that's done, it will land in eval_val. For all but
409 * the last, leave a stack frame with eval_begin set so that we come
410 * back here. For the last, don't add a stack frame so that we can
414 ao_lisp_eval_begin(void)
416 DBGI("begin: "); DBG_POLY(ao_lisp_v); DBG(" sexprs "); DBG_POLY(ao_lisp_stack->sexprs); DBG("\n");
417 DBGI(".. frame "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n");
418 DBGI(".. saved frame "); DBG_POLY(ao_lisp_stack->frame); DBG("\n");
420 if (!ao_lisp_stack->sexprs) {
421 ao_lisp_v = AO_LISP_NIL;
422 ao_lisp_stack->state = eval_val;
424 ao_lisp_v = ao_lisp_poly_cons(ao_lisp_stack->sexprs)->car;
425 ao_lisp_stack->sexprs = ao_lisp_poly_cons(ao_lisp_stack->sexprs)->cdr;
427 /* If there are more sexprs to do, then come back here, otherwise
428 * return the value of the last one by just landing in eval_sexpr
430 if (ao_lisp_stack->sexprs) {
431 ao_lisp_stack->state = eval_begin;
432 if (!ao_lisp_stack_push())
435 ao_lisp_stack->state = eval_sexpr;
441 * Conditionally execute a list of sexprs while the first is true
444 ao_lisp_eval_while(void)
446 DBGI("while: "); DBG_POLY(ao_lisp_stack->sexprs); DBG("\n");
447 DBGI(".. frame "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n");
448 DBGI(".. saved frame "); DBG_POLY(ao_lisp_stack->frame); DBG("\n");
450 ao_lisp_stack->values = ao_lisp_v;
451 if (!ao_lisp_stack->sexprs) {
452 ao_lisp_v = AO_LISP_NIL;
453 ao_lisp_stack->state = eval_val;
455 ao_lisp_v = ao_lisp_poly_cons(ao_lisp_stack->sexprs)->car;
456 ao_lisp_stack->state = eval_while_test;
457 if (!ao_lisp_stack_push())
464 * Check the while condition, terminate the loop if nil. Otherwise keep going
467 ao_lisp_eval_while_test(void)
469 DBGI("while_test: "); DBG_POLY(ao_lisp_v); DBG(" sexprs "); DBG_POLY(ao_lisp_stack->sexprs); DBG("\n");
470 DBGI(".. frame "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n");
471 DBGI(".. saved frame "); DBG_POLY(ao_lisp_stack->frame); DBG("\n");
473 if (ao_lisp_v != _ao_lisp_bool_false) {
474 ao_lisp_stack->values = ao_lisp_v;
475 ao_lisp_v = ao_lisp_poly_cons(ao_lisp_stack->sexprs)->cdr;
476 ao_lisp_stack->state = eval_while;
477 if (!ao_lisp_stack_push())
479 ao_lisp_stack->state = eval_begin;
480 ao_lisp_stack->sexprs = ao_lisp_v;
484 ao_lisp_stack->state = eval_val;
485 ao_lisp_v = ao_lisp_stack->values;
491 * Replace the original sexpr with the macro expansion, then
495 ao_lisp_eval_macro(void)
497 DBGI("macro: "); DBG_POLY(ao_lisp_v); DBG(" sexprs "); DBG_POLY(ao_lisp_stack->sexprs); DBG("\n");
499 if (ao_lisp_v == AO_LISP_NIL)
501 if (ao_lisp_poly_type(ao_lisp_v) == AO_LISP_CONS) {
502 *ao_lisp_poly_cons(ao_lisp_stack->sexprs) = *ao_lisp_poly_cons(ao_lisp_v);
503 ao_lisp_v = ao_lisp_stack->sexprs;
504 DBGI("sexprs rewritten to: "); DBG_POLY(ao_lisp_v); DBG("\n");
506 ao_lisp_stack->sexprs = AO_LISP_NIL;
507 ao_lisp_stack->state = eval_sexpr;
511 static int (*const evals[])(void) = {
512 [eval_sexpr] = ao_lisp_eval_sexpr,
513 [eval_val] = ao_lisp_eval_val,
514 [eval_formal] = ao_lisp_eval_formal,
515 [eval_exec] = ao_lisp_eval_exec,
516 [eval_apply] = ao_lisp_eval_apply,
517 [eval_cond] = ao_lisp_eval_cond,
518 [eval_cond_test] = ao_lisp_eval_cond_test,
519 [eval_begin] = ao_lisp_eval_begin,
520 [eval_while] = ao_lisp_eval_while,
521 [eval_while_test] = ao_lisp_eval_while_test,
522 [eval_macro] = ao_lisp_eval_macro,
525 const char *ao_lisp_state_names[] = {
526 [eval_sexpr] = "sexpr",
528 [eval_formal] = "formal",
529 [eval_exec] = "exec",
530 [eval_apply] = "apply",
531 [eval_cond] = "cond",
532 [eval_cond_test] = "cond_test",
533 [eval_begin] = "begin",
534 [eval_while] = "while",
535 [eval_while_test] = "while_test",
536 [eval_macro] = "macro",
540 * Called at restore time to reset all execution state
544 ao_lisp_eval_clear_globals(void)
546 ao_lisp_stack = NULL;
547 ao_lisp_frame_current = NULL;
548 ao_lisp_v = AO_LISP_NIL;
552 ao_lisp_eval_restart(void)
554 return ao_lisp_stack_push();
558 ao_lisp_eval(ao_poly _v)
562 ao_lisp_frame_init();
564 if (!ao_lisp_stack_push())
567 while (ao_lisp_stack) {
568 if (!(*evals[ao_lisp_stack->state])() || ao_lisp_exception) {
569 ao_lisp_stack_clear();
573 DBG_DO(if (ao_lisp_frame_current) {DBGI("frame left as "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n");});
574 ao_lisp_frame_current = NULL;