From 3e47163ee5be5b8d7817141f0a59bd3528b990ad Mon Sep 17 00:00:00 2001 From: Andre Wagner Date: Thu, 14 May 2026 13:02:43 -0500 Subject: [PATCH] . --- .gitignore | 1 + Makefile | 15 +++++-- lib/code.c | 9 +++++ lib/compiler.c | 36 +++++++++++++++++ lib/compiler/compiler.lua | 85 +++++++++++++++++++++++++++++++++++++++ lib/tyche.h | 1 + 6 files changed, 144 insertions(+), 3 deletions(-) create mode 100644 lib/code.c create mode 100644 lib/compiler.c create mode 100644 lib/compiler/compiler.lua diff --git a/.gitignore b/.gitignore index df81a13..c73b140 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,4 @@ tyche tyche-test libtyche.a libtyche.so* +lib/compiler/compiler.lua.h \ No newline at end of file diff --git a/Makefile b/Makefile index b77b197..d31e2bc 100644 --- a/Makefile +++ b/Makefile @@ -48,7 +48,6 @@ RELEASE_LDFLAGS=-flto=auto CFLAGS+=-std=c99 -D_GNU_SOURCE -fPIC -fvisibility=hidden -isystem lib/contrib -MMD -MP LDFLAGS+= - # # generic targets # @@ -59,7 +58,7 @@ check: tyche-test ./tyche-test clean: - rm -f tyche libtyche.a libtyche.so* tyche-test **/*.o **/*.d + rm -f tyche libtyche.a libtyche.so* tyche-test **/*.o **/*.d compiler/compiler.h install: tyche libtyche.a libtyche.so.${VERSION} lib/tyche.h install -m 644 libtyche.a libtyche.so.${VERSION} ${PREFIX}/lib @@ -73,11 +72,21 @@ uninstall: .PHONY: all check clean install uninstall +# +# TODO - temporary, using Lua for compilation for now +# +LDFLAGS+=-llua -lm +lib/compiler/compiler.lua.h: + luac -o lib/compiler/compiler.out lib/compiler/compiler.lua + xxd -i lib/compiler/compiler.out > lib/compiler/compiler.lua.h + rm lib/compiler/compiler.out +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/utils.o +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 tyche: CFLAGS += ${RELEASE_CFLAGS} tyche: LDFLAGS += ${RELEASE_LDFLAGS} diff --git a/lib/code.c b/lib/code.c new file mode 100644 index 0000000..feae963 --- /dev/null +++ b/lib/code.c @@ -0,0 +1,9 @@ +#include "priv.h" + +Code* code_load_bytecode(uint8_t* bytecode, size_t bytecode_sz) +{ +} + +Code* code_load_bytecode_cb(void(*read_bytes)(size_t, void*), void* data) +{ +} \ No newline at end of file diff --git a/lib/compiler.c b/lib/compiler.c new file mode 100644 index 0000000..c272da2 --- /dev/null +++ b/lib/compiler.c @@ -0,0 +1,36 @@ +#include "priv.h" + +#include +#include + +#include "lua.h" +#include "lauxlib.h" + +#include "compiler/compiler.lua.h" + +TYC_RESULT code_assemble(const char* code, uint8_t** bytecode, size_t* bytecode_sz) +{ + lua_State* L = luaL_newstate(); + + int r = luaL_loadbufferx(L, (const char *) lib_compiler_compiler_out, lib_compiler_compiler_out_len, "compiler", "b"); + if (r == LUA_ERRSYNTAX) + abort(); + else if (r == LUA_ERRMEM) + out_of_memory(); + + lua_pushstring(L, code); + r = lua_pcall(L, 1, 1, 0); + if (r == LUA_ERRMEM) { + out_of_memory(); + } else if (r == LUA_ERRERR) { + abort(); + } else if (r == LUA_ERRRUN) { + fprintf(stderr, "%s\n", lua_tostring(L, -1)); + return T_ERR_ASSEMBLER_SYNTAX_ERROR; + } + + + + lua_close(L); + return T_OK; +} diff --git a/lib/compiler/compiler.lua b/lib/compiler/compiler.lua new file mode 100644 index 0000000..367d945 --- /dev/null +++ b/lib/compiler/compiler.lua @@ -0,0 +1,85 @@ +---------------------- +-- -- +-- PARSER -- +-- -- +---------------------- + +local function assemble(source) + local proto = { + constants = {}, + functions = {}, + } + + local section = '' + local current_f_id = 0 + + local next_label = nil + for line in source:gmatch("([^\n]+)") do + local line = line:gsub("%s*;.*$", "") -- remove comments + line = line:match("^%s*(.-)%s*$") -- trim + + if #line == 0 then goto continue end + + if line == ".const" then + section = 'const' + elseif line:match("%.func%s+%d+") then + section = 'function' + local f_id = tonumber(line:match("%.func%s+(%d+)")) + proto.functions[f_id] = {} + current_f_id = f_id + elseif section == 'const' then + local k, v = line:match("^%s*(%d+)%s*:%s*(.+)$") + if not k then error("Invalid row for constant: " .. line) end + if v:sub(1, 1) == '"' then + proto.constants[tonumber(k)] = line:match('"(.*)"') + else + proto.constants[tonumber(k)] = tonumber(v) + end + elseif section == 'function' then + local regexes = { + "^%s*(%a+)%s+(%d+)%s*$", -- instruction + parameter + "^%s*(%a+)%s+(@[%a_][%a%d_]*)%s*$", -- instruction + label + "^%s*(%a+)%s*$", -- instruction only + "^(@[%a_][%a%d_]*):%s*$", -- label + } + local match = false + for i,regex in ipairs(regexes) do + local inst, par = line:match(regex) + if inst then + match = true + if i == 1 then -- instruction + parameter + table.insert(proto.functions[current_f_id], { inst, tonumber(par), labels = next_label }) + elseif i == 2 then -- instruction + label + table.insert(proto.functions[current_f_id], { inst, par, labels = next_label }) + elseif i == 3 then -- instruction only + table.insert(proto.functions[current_f_id], { inst, labels = next_label }) + elseif i == 4 then -- label + if not next_label then + next_label = { inst } + else + table.insert(next_label, inst) + end + end + if i ~= 4 then + next_label = nil + end + end + end + if not match then error("Invalid instruction: " .. line) end + end + + ::continue:: + end + + return proto +end + +---------------------- +-- -- +-- GENERIC -- +-- -- +---------------------- + +return function(source) + return { 0, 1, 2, 3, 4 } +end \ No newline at end of file diff --git a/lib/tyche.h b/lib/tyche.h index 52fa1e8..34b7344 100644 --- a/lib/tyche.h +++ b/lib/tyche.h @@ -10,6 +10,7 @@ typedef enum { T_ERR_STACK_UNDERFLOW = -1, T_ERR_STACK_FP_UNDERFLOW = -2, T_ERR_STACK_ACCESS_OUT_OF_RANGE = -3, T_ERR_HEAP_KEY_NOT_FOUND = -10, T_ERR_TABLE_KEY_NOT_FOUND = -20, + T_ERR_ASSEMBLER_SYNTAX_ERROR = -30, } TYC_RESULT; #endif //TYCHE_TYCHE_H