mirror of
https://github.com/notwa/mm
synced 2024-11-05 00:39:02 -08:00
111 lines
2.6 KiB
Lua
111 lines
2.6 KiB
Lua
local floor = math.floor
|
|
|
|
local path = string.gsub(..., "[^.]+$", "")
|
|
local Base = require(path.."Base")
|
|
local util = require(path.."util")
|
|
|
|
local bitrange = util.bitrange
|
|
|
|
local Token = Base:extend()
|
|
function Token:init(...)
|
|
local args = {...}
|
|
if #args == 1 then
|
|
local t = args[1]
|
|
if type(t) == 'table' then
|
|
for k, v in pairs(t) do
|
|
self[k] = v
|
|
end
|
|
end
|
|
elseif #args == 3 then
|
|
self.fn = args[1]
|
|
self.line = args[2]
|
|
local t = args[3]
|
|
if type(t) == 'table' then
|
|
self.tt = t[1]
|
|
self.tok = t[2]
|
|
elseif type(t) == 'string' then
|
|
self.tt = 'REG'
|
|
self.tok = t
|
|
elseif type(t) == 'number' then
|
|
self.tt = 'NUM'
|
|
self.tok = t
|
|
else
|
|
error('Internal Error: unknown type to construct', 3)
|
|
end
|
|
elseif #args == 4 then
|
|
self.fn = args[1]
|
|
self.line = args[2]
|
|
self.tt = args[3]
|
|
self.tok = args[4]
|
|
else
|
|
error('Internal Error: init takes 1, 3 or 4 arguments', 3)
|
|
end
|
|
self:validate(1)
|
|
return self
|
|
end
|
|
|
|
function Token:validate(n)
|
|
n = (n or 0) + 3 -- depth for error message
|
|
if not self.fn then
|
|
error('Internal Error: tokens require a filename', n)
|
|
end
|
|
if not self.line then
|
|
error('Internal Error: tokens require a line number', n)
|
|
end
|
|
if not self.tt then
|
|
error('Internal Error: token is missing a type', n)
|
|
end
|
|
if not self.tok then
|
|
error('Internal Error: token is missing a value', n)
|
|
end
|
|
end
|
|
|
|
function Token:set(key, value)
|
|
if value == nil then
|
|
value = true
|
|
end
|
|
self[key] = value
|
|
return self
|
|
end
|
|
|
|
function Token:compute(n)
|
|
local n = n or self.tok
|
|
assert(n or self.tt == 'NUM', 'Internal Error: cannot compute a non-number token')
|
|
|
|
if self.offset then
|
|
n = n + self.offset
|
|
end
|
|
|
|
if self.index then
|
|
n = n % 0x80000000
|
|
n = floor(n/4)
|
|
end
|
|
if self.negate then
|
|
n = -n
|
|
end
|
|
|
|
if self.portion == 'upper' then
|
|
n = bitrange(n, 16, 31)
|
|
elseif self.portion == 'lower' then
|
|
n = bitrange(n, 0, 15)
|
|
elseif self.portion == 'upperoff' then
|
|
local upper = bitrange(n, 16, 31)
|
|
local lower = bitrange(n, 0, 15)
|
|
if lower >= 0x8000 then
|
|
-- accommodate for offsets being signed
|
|
upper = (upper + 1) % 0x10000
|
|
end
|
|
n = upper
|
|
end
|
|
|
|
if self.signed then
|
|
if n >= 0x10000 or n < -0x8000 then
|
|
return n, 'value out of range'
|
|
end
|
|
n = n % 0x10000
|
|
end
|
|
|
|
return n
|
|
end
|
|
|
|
return Token
|