This commit is contained in:
Andre Wagner
2026-05-07 20:26:03 -05:00
parent 4a23c52781
commit 9ff38cd4c0
3 changed files with 59 additions and 36 deletions

View File

@@ -82,10 +82,10 @@ External code:
49 asmbl Assemble code to bytecode format 49 asmbl Assemble code to bytecode format
4a load Load bytecode as function (will place function on stack) 4a load Load bytecode as function (will place function on stack)
Control flow: Control flow (the destination is always a 16-bit field):
a8 c8 e8 bz [pc] Branch if zero c8 bz [pc] Branch if zero
a9 c9 e9 bnz [pc] Branch if not zero c9 bnz [pc] Branch if not zero
aa ca ea jmp [pc] Unconditional jump ca jmp [pc] Unconditional jump
* Jumps can only happen within the same function. * Jumps can only happen within the same function.

View File

@@ -71,30 +71,30 @@ do TEST "Parser"
assert_eq(found, expected) assert_eq(found, expected)
end end
--do TEST "Parser: labels" do TEST "Parser: labels"
--
-- local source = [[ local source = [[
-- .func 0 .func 0
-- jmp %my_label jmp @my_label
-- pushi 3 pushi 3
-- %my_label: @my_label:
-- ret ]] ret ]]
--
-- local expected = { local expected = {
-- constants = {}, constants = {},
-- functions = { functions = {
-- [0] = { [0] = {
-- { "jmp", "%my_label" }, { "jmp", "@my_label" },
-- { "pushi", 3 }, { "pushi", 3 },
-- { "ret", labels = { "%my_label" } }, { "ret", labels = { "@my_label" } },
-- } }
-- } }
-- } }
--
-- local found = assemble(source) local found = assemble(source)
-- pprint(found) pprint(found)
-- assert_eq(found, expected) assert_eq(found, expected)
--end end
---------------------- ----------------------
-- -- -- --

View File

@@ -13,6 +13,7 @@ local function assemble(source)
local section = '' local section = ''
local current_f_id = 0 local current_f_id = 0
local next_label = nil
for line in source:gmatch("([^\n]+)") do for line in source:gmatch("([^\n]+)") do
local line = line:gsub("%s*;.*$", "") -- remove comments local line = line:gsub("%s*;.*$", "") -- remove comments
line = line:match("^%s*(.-)%s*$") -- trim line = line:match("^%s*(.-)%s*$") -- trim
@@ -28,22 +29,44 @@ local function assemble(source)
current_f_id = f_id current_f_id = f_id
elseif section == 'const' then elseif section == 'const' then
local k, v = line:match("^%s*(%d+)%s*:%s*(.+)$") local k, v = line:match("^%s*(%d+)%s*:%s*(.+)$")
if not k then error("Invalid row for constant") end if not k then error("Invalid row for constant: " .. line) end
if v:sub(1, 1) == '"' then if v:sub(1, 1) == '"' then
proto.constants[tonumber(k)] = line:match('"(.*)"') proto.constants[tonumber(k)] = line:match('"(.*)"')
else else
proto.constants[tonumber(k)] = tonumber(v) proto.constants[tonumber(k)] = tonumber(v)
end end
elseif section == 'function' then elseif section == 'function' then
local inst, par = line:match("^%s*(%a+)%s+(%d+)%s*$") local regexes = {
"^%s*(%a+)%s+(%d+)%s*$", -- instruction + parameter
"^%s*(%a+)%s+(@[%a_]+)%s*$", -- instruction + label
"^%s*(%a+)%s*$", -- instruction only
"^(@[%a_]+):%s*$", -- label
}
local match = false
for i,regex in ipairs(regexes) do
local inst, par = line:match(regex)
if inst then if inst then
table.insert(proto.functions[current_f_id], { inst, tonumber(par) }) 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 else
local inst = line:match("^%s*(%a+)%s*$") table.insert(next_label, inst)
if not inst then error("Invalid row for function") end
table.insert(proto.functions[current_f_id], { inst })
end end
end end
if i ~= 4 then
next_label = nil
end
end
end
if not match then error("Invalid instruction: " .. line) end
end
::continue:: ::continue::
end end