From 21994864559386f1d11c001d6d27714cbf624a15 Mon Sep 17 00:00:00 2001
From: ubq323 <ubq323@ubq323.website>
Date: Fri, 21 Jun 2024 12:56:30 +0100
Subject: add tests, and make dumping disasm optional

---
 .gitignore                      |  1 +
 Makefile                        |  7 +++++--
 com.c                           | 13 +++++++------
 "fizzbuzz.b\303\276"            | 10 ----------
 run_tests.sh                    | 39 +++++++++++++++++++++++++++++++++++++++
 state.h                         |  2 ++
 "test.b\303\276"                |  1 -
 "tests/compile_error.b\303\276" |  1 +
 tests/compile_error.out         |  1 +
 "tests/fizzbuzz.b\303\276"      | 10 ++++++++++
 tests/fizzbuzz.out              | 30 ++++++++++++++++++++++++++++++
 "tests/four.b\303\276"          |  1 +
 tests/four.out                  |  1 +
 "tests/vars.b\303\276"          |  9 +++++++++
 tests/vars.out                  |  5 +++++
 val.c                           |  2 +-
 vm.c                            |  7 ++++---
 17 files changed, 117 insertions(+), 23 deletions(-)
 delete mode 100644 "fizzbuzz.b\303\276"
 create mode 100755 run_tests.sh
 delete mode 100644 "test.b\303\276"
 create mode 100644 "tests/compile_error.b\303\276"
 create mode 100644 tests/compile_error.out
 create mode 100644 "tests/fizzbuzz.b\303\276"
 create mode 100644 tests/fizzbuzz.out
 create mode 100644 "tests/four.b\303\276"
 create mode 100644 tests/four.out
 create mode 100644 "tests/vars.b\303\276"
 create mode 100644 tests/vars.out

diff --git a/.gitignore b/.gitignore
index 276812f..17743a8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,4 @@ prs.c
 prs.h
 bþ
 vm
+gmon.out
diff --git a/Makefile b/Makefile
index 596f2a3..917c481 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 CS=ast.c com.c dis.c ht.c mem.c prs.c read.c state.c val.c vm.c
 HS=ast.h       dis.h ht.h mem.h prs.h read.h state.h val.h vm.h
-CFLAGS=-O3 -lm -Wall -Wpedantic -Werror=implicit-function-declaration
+CFLAGS=$(EXTRA_CFLAGS) -O3 -lm -Wall -Wpedantic -Werror=implicit-function-declaration
 
 bþ: $(CS) $(HS) Makefile
 	$(CC) $(CFLAGS) -o bþ $(CS)
@@ -8,7 +8,10 @@ bþ: $(CS) $(HS) Makefile
 prs.c: g.peg
 	packcc -o prs g.peg
 
+test: bþ
+	./run_tests.sh
+
 clean:
 	rm bþ prs.c prs.h
 
-.PHONY: clean
+.PHONY: clean test
diff --git a/com.c b/com.c
index fbc93ac..93b0b59 100644
--- a/com.c
+++ b/com.c
@@ -47,7 +47,7 @@ static void compile_node(State *S, Chunk *ch, AstNode a) {
 	}
 	case AST_LIST: {
 		AstVec l = a.as.list;
-		#define CK(cond, msg) if (!(cond)) { puts(msg); exit(1); }
+		#define CK(cond, msg) if (!(cond)) { fputs(msg "\n", stderr); exit(1); }
 		CK(l.len > 0, "can't handle empty list");
 		CK(l.vals[0].ty == AST_IDENT, "can only call ops");
 
@@ -150,7 +150,7 @@ static void compile_node(State *S, Chunk *ch, AstNode a) {
 }
 
 
-int main() {
+int main(int argc, char **argv) {
 	State st = state_new();
 	State *S = &st;
 	Thread th = thread_new(S);
@@ -158,12 +158,14 @@ int main() {
 	Chunk ch = chunk_new(S);
 	th.ch = &ch;
 
+	S->do_disasm = (argc > 1 && 0 == strcmp(argv[1], "-l"));
+
 	char n1[] = "foo";
 	char n2[] = "bar";
 	char n3[] = "baz";
-	ObjString *o1 = objstring_copy(S, n1, 3);
-	ObjString *o2 = objstring_copy(S, n2, 3);
-	ObjString *o3 = objstring_copy(S, n3, 3);
+	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)); 
@@ -175,7 +177,6 @@ int main() {
 	chunk_wbc(S, &ch, OP_PRINT);
 	chunk_wbc(S, &ch, OP_RET);
 
-	puts("compile done");
 	return runvm(S);
 }
 
diff --git "a/fizzbuzz.b\303\276" "b/fizzbuzz.b\303\276"
deleted file mode 100644
index e70c2c1..0000000
--- "a/fizzbuzz.b\303\276"
+++ /dev/null
@@ -1,10 +0,0 @@
-(do 
- (set n 1)
- (while (< n 30)
-        (print 
-         (if (= 0 (% n 5))
-             (if (= 0 (% n 3)) "fizzbuzz" "buzz")
-             (if (= 0 (% n 3)) "fizz" n)))
-        (set n (+ n 1))))
-
-
diff --git a/run_tests.sh b/run_tests.sh
new file mode 100755
index 0000000..3c561a7
--- /dev/null
+++ b/run_tests.sh
@@ -0,0 +1,39 @@
+#!/bin/sh
+
+pass=0
+fail=0
+
+for testfile in tests/*.bþ; do
+	outfile=${testfile%.bþ}.out
+	output="$(./bþ <$testfile 2>&1)"
+	run_res=$?
+	echo "$output" | diff $outfile - >/dev/null
+	diff_res=$?
+	testname=${testfile#tests/}
+	testname=${testname%.bþ}
+	case $diff_res in
+	0) 	printf '\033[32m\033[1mPASS\033[0m %s\n' "$testname"
+		pass=$((pass + 1)) ;;
+	1) 	printf '\033[31m\033[1mFAIL\033[0m %s\n' "$testname"
+		printf "\tgot output: %s\n" "$output"
+		printf "\texpected: "
+		cat $outfile
+		fail=$((fail + 1)) ;;
+	esac
+done
+
+echo
+printf "\033[32m%s\033[0m passed; " $pass
+if [ $fail -eq 0 ]; then
+	printf "0 failed; "
+else
+	printf "\033[31m%s\033[0m failed; " $fail
+fi
+printf "%s total\n" $((pass + fail))
+
+if [ $fail -eq 0 ]; then
+	exit 0
+else
+	exit 1
+fi
+
diff --git a/state.h b/state.h
index 9563376..dab9a97 100644
--- a/state.h
+++ b/state.h
@@ -10,6 +10,8 @@ struct _state {
 	Thread *th;
 	Ht strings;
 	Ht globals;
+
+	bool do_disasm;
 };
 State state_new();
 
diff --git "a/test.b\303\276" "b/test.b\303\276"
deleted file mode 100644
index 641d9f2..0000000
--- "a/test.b\303\276"
+++ /dev/null
@@ -1 +0,0 @@
-(+ "abc" (* 9 25))
diff --git "a/tests/compile_error.b\303\276" "b/tests/compile_error.b\303\276"
new file mode 100644
index 0000000..b151c2f
--- /dev/null
+++ "b/tests/compile_error.b\303\276"
@@ -0,0 +1 @@
+(while)
diff --git a/tests/compile_error.out b/tests/compile_error.out
new file mode 100644
index 0000000..b7b8184
--- /dev/null
+++ b/tests/compile_error.out
@@ -0,0 +1 @@
+while requires at least 2 arguments
diff --git "a/tests/fizzbuzz.b\303\276" "b/tests/fizzbuzz.b\303\276"
new file mode 100644
index 0000000..e70c2c1
--- /dev/null
+++ "b/tests/fizzbuzz.b\303\276"
@@ -0,0 +1,10 @@
+(do 
+ (set n 1)
+ (while (< n 30)
+        (print 
+         (if (= 0 (% n 5))
+             (if (= 0 (% n 3)) "fizzbuzz" "buzz")
+             (if (= 0 (% n 3)) "fizz" n)))
+        (set n (+ n 1))))
+
+
diff --git a/tests/fizzbuzz.out b/tests/fizzbuzz.out
new file mode 100644
index 0000000..51ff50b
--- /dev/null
+++ b/tests/fizzbuzz.out
@@ -0,0 +1,30 @@
+1
+2
+fizz
+4
+buzz
+fizz
+7
+8
+fizz
+buzz
+11
+fizz
+13
+14
+fizzbuzz
+16
+17
+fizz
+19
+buzz
+fizz
+22
+23
+fizz
+buzz
+26
+fizz
+28
+29
+nil
diff --git "a/tests/four.b\303\276" "b/tests/four.b\303\276"
new file mode 100644
index 0000000..8804fe4
--- /dev/null
+++ "b/tests/four.b\303\276"
@@ -0,0 +1 @@
+(+ 2 2)
diff --git a/tests/four.out b/tests/four.out
new file mode 100644
index 0000000..b8626c4
--- /dev/null
+++ b/tests/four.out
@@ -0,0 +1 @@
+4
diff --git "a/tests/vars.b\303\276" "b/tests/vars.b\303\276"
new file mode 100644
index 0000000..7799acf
--- /dev/null
+++ "b/tests/vars.b\303\276"
@@ -0,0 +1,9 @@
+(do
+	(set a 5)
+	(set b 10)
+	(set thethe 1234)
+	(print (+ a b))
+	(print (- thethe a))
+	(print (+ (set a 90) b))
+	(print a)
+	nil)
diff --git a/tests/vars.out b/tests/vars.out
new file mode 100644
index 0000000..bef4ee4
--- /dev/null
+++ b/tests/vars.out
@@ -0,0 +1,5 @@
+15
+1229
+100
+90
+nil
diff --git a/val.c b/val.c
index 18d0ffa..8e351ff 100644
--- a/val.c
+++ b/val.c
@@ -54,7 +54,7 @@ void print_val(Val v) {
 		printf("nil");
 		break;
 	case TY_NUM:
-		printf("%f",AS_NUM(v));
+		printf("%g",AS_NUM(v));
 		break;
 	case TY_BOOL:
 		printf("%s",AS_BOOL(v) ? "true" : "false");
diff --git a/vm.c b/vm.c
index 1dc40e0..667ceed 100644
--- a/vm.c
+++ b/vm.c
@@ -57,7 +57,10 @@ int runvm(State *S) {
 
 	int status = 1;
 
-	disasm_chunk(ch);
+	if (S->do_disasm) {
+		disasm_chunk(ch);
+		puts("---");
+	}
 
 #define RBYTE() (ch->bc.d[th->ip++])
 #define RSHORT() (th->ip += 2, (uint16_t)( ch->bc.d[th->ip-2] | ch->bc.d[th->ip-1] << 8 ))
@@ -66,13 +69,11 @@ int runvm(State *S) {
 #define POP()   (th->stack[--th->sp])
 #define PEEK()  (th->stack[th->sp-1])
 
-	puts("---");
 	while (1) {
 		uint8_t instr = RBYTE();
 		switch (instr) {
 		case OP_RET:
 			status  = 0;
-			printf("done!\n");
 			goto done;
 			break;
 		case OP_LOADK: {
-- 
cgit v1.2.3