+enum eval_state {
+ eval_sexpr,
+ eval_val,
+ eval_formal,
+ eval_exec,
+ eval_exec_direct,
+ eval_cond,
+ eval_cond_test
+};
+
+struct ao_lisp_stack {
+ ao_poly prev;
+ uint8_t state;
+ uint8_t macro;
+ ao_poly actuals;
+ ao_poly formals;
+ ao_poly formals_tail;
+ ao_poly frame;
+};
+
+static struct ao_lisp_stack *
+ao_lisp_poly_stack(ao_poly p)
+{
+ return ao_lisp_ref(p);
+}
+
+static ao_poly
+ao_lisp_stack_poly(struct ao_lisp_stack *stack)
+{
+ return ao_lisp_poly(stack, AO_LISP_OTHER);
+}
+
+static int
+stack_size(void *addr)
+{
+ (void) addr;
+ return sizeof (struct ao_lisp_stack);
+}
+
+static void
+stack_mark(void *addr)
+{
+ struct ao_lisp_stack *stack = addr;
+ for (;;) {
+ ao_lisp_poly_mark(stack->actuals);
+ ao_lisp_poly_mark(stack->formals);
+ /* no need to mark formals_tail */
+ ao_lisp_poly_mark(stack->frame);
+ stack = ao_lisp_poly_stack(stack->prev);
+ if (ao_lisp_mark_memory(stack, sizeof (struct ao_lisp_stack)))
+ break;
+ }
+}
+
+static const struct ao_lisp_type ao_lisp_stack_type;
+
+#if DBG_CODE
+static void
+stack_validate_tail(struct ao_lisp_stack *stack)
+{
+ struct ao_lisp_cons *head = ao_lisp_poly_cons(stack->formals);
+ struct ao_lisp_cons *tail = ao_lisp_poly_cons(stack->formals_tail);
+ struct ao_lisp_cons *cons;
+ for (cons = head; cons && cons->cdr && cons != tail; cons = ao_lisp_poly_cons(cons->cdr))
+ ;
+ if (cons != tail || (tail && tail->cdr)) {
+ if (!tail) {
+ printf("tail null\n");
+ } else {
+ printf("tail validate fail head %d actual %d recorded %d\n",
+ OFFSET(head), OFFSET(cons), OFFSET(tail));
+ abort();
+ }
+ }
+}
+#else
+#define stack_validate_tail(s)
+#endif
+
+static void
+stack_move(void *addr)
+{
+ struct ao_lisp_stack *stack = addr;
+
+ while (stack) {
+ void *prev;
+ int ret;
+ (void) ao_lisp_poly_move(&stack->actuals);
+ (void) ao_lisp_poly_move(&stack->formals);
+ (void) ao_lisp_poly_move(&stack->formals_tail);
+ (void) ao_lisp_poly_move(&stack->frame);
+ prev = ao_lisp_poly_stack(stack->prev);
+ ret = ao_lisp_move(&ao_lisp_stack_type, &prev);
+ if (prev != ao_lisp_poly_stack(stack->prev))
+ stack->prev = ao_lisp_stack_poly(prev);
+ stack_validate_tail(stack);
+ if (ret)
+ break;
+ stack = ao_lisp_poly_stack(stack->prev);
+ }
+}
+
+static const struct ao_lisp_type ao_lisp_stack_type = {
+ .size = stack_size,
+ .mark = stack_mark,
+ .move = stack_move
+};
+
+static struct ao_lisp_stack *ao_lisp_stack;
+static ao_poly ao_lisp_v;
+static uint8_t been_here;
+
+#if DBG_CODE
+static void
+stack_validate_tails(void)
+{
+ struct ao_lisp_stack *stack;
+
+ for (stack = ao_lisp_stack; stack; stack = ao_lisp_poly_stack(stack->prev))
+ stack_validate_tail(stack);
+}
+#else
+#define stack_validate_tails(s)
+#endif
+