aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2022-01-09 14:34:03 +0100
committerBad Diode <bd@badd10de.dev>2022-01-09 14:34:03 +0100
commit6f5f0875685832be6efa75016a46d4c69dbcfd36 (patch)
tree3da16f0b61932ba432457b1c2a385bb867bd4718
parenta926335a9098a4ca42b447c012b038881c1e3559 (diff)
downloadbdl-6f5f0875685832be6efa75016a46d4c69dbcfd36.tar.gz
bdl-6f5f0875685832be6efa75016a46d4c69dbcfd36.zip
Add `compile_symbol` for ir
-rw-r--r--src/ir.h113
1 files changed, 82 insertions, 31 deletions
diff --git a/src/ir.h b/src/ir.h
index f039882..1c7a6c8 100644
--- a/src/ir.h
+++ b/src/ir.h
@@ -50,12 +50,16 @@ typedef enum Op {
50 OP_JUMP_IF_GE, 50 OP_JUMP_IF_GE,
51 OP_JUMP_IF_LE, 51 OP_JUMP_IF_LE,
52 // Variable access. 52 // Variable access.
53 // - Require an index corresponding to the local variable to store. 53 // - Require an index corresponding to the variable to store.
54 // - Consume the last item in the stack. 54 // - Consume the last item in the stack.
55 OP_STORE_LOCAL, 55 OP_STORE_LOCAL,
56 // - Require an index corresponding to the local variable to load. 56 OP_STORE_CAPTURED,
57 OP_STORE_PARAM,
58 // - Require an index corresponding to the variable to load.
57 // - The loaded value is pushed into the stack. 59 // - The loaded value is pushed into the stack.
58 OP_LOAD_LOCAL, 60 OP_LOAD_LOCAL,
61 OP_LOAD_CAPTURED,
62 OP_LOAD_PARAM,
59 // Primitive complex commands. 63 // Primitive complex commands.
60 // - Prints the last object in the stack. 64 // - Prints the last object in the stack.
61 OP_PRINT, 65 OP_PRINT,
@@ -69,32 +73,36 @@ typedef enum Op {
69} Op; 73} Op;
70 74
71static const char* ops_str[] = { 75static const char* ops_str[] = {
72 [OP_ADD] = "OP_ADD", 76 [OP_ADD] = "OP_ADD",
73 [OP_SUB] = "OP_SUB", 77 [OP_SUB] = "OP_SUB",
74 [OP_MUL] = "OP_MUL", 78 [OP_MUL] = "OP_MUL",
75 [OP_DIV] = "OP_DIV", 79 [OP_DIV] = "OP_DIV",
76 [OP_MOD] = "OP_MOD", 80 [OP_MOD] = "OP_MOD",
77 [OP_NOT] = "OP_NOT", 81 [OP_NOT] = "OP_NOT",
78 [OP_PUSH] = "OP_PUSH", 82 [OP_PUSH] = "OP_PUSH",
79 [OP_DROP] = "OP_DROP", 83 [OP_DROP] = "OP_DROP",
80 [OP_DUP] = "OP_DUP", 84 [OP_DUP] = "OP_DUP",
81 [OP_ROT_RIGHT] = "OP_ROT_RIGHT", 85 [OP_ROT_RIGHT] = "OP_ROT_RIGHT",
82 [OP_ROT_LEFT] = "OP_ROT_LEFT", 86 [OP_ROT_LEFT] = "OP_ROT_LEFT",
83 [OP_LABEL] = "OP_LABEL", 87 [OP_LABEL] = "OP_LABEL",
84 [OP_JUMP] = "OP_JUMP", 88 [OP_JUMP] = "OP_JUMP",
85 [OP_JUMP_IF_TRUE] = "OP_JUMP_IF_TRUE", 89 [OP_JUMP_IF_TRUE] = "OP_JUMP_IF_TRUE",
86 [OP_JUMP_IF_FALSE] = "OP_JUMP_IF_FALSE", 90 [OP_JUMP_IF_FALSE] = "OP_JUMP_IF_FALSE",
87 [OP_JUMP_IF_EQ] = "OP_JUMP_IF_EQ", 91 [OP_JUMP_IF_EQ] = "OP_JUMP_IF_EQ",
88 [OP_JUMP_IF_NEQ] = "OP_JUMP_IF_NEQ", 92 [OP_JUMP_IF_NEQ] = "OP_JUMP_IF_NEQ",
89 [OP_JUMP_IF_GT] = "OP_JUMP_IF_GT", 93 [OP_JUMP_IF_GT] = "OP_JUMP_IF_GT",
90 [OP_JUMP_IF_LT] = "OP_JUMP_IF_LT", 94 [OP_JUMP_IF_LT] = "OP_JUMP_IF_LT",
91 [OP_JUMP_IF_GE] = "OP_JUMP_IF_GE", 95 [OP_JUMP_IF_GE] = "OP_JUMP_IF_GE",
92 [OP_JUMP_IF_LE] = "OP_JUMP_IF_LE", 96 [OP_JUMP_IF_LE] = "OP_JUMP_IF_LE",
93 [OP_STORE_LOCAL] = "OP_STORE_LOCAL", 97 [OP_STORE_LOCAL] = "OP_STORE_LOCAL",
94 [OP_LOAD_LOCAL] = "OP_LOAD_LOCAL", 98 [OP_STORE_CAPTURED] = "OP_STORE_CAPTURED",
95 [OP_PRINT] = "OP_PRINT", 99 [OP_STORE_PARAM] = "OP_STORE_PARAM",
96 [OP_CALL] = "OP_CALL", 100 [OP_LOAD_LOCAL] = "OP_LOAD_LOCAL",
97 [OP_RETURN] = "OP_RETURN", 101 [OP_LOAD_CAPTURED] = "OP_LOAD_CAPTURED",
102 [OP_LOAD_PARAM] = "OP_LOAD_PARAM",
103 [OP_PRINT] = "OP_PRINT",
104 [OP_CALL] = "OP_CALL",
105 [OP_RETURN] = "OP_RETURN",
98}; 106};
99 107
100typedef struct Instruction { 108typedef struct Instruction {
@@ -129,8 +137,10 @@ typedef struct Procedure {
129 // Program code. 137 // Program code.
130 Instruction *instructions; 138 Instruction *instructions;
131 139
132 // Locals code. 140 // Variables.
133 Object **locals; 141 Object **locals;
142 Object **captured;
143 Object **params;
134} Procedure; 144} Procedure;
135 145
136typedef struct ProgramIr { 146typedef struct ProgramIr {
@@ -185,7 +195,11 @@ print_instruction(Instruction *instruction) {
185 printf("%-16s -> %zu\n", ops_str[op], instruction->label_id); 195 printf("%-16s -> %zu\n", ops_str[op], instruction->label_id);
186 } break; 196 } break;
187 case OP_STORE_LOCAL: 197 case OP_STORE_LOCAL:
188 case OP_LOAD_LOCAL: { 198 case OP_STORE_CAPTURED:
199 case OP_STORE_PARAM:
200 case OP_LOAD_LOCAL:
201 case OP_LOAD_CAPTURED:
202 case OP_LOAD_PARAM: {
189 printf("%-16s -> %zu\n", ops_str[op], instruction->index); 203 printf("%-16s -> %zu\n", ops_str[op], instruction->index);
190 } break; 204 } break;
191 default: { 205 default: {
@@ -210,6 +224,8 @@ proc_alloc(ProgramIr *program, StringView name, Procedure *parent) {
210 array_insert(proc->name, name.start, name.n); 224 array_insert(proc->name, name.start, name.n);
211 array_init(proc->instructions, 0); 225 array_init(proc->instructions, 0);
212 array_init(proc->locals, 0); 226 array_init(proc->locals, 0);
227 array_init(proc->captured, 0);
228 array_init(proc->params, 0);
213 proc->parent = parent; 229 proc->parent = parent;
214 array_push(program->procedures, proc); 230 array_push(program->procedures, proc);
215 return proc; 231 return proc;
@@ -417,6 +433,13 @@ compile_lambda(ProgramIr *program, Procedure *proc, Object *obj) {
417 } 433 }
418 array_push(program->lambdas, obj); 434 array_push(program->lambdas, obj);
419 Procedure *lambda = proc_alloc(program, STRING("lambda"), proc); 435 Procedure *lambda = proc_alloc(program, STRING("lambda"), proc);
436
437 // Parameters.
438 for (size_t i = 0; i < array_size(obj->params); ++i) {
439 array_push(lambda->params, obj->params[i]);
440 }
441
442 // Body.
420 for (size_t i = 0; i < array_size(obj->body) - 1; i++) { 443 for (size_t i = 0; i < array_size(obj->body) - 1; i++) {
421 compile_object(program, lambda, obj->body[i]); 444 compile_object(program, lambda, obj->body[i]);
422 } 445 }
@@ -470,6 +493,34 @@ compile_lambda(ProgramIr *program, Procedure *proc, Object *obj) {
470} 493}
471 494
472void 495void
496compile_symbol(ProgramIr *program, Procedure *proc, Object *obj) {
497 ssize_t idx = -1;
498
499 // Is a local variable?
500 idx = find_var_index(proc->locals, obj);
501 if (idx != -1) {
502 INST_VAR(proc, OP_LOAD_LOCAL, idx, obj->line, obj->col);
503 return;
504 }
505
506 // Is a captured variable?
507 idx = find_var_index(proc->captured, obj);
508 if (idx != -1) {
509 INST_VAR(proc, OP_LOAD_CAPTURED, idx, obj->line, obj->col);
510 return;
511 }
512
513 // Is a function parameter?
514 idx = find_var_index(proc->params, obj);
515 if (idx != -1) {
516 INST_VAR(proc, OP_LOAD_PARAM, idx, obj->line, obj->col);
517 return;
518 }
519
520 assert(idx != -1 && "unexpected index");
521}
522
523void
473compile_object(ProgramIr *program, Procedure *proc, Object *obj) { 524compile_object(ProgramIr *program, Procedure *proc, Object *obj) {
474 switch (obj->type) { 525 switch (obj->type) {
475 case OBJ_TYPE_NIL: 526 case OBJ_TYPE_NIL:
@@ -481,7 +532,7 @@ compile_object(ProgramIr *program, Procedure *proc, Object *obj) {
481 case OBJ_TYPE_IF: { compile_if(program, proc, obj); } break; 532 case OBJ_TYPE_IF: { compile_if(program, proc, obj); } break;
482 case OBJ_TYPE_LAMBDA: { compile_lambda(program, proc, obj); } break; 533 case OBJ_TYPE_LAMBDA: { compile_lambda(program, proc, obj); } break;
483 case OBJ_TYPE_DEF: { compile_def(program, proc, obj); } break; 534 case OBJ_TYPE_DEF: { compile_def(program, proc, obj); } break;
484 // case OBJ_TYPE_SYMBOL: { compile_symbol(obj); } break; 535 case OBJ_TYPE_SYMBOL: { compile_symbol(program, proc, obj); } break;
485 default: { 536 default: {
486 // TODO: assert? 537 // TODO: assert?
487 fprintf(stderr, "NOT IMPLEMENTED: compile_object for "); 538 fprintf(stderr, "NOT IMPLEMENTED: compile_object for ");