summaryrefslogtreecommitdiff
path: root/com.c
diff options
context:
space:
mode:
Diffstat (limited to 'com.c')
-rw-r--r--com.c44
1 files changed, 37 insertions, 7 deletions
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)