altos/lisp: re-use small frames
[fw/altos] / src / lisp / ao_lisp_eval.c
1 /*
2  * Copyright © 2016 Keith Packard <keithp@keithp.com>
3  *
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.
8  *
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.
13  */
14
15 #define DBG_EVAL 0
16 #include "ao_lisp.h"
17 #include <assert.h>
18
19 const struct ao_lisp_type ao_lisp_stack_type;
20
21 static int
22 stack_size(void *addr)
23 {
24         (void) addr;
25         return sizeof (struct ao_lisp_stack);
26 }
27
28 static void
29 stack_mark(void *addr)
30 {
31         struct ao_lisp_stack    *stack = addr;
32         for (;;) {
33                 ao_lisp_poly_mark(stack->sexprs, 0);
34                 ao_lisp_poly_mark(stack->values, 0);
35                 /* no need to mark values_tail */
36                 ao_lisp_poly_mark(stack->frame, 0);
37                 ao_lisp_poly_mark(stack->list, 0);
38                 stack = ao_lisp_poly_stack(stack->prev);
39                 if (ao_lisp_mark_memory(&ao_lisp_stack_type, stack))
40                         break;
41         }
42 }
43
44 static void
45 stack_move(void *addr)
46 {
47         struct ao_lisp_stack    *stack = addr;
48
49         while (stack) {
50                 struct ao_lisp_stack    *prev;
51                 int                     ret;
52                 (void) ao_lisp_poly_move(&stack->sexprs, 0);
53                 (void) ao_lisp_poly_move(&stack->values, 0);
54                 (void) ao_lisp_poly_move(&stack->values_tail, 0);
55                 (void) ao_lisp_poly_move(&stack->frame, 0);
56                 (void) ao_lisp_poly_move(&stack->list, 0);
57                 prev = ao_lisp_poly_stack(stack->prev);
58                 if (!prev)
59                         break;
60                 ret = ao_lisp_move_memory(&ao_lisp_stack_type, (void **) &prev);
61                 if (prev != ao_lisp_poly_stack(stack->prev))
62                         stack->prev = ao_lisp_stack_poly(prev);
63                 if (ret)
64                         break;
65                 stack = prev;
66         }
67 }
68
69 const struct ao_lisp_type ao_lisp_stack_type = {
70         .size = stack_size,
71         .mark = stack_mark,
72         .move = stack_move,
73         .name = "stack"
74 };
75
76 struct ao_lisp_stack            *ao_lisp_stack;
77 ao_poly                         ao_lisp_v;
78
79 struct ao_lisp_stack            *ao_lisp_stack_free_list;
80
81 ao_poly
82 ao_lisp_set_cond(struct ao_lisp_cons *c)
83 {
84         ao_lisp_stack->state = eval_cond;
85         ao_lisp_stack->sexprs = ao_lisp_cons_poly(c);
86         return AO_LISP_NIL;
87 }
88
89 static void
90 ao_lisp_stack_reset(struct ao_lisp_stack *stack)
91 {
92         stack->state = eval_sexpr;
93         stack->sexprs = AO_LISP_NIL;
94         stack->values = AO_LISP_NIL;
95         stack->values_tail = AO_LISP_NIL;
96 }
97
98
99 static int
100 ao_lisp_stack_push(void)
101 {
102         struct ao_lisp_stack    *stack;
103         if (ao_lisp_stack_free_list) {
104                 stack = ao_lisp_stack_free_list;
105                 ao_lisp_stack_free_list = ao_lisp_poly_stack(stack->prev);
106         } else {
107                 stack = ao_lisp_alloc(sizeof (struct ao_lisp_stack));
108                 if (!stack)
109                         return 0;
110         }
111         stack->prev = ao_lisp_stack_poly(ao_lisp_stack);
112         stack->frame = ao_lisp_frame_poly(ao_lisp_frame_current);
113         stack->list = AO_LISP_NIL;
114         ao_lisp_stack = stack;
115         ao_lisp_stack_reset(stack);
116         DBGI("stack push\n");
117         DBG_FRAMES();
118         DBG_IN();
119         return 1;
120 }
121
122 static void
123 ao_lisp_stack_pop(void)
124 {
125         ao_poly                 prev;
126         struct ao_lisp_frame    *prev_frame;
127
128         if (!ao_lisp_stack)
129                 return;
130         prev = ao_lisp_stack->prev;
131         ao_lisp_stack->prev = ao_lisp_stack_poly(ao_lisp_stack_free_list);
132         ao_lisp_stack_free_list = ao_lisp_stack;
133
134         ao_lisp_stack = ao_lisp_poly_stack(prev);
135         prev_frame = ao_lisp_frame_current;
136         if (ao_lisp_stack)
137                 ao_lisp_frame_current = ao_lisp_poly_frame(ao_lisp_stack->frame);
138         else
139                 ao_lisp_frame_current = NULL;
140         if (ao_lisp_frame_current != prev_frame)
141                 ao_lisp_frame_free(prev_frame);
142         DBG_OUT();
143         DBGI("stack pop\n");
144         DBG_FRAMES();
145 }
146
147 static void
148 ao_lisp_stack_clear(void)
149 {
150         ao_lisp_stack = NULL;
151         ao_lisp_frame_current = NULL;
152         ao_lisp_v = AO_LISP_NIL;
153 }
154
155 static int
156 func_type(ao_poly func)
157 {
158         if (func == AO_LISP_NIL)
159                 return ao_lisp_error(AO_LISP_INVALID, "func is nil");
160         switch (ao_lisp_poly_type(func)) {
161         case AO_LISP_BUILTIN:
162                 return ao_lisp_poly_builtin(func)->args & AO_LISP_FUNC_MASK;
163         case AO_LISP_LAMBDA:
164                 return ao_lisp_poly_lambda(func)->args;
165         default:
166                 ao_lisp_error(AO_LISP_INVALID, "not a func");
167                 return -1;
168         }
169 }
170
171 /*
172  * Flattened eval to avoid stack issues
173  */
174
175 /*
176  * Evaluate an s-expression
177  *
178  * For a list, evaluate all of the elements and
179  * then execute the resulting function call.
180  *
181  * Each element of the list is evaluated in
182  * a clean stack context.
183  *
184  * The current stack state is set to 'formal' so that
185  * when the evaluation is complete, the value
186  * will get appended to the values list.
187  *
188  * For other types, compute the value directly.
189  */
190
191 static int
192 ao_lisp_eval_sexpr(void)
193 {
194         DBGI("sexpr: "); DBG_POLY(ao_lisp_v); DBG("\n");
195         switch (ao_lisp_poly_type(ao_lisp_v)) {
196         case AO_LISP_CONS:
197                 if (ao_lisp_v == AO_LISP_NIL) {
198                         if (!ao_lisp_stack->values) {
199                                 /*
200                                  * empty list evaluates to empty list
201                                  */
202                                 ao_lisp_v = AO_LISP_NIL;
203                                 ao_lisp_stack->state = eval_val;
204                         } else {
205                                 /*
206                                  * done with arguments, go execute it
207                                  */
208                                 ao_lisp_v = ao_lisp_poly_cons(ao_lisp_stack->values)->car;
209                                 ao_lisp_stack->state = eval_exec;
210                         }
211                 } else {
212                         if (!ao_lisp_stack->values)
213                                 ao_lisp_stack->list = ao_lisp_v;
214                         /*
215                          * Evaluate another argument and then switch
216                          * to 'formal' to add the value to the values
217                          * list
218                          */
219                         ao_lisp_stack->sexprs = ao_lisp_v;
220                         ao_lisp_stack->state = eval_formal;
221                         if (!ao_lisp_stack_push())
222                                 return 0;
223                         /*
224                          * push will reset the state to 'sexpr', which
225                          * will evaluate the expression
226                          */
227                         ao_lisp_v = ao_lisp_poly_cons(ao_lisp_v)->car;
228                 }
229                 break;
230         case AO_LISP_ATOM:
231                 DBGI("..frame "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n");
232                 ao_lisp_v = ao_lisp_atom_get(ao_lisp_v);
233                 /* fall through */
234         case AO_LISP_INT:
235         case AO_LISP_STRING:
236         case AO_LISP_BUILTIN:
237         case AO_LISP_LAMBDA:
238                 ao_lisp_stack->state = eval_val;
239                 break;
240         }
241         DBGI(".. result "); DBG_POLY(ao_lisp_v); DBG("\n");
242         return 1;
243 }
244
245 /*
246  * A value has been computed.
247  *
248  * If the value was computed from a macro,
249  * then we want to reset the current context
250  * to evaluate the macro result again.
251  *
252  * If not a macro, then pop the stack.
253  * If the stack is empty, we're done.
254  * Otherwise, the stack will contain
255  * the next state.
256  */
257
258 static int
259 ao_lisp_eval_val(void)
260 {
261         DBGI("val: "); DBG_POLY(ao_lisp_v); DBG("\n");
262         /*
263          * Value computed, pop the stack
264          * to figure out what to do with the value
265          */
266         ao_lisp_stack_pop();
267         DBGI("..state %d\n", ao_lisp_stack ? ao_lisp_stack->state : -1);
268         return 1;
269 }
270
271 /*
272  * A formal has been computed.
273  *
274  * If this is the first formal, then check to see if we've got a
275  * lamda/lexpr or macro/nlambda.
276  *
277  * For lambda/lexpr, go compute another formal.  This will terminate
278  * when the sexpr state sees nil.
279  *
280  * For macro/nlambda, we're done, so move the sexprs into the values
281  * and go execute it.
282  *
283  * Macros have an additional step of saving a stack frame holding the
284  * macro value execution context, which then gets the result of the
285  * macro to run
286  */
287
288 static int
289 ao_lisp_eval_formal(void)
290 {
291         ao_poly                 formal;
292         struct ao_lisp_stack    *prev;
293
294         DBGI("formal: "); DBG_POLY(ao_lisp_v); DBG("\n");
295
296         /* Check what kind of function we've got */
297         if (!ao_lisp_stack->values) {
298                 switch (func_type(ao_lisp_v)) {
299                 case AO_LISP_FUNC_LAMBDA:
300                 case AO_LISP_FUNC_LEXPR:
301                         DBGI(".. lambda or lexpr\n");
302                         break;
303                 case AO_LISP_FUNC_MACRO:
304                         /* Evaluate the result once more */
305                         ao_lisp_stack->state = eval_macro;
306                         if (!ao_lisp_stack_push())
307                                 return 0;
308
309                         /* After the function returns, take that
310                          * value and re-evaluate it
311                          */
312                         prev = ao_lisp_poly_stack(ao_lisp_stack->prev);
313                         ao_lisp_stack->state = eval_sexpr;
314                         ao_lisp_stack->sexprs = prev->sexprs;
315
316                         DBGI(".. start macro\n");
317                         DBGI(".. sexprs       "); DBG_POLY(ao_lisp_stack->sexprs); DBG("\n");
318                         DBGI(".. values       "); DBG_POLY(ao_lisp_stack->values); DBG("\n");
319                         DBG_FRAMES();
320
321                         /* fall through ... */
322                 case AO_LISP_FUNC_NLAMBDA:
323                         DBGI(".. nlambda or macro\n");
324
325                         /* use the raw sexprs as values */
326                         ao_lisp_stack->values = ao_lisp_stack->sexprs;
327                         ao_lisp_stack->values_tail = AO_LISP_NIL;
328                         ao_lisp_stack->state = eval_exec;
329
330                         /* ready to execute now */
331                         return 1;
332                 case -1:
333                         return 0;
334                 }
335         }
336
337         /* Append formal to list of values */
338         formal = ao_lisp_cons_poly(ao_lisp_cons_cons(ao_lisp_v, NULL));
339         if (!formal)
340                 return 0;
341
342         if (ao_lisp_stack->values_tail)
343                 ao_lisp_poly_cons(ao_lisp_stack->values_tail)->cdr = formal;
344         else
345                 ao_lisp_stack->values = formal;
346         ao_lisp_stack->values_tail = formal;
347
348         DBGI(".. values "); DBG_POLY(ao_lisp_stack->values); DBG("\n");
349
350         /*
351          * Step to the next argument, if this is last, then
352          * 'sexpr' will end up switching to 'exec'
353          */
354         ao_lisp_v = ao_lisp_poly_cons(ao_lisp_stack->sexprs)->cdr;
355
356         ao_lisp_stack->state = eval_sexpr;
357
358         DBGI(".. "); DBG_POLY(ao_lisp_v); DBG("\n");
359         return 1;
360 }
361
362 /*
363  * Start executing a function call
364  *
365  * Most builtins are easy, just call the function.
366  * 'cond' is magic; it sticks the list of clauses
367  * in 'sexprs' and switches to 'cond' state. That
368  * bit of magic is done in ao_lisp_set_cond.
369  *
370  * Lambdas build a new frame to hold the locals and
371  * then re-use the current stack context to evaluate
372  * the s-expression from the lambda.
373  */
374
375 static int
376 ao_lisp_eval_exec(void)
377 {
378         ao_poly v;
379         struct ao_lisp_builtin  *builtin;
380
381         DBGI("exec: "); DBG_POLY(ao_lisp_v); DBG(" values "); DBG_POLY(ao_lisp_stack->values); DBG ("\n");
382         ao_lisp_stack->sexprs = AO_LISP_NIL;
383         switch (ao_lisp_poly_type(ao_lisp_v)) {
384         case AO_LISP_BUILTIN:
385                 ao_lisp_stack->state = eval_val;
386                 builtin = ao_lisp_poly_builtin(ao_lisp_v);
387                 v = ao_lisp_func(builtin) (
388                         ao_lisp_poly_cons(ao_lisp_poly_cons(ao_lisp_stack->values)->cdr));
389                 DBG_DO(if (!ao_lisp_exception && ao_lisp_poly_builtin(ao_lisp_v)->func == builtin_set) {
390                                 struct ao_lisp_cons *cons = ao_lisp_poly_cons(ao_lisp_stack->values);
391                                 ao_poly atom = ao_lisp_arg(cons, 1);
392                                 ao_poly val = ao_lisp_arg(cons, 2);
393                                 DBGI("set "); DBG_POLY(atom); DBG(" = "); DBG_POLY(val); DBG("\n");
394                         });
395                 builtin = ao_lisp_poly_builtin(ao_lisp_v);
396                 if (builtin->args & AO_LISP_FUNC_FREE_ARGS)
397                         ao_lisp_cons_free(ao_lisp_poly_cons(ao_lisp_stack->values));
398
399                 ao_lisp_v = v;
400                 DBGI(".. result "); DBG_POLY(ao_lisp_v); DBG ("\n");
401                 DBGI(".. frame "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n");
402                 break;
403         case AO_LISP_LAMBDA:
404                 ao_lisp_stack->state = eval_sexpr;
405                 DBGI(".. frame "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n");
406                 ao_lisp_v = ao_lisp_lambda_eval();
407                 DBGI(".. sexpr "); DBG_POLY(ao_lisp_v); DBG("\n");
408                 DBGI(".. frame "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n");
409                 break;
410         }
411         ao_lisp_stack->values = AO_LISP_NIL;
412         ao_lisp_stack->values_tail = AO_LISP_NIL;
413         return 1;
414 }
415
416 /*
417  * Start evaluating the next cond clause
418  *
419  * If the list of clauses is empty, then
420  * the result of the cond is nil.
421  *
422  * Otherwise, set the current stack state to 'cond_test' and create a
423  * new stack context to evaluate the test s-expression. Once that's
424  * complete, we'll land in 'cond_test' to finish the clause.
425  */
426 static int
427 ao_lisp_eval_cond(void)
428 {
429         DBGI("cond: "); DBG_POLY(ao_lisp_stack->sexprs); DBG("\n");
430         DBGI(".. frame "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n");
431         DBGI(".. saved frame "); DBG_POLY(ao_lisp_stack->frame); DBG("\n");
432         if (!ao_lisp_stack->sexprs) {
433                 ao_lisp_v = AO_LISP_NIL;
434                 ao_lisp_stack->state = eval_val;
435         } else {
436                 ao_lisp_v = ao_lisp_poly_cons(ao_lisp_stack->sexprs)->car;
437                 if (!ao_lisp_v || ao_lisp_poly_type(ao_lisp_v) != AO_LISP_CONS) {
438                         ao_lisp_error(AO_LISP_INVALID, "invalid cond clause");
439                         return 0;
440                 }
441                 ao_lisp_v = ao_lisp_poly_cons(ao_lisp_v)->car;
442                 ao_lisp_stack->state = eval_cond_test;
443                 if (!ao_lisp_stack_push())
444                         return 0;
445                 ao_lisp_stack->state = eval_sexpr;
446         }
447         return 1;
448 }
449
450 /*
451  * Finish a cond clause.
452  *
453  * Check the value from the test expression, if
454  * non-nil, then set up to evaluate the value expression.
455  *
456  * Otherwise, step to the next clause and go back to the 'cond'
457  * state
458  */
459 static int
460 ao_lisp_eval_cond_test(void)
461 {
462         DBGI("cond_test: "); DBG_POLY(ao_lisp_v); DBG(" sexprs "); DBG_POLY(ao_lisp_stack->sexprs); DBG("\n");
463         DBGI(".. frame "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n");
464         DBGI(".. saved frame "); DBG_POLY(ao_lisp_stack->frame); DBG("\n");
465         if (ao_lisp_v) {
466                 struct ao_lisp_cons *car = ao_lisp_poly_cons(ao_lisp_poly_cons(ao_lisp_stack->sexprs)->car);
467                 struct ao_lisp_cons *c = ao_lisp_poly_cons(car->cdr);
468
469                 if (c) {
470                         ao_lisp_stack->state = eval_sexpr;
471                         ao_lisp_v = c->car;
472                 } else
473                         ao_lisp_stack->state = eval_val;
474         } else {
475                 ao_lisp_stack->sexprs = ao_lisp_poly_cons(ao_lisp_stack->sexprs)->cdr;
476                 DBGI("next cond: "); DBG_POLY(ao_lisp_stack->sexprs); DBG("\n");
477                 ao_lisp_stack->state = eval_cond;
478         }
479         return 1;
480 }
481
482 /*
483  * Evaluate a list of sexprs, returning the value from the last one.
484  *
485  * ao_lisp_progn records the list in stack->sexprs, so we just need to
486  * walk that list. Set ao_lisp_v to the car of the list and jump to
487  * eval_sexpr. When that's done, it will land in eval_val. For all but
488  * the last, leave a stack frame with eval_progn set so that we come
489  * back here. For the last, don't add a stack frame so that we can
490  * just continue on.
491  */
492 static int
493 ao_lisp_eval_progn(void)
494 {
495         DBGI("progn: "); DBG_POLY(ao_lisp_v); DBG(" sexprs "); DBG_POLY(ao_lisp_stack->sexprs); DBG("\n");
496         DBGI(".. frame "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n");
497         DBGI(".. saved frame "); DBG_POLY(ao_lisp_stack->frame); DBG("\n");
498
499         if (!ao_lisp_stack->sexprs) {
500                 ao_lisp_v = AO_LISP_NIL;
501                 ao_lisp_stack->state = eval_val;
502         } else {
503                 ao_lisp_v = ao_lisp_poly_cons(ao_lisp_stack->sexprs)->car;
504                 ao_lisp_stack->sexprs = ao_lisp_poly_cons(ao_lisp_stack->sexprs)->cdr;
505                 if (ao_lisp_stack->sexprs) {
506                         ao_lisp_stack->state = eval_progn;
507                         if (!ao_lisp_stack_push())
508                                 return 0;
509                 }
510                 ao_lisp_stack->state = eval_sexpr;
511         }
512         return 1;
513 }
514
515 /*
516  * Conditionally execute a list of sexprs while the first is true
517  */
518 static int
519 ao_lisp_eval_while(void)
520 {
521         DBGI("while: "); DBG_POLY(ao_lisp_stack->sexprs); DBG("\n");
522         DBGI(".. frame "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n");
523         DBGI(".. saved frame "); DBG_POLY(ao_lisp_stack->frame); DBG("\n");
524
525         if (!ao_lisp_stack->sexprs) {
526                 ao_lisp_v = AO_LISP_NIL;
527                 ao_lisp_stack->state = eval_val;
528         } else {
529                 ao_lisp_v = ao_lisp_poly_cons(ao_lisp_stack->sexprs)->car;
530                 ao_lisp_stack->state = eval_while_test;
531                 if (!ao_lisp_stack_push())
532                         return 0;
533                 ao_lisp_stack->state = eval_sexpr;
534         }
535         return 1;
536 }
537
538 /*
539  * Check the while condition, terminate the loop if nil. Otherwise keep going
540  */
541 static int
542 ao_lisp_eval_while_test(void)
543 {
544         DBGI("while_test: "); DBG_POLY(ao_lisp_v); DBG(" sexprs "); DBG_POLY(ao_lisp_stack->sexprs); DBG("\n");
545         DBGI(".. frame "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n");
546         DBGI(".. saved frame "); DBG_POLY(ao_lisp_stack->frame); DBG("\n");
547
548         if (ao_lisp_v) {
549                 ao_lisp_v = ao_lisp_poly_cons(ao_lisp_stack->sexprs)->cdr;
550                 if (ao_lisp_v)
551                         ao_lisp_v = ao_lisp_poly_cons(ao_lisp_v)->car;
552                 ao_lisp_stack->state = eval_while;
553                 if (!ao_lisp_stack_push())
554                         return 0;
555         }
556         else
557                 ao_lisp_stack->state = eval_val;
558         return 1;
559 }
560
561 /*
562  * Replace the original sexpr with the macro expansion, then
563  * execute that
564  */
565 static int
566 ao_lisp_eval_macro(void)
567 {
568         DBGI("macro: "); DBG_POLY(ao_lisp_v); DBG(" sexprs "); DBG_POLY(ao_lisp_stack->sexprs); DBG("\n");
569
570         if (ao_lisp_poly_type(ao_lisp_v) == AO_LISP_CONS) {
571                 *ao_lisp_poly_cons(ao_lisp_stack->sexprs) = *ao_lisp_poly_cons(ao_lisp_v);
572                 ao_lisp_v = ao_lisp_stack->sexprs;
573                 DBGI("sexprs rewritten to: "); DBG_POLY(ao_lisp_v); DBG("\n");
574         }
575         ao_lisp_stack->sexprs = AO_LISP_NIL;
576         ao_lisp_stack->state = eval_sexpr;
577         return 1;
578 }
579
580 static int (*const evals[])(void) = {
581         [eval_sexpr] = ao_lisp_eval_sexpr,
582         [eval_val] = ao_lisp_eval_val,
583         [eval_formal] = ao_lisp_eval_formal,
584         [eval_exec] = ao_lisp_eval_exec,
585         [eval_cond] = ao_lisp_eval_cond,
586         [eval_cond_test] = ao_lisp_eval_cond_test,
587         [eval_progn] = ao_lisp_eval_progn,
588         [eval_while] = ao_lisp_eval_while,
589         [eval_while_test] = ao_lisp_eval_while_test,
590         [eval_macro] = ao_lisp_eval_macro,
591 };
592
593 /*
594  * Called at restore time to reset all execution state
595  */
596
597 void
598 ao_lisp_eval_clear_globals(void)
599 {
600         ao_lisp_stack = NULL;
601         ao_lisp_frame_current = NULL;
602         ao_lisp_v = AO_LISP_NIL;
603 }
604
605 int
606 ao_lisp_eval_restart(void)
607 {
608         return ao_lisp_stack_push();
609 }
610
611 ao_poly
612 ao_lisp_eval(ao_poly _v)
613 {
614         ao_lisp_v = _v;
615
616         if (!ao_lisp_stack_push())
617                 return AO_LISP_NIL;
618
619         while (ao_lisp_stack) {
620                 if (!(*evals[ao_lisp_stack->state])() || ao_lisp_exception) {
621                         ao_lisp_stack_clear();
622                         return AO_LISP_NIL;
623                 }
624         }
625         DBG_DO(if (ao_lisp_frame_current) {DBGI("frame left as "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n");});
626         ao_lisp_frame_current = NULL;
627         return ao_lisp_v;
628 }