1
0
Fork 0
mirror of https://github.com/notwa/mm synced 2024-11-05 06:39:02 -08:00
mm/Lua/lib/lips/Expander.lua
2018-05-01 17:31:00 +02:00

98 lines
2.7 KiB
Lua

local insert = table.insert
local path = string.gsub(..., "[^.]+$", "")
local data = require(path.."data")
local overrides = require(path.."overrides")
local Statement = require(path.."Statement")
local Reader = require(path.."Reader")
local Expander = Reader:extend()
function Expander:init(options)
self.options = options or {}
end
function Expander:statement(...)
local s = Statement(self.fn, self.line, ...)
return s
end
function Expander:push(s)
s:validate()
insert(self.statements, s)
end
function Expander:push_new(...)
self:push(self:statement(...))
end
function Expander:pop(kind)
local ret
if kind == nil then
ret = self.s[self.i]
elseif kind == 'CPU' then
ret = self:register(data.registers)
elseif kind == 'FPU' then
ret = self:register(data.fpu_registers)
elseif kind == 'DEREF' then
ret = self:deref()
elseif kind == 'CONST' then
ret = self:const()
elseif kind == 'END' then
if self.s[self.i] ~= nil then
self:error('expected EOL; too many arguments')
end
return -- don't increment self.i past end of arguments
else
error('Internal Error: unknown kind, got '..tostring(kind))
end
self.i = self.i + 1
return ret
end
function Expander:expand(statements)
-- third pass: expand pseudo-instructions and register arguments
self.statements = {}
for i, s in ipairs(statements) do
self.s = s
self.fn = s.fn
self.line = s.line
if s.type:sub(1, 1) == '!' then
self:push(s)
else
local name = s.type
local h = data.instructions[name]
if h == nil then
error('Internal Error: unknown instruction')
end
if data.one_register_variants[name] then
self.i = 1
local a = self:register(data.all_registers)
local b = s[2]
if b == nil or b.tt ~= 'REG' then
insert(s, 2, self:token(a))
end
elseif data.two_register_variants[name] then
self.i = 1
local a = self:register(data.all_registers)
local b = self:register(data.all_registers)
local c = s[3]
if c == nil or c.tt ~= 'REG' then
insert(s, 2, self:token(a))
end
end
if overrides[name] then
self.i = 1
overrides[name](self, name)
self:pop('END')
else
self:push(s)
end
end
end
return self.statements
end
return Expander