diff options
-rw-r--r-- | com.c | 21 | ||||
-rw-r--r-- | dis.c | 35 | ||||
-rw-r--r-- | dis.h | 2 | ||||
-rw-r--r-- | lib.c | 38 | ||||
-rw-r--r-- | tests/sin.bth | 14 | ||||
-rw-r--r-- | tests/sin.out | 50 | ||||
-rw-r--r-- | tests/sincos.bth | 37 |
7 files changed, 196 insertions, 1 deletions
@@ -9,6 +9,7 @@ #include "util.h" #include "lib.h" #include "read.h" +#include "dis.h" #define BYTECODE(C) (C->ch->bc) @@ -363,7 +364,7 @@ static void for_form(Compiler *C, ObjArr *a, Op _, int flags) { cpl_constop(C, OP_LOADK, VAL_NUM(1)); cpl_op(C, OP_ADD); cpl_op(C, OP_SETLOCAL); - cpl_op(C, islot); + cpl_byte(C, islot); cpl_op(C, OP_DROP); cpl_op(C, OP_REDO); size_t ph_A = placeholder(C); @@ -593,6 +594,12 @@ static BuiltinForm *find_builtinform(char *name) { } static void cpl_expr(Compiler *C, Val v, int flags) { + int stack_cur_a = C->stack_cur; + int nlocals_a = 0; + if (C->scope) { + nlocals_a = C->scope->nlocals; + } + switch (val_type(v)) { case TY_NUM: case TY_NIL: case TY_BOOL: cpl_constop(C, OP_LOADK, v); @@ -636,6 +643,18 @@ static void cpl_expr(Compiler *C, Val v, int flags) { } break; } + + int stack_cur_b = C->stack_cur; + int nlocals_b = C->stack_cur; + if (C->scope) { + nlocals_b = C->scope->nlocals; + } + + // every badthing expression returns exactly one value, + // and might declare some locals as well, which also live on the stack + // so (returned values) = (stack change) - (new locals) = 1 + CHECK( (stack_cur_b - stack_cur_a) - (nlocals_b - nlocals_a) == 1, + "stack corruption (compiler bug)"); } @@ -10,6 +10,41 @@ static void print_const(Chunk *ch, uint8_t ix) { println_val(k); } + +char *op_name(Op op) { + switch (op) { + case OP_RET: return "ret"; break; + case OP_LOADK: return "loadk"; break; + case OP_ADD: return "add"; break; + case OP_SUB: return "sub"; break; + case OP_MUL: return "mul"; break; + case OP_DIV: return "div"; break; + case OP_MOD: return "mod"; break; + case OP_EQU: return "equ"; break; + case OP_CMP: return "cmp"; break; + case OP_HALT: return "halt"; break; + case OP_DROP: return "drop"; break; + case OP_GETGLOBAL: return "getglobal"; break; + case OP_SETGLOBAL: return "setglobal"; break; + case OP_GETLOCAL: return "getlocal"; break; + case OP_SETLOCAL: return "setlocal"; break; + case OP_TRUE: return "true"; break; + case OP_FALSE: return "false"; break; + case OP_NIL: return "nil"; break; + case OP_0BRANCH: return "0branch"; break; + case OP_SKIP: return "skip"; break; + case OP_REDO: return "redo"; break; + case OP_CALL: return "call"; break; + case OP_TAILCALL: return "tailcall"; break; + case OP_ENDSCOPE: return "endscope"; break; + case OP_ARRNEW: return "arrnew"; break; + case OP_ARRAPPEND: return "arrappend"; break; + case OP_ARRLEN: return "arrlen"; break; + case OP_SETIDX: return "setidx"; break; + default: return "???"; break; + } +} + static void disasm_chunk_h(Chunk *ch, int depth); void disasm_chunk(Chunk *ch) { disasm_chunk_h(ch, 0); @@ -7,4 +7,6 @@ void disasm_chunk(Chunk *ch); // returns length of disasmed instr in bytes size_t disasm_instr(Chunk *ch, size_t ip); +char *op_name(Op op); + #endif @@ -1,3 +1,4 @@ +#include <math.h> #include <time.h> #include <string.h> #include <stdio.h> @@ -115,6 +116,37 @@ static Val fn_ssplit(State *S, int nargs, Val *args) { return VAL_OBJ(out); } +// math +static Val fn_sin(State *S, int nargs, Val *args) { + CHECK(nargs == 1, "need exactly 1 arg for sin"); + CHECK(IS_NUM(args[0]), "need num for sin"); + double x = AS_NUM(args[0]); + return VAL_NUM(sin(x)); +} +static Val fn_cos(State *S, int nargs, Val *args) { + CHECK(nargs == 1, "need exactly 1 arg for cos"); + CHECK(IS_NUM(args[0]), "need num for cos"); + double x = AS_NUM(args[0]); + return VAL_NUM(cos(x)); +} +static Val fn_ceil(State *S, int nargs, Val *args) { + CHECK(nargs == 1, "need exactly 1 arg for ceil"); + CHECK(IS_NUM(args[0]), "need num for ceil"); + double x = AS_NUM(args[0]); + return VAL_NUM(ceil(x)); +} +static Val fn_floor(State *S, int nargs, Val *args) { + CHECK(nargs == 1, "need exactly 1 arg for floor"); + CHECK(IS_NUM(args[0]), "need num for floor"); + double x = AS_NUM(args[0]); + return VAL_NUM(floor(x)); +} +static Val fn_abs(State *S, int nargs, Val *args) { + CHECK(nargs == 1, "need exactly 1 arg for abs"); + CHECK(IS_NUM(args[0]), "need num for abs"); + double x = AS_NUM(args[0]); + return VAL_NUM(abs(x)); +} typedef struct { @@ -133,6 +165,12 @@ static BuiltinFunc builtin_funcs[] = { { ",", fn_pend }, { "s,", fn_spend }, { "ssplit", fn_ssplit }, + + { "sin", fn_sin }, + { "cos", fn_cos }, + { "ceil", fn_ceil }, + { "floor", fn_floor }, + { "abs", fn_abs }, { 0 }, }; diff --git a/tests/sin.bth b/tests/sin.bth new file mode 100644 index 0000000..319241f --- /dev/null +++ b/tests/sin.bth @@ -0,0 +1,14 @@ +(defn (ts x) + (* 10 (+ 1 (sin x)))) + +(set! _G_ts ts) + +(defn (p t) + (for (i (_G_ts t)) + (write " ")) + (say 'x)) + + + +(for (i 50) (p (/ i 8))) + diff --git a/tests/sin.out b/tests/sin.out new file mode 100644 index 0000000..3519c6d --- /dev/null +++ b/tests/sin.out @@ -0,0 +1,50 @@ + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x diff --git a/tests/sincos.bth b/tests/sincos.bth new file mode 100644 index 0000000..7f6a135 --- /dev/null +++ b/tests/sincos.bth @@ -0,0 +1,37 @@ +(defn (ts x) + (* 10 (+ 1 (sin x)))) +(defn (tc x) + (* 10 (+ 1 (cos x)))) +(set! _G_ts ts) +(set! _G_tc tc) + +(defn (min x y) + (if (< x y) x y)) +(defn (max x y) + (if (< x y) y x)) +(set! _G_min min) +(set! _G_max max) + +(defn (ws n) + (for (i (- n 1)) (write " ")) + (say 'x)) +(set! _G_ws ws) + +(defn (p2 t) + (let (s (_G_ts t) + c (_G_tc t) + fs (floor s) + fc (floor c) + m (_G_min fs fc) + M (_G_max fs fc) + d (- M m)) + (if (= 0 d) + (_G_ws m) + (do (_G_ws m) (_G_ws d))))) + + + + + +(for (i 100) (p2 (/ i 16))) + |