mirror of
https://github.com/notwa/mm
synced 2024-11-05 06:39:02 -08:00
98 lines
2.7 KiB
Lua
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
|