diff options
-rw-r--r-- | com.c | 13 | ||||
-rwxr-xr-x | run_tests.sh | 53 | ||||
-rw-r--r-- | tests/flet.bth | 7 | ||||
-rw-r--r-- | tests/flet.out | 2 | ||||
-rw-r--r-- | tests/iflet.bth | 8 | ||||
-rw-r--r-- | tests/iflet.out | 1 | ||||
-rw-r--r-- | tests/letstar.bth | 4 | ||||
-rw-r--r-- | tests/sumrec.bth | 7 | ||||
-rw-r--r-- | tests/sumrec.out | 2 | ||||
-rw-r--r-- | tests/whilelet.bth | 11 | ||||
-rw-r--r-- | tests/whilelet.out | 2 | ||||
-rw-r--r-- | vm.c | 7 |
12 files changed, 94 insertions, 23 deletions
@@ -180,18 +180,30 @@ void if_form(Compiler *C, AstVec l, Op _) { // skip ->B // A: if-false // B: + + int orig_stack_cur = C->stack_cur; + compile_node(C, l.vals[1]); compile_opcode(C, OP_0BRANCH); size_t ph_a = placeholder(C); compile_node(C, l.vals[2]); compile_opcode(C, OP_SKIP); + size_t ph_b = placeholder(C); size_t dest_a = BYTECODE(C).len; + int stack_cur_a = C->stack_cur; + C->stack_cur = orig_stack_cur; + compile_node(C, l.vals[3]); size_t dest_b = BYTECODE(C).len; + int stack_cur_b = C->stack_cur; + patch(C, ph_a, dest_a - ph_a - 2); patch(C, ph_b, dest_b - ph_b - 2); + + CHECK(stack_cur_a == stack_cur_b, "this should never happen"); + CHECK(stack_cur_a == orig_stack_cur + 1, "this should never happen"); } void while_form(Compiler *C, AstVec l, Op _) { @@ -520,6 +532,7 @@ int main(int argc, char **argv) { } + compile_opcode(&com, OP_HALT); Thread th = thread_new(S); diff --git a/run_tests.sh b/run_tests.sh index 63b85aa..18885da 100755 --- a/run_tests.sh +++ b/run_tests.sh @@ -2,34 +2,47 @@ pass=0 fail=0 +skip=0 for testfile in tests/*.bth; do outfile=${testfile%.bth}.out - output="$(./bth $testfile 2>&1)" - run_res=$? - echo "$output" | diff $outfile - >/dev/null - diff_res=$? testname=${testfile#tests/} testname=${testname%.bth} - 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" "$(echo "$output" | head -n4)" - printf "\texpected: " - cat $outfile - fail=$((fail + 1)) ;; - esac + if [ ! -f "$outfile" ]; then + printf '\033[33mSKIP\033[0m %s (no output file)\n' "$testname" + skip=$((skip + 1)) + else + output="$(./bth $testfile 2>&1)" + run_res=$? + echo "$output" | diff $outfile - >/dev/null + diff_res=$? + 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" "$(echo "$output" | head -n4)" + printf "\texpected: " + cat $outfile + fail=$((fail + 1)) ;; + esac + fi 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)) + +pnum () { + if [ $1 -eq 0 ]; then + printf "0 %s; " "$2" + else + printf "\033[3%dm%d\033[0m %s; " $3 $1 "$2" + fi +} + +pnum $pass passed 2 +pnum $fail failed 1 +pnum $skip skipped 3 + +printf "%s total\n" $((pass + fail + skip)) if [ $fail -eq 0 ]; then exit 0 diff --git a/tests/flet.bth b/tests/flet.bth new file mode 100644 index 0000000..102fc34 --- /dev/null +++ b/tests/flet.bth @@ -0,0 +1,7 @@ +(set f1 (fn (a b c) (say (* a (+ b c))))) +(set f2 (fn (a) (say (* a a)))) +(if true + (f1 6 2 4) + (f2 7)) +(let (a 100 b 200 c 300) + (say b)) diff --git a/tests/flet.out b/tests/flet.out new file mode 100644 index 0000000..7ba6bc8 --- /dev/null +++ b/tests/flet.out @@ -0,0 +1,2 @@ +36 +200 diff --git a/tests/iflet.bth b/tests/iflet.bth new file mode 100644 index 0000000..b461a5f --- /dev/null +++ b/tests/iflet.bth @@ -0,0 +1,8 @@ +(do + (if (< 2 3) + "yes" + "no") + (let (a 100 + b 200 + c 300) + (say b))) diff --git a/tests/iflet.out b/tests/iflet.out new file mode 100644 index 0000000..08839f6 --- /dev/null +++ b/tests/iflet.out @@ -0,0 +1 @@ +200 diff --git a/tests/letstar.bth b/tests/letstar.bth new file mode 100644 index 0000000..03d4305 --- /dev/null +++ b/tests/letstar.bth @@ -0,0 +1,4 @@ +(say (let (a 100) + (let (a 200 + b (/ a 10)) + (+ a b)))) diff --git a/tests/sumrec.bth b/tests/sumrec.bth new file mode 100644 index 0000000..8c8804a --- /dev/null +++ b/tests/sumrec.bth @@ -0,0 +1,7 @@ +(set f' (fn (x acc) + (if (< x 1) + acc + (f' (- x 1) (+ acc x))))) +(set f (fn (x) (f' x 0))) +(say (f 10)) +(say (f 100)) diff --git a/tests/sumrec.out b/tests/sumrec.out new file mode 100644 index 0000000..e613215 --- /dev/null +++ b/tests/sumrec.out @@ -0,0 +1,2 @@ +55 +5050 diff --git a/tests/whilelet.bth b/tests/whilelet.bth new file mode 100644 index 0000000..ce8a482 --- /dev/null +++ b/tests/whilelet.bth @@ -0,0 +1,11 @@ +(do + (let (i 0 + a []) + (while (< i 10) + (append a i) + (set i (+ i 1))) + (let (x 100 + y 200 + z 300) + (say y)) + (say a))) diff --git a/tests/whilelet.out b/tests/whilelet.out new file mode 100644 index 0000000..013e367 --- /dev/null +++ b/tests/whilelet.out @@ -0,0 +1,2 @@ +200 +[ 0 1 2 3 4 5 6 7 8 9 ] @@ -177,12 +177,14 @@ int runvm(State *S) { case OP_CALL: { // nargs + 1 = function and args uint8_t len = RBYTE(); - + uint8_t nargs = len - 1; Val callee = PEEKN(len); if (IS_FUNC(callee)) { ObjFunc *func = AS_FUNC(callee); + CHECK(nargs == func->arity, "func needs exactly %d args, but got %d",func->arity,nargs); + CHECK(th->rsp < MAXDEPTH, "rstack overflow"); StackFrame *sf = &th->rstack[th->rsp++]; sf->ip = th->ip; sf->ch = th->ch; @@ -192,9 +194,8 @@ int runvm(State *S) { th->ch = &func->ch; th->fp = th->sp - len; } else if (IS_CFUNC(callee)) { - int nargs = len - 1; Val *firstarg = &th->stack[th->sp - nargs]; - Val res = AS_CFUNC(callee)(S, len - 1, firstarg); + Val res = AS_CFUNC(callee)(S, nargs, firstarg); th->sp -= len; PUSH(res); } else if (IS_ARR(callee)) { |