aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-12-30 16:07:41 +0100
committerBad Diode <bd@badd10de.dev>2021-12-30 16:07:41 +0100
commit082764ad89c1b9613b6894d6593dee66041a5e54 (patch)
tree60700473f43e9b932d17e6be34973f331434f2d9
parente8a30ba744982f1f00db6a962bd849ef53514bff (diff)
downloadbdl-082764ad89c1b9613b6894d6593dee66041a5e54.tar.gz
bdl-082764ad89c1b9613b6894d6593dee66041a5e54.zip
Add WIP compilation of lambdas
-rw-r--r--src/ir.h173
1 files changed, 116 insertions, 57 deletions
diff --git a/src/ir.h b/src/ir.h
index d9706ee..d92f912 100644
--- a/src/ir.h
+++ b/src/ir.h
@@ -124,15 +124,13 @@ typedef struct Procedure {
124 // Procedure name. 124 // Procedure name.
125 char *name; 125 char *name;
126 126
127 struct Procedure *parent;
128
127 // Program code. 129 // Program code.
128 Instruction *instructions; 130 Instruction *instructions;
129 131
130 // Locals code. 132 // Locals code.
131 Object **locals; 133 Object **locals;
132
133 // Number of locals and parameters.
134 size_t n_params;
135 size_t n_locals;
136} Procedure; 134} Procedure;
137 135
138typedef struct ProgramIr { 136typedef struct ProgramIr {
@@ -205,12 +203,13 @@ print_procedure(Procedure *proc) {
205} 203}
206 204
207Procedure * 205Procedure *
208proc_alloc(ProgramIr *program, StringView name) { 206proc_alloc(ProgramIr *program, StringView name, Procedure *parent) {
209 Procedure *proc = calloc(1, sizeof(Procedure)); 207 Procedure *proc = calloc(1, sizeof(Procedure));
210 array_init(proc->name, name.n); 208 array_init(proc->name, name.n);
211 array_insert(proc->name, name.start, name.n); 209 array_insert(proc->name, name.start, name.n);
212 array_init(proc->instructions, 0); 210 array_init(proc->instructions, 0);
213 array_init(proc->locals, 0); 211 array_init(proc->locals, 0);
212 proc->parent = parent;
214 array_push(program->procedures, proc); 213 array_push(program->procedures, proc);
215 return proc; 214 return proc;
216} 215}
@@ -304,58 +303,63 @@ compile_or(ProgramIr *program, Procedure *proc,
304} 303}
305 304
306void 305void
307compile_proc_call(ProgramIr *program, Procedure *proc, Object *obj) { 306compile_builtin(ProgramIr *program, Procedure *proc, Object *obj) {
308 size_t line = obj->line; 307 size_t line = obj->line;
309 size_t col = obj->col; 308 size_t col = obj->col;
310 if (obj->head->type == OBJ_TYPE_BUILTIN) { 309 switch (obj->head->builtin) {
311 switch (obj->head->builtin) { 310 case BUILTIN_ADD: {
312 case BUILTIN_ADD: { 311 compile_arithmetic(program, proc, OP_ADD, line, col, obj->tail);
313 compile_arithmetic(program, proc, OP_ADD, line, col, obj->tail); 312 } break;
314 } break; 313 case BUILTIN_SUB: {
315 case BUILTIN_SUB: { 314 compile_arithmetic(program, proc, OP_SUB, line, col, obj->tail);
316 compile_arithmetic(program, proc, OP_SUB, line, col, obj->tail); 315 } break;
317 } break; 316 case BUILTIN_MUL: {
318 case BUILTIN_MUL: { 317 compile_arithmetic(program, proc, OP_MUL, line, col, obj->tail);
319 compile_arithmetic(program, proc, OP_MUL, line, col, obj->tail); 318 } break;
320 } break; 319 case BUILTIN_DIV: {
321 case BUILTIN_DIV: { 320 compile_arithmetic(program, proc, OP_DIV, line, col, obj->tail);
322 compile_arithmetic(program, proc, OP_DIV, line, col, obj->tail); 321 } break;
323 } break; 322 case BUILTIN_MOD: {
324 case BUILTIN_MOD: { 323 compile_arithmetic(program, proc, OP_MOD, line, col, obj->tail);
325 compile_arithmetic(program, proc, OP_MOD, line, col, obj->tail); 324 } break;
326 } break; 325 case BUILTIN_PRINT: {
327 case BUILTIN_PRINT: { 326 compile_print(program, proc, line, col, obj->tail);
328 compile_print(program, proc, line, col, obj->tail); 327 } break;
329 } break; 328 case BUILTIN_NOT: {
330 case BUILTIN_NOT: { 329 compile_not(program, proc, line, col, obj->tail);
331 compile_not(program, proc, line, col, obj->tail); 330 } break;
332 } break; 331 case BUILTIN_AND: {
333 case BUILTIN_AND: { 332 compile_and(program, proc, line, col, obj->tail);
334 compile_and(program, proc, line, col, obj->tail); 333 } break;
335 } break; 334 case BUILTIN_OR: {
336 case BUILTIN_OR: { 335 compile_or(program, proc, line, col, obj->tail);
337 compile_or(program, proc, line, col, obj->tail); 336 } break;
338 } break; 337 case BUILTIN_EQ: {
339 case BUILTIN_EQ: { 338 compile_numeric_cmp(program, proc, OP_JUMP_IF_NEQ, line, col, obj->tail);
340 compile_numeric_cmp(program, proc, OP_JUMP_IF_NEQ, line, col, obj->tail); 339 } break;
341 } break; 340 case BUILTIN_GT: {
342 case BUILTIN_GT: { 341 compile_numeric_cmp(program, proc, OP_JUMP_IF_LE, line, col, obj->tail);
343 compile_numeric_cmp(program, proc, OP_JUMP_IF_LE, line, col, obj->tail); 342 } break;
344 } break; 343 case BUILTIN_LT: {
345 case BUILTIN_LT: { 344 compile_numeric_cmp(program, proc, OP_JUMP_IF_GE, line, col, obj->tail);
346 compile_numeric_cmp(program, proc, OP_JUMP_IF_GE, line, col, obj->tail); 345 } break;
347 } break; 346 case BUILTIN_GE: {
348 case BUILTIN_GE: { 347 compile_numeric_cmp(program, proc, OP_JUMP_IF_LT, line, col, obj->tail);
349 compile_numeric_cmp(program, proc, OP_JUMP_IF_LT, line, col, obj->tail); 348 } break;
350 } break; 349 case BUILTIN_LE: {
351 case BUILTIN_LE: { 350 compile_numeric_cmp(program, proc, OP_JUMP_IF_GT, line, col, obj->tail);
352 compile_numeric_cmp(program, proc, OP_JUMP_IF_GT, line, col, obj->tail); 351 } break;
353 } break; 352 // TODO: cons, car, cdr, type checks (nil? zero? fixnum? bool? ...)
354 // TODO: cons, car, cdr, type checks (nil? zero? fixnum? bool? ...) 353 default: {
355 default: { 354 assert(false && "builtin not implemented");
356 assert(false && "builtin not implemented"); 355 } break;
357 } break; 356 }
358 } 357}
358
359void
360compile_proc_call(ProgramIr *program, Procedure *proc, Object *obj) {
361 if (IS_BUILTIN(obj->head)) {
362 compile_builtin(program, proc, obj);
359 } else { 363 } else {
360 assert(false && "compile_proc_call: not implemented"); 364 assert(false && "compile_proc_call: not implemented");
361 } 365 }
@@ -390,6 +394,61 @@ compile_def(ProgramIr *program, Procedure *proc, Object *obj) {
390} 394}
391 395
392void 396void
397compile_lambda(ProgramIr *program, Procedure *proc, Object *obj) {
398 Procedure *lambda = proc_alloc(program, STRING("lambda"), proc);
399 for (size_t i = 0; i < array_size(obj->body) - 1; i++) {
400 compile_object(program, lambda, obj->body[i]);
401 }
402 Object *last_expr = obj->body[array_size(obj->body) - 1];
403
404 // Tail Call Optimization.
405 // TODO: also for if statements
406 if (IS_PAIR(last_expr)) {
407 if (IS_BUILTIN(last_expr->head)) {
408 compile_builtin(program, lambda, last_expr);
409 } else {
410 // Discard the previous stack frame.
411 // context_printf(" mov rsp, rbp\n");
412
413 // size_t old_offset = n_locals + n_captured + n_params;
414 // size_t new_offset = compile_call_body(last_expr);
415 // context_printf(" mov rdi, [rbp - 8]\n");
416 // for (size_t i = 0; i < new_offset + 1; i++) {
417 // context_printf(" mov rax, [rbp - 8 * %zu]\n", i + 1);
418 // context_printf(" mov [rbp + 8 * %zu], rax\n", old_offset - i);
419 // }
420
421 // // Set the stack pointer at the end of given parameters.
422 // context_printf(" mov rsp, rbp\n");
423 // ssize_t offset_diff = old_offset - new_offset;
424 // if (offset_diff > 0) {
425 // context_printf(" add rsp, 8 * %zu\n", offset_diff);
426 // } else {
427 // context_printf(" sub rsp, 8 * %zu\n", offset_diff);
428 // }
429
430 // context_printf(" jmp rdi\n");
431 }
432 } else {
433 // compile_nil();
434 compile_object(program, lambda, last_expr);
435
436 // // Return is stored in the `rax`.
437 // context_printf(" pop rax\n");
438
439 // // Restore the previous call frame.
440 // size_t rp_offset = (n_locals + n_params + n_captured + 1);
441 // context_printf(" mov rdi, [rbp + %zu]\n", 8 * rp_offset);
442 // context_printf(" mov rsp, rbp\n");
443 // context_printf(" add rsp, %zu\n", 8 * n_locals);
444 // context_printf(" jmp rdi\n");
445 }
446 INST_SIMPLE(lambda, OP_RETURN, obj->line, obj->col);
447
448 INST_ARG(proc, OP_PUSH, obj, obj->line, obj->col);
449}
450
451void
393compile_object(ProgramIr *program, Procedure *proc, Object *obj) { 452compile_object(ProgramIr *program, Procedure *proc, Object *obj) {
394 switch (obj->type) { 453 switch (obj->type) {
395 case OBJ_TYPE_NIL: 454 case OBJ_TYPE_NIL:
@@ -399,7 +458,7 @@ compile_object(ProgramIr *program, Procedure *proc, Object *obj) {
399 case OBJ_TYPE_FIXNUM: { INST_ARG(proc, OP_PUSH, obj, obj->line, obj->col); } break; 458 case OBJ_TYPE_FIXNUM: { INST_ARG(proc, OP_PUSH, obj, obj->line, obj->col); } break;
400 case OBJ_TYPE_PAIR: { compile_proc_call(program, proc, obj); } break; 459 case OBJ_TYPE_PAIR: { compile_proc_call(program, proc, obj); } break;
401 case OBJ_TYPE_IF: { compile_if(program, proc, obj); } break; 460 case OBJ_TYPE_IF: { compile_if(program, proc, obj); } break;
402 // case OBJ_TYPE_LAMBDA: { compile_lambda(obj); } break; 461 case OBJ_TYPE_LAMBDA: { compile_lambda(program, proc, obj); } break;
403 case OBJ_TYPE_DEF: { compile_def(program, proc, obj); } break; 462 case OBJ_TYPE_DEF: { compile_def(program, proc, obj); } break;
404 // case OBJ_TYPE_SYMBOL: { compile_symbol(obj); } break; 463 // case OBJ_TYPE_SYMBOL: { compile_symbol(obj); } break;
405 default: { 464 default: {
@@ -415,7 +474,7 @@ ProgramIr
415compile(Program program) { 474compile(Program program) {
416 ProgramIr program_ir = {0}; 475 ProgramIr program_ir = {0};
417 array_init(program_ir.procedures, 0); 476 array_init(program_ir.procedures, 0);
418 Procedure *main = proc_alloc(&program_ir, STRING("main")); 477 Procedure *main = proc_alloc(&program_ir, STRING("main"), NULL);
419 478
420 for (size_t i = 0; i < array_size(program.roots); i++) { 479 for (size_t i = 0; i < array_size(program.roots); i++) {
421 Object *root = program.roots[i]; 480 Object *root = program.roots[i];