diff --git a/lips/Collector.lua b/lips/Collector.lua index a4ce389..34da262 100644 --- a/lips/Collector.lua +++ b/lips/Collector.lua @@ -160,8 +160,9 @@ function Collector:instruction() elseif self.tt == 'UNARY' then local peek = self.tokens[self.i + 1] if peek.tt == 'VARSYM' then + local negate = t.tok == -1 t = self:advance() - t = Token(t):set('negate') + t = Token(t):set('negate', negate) insert(s, t) self:advance() elseif peek.tt == 'EOL' or peek.tt == 'SEP' then diff --git a/lips/Dumper.lua b/lips/Dumper.lua index dde559b..8163365 100644 --- a/lips/Dumper.lua +++ b/lips/Dumper.lua @@ -73,47 +73,6 @@ function Dumper:desym(t) error('Internal Error: failed to desym') end -function Dumper:toval(t) - if type(t) == 'number' then - return t - end - - assert(type(t) == 'table', 'Internal Error: invalid value') - - local val = self:desym(t) - - if t.index then - val = val % 0x80000000 - val = floor(val/4) - end - if t.negate then - val = -val - end - - if t.portion == 'upper' then - val = bitrange(val, 16, 31) - elseif t.portion == 'lower' then - val = bitrange(val, 0, 15) - elseif t.portion == 'upperoff' then - local upper = bitrange(val, 16, 31) - local lower = bitrange(val, 0, 15) - if lower >= 0x8000 then - -- accommodate for offsets being signed - upper = (upper + 1) % 0x10000 - end - val = upper - end - - if t.negate or t.signed then - if val >= 0x10000 or val < -0x8000 then - self:error('value out of range', val) - end - val = val % 0x10000 - end - - return val -end - function Dumper:validate(n, bits) local max = 2^bits if n == nil then @@ -126,7 +85,16 @@ function Dumper:validate(n, bits) end function Dumper:valvar(t, bits) - local val = self:toval(t) + local val = t + local err + if type(val) ~= 'number' then + t.tok = self:desym(t) + t.tt = 'NUM' + val, err = t:compute() + if err then + self:error(err, val) + end + end return self:validate(val, bits) end diff --git a/lips/Token.lua b/lips/Token.lua index a3ccc4a..4b94a56 100644 --- a/lips/Token.lua +++ b/lips/Token.lua @@ -1,5 +1,10 @@ +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(...) @@ -63,4 +68,39 @@ function Token:set(key, value) return self end +function Token:compute() + assert(self.tt == 'NUM', 'Internal Error: cannot compute a non-number token') + local n = self.tok + 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.negate or 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 diff --git a/lips/overrides.lua b/lips/overrides.lua index e7ac500..d6adf32 100644 --- a/lips/overrides.lua +++ b/lips/overrides.lua @@ -16,7 +16,11 @@ local function tob_override(self, name) else -- NUM or LABELSYM local o = self:pop('CONST') if self:peek('NUM') then - o:set('offset', self:pop('CONST').tok) + local temp, err = self:pop('CONST'):compute() + if err then + self:error(err, temp) + end + o:set('offset', temp) end offset = self:token(o) if not o.portion then