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_vals_num_size(int num)
20 return sizeof (struct ao_lisp_frame_vals) + num * sizeof (struct ao_lisp_val);
24 frame_vals_size(void *addr)
26 struct ao_lisp_frame_vals *vals = addr;
27 return frame_vals_num_size(vals->size);
31 frame_vals_mark(void *addr)
33 struct ao_lisp_frame_vals *vals = addr;
36 for (f = 0; f < vals->size; f++) {
37 struct ao_lisp_val *v = &vals->vals[f];
39 ao_lisp_poly_mark(v->val, 0);
40 MDBG_MOVE("frame mark atom %s %d val %d at %d\n",
41 ao_lisp_poly_atom(v->atom)->name,
42 MDBG_OFFSET(ao_lisp_ref(v->atom)),
43 MDBG_OFFSET(ao_lisp_ref(v->val)), f);
48 frame_vals_move(void *addr)
50 struct ao_lisp_frame_vals *vals = addr;
53 for (f = 0; f < vals->size; f++) {
54 struct ao_lisp_val *v = &vals->vals[f];
56 ao_lisp_poly_move(&v->atom, 0);
57 ao_lisp_poly_move(&v->val, 0);
58 MDBG_MOVE("frame move atom %s %d val %d at %d\n",
59 ao_lisp_poly_atom(v->atom)->name,
60 MDBG_OFFSET(ao_lisp_ref(v->atom)),
61 MDBG_OFFSET(ao_lisp_ref(v->val)), f);
65 const struct ao_lisp_type ao_lisp_frame_vals_type = {
66 .mark = frame_vals_mark,
67 .size = frame_vals_size,
68 .move = frame_vals_move,
73 frame_size(void *addr)
76 return sizeof (struct ao_lisp_frame);
80 frame_mark(void *addr)
82 struct ao_lisp_frame *frame = addr;
85 MDBG_MOVE("frame mark %d\n", MDBG_OFFSET(frame));
86 if (!AO_LISP_IS_POOL(frame))
88 ao_lisp_poly_mark(frame->vals, 0);
89 frame = ao_lisp_poly_frame(frame->prev);
90 MDBG_MOVE("frame next %d\n", MDBG_OFFSET(frame));
93 if (ao_lisp_mark_memory(&ao_lisp_frame_type, frame))
99 frame_move(void *addr)
101 struct ao_lisp_frame *frame = addr;
104 struct ao_lisp_frame *prev;
107 MDBG_MOVE("frame move %d\n", MDBG_OFFSET(frame));
108 if (!AO_LISP_IS_POOL(frame))
110 ao_lisp_poly_move(&frame->vals, 0);
111 prev = ao_lisp_poly_frame(frame->prev);
114 ret = ao_lisp_move_memory(&ao_lisp_frame_type, (void **) &prev);
115 if (prev != ao_lisp_poly_frame(frame->prev)) {
116 MDBG_MOVE("frame prev moved from %d to %d\n",
117 MDBG_OFFSET(ao_lisp_poly_frame(frame->prev)),
119 frame->prev = ao_lisp_frame_poly(prev);
127 const struct ao_lisp_type ao_lisp_frame_type = {
135 ao_lisp_frame_write(ao_poly p)
137 struct ao_lisp_frame *frame = ao_lisp_poly_frame(p);
138 struct ao_lisp_frame_vals *vals = ao_lisp_poly_frame_vals(frame->vals);
143 if (frame->type & AO_LISP_FRAME_PRINT)
144 printf("recurse...");
146 frame->type |= AO_LISP_FRAME_PRINT;
147 for (f = 0; f < frame->num; f++) {
150 ao_lisp_poly_write(vals->vals[f].atom);
152 ao_lisp_poly_write(vals->vals[f].val);
155 ao_lisp_poly_write(frame->prev);
156 frame->type &= ~AO_LISP_FRAME_PRINT;
163 ao_lisp_frame_find(struct ao_lisp_frame *frame, int top, ao_poly atom)
165 struct ao_lisp_frame_vals *vals = ao_lisp_poly_frame_vals(frame->vals);
170 int m = (l + r) >> 1;
171 if (vals->vals[m].atom < atom)
180 ao_lisp_frame_ref(struct ao_lisp_frame *frame, ao_poly atom)
182 struct ao_lisp_frame_vals *vals = ao_lisp_poly_frame_vals(frame->vals);
183 int l = ao_lisp_frame_find(frame, frame->num, atom);
188 if (vals->vals[l].atom != atom)
190 return &vals->vals[l].val;
193 struct ao_lisp_frame *ao_lisp_frame_free_list[AO_LISP_FRAME_FREE];
195 static struct ao_lisp_frame_vals *
196 ao_lisp_frame_vals_new(int num)
198 struct ao_lisp_frame_vals *vals;
200 vals = ao_lisp_alloc(frame_vals_num_size(num));
203 vals->type = AO_LISP_FRAME_VALS;
208 struct ao_lisp_frame *
209 ao_lisp_frame_new(int num)
211 struct ao_lisp_frame *frame;
212 struct ao_lisp_frame_vals *vals;
214 if (num < AO_LISP_FRAME_FREE && (frame = ao_lisp_frame_free_list[num])) {
215 ao_lisp_frame_free_list[num] = ao_lisp_poly_frame(frame->prev);
216 vals = ao_lisp_poly_frame_vals(frame->vals);
218 frame = ao_lisp_alloc(sizeof (struct ao_lisp_frame));
221 frame->type = AO_LISP_FRAME;
223 frame->prev = AO_LISP_NIL;
224 frame->vals = AO_LISP_NIL;
225 ao_lisp_poly_stash(0, ao_lisp_frame_poly(frame));
226 vals = ao_lisp_frame_vals_new(num);
227 frame = ao_lisp_poly_frame(ao_lisp_poly_fetch(0));
228 frame->vals = ao_lisp_frame_vals_poly(vals);
231 frame->prev = AO_LISP_NIL;
232 memset(vals, '\0', vals->size * sizeof (struct ao_lisp_val));
237 ao_lisp_frame_mark(struct ao_lisp_frame *frame)
241 frame->type |= AO_LISP_FRAME_MARK;
242 return ao_lisp_frame_poly(frame);
246 ao_lisp_frame_free(struct ao_lisp_frame *frame)
248 if (!ao_lisp_frame_marked(frame)) {
249 int num = frame->num;
250 if (num < AO_LISP_FRAME_FREE) {
251 frame->prev = ao_lisp_frame_poly(ao_lisp_frame_free_list[num]);
252 ao_lisp_frame_free_list[num] = frame;
257 static struct ao_lisp_frame *
258 ao_lisp_frame_realloc(struct ao_lisp_frame *frame, int new_num)
260 struct ao_lisp_frame_vals *vals;
261 struct ao_lisp_frame_vals *new_vals;
264 if (new_num == frame->num)
266 ao_lisp_frame_stash(0, frame);
267 new_vals = ao_lisp_frame_vals_new(new_num);
270 frame = ao_lisp_frame_fetch(0);
271 vals = ao_lisp_poly_frame_vals(frame->vals);
273 if (copy > frame->num)
275 memcpy(new_vals->vals, vals->vals, copy * sizeof (struct ao_lisp_val));
276 frame->vals = ao_lisp_frame_vals_poly(new_vals);
277 frame->num = new_num;
282 ao_lisp_frame_bind(struct ao_lisp_frame *frame, int num, ao_poly atom, ao_poly val)
284 struct ao_lisp_frame_vals *vals = ao_lisp_poly_frame_vals(frame->vals);
285 int l = ao_lisp_frame_find(frame, num, atom);
287 memmove(&vals->vals[l+1],
289 (num - l) * sizeof (struct ao_lisp_val));
290 vals->vals[l].atom = atom;
291 vals->vals[l].val = val;
295 ao_lisp_frame_add(struct ao_lisp_frame **frame_ref, ao_poly atom, ao_poly val)
297 struct ao_lisp_frame *frame = *frame_ref;
298 ao_poly *ref = frame ? ao_lisp_frame_ref(frame, atom) : NULL;
302 ao_lisp_poly_stash(0, atom);
303 ao_lisp_poly_stash(1, val);
306 frame = ao_lisp_frame_realloc(frame, f + 1);
309 frame = ao_lisp_frame_new(1);
314 atom = ao_lisp_poly_fetch(0);
315 val = ao_lisp_poly_fetch(1);
316 ao_lisp_frame_bind(frame, frame->num - 1, atom, val);