From 9ff38cd4c0b495fc65b787e35b7cd55bd9b100a6 Mon Sep 17 00:00:00 2001 From: Andre Wagner Date: Thu, 7 May 2026 20:26:03 -0500 Subject: [PATCH] . --- lua-temp/doc/OPCODES | 8 ++++---- lua-temp/tests.lua | 48 +++++++++++++++++++++---------------------- lua-temp/tyche-as.lua | 39 +++++++++++++++++++++++++++-------- 3 files changed, 59 insertions(+), 36 deletions(-) diff --git a/lua-temp/doc/OPCODES b/lua-temp/doc/OPCODES index e333e7a..18338b3 100644 --- a/lua-temp/doc/OPCODES +++ b/lua-temp/doc/OPCODES @@ -82,10 +82,10 @@ External code: 49 asmbl Assemble code to bytecode format 4a load Load bytecode as function (will place function on stack) -Control flow: - a8 c8 e8 bz [pc] Branch if zero - a9 c9 e9 bnz [pc] Branch if not zero - aa ca ea jmp [pc] Unconditional jump +Control flow (the destination is always a 16-bit field): + c8 bz [pc] Branch if zero + c9 bnz [pc] Branch if not zero + ca jmp [pc] Unconditional jump * Jumps can only happen within the same function. diff --git a/lua-temp/tests.lua b/lua-temp/tests.lua index c5eb8d4..4cec26e 100644 --- a/lua-temp/tests.lua +++ b/lua-temp/tests.lua @@ -71,30 +71,30 @@ do TEST "Parser" assert_eq(found, expected) end ---do TEST "Parser: labels" --- --- local source = [[ --- .func 0 --- jmp %my_label --- pushi 3 --- %my_label: --- ret ]] --- --- local expected = { --- constants = {}, --- functions = { --- [0] = { --- { "jmp", "%my_label" }, --- { "pushi", 3 }, --- { "ret", labels = { "%my_label" } }, --- } --- } --- } --- --- local found = assemble(source) --- pprint(found) --- assert_eq(found, expected) ---end +do TEST "Parser: labels" + + local source = [[ + .func 0 + jmp @my_label + pushi 3 + @my_label: + ret ]] + + local expected = { + constants = {}, + functions = { + [0] = { + { "jmp", "@my_label" }, + { "pushi", 3 }, + { "ret", labels = { "@my_label" } }, + } + } + } + + local found = assemble(source) + pprint(found) + assert_eq(found, expected) +end ---------------------- -- -- diff --git a/lua-temp/tyche-as.lua b/lua-temp/tyche-as.lua index 0fd8c40..e481b32 100644 --- a/lua-temp/tyche-as.lua +++ b/lua-temp/tyche-as.lua @@ -13,6 +13,7 @@ local function assemble(source) 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 @@ -28,21 +29,43 @@ local function assemble(source) 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") end + 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 inst, par = line:match("^%s*(%a+)%s+(%d+)%s*$") - if inst then - table.insert(proto.functions[current_f_id], { inst, tonumber(par) }) - else - local inst = line:match("^%s*(%a+)%s*$") - if not inst then error("Invalid row for function") end - table.insert(proto.functions[current_f_id], { inst }) + 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 + 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::