From 1d496f5f7f01b20fb34e63d1c85a33d8decd1894 Mon Sep 17 00:00:00 2001 From: ubq323 Date: Sat, 22 Jun 2024 12:23:55 +0100 Subject: add function literals --- chunk.h | 25 +++++++++++++++++++++++++ com.c | 44 +++++++++++++++++++++++++++++++++++++------- com.h | 18 ++++++++++++++++++ dis.c | 11 +++++++++++ val.c | 6 ++++++ val.h | 1 + 6 files changed, 98 insertions(+), 7 deletions(-) create mode 100644 chunk.h create mode 100644 com.h diff --git a/chunk.h b/chunk.h new file mode 100644 index 0000000..afefda0 --- /dev/null +++ b/chunk.h @@ -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 diff --git a/com.c b/com.c index 4f377ce..92f0d80 100644 --- a/com.c +++ b/com.c @@ -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) diff --git a/com.h b/com.h new file mode 100644 index 0000000..f08769e --- /dev/null +++ b/com.h @@ -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 diff --git a/dis.c b/dis.c index ba0e1db..5097b05 100644 --- a/dis.c +++ b/dis.c @@ -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); + } + } + + } diff --git a/val.c b/val.c index ec3e636..621b073 100644 --- a/val.c +++ b/val.c @@ -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) { diff --git a/val.h b/val.h index e4227a4..c71e419 100644 --- a/val.h +++ b/val.h @@ -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) -- cgit v1.2.3