diff options
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | com.c | 59 | ||||
-rw-r--r-- | util.h | 10 | ||||
-rw-r--r-- | val.c | 3 | ||||
-rw-r--r-- | val.h | 3 |
5 files changed, 45 insertions, 34 deletions
@@ -1,5 +1,5 @@ -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 val.h vm.h +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 bth: $(CS) $(HS) Makefile @@ -7,6 +7,7 @@ #include "chunk.h" #include "ast.h" #include "read.h" +#include "util.h" #define BYTECODE(C) (C->ch->bc) @@ -86,10 +87,7 @@ void single_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"); - exit(1); - } + CHECK(ident.ty == AST_IDENT, "set's first argument must be identifier"); ObjString *o = objstring_copy_cstr(C->S, ident.as.str); compile_node(C, l.vals[2]); chunk_wbc(C, OP_SETGLOBAL); @@ -160,13 +158,12 @@ void arith_form(Compiler *C, AstVec l, Op op) { 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); - } + 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); + ObjFunc *func = objfunc_new(C->S, arity); Compiler subcompiler = compiler_new(C, &func->ch); for (int i = 2; i < l.len - 1; i++) { @@ -246,9 +243,7 @@ static void compile_node(Compiler *C, AstNode a) { case AST_LIST: { AstVec l = a.as.list; - #define CK(cond, msg) if (!(cond)) { fputs(msg "\n", stderr); exit(1); } - CK(l.len > 0, "can't handle empty list"); - #undef CK + CHECK(l.len > 0, "can't handle empty list"); BuiltinForm *form = NULL; @@ -263,15 +258,13 @@ static void compile_node(Compiler *C, AstNode a) { } if (form != NULL) { - if (form->ellipsis && l.len < form->min_params + 1) { - fprintf(stderr, "%s requires at least %d parameters\n", + size_t nparams = l.len - 1; + if (form->ellipsis) + CHECK(nparams >= form->min_params, "%s requires at least %d parameters", form->name, form->min_params); - exit(1); - } else if (!form->ellipsis && l.len != form->min_params + 1) { - fprintf(stderr, "%s requires exactly %d parameters\n", + else + CHECK(nparams == form->min_params, "%s requires exactly %d parameters", form->name, form->min_params); - exit(1); - } form->action(C, l, form->op); } else { @@ -298,19 +291,23 @@ int main(int argc, char **argv) { State *S = &st; Chunk ch = chunk_new(S); - S->do_disasm = (argc > 1 && 0 == strcmp(argv[1], "-l")); + S->do_disasm = false; S->do_trace = false; - char n1[] = "foo"; - char n2[] = "bar"; - char n3[] = "baz"; - ObjString *o1 = objstring_copy_cstr(S, n1); - ObjString *o2 = objstring_copy_cstr(S, n2); - ObjString *o3 = objstring_copy_cstr(S, n3); - - 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)); + for (int i = 1; i < argc; i++) { + if (argv[i][0] != '-') break; + switch (argv[i][1]) { + case 'D': + CHECK(strlen(argv[i]) > 1, "unknown option a"); + switch (argv[i][2]) { + case 'l': S->do_disasm = true; break; + case 't': S->do_trace = true; break; + default: ERROR("unknown option b"); + } + break; + default: ERROR("unknown option c"); + } + } AstNode an = read(); @@ -331,3 +328,5 @@ int main(int argc, char **argv) { return runvm(S); } +#undef CHECK +#undef ER @@ -0,0 +1,10 @@ +#ifndef _util_h +#define _util_h + +#define CHECK(cond, ...) do { if (!(cond)) { fprintf(stderr, __VA_ARGS__); exit(1); } } while(0) +#define ERROR(...) CHECK(false, __VA_ARGS__) + + + +#endif + @@ -47,9 +47,10 @@ static ObjString *objstring_create(State *S, char *src, size_t len, uint32_t has return o; } -ObjFunc *objfunc_new(State *S) { +ObjFunc *objfunc_new(State *S, uint8_t arity) { ObjFunc *o = NEW_OBJ(S, ObjFunc, OTY_FUNC); o->ch = chunk_new(S); + o->arity = arity; return o; } @@ -54,6 +54,7 @@ typedef struct { typedef struct { Obj obj; Chunk ch; + uint8_t arity; } ObjFunc; // Constructs a new objstring from the given C string, @@ -64,7 +65,7 @@ ObjString *objstring_copy_cstr(State *s, char *str); // taking ownership of the provided data. ObjString *objstring_take(State *S, char *src, size_t len); -ObjFunc *objfunc_new(State *S); +ObjFunc *objfunc_new(State *S, uint8_t arity); #define IS_NIL(x) (x.ty == TY_NIL) #define IS_NUM(x) (x.ty == TY_NUM) |