- struct ao_lisp_stack *stack;
- ao_poly formal;
-
- if (!been_here) {
- been_here = 1;
- ao_lisp_root_add(&ao_lisp_stack_type, &stack);
- }
-
- stack = ao_lisp_stack_push();
-
- for (;;) {
- if (ao_lisp_exception)
- return AO_LISP_NIL;
- switch (stack->state) {
- case eval_sexpr:
- DBGI("sexpr: "); DBG_POLY(v); DBG("\n");
- switch (ao_lisp_poly_type(v)) {
- case AO_LISP_CONS:
- if (v == AO_LISP_NIL) {
- stack->state = eval_exec;
- break;
- }
- stack->actuals = v;
- stack = ao_lisp_stack_push();
- v = ao_lisp_poly_cons(v)->car;
- break;
- case AO_LISP_ATOM:
- v = ao_lisp_atom_get(v);
- /* fall through */
- case AO_LISP_INT:
- case AO_LISP_STRING:
- stack->state = eval_val;
- break;
- }
- break;
- case eval_val:
- DBGI("val: "); DBG_POLY(v); DBG("\n");
- stack = ao_lisp_stack_pop();
- if (!stack)
- return v;
-
- stack->state = eval_sexpr;
- /* Check what kind of function we've got */
- if (!stack->formals) {
- switch (func_type(v)) {
- case AO_LISP_LAMBDA:
- case _ao_lisp_atom_lambda:
- case AO_LISP_LEXPR:
- case _ao_lisp_atom_lexpr:
- DBGI(".. lambda or lexpr\n");
- break;
- case AO_LISP_NLAMBDA:
- case _ao_lisp_atom_nlambda:
- case AO_LISP_MACRO:
- case _ao_lisp_atom_macro:
- DBGI(".. nlambda or macro\n");
- stack->formals = stack->actuals;
- stack->state = eval_exec_direct;
- break;
- }
- if (stack->state == eval_exec_direct)
- break;
- }
-
- formal = ao_lisp_cons_poly(ao_lisp_cons_cons(v, NULL));
- if (!formal) {
- ao_lisp_stack_clear();
- return AO_LISP_NIL;
- }
-
- if (stack->formals_tail)
- ao_lisp_poly_cons(stack->formals_tail)->cdr = formal;
- else
- stack->formals = formal;
- stack->formals_tail = formal;
-
- DBGI("formals now "); DBG_POLY(stack->formals); DBG("\n");
-
- v = ao_lisp_poly_cons(stack->actuals)->cdr;
-
- break;
- case eval_exec:
- v = ao_lisp_poly_cons(stack->formals)->car;
- case eval_exec_direct:
- DBGI("exec: "); DBG_POLY(v); DBG(" formals "); DBG_POLY(stack->formals); DBG ("\n");
- if (ao_lisp_poly_type(v) == AO_LISP_BUILTIN) {
- struct ao_lisp_builtin *b = ao_lisp_poly_builtin(v);
-
- v = ao_lisp_func(b) (ao_lisp_poly_cons(ao_lisp_poly_cons(stack->formals)->cdr));
- DBGI("builtin result:"); DBG_POLY(v); DBG ("\n");
- if (ao_lisp_exception) {
- ao_lisp_stack_clear();
- return AO_LISP_NIL;
- }
- stack->state = eval_val;
- break;
- } else {
- v = ao_lisp_lambda(ao_lisp_poly_cons(stack->formals));
- ao_lisp_stack_reset(stack);
- }
- break;
- }