1
0
mirror of https://github.com/janet-lang/janet synced 2024-12-23 15:00:27 +00:00

Remove some c functions in favor of bytecode.

This commit is contained in:
Calvin Rose 2018-07-02 00:12:36 -04:00
parent e60c8a9b75
commit 5e2de33ae7
12 changed files with 284 additions and 319 deletions

View File

@ -13,7 +13,7 @@ body once, and then memoizes the result."
(tuple 'do (tuple 'do
(tuple 'var $state nil) (tuple 'var $state nil)
(tuple 'var $loaded nil) (tuple 'var $loaded nil)
(tuple 'fn (array) (tuple 'fn []
(tuple 'if $loaded (tuple 'if $loaded
$state $state
(tuple 'do (tuple 'do

View File

@ -1058,7 +1058,7 @@
(when c (file.write stdout " cfunction")) (when c (file.write stdout " cfunction"))
(if name (if name
(file.write stdout " " name) (file.write stdout " " name)
(when func (file.write stdout " " func))) (when func (file.write stdout " " (string func))))
(if source (if source
(do (do
(file.write stdout " [" source "]") (file.write stdout " [" source "]")

View File

@ -114,48 +114,8 @@ static DstSlot genericSSI(DstFopts opts, int op, DstSlot s, int32_t imm) {
return target; return target;
} }
static DstSlot add(DstFopts opts, DstSlot *args) { /* Function optimizers */
return opreduce(opts, args, DOP_ADD, dst_wrap_integer(0), NULL);
}
static DstSlot mul(DstFopts opts, DstSlot *args) {
return opreduce(opts, args, DOP_MULTIPLY, dst_wrap_integer(1), NULL);
}
static DstSlot subUnary(DstFopts opts, DstSlot onearg) {
return genericSSS(opts, DOP_SUBTRACT, dst_wrap_integer(0), onearg);
}
static DstSlot sub(DstFopts opts, DstSlot *args) {
return opreduce(opts, args, DOP_SUBTRACT, dst_wrap_integer(0), subUnary);
}
static DstSlot divUnary(DstFopts opts, DstSlot onearg) {
return genericSSS(opts, DOP_DIVIDE, dst_wrap_integer(1), onearg);
}
static DstSlot divide(DstFopts opts, DstSlot *args) {
return opreduce(opts, args, DOP_DIVIDE, dst_wrap_integer(1), divUnary);
}
static const DstCFunOptimizer coptimizers[] = {
{dst_add, NULL, add},
{dst_subtract, NULL, sub},
{dst_multiply, NULL, mul},
{dst_divide, NULL, divide},
};
/* Get a cfunction optimizer. Return NULL if none exists. */
const DstCFunOptimizer *dstc_cfunopt(DstCFunction cfun) {
size_t i;
size_t n = sizeof(coptimizers)/sizeof(DstCFunOptimizer);
for (i = 0; i < n; i++)
if (coptimizers[i].cfun == cfun)
return coptimizers + i;
return NULL;
}
/* Normal function optimizers */
/* Get, put, etc. */
static DstSlot do_error(DstFopts opts, DstSlot *args) { static DstSlot do_error(DstFopts opts, DstSlot *args) {
dstc_emit_s(opts.compiler, DOP_ERROR, args[0]); dstc_emit_s(opts.compiler, DOP_ERROR, args[0]);
return dstc_cslot(dst_wrap_nil()); return dstc_cslot(dst_wrap_nil());
@ -201,6 +161,54 @@ static DstSlot do_apply1(DstFopts opts, DstSlot *args) {
dstc_free_reg(opts.compiler, args[0], fun_reg); dstc_free_reg(opts.compiler, args[0], fun_reg);
return target; return target;
} }
static DstSlot do_add(DstFopts opts, DstSlot *args) {
return opreduce(opts, args, DOP_ADD, dst_wrap_integer(0), NULL);
}
static DstSlot do_sub_unary(DstFopts opts, DstSlot slot) {
return genericSSS(opts, DOP_SUBTRACT, dst_wrap_integer(0), slot);
}
static DstSlot do_sub(DstFopts opts, DstSlot *args) {
return opreduce(opts, args, DOP_SUBTRACT, dst_wrap_integer(0), do_sub_unary);
}
static DstSlot do_mul(DstFopts opts, DstSlot *args) {
return opreduce(opts, args, DOP_MULTIPLY, dst_wrap_integer(1), NULL);
}
static DstSlot do_div_unary(DstFopts opts, DstSlot slot) {
return genericSSS(opts, DOP_DIVIDE, dst_wrap_integer(1), slot);
}
static DstSlot do_div(DstFopts opts, DstSlot *args) {
return opreduce(opts, args, DOP_DIVIDE, dst_wrap_integer(1), do_div_unary);
}
static DstSlot do_band(DstFopts opts, DstSlot *args) {
return opreduce(opts, args, DOP_BAND, dst_wrap_integer(-1), NULL);
}
static DstSlot do_bor(DstFopts opts, DstSlot *args) {
return opreduce(opts, args, DOP_BOR, dst_wrap_integer(0), NULL);
}
static DstSlot do_bxor(DstFopts opts, DstSlot *args) {
return opreduce(opts, args, DOP_BXOR, dst_wrap_integer(0), NULL);
}
static DstSlot do_lshift_unary(DstFopts opts, DstSlot s) {
return genericSSS(opts, DOP_SHIFT_LEFT, dst_wrap_integer(1), s);
}
static DstSlot do_lshift(DstFopts opts, DstSlot *args) {
return opreduce(opts, args, DOP_SHIFT_LEFT,
dst_wrap_integer(1), do_lshift_unary);
}
static DstSlot do_rshift_unary(DstFopts opts, DstSlot s) {
return genericSSS(opts, DOP_SHIFT_RIGHT, dst_wrap_integer(1), s);
}
static DstSlot do_rshift(DstFopts opts, DstSlot *args) {
return opreduce(opts, args, DOP_SHIFT_RIGHT,
dst_wrap_integer(1), do_rshift_unary);
}
static DstSlot do_rshiftu_unary(DstFopts opts, DstSlot s) {
return genericSSS(opts, DOP_SHIFT_RIGHT_UNSIGNED, dst_wrap_integer(1), s);
}
static DstSlot do_rshiftu(DstFopts opts, DstSlot *args) {
return opreduce(opts, args, DOP_SHIFT_RIGHT,
dst_wrap_integer(1), do_rshiftu_unary);
}
/* Arranged by tag */ /* Arranged by tag */
static const DstFunOptimizer optimizers[] = { static const DstFunOptimizer optimizers[] = {
@ -212,12 +220,24 @@ static const DstFunOptimizer optimizers[] = {
{fixarity2, do_resume}, {fixarity2, do_resume},
{fixarity2, do_get}, {fixarity2, do_get},
{fixarity2, do_put}, {fixarity2, do_put},
{fixarity1, do_length} {fixarity1, do_length},
{NULL, do_add},
{NULL, do_sub},
{NULL, do_mul},
{NULL, do_div},
{NULL, do_band},
{NULL, do_bor},
{NULL, do_bxor},
{NULL, do_lshift},
{NULL, do_rshift},
{NULL, do_rshiftu},
}; };
const DstFunOptimizer *dstc_funopt(uint32_t flags) { const DstFunOptimizer *dstc_funopt(uint32_t flags) {
uint32_t tag = flags & DST_FUNCDEF_FLAG_TAG; uint32_t tag = flags & DST_FUNCDEF_FLAG_TAG;
if (tag == 0 || tag > 8) return NULL; if (tag == 0 || tag >=
((sizeof(optimizers)/sizeof(uint32_t) - 1)))
return NULL;
return optimizers + tag; return optimizers + tag;
} }

View File

@ -386,13 +386,7 @@ static DstSlot dstc_call(DstFopts opts, DstSlot *slots, DstSlot fun) {
DstCompiler *c = opts.compiler; DstCompiler *c = opts.compiler;
int specialized = 0; int specialized = 0;
if (fun.flags & DST_SLOT_CONSTANT) { if (fun.flags & DST_SLOT_CONSTANT) {
if (dst_checktype(fun.constant, DST_CFUNCTION)) { if (dst_checktype(fun.constant, DST_FUNCTION)) {
const DstCFunOptimizer *o = dstc_cfunopt(dst_unwrap_cfunction(fun.constant));
if (o && (!o->can_optimize || o->can_optimize(opts, slots))) {
specialized = 1;
retslot = o->optimize(opts, slots);
}
} else if (dst_checktype(fun.constant, DST_FUNCTION)) {
DstFunction *f = dst_unwrap_function(fun.constant); DstFunction *f = dst_unwrap_function(fun.constant);
const DstFunOptimizer *o = dstc_funopt(f->def->flags); const DstFunOptimizer *o = dstc_funopt(f->def->flags);
if (o && (!o->can_optimize || o->can_optimize(opts, slots))) { if (o && (!o->can_optimize || o->can_optimize(opts, slots))) {

View File

@ -37,6 +37,16 @@
#define DST_FUN_GET 6 #define DST_FUN_GET 6
#define DST_FUN_PUT 7 #define DST_FUN_PUT 7
#define DST_FUN_LENGTH 8 #define DST_FUN_LENGTH 8
#define DST_FUN_ADD 9
#define DST_FUN_SUBTRACT 10
#define DST_FUN_MULTIPLY 11
#define DST_FUN_DIVIDE 12
#define DST_FUN_BAND 13
#define DST_FUN_BOR 14
#define DST_FUN_BXOR 15
#define DST_FUN_LSHIFT 16
#define DST_FUN_RSHIFT 17
#define DST_FUN_RSHIFTU 18
/* Compiler typedefs */ /* Compiler typedefs */
typedef struct DstCompiler DstCompiler; typedef struct DstCompiler DstCompiler;
@ -45,7 +55,6 @@ typedef struct SlotTracker SlotTracker;
typedef struct DstScope DstScope; typedef struct DstScope DstScope;
typedef struct DstSlot DstSlot; typedef struct DstSlot DstSlot;
typedef struct DstFopts DstFopts; typedef struct DstFopts DstFopts;
typedef struct DstCFunOptimizer DstCFunOptimizer;
typedef struct DstFunOptimizer DstFunOptimizer; typedef struct DstFunOptimizer DstFunOptimizer;
typedef struct DstSpecial DstSpecial; typedef struct DstSpecial DstSpecial;
@ -148,15 +157,6 @@ struct DstFopts {
/* Get the default form options */ /* Get the default form options */
DstFopts dstc_fopts_default(DstCompiler *c); DstFopts dstc_fopts_default(DstCompiler *c);
/* A grouping of optimizations on a cfunction given certain conditions
* on the arguments (such as all constants, or some known types). The appropriate
* optimizations should be tried before compiling a normal function call. */
struct DstCFunOptimizer {
DstCFunction cfun;
int (*can_optimize)(DstFopts opts, DstSlot *args);
DstSlot (*optimize)(DstFopts opts, DstSlot *args);
};
/* For optimizing builtin normal functions. */ /* For optimizing builtin normal functions. */
struct DstFunOptimizer { struct DstFunOptimizer {
int (*can_optimize)(DstFopts opts, DstSlot *args); int (*can_optimize)(DstFopts opts, DstSlot *args);
@ -172,7 +172,6 @@ struct DstSpecial {
/****************************************************/ /****************************************************/
/* Get an optimizer if it exists, otherwise NULL */ /* Get an optimizer if it exists, otherwise NULL */
const DstCFunOptimizer *dstc_cfunopt(DstCFunction cfun);
const DstFunOptimizer *dstc_funopt(uint32_t flags); const DstFunOptimizer *dstc_funopt(uint32_t flags);
/* Get a special. Return NULL if none exists */ /* Get a special. Return NULL if none exists */

View File

@ -77,6 +77,76 @@ static void dst_quick_asm(
dst_env_def(env, name, dst_wrap_function(dst_thunk(def))); dst_env_def(env, name, dst_wrap_function(dst_thunk(def)));
} }
#define SSS(op, a, b, c) (op | (a << 8) | (b << 16) | (c << 24))
#define SS(op, a, b) SSS(op, a, b, 0)
#define S(op, a) SSS(op, a, 0, 0)
/* Variadic operator assembly. Must be templatized for each different opcode. */
/* Reg 0: Argument tuple (args) */
/* Reg 1: Argument count (argn) */
/* Reg 2: Jump flag (jump?) */
/* Reg 3: Accumulator (accum) */
/* Reg 4: Next operand (operand) */
/* Reg 5: Loop iterator (i) */
static DST_THREAD_LOCAL uint32_t varop_asm[] = {
DOP_LENGTH | (1 << 8), /* Put number of arguments in register 1 -> argn = count(args) */
/* Cheack nullary */
DOP_EQUALS_IMMEDIATE | (2 << 8) | (1 << 16) | (0 << 24), /* Check if numargs equal to 0 */
DOP_JUMP_IF_NOT | (2 << 8) | (3 << 16), /* If not 0, jump to next check */
/* Nullary */
DOP_LOAD_INTEGER | (3 << 8), /* accum = nullary value */
DOP_RETURN | (3 << 8), /* return accum */
/* Check unary */
DOP_EQUALS_IMMEDIATE | (2 << 8) | (1 << 16) | (1 << 24), /* Check if numargs equal to 1 */
DOP_JUMP_IF_NOT | (2 << 8) | (5 << 16), /* If not 1, jump to next check */
/* Unary */
DOP_LOAD_INTEGER | (3 << 8), /* accum = unary value */
DOP_GET_INDEX | (4 << 8) | (0 << 16) | (0 << 24), /* operand = args[0] */
DOP_NOOP | (3 << 8) | (3 << 16) | (4 << 24), /* accum = accum op operand */
DOP_RETURN | (3 << 8), /* return accum */
/* Mutli (2 or more) arity */
/* Prime loop */
DOP_GET_INDEX | (3 << 8) | (0 << 16) | (0 << 24), /* accum = args[0] */
DOP_LOAD_INTEGER | (5 << 8) | (1 << 16), /* i = 1 */
/* Main loop */
DOP_GET | (4 << 8) | (0 << 16) | (5 << 24), /* operand = args[i] */
DOP_NOOP | (3 << 8) | (3 << 16) | (4 << 24), /* accum = accum op operand */
DOP_ADD_IMMEDIATE | (5 << 8) | (5 << 16) | (1 << 24), /* i++ */
DOP_EQUALS_INTEGER | (2 << 8) | (5 << 16) | (1 << 24), /* jump? = (i == argn) */
DOP_JUMP_IF_NOT | (2 << 8) | ((uint32_t)(-4) << 16), /* if not jump? go back 4 */
/* Done, do last and return accumulator */
DOP_RETURN | (3 << 8) /* return accum */
};
#define VAROP_NULLARY_LOC 3
#define VAROP_UNARY_LOC 7
#define VAROP_OP_LOC1 9
#define VAROP_OP_LOC2 14
/* Templatize a varop */
static void templatize_varop(
DstTable *env,
int32_t flags,
const char *name,
int32_t nullary,
int32_t unary,
uint32_t op) {
varop_asm[VAROP_NULLARY_LOC] = SS(DOP_LOAD_INTEGER, 3, nullary);
varop_asm[VAROP_UNARY_LOC] = SS(DOP_LOAD_INTEGER, 3, unary);
varop_asm[VAROP_OP_LOC1] = SSS(op, 3, 3, 4);
varop_asm[VAROP_OP_LOC2] = SSS(op, 3, 3, 4);
dst_quick_asm(
env,
flags | DST_FUNCDEF_FLAG_VARARG,
name,
0,
6,
varop_asm,
sizeof(varop_asm));
}
DstTable *dst_stl_env(int flags) { DstTable *dst_stl_env(int flags) {
static uint32_t error_asm[] = { static uint32_t error_asm[] = {
DOP_ERROR DOP_ERROR
@ -125,6 +195,18 @@ DstTable *dst_stl_env(int flags) {
dst_quick_asm(env, DST_FUN_PUT, "put", 3, 3, put_asm, sizeof(put_asm)); dst_quick_asm(env, DST_FUN_PUT, "put", 3, 3, put_asm, sizeof(put_asm));
dst_quick_asm(env, DST_FUN_LENGTH, "length", 1, 1, length_asm, sizeof(length_asm)); dst_quick_asm(env, DST_FUN_LENGTH, "length", 1, 1, length_asm, sizeof(length_asm));
/* Variadic ops */
templatize_varop(env, DST_FUN_ADD, "+", 0, 0, DOP_ADD);
templatize_varop(env, DST_FUN_SUBTRACT, "-", 0, 0, DOP_SUBTRACT);
templatize_varop(env, DST_FUN_MULTIPLY, "*", 1, 1, DOP_MULTIPLY);
templatize_varop(env, DST_FUN_DIVIDE, "/", 1, 1, DOP_DIVIDE);
templatize_varop(env, DST_FUN_BAND, "&", -1, -1, DOP_BAND);
templatize_varop(env, DST_FUN_BOR, "|", 0, 0, DOP_BOR);
templatize_varop(env, DST_FUN_BXOR, "^", 0, 0, DOP_BXOR);
templatize_varop(env, DST_FUN_LSHIFT, "<<", 1, 1, DOP_SHIFT_LEFT);
templatize_varop(env, DST_FUN_RSHIFT, ">>", 1, 1, DOP_SHIFT_RIGHT);
templatize_varop(env, DST_FUN_RSHIFTU, ">>>", 1, 1, DOP_SHIFT_RIGHT_UNSIGNED);
dst_env_def(env, "VERSION", dst_cstringv(DST_VERSION)); dst_env_def(env, "VERSION", dst_cstringv(DST_VERSION));
/* Set as gc root */ /* Set as gc root */

View File

@ -112,6 +112,7 @@ static const DstInstructionDef dst_ops[] = {
{"lds", DOP_LOAD_SELF}, {"lds", DOP_LOAD_SELF},
{"ldt", DOP_LOAD_TRUE}, {"ldt", DOP_LOAD_TRUE},
{"ldu", DOP_LOAD_UPVALUE}, {"ldu", DOP_LOAD_UPVALUE},
{"length", DOP_LENGTH},
{"lt", DOP_LESS_THAN}, {"lt", DOP_LESS_THAN},
{"lti", DOP_LESS_THAN_INTEGER}, {"lti", DOP_LESS_THAN_INTEGER},
{"ltim", DOP_LESS_THAN_IMMEDIATE}, {"ltim", DOP_LESS_THAN_IMMEDIATE},

View File

@ -72,100 +72,6 @@ int dst_real(DstArgs args) {
return 0; return 0;
} }
#define ADD(x, y) ((x) + (y))
#define SUB(x, y) ((x) - (y))
#define MUL(x, y) ((x) * (y))
#define MOD(x, y) ((x) % (y))
#define DIV(x, y) ((x) / (y))
#define DST_DEFINE_BINOP(name, op, rop, onerr)\
Dst dst_op_##name(Dst lhs, Dst rhs) {\
if (!(dst_checktype(lhs, DST_INTEGER) || dst_checktype(lhs, DST_REAL))) onerr;\
if (!(dst_checktype(rhs, DST_INTEGER) || dst_checktype(rhs, DST_REAL))) onerr;\
return dst_checktype(lhs, DST_INTEGER)\
? (dst_checktype(rhs, DST_INTEGER)\
? dst_wrap_integer(op(dst_unwrap_integer(lhs), dst_unwrap_integer(rhs)))\
: dst_wrap_real(rop((double)dst_unwrap_integer(lhs), dst_unwrap_real(rhs))))\
: (dst_checktype(rhs, DST_INTEGER)\
? dst_wrap_real(rop(dst_unwrap_real(lhs), (double)dst_unwrap_integer(rhs)))\
: dst_wrap_real(rop(dst_unwrap_real(lhs), dst_unwrap_real(rhs))));\
}
DST_DEFINE_BINOP(add, ADD, ADD, return dst_wrap_nil())
DST_DEFINE_BINOP(subtract, SUB, SUB, return dst_wrap_nil())
DST_DEFINE_BINOP(multiply, MUL, MUL, return dst_wrap_nil())
#define DST_DEFINE_DIVIDER_OP(name, op, rop)\
Dst dst_op_##name(Dst lhs, Dst rhs) {\
if (!(dst_checktype(lhs, DST_INTEGER) || dst_checktype(lhs, DST_REAL))) return dst_wrap_nil();\
if (!(dst_checktype(rhs, DST_INTEGER) || dst_checktype(rhs, DST_REAL))) return dst_wrap_nil();\
return dst_checktype(lhs, DST_INTEGER)\
? (dst_checktype(rhs, DST_INTEGER)\
? (dst_unwrap_integer(rhs) == 0 || ((dst_unwrap_integer(lhs) == INT32_MIN) && (dst_unwrap_integer(rhs) == -1)))\
? dst_wrap_nil()\
: dst_wrap_integer(op(dst_unwrap_integer(lhs), dst_unwrap_integer(rhs)))\
: dst_wrap_real(rop((double)dst_unwrap_integer(lhs), dst_unwrap_real(rhs))))\
: (dst_checktype(rhs, DST_INTEGER)\
? dst_wrap_real(rop(dst_unwrap_real(lhs), (double)dst_unwrap_integer(rhs)))\
: dst_wrap_real(rop(dst_unwrap_real(lhs), dst_unwrap_real(rhs))));\
}
DST_DEFINE_DIVIDER_OP(divide, DIV, DIV)
DST_DEFINE_DIVIDER_OP(modulo, MOD, fmod)
#define DST_DEFINE_REDUCER(name, fop, start)\
int dst_##name(DstArgs args) {\
int32_t i;\
Dst accum = dst_wrap_integer(start);\
for (i = 0; i < args.n; i++) {\
accum = fop(accum, args.v[i]);\
}\
if (dst_checktype(accum, DST_NIL)) {\
*args.ret = dst_cstringv("expected number");\
return 1;\
}\
*args.ret = accum;\
return 0;\
}
DST_DEFINE_REDUCER(add, dst_op_add, 0)
DST_DEFINE_REDUCER(multiply, dst_op_multiply, 1)
#define DST_DEFINE_DIVIDER(name, unarystart)\
int dst_##name(DstArgs args) {\
int32_t i;\
Dst accum;\
if (args.n < 1) {\
*args.ret = dst_cstringv("expected at least one argument");\
return 1;\
} else if (args.n == 1) {\
accum = unarystart;\
i = 0;\
} else {\
accum = args.v[0];\
i = 1;\
}\
for (; i < args.n; i++) {\
accum = dst_op_##name(accum, args.v[i]);\
}\
if (dst_checktype(accum, DST_NIL)) {\
*args.ret = dst_cstringv("expected number or division error");\
return 1;\
}\
*args.ret = accum;\
return 0;\
}
DST_DEFINE_DIVIDER(divide, dst_wrap_real(1))
DST_DEFINE_DIVIDER(modulo, dst_wrap_real(1))
DST_DEFINE_DIVIDER(subtract, dst_wrap_integer(0))
#undef ADD
#undef SUB
#undef MUL
#undef MOD
#undef DST_DEFINE_BINOP
int dst_bnot(DstArgs args) { int dst_bnot(DstArgs args) {
if (args.n != 1) { if (args.n != 1) {
*args.ret = dst_cstringv("expected 1 argument"); *args.ret = dst_cstringv("expected 1 argument");
@ -179,48 +85,20 @@ int dst_bnot(DstArgs args) {
return 0; return 0;
} }
#define DST_DEFINE_BITOP(name, op, start)\ int dst_remainder(DstArgs args) {
int dst_##name(DstArgs args) {\
int32_t i;\
int32_t accum = start;\
for (i = 0; i < args.n; i++) {\
Dst arg = args.v[i];\
if (!dst_checktype(arg, DST_INTEGER)) {\
*args.ret = dst_cstringv("expected integer");\
return -1;\
}\
accum op dst_unwrap_integer(arg);\
}\
*args.ret = dst_wrap_integer(accum);\
return 0;\
}
DST_DEFINE_BITOP(band, &=, -1)
DST_DEFINE_BITOP(bor, |=, 0)
DST_DEFINE_BITOP(bxor, ^=, 0)
int dst_lshift(DstArgs args) {
int32_t lhs, rhs;
DST_FIXARITY(args, 2); DST_FIXARITY(args, 2);
DST_ARG_INTEGER(lhs, args, 0); if (dst_checktype(args.v[0], DST_INTEGER) &&
DST_ARG_INTEGER(rhs, args, 1); dst_checktype(args.v[1], DST_INTEGER)) {
DST_RETURN_INTEGER(args, lhs >> rhs); int32_t x, y;
x = dst_unwrap_integer(args.v[0]);
y = dst_unwrap_integer(args.v[1]);
DST_RETURN_INTEGER(args, x % y);
} else {
double x, y;
DST_ARG_NUMBER(x, args, 0);
DST_ARG_NUMBER(y, args, 1);
DST_RETURN_REAL(args, fmod(x, y));
} }
int dst_rshift(DstArgs args) {
int32_t lhs, rhs;
DST_FIXARITY(args, 2);
DST_ARG_INTEGER(lhs, args, 0);
DST_ARG_INTEGER(rhs, args, 1);
DST_RETURN_INTEGER(args, lhs << rhs);
}
int dst_lshiftu(DstArgs args) {
int32_t lhs, rhs;
DST_FIXARITY(args, 2);
DST_ARG_INTEGER(lhs, args, 0);
DST_ARG_INTEGER(rhs, args, 1);
DST_RETURN_INTEGER(args, (int32_t)((uint32_t)lhs << rhs));
} }
#define DST_DEFINE_MATHOP(name, fop)\ #define DST_DEFINE_MATHOP(name, fop)\
@ -337,15 +215,7 @@ DEF_NUMERIC_COMP(eq, ==)
DEF_NUMERIC_COMP(neq, !=) DEF_NUMERIC_COMP(neq, !=)
static const DstReg cfuns[] = { static const DstReg cfuns[] = {
{"random", dst_rand}, {"%", dst_remainder},
{"seedrandom", dst_srand},
{"int", dst_int},
{"real", dst_real},
{"+", dst_add},
{"-", dst_subtract},
{"*", dst_multiply},
{"/", dst_divide},
{"%", dst_modulo},
{"=", dst_strict_equal}, {"=", dst_strict_equal},
{"not=", dst_strict_notequal}, {"not=", dst_strict_notequal},
{"order<", dst_ascending}, {"order<", dst_ascending},
@ -358,27 +228,25 @@ static const DstReg cfuns[] = {
{">", dst_numeric_gt}, {">", dst_numeric_gt},
{"<=", dst_numeric_lte}, {"<=", dst_numeric_lte},
{">=", dst_numeric_gte}, {">=", dst_numeric_gte},
{"|", dst_bor},
{"&", dst_band},
{"^", dst_bxor},
{"~", dst_bnot}, {"~", dst_bnot},
{">>", dst_lshift},
{"<<", dst_rshift},
{">>>", dst_lshiftu},
{"not", dst_not}, {"not", dst_not},
{"cos", dst_cos}, {"int", dst_int},
{"sin", dst_sin}, {"real", dst_real},
{"tan", dst_tan}, {"math.random", dst_rand},
{"acos", dst_acos}, {"math.seedrandom", dst_srand},
{"asin", dst_asin}, {"math.cos", dst_cos},
{"atan", dst_atan}, {"math.sin", dst_sin},
{"exp", dst_exp}, {"math.tan", dst_tan},
{"log", dst_log}, {"math.acos", dst_acos},
{"log10", dst_log10}, {"math.asin", dst_asin},
{"sqrt", dst_sqrt}, {"math.atan", dst_atan},
{"floor", dst_floor}, {"math.exp", dst_exp},
{"ceil", dst_ceil}, {"math.log", dst_log},
{"pow", dst_pow}, {"math.log10", dst_log10},
{"math.sqrt", dst_sqrt},
{"math.floor", dst_floor},
{"math.ceil", dst_ceil},
{"math.pow", dst_pow},
{NULL, NULL} {NULL, NULL}
}; };
@ -387,8 +255,8 @@ int dst_lib_math(DstArgs args) {
DstTable *env = dst_env_arg(args); DstTable *env = dst_env_arg(args);
dst_env_cfuns(env, cfuns); dst_env_cfuns(env, cfuns);
dst_env_def(env, "pi", dst_wrap_real(3.1415926535897931)); dst_env_def(env, "math.pi", dst_wrap_real(3.1415926535897931));
dst_env_def(env, "e", dst_wrap_real(2.7182818284590451)); dst_env_def(env, "math.e", dst_wrap_real(2.7182818284590451));
dst_env_def(env, "inf", dst_wrap_real(INFINITY)); dst_env_def(env, "math.inf", dst_wrap_real(INFINITY));
return 0; return 0;
} }

View File

@ -336,10 +336,10 @@ static void *op_lookup[255] = {
vm_assert(dst_checktype(op1, DST_INTEGER) || dst_checktype(op1, DST_REAL), "expected number"); vm_assert(dst_checktype(op1, DST_INTEGER) || dst_checktype(op1, DST_REAL), "expected number");
vm_assert(dst_checktype(op2, DST_INTEGER) || dst_checktype(op2, DST_REAL), "expected number"); vm_assert(dst_checktype(op2, DST_INTEGER) || dst_checktype(op2, DST_REAL), "expected number");
if (dst_checktype(op2, DST_INTEGER) && dst_unwrap_integer(op2) == 0) if (dst_checktype(op2, DST_INTEGER) && dst_unwrap_integer(op2) == 0)
vm_throw("integer divide error"); vm_throw("integer divide by zero");
if (dst_checktype(op2, DST_INTEGER) && dst_unwrap_integer(op2) == -1 && if (dst_checktype(op2, DST_INTEGER) && dst_unwrap_integer(op2) == -1 &&
dst_checktype(op1, DST_INTEGER) && dst_unwrap_integer(op1) == INT32_MIN) dst_checktype(op1, DST_INTEGER) && dst_unwrap_integer(op1) == INT32_MIN)
vm_throw("integer divide error"); vm_throw("integer divide out of range");
stack[oparg(1, 0xFF)] = dst_checktype(op1, DST_INTEGER) stack[oparg(1, 0xFF)] = dst_checktype(op1, DST_INTEGER)
? (dst_checktype(op2, DST_INTEGER) ? (dst_checktype(op2, DST_INTEGER)
? dst_wrap_integer(dst_unwrap_integer(op1) / dst_unwrap_integer(op2)) ? dst_wrap_integer(dst_unwrap_integer(op1) / dst_unwrap_integer(op2))

View File

@ -35,20 +35,9 @@ int dst_core_native(DstArgs args);
/* Arithmetic */ /* Arithmetic */
int dst_int(DstArgs args); int dst_int(DstArgs args);
int dst_real(DstArgs args); int dst_real(DstArgs args);
int dst_add(DstArgs args);
int dst_subtract(DstArgs args);
int dst_multiply(DstArgs args);
int dst_divide(DstArgs args);
int dst_modulo(DstArgs args);
int dst_rand(DstArgs args); int dst_rand(DstArgs args);
int dst_srand(DstArgs args); int dst_srand(DstArgs args);
int dst_bor(DstArgs args); int dst_remainder(DstArgs args);
int dst_band(DstArgs args);
int dst_bxor(DstArgs args);
int dst_bnot(DstArgs args);
int dst_lshift(DstArgs args);
int dst_rshift(DstArgs args);
int dst_lshiftu(DstArgs args);
/* Math */ /* Math */
int dst_cos(DstArgs args); int dst_cos(DstArgs args);

View File

@ -45,7 +45,7 @@
(struct 1 2 3 4) (struct 1 2 3 4)
(buffer "hi") (buffer "hi")
(fn [x] (+ x x)) (fn [x] (+ x x))
+) "type ordering") print) "type ordering")
(assert (= (string (buffer "123" "456")) (string @"123456")) "buffer literal") (assert (= (string (buffer "123" "456")) (string @"123456")) "buffer literal")
(assert (= (get {} 1) nil) "get nil from empty struct") (assert (= (get {} 1) nil) "get nil from empty struct")

View File

@ -21,8 +21,8 @@
(import test.helper :prefix "" :exit true) (import test.helper :prefix "" :exit true)
(start-suite 1) (start-suite 1)
(assert (= 400.0 (sqrt 160000)) "sqrt(160000)=400") (assert (= 400.0 (math.sqrt 160000)) "sqrt(160000)=400")
(assert (= (real 400) (sqrt 160000)) "sqrt(160000)=400") (assert (= (real 400) (math.sqrt 160000)) "sqrt(160000)=400")
(def test-struct {'def 1 'bork 2 'sam 3 'a 'b 'het @[1 2 3 4 5]}) (def test-struct {'def 1 'bork 2 'sam 3 'a 'b 'het @[1 2 3 4 5]})
(assert (= (get test-struct 'def) 1) "struct get") (assert (= (get test-struct 'def) 1) "struct get")
@ -47,7 +47,7 @@
(:= good false))) (:= good false)))
(assert good e)) (assert good e))
(assert-many (fn [] (>= 1 (random) 0)) 200 "(random) between 0 and 1") (assert-many (fn [] (>= 1 (math.random) 0)) 200 "(random) between 0 and 1")
## Table prototypes ## Table prototypes
@ -167,4 +167,16 @@
(def f (compile (tuple.prepend manydefs 'do) *env*)) (def f (compile (tuple.prepend manydefs 'do) *env*))
(assert (= (f) (* 10000 3 5 7 9)) "long function compilation") (assert (= (f) (* 10000 3 5 7 9)) "long function compilation")
# Some higher order functions and macros
(def my-array @[1 2 3 4 5 6])
(def x (if-let [x (get my-array 5)] x))
(assert (= x 6) "if-let")
(def x (if-let [y (get @{} :key)] 10 nil))
(assert (not x) "if-let 2")
(assert (= 14 (sum (map inc @[1 2 3 4]))) "sum map")
(def myfun (juxt + - * /))
(assert (= '[2 -2 2 0] (myfun 2)) "juxt")
(end-suite) (end-suite)