diff options
Diffstat (limited to 'com.c')
-rw-r--r-- | com.c | 44 |
1 files changed, 37 insertions, 7 deletions
@@ -27,7 +27,16 @@ Chunk chunk_new(State *S) { return (Chunk){ 0 }; } +Compiler compiler_new(Compiler *outer, Chunk *ch) { + return (Compiler){ + .S = outer->S, + .ch = ch, + }; +} + + size_t chunk_wbc(Compiler *C, uint8_t byte) { + printf("\t%p %hd\n",C, byte); Chunk *ch = C->ch; if (ch->bc.len == ch->bc.cap) { size_t newsz = (ch->bc.cap == 0 ? 8 : ch->bc.cap * 2); @@ -76,7 +85,7 @@ void single_form(Compiler *C, AstVec l, Op op) { chunk_wbc(C, op); } -void set_form(Compiler *C, AstVec l, Op op) { +void set_form(Compiler *C, AstVec l, Op _) { AstNode ident = l.vals[1]; if (ident.ty != AST_IDENT) { fprintf(stderr, "set's first argument must be identifier"); @@ -88,7 +97,7 @@ void set_form(Compiler *C, AstVec l, Op op) { chunk_wbc(C, chunk_wconst(C, VAL_OBJ(o))); } -void do_form(Compiler *C, AstVec l, Op op) { +void do_form(Compiler *C, AstVec l, Op _) { for (int i = 1; i < l.len - 1; i++) { compile_node(C, l.vals[i]); chunk_wbc(C, OP_DROP); @@ -96,7 +105,7 @@ void do_form(Compiler *C, AstVec l, Op op) { compile_node(C, l.vals[l.len - 1]); } -void if_form(Compiler *C, AstVec l, Op op) { +void if_form(Compiler *C, AstVec l, Op _) { // (if cond if-true if-false) // cond // 0branch ->A @@ -118,7 +127,7 @@ void if_form(Compiler *C, AstVec l, Op op) { patch(C, ph_b, dest_b - ph_b - 2); } -void while_form(Compiler *C, AstVec l, Op op) { +void while_form(Compiler *C, AstVec l, Op _) { // (while cond body ...) // A: // cond @@ -150,9 +159,29 @@ void arith_form(Compiler *C, AstVec l, Op op) { chunk_wbc(C, op); } -// void fn_form(Compiler *C, AstVec l, Op op) { -// Compiler subcompiler = compiler_new(C); - +void fn_form(Compiler *C, AstVec l, Op op) { + // (fn (arg arg arg) body ...) + if (l.vals[1].ty != AST_LIST) { + fprintf(stderr, "fn's first argument must be list"); + exit(1); + } + AstVec arglist = l.vals[1].as.list; + + ObjFunc *func = objfunc_new(C->S); + Compiler subcompiler = compiler_new(C, &func->chunk); + + for (int i = 2; i < l.len - 1; i++) { + compile_node(&subcompiler, l.vals[i]); + chunk_wbc(&subcompiler, OP_DROP); + } + compile_node(&subcompiler, l.vals[l.len-1]); + chunk_wbc(&subcompiler, OP_RET); + + chunk_wbc(C, OP_LOADK); + chunk_wbc(C, chunk_wconst(C, VAL_OBJ(func))); +} + + static BuiltinForm builtin_forms[] = { { "puts", 1, false, single_form, OP_PUTS }, @@ -161,6 +190,7 @@ static BuiltinForm builtin_forms[] = { { "do", 1, true, do_form, 0 }, { "if", 3, false, if_form, 0 }, { "while", 2, true, while_form, 0 }, + { "fn", 2, true, fn_form, 0 }, #define ARITH_OP(str, op) \ { str, 2, false, arith_form, op }, ARITH_OP("+", OP_ADD) |