X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Flisp%2Fao_lisp_frame.c;h=05f6d253ca23159fee0413c516e32cbbc9be0c8d;hb=97cf9df882291b9e494b2f64f84eb37357a6ab31;hp=e23a641384b74781349f4dae712bb2bb21b1f910;hpb=ddb4b8d90478ae324aa207a7541352c1ac9451ee;p=fw%2Faltos diff --git a/src/lisp/ao_lisp_frame.c b/src/lisp/ao_lisp_frame.c index e23a6413..05f6d253 100644 --- a/src/lisp/ao_lisp_frame.c +++ b/src/lisp/ao_lisp_frame.c @@ -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; }