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 #define DBG(...) printf(__VA_ARGS__)
24 frame_num_size(int num)
26 return sizeof (struct ao_lisp_frame) + num * sizeof (struct ao_lisp_val);
30 frame_size(void *addr)
32 struct ao_lisp_frame *frame = addr;
33 return frame_num_size(frame->num);
36 #define OFFSET(a) ((int) ((uint8_t *) (ao_lisp_ref(a)) - ao_lisp_const))
39 frame_mark(void *addr)
41 struct ao_lisp_frame *frame = addr;
45 DBG("frame mark %p\n", frame);
46 if (!AO_LISP_IS_POOL(frame))
48 for (f = 0; f < frame->num; f++) {
49 struct ao_lisp_val *v = &frame->vals[f];
51 ao_lisp_poly_mark(v->val, 0);
52 DBG ("\tframe mark atom %s %d val %d at %d\n",
53 ao_lisp_poly_atom(v->atom)->name,
54 OFFSET(v->atom), OFFSET(v->val), f);
56 frame = ao_lisp_poly_frame(frame->next);
57 DBG("frame next %p\n", frame);
60 if (ao_lisp_mark_memory(frame, frame_size(frame)))
66 frame_move(void *addr)
68 struct ao_lisp_frame *frame = addr;
72 struct ao_lisp_frame *next;
75 DBG("frame move %p\n", frame);
76 if (!AO_LISP_IS_POOL(frame))
78 for (f = 0; f < frame->num; f++) {
79 struct ao_lisp_val *v = &frame->vals[f];
81 ao_lisp_poly_move(&v->atom, 0);
82 DBG("moved atom %s\n", ao_lisp_poly_atom(v->atom)->name);
83 ao_lisp_poly_move(&v->val, 0);
85 next = ao_lisp_poly_frame(frame->next);
88 ret = ao_lisp_move_memory((void **) &next, frame_size(next));
89 if (next != ao_lisp_poly_frame(frame->next))
90 frame->next = ao_lisp_frame_poly(next);
97 const struct ao_lisp_type ao_lisp_frame_type = {
104 ao_lisp_frame_print(ao_poly p)
106 struct ao_lisp_frame *frame = ao_lisp_poly_frame(p);
111 for (f = 0; f < frame->num; f++) {
114 ao_lisp_poly_print(frame->vals[f].atom);
116 ao_lisp_poly_print(frame->vals[f].val);
119 ao_lisp_poly_print(frame->next);
125 ao_lisp_frame_ref(struct ao_lisp_frame *frame, ao_poly atom)
128 for (f = 0; f < frame->num; f++)
129 if (frame->vals[f].atom == atom)
130 return &frame->vals[f].val;
135 ao_lisp_frame_set(struct ao_lisp_frame *frame, ao_poly atom, ao_poly val)
138 if (!AO_LISP_IS_CONST(frame)) {
139 ao_poly *ref = ao_lisp_frame_ref(frame, atom);
145 frame = ao_lisp_poly_frame(frame->next);
151 ao_lisp_frame_get(struct ao_lisp_frame *frame, ao_poly atom)
154 ao_poly *ref = ao_lisp_frame_ref(frame, atom);
157 frame = ao_lisp_poly_frame(frame->next);
162 struct ao_lisp_frame *
163 ao_lisp_frame_new(int num)
165 struct ao_lisp_frame *frame = ao_lisp_alloc(frame_num_size(num));
169 frame->type = AO_LISP_FRAME;
171 frame->next = AO_LISP_NIL;
172 memset(frame->vals, '\0', num * sizeof (struct ao_lisp_val));
176 static struct ao_lisp_frame *
177 ao_lisp_frame_realloc(struct ao_lisp_frame **frame_ref, int new_num)
179 struct ao_lisp_frame *frame = *frame_ref;
180 struct ao_lisp_frame *new;
183 if (new_num == frame->num)
185 new = ao_lisp_frame_new(new_num);
189 * Re-fetch the frame as it may have moved
190 * during the allocation
194 if (copy > frame->num)
196 memcpy(new->vals, frame->vals, copy * sizeof (struct ao_lisp_val));
197 new->next = frame->next;
202 ao_lisp_frame_add(struct ao_lisp_frame **frame_ref, ao_poly atom, ao_poly val)
204 struct ao_lisp_frame *frame = *frame_ref;
205 ao_poly *ref = frame ? ao_lisp_frame_ref(frame, atom) : NULL;
209 ao_lisp_root_poly_add(&atom);
210 ao_lisp_root_poly_add(&val);
213 frame = ao_lisp_frame_realloc(frame_ref, f + 1);
216 frame = ao_lisp_frame_new(1);
218 ao_lisp_root_clear(&atom);
219 ao_lisp_root_clear(&val);
223 DBG ("add atom %s %d, val %d at %d\n", ao_lisp_poly_atom(atom)->name, OFFSET(atom), OFFSET(val), f);
224 frame->vals[f].atom = atom;
225 ref = &frame->vals[f].val;