diff options
author | ubq323 <ubq323@ubq323.website> | 2024-06-24 16:49:15 +0100 |
---|---|---|
committer | ubq323 <ubq323@ubq323.website> | 2024-06-24 16:49:15 +0100 |
commit | 08d7465f5a841366ec4c66f11475ede4e9082a8d (patch) | |
tree | 556527c70b412034a4c7ae18f70a7f6906391900 /com.c | |
parent | 8c3037662ba572a6935170dbd4cb8cc8a3636417 (diff) |
refactor error checking and argument parsing
Diffstat (limited to 'com.c')
-rw-r--r-- | com.c | 59 |
1 files changed, 29 insertions, 30 deletions
@@ -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 |