altos/telegps-v2.0: git ignore make results
[fw/altos] / src / lisp / ao_lisp_eval.c
index 5cc1b75a6838c6eae1f82541b541e23ba6bc1942..3be7c9c4fa68c2fb29b60ec6f8b10ec6216ae705 100644 (file)
  * General Public License for more details.
  */
 
-#define DBG_EVAL 0
 #include "ao_lisp.h"
 #include <assert.h>
 
-const struct ao_lisp_type ao_lisp_stack_type;
-
-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->sexprs, 0);
-               ao_lisp_poly_mark(stack->values, 0);
-               /* no need to mark values_tail */
-               ao_lisp_poly_mark(stack->frame, 0);
-               ao_lisp_poly_mark(stack->list, 0);
-               stack = ao_lisp_poly_stack(stack->prev);
-               if (ao_lisp_mark_memory(&ao_lisp_stack_type, stack))
-                       break;
-       }
-}
-
-static void
-stack_move(void *addr)
-{
-       struct ao_lisp_stack    *stack = addr;
-
-       while (stack) {
-               struct ao_lisp_stack    *prev;
-               int                     ret;
-               (void) ao_lisp_poly_move(&stack->sexprs, 0);
-               (void) ao_lisp_poly_move(&stack->values, 0);
-               (void) ao_lisp_poly_move(&stack->values_tail, 0);
-               (void) ao_lisp_poly_move(&stack->frame, 0);
-               (void) ao_lisp_poly_move(&stack->list, 0);
-               prev = ao_lisp_poly_stack(stack->prev);
-               if (!prev)
-                       break;
-               ret = ao_lisp_move_memory(&ao_lisp_stack_type, (void **) &prev);
-               if (prev != ao_lisp_poly_stack(stack->prev))
-                       stack->prev = ao_lisp_stack_poly(prev);
-               if (ret)
-                       break;
-               stack = prev;
-       }
-}
-
-const struct ao_lisp_type ao_lisp_stack_type = {
-       .size = stack_size,
-       .mark = stack_mark,
-       .move = stack_move,
-       .name = "stack"
-};
-
 struct ao_lisp_stack           *ao_lisp_stack;
 ao_poly                                ao_lisp_v;
 
-struct ao_lisp_stack           *ao_lisp_stack_free_list;
-
 ao_poly
 ao_lisp_set_cond(struct ao_lisp_cons *c)
 {
@@ -86,68 +26,6 @@ ao_lisp_set_cond(struct ao_lisp_cons *c)
        return AO_LISP_NIL;
 }
 
-static void
-ao_lisp_stack_reset(struct ao_lisp_stack *stack)
-{
-       stack->state = eval_sexpr;
-       stack->sexprs = AO_LISP_NIL;
-       stack->values = AO_LISP_NIL;
-       stack->values_tail = AO_LISP_NIL;
-}
-
-
-static int
-ao_lisp_stack_push(void)
-{
-       struct ao_lisp_stack    *stack;
-       if (ao_lisp_stack_free_list) {
-               stack = ao_lisp_stack_free_list;
-               ao_lisp_stack_free_list = ao_lisp_poly_stack(stack->prev);
-       } else {
-               stack = ao_lisp_alloc(sizeof (struct ao_lisp_stack));
-               if (!stack)
-                       return 0;
-       }
-       stack->prev = ao_lisp_stack_poly(ao_lisp_stack);
-       stack->frame = ao_lisp_frame_poly(ao_lisp_frame_current);
-       stack->list = AO_LISP_NIL;
-       ao_lisp_stack = stack;
-       ao_lisp_stack_reset(stack);
-       DBGI("stack push\n");
-       DBG_FRAMES();
-       DBG_IN();
-       return 1;
-}
-
-static void
-ao_lisp_stack_pop(void)
-{
-       ao_poly prev;
-
-       if (!ao_lisp_stack)
-               return;
-       prev = ao_lisp_stack->prev;
-       ao_lisp_stack->prev = ao_lisp_stack_poly(ao_lisp_stack_free_list);
-       ao_lisp_stack_free_list = ao_lisp_stack;
-
-       ao_lisp_stack = ao_lisp_poly_stack(prev);
-       if (ao_lisp_stack)
-               ao_lisp_frame_current = ao_lisp_poly_frame(ao_lisp_stack->frame);
-       else
-               ao_lisp_frame_current = NULL;
-       DBG_OUT();
-       DBGI("stack pop\n");
-       DBG_FRAMES();
-}
-
-static void
-ao_lisp_stack_clear(void)
-{
-       ao_lisp_stack = NULL;
-       ao_lisp_frame_current = NULL;
-       ao_lisp_v = AO_LISP_NIL;
-}
-
 static int
 func_type(ao_poly func)
 {
@@ -158,6 +36,8 @@ func_type(ao_poly func)
                return ao_lisp_poly_builtin(func)->args & AO_LISP_FUNC_MASK;
        case AO_LISP_LAMBDA:
                return ao_lisp_poly_lambda(func)->args;
+       case AO_LISP_STACK:
+               return AO_LISP_FUNC_LAMBDA;
        default:
                ao_lisp_error(AO_LISP_INVALID, "not a func");
                return -1;
@@ -298,7 +178,7 @@ ao_lisp_eval_formal(void)
                        break;
                case AO_LISP_FUNC_MACRO:
                        /* Evaluate the result once more */
-                       ao_lisp_stack->state = eval_sexpr;
+                       ao_lisp_stack->state = eval_macro;
                        if (!ao_lisp_stack_push())
                                return 0;
 
@@ -306,9 +186,7 @@ ao_lisp_eval_formal(void)
                         * value and re-evaluate it
                         */
                        prev = ao_lisp_poly_stack(ao_lisp_stack->prev);
-                       ao_lisp_stack->state = eval_sexpr;
                        ao_lisp_stack->sexprs = prev->sexprs;
-                       prev->sexprs = AO_LISP_NIL;
 
                        DBGI(".. start macro\n");
                        DBGI(".. sexprs       "); DBG_POLY(ao_lisp_stack->sexprs); DBG("\n");
@@ -390,23 +268,32 @@ ao_lisp_eval_exec(void)
                                DBGI("set "); DBG_POLY(atom); DBG(" = "); DBG_POLY(val); DBG("\n");
                        });
                builtin = ao_lisp_poly_builtin(ao_lisp_v);
-               if (builtin->args & AO_LISP_FUNC_FREE_ARGS)
+               if (builtin->args & AO_LISP_FUNC_FREE_ARGS && !ao_lisp_stack_marked(ao_lisp_stack))
                        ao_lisp_cons_free(ao_lisp_poly_cons(ao_lisp_stack->values));
 
                ao_lisp_v = v;
+               ao_lisp_stack->values = AO_LISP_NIL;
+               ao_lisp_stack->values_tail = AO_LISP_NIL;
                DBGI(".. result "); DBG_POLY(ao_lisp_v); DBG ("\n");
                DBGI(".. frame "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n");
                break;
        case AO_LISP_LAMBDA:
-               ao_lisp_stack->state = eval_sexpr;
                DBGI(".. frame "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n");
-               ao_lisp_v = ao_lisp_lambda_eval();
-               DBGI(".. sexpr "); DBG_POLY(ao_lisp_v); DBG("\n");
+               ao_lisp_stack->state = eval_progn;
+               v = ao_lisp_lambda_eval();
+               ao_lisp_stack->sexprs = v;
+               ao_lisp_stack->values = AO_LISP_NIL;
+               ao_lisp_stack->values_tail = AO_LISP_NIL;
+               DBGI(".. sexprs "); DBG_POLY(ao_lisp_stack->sexprs); DBG("\n");
+               DBGI(".. frame "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n");
+               break;
+       case AO_LISP_STACK:
+               DBGI(".. stack "); DBG_POLY(ao_lisp_v); DBG("\n");
+               ao_lisp_v = ao_lisp_stack_eval();
+               DBGI(".. value "); DBG_POLY(ao_lisp_v); DBG("\n");
                DBGI(".. frame "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n");
                break;
        }
-       ao_lisp_stack->values = AO_LISP_NIL;
-       ao_lisp_stack->values_tail = AO_LISP_NIL;
        return 1;
 }
 
@@ -439,7 +326,6 @@ ao_lisp_eval_cond(void)
                ao_lisp_stack->state = eval_cond_test;
                if (!ao_lisp_stack_push())
                        return 0;
-               ao_lisp_stack->state = eval_sexpr;
        }
        return 1;
 }
@@ -461,11 +347,11 @@ ao_lisp_eval_cond_test(void)
        DBGI(".. saved frame "); DBG_POLY(ao_lisp_stack->frame); DBG("\n");
        if (ao_lisp_v) {
                struct ao_lisp_cons *car = ao_lisp_poly_cons(ao_lisp_poly_cons(ao_lisp_stack->sexprs)->car);
-               struct ao_lisp_cons *c = ao_lisp_poly_cons(car->cdr);
+               ao_poly c = car->cdr;
 
                if (c) {
-                       ao_lisp_stack->state = eval_sexpr;
-                       ao_lisp_v = c->car;
+                       ao_lisp_stack->state = eval_progn;
+                       ao_lisp_stack->sexprs = c;
                } else
                        ao_lisp_stack->state = eval_val;
        } else {
@@ -499,6 +385,10 @@ ao_lisp_eval_progn(void)
        } else {
                ao_lisp_v = ao_lisp_poly_cons(ao_lisp_stack->sexprs)->car;
                ao_lisp_stack->sexprs = ao_lisp_poly_cons(ao_lisp_stack->sexprs)->cdr;
+
+               /* If there are more sexprs to do, then come back here, otherwise
+                * return the value of the last one by just landing in eval_sexpr
+                */
                if (ao_lisp_stack->sexprs) {
                        ao_lisp_stack->state = eval_progn;
                        if (!ao_lisp_stack_push())
@@ -519,6 +409,7 @@ ao_lisp_eval_while(void)
        DBGI(".. frame "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n");
        DBGI(".. saved frame "); DBG_POLY(ao_lisp_stack->frame); DBG("\n");
 
+       ao_lisp_stack->values = ao_lisp_v;
        if (!ao_lisp_stack->sexprs) {
                ao_lisp_v = AO_LISP_NIL;
                ao_lisp_stack->state = eval_val;
@@ -527,7 +418,6 @@ ao_lisp_eval_while(void)
                ao_lisp_stack->state = eval_while_test;
                if (!ao_lisp_stack_push())
                        return 0;
-               ao_lisp_stack->state = eval_sexpr;
        }
        return 1;
 }
@@ -543,15 +433,40 @@ ao_lisp_eval_while_test(void)
        DBGI(".. saved frame "); DBG_POLY(ao_lisp_stack->frame); DBG("\n");
 
        if (ao_lisp_v) {
+               ao_lisp_stack->values = ao_lisp_v;
                ao_lisp_v = ao_lisp_poly_cons(ao_lisp_stack->sexprs)->cdr;
-               if (ao_lisp_v)
-                       ao_lisp_v = ao_lisp_poly_cons(ao_lisp_v)->car;
                ao_lisp_stack->state = eval_while;
                if (!ao_lisp_stack_push())
                        return 0;
+               ao_lisp_stack->state = eval_progn;
+               ao_lisp_stack->sexprs = ao_lisp_v;
        }
        else
+       {
                ao_lisp_stack->state = eval_val;
+               ao_lisp_v = ao_lisp_stack->values;
+       }
+       return 1;
+}
+
+/*
+ * Replace the original sexpr with the macro expansion, then
+ * execute that
+ */
+static int
+ao_lisp_eval_macro(void)
+{
+       DBGI("macro: "); DBG_POLY(ao_lisp_v); DBG(" sexprs "); DBG_POLY(ao_lisp_stack->sexprs); DBG("\n");
+
+       if (ao_lisp_v == AO_LISP_NIL)
+               ao_lisp_abort();
+       if (ao_lisp_poly_type(ao_lisp_v) == AO_LISP_CONS) {
+               *ao_lisp_poly_cons(ao_lisp_stack->sexprs) = *ao_lisp_poly_cons(ao_lisp_v);
+               ao_lisp_v = ao_lisp_stack->sexprs;
+               DBGI("sexprs rewritten to: "); DBG_POLY(ao_lisp_v); DBG("\n");
+       }
+       ao_lisp_stack->sexprs = AO_LISP_NIL;
+       ao_lisp_stack->state = eval_sexpr;
        return 1;
 }
 
@@ -565,6 +480,17 @@ static int (*const evals[])(void) = {
        [eval_progn] = ao_lisp_eval_progn,
        [eval_while] = ao_lisp_eval_while,
        [eval_while_test] = ao_lisp_eval_while_test,
+       [eval_macro] = ao_lisp_eval_macro,
+};
+
+const char *ao_lisp_state_names[] = {
+       "sexpr",
+       "val",
+       "formal",
+       "exec",
+       "cond",
+       "cond_test",
+       "progn",
 };
 
 /*