This commit is contained in:
2026-05-14 13:02:43 -05:00
parent 2265b8cf08
commit 3e47163ee5
6 changed files with 144 additions and 3 deletions

1
.gitignore vendored
View File

@@ -39,3 +39,4 @@ tyche
tyche-test
libtyche.a
libtyche.so*
lib/compiler/compiler.lua.h

View File

@@ -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}

9
lib/code.c Normal file
View File

@@ -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)
{
}

36
lib/compiler.c Normal file
View File

@@ -0,0 +1,36 @@
#include "priv.h"
#include <stdlib.h>
#include <string.h>
#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;
}

85
lib/compiler/compiler.lua Normal file
View File

@@ -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

View File

@@ -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