#include #include #include #include "vm.h" #include "ast.h" #include "read.h" #include "state.h" static void compile_node(State *S, Chunk *ch, AstNode a) { switch (a.ty) { case AST_IDENT:; size_t len = strlen(a.as.str); ObjString *o = objstring_copy(S, a.as.str, len); chunk_wbc(S, ch, OP_GETGLOBAL); chunk_wbc(S, ch, chunk_wconst(S, ch, VAL_OBJ(o))); break; case AST_NUM: chunk_wbc(S, ch, OP_LOADK); chunk_wbc(S, ch, chunk_wconst(S, ch, VAL_NUM(a.as.num))); break; case AST_STRING: { size_t len = strlen(a.as.str); ObjString *o = objstring_copy(S, a.as.str, len); chunk_wbc(S, ch, OP_LOADK); chunk_wbc(S, ch, chunk_wconst(S, ch, VAL_OBJ(o))); break; } case AST_LIST: { AstVec l = a.as.list; #define CK(cond, msg) if (!(cond)) { puts(msg); exit(1); } CK(l.vals[0].ty == AST_IDENT, "can only call ops"); if (0 == strcmp(l.vals[0].as.str, "print")) { CK(l.len == 2, "print requires exactly 1 argument"); compile_node(S, ch, l.vals[1]); chunk_wbc(S, ch, OP_PRINT); } else if (0 == strcmp(l.vals[0].as.str, "set")) { CK(l.len == 3, "set requires exactly 2 arguments"); AstNode ident = l.vals[1]; CK(ident.ty == AST_IDENT, "set's first argument must be identifier"); size_t len = strlen(ident.as.str); ObjString *o = objstring_copy(S, ident.as.str, len); compile_node(S, ch, l.vals[2]); chunk_wbc(S, ch, OP_SETGLOBAL); chunk_wbc(S, ch, chunk_wconst(S, ch, VAL_OBJ(o))); } else if (0 == strcmp(l.vals[0].as.str, "do")) { for (int i = 1; i < l.len - 1; i++) { compile_node(S, ch, l.vals[i]); chunk_wbc(S, ch, OP_DROP); } compile_node(S, ch, l.vals[l.len - 1]); } else { CK(l.len == 3, "can only compile binary ops"); char opchar = l.vals[0].as.str[0]; Op op; switch (opchar) { #define OP(char, code) case char: op = code; break; OP('+', OP_ADD) OP('-', OP_SUB) OP('*', OP_MUL) OP('/', OP_DIV) #undef OP default: printf("unkown op %s\n",l.vals[0].as.str); exit(1); break; } compile_node(S, ch, l.vals[1]); compile_node(S, ch, l.vals[2]); chunk_wbc(S, ch, op); } #undef CK } } } int main() { State st = state_new(); State *S = &st; Thread th = thread_new(S); st.th = &th; Chunk ch = chunk_new(S); th.ch = &ch; char n1[] = "foo"; char n2[] = "bar"; char n3[] = "baz"; ObjString *o1 = objstring_copy(S, n1, 3); ObjString *o2 = objstring_copy(S, n2, 3); ObjString *o3 = objstring_copy(S, n3, 3); ht_put(S, &st.globals, o1, VAL_NUM(69)); ht_put(S, &st.globals, o2, VAL_NUM(2)); ht_put(S, &st.globals, o3, VAL_NUM(3)); AstNode an = read(); compile_node(S, &ch, an); chunk_wbc(S, &ch, OP_PRINT); chunk_wbc(S, &ch, OP_RET); runvm(S); }