+ for (stack = ao_lisp_stack; stack; stack = ao_lisp_poly_stack(stack->prev))
+ stack_validate_tail(stack);
+}
+#else
+#define stack_validate_tails(s)
+#endif
+
+ao_poly
+ao_lisp_set_cond(struct ao_lisp_cons *c)
+{
+ ao_lisp_stack->state = eval_cond;
+ ao_lisp_stack->actuals = ao_lisp_cons_poly(c);
+ return AO_LISP_NIL;
+}
+
+void
+ao_lisp_stack_reset(struct ao_lisp_stack *stack)
+{
+ stack->state = eval_sexpr;
+ stack->macro = 0;
+ stack->actuals = AO_LISP_NIL;
+ stack->formals = AO_LISP_NIL;
+ stack->formals_tail = AO_LISP_NIL;
+ stack->frame = ao_lisp_frame_poly(ao_lisp_frame_current);
+ stack_validate_tails();
+}
+
+int
+ao_lisp_stack_push(void)
+{
+ stack_validate_tails();
+ if (ao_lisp_stack) {
+ DBGI("formals "); DBG_POLY(ao_lisp_stack->formals); DBG("\n");
+ DBGI("actuals "); DBG_POLY(ao_lisp_stack->actuals); DBG("\n");
+ }
+ DBGI("stack push\n");
+ DBG_IN();
+ struct ao_lisp_stack *stack = ao_lisp_alloc(sizeof (struct ao_lisp_stack));
+ if (!stack)
+ return 0;
+ stack->prev = ao_lisp_stack_poly(ao_lisp_stack);
+ ao_lisp_stack = stack;
+ ao_lisp_stack_reset(stack);
+ stack_validate_tails();
+ return 1;
+}
+
+void
+ao_lisp_stack_pop(void)
+{
+ if (!ao_lisp_stack)
+ return;
+ stack_validate_tails();
+ DBG_OUT();
+ DBGI("stack pop\n");
+ ao_lisp_stack = ao_lisp_poly_stack(ao_lisp_stack->prev);
+ if (ao_lisp_stack)
+ ao_lisp_frame_current = ao_lisp_poly_frame(ao_lisp_stack->frame);
+ else
+ ao_lisp_frame_current = NULL;
+ if (ao_lisp_stack) {
+ DBGI("formals "); DBG_POLY(ao_lisp_stack->formals); DBG("\n");
+ DBGI("actuals "); DBG_POLY(ao_lisp_stack->actuals); DBG("\n");
+ }
+}
+
+static void
+ao_lisp_stack_clear(void)
+{
+ stack_validate_tails();
+ ao_lisp_stack = NULL;
+ ao_lisp_frame_current = NULL;
+}
+
+static ao_poly
+func_type(ao_poly func)
+{
+ struct ao_lisp_cons *cons;
+ struct ao_lisp_cons *args;
+ int f;
+
+ DBGI("func type "); DBG_POLY(func); DBG("\n");
+ if (func == AO_LISP_NIL)
+ return ao_lisp_error(AO_LISP_INVALID, "func is nil");
+ if (ao_lisp_poly_type(func) == AO_LISP_BUILTIN) {
+ struct ao_lisp_builtin *b = ao_lisp_poly_builtin(func);
+ return b->args;
+ } else if (ao_lisp_poly_type(func) == AO_LISP_CONS) {
+ cons = ao_lisp_poly_cons(func);
+ if (!ao_lisp_check_argc(_ao_lisp_atom_lambda, cons, 3, 3))
+ return AO_LISP_NIL;
+ if (!ao_lisp_check_argt(_ao_lisp_atom_lambda, cons, 0, AO_LISP_ATOM, 0))
+ return AO_LISP_NIL;
+ if (!ao_lisp_check_argt(_ao_lisp_atom_lambda, cons, 1, AO_LISP_CONS, 1))
+ return AO_LISP_NIL;
+ args = ao_lisp_poly_cons(ao_lisp_arg(cons, 1));
+ f = 0;
+ while (args) {
+ if (ao_lisp_poly_type(args->car) != AO_LISP_ATOM) {
+ return ao_lisp_error(ao_lisp_arg(cons, 0), "formal %d is not an atom", f);