summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--com.c65
-rw-r--r--tests/vars2.bth4
-rw-r--r--vm.c23
-rw-r--r--vm.h3
5 files changed, 62 insertions, 35 deletions
diff --git a/Makefile b/Makefile
index fcb0c82..e81ea76 100644
--- a/Makefile
+++ b/Makefile
@@ -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)
diff --git a/com.c b/com.c
index b2f1f09..c5362cd 100644
--- a/com.c
+++ b/com.c
@@ -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))))
diff --git a/vm.c b/vm.c
index b5b66d3..6084f21 100644
--- a/vm.c
+++ b/vm.c
@@ -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:
diff --git a/vm.h b/vm.h
index 0d1782d..39fc0bb 100644
--- a/vm.h
+++ b/vm.h
@@ -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;