diff options
author | Bad Diode <bd@badd10de.dev> | 2021-12-30 17:01:50 +0100 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2021-12-30 17:01:50 +0100 |
commit | 073105080457218e67d999d6d70610914c9effe7 (patch) | |
tree | d5c2bddc67fce4e0883d3ced2e1502f900538080 /src | |
parent | 082764ad89c1b9613b6894d6593dee66041a5e54 (diff) | |
download | bdl-073105080457218e67d999d6d70610914c9effe7.tar.gz bdl-073105080457218e67d999d6d70610914c9effe7.zip |
Ensure new procedures are compiled only once
Diffstat (limited to 'src')
-rw-r--r-- | src/ir.h | 14 | ||||
-rw-r--r-- | src/parser.c | 39 |
2 files changed, 51 insertions, 2 deletions
@@ -60,7 +60,7 @@ typedef enum Op { | |||
60 | // - Prints the last object in the stack. | 60 | // - Prints the last object in the stack. |
61 | OP_PRINT, | 61 | OP_PRINT, |
62 | // Procedures. | 62 | // Procedures. |
63 | // - Requires a function name as parameter. | 63 | // - Consumes the last value in the stack, which must be a lambda. |
64 | OP_CALL, | 64 | OP_CALL, |
65 | // - Return position is on a know location of the stack based on the offset | 65 | // - Return position is on a know location of the stack based on the offset |
66 | // of locals, parameters, etc. | 66 | // of locals, parameters, etc. |
@@ -135,6 +135,7 @@ typedef struct Procedure { | |||
135 | 135 | ||
136 | typedef struct ProgramIr { | 136 | typedef struct ProgramIr { |
137 | Procedure **procedures; | 137 | Procedure **procedures; |
138 | Object **lambdas; | ||
138 | size_t labels; | 139 | size_t labels; |
139 | } ProgramIr; | 140 | } ProgramIr; |
140 | 141 | ||
@@ -360,6 +361,9 @@ void | |||
360 | compile_proc_call(ProgramIr *program, Procedure *proc, Object *obj) { | 361 | compile_proc_call(ProgramIr *program, Procedure *proc, Object *obj) { |
361 | if (IS_BUILTIN(obj->head)) { | 362 | if (IS_BUILTIN(obj->head)) { |
362 | compile_builtin(program, proc, obj); | 363 | compile_builtin(program, proc, obj); |
364 | } else if (IS_LAMBDA(obj->head)) { | ||
365 | compile_object(program, proc, obj->head); | ||
366 | INST_SIMPLE(proc, OP_CALL, obj->line, obj->col); | ||
363 | } else { | 367 | } else { |
364 | assert(false && "compile_proc_call: not implemented"); | 368 | assert(false && "compile_proc_call: not implemented"); |
365 | } | 369 | } |
@@ -395,6 +399,13 @@ compile_def(ProgramIr *program, Procedure *proc, Object *obj) { | |||
395 | 399 | ||
396 | void | 400 | void |
397 | compile_lambda(ProgramIr *program, Procedure *proc, Object *obj) { | 401 | compile_lambda(ProgramIr *program, Procedure *proc, Object *obj) { |
402 | for (size_t i = 0; i < array_size(program->lambdas); ++i) { | ||
403 | if (object_equal(program->lambdas[i], obj)) { | ||
404 | INST_ARG(proc, OP_PUSH, obj, obj->line, obj->col); | ||
405 | return; | ||
406 | } | ||
407 | } | ||
408 | array_push(program->lambdas, obj); | ||
398 | Procedure *lambda = proc_alloc(program, STRING("lambda"), proc); | 409 | Procedure *lambda = proc_alloc(program, STRING("lambda"), proc); |
399 | for (size_t i = 0; i < array_size(obj->body) - 1; i++) { | 410 | for (size_t i = 0; i < array_size(obj->body) - 1; i++) { |
400 | compile_object(program, lambda, obj->body[i]); | 411 | compile_object(program, lambda, obj->body[i]); |
@@ -474,6 +485,7 @@ ProgramIr | |||
474 | compile(Program program) { | 485 | compile(Program program) { |
475 | ProgramIr program_ir = {0}; | 486 | ProgramIr program_ir = {0}; |
476 | array_init(program_ir.procedures, 0); | 487 | array_init(program_ir.procedures, 0); |
488 | array_init(program_ir.lambdas, 0); | ||
477 | Procedure *main = proc_alloc(&program_ir, STRING("main"), NULL); | 489 | Procedure *main = proc_alloc(&program_ir, STRING("main"), NULL); |
478 | 490 | ||
479 | for (size_t i = 0; i < array_size(program.roots); i++) { | 491 | for (size_t i = 0; i < array_size(program.roots); i++) { |
diff --git a/src/parser.c b/src/parser.c index 29a0444..bd52c49 100644 --- a/src/parser.c +++ b/src/parser.c | |||
@@ -852,7 +852,44 @@ object_equal(Object *a, Object *b) { | |||
852 | return sv_equal(&a->text, &b->text); | 852 | return sv_equal(&a->text, &b->text); |
853 | } break; | 853 | } break; |
854 | case OBJ_TYPE_BUILTIN: { | 854 | case OBJ_TYPE_BUILTIN: { |
855 | return a->builtin = b->builtin; | 855 | return a->builtin == b->builtin; |
856 | } break; | ||
857 | case OBJ_TYPE_PAIR: { | ||
858 | Object *a_head = a->head; | ||
859 | Object *b_head = b->head; | ||
860 | if (!object_equal(a_head, b_head)) { | ||
861 | return false; | ||
862 | } | ||
863 | Object *a_tail = a->tail; | ||
864 | Object *b_tail = b->tail; | ||
865 | while (a_tail != NULL && b_tail != NULL) { | ||
866 | if (!object_equal(a_head, b_head)) { | ||
867 | return false; | ||
868 | } | ||
869 | a_head = a_tail->head; | ||
870 | b_head = b_tail->head; | ||
871 | a_tail = a_tail->tail; | ||
872 | b_tail = b_tail->tail; | ||
873 | } | ||
874 | if (a_tail == b_tail && object_equal(a_head, b_head)) { | ||
875 | return true; | ||
876 | } | ||
877 | return false; | ||
878 | } break; | ||
879 | case OBJ_TYPE_LAMBDA: { | ||
880 | size_t n_params_a = array_size(a->params); | ||
881 | size_t n_params_b = array_size(b->params); | ||
882 | size_t n_expr_a = array_size(a->body); | ||
883 | size_t n_expr_b = array_size(b->body); | ||
884 | if (n_params_a != n_params_b || n_expr_a != n_expr_b) { | ||
885 | return false; | ||
886 | } | ||
887 | for (size_t i = 0; i < array_size(a->body); ++i) { | ||
888 | if (!object_equal(a->body[i], b->body[i])) { | ||
889 | return false; | ||
890 | } | ||
891 | } | ||
892 | return true; | ||
856 | } break; | 893 | } break; |
857 | default: break; | 894 | default: break; |
858 | } | 895 | } |