2 * Copyright © 2016 Keith Packard <keithp@keithp.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
18 frame_num_size(int num)
20 return sizeof (struct ao_lisp_frame) + num * sizeof (struct ao_lisp_val);
24 frame_size(void *addr)
26 struct ao_lisp_frame *frame = addr;
27 return frame_num_size(frame->num);
31 frame_mark(void *addr)
33 struct ao_lisp_frame *frame = addr;
37 MDBG_MOVE("frame mark %d\n", MDBG_OFFSET(frame));
38 if (!AO_LISP_IS_POOL(frame))
40 for (f = 0; f < frame->num; f++) {
41 struct ao_lisp_val *v = &frame->vals[f];
43 ao_lisp_poly_mark(v->val, 0);
44 MDBG_MOVE("frame mark atom %s %d val %d at %d\n",
45 ao_lisp_poly_atom(v->atom)->name,
46 MDBG_OFFSET(ao_lisp_ref(v->atom)),
47 MDBG_OFFSET(ao_lisp_ref(v->val)), f);
49 frame = ao_lisp_poly_frame(frame->prev);
50 MDBG_MOVE("frame next %d\n", MDBG_OFFSET(frame));
53 if (ao_lisp_mark_memory(&ao_lisp_frame_type, frame))
59 frame_move(void *addr)
61 struct ao_lisp_frame *frame = addr;
65 struct ao_lisp_frame *prev;
68 MDBG_MOVE("frame move %d\n", MDBG_OFFSET(frame));
69 if (!AO_LISP_IS_POOL(frame))
71 for (f = 0; f < frame->num; f++) {
72 struct ao_lisp_val *v = &frame->vals[f];
74 ao_lisp_poly_move(&v->atom, 0);
75 ao_lisp_poly_move(&v->val, 0);
76 MDBG_MOVE("frame move atom %s %d val %d at %d\n",
77 ao_lisp_poly_atom(v->atom)->name,
78 MDBG_OFFSET(ao_lisp_ref(v->atom)),
79 MDBG_OFFSET(ao_lisp_ref(v->val)), f);
81 prev = ao_lisp_poly_frame(frame->prev);
84 ret = ao_lisp_move_memory(&ao_lisp_frame_type, (void **) &prev);
85 if (prev != ao_lisp_poly_frame(frame->prev)) {
86 MDBG_MOVE("frame prev moved from %d to %d\n",
87 MDBG_OFFSET(ao_lisp_poly_frame(frame->prev)),
89 frame->prev = ao_lisp_frame_poly(prev);
97 const struct ao_lisp_type ao_lisp_frame_type = {
105 ao_lisp_frame_print(ao_poly p)
107 struct ao_lisp_frame *frame = ao_lisp_poly_frame(p);
112 if (frame->type & AO_LISP_FRAME_PRINT)
113 printf("recurse...");
115 frame->type |= AO_LISP_FRAME_PRINT;
116 for (f = 0; f < frame->num; f++) {
119 ao_lisp_poly_print(frame->vals[f].atom);
121 ao_lisp_poly_print(frame->vals[f].val);
124 ao_lisp_poly_print(frame->prev);
125 frame->type &= ~AO_LISP_FRAME_PRINT;
132 ao_lisp_frame_find(struct ao_lisp_frame *frame, int top, ao_poly atom)
137 int m = (l + r) >> 1;
138 if (frame->vals[m].atom < atom)
147 ao_lisp_frame_ref(struct ao_lisp_frame *frame, ao_poly atom)
149 int l = ao_lisp_frame_find(frame, frame->num, atom);
154 if (frame->vals[l].atom != atom)
156 return &frame->vals[l].val;
160 ao_lisp_frame_set(struct ao_lisp_frame *frame, ao_poly atom, ao_poly val)
163 if (!AO_LISP_IS_CONST(frame)) {
164 ao_poly *ref = ao_lisp_frame_ref(frame, atom);
170 frame = ao_lisp_poly_frame(frame->prev);
176 ao_lisp_frame_get(struct ao_lisp_frame *frame, ao_poly atom)
179 ao_poly *ref = ao_lisp_frame_ref(frame, atom);
182 frame = ao_lisp_poly_frame(frame->prev);
187 struct ao_lisp_frame *ao_lisp_frame_free_list[AO_LISP_FRAME_FREE];
189 struct ao_lisp_frame *
190 ao_lisp_frame_new(int num)
192 struct ao_lisp_frame *frame;
194 if (num < AO_LISP_FRAME_FREE && (frame = ao_lisp_frame_free_list[num]))
195 ao_lisp_frame_free_list[num] = ao_lisp_poly_frame(frame->prev);
197 frame = ao_lisp_alloc(frame_num_size(num));
201 frame->type = AO_LISP_FRAME;
203 frame->prev = AO_LISP_NIL;
204 memset(frame->vals, '\0', num * sizeof (struct ao_lisp_val));
209 ao_lisp_frame_mark(struct ao_lisp_frame *frame)
213 frame->type |= AO_LISP_FRAME_MARK;
214 return ao_lisp_frame_poly(frame);
218 ao_lisp_frame_free(struct ao_lisp_frame *frame)
220 if (!ao_lisp_frame_marked(frame)) {
221 int num = frame->num;
222 if (num < AO_LISP_FRAME_FREE) {
223 frame->prev = ao_lisp_frame_poly(ao_lisp_frame_free_list[num]);
224 ao_lisp_frame_free_list[num] = frame;
229 static struct ao_lisp_frame *
230 ao_lisp_frame_realloc(struct ao_lisp_frame **frame_ref, int new_num)
232 struct ao_lisp_frame *frame = *frame_ref;
233 struct ao_lisp_frame *new;
236 if (new_num == frame->num)
238 new = ao_lisp_frame_new(new_num);
242 * Re-fetch the frame as it may have moved
243 * during the allocation
247 if (copy > frame->num)
249 memcpy(new->vals, frame->vals, copy * sizeof (struct ao_lisp_val));
250 new->prev = frame->prev;
251 ao_lisp_frame_free(frame);
256 ao_lisp_frame_bind(struct ao_lisp_frame *frame, int num, ao_poly atom, ao_poly val)
258 int l = ao_lisp_frame_find(frame, num, atom);
260 memmove(&frame->vals[l+1],
262 (num - l) * sizeof (struct ao_lisp_val));
263 frame->vals[l].atom = atom;
264 frame->vals[l].val = val;
268 ao_lisp_frame_add(struct ao_lisp_frame **frame_ref, ao_poly atom, ao_poly val)
270 struct ao_lisp_frame *frame = *frame_ref;
271 ao_poly *ref = frame ? ao_lisp_frame_ref(frame, atom) : NULL;
275 ao_lisp_poly_stash(0, atom);
276 ao_lisp_poly_stash(1, val);
279 frame = ao_lisp_frame_realloc(frame_ref, f + 1);
282 frame = ao_lisp_frame_new(1);
287 atom = ao_lisp_poly_fetch(0);
288 val = ao_lisp_poly_fetch(1);
289 ao_lisp_frame_bind(frame, frame->num - 1, atom, val);