diff options
author | ubq323 <ubq323@ubq323.website> | 2024-06-22 12:23:55 +0100 |
---|---|---|
committer | ubq323 <ubq323@ubq323.website> | 2024-06-22 12:23:55 +0100 |
commit | 1d496f5f7f01b20fb34e63d1c85a33d8decd1894 (patch) | |
tree | da55156c23b474fa56b012cbb645b244adf42402 | |
parent | ba0eb2042cefce45efa5c1ad294f05d0122815ee (diff) |
add function literals
-rw-r--r-- | chunk.h | 25 | ||||
-rw-r--r-- | com.c | 44 | ||||
-rw-r--r-- | com.h | 18 | ||||
-rw-r--r-- | dis.c | 11 | ||||
-rw-r--r-- | val.c | 6 | ||||
-rw-r--r-- | val.h | 1 |
6 files changed, 98 insertions, 7 deletions
@@ -0,0 +1,25 @@ +#ifndef _chunk_h +#define _chunk_h + +typedef struct _chunk Chunk; +typedef struct _compiler Compiler; +typedef struct _state State; + + +struct _chunk { + struct { + size_t len; + size_t cap; + uint8_t *d; + } bc; + struct { + size_t len; + size_t cap; + Val *d; + } consts; +}; +Chunk chunk_new(State *S); +size_t chunk_wbc(Compiler *C, uint8_t byte); +size_t chunk_wconst(Compiler *C, Val v); + +#endif @@ -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) @@ -0,0 +1,18 @@ +#ifndef _com_h +#define _com_h + +typedef struct _compiler Compiler; + +#include "state.h" +#include "chunk.h" + + +struct _compiler { + State *S; + Chunk *ch; +}; +Compiler compiler_new(Compiler *outer, Chunk *ch); + +#define BYTECODE(C) (C->ch->bc) + +#endif @@ -87,6 +87,17 @@ void disasm_chunk(Chunk *ch) { } } + printf("\n"); + + for (uint8_t cix = 0; cix < ch->consts.len; cix++) { + Val c = ch->consts.d[cix]; + if (IS_FUNC(c)) { + printf("const %d is function:\n", cix); + disasm_chunk(&AS_FUNC(c)->chunk); + } + } + + } @@ -47,6 +47,12 @@ static ObjString *objstring_create(State *S, char *src, size_t len, uint32_t has return o; } +ObjFunc *objfunc_new(State *S) { + ObjFunc *o = NEW_OBJ(S, ObjFunc, OTY_FUNC); + o->chunk = chunk_new(S); + return o; +} + void print_val(Val v) { switch (v.ty) { @@ -72,6 +72,7 @@ ObjFunc *objfunc_new(State *S); #define IS_OBJ(x) (x.ty == TY_OBJ) #define IS_STRING(x) (is_obj_ty((x), OTY_STRING)) +#define IS_FUNC(x) (is_obj_ty((x), OTY_FUNC)) #define AS_NUM(x) (x.as.d) #define AS_BOOL(x) (x.as.b) |