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