diff --git a/TODO.md b/TODO.md index eb5d0c1..e10c92c 100644 --- a/TODO.md +++ b/TODO.md @@ -18,11 +18,11 @@ Decisions: - [x] (Lua interface) call assembler - [x] (Lua) generate bytecode - [x] Labels - - [ ] Code - - [ ] Interpret bytecode (fast) - - [ ] Execution loop (fast) + - [x] Code + - [x] Interpret bytecode (fast) + - [x] Execution loop (fast) - [ ] VM operations - - [ ] Expressions + - [x] Expressions - [ ] Local variables - [ ] Functions - [ ] With parameters diff --git a/lib/expr.c b/lib/expr.c index d3e621a..412df27 100644 --- a/lib/expr.c +++ b/lib/expr.c @@ -1,6 +1,7 @@ #include "priv.h" #include +#include static bool was_init = false; @@ -10,8 +11,23 @@ static BIN_EXPR_FN bin_expr_fn[TX_COUNT__][TT_COUNT__][TT_COUNT__]; static TYC_RESULT default_bin_op(VALUE a, VALUE b, VALUE* r) { (void) a; (void) b, (void) r; return T_ERR_EXPR_INCORRECT_TYPES; } #define BIN_OP(name) static TYC_RESULT name(VALUE a, VALUE b, VALUE* r) -BIN_OP(sum_int) { *r = create_value_integer(value_integer(a) + value_integer(b)); return T_OK; } -BIN_OP(sub_int) { *r = create_value_integer(value_integer(a) - value_integer(b)); return T_OK; } +BIN_OP(sum_int_int) { *r = create_value_integer(value_integer(a) + value_integer(b)); return T_OK; } +BIN_OP(sub_int_int) { *r = create_value_integer(value_integer(a) - value_integer(b)); return T_OK; } +BIN_OP(mul_int_int) { *r = create_value_integer(value_integer(a) * value_integer(b)); return T_OK; } +BIN_OP(idiv_int_int) { *r = create_value_integer(value_integer(a) / value_integer(b)); return T_OK; } +BIN_OP(eq_int_int) { *r = create_value_from_bool(value_integer(a) == value_integer(b)); return T_OK; } +BIN_OP(neq_int_int) { *r = create_value_from_bool(value_integer(a) != value_integer(b)); return T_OK; } +BIN_OP(lt_int_int) { *r = create_value_from_bool(value_integer(a) < value_integer(b)); return T_OK; } +BIN_OP(lte_int_int) { *r = create_value_from_bool(value_integer(a) <= value_integer(b)); return T_OK; } +BIN_OP(gt_int_int) { *r = create_value_from_bool(value_integer(a) > value_integer(b)); return T_OK; } +BIN_OP(gte_int_int) { *r = create_value_from_bool(value_integer(a) >= value_integer(b)); return T_OK; } +BIN_OP(and_int_int) { *r = create_value_integer(value_integer(a) & value_integer(b)); return T_OK; } +BIN_OP(or_int_int) { *r = create_value_integer(value_integer(a) | value_integer(b)); return T_OK; } +BIN_OP(xor_int_int) { *r = create_value_integer(value_integer(a) ^ value_integer(b)); return T_OK; } +BIN_OP(pow_int_int) { *r = create_value_integer(pow(value_integer(a), value_integer(b))); return T_OK; } +BIN_OP(shl_int_int) { *r = create_value_integer(value_integer(a) << value_integer(b)); return T_OK; } +BIN_OP(shr_int_int) { *r = create_value_integer(value_integer(a) >> value_integer(b)); return T_OK; } +BIN_OP(mod_int_int) { *r = create_value_integer(value_integer(a) % value_integer(b)); return T_OK; } void expr_init(void) { @@ -23,8 +39,23 @@ void expr_init(void) for (size_t k = 0; k < TT_COUNT__; ++k) bin_expr_fn[i][j][k] = default_bin_op; - bin_expr_fn[TX_SUM][TT_INTEGER][TT_INTEGER] = sum_int; - bin_expr_fn[TX_SUBTRACT][TT_INTEGER][TT_INTEGER] = sub_int; + bin_expr_fn[TX_SUM][TT_INTEGER][TT_INTEGER] = sum_int_int; + bin_expr_fn[TX_SUB][TT_INTEGER][TT_INTEGER] = sub_int_int; + bin_expr_fn[TX_MUL][TT_INTEGER][TT_INTEGER] = mul_int_int; + bin_expr_fn[TX_IDIV][TT_INTEGER][TT_INTEGER] = idiv_int_int; + bin_expr_fn[TX_EQ][TT_INTEGER][TT_INTEGER] = eq_int_int; + bin_expr_fn[TX_NEQ][TT_INTEGER][TT_INTEGER] = neq_int_int; + bin_expr_fn[TX_LT][TT_INTEGER][TT_INTEGER] = lt_int_int; + bin_expr_fn[TX_LTE][TT_INTEGER][TT_INTEGER] = lte_int_int; + bin_expr_fn[TX_GT][TT_INTEGER][TT_INTEGER] = gt_int_int; + bin_expr_fn[TX_GTE][TT_INTEGER][TT_INTEGER] = gte_int_int; + bin_expr_fn[TX_AND][TT_INTEGER][TT_INTEGER] = and_int_int; + bin_expr_fn[TX_OR][TT_INTEGER][TT_INTEGER] = or_int_int; + bin_expr_fn[TX_XOR][TT_INTEGER][TT_INTEGER] = xor_int_int; + bin_expr_fn[TX_POW][TT_INTEGER][TT_INTEGER] = pow_int_int; + bin_expr_fn[TX_SHL][TT_INTEGER][TT_INTEGER] = shl_int_int; + bin_expr_fn[TX_SHR][TT_INTEGER][TT_INTEGER] = shr_int_int; + bin_expr_fn[TX_MOD][TT_INTEGER][TT_INTEGER] = mod_int_int; was_init = true; } diff --git a/lib/priv.h b/lib/priv.h index c618cfe..3d3ffb1 100644 --- a/lib/priv.h +++ b/lib/priv.h @@ -140,6 +140,7 @@ uint32_t value_idx(VALUE v); bool value_is_zero(VALUE v); VALUE create_value_nil(void); +VALUE create_value_from_bool(bool b); VALUE create_value_integer(int32_t v); VALUE create_value_real(float f); VALUE create_value_idx(TYC_TYPE type, uint32_t idx); diff --git a/lib/tyche.h b/lib/tyche.h index 9948e4e..a9d4691 100644 --- a/lib/tyche.h +++ b/lib/tyche.h @@ -20,7 +20,8 @@ typedef enum { } TYC_RESULT; typedef enum { - TX_SUM, TX_SUBTRACT, + TX_SUM, TX_SUB, TX_MUL, TX_IDIV, TX_EQ, TX_NEQ, TX_LT, TX_LTE, TX_GT, TX_GTE, TX_AND, TX_OR, TX_XOR, TX_POW, + TX_SHL, TX_SHR, TX_MOD, TX_COUNT__ } TYC_EXPR; diff --git a/lib/value.c b/lib/value.c index 0c0670c..5acf141 100644 --- a/lib/value.c +++ b/lib/value.c @@ -46,6 +46,11 @@ VALUE create_value_nil(void) return (VALUE) { .type = TT_NIL }; } +VALUE create_value_from_bool(bool b) +{ + return b ? create_value_integer(1) : create_value_integer(0); +} + VALUE create_value_integer(int32_t v) { return (VALUE) { .type = TT_INTEGER, .v = { .i = v } }; diff --git a/lib/vm.c b/lib/vm.c index afce9ed..6729a64 100644 --- a/lib/vm.c +++ b/lib/vm.c @@ -221,8 +221,23 @@ static TYC_RESULT step(TycheVM* T) // expressions // - case TO_SUM: TRY(tyc_expr(T, TX_SUM)); break; - case TO_SUB: TRY(tyc_expr(T, TX_SUBTRACT)); break; + case TO_SUM: TRY(tyc_expr(T, TX_SUM)); break; + case TO_SUB: TRY(tyc_expr(T, TX_SUB)); break; + case TO_MUL: TRY(tyc_expr(T, TX_MUL)); break; + case TO_IDIV: TRY(tyc_expr(T, TX_IDIV)); break; + case TO_EQ: TRY(tyc_expr(T, TX_EQ)); break; + case TO_NEQ: TRY(tyc_expr(T, TX_NEQ)); break; + case TO_LT: TRY(tyc_expr(T, TX_LT)); break; + case TO_LTE: TRY(tyc_expr(T, TX_LTE)); break; + case TO_GT: TRY(tyc_expr(T, TX_GT)); break; + case TO_GTE: TRY(tyc_expr(T, TX_GTE)); break; + case TO_AND: TRY(tyc_expr(T, TX_AND)); break; + case TO_OR: TRY(tyc_expr(T, TX_OR)); break; + case TO_XOR: TRY(tyc_expr(T, TX_XOR)); break; + case TO_POW: TRY(tyc_expr(T, TX_POW)); break; + case TO_SHL: TRY(tyc_expr(T, TX_SHL)); break; + case TO_SHR: TRY(tyc_expr(T, TX_SHR)); break; + case TO_MOD: TRY(tyc_expr(T, TX_MOD)); break; // // function calls diff --git a/test/code-tests.lua b/test/code-tests.lua index eceb9bc..5aef6ac 100644 --- a/test/code-tests.lua +++ b/test/code-tests.lua @@ -21,8 +21,25 @@ return { ret ]], scenarios = { - { parameters = { 2, 3, 'sum' }, name = "Sum", expected_stack_top = 5 }, - { parameters = { 2, 3, 'sub' }, name = "Subtraction", expected_stack_top = -1 }, + { parameters = { 2, 5, 'sum' }, name = "Sum", expected_stack_top = 7 }, + { parameters = { 2, 5, 'sub' }, name = "Subtraction", expected_stack_top = -3 }, + { parameters = { 2, 5, 'mul' }, name = "Multiplication", expected_stack_top = 10 }, + { parameters = { 20, 3, 'idiv' }, name = "Integer division", expected_stack_top = 6 }, + { parameters = { 5, 5, 'eq' }, name = "Equality", expected_stack_top = 1 }, + { parameters = { 5, 5, 'neq' }, name = "Inequality", expected_stack_top = 0 }, + { parameters = { 4, 5, 'lt' }, name = "Less than", expected_stack_top = 1 }, + { parameters = { 5, 5, 'lt' }, name = "Less than", expected_stack_top = 0 }, + { parameters = { 4, 5, 'lte' }, name = "Less than or equal", expected_stack_top = 1 }, + { parameters = { 5, 5, 'lte' }, name = "Less than or equal", expected_stack_top = 1 }, + { parameters = { 5, 5, 'gt' }, name = "Greater than", expected_stack_top = 0 }, + { parameters = { 5, 5, 'gte' }, name = "Greater than or equal", expected_stack_top = 1 }, + { parameters = { 20, 5, 'and' }, name = "Logical AND", expected_stack_top = 4 }, + { parameters = { 20, 5, 'or' }, name = "Logical OR", expected_stack_top = 21 }, + { parameters = { 20, 5, 'xor' }, name = "Logical XOR", expected_stack_top = 17 }, + { parameters = { 2, 5, 'pow' }, name = "Power", expected_stack_top = 32 }, + { parameters = { 2, 5, 'shl' }, name = "Shift left", expected_stack_top = 64 }, + { parameters = { 20, 3, 'shr' }, name = "Shift right", expected_stack_top = 2}, + { parameters = { 20, 3, 'mod' }, name = "Modulo", expected_stack_top = 2 }, }, } } \ No newline at end of file