1
0
Fork 0
mirror of https://github.com/notwa/mm synced 2024-11-05 06:39:02 -08:00

update lips

This commit is contained in:
Connor Olding 2016-11-10 18:03:40 -08:00
parent 977130b3d4
commit bef45dc1cd
4 changed files with 68 additions and 2 deletions

View file

@ -243,6 +243,10 @@ function Dumper:load(statements)
self.fn = s.fn self.fn = s.fn
self.line = s.line self.line = s.line
if s.type:sub(1, 1) == '!' then if s.type:sub(1, 1) == '!' then
if s[1] and s[1].tt == 'EXPR' then
self:error('unevaluated expression')
end
if s.type == '!LABEL' then if s.type == '!LABEL' then
self.labels[s[1].tok] = self:pc() self.labels[s[1].tok] = self:pc()
elseif s.type == '!DATA' then elseif s.type == '!DATA' then
@ -255,6 +259,7 @@ function Dumper:load(statements)
elseif s.type == '!BASE' then elseif s.type == '!BASE' then
self.base = s[1].tok self.base = s[1].tok
insert(new_statements, s) insert(new_statements, s)
elseif s.type == '!PUSH' or s.type == '!POP' then elseif s.type == '!PUSH' or s.type == '!POP' then
local thistype = s.type:sub(2):lower() local thistype = s.type:sub(2):lower()
for i, t in ipairs(s) do for i, t in ipairs(s) do
@ -300,6 +305,7 @@ function Dumper:load(statements)
insert(new_statements, s) insert(new_statements, s)
end end
end end
elseif s.type == '!ALIGN' or s.type == '!SKIP' then elseif s.type == '!ALIGN' or s.type == '!SKIP' then
local length, content local length, content
if s.type == '!ALIGN' then if s.type == '!ALIGN' then
@ -332,6 +338,7 @@ function Dumper:load(statements)
else else
-- length is 0, noop -- length is 0, noop
end end
else else
error('Internal Error: unknown statement, got '..s.type) error('Internal Error: unknown statement, got '..s.type)
end end

View file

@ -329,6 +329,38 @@ function Lexer:lex_include_binary(_yield)
end end
end end
function Lexer:lex_expression(yield)
if self.chr ~= '(' then
self:error('expected opening parenthesis for expression')
end
self:nextc()
local expr = ""
local depth = 1
while true do
if self.chr == '\n' then
self:error('unexpected newline; incomplete expression')
elseif self.ord == self.EOF then
self:nextc()
self:error('unexpected EOF; incomplete expression')
elseif self.chr == '(' then
depth = depth + 1
self:nextc()
expr = expr..'('
elseif self.chr == ')' then
depth = depth - 1
self:nextc()
if depth == 0 then break end
expr = expr..')'
else
expr = expr..self.chr
self:nextc()
end
end
yield('EXPR', expr)
end
function Lexer:lex(_yield) function Lexer:lex(_yield)
local function yield(tt, tok) local function yield(tt, tok)
return _yield(tt, tok, self.fn, self.line) return _yield(tt, tok, self.fn, self.line)
@ -410,6 +442,8 @@ function Lexer:lex(_yield)
end end
elseif self.chr:find('[01]') then elseif self.chr:find('[01]') then
yield('NUM', self:read_binary()) yield('NUM', self:read_binary())
elseif self.chr == '(' then
self:lex_expression(yield)
else else
self:error('unknown % syntax') self:error('unknown % syntax')
end end

View file

@ -115,7 +115,13 @@ function Muncher:deref()
end end
function Muncher:const(relative, no_label) function Muncher:const(relative, no_label)
if self.tt ~= 'NUM' and self.tt ~= 'VARSYM' and self.tt ~= 'LABELSYM' then local good = {
NUM = true,
EXPR = true,
VARSYM = true,
LABELSYM = true,
}
if not good[self.tt] then
self:error('expected constant', self.tt) self:error('expected constant', self.tt)
end end
if no_label and self.tt == 'LABELSYM' then if no_label and self.tt == 'LABELSYM' then

View file

@ -5,6 +5,7 @@ local data = require(path.."data")
local overrides = require(path.."overrides") local overrides = require(path.."overrides")
local Statement = require(path.."Statement") local Statement = require(path.."Statement")
local Reader = require(path.."Reader") local Reader = require(path.."Reader")
local Expression = require(path.."Expression")
local abs = math.abs local abs = math.abs
@ -172,6 +173,24 @@ function Preproc:process(statements)
end end
end end
-- third pass: evaluate constant expressions
for i=1, #new_statements do
local s = new_statements[i]
self.fn = s.fn
self.line = s.line
for j, t in ipairs(s) do
if t.tt == 'EXPR' then
local expr = Expression()
local result, err = expr:eval(t.tok)
if err then
self:error('failed to evaulate ('..t.tok..')', err)
end
t.tt = 'NUM'
t.tok = result
end
end
end
return new_statements return new_statements
end end
@ -214,7 +233,7 @@ function Preproc:pop(kind)
end end
function Preproc:expand(statements) function Preproc:expand(statements)
-- third pass: expand pseudo-instructions and register arguments -- fourth pass: expand pseudo-instructions and register arguments
self.statements = {} self.statements = {}
for i=1, #statements do for i=1, #statements do
local s = statements[i] local s = statements[i]