From c8a6db0e4e6ffea1db733540736a74216ad122c5 Mon Sep 17 00:00:00 2001 From: Andre Wagner Date: Fri, 15 May 2026 07:22:58 -0500 Subject: [PATCH] . --- lib/code.c | 35 ++++++++++++++ lib/compiler/compiler.lua | 97 ++++++++++++++++++++++++++++++++++++++- lib/priv.h | 86 ++++++++++++++++++++++++++++++++++ test/tests.c | 26 ++++++++++- 4 files changed, 241 insertions(+), 3 deletions(-) diff --git a/lib/code.c b/lib/code.c index 2265125..ee68897 100644 --- a/lib/code.c +++ b/lib/code.c @@ -15,6 +15,10 @@ #define N_CONST_ADDR 0x0c #define CONST_START 0x10 +#define OP_8BIT_OPERAND 0xa0 +#define OP_16BIT_OPERAND 0xc0 +#define OP_32BIT_OPERAND 0xe0 + struct Code { uint8_t const* bytecode; size_t bytecode_sz; @@ -126,3 +130,34 @@ uint32_t code_n_functions(Code const* code) { return code->fn_count; } + +Instruction code_next_instruction(Code const* code, uint32_t function_id, uint32_t pc) +{ + uint32_t addr = code->fn_addr[function_id] + 4 + pc; + uint8_t opcode = code->bytecode[addr]; + int32_t operand = 0; + uint8_t sz = 1; + + if (opcode >= OP_8BIT_OPERAND && opcode < OP_16BIT_OPERAND) { + operand = code->bytecode[addr + 1]; + sz = 2; + } else if (opcode >= OP_16BIT_OPERAND && opcode < OP_32BIT_OPERAND) { + opcode -= 0x20; + operand = (uint16_t) code->bytecode[addr + 1] | + (uint16_t) (code->bytecode[addr + 2] << 8); + sz = 3; + } else if (opcode >= OP_32BIT_OPERAND) { + opcode -= 0x40; + operand = (uint32_t) code->bytecode[addr + 1] | + (uint32_t) (code->bytecode[addr + 2] << 8) | + (uint32_t) (code->bytecode[addr + 3] << 16) | + (uint32_t) (code->bytecode[addr + 4] << 24); + sz = 5; + } + + return (Instruction) { + .operator = (TYC_INST) opcode, + .operand = operand, + .sz = sz, + }; +} \ No newline at end of file diff --git a/lib/compiler/compiler.lua b/lib/compiler/compiler.lua index 8b4bb05..fbe560b 100644 --- a/lib/compiler/compiler.lua +++ b/lib/compiler/compiler.lua @@ -80,6 +80,81 @@ end -- -- ---------------------- +local instructions = { + -- stack operations + pushi = 0xa0, + pushc = 0xa1, + pushf = 0xa2, + pushn = 0x00, + pushz = 0x01, + pusht = 0x02, + newa = 0x03, + newt = 0x04, + pop = 0x05, + dup = 0x06, + + -- local variables + pushv = 0xa3, + set = 0xa4, + dupv = 0xa5, + setg = 0xa6, + getg = 0xa7, + + -- function operations + call = 0xa7, + ret = 0x10, + reti = 0x11, + + -- table and array operations + getkv = 0x16, + setkv = 0x17, + geti = 0xa8, + seti = 0xa9, + appnd = 0x18, + next = 0x19, + smt = 0x1a, + mt = 0x1b, + + -- logical/arithmetic + sum = 0x20, + sub = 0x21, + mul = 0x22, + div = 0x23, + idiv = 0x24, + mod = 0x25, + eq = 0x26, + neq = 0x27, + lt = 0x28, + lte = 0x29, + gt = 0x2a, + gte = 0x2b, + ['and'] = 0x2c, + ['or'] = 0x2d, + xor = 0x2e, + pow = 0x2f, + shl = 0x30, + shr = 0x31, + + -- other value operations + len = 0x40, + type = 0x41, + cast = 0xaa, + ver = 0x42, + + -- external code + cmpl = 0x48, + asmbl = 0x49, + load = 0x4a, + + -- control flow + bz = 0xca, + bnz = 0xcb, + jmp = 0xcc, + + -- memory management + gc = 0x4b, +} + local MAGIC = 0xa7d6e9b1 local VERSION = 1 @@ -143,7 +218,27 @@ local function assemble(proto) local func = proto.functions[i] local next_function_pos = #bin + 1 push32(0) -- to be replaced with next function address - -- TODO - add code + for _,inst in ipairs(func) do + local opcode, operand = instructions[inst[1]], inst[2] + if opcode == nil then error("Unknown instruction " .. inst[1]) end + if operand == nil then + table.insert(bin, opcode) + else + if opcode >= 0xc0 and opcode < 0xe0 then + table.insert(bin, opcode) + push16(operand) + elseif operand >= -128 and operand <= 127 then + table.insert(bin, opcode) + table.insert(bin, operand) + elseif operand >= -32768 and operand <= 32767 then + table.insert(bin, opcode + 0x20) + push16(operand) + else + table.insert(bin, opcode + 0x40) + push32(operand) + end + end + end replace32(next_function_pos, #bin) end return string.char(table.unpack(bin)) diff --git a/lib/priv.h b/lib/priv.h index da1858e..c8d1574 100644 --- a/lib/priv.h +++ b/lib/priv.h @@ -7,6 +7,85 @@ #include #include +// +// INSTRUCTIONS +// + +typedef enum { + // STACK OPERATIONS + TO_PUSHI = 0XA0, + TO_PUSHC = 0XA1, + TO_PUSHF = 0XA2, + TO_PUSHN = 0X00, + TO_PUSHZ = 0X01, + TO_PUSHT = 0X02, + TO_NEWA = 0X03, + TO_NEWT = 0X04, + TO_POP = 0X05, + TO_DUP = 0X06, + + // LOCAL VARIABLES + TO_PUSHV = 0XA3, + TO_SET = 0XA4, + TO_DUPV = 0XA5, + TO_SETG = 0XA6, + TO_GETG = 0XA7, + + // FUNCTION OPERATIONS + TO_CALL = 0XA7, + TO_RET = 0X10, + TO_RETI = 0X11, + + // TABLE AND ARRAY OPERATIONS + TO_GETKV = 0X16, + TO_SETKV = 0X17, + TO_GETI = 0XA8, + TO_SETI = 0XA9, + TO_APPND = 0X18, + TO_NEXT = 0X19, + TO_SMT = 0X1A, + TO_MT = 0X1B, + + // LOGICAL/ARITHMETIC + TO_SUM = 0X20, + TO_SUB = 0X21, + TO_MUL = 0X22, + TO_DIV = 0X23, + TO_IDIV = 0X24, + TO_MOD = 0X25, + TO_EQ = 0X26, + TO_NEQ = 0X27, + TO_LT = 0X28, + TO_LTE = 0X29, + TO_GT = 0X2A, + TO_GTE = 0X2B, + TO_AND = 0X2C, + TO_OR = 0X2D, + TO_XOR = 0X2E, + TO_POW = 0X2F, + TO_SHL = 0X30, + TO_SHR = 0X31, + + // OTHER VALUE OPERATIONS + TO_LEN = 0X40, + TO_TYPE = 0X41, + TO_CAST = 0XAA, + TO_VER = 0X42, + + // EXTERNAL CODE + TO_CMPL = 0X48, + TO_ASMBL = 0X49, + TO_LOAD = 0X4A, + + // CONTROL FLOW + TO_BZ = 0XCA, + TO_BNZ = 0XCB, + TO_JMP = 0XCC, + + // MEMORY MANAGEMENT + TO_GC = 0X4B, +} TYC_INST; + // // TYPE DECLARATION // @@ -33,6 +112,12 @@ typedef enum { TC_STRING, TC_REAL, TC_INVALID_TYPE } TYC_CONST_TYPE; +typedef struct Instruction { + TYC_INST operator; + int32_t operand; + uint8_t sz; +} Instruction; + // // UTILS // @@ -138,5 +223,6 @@ T_REAL code_const_real(Code const* code, size_t n); 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); #endif //TYCHE_PRIV_H diff --git a/test/tests.c b/test/tests.c index 45fa716..4bf2fda 100644 --- a/test/tests.c +++ b/test/tests.c @@ -223,7 +223,7 @@ int main() "\n" ".func 0\n" " pushi 2 ; this is a comment\n" - " pushi 3\n" + " pushi -3\n" " sum\n" " ret\n" ".func 1\n" @@ -240,10 +240,32 @@ int main() assert(code_n_consts(code) == 2); assert(code_const_type(code, 0) == TC_REAL); assert(code_const_type(code, 1) == TC_STRING); - assert(code_const_real(code, 0) >= 3.13 && code_const_real(code, 0) <= 3.15); + assert(code_const_real(code, 0) > 3.13f && code_const_real(code, 0) < 3.15f); assert(strcmp(code_const_string(code, 1), "Hello world") == 0); assert(code_n_functions(code) == 2); + uint32_t addr = 0; + Instruction inst = code_next_instruction(code, 0, addr); + assert(inst.operator == TO_PUSHI); + assert(inst.operand == 2); + assert(inst.sz == 2); + addr += inst.sz; + + inst = code_next_instruction(code, 0, addr); + assert(inst.operator == TO_PUSHI); + assert(inst.operand == -3); + addr += inst.sz; + + inst = code_next_instruction(code, 0, addr); + assert(inst.operator == TO_SUM); + assert(inst.operand == 0); + addr += inst.sz; + + inst = code_next_instruction(code, 1, 0); + assert(inst.operator == TO_PUSHI); + assert(inst.operand == 5000); + assert(inst.sz == 3); + code_destroy(code); free(bytecode); }