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)  | 
