summaryrefslogtreecommitdiff
path: root/com.c
diff options
context:
space:
mode:
authorubq323 <ubq323@ubq323.website>2024-06-25 00:51:37 +0100
committerubq323 <ubq323@ubq323.website>2024-06-25 00:51:37 +0100
commitf76f5a8c244ac6d04e4d89778a6d8c2c2040cdc9 (patch)
tree484b9fea3fa5a136972384239f0890a3886bb5ba /com.c
parente9b99a90510309ac4f5d91d4a5138e7a84904057 (diff)
get functions and arguments and returning to work fully
Diffstat (limited to 'com.c')
-rw-r--r--com.c65
1 files changed, 40 insertions, 25 deletions
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);