diff --git a/Makefile b/Makefile index 431fcac..dbc9a36 100644 --- a/Makefile +++ b/Makefile @@ -87,7 +87,7 @@ lib/compiler.o: lib/compiler.c lib/compiler/compiler.lua.h # executable files # -LIB_SRC=lib/value.o lib/stack.o lib/array.o lib/table.o lib/heap.o lib/vm.o lib/compiler.o lib/code.o lib/utils.o +LIB_SRC=lib/value.o lib/stack.o lib/array.o lib/table.o lib/heap.o lib/vm.o lib/expr.o lib/compiler.o lib/code.o lib/utils.o tyche: CFLAGS += ${RELEASE_CFLAGS} tyche: LDFLAGS += ${RELEASE_LDFLAGS} diff --git a/lib/expr.c b/lib/expr.c new file mode 100644 index 0000000..d3e621a --- /dev/null +++ b/lib/expr.c @@ -0,0 +1,35 @@ +#include "priv.h" + +#include + +static bool was_init = false; + +typedef TYC_RESULT(*BIN_EXPR_FN)(VALUE, VALUE, VALUE*); +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; } + +void expr_init(void) +{ + if (was_init) + return; + + for (size_t i = 0; i < TX_COUNT__; ++i) + for (size_t j = 0; j < TT_COUNT__; ++j) + 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; + + was_init = true; +} + +TYC_RESULT binary_expr(TYC_EXPR op, VALUE a, VALUE b, VALUE* result) +{ + return bin_expr_fn[op][value_type(a)][value_type(b)](a, b, result); +} \ No newline at end of file diff --git a/lib/priv.h b/lib/priv.h index 4398ce1..c618cfe 100644 --- a/lib/priv.h +++ b/lib/priv.h @@ -225,4 +225,11 @@ const char* code_const_string(Code const* code, size_t n); uint32_t code_n_functions(Code const* code); Instruction code_next_instruction(Code const* code, uint32_t function_id, uint32_t pc); +// +// EXPRESSIONS +// + +void expr_init(void); +TYC_RESULT binary_expr(TYC_EXPR op, VALUE a, VALUE b, VALUE* result); + #endif //TYCHE_PRIV_H diff --git a/lib/table.c b/lib/table.c index 2472d0e..6614db8 100644 --- a/lib/table.c +++ b/lib/table.c @@ -59,6 +59,7 @@ static TABLE_HASH value_hash(VALUE v) case TT_NATIVE_PTR: return (TABLE_HASH) value_idx(v) | ((TABLE_HASH) 1 << 37); case TT_STRING: + case TT_COUNT__: default: __builtin_unreachable(); } diff --git a/lib/tyche.h b/lib/tyche.h index 1fd7c49..9948e4e 100644 --- a/lib/tyche.h +++ b/lib/tyche.h @@ -6,6 +6,7 @@ typedef enum { TT_NIL, TT_INTEGER, TT_REAL, TT_STRING, TT_STRING_CONST, TT_ARRAY, TT_TABLE, TT_FUNCTION, TT_NATIVE_PTR, + TT_COUNT__ } TYC_TYPE; typedef enum { @@ -15,11 +16,12 @@ typedef enum { T_ERR_TABLE_KEY_NOT_FOUND = -20, T_ERR_ASSEMBLER_SYNTAX_ERROR = -30, T_ERR_BYTECODE_TOO_SMALL = -40, T_ERR_BYTECODE_INVALID_MAGIC = -41, - T_ERR_TYPE_UNEXPECTED = -50, T_ERR_INVALID_OPCODE = -51, + T_ERR_TYPE_UNEXPECTED = -50, T_ERR_INVALID_OPCODE = -51, T_ERR_EXPR_INCORRECT_TYPES = -52, } TYC_RESULT; typedef enum { - TX_SUM, + TX_SUM, TX_SUBTRACT, + TX_COUNT__ } TYC_EXPR; #define T_REAL float diff --git a/lib/vm.c b/lib/vm.c index 814e5fc..afce9ed 100644 --- a/lib/vm.c +++ b/lib/vm.c @@ -39,6 +39,9 @@ TycheVM* tyc_new(void) .cap = 4, .sz = 0, }; + + expr_init(); + return t; } @@ -177,13 +180,16 @@ TYC_RESULT tyc_tointeger(TycheVM* T, int idx, int32_t* value) return r; } -TYC_RESULT tyc_expr(TycheVM* T, TYC_EXPR expr) +TYC_RESULT tyc_expr(TycheVM* T, TYC_EXPR op) { - // TODO - VALUE v1, v2; + TYC_RESULT r; + VALUE v1, v2, result; + stack_pop(T->stack, &v2); stack_pop(T->stack, &v1); - stack_push(T->stack, create_value_integer(value_integer(v1) + value_integer(v2))); + TRY(binary_expr(op, v1, v2, &result)) + stack_push(T->stack, result); + return T_OK; } @@ -203,13 +209,24 @@ static TYC_RESULT step(TycheVM* T) switch (inst.operator) { + // + // stack manipulation + // + case TO_PUSHI: tyc_pushinteger(T, inst.operand); break; - case TO_SUM: - TRY(tyc_expr(T, TX_SUM)) - break; + // + // expressions + // + + case TO_SUM: TRY(tyc_expr(T, TX_SUM)); break; + case TO_SUB: TRY(tyc_expr(T, TX_SUBTRACT)); break; + + // + // function calls + // case TO_RET: TRY(stack_pop(T->stack, &a)) diff --git a/test/tests.c b/test/tests.c index b96f276..6af07ed 100644 --- a/test/tests.c +++ b/test/tests.c @@ -310,7 +310,7 @@ int main(void) tyc_pushinteger(T, 2); tyc_pushinteger(T, 3); - tyc_expr(T, TX_SUM); + assert(tyc_expr(T, TX_SUM) == T_OK); int32_t result; assert(tyc_tointeger(T, -1, &result) == T_OK); assert(result == 5); @@ -408,7 +408,7 @@ static void run_assembly_test_code(lua_State* L) static void run_assembly_test_template(lua_State* L) { lua_getfield(L, -1, "template"); - const char* template = strdup(lua_tostring(L, -1)); + char* template = strdup(lua_tostring(L, -1)); lua_pop(L, 1); lua_getfield(L, -1, "scenarios"); @@ -430,12 +430,12 @@ static void run_assembly_test_template(lua_State* L) lua_getfield(L, -3, "parameters"); assert(!lua_isnil(L, -1)); int n_params = (int) luaL_len(L, -1); - for (long j = 0; j < n_params; ++j) + for (int j = 0; j < n_params; ++j) lua_geti(L, -(j + 1), j + 1); lua_remove(L, -(n_params + 1)); lua_call(L, n_params + 1, 1); - const char* formatted_code = strdup(lua_tostring(L, -1)); + char* formatted_code = strdup(lua_tostring(L, -1)); lua_pop(L, 1); // run code