aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-12-30 17:01:50 +0100
committerBad Diode <bd@badd10de.dev>2021-12-30 17:01:50 +0100
commit073105080457218e67d999d6d70610914c9effe7 (patch)
treed5c2bddc67fce4e0883d3ced2e1502f900538080
parent082764ad89c1b9613b6894d6593dee66041a5e54 (diff)
downloadbdl-073105080457218e67d999d6d70610914c9effe7.tar.gz
bdl-073105080457218e67d999d6d70610914c9effe7.zip
Ensure new procedures are compiled only once
-rw-r--r--src/ir.h14
-rw-r--r--src/parser.c39
2 files changed, 51 insertions, 2 deletions
diff --git a/src/ir.h b/src/ir.h
index d92f912..cd2100c 100644
--- a/src/ir.h
+++ b/src/ir.h
@@ -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
136typedef struct ProgramIr { 136typedef 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
360compile_proc_call(ProgramIr *program, Procedure *proc, Object *obj) { 361compile_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
396void 400void
397compile_lambda(ProgramIr *program, Procedure *proc, Object *obj) { 401compile_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
474compile(Program program) { 485compile(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 }