the hito embeddable programming language
1#include "eval.h"
2#include "builtins.h"
3#include "env.h"
4#include "syntax.h"
5#include "util.h"
6#include "value.h"
7#include <string.h>
8#include <stdlib.h>
9#include <stdio.h>
10
11
12
13typedef union amb_ptr {
14 expr_t *unevaled;
15 value_t *evaled;
16} amb_ptr;
17
18
19typedef struct {
20 enum {
21 FRAME_CALL_ARGS,
22 FRAME_CALL_CALLEE,
23 FRAME_CALL_ARGS_GROUP,
24 FRAME_CALL_ARGS_TUPLE,
25 FRAME_ALT,
26 FRAME_FGROUP_ALT,
27 FRAME_SEQ,
28 FRAME_LET,
29 FRAME_ENV
30 } tag;
31 source_t *source;
32 pos_t pos;
33 union {
34 struct {
35 expr_t **arguments;
36 size_t nargs;
37 } call_callee;
38 struct {
39 expr_t **arguments;
40 size_t nargs;
41 size_t arg_base;
42 } call_args;
43 struct {
44 expr_t *orelse;
45 } alt;
46 struct {
47 value_t *orelse;
48 } fgroup_alt;
49 struct {
50 expr_t *after;
51 } seq;
52 struct {
53 pattern_t pattern;
54 expr_t *in;
55 } let_binding;
56 struct {
57 size_t locals_top;
58 size_t locals_frame;
59 value_t *captures; /* should be an env value */
60 } env;
61 } as;
62} frame_t;
63typedef enum {
64 MODE_EVAL, MODE_RETURN
65} eval_mode_t;
66
67void _frame_debug_dump(frame_t *it) {
68 switch (it->tag) {
69 case FRAME_ALT:
70 printf("ALT(");
71 syntax_dump_expr(it->as.alt.orelse);
72 printf(")");
73 break;
74 case FRAME_SEQ:
75 printf("SEQ(");
76 syntax_dump_expr(it->as.seq.after);
77 printf(")");
78 break;
79 case FRAME_FGROUP_ALT:
80 printf("ALTF(");
81 value_debug_dump(it->as.fgroup_alt.orelse);
82 printf("..?)");
83 break;
84
85 case FRAME_ENV:
86 printf("ENV ..");
87 break;
88 case FRAME_LET:
89 printf("LET");
90 break;
91 case FRAME_CALL_ARGS_GROUP:
92 case FRAME_CALL_ARGS_TUPLE:
93 printf("CAT");
94 break;
95 case FRAME_CALL_ARGS:
96 printf("CA");
97 break;
98 case FRAME_CALL_CALLEE:
99 printf("CC");
100 break;
101 }
102}
103static inline size_t stack_bump(frame_t **stack, size_t stack_size, size_t stack_capacity) {
104 if (stack_size == stack_capacity) {
105 stack_capacity *= 2;
106 *stack = realloc(*stack, stack_capacity);
107 if (*stack == NULL)
108 die("Out of memory: cannot enlarge stack");
109 }
110 return stack_capacity;
111}
112
113static inline size_t arg_stack_bump(value_t ***stack, size_t stack_size, size_t stack_capacity) {
114 if (stack_size == stack_capacity) {
115 stack_capacity *= 2;
116 *stack = realloc(*stack, stack_capacity);
117 if (*stack == NULL)
118 die("Out of memory: cannot enlarge arg stack");
119 }
120 return stack_capacity;
121}
122
123bool _pattern_match(value_t *value,value_t ***bindings, expr_t *pattern) {
124 switch (pattern->tag) {
125 case EXPR_CALL:
126 if (pattern->as.call.callee->tag == EXPR_CONSTRUCTOR
127 && value->tag == VALUE_CONSTRUCTOR
128 && pattern->as.call.nargs == value->as.constructor.num_args
129 && pattern->as.call.callee->as.constructor == value->as.constructor.name) {
130 for (int i = 0; i < pattern->as.call.nargs; i++) {
131 if (!_pattern_match(value->as.constructor.args[i], bindings, pattern->as.call.arguments[i])) {
132 return false;
133 }
134 }
135 return true;
136 } else return false;
137 case EXPR_TUPLE:
138 // TODO
139 return false;
140 case EXPR_CONSTRUCTOR:
141 return (value->tag == VALUE_CONSTRUCTOR
142 && pattern->as.call.nargs == 0
143 && pattern->as.constructor == value->as.constructor.name);
144 case EXPR_PAT_IDENT: {
145 printf("%s:",pattern->as.ident);
146 (*bindings)[0] = value;
147 value_debug_dump(value);
148 (*bindings)++;
149 printf("\n");
150 return true;
151 }
152 case EXPR_INT_LIT: return (value->tag == VALUE_INT && value->as.integer == pattern->as.int_lit);
153 case EXPR_FLOAT_LIT: return (value->tag == VALUE_FLOAT && value->as.floating == pattern->as.float_lit);
154 case EXPR_STRING_LIT: return (value->tag == VALUE_STRING && strcmp(value->as.string.string, pattern->as.string_lit) == 0);
155 default:
156 break;
157 }
158 return false;
159}
160
161value_t *eval(expr_t *expr, gc_t *gc) {
162
163 frame_t *stack = malloc(sizeof(frame_t) * 32);
164 if (stack == NULL)
165 die("Out of memory: cannot allocate control stack");
166 value_t** locals = malloc(sizeof(value_t *) * 64);
167 if (locals == NULL)
168 die("Out of memory: cannot allocate locals stack");
169 value_t** arguments = malloc(sizeof(value_t *) * 64);
170 if (arguments == NULL)
171 die("Out of memory: cannot allocate arguments stack");
172
173 size_t stack_size = 0;
174 size_t stack_capacity = 32;
175 size_t locals_capacity = 64;
176 size_t locals_frame = 0;
177 size_t locals_size = 0;
178
179 size_t arguments_capacity = 64;
180 size_t arguments_size = 0;
181
182 eval_mode_t mode = MODE_EVAL;
183 amb_ptr focus;
184 focus.unevaled = expr;
185 value_t *env_val = value_alloc(gc);
186 env_val->tag = VALUE_ENV;
187 env_val->as.env = NULL;
188 while (!(mode == MODE_RETURN && stack_size == 0)) {
189 /* debugging code: */
190 for (int i = 0; i < stack_size; i++) {
191 _frame_debug_dump(stack + i);
192 if (i < stack_size - 1)
193 printf(", ");
194 }
195 printf(" | ");
196 for (int i = 0; i < locals_size; i++) {
197 if (i == locals_size - locals_frame - 1) {
198 printf("[");
199 }
200 value_debug_dump(locals[i]);
201 if (i == locals_size - locals_frame - 1) {
202 printf("]");
203 }
204 if (i < locals_size - 1)
205 printf(", ");
206 }
207 printf("{");
208 if (env_val->as.env) {env_debug_dump(env_val->as.env);};
209 printf("}");
210 printf(" | ");
211 for (int i = 0; i < arguments_size; i++) {
212 value_debug_dump(arguments[i]);
213 if (i < stack_size - 1)
214 printf(", ");
215 }
216 if (mode == MODE_EVAL) {
217 printf(" > ");
218 syntax_dump_expr(focus.unevaled);
219 printf("\n");
220 } else {
221 printf(" < ");
222 value_debug_dump(focus.evaled);
223 printf("\n");
224 }
225
226 switch (mode) {
227 case MODE_EVAL: switch (focus.unevaled->tag) {
228 case EXPR_VAR: {
229 value_t *val = (focus.unevaled->as.var >= locals_frame) ?
230 env_lookup(env_val->as.env, focus.unevaled->as.var - locals_frame) :
231 locals[locals_size - 1 - focus.unevaled->as.var];
232 mode = MODE_RETURN;
233 focus.evaled = val;
234 break;
235 }
236 case EXPR_BUILTIN: {
237 builtin_func_t *func = focus.unevaled->as.builtin;
238 value_t * val = value_alloc(gc);
239 val->tag = VALUE_BUILTIN;
240 val->as.builtin = func;
241 focus.evaled = val;
242 mode = MODE_RETURN;
243 break;
244 }
245 case EXPR_INT_LIT: {
246 focus.evaled = value_alloc_int(gc,focus.unevaled->as.int_lit);
247 mode = MODE_RETURN;
248 break;
249 }
250 case EXPR_FLOAT_LIT: {
251 focus.evaled = value_alloc_int(gc,focus.unevaled->as.float_lit);
252 mode = MODE_RETURN;
253 break;
254 }
255 case EXPR_STRING_LIT: {
256 focus.evaled = value_alloc_string(gc,focus.unevaled->as.string_lit,true);
257 mode = MODE_RETURN;
258 break;
259 }
260 case EXPR_CONSTRUCTOR: {
261 value_t *val = value_alloc(gc);
262 val->tag = VALUE_CONSTRUCTOR;
263 val->as.constructor.args = NULL;
264 val->as.constructor.num_args = 0;
265 val->as.constructor.name = focus.unevaled->as.constructor;
266 focus.evaled = val;
267 mode = MODE_RETURN;
268 break;
269 }
270 case EXPR_LAMBDA_COMPILED: {
271 value_t *val = value_alloc(gc);
272 val->tag = VALUE_CLOSURE;
273 val->as.closure.body = focus.unevaled->as.lambda.body;
274 val->as.closure.env = value_alloc(gc);
275 env_t *captured = env_capture(env_val->as.env, locals, locals_frame,locals_size, focus.unevaled->as.lambda.mask);
276 val->as.closure.env->tag = VALUE_ENV;
277 val->as.closure.env->as.env = captured;
278 val->as.closure.next = NULL;
279 val->as.closure.arity = focus.unevaled->as.lambda.args;
280 focus.evaled = val;
281 mode = MODE_RETURN;
282 break;
283 }
284 case EXPR_ALT:
285 stack_capacity = stack_bump(&stack, stack_size, stack_capacity);
286 stack[stack_size].as.alt.orelse = focus.unevaled->as.alt.orelse;
287 stack[stack_size].tag = FRAME_ALT;
288 stack_size++;
289 focus.unevaled = focus.unevaled->as.alt.try;
290 break;
291 case EXPR_SEQ:
292 stack_capacity = stack_bump(&stack, stack_size, stack_capacity);
293 stack[stack_size].as.seq.after = focus.unevaled->as.seq.then;
294 stack[stack_size].tag = FRAME_SEQ;
295 focus.unevaled = focus.unevaled->as.seq.first;
296 stack_size++;
297 break;
298 case EXPR_GROUP:
299 stack_capacity = stack_bump(&stack, stack_size, stack_capacity);
300 stack[stack_size].as.call_args.arguments = focus.unevaled->as.group.clauses + 1;
301 stack[stack_size].as.call_args.nargs = focus.unevaled->as.group.nclauses - 1;
302 stack[stack_size].as.call_args.arg_base = arguments_size;
303 stack[stack_size].tag = FRAME_CALL_ARGS_GROUP;
304 stack_size++;
305 focus.unevaled = focus.unevaled->as.group.clauses[0];
306 break;
307 case EXPR_CALL:
308 stack_capacity = stack_bump(&stack, stack_size, stack_capacity);
309 stack[stack_size].as.call_callee.arguments = focus.unevaled->as.call.arguments;
310 stack[stack_size].as.call_callee.nargs = focus.unevaled->as.call.nargs;
311 stack[stack_size].tag = FRAME_CALL_CALLEE;
312 stack_size++;
313 focus.unevaled = focus.unevaled->as.call.callee;
314 break;
315 case EXPR_LET_BINDING:
316 stack_capacity = stack_bump(&stack, stack_size, stack_capacity);
317 stack[stack_size].as.let_binding.in = focus.unevaled->as.let_binding.in;
318 stack[stack_size].as.let_binding.pattern = focus.unevaled->as.let_binding.pattern;
319 stack[stack_size].tag = FRAME_LET;
320 stack_size++;
321 focus.unevaled = focus.unevaled->as.let_binding.expr;
322 break;
323 case EXPR_PAT_IDENT:
324 case EXPR_LAMBDA:
325 die("Impossible: uncompiled expression found while evaluating");
326 }
327 break;
328 case MODE_RETURN: switch (stack[--stack_size].tag) {
329 case FRAME_ENV:
330 env_val = stack[stack_size].as.env.captures;
331 locals_frame = stack[stack_size].as.env.locals_frame;
332 locals_size = stack[stack_size].as.env.locals_top;
333 break;
334 case FRAME_ALT:
335 if (focus.evaled == NULL) {
336 focus.unevaled = stack[stack_size].as.alt.orelse;
337 mode = MODE_EVAL;
338 }
339 break;
340 case FRAME_FGROUP_ALT:
341 if (focus.evaled == NULL) {
342 env_val = stack[stack_size].as.fgroup_alt.orelse->as.closure.env;
343 focus.unevaled = stack[stack_size].as.fgroup_alt.orelse->as.closure.body;
344 mode = MODE_EVAL;
345 }
346 break;
347 case FRAME_SEQ:
348 if (focus.evaled != NULL) {
349 focus.unevaled = stack[stack_size].as.seq.after;
350 mode = MODE_EVAL;
351 }
352 break;
353 case FRAME_LET: {
354 size_t bound_vars = stack[stack_size].as.let_binding.pattern.bound_vars;
355 locals_capacity = arg_stack_bump(&locals, locals_size + bound_vars - 1, locals_capacity);
356 value_t **write_to = locals + locals_size;
357 if (_pattern_match(focus.evaled,&write_to, stack[stack_size].as.let_binding.pattern.expr)) {
358 locals_size += bound_vars;
359 locals_frame += bound_vars;
360 focus.unevaled = stack[stack_size].as.let_binding.in;
361 mode = MODE_EVAL;
362 if (stack_size > 0 && stack[stack_size-1].tag != FRAME_ENV || stack_size == 0) {
363 stack[stack_size].tag = FRAME_ENV;
364 stack[stack_size].as.env.captures = env_val;
365 stack[stack_size].as.env.locals_top = locals_size - 1;
366 stack[stack_size].as.env.locals_frame = locals_frame;
367 stack_size++;
368 }
369 } else {
370 focus.evaled = NULL;
371 }
372 break;
373 }
374 case FRAME_CALL_CALLEE: {
375 expr_t ** args = stack[stack_size].as.call_callee.arguments;
376 size_t nargs = stack[stack_size].as.call_callee.nargs;
377 stack[stack_size].tag = FRAME_CALL_ARGS;
378 stack[stack_size].as.call_args.arg_base = arguments_size;
379 stack[stack_size].as.call_args.arguments = args;
380 stack[stack_size].as.call_args.nargs = nargs;
381 // fall through
382 }
383 case FRAME_CALL_ARGS_GROUP:
384 case FRAME_CALL_ARGS: {
385 arguments_capacity = arg_stack_bump(&arguments, arguments_size, arguments_capacity);
386 arguments[arguments_size] = focus.evaled;
387 arguments_size++;
388 if (stack[stack_size].as.call_args.nargs > 0) {
389 focus.unevaled = stack[stack_size].as.call_args.arguments[0];
390 stack[stack_size].as.call_args.nargs--;
391 stack[stack_size].as.call_args.arguments++;
392 mode = MODE_EVAL;
393 stack_size++;
394 } else if (stack[stack_size].tag == FRAME_CALL_ARGS_GROUP) {
395 size_t num_args = arguments_size - stack[stack_size].as.call_args.arg_base;
396 value_t **args_start = arguments + stack[stack_size].as.call_args.arg_base;
397 printf("num_args %zu arg_base %zu\n",num_args,stack[stack_size].as.call_args.arg_base);
398 arguments_size = stack[stack_size].as.call_args.arg_base;
399 value_t *ret = args_start[num_args-1];
400 if (ret->tag != VALUE_CLOSURE) {
401 focus.evaled = NULL;
402 break;
403 }
404 size_t i = num_args;
405 while (i >= 2) {
406 if (args_start[i-2]->tag != VALUE_CLOSURE || args_start[i-2]->as.closure.arity != ret->as.closure.arity) {
407 ret = NULL;
408 break;
409 }
410 value_t *nret = value_alloc(gc);
411 nret->tag = VALUE_CLOSURE;
412 nret->as.closure.arity = ret->as.closure.arity;
413 nret->as.closure.env = args_start[i-2]->as.closure.env;
414 nret->as.closure.body = args_start[i-2]->as.closure.body;
415 nret->as.closure.next = ret;
416 ret = nret;
417 i--;
418 }
419 focus.evaled = ret;
420 } else if (stack[stack_size].tag == FRAME_CALL_ARGS) {
421 value_t *callee = arguments[stack[stack_size].as.call_args.arg_base];
422 size_t num_args = arguments_size - stack[stack_size].as.call_args.arg_base - 1;
423 value_t **args_start = arguments + stack[stack_size].as.call_args.arg_base + 1;
424 arguments_size = stack[stack_size].as.call_args.arg_base;
425 printf("num_args %zu arg_base %zu\n",num_args,stack[stack_size].as.call_args.arg_base);
426 printf("callee %d\n",callee->as.closure.arity);
427 if (callee == NULL) {
428 focus.evaled = NULL;
429 } else switch (callee->tag) {
430 case VALUE_BUILTIN:
431 focus.evaled = callee->as.builtin(gc,args_start, num_args);
432 break;
433 case VALUE_CLOSURE:
434 if (callee->as.closure.arity == num_args) {
435 printf("ARITY CHECK\n");
436 if (stack_size > 0 && stack[stack_size-1].tag != FRAME_ENV || stack_size == 0) {
437 stack[stack_size].as.env.captures = env_val;
438 stack[stack_size].as.env.locals_frame = locals_frame;
439 stack[stack_size].as.env.locals_top = locals_size;
440 stack[stack_size].tag = FRAME_ENV;
441 stack_size++;
442 }
443 locals_frame = num_args;
444 locals_capacity = arg_stack_bump(&locals, locals_size + num_args, locals_capacity);
445 memcpy(locals + locals_size, args_start, sizeof(value_t*) * num_args);
446 locals_size += num_args;
447
448 env_val = callee->as.closure.env;
449 focus.unevaled = callee->as.closure.body;
450 if (callee->as.closure.next != NULL) {
451 stack_bump(&stack, stack_size, stack_capacity);
452 stack[stack_size].as.fgroup_alt.orelse = callee->as.closure.next;
453 stack[stack_size].tag = FRAME_FGROUP_ALT;
454 stack_size++;
455 }
456 mode = MODE_EVAL;
457 } else {
458 focus.evaled = NULL;
459 }
460 break;
461 case VALUE_CONSTRUCTOR:
462 if (callee->as.constructor.args == NULL) {
463 value_t *val = value_alloc(gc);
464 val->tag = VALUE_CONSTRUCTOR;
465 val->as.constructor.args = malloc(sizeof(value_t*) * num_args);
466 if (val->as.constructor.args == NULL) {
467 die("Out of memory, can't allocate args buffer");
468 }
469 memcpy(val->as.constructor.args,args_start, sizeof(value_t*) * num_args);
470 val->as.constructor.num_args = num_args;
471 val->as.constructor.name = callee->as.constructor.name;
472 focus.evaled = val;
473 break;
474 }
475 //fall through
476 case VALUE_INT:
477 case VALUE_FLOAT:
478 case VALUE_STRING:
479 focus.evaled = NULL;
480 case VALUE_ENV: // should be impossible
481 focus.evaled = NULL;
482 }
483 }
484 break;
485 }
486 }
487 break;
488 }
489 }
490 free(arguments);
491 free(locals);
492 free(stack);
493 return focus.evaled;
494}
495