summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorubq323 <ubq323@ubq323.website>2024-06-24 16:49:15 +0100
committerubq323 <ubq323@ubq323.website>2024-06-24 16:49:15 +0100
commit08d7465f5a841366ec4c66f11475ede4e9082a8d (patch)
tree556527c70b412034a4c7ae18f70a7f6906391900
parent8c3037662ba572a6935170dbd4cb8cc8a3636417 (diff)
refactor error checking and argument parsing
-rw-r--r--Makefile4
-rw-r--r--com.c59
-rw-r--r--util.h10
-rw-r--r--val.c3
-rw-r--r--val.h3
5 files changed, 45 insertions, 34 deletions
diff --git a/Makefile b/Makefile
index 58ef051..fcb0c82 100644
--- a/Makefile
+++ b/Makefile
@@ -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
diff --git a/com.c b/com.c
index 5a98ef1..72975ed 100644
--- a/com.c
+++ b/com.c
@@ -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
diff --git a/util.h b/util.h
new file mode 100644
index 0000000..b0f2658
--- /dev/null
+++ b/util.h
@@ -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
+
diff --git a/val.c b/val.c
index 930ebd8..ec200d3 100644
--- a/val.c
+++ b/val.c
@@ -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;
}
diff --git a/val.h b/val.h
index 6aa85c5..4ee76d2 100644
--- a/val.h
+++ b/val.h
@@ -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)