2 Copyright (C) 2017 Keziah Wesley
4 You can redistribute and/or modify this file under the terms of the
5 GNU Affero General Public License as published by the Free Software
6 Foundation, either version 3 of the License, or (at your option) any
9 This file 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 Affero General Public License for more details.
14 You should have received a copy of the GNU Affero General Public
15 License along with this file. If not, see
16 <http://www.gnu.org/licenses/>.
29 push_frame (void (*fn) (), tuple_object args, void (*cont) ())
31 // update current frame's continuation
32 cf->cont = new_subr (cont);
34 // allocate new frame, make current
37 cst += sizeof (frame) / sizeof (object);
39 // set new frame's frametop
40 cf->cont = new_subr (fn);
43 new_tuple ((object *) prev, sizeof (frame) / sizeof (object));
49 cf = (frame *) cf->prevframe.body;
50 cst = (object *) cf - sizeof (frame) / sizeof (object);
53 #define RETURN(x) do { ret = (x); pop_frame(); return; } while (0)
54 #define CALL_THEN(fn, args, cont) do { push_frame(fn, args, cont); return; } while (0)
55 #define TAILCALL(fn) do { cf->cont = fn; return; } while (0)
59 pool_object *x = POOL_OBJECT(o->head);
62 x = POOL_OBJECT(o->rest);
65 return mcall(evaluator, len);
71 // store result of previous call
74 // get next input, and advance input pointer
75 pool_ptr rest_in = as_list(&cf->args.body[0])->head;
77 RETURN(cf->locals[0]);
78 POOL_OBJECT(as_list(&cf->locals[1])->head)->rest =
79 as_list(&cf->locals[1])->head + (pool_ptr)sizeof(pool_object);
82 CALL_THEN (eval, new_tuple ((object*)POOL_OBJECT(rest_in), 1), eval_list);
88 assert (cf->args.len == 1);
89 switch (cf->args.body[0].type)
93 RETURN (cf->args.body[0]);
95 // Handle `head` now; then iterate on `.rest`.
96 if (!cf->args.body[0].list.head)
97 RETURN (cf->args.body[0]);
98 // locals: { list_object list, list_object tail }
100 // Allocate the new list contiguously and keep track of the
101 // current tail so we can build it in forward order.
103 new_list (POOL_PTR (pool_alloc (list_length (&cf->args.body[0].list))));
104 cf->locals[1] = cf->locals[0];
105 CALL_THEN (eval, new_tuple ((object*)POOL_OBJECT (cf->args.body[0].list.head), 1), eval_list);
107 case EVALTYPE_FORM: TAILCALL(eval_form);
108 case EVALTYPE_VECTOR: TAILCALL(eval_vector);
111 assert (0 && "I don't know how to eval that");