altos/telegps-v2.0: git ignore make results
[fw/altos] / src / lisp / ao_lisp_frame.c
index e23a641384b74781349f4dae712bb2bb21b1f910..05f6d253ca23159fee0413c516e32cbbc9be0c8d 100644 (file)
@@ -46,7 +46,7 @@ frame_mark(void *addr)
                                  MDBG_OFFSET(ao_lisp_ref(v->atom)),
                                  MDBG_OFFSET(ao_lisp_ref(v->val)), f);
                }
-               frame = ao_lisp_poly_frame(frame->next);
+               frame = ao_lisp_poly_frame(frame->prev);
                MDBG_MOVE("frame next %d\n", MDBG_OFFSET(frame));
                if (!frame)
                        break;
@@ -62,7 +62,7 @@ frame_move(void *addr)
        int                     f;
 
        for (;;) {
-               struct ao_lisp_frame    *next;
+               struct ao_lisp_frame    *prev;
                int                     ret;
 
                MDBG_MOVE("frame move %d\n", MDBG_OFFSET(frame));
@@ -78,19 +78,19 @@ frame_move(void *addr)
                                  MDBG_OFFSET(ao_lisp_ref(v->atom)),
                                  MDBG_OFFSET(ao_lisp_ref(v->val)), f);
                }
-               next = ao_lisp_poly_frame(frame->next);
-               if (!next)
+               prev = ao_lisp_poly_frame(frame->prev);
+               if (!prev)
                        break;
-               ret = ao_lisp_move_memory(&ao_lisp_frame_type, (void **) &next);
-               if (next != ao_lisp_poly_frame(frame->next)) {
-                       MDBG_MOVE("frame next moved from %d to %d\n",
-                                 MDBG_OFFSET(ao_lisp_poly_frame(frame->next)),
-                                 MDBG_OFFSET(next));
-                       frame->next = ao_lisp_frame_poly(next);
+               ret = ao_lisp_move_memory(&ao_lisp_frame_type, (void **) &prev);
+               if (prev != ao_lisp_poly_frame(frame->prev)) {
+                       MDBG_MOVE("frame prev moved from %d to %d\n",
+                                 MDBG_OFFSET(ao_lisp_poly_frame(frame->prev)),
+                                 MDBG_OFFSET(prev));
+                       frame->prev = ao_lisp_frame_poly(prev);
                }
                if (ret)
                        break;
-               frame = next;
+               frame = prev;
        }
 }
 
@@ -109,27 +109,51 @@ ao_lisp_frame_print(ao_poly p)
 
        printf ("{");
        if (frame) {
-               for (f = 0; f < frame->num; f++) {
-                       if (f != 0)
-                               printf(", ");
-                       ao_lisp_poly_print(frame->vals[f].atom);
-                       printf(" = ");
-                       ao_lisp_poly_print(frame->vals[f].val);
+               if (frame->type & AO_LISP_FRAME_PRINT)
+                       printf("recurse...");
+               else {
+                       frame->type |= AO_LISP_FRAME_PRINT;
+                       for (f = 0; f < frame->num; f++) {
+                               if (f != 0)
+                                       printf(", ");
+                               ao_lisp_poly_print(frame->vals[f].atom);
+                               printf(" = ");
+                               ao_lisp_poly_print(frame->vals[f].val);
+                       }
+                       if (frame->prev)
+                               ao_lisp_poly_print(frame->prev);
+                       frame->type &= ~AO_LISP_FRAME_PRINT;
                }
-               if (frame->next)
-                       ao_lisp_poly_print(frame->next);
        }
        printf("}");
 }
 
+static int
+ao_lisp_frame_find(struct ao_lisp_frame *frame, int top, ao_poly atom)
+{
+       int l = 0;
+       int r = top - 1;
+       while (l <= r) {
+               int m = (l + r) >> 1;
+               if (frame->vals[m].atom < atom)
+                       l = m + 1;
+               else
+                       r = m - 1;
+       }
+       return l;
+}
+
 ao_poly *
 ao_lisp_frame_ref(struct ao_lisp_frame *frame, ao_poly atom)
 {
-       int f;
-       for (f = 0; f < frame->num; f++)
-               if (frame->vals[f].atom == atom)
-                       return &frame->vals[f].val;
-       return NULL;
+       int l = ao_lisp_frame_find(frame, frame->num, atom);
+
+       if (l >= frame->num)
+               return NULL;
+
+       if (frame->vals[l].atom != atom)
+               return NULL;
+       return &frame->vals[l].val;
 }
 
 int
@@ -143,7 +167,7 @@ ao_lisp_frame_set(struct ao_lisp_frame *frame, ao_poly atom, ao_poly val)
                                return 1;
                        }
                }
-               frame = ao_lisp_poly_frame(frame->next);
+               frame = ao_lisp_poly_frame(frame->prev);
        }
        return 0;
 }
@@ -155,25 +179,53 @@ ao_lisp_frame_get(struct ao_lisp_frame *frame, ao_poly atom)
                ao_poly *ref = ao_lisp_frame_ref(frame, atom);
                if (ref)
                        return *ref;
-               frame = ao_lisp_poly_frame(frame->next);
+               frame = ao_lisp_poly_frame(frame->prev);
        }
        return AO_LISP_NIL;
 }
 
+struct ao_lisp_frame   *ao_lisp_frame_free_list[AO_LISP_FRAME_FREE];
+
 struct ao_lisp_frame *
 ao_lisp_frame_new(int num)
 {
-       struct ao_lisp_frame *frame = ao_lisp_alloc(frame_num_size(num));
+       struct ao_lisp_frame    *frame;
 
-       if (!frame)
-               return NULL;
+       if (num < AO_LISP_FRAME_FREE && (frame = ao_lisp_frame_free_list[num]))
+               ao_lisp_frame_free_list[num] = ao_lisp_poly_frame(frame->prev);
+       else {
+               frame = ao_lisp_alloc(frame_num_size(num));
+               if (!frame)
+                       return NULL;
+       }
        frame->type = AO_LISP_FRAME;
        frame->num = num;
-       frame->next = AO_LISP_NIL;
+       frame->prev = AO_LISP_NIL;
        memset(frame->vals, '\0', num * sizeof (struct ao_lisp_val));
        return frame;
 }
 
+ao_poly
+ao_lisp_frame_mark(struct ao_lisp_frame *frame)
+{
+       if (!frame)
+               return AO_LISP_NIL;
+       frame->type |= AO_LISP_FRAME_MARK;
+       return ao_lisp_frame_poly(frame);
+}
+
+void
+ao_lisp_frame_free(struct ao_lisp_frame *frame)
+{
+       if (!ao_lisp_frame_marked(frame)) {
+               int     num = frame->num;
+               if (num < AO_LISP_FRAME_FREE) {
+                       frame->prev = ao_lisp_frame_poly(ao_lisp_frame_free_list[num]);
+                       ao_lisp_frame_free_list[num] = frame;
+               }
+       }
+}
+
 static struct ao_lisp_frame *
 ao_lisp_frame_realloc(struct ao_lisp_frame **frame_ref, int new_num)
 {
@@ -195,10 +247,23 @@ ao_lisp_frame_realloc(struct ao_lisp_frame **frame_ref, int new_num)
        if (copy > frame->num)
                copy = frame->num;
        memcpy(new->vals, frame->vals, copy * sizeof (struct ao_lisp_val));
-       new->next = frame->next;
+       new->prev = frame->prev;
+       ao_lisp_frame_free(frame);
        return new;
 }
 
+void
+ao_lisp_frame_bind(struct ao_lisp_frame *frame, int num, ao_poly atom, ao_poly val)
+{
+       int l = ao_lisp_frame_find(frame, num, atom);
+
+       memmove(&frame->vals[l+1],
+               &frame->vals[l],
+               (num - l) * sizeof (struct ao_lisp_val));
+       frame->vals[l].atom = atom;
+       frame->vals[l].val = val;
+}
+
 int
 ao_lisp_frame_add(struct ao_lisp_frame **frame_ref, ao_poly atom, ao_poly val)
 {
@@ -216,14 +281,13 @@ ao_lisp_frame_add(struct ao_lisp_frame **frame_ref, ao_poly atom, ao_poly val)
                        f = 0;
                        frame = ao_lisp_frame_new(1);
                }
-               atom = ao_lisp_poly_fetch(0);
-               val = ao_lisp_poly_fetch(1);
                if (!frame)
                        return 0;
                *frame_ref = frame;
-               frame->vals[f].atom = atom;
-               ref = &frame->vals[f].val;
-       }
-       *ref = val;
+               atom = ao_lisp_poly_fetch(0);
+               val = ao_lisp_poly_fetch(1);
+               ao_lisp_frame_bind(frame, frame->num - 1, atom, val);
+       } else
+               *ref = val;
        return 1;
 }