.
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -39,3 +39,4 @@ tyche
|
||||
tyche-test
|
||||
libtyche.a
|
||||
libtyche.so*
|
||||
lib/compiler/compiler.lua.h
|
||||
15
Makefile
15
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}
|
||||
|
||||
9
lib/code.c
Normal file
9
lib/code.c
Normal 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
36
lib/compiler.c
Normal 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
85
lib/compiler/compiler.lua
Normal 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
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user