diff options
author | ubq323 <ubq323@ubq323.website> | 2024-06-25 00:51:37 +0100 |
---|---|---|
committer | ubq323 <ubq323@ubq323.website> | 2024-06-25 00:51:37 +0100 |
commit | f76f5a8c244ac6d04e4d89778a6d8c2c2040cdc9 (patch) | |
tree | 484b9fea3fa5a136972384239f0890a3886bb5ba | |
parent | e9b99a90510309ac4f5d91d4a5138e7a84904057 (diff) |
get functions and arguments and returning to work fully
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | com.c | 65 | ||||
-rw-r--r-- | tests/vars2.bth | 4 | ||||
-rw-r--r-- | vm.c | 23 | ||||
-rw-r--r-- | vm.h | 3 |
5 files changed, 62 insertions, 35 deletions
@@ -1,6 +1,6 @@ CS=ast.c com.c dis.c ht.c mem.c prs.c read.c state.c val.c vm.c HS=ast.h chunk.h com.h dis.h ht.h mem.h prs.h read.h state.h util.h val.h vm.h -CFLAGS=$(EXTRA_CFLAGS) -O3 -lm -Wall -Wpedantic -Werror=implicit-function-declaration +CFLAGS=$(EXTRA_CFLAGS) -g -O3 -lm -Wall -Wpedantic -Werror=implicit-function-declaration bth: $(CS) $(HS) Makefile $(CC) $(CFLAGS) -o bth $(CS) @@ -21,6 +21,7 @@ Compiler compiler_new(Compiler *outer, Chunk *ch) { .S = outer->S, .ch = ch, .stack_cur = 0, + .scope = NULL, }; } @@ -211,26 +212,6 @@ void arith_form(Compiler *C, AstVec l, Op op) { compile_opcode(C, op); } -void fn_form(Compiler *C, AstVec l, Op _) { - // (fn (arg arg arg) body ...) - CHECK(l.vals[1].ty == AST_LIST, "fn's first argument must be list"); - AstVec arglist = l.vals[1].as.list; - CHECK(arglist.len <= 255, "maximum 255 args for function"); - uint8_t arity = arglist.len; - - ObjFunc *func = objfunc_new(C->S, arity); - Compiler subcompiler = compiler_new(C, &func->ch); - - for (int i = 2; i < l.len - 1; i++) { - compile_node(&subcompiler, l.vals[i]); - compile_opcode(&subcompiler, OP_DROP); - } - compile_node(&subcompiler, l.vals[l.len-1]); - compile_opcode(&subcompiler, OP_RET); - - compile_opcode(C, OP_LOADK); - compile_byte(C, compile_constant(C, VAL_OBJ(func))); -} static void begin_scope(Compiler *C) { Scope *sc = malloc(sizeof(Scope)); @@ -261,6 +242,7 @@ static void declare_local(Compiler *C, char *name) { // -1 because local is expected to be already on the stack // ie sitting just below where stack_cur points l->slot = C->stack_cur - 1; + // printf("declaring local %s at %d, stack_cur is %d\n",l->name, l->slot, C->stack_cur); } void let_form(Compiler *C, AstVec l, Op _) { @@ -286,7 +268,41 @@ void let_form(Compiler *C, AstVec l, Op _) { end_scope(C); } +void fn_form(Compiler *C, AstVec l, Op _) { + // (fn (arg arg arg) body ...) + CHECK(l.vals[1].ty == AST_LIST, "fn's first argument must be list"); + AstVec arglist = l.vals[1].as.list; + CHECK(arglist.len <= 255, "maximum 255 args for function"); + uint8_t arity = arglist.len; + + ObjFunc *func = objfunc_new(C->S, arity); + Compiler subcompiler = compiler_new(C, &func->ch); + Compiler *SC = &subcompiler; + begin_scope(SC); + // when called, stack slot 0 contains the function itself, + // stack slots 1..n contain passed arguments + SC->stack_cur ++; + declare_local(SC, "__func__"); + for (int i = 0; i < arity; i++) { + AstNode argname = arglist.vals[i]; + CHECK(argname.ty == AST_IDENT, "argument name must be identifier"); + SC->stack_cur ++; + declare_local(SC, argname.as.str); + } + + for (int i = 2; i < l.len - 1; i++) { + compile_node(SC, l.vals[i]); + compile_opcode(SC, OP_DROP); + } + compile_node(&subcompiler, l.vals[l.len-1]); + + end_scope(SC); + compile_opcode(SC, OP_RET); + + compile_opcode(C, OP_LOADK); + compile_byte(C, compile_constant(C, VAL_OBJ(func))); +} typedef struct { char *name; @@ -444,14 +460,13 @@ int main(int argc, char **argv) { AstNode an = read(); - Compiler com = (Compiler){ - .S = S, - .ch = &ch, - }; + Compiler com = (Compiler){ 0 }; + com.S = S; + com.ch = &ch; + Compiler *C = &com; compile_node(C, an); - compile_opcode(C, OP_PUTS); compile_opcode(C, OP_HALT); diff --git a/tests/vars2.bth b/tests/vars2.bth index 3474d54..2d5ebd1 100644 --- a/tests/vars2.bth +++ b/tests/vars2.bth @@ -1,4 +1,4 @@ (+ 2 (* 6 (let (a 10 - b 20 - c 30) + b 20 + c 30) (* b b)))) @@ -36,14 +36,19 @@ int runvm(State *S) { #define RBYTE() (ch->bc.d[th->ip++]) #define RSHORT() (th->ip += 2, (uint16_t)( ch->bc.d[th->ip-2] | ch->bc.d[th->ip-1] << 8 )) -#define PUSH(v) th->stack[th->sp++] = v; -#define POP() (th->stack[--th->sp]) -#define PEEK() (th->stack[th->sp-1]) +#define PUSH(v) th->stack[th->fp + th->sp++] = v; +#define POP() (th->stack[th->fp + --th->sp]) +#define PEEK() (th->stack[th->fp + th->sp-1]) while (1) { ch = th->ch; if (S->do_trace) { - printf("%p ",(void *)ch); + printf("\t[%lu + %lu] : ",th->fp, th->sp); + for (int i = 0; i < th->sp; i++) { + print_val(th->stack[th->fp + i]); + printf(" ; "); + } + printf("\n%p ",(void *)ch); disasm_instr(ch, th->ip); } uint8_t instr = RBYTE(); @@ -113,7 +118,7 @@ int runvm(State *S) { case OP_GETLOCAL: { uint8_t lidx = RBYTE(); - PUSH(th->stack[lidx]); + PUSH(th->stack[th->fp + lidx]); break; } @@ -164,9 +169,9 @@ int runvm(State *S) { case OP_CALL: { uint8_t len = RBYTE(); - // ignore arguments for now th->sp -= len-1; Val callee = POP(); + if (!IS_FUNC(callee)) { fprintf(stderr, "can only call functions\n"); goto done; @@ -176,9 +181,12 @@ int runvm(State *S) { StackFrame *sf = &th->rstack[th->rsp++]; sf->ch = th->ch; sf->ip = th->ip; + sf->fp = th->fp; th->ch = &func->ch; th->ip = 0; + th->fp = th->sp; + th->sp = len; break; } @@ -192,8 +200,11 @@ int runvm(State *S) { case OP_RET: { StackFrame *sf = &th->rstack[--th->rsp]; + size_t orig_fp = th->fp; th->ch = sf->ch; th->ip = sf->ip; + th->fp = sf->fp; + th->sp += (orig_fp - th->fp); break; } case OP_HALT: @@ -13,7 +13,7 @@ typedef struct _thread Thread; typedef struct { size_t ip; Chunk *ch; - + size_t fp; } StackFrame; #define MAXDEPTH 64 @@ -22,6 +22,7 @@ typedef struct _thread { Chunk *ch; size_t ip; Val stack[STACKSIZE]; + size_t fp; size_t sp; StackFrame rstack[MAXDEPTH]; size_t rsp; |