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;
22 ao_lisp_set_cond(struct ao_lisp_cons *c)
24 ao_lisp_stack->state = eval_cond;
25 ao_lisp_stack->sexprs = ao_lisp_cons_poly(c);
30 func_type(ao_poly func)
32 if (func == AO_LISP_NIL)
33 return ao_lisp_error(AO_LISP_INVALID, "func is nil");
34 switch (ao_lisp_poly_type(func)) {
36 return ao_lisp_poly_builtin(func)->args & AO_LISP_FUNC_MASK;
38 return ao_lisp_poly_lambda(func)->args;
40 return AO_LISP_FUNC_LAMBDA;
42 ao_lisp_error(AO_LISP_INVALID, "not a func");
48 * Flattened eval to avoid stack issues
52 * Evaluate an s-expression
54 * For a list, evaluate all of the elements and
55 * then execute the resulting function call.
57 * Each element of the list is evaluated in
58 * a clean stack context.
60 * The current stack state is set to 'formal' so that
61 * when the evaluation is complete, the value
62 * will get appended to the values list.
64 * For other types, compute the value directly.
68 ao_lisp_eval_sexpr(void)
70 DBGI("sexpr: "); DBG_POLY(ao_lisp_v); DBG("\n");
71 switch (ao_lisp_poly_type(ao_lisp_v)) {
73 if (ao_lisp_v == AO_LISP_NIL) {
74 if (!ao_lisp_stack->values) {
76 * empty list evaluates to empty list
78 ao_lisp_v = AO_LISP_NIL;
79 ao_lisp_stack->state = eval_val;
82 * done with arguments, go execute it
84 ao_lisp_v = ao_lisp_poly_cons(ao_lisp_stack->values)->car;
85 ao_lisp_stack->state = eval_exec;
88 if (!ao_lisp_stack->values)
89 ao_lisp_stack->list = ao_lisp_v;
91 * Evaluate another argument and then switch
92 * to 'formal' to add the value to the values
95 ao_lisp_stack->sexprs = ao_lisp_v;
96 ao_lisp_stack->state = eval_formal;
97 if (!ao_lisp_stack_push())
100 * push will reset the state to 'sexpr', which
101 * will evaluate the expression
103 ao_lisp_v = ao_lisp_poly_cons(ao_lisp_v)->car;
107 DBGI("..frame "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n");
108 ao_lisp_v = ao_lisp_atom_get(ao_lisp_v);
113 case AO_LISP_BUILTIN:
115 ao_lisp_stack->state = eval_val;
118 DBGI(".. result "); DBG_POLY(ao_lisp_v); DBG("\n");
123 * A value has been computed.
125 * If the value was computed from a macro,
126 * then we want to reset the current context
127 * to evaluate the macro result again.
129 * If not a macro, then pop the stack.
130 * If the stack is empty, we're done.
131 * Otherwise, the stack will contain
136 ao_lisp_eval_val(void)
138 DBGI("val: "); DBG_POLY(ao_lisp_v); DBG("\n");
140 * Value computed, pop the stack
141 * to figure out what to do with the value
144 DBGI("..state %d\n", ao_lisp_stack ? ao_lisp_stack->state : -1);
149 * A formal has been computed.
151 * If this is the first formal, then check to see if we've got a
152 * lamda/lexpr or macro/nlambda.
154 * For lambda/lexpr, go compute another formal. This will terminate
155 * when the sexpr state sees nil.
157 * For macro/nlambda, we're done, so move the sexprs into the values
160 * Macros have an additional step of saving a stack frame holding the
161 * macro value execution context, which then gets the result of the
166 ao_lisp_eval_formal(void)
169 struct ao_lisp_stack *prev;
171 DBGI("formal: "); DBG_POLY(ao_lisp_v); DBG("\n");
173 /* Check what kind of function we've got */
174 if (!ao_lisp_stack->values) {
175 switch (func_type(ao_lisp_v)) {
176 case AO_LISP_FUNC_LAMBDA:
177 case AO_LISP_FUNC_LEXPR:
178 DBGI(".. lambda or lexpr\n");
180 case AO_LISP_FUNC_MACRO:
181 /* Evaluate the result once more */
182 ao_lisp_stack->state = eval_macro;
183 if (!ao_lisp_stack_push())
186 /* After the function returns, take that
187 * value and re-evaluate it
189 prev = ao_lisp_poly_stack(ao_lisp_stack->prev);
190 ao_lisp_stack->sexprs = prev->sexprs;
192 DBGI(".. start macro\n");
193 DBGI(".. sexprs "); DBG_POLY(ao_lisp_stack->sexprs); DBG("\n");
194 DBGI(".. values "); DBG_POLY(ao_lisp_stack->values); DBG("\n");
197 /* fall through ... */
198 case AO_LISP_FUNC_NLAMBDA:
199 DBGI(".. nlambda or macro\n");
201 /* use the raw sexprs as values */
202 ao_lisp_stack->values = ao_lisp_stack->sexprs;
203 ao_lisp_stack->values_tail = AO_LISP_NIL;
204 ao_lisp_stack->state = eval_exec;
206 /* ready to execute now */
213 /* Append formal to list of values */
214 formal = ao_lisp__cons(ao_lisp_v, AO_LISP_NIL);
218 if (ao_lisp_stack->values_tail)
219 ao_lisp_poly_cons(ao_lisp_stack->values_tail)->cdr = formal;
221 ao_lisp_stack->values = formal;
222 ao_lisp_stack->values_tail = formal;
224 DBGI(".. values "); DBG_POLY(ao_lisp_stack->values); DBG("\n");
227 * Step to the next argument, if this is last, then
228 * 'sexpr' will end up switching to 'exec'
230 ao_lisp_v = ao_lisp_poly_cons(ao_lisp_stack->sexprs)->cdr;
232 ao_lisp_stack->state = eval_sexpr;
234 DBGI(".. "); DBG_POLY(ao_lisp_v); DBG("\n");
239 * Start executing a function call
241 * Most builtins are easy, just call the function.
242 * 'cond' is magic; it sticks the list of clauses
243 * in 'sexprs' and switches to 'cond' state. That
244 * bit of magic is done in ao_lisp_set_cond.
246 * Lambdas build a new frame to hold the locals and
247 * then re-use the current stack context to evaluate
248 * the s-expression from the lambda.
252 ao_lisp_eval_exec(void)
255 struct ao_lisp_builtin *builtin;
257 DBGI("exec: "); DBG_POLY(ao_lisp_v); DBG(" values "); DBG_POLY(ao_lisp_stack->values); DBG ("\n");
258 ao_lisp_stack->sexprs = AO_LISP_NIL;
259 switch (ao_lisp_poly_type(ao_lisp_v)) {
260 case AO_LISP_BUILTIN:
261 ao_lisp_stack->state = eval_val;
262 builtin = ao_lisp_poly_builtin(ao_lisp_v);
263 v = ao_lisp_func(builtin) (
264 ao_lisp_poly_cons(ao_lisp_poly_cons(ao_lisp_stack->values)->cdr));
265 DBG_DO(if (!ao_lisp_exception && ao_lisp_poly_builtin(ao_lisp_v)->func == builtin_set) {
266 struct ao_lisp_cons *cons = ao_lisp_poly_cons(ao_lisp_stack->values);
267 ao_poly atom = ao_lisp_arg(cons, 1);
268 ao_poly val = ao_lisp_arg(cons, 2);
269 DBGI("set "); DBG_POLY(atom); DBG(" = "); DBG_POLY(val); DBG("\n");
271 builtin = ao_lisp_poly_builtin(ao_lisp_v);
272 if (builtin->args & AO_LISP_FUNC_FREE_ARGS && !ao_lisp_stack_marked(ao_lisp_stack))
273 ao_lisp_cons_free(ao_lisp_poly_cons(ao_lisp_stack->values));
276 ao_lisp_stack->values = AO_LISP_NIL;
277 ao_lisp_stack->values_tail = AO_LISP_NIL;
278 DBGI(".. result "); DBG_POLY(ao_lisp_v); DBG ("\n");
279 DBGI(".. frame "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n");
282 DBGI(".. frame "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n");
283 ao_lisp_stack->state = eval_progn;
284 v = ao_lisp_lambda_eval();
285 ao_lisp_stack->sexprs = v;
286 ao_lisp_stack->values = AO_LISP_NIL;
287 ao_lisp_stack->values_tail = AO_LISP_NIL;
288 DBGI(".. sexprs "); DBG_POLY(ao_lisp_stack->sexprs); DBG("\n");
289 DBGI(".. frame "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n");
292 DBGI(".. stack "); DBG_POLY(ao_lisp_v); DBG("\n");
293 ao_lisp_v = ao_lisp_stack_eval();
294 DBGI(".. value "); DBG_POLY(ao_lisp_v); DBG("\n");
295 DBGI(".. frame "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n");
302 * Start evaluating the next cond clause
304 * If the list of clauses is empty, then
305 * the result of the cond is nil.
307 * Otherwise, set the current stack state to 'cond_test' and create a
308 * new stack context to evaluate the test s-expression. Once that's
309 * complete, we'll land in 'cond_test' to finish the clause.
312 ao_lisp_eval_cond(void)
314 DBGI("cond: "); DBG_POLY(ao_lisp_stack->sexprs); DBG("\n");
315 DBGI(".. frame "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n");
316 DBGI(".. saved frame "); DBG_POLY(ao_lisp_stack->frame); DBG("\n");
317 if (!ao_lisp_stack->sexprs) {
318 ao_lisp_v = AO_LISP_NIL;
319 ao_lisp_stack->state = eval_val;
321 ao_lisp_v = ao_lisp_poly_cons(ao_lisp_stack->sexprs)->car;
322 if (!ao_lisp_v || ao_lisp_poly_type(ao_lisp_v) != AO_LISP_CONS) {
323 ao_lisp_error(AO_LISP_INVALID, "invalid cond clause");
326 ao_lisp_v = ao_lisp_poly_cons(ao_lisp_v)->car;
327 if (ao_lisp_v == _ao_lisp_atom_else)
328 ao_lisp_v = _ao_lisp_bool_true;
329 ao_lisp_stack->state = eval_cond_test;
330 if (!ao_lisp_stack_push())
337 * Finish a cond clause.
339 * Check the value from the test expression, if
340 * non-nil, then set up to evaluate the value expression.
342 * Otherwise, step to the next clause and go back to the 'cond'
346 ao_lisp_eval_cond_test(void)
348 DBGI("cond_test: "); DBG_POLY(ao_lisp_v); DBG(" sexprs "); DBG_POLY(ao_lisp_stack->sexprs); DBG("\n");
349 DBGI(".. frame "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n");
350 DBGI(".. saved frame "); DBG_POLY(ao_lisp_stack->frame); DBG("\n");
351 if (ao_lisp_v != _ao_lisp_bool_false) {
352 struct ao_lisp_cons *car = ao_lisp_poly_cons(ao_lisp_poly_cons(ao_lisp_stack->sexprs)->car);
353 ao_poly c = car->cdr;
356 ao_lisp_stack->state = eval_progn;
357 ao_lisp_stack->sexprs = c;
359 ao_lisp_stack->state = eval_val;
361 ao_lisp_stack->sexprs = ao_lisp_poly_cons(ao_lisp_stack->sexprs)->cdr;
362 DBGI("next cond: "); DBG_POLY(ao_lisp_stack->sexprs); DBG("\n");
363 ao_lisp_stack->state = eval_cond;
369 * Evaluate a list of sexprs, returning the value from the last one.
371 * ao_lisp_progn records the list in stack->sexprs, so we just need to
372 * walk that list. Set ao_lisp_v to the car of the list and jump to
373 * eval_sexpr. When that's done, it will land in eval_val. For all but
374 * the last, leave a stack frame with eval_progn set so that we come
375 * back here. For the last, don't add a stack frame so that we can
379 ao_lisp_eval_progn(void)
381 DBGI("progn: "); DBG_POLY(ao_lisp_v); DBG(" sexprs "); DBG_POLY(ao_lisp_stack->sexprs); DBG("\n");
382 DBGI(".. frame "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n");
383 DBGI(".. saved frame "); DBG_POLY(ao_lisp_stack->frame); DBG("\n");
385 if (!ao_lisp_stack->sexprs) {
386 ao_lisp_v = AO_LISP_NIL;
387 ao_lisp_stack->state = eval_val;
389 ao_lisp_v = ao_lisp_poly_cons(ao_lisp_stack->sexprs)->car;
390 ao_lisp_stack->sexprs = ao_lisp_poly_cons(ao_lisp_stack->sexprs)->cdr;
392 /* If there are more sexprs to do, then come back here, otherwise
393 * return the value of the last one by just landing in eval_sexpr
395 if (ao_lisp_stack->sexprs) {
396 ao_lisp_stack->state = eval_progn;
397 if (!ao_lisp_stack_push())
400 ao_lisp_stack->state = eval_sexpr;
406 * Conditionally execute a list of sexprs while the first is true
409 ao_lisp_eval_while(void)
411 DBGI("while: "); DBG_POLY(ao_lisp_stack->sexprs); DBG("\n");
412 DBGI(".. frame "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n");
413 DBGI(".. saved frame "); DBG_POLY(ao_lisp_stack->frame); DBG("\n");
415 ao_lisp_stack->values = ao_lisp_v;
416 if (!ao_lisp_stack->sexprs) {
417 ao_lisp_v = AO_LISP_NIL;
418 ao_lisp_stack->state = eval_val;
420 ao_lisp_v = ao_lisp_poly_cons(ao_lisp_stack->sexprs)->car;
421 ao_lisp_stack->state = eval_while_test;
422 if (!ao_lisp_stack_push())
429 * Check the while condition, terminate the loop if nil. Otherwise keep going
432 ao_lisp_eval_while_test(void)
434 DBGI("while_test: "); DBG_POLY(ao_lisp_v); DBG(" sexprs "); DBG_POLY(ao_lisp_stack->sexprs); DBG("\n");
435 DBGI(".. frame "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n");
436 DBGI(".. saved frame "); DBG_POLY(ao_lisp_stack->frame); DBG("\n");
438 if (ao_lisp_v != _ao_lisp_bool_false) {
439 ao_lisp_stack->values = ao_lisp_v;
440 ao_lisp_v = ao_lisp_poly_cons(ao_lisp_stack->sexprs)->cdr;
441 ao_lisp_stack->state = eval_while;
442 if (!ao_lisp_stack_push())
444 ao_lisp_stack->state = eval_progn;
445 ao_lisp_stack->sexprs = ao_lisp_v;
449 ao_lisp_stack->state = eval_val;
450 ao_lisp_v = ao_lisp_stack->values;
456 * Replace the original sexpr with the macro expansion, then
460 ao_lisp_eval_macro(void)
462 DBGI("macro: "); DBG_POLY(ao_lisp_v); DBG(" sexprs "); DBG_POLY(ao_lisp_stack->sexprs); DBG("\n");
464 if (ao_lisp_v == AO_LISP_NIL)
466 if (ao_lisp_poly_type(ao_lisp_v) == AO_LISP_CONS) {
467 *ao_lisp_poly_cons(ao_lisp_stack->sexprs) = *ao_lisp_poly_cons(ao_lisp_v);
468 ao_lisp_v = ao_lisp_stack->sexprs;
469 DBGI("sexprs rewritten to: "); DBG_POLY(ao_lisp_v); DBG("\n");
471 ao_lisp_stack->sexprs = AO_LISP_NIL;
472 ao_lisp_stack->state = eval_sexpr;
476 static int (*const evals[])(void) = {
477 [eval_sexpr] = ao_lisp_eval_sexpr,
478 [eval_val] = ao_lisp_eval_val,
479 [eval_formal] = ao_lisp_eval_formal,
480 [eval_exec] = ao_lisp_eval_exec,
481 [eval_cond] = ao_lisp_eval_cond,
482 [eval_cond_test] = ao_lisp_eval_cond_test,
483 [eval_progn] = ao_lisp_eval_progn,
484 [eval_while] = ao_lisp_eval_while,
485 [eval_while_test] = ao_lisp_eval_while_test,
486 [eval_macro] = ao_lisp_eval_macro,
489 const char *ao_lisp_state_names[] = {
503 * Called at restore time to reset all execution state
507 ao_lisp_eval_clear_globals(void)
509 ao_lisp_stack = NULL;
510 ao_lisp_frame_current = NULL;
511 ao_lisp_v = AO_LISP_NIL;
515 ao_lisp_eval_restart(void)
517 return ao_lisp_stack_push();
521 ao_lisp_eval(ao_poly _v)
525 if (!ao_lisp_stack_push())
528 while (ao_lisp_stack) {
529 if (!(*evals[ao_lisp_stack->state])() || ao_lisp_exception) {
530 ao_lisp_stack_clear();
534 DBG_DO(if (ao_lisp_frame_current) {DBGI("frame left as "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n");});
535 ao_lisp_frame_current = NULL;