mirror of
https://github.com/notwa/lips
synced 2024-11-14 10:09:03 -08:00
implement basic specials; more refactoring
This commit is contained in:
parent
195236a52c
commit
07c68b6229
8 changed files with 171 additions and 131 deletions
|
@ -127,20 +127,20 @@ function Dumper:add_directive(fn, line, name, a, b)
|
|||
end
|
||||
end
|
||||
|
||||
function Dumper:desym(tok)
|
||||
if type(tok[2]) == 'number' then
|
||||
return tok[2]
|
||||
elseif tok[1] == 'REG' then
|
||||
assert(data.all_registers[tok[2]], 'Internal Error: unknown register')
|
||||
return data.registers[tok[2]] or data.fpu_registers[tok[2]] or data.sys_registers[tok[2]]
|
||||
elseif tok[1] == 'LABELSYM' then
|
||||
local label = self.labels[tok[2]]
|
||||
function Dumper:desym(t)
|
||||
if type(t.tok) == 'number' then
|
||||
return t.tok
|
||||
elseif t.tt == 'REG' then
|
||||
assert(data.all_registers[t.tok], 'Internal Error: unknown register')
|
||||
return data.registers[t.tok] or data.fpu_registers[t.tok] or data.sys_registers[t.tok]
|
||||
elseif t.tt == 'LABELSYM' then
|
||||
local label = self.labels[t.tok]
|
||||
if label == nil then
|
||||
self:error('undefined label')
|
||||
end
|
||||
return label
|
||||
elseif tok[1] == 'LABELREL' then
|
||||
local label = self.labels[tok[2]]
|
||||
elseif t.tt == 'LABELREL' then
|
||||
local label = self.labels[t.tok]
|
||||
if label == nil then
|
||||
self:error('undefined label')
|
||||
end
|
||||
|
@ -155,31 +155,30 @@ function Dumper:desym(tok)
|
|||
error('Internal Error: failed to desym')
|
||||
end
|
||||
|
||||
function Dumper:toval(tok)
|
||||
assert(type(tok) == 'table', 'Internal Error: invalid value')
|
||||
assert(#tok == 2, 'Internal Error: invalid token')
|
||||
function Dumper:toval(t)
|
||||
assert(type(t) == 'table', 'Internal Error: invalid value')
|
||||
|
||||
local val = self:desym(tok)
|
||||
local val = self:desym(t)
|
||||
|
||||
if tok.index then
|
||||
if t.index then
|
||||
val = val % 0x80000000
|
||||
val = floor(val/4)
|
||||
end
|
||||
if tok.negate then
|
||||
if t.negate then
|
||||
val = -val
|
||||
end
|
||||
if tok.negate or tok.signed then
|
||||
if t.negate or t.signed then
|
||||
if val >= 0x10000 or val < -0x8000 then
|
||||
self:error('value out of range')
|
||||
end
|
||||
val = val % 0x10000
|
||||
end
|
||||
|
||||
if tok.portion == 'upper' then
|
||||
if t.portion == 'upper' then
|
||||
val = bitrange(val, 16, 31)
|
||||
elseif tok.portion == 'lower' then
|
||||
elseif t.portion == 'lower' then
|
||||
val = bitrange(val, 0, 15)
|
||||
elseif tok.portion == 'upperoff' then
|
||||
elseif t.portion == 'upperoff' then
|
||||
local upper = bitrange(val, 16, 31)
|
||||
local lower = bitrange(val, 0, 15)
|
||||
if lower >= 0x8000 then
|
||||
|
@ -202,8 +201,8 @@ function Dumper:validate(n, bits)
|
|||
end
|
||||
end
|
||||
|
||||
function Dumper:valvar(tok, bits)
|
||||
local val = self:toval(tok)
|
||||
function Dumper:valvar(t, bits)
|
||||
local val = self:toval(t)
|
||||
self:validate(val, bits)
|
||||
return val
|
||||
end
|
||||
|
|
|
@ -3,6 +3,7 @@ local insert = table.insert
|
|||
|
||||
local data = require "lips.data"
|
||||
local util = require "lips.util"
|
||||
local Token = require "lips.Token"
|
||||
|
||||
local arg_types = {
|
||||
NUM = true,
|
||||
|
@ -19,14 +20,25 @@ function Muncher:error(msg)
|
|||
error(format('%s:%d: Error: %s', self.fn, self.line, msg), 2)
|
||||
end
|
||||
|
||||
function Muncher:token(t, val)
|
||||
-- note: call Token directly if you want to specify fn and line manually
|
||||
if type(t) == 'table' then
|
||||
t.fn = self.fn
|
||||
t.line = self.line
|
||||
return Token(t)
|
||||
else
|
||||
return Token(self.fn, self.line, t, val)
|
||||
end
|
||||
end
|
||||
|
||||
function Muncher:advance()
|
||||
self.i = self.i + 1
|
||||
local t = self.tokens[self.i]
|
||||
self.tt = t.tt
|
||||
self.tok = t.tok
|
||||
self.fn = t.fn
|
||||
self.line = t.line
|
||||
return t
|
||||
self.t = self.tokens[self.i]
|
||||
self.tt = self.t.tt
|
||||
self.tok = self.t.tok
|
||||
self.fn = self.t.fn
|
||||
self.line = self.t.line
|
||||
return self.t
|
||||
end
|
||||
|
||||
function Muncher:is_EOL()
|
||||
|
@ -52,31 +64,31 @@ function Muncher:number()
|
|||
if self.tt ~= 'NUM' then
|
||||
self:error('expected number')
|
||||
end
|
||||
local value = self.tok
|
||||
local t = self.t
|
||||
self:advance()
|
||||
return value
|
||||
return self:token(t)
|
||||
end
|
||||
|
||||
function Muncher:string()
|
||||
if self.tt ~= 'STRING' then
|
||||
self:error('expected string')
|
||||
end
|
||||
local value = self.tok
|
||||
local t = self.t
|
||||
self:advance()
|
||||
return value
|
||||
return self:token(t)
|
||||
end
|
||||
|
||||
function Muncher:register(t)
|
||||
t = t or data.registers
|
||||
function Muncher:register(registers)
|
||||
registers = registers or data.registers
|
||||
if self.tt ~= 'REG' then
|
||||
self:error('expected register')
|
||||
end
|
||||
local reg = self.tok
|
||||
if not t[reg] then
|
||||
local t = self.t
|
||||
if not registers[t.tok] then
|
||||
self:error('wrong type of register')
|
||||
end
|
||||
self:advance()
|
||||
return reg
|
||||
return self:token(t)
|
||||
end
|
||||
|
||||
function Muncher:deref()
|
||||
|
@ -87,13 +99,13 @@ function Muncher:deref()
|
|||
if self.tt ~= 'REG' then
|
||||
self:error('expected register to dereference')
|
||||
end
|
||||
local reg = self.tok
|
||||
local t = self.t
|
||||
self:advance()
|
||||
if self.tt ~= 'CLOSE' then
|
||||
self:error('expected closing parenthesis for dereferencing')
|
||||
end
|
||||
self:advance()
|
||||
return reg
|
||||
return self:token(t)
|
||||
end
|
||||
|
||||
function Muncher:const(relative, no_label)
|
||||
|
@ -106,9 +118,9 @@ function Muncher:const(relative, no_label)
|
|||
if relative and self.tt == 'LABELSYM' then
|
||||
self.tt = 'LABELREL'
|
||||
end
|
||||
local t = {self.tt, self.tok}
|
||||
local t = self.t
|
||||
self:advance()
|
||||
return t
|
||||
return self:token(t)
|
||||
end
|
||||
|
||||
function Muncher:special()
|
||||
|
@ -133,7 +145,6 @@ function Muncher:special()
|
|||
insert(args, arg)
|
||||
elseif self.tt == 'CLOSE' then
|
||||
insert(args, arg)
|
||||
self:advance()
|
||||
break
|
||||
else
|
||||
self:error('unexpected token in argument list')
|
||||
|
|
|
@ -3,14 +3,12 @@ local insert = table.insert
|
|||
local data = require "lips.data"
|
||||
local util = require "lips.util"
|
||||
local overrides = require "lips.overrides"
|
||||
local Token = require "lips.Token"
|
||||
local Lexer = require "lips.Lexer"
|
||||
local Dumper = require "lips.Dumper"
|
||||
local Muncher = require "lips.Muncher"
|
||||
local Preproc = require "lips.Preproc"
|
||||
|
||||
local construct = util.construct
|
||||
local withflag = util.withflag
|
||||
|
||||
local Parser = util.Class(Muncher)
|
||||
function Parser:init(writer, fn, options)
|
||||
self.fn = fn or '(string)'
|
||||
|
@ -26,7 +24,7 @@ function Parser:directive()
|
|||
self.dumper:add_directive(self.fn, self.line, ...)
|
||||
end
|
||||
if name == 'ORG' then
|
||||
add(name, self:number())
|
||||
add(name, self:number().tok)
|
||||
elseif name == 'ALIGN' or name == 'SKIP' then
|
||||
if self:is_EOL() and name == 'ALIGN' then
|
||||
add(name, 0)
|
||||
|
@ -36,24 +34,24 @@ function Parser:directive()
|
|||
add(name, size)
|
||||
else
|
||||
self:optional_comma()
|
||||
add(name, size, self:number())
|
||||
add(name, size, self:number().tok)
|
||||
end
|
||||
self:expect_EOL()
|
||||
end
|
||||
elseif name == 'BYTE' or name == 'HALFWORD' then
|
||||
add(name, self:number())
|
||||
add(name, self:number().tok)
|
||||
while not self:is_EOL() do
|
||||
self:advance()
|
||||
self:optional_comma()
|
||||
add(name, self:number())
|
||||
add(name, self:number().tok)
|
||||
end
|
||||
self:expect_EOL()
|
||||
elseif name == 'WORD' then -- allow labels in word directives
|
||||
add(name, self:const()[2])
|
||||
add(name, self:const().tok)
|
||||
while not self:is_EOL() do
|
||||
self:advance()
|
||||
self:optional_comma()
|
||||
add(name, self:const()[2])
|
||||
add(name, self:const().tok)
|
||||
end
|
||||
self:expect_EOL()
|
||||
elseif name == 'INC' then
|
||||
|
@ -100,17 +98,17 @@ function Parser:format_in(informat)
|
|||
elseif c == 'Z' and not args.rt then
|
||||
args.rt = self:register(data.sys_registers)
|
||||
elseif c == 'o' and not args.offset then
|
||||
args.offset = withflag(self:const(), 'signed')
|
||||
args.offset = Token(self:const()):set('signed')
|
||||
elseif c == 'r' and not args.offset then
|
||||
args.offset = withflag(self:const('relative'), 'signed')
|
||||
args.offset = Token(self:const('relative')):set('signed')
|
||||
elseif c == 'i' and not args.immediate then
|
||||
args.immediate = self:const(nil, 'no label')
|
||||
elseif c == 'I' and not args.index then
|
||||
args.index = withflag(self:const(), 'index')
|
||||
args.index = Token(self:const()):set('index')
|
||||
elseif c == 'k' and not args.immediate then
|
||||
args.immediate = withflag(self:const(nil, 'no label'), 'negate')
|
||||
args.immediate = Token(self:const(nil, 'no label')):set('negate')
|
||||
elseif c == 'K' and not args.immediate then
|
||||
args.immediate = withflag(self:const(nil, 'no label'), 'signed')
|
||||
args.immediate = Token(self:const(nil, 'no label')):set('signed')
|
||||
elseif c == 'b' and not args.base then
|
||||
args.base = self:deref()
|
||||
else
|
||||
|
@ -133,31 +131,31 @@ function Parser:format_out_raw(outformat, first, args, const, formatconst)
|
|||
for i=1,#outformat do
|
||||
local c = outformat:sub(i, i)
|
||||
if c == 'd' then
|
||||
out[#out+1] = construct(args.rd)
|
||||
out[#out+1] = self:token(args.rd)
|
||||
elseif c == 's' then
|
||||
out[#out+1] = construct(args.rs)
|
||||
out[#out+1] = self:token(args.rs)
|
||||
elseif c == 't' then
|
||||
out[#out+1] = construct(args.rt)
|
||||
out[#out+1] = self:token(args.rt)
|
||||
elseif c == 'D' then
|
||||
out[#out+1] = construct(args.fd)
|
||||
out[#out+1] = self:token(args.fd)
|
||||
elseif c == 'S' then
|
||||
out[#out+1] = construct(args.fs)
|
||||
out[#out+1] = self:token(args.fs)
|
||||
elseif c == 'T' then
|
||||
out[#out+1] = construct(args.ft)
|
||||
out[#out+1] = self:token(args.ft)
|
||||
elseif c == 'o' then
|
||||
out[#out+1] = construct(args.offset)
|
||||
out[#out+1] = self:token(args.offset)
|
||||
elseif c == 'i' then
|
||||
out[#out+1] = construct(args.immediate)
|
||||
out[#out+1] = self:token(args.immediate)
|
||||
elseif c == 'I' then
|
||||
out[#out+1] = construct(args.index)
|
||||
out[#out+1] = self:token(args.index)
|
||||
elseif c == 'b' then
|
||||
out[#out+1] = construct(args.base)
|
||||
out[#out+1] = self:token(args.base)
|
||||
elseif c == '0' then
|
||||
out[#out+1] = construct(0)
|
||||
out[#out+1] = self:token(0)
|
||||
elseif c == 'C' then
|
||||
out[#out+1] = construct(const)
|
||||
out[#out+1] = self:token(const)
|
||||
elseif c == 'F' then
|
||||
out[#out+1] = construct(formatconst)
|
||||
out[#out+1] = self:token(formatconst)
|
||||
end
|
||||
end
|
||||
local f = lookup[#outformat]
|
||||
|
@ -193,9 +191,12 @@ function Parser:instruction()
|
|||
local lui_args = {}
|
||||
local addu_args = {}
|
||||
local o = self:const()
|
||||
args.offset = withflag({o[1], o[2]}, 'portion', 'lower')
|
||||
if o[1] == 'LABELSYM' or o[2] >= 0x80000000 then
|
||||
lui_args.immediate = withflag({o[1], o[2]}, 'portion', 'upperoff')
|
||||
args.offset = self:token(o)
|
||||
if not o.portion then
|
||||
args.offset:set('portion', 'lower')
|
||||
end
|
||||
if not o.portion and (o.tt == 'LABELSYM' or o.tok >= 0x80000000) then
|
||||
lui_args.immediate = Token(o):set('portion', 'upperoff')
|
||||
lui_args.rt = 'AT'
|
||||
self:format_out(lui, lui_args)
|
||||
if not self:is_EOL() then
|
||||
|
@ -236,11 +237,7 @@ function Parser:tokenize(asm)
|
|||
end
|
||||
assert(a, 'Internal Error: missing token')
|
||||
|
||||
local t = {}
|
||||
t.tt = a
|
||||
t.tok = b
|
||||
t.fn = c
|
||||
t.line = d
|
||||
local t = Token(c, d, a, b)
|
||||
insert(tokens, t)
|
||||
|
||||
if t.tt == 'EOF' and t.fn == self.main_fn then
|
||||
|
|
|
@ -3,6 +3,7 @@ local insert = table.insert
|
|||
local data = require "lips.data"
|
||||
local util = require "lips.util"
|
||||
local Muncher = require "lips.Muncher"
|
||||
local Token = require "lips.Token"
|
||||
|
||||
local Preproc = util.Class(Muncher)
|
||||
function Preproc:init(options)
|
||||
|
@ -35,7 +36,7 @@ function Preproc:process(tokens)
|
|||
if tok == nil then
|
||||
self:error('undefined define') -- uhhh nice wording
|
||||
end
|
||||
insert(new_tokens, {fn=t.fn, line=t.line, tt=tt, tok=tok})
|
||||
insert(new_tokens, self:token(tt, tok))
|
||||
elseif t.tt == 'RELLABEL' then
|
||||
if t.tok == '+' then
|
||||
insert(plus_labels, #new_tokens + 1)
|
||||
|
@ -99,8 +100,6 @@ function Preproc:process(tokens)
|
|||
self.i = 0
|
||||
while self.i < #self.tokens do
|
||||
local t = self:advance()
|
||||
self.fn = t.fn
|
||||
self.line = t.line
|
||||
if t.tt == 'SPECIAL' then
|
||||
local name, args = self:special()
|
||||
-- TODO: split to its own file, not unlike overrides.lua
|
||||
|
@ -108,22 +107,19 @@ function Preproc:process(tokens)
|
|||
if #args ~= 1 then
|
||||
self:error('%hi expected exactly one argument')
|
||||
end
|
||||
--local tnew = {fn=t.fn, line=t.line, tt='UPPEROFF', tok=args[1]}
|
||||
self:error('unimplemented special')
|
||||
local tnew = self:token(args[1]):set('portion', 'upperoff')
|
||||
insert(new_tokens, tnew)
|
||||
elseif name == 'up' then
|
||||
if #args ~= 1 then
|
||||
self:error('%up expected exactly one argument')
|
||||
end
|
||||
--local tnew = {fn=t.fn, line=t.line, tt='UPPER', tok=args[1]}
|
||||
self:error('unimplemented special')
|
||||
local tnew = self:token(args[1]):set('portion', 'upper')
|
||||
insert(new_tokens, tnew)
|
||||
elseif name == 'lo' then
|
||||
if #args ~= 1 then
|
||||
self:error('%lo expected exactly one argument')
|
||||
end
|
||||
self:error('unimplemented special')
|
||||
--local tnew = {fn=t.fn, line=t.line, tt='LOWER', tok=args[1]}
|
||||
local tnew = self:token(args[1]):set('portion', 'lower')
|
||||
insert(new_tokens, tnew)
|
||||
else
|
||||
self:error('unknown special')
|
||||
|
|
60
lips/Token.lua
Normal file
60
lips/Token.lua
Normal file
|
@ -0,0 +1,60 @@
|
|||
local util = require "lips.util"
|
||||
|
||||
local Token = util.Class()
|
||||
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
|
||||
if not self.fn then
|
||||
error('Internal Error: tokens require a filename', 3)
|
||||
end
|
||||
if not self.line then
|
||||
error('Internal Error: tokens require a line number', 3)
|
||||
end
|
||||
if not self.tt then
|
||||
error('Internal Error: token is missing a type', 3)
|
||||
end
|
||||
if not self.tok then
|
||||
error('Internal Error: token is missing a value', 3)
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
function Token:set(key, value)
|
||||
if value == nil then
|
||||
value = true
|
||||
end
|
||||
self[key] = value
|
||||
return self
|
||||
end
|
||||
|
||||
return Token
|
|
@ -4,7 +4,6 @@ local data = require "lips.data"
|
|||
local util = require "lips.util"
|
||||
|
||||
local instructions = data.instructions
|
||||
local withflag = util.withflag
|
||||
|
||||
local overrides = {}
|
||||
-- note: "self" is an instance of Parser
|
||||
|
@ -20,26 +19,33 @@ function overrides.LI(self, name)
|
|||
|
||||
-- for us, this is just semantics. for a "real" assembler,
|
||||
-- LA could add appropriate RELO LUI/ADDIU directives.
|
||||
if im[1] == 'LABELSYM' then
|
||||
if im.tt == 'LABELSYM' then
|
||||
self:error('use LA for labels')
|
||||
end
|
||||
|
||||
im[2] = im[2] % 0x100000000
|
||||
if im[2] >= 0x10000 and im[2] <= 0xFFFF8000 then
|
||||
if im.portion then
|
||||
args.rs = 'R0'
|
||||
args.immediate = im
|
||||
self:format_out(addiu, args)
|
||||
return
|
||||
end
|
||||
|
||||
im.tok = im.tok % 0x100000000
|
||||
if im.tok >= 0x10000 and im.tok <= 0xFFFF8000 then
|
||||
args.rs = args.rt
|
||||
args.immediate = withflag(im, 'portion', 'upper')
|
||||
args.immediate = self:token(im):set('portion', 'upper')
|
||||
self:format_out(lui, args)
|
||||
if im[2] % 0x10000 ~= 0 then
|
||||
args.immediate = withflag(im, 'portion', 'lower')
|
||||
if im.tok % 0x10000 ~= 0 then
|
||||
args.immediate = self:token(im):set('portion', 'lower')
|
||||
self:format_out(ori, args)
|
||||
end
|
||||
elseif im[2] >= 0x8000 and im[2] < 0x10000 then
|
||||
elseif im.tok >= 0x8000 and im.tok < 0x10000 then
|
||||
args.rs = 'R0'
|
||||
args.immediate = withflag(im, 'portion', 'lower')
|
||||
args.immediate = self:token(im):set('portion', 'lower')
|
||||
self:format_out(ori, args)
|
||||
else
|
||||
args.rs = 'R0'
|
||||
args.immediate = withflag(im, 'portion', 'lower')
|
||||
args.immediate = self:token(im):set('portion', 'lower')
|
||||
self:format_out(addiu, args)
|
||||
end
|
||||
end
|
||||
|
@ -53,9 +59,9 @@ function overrides.LA(self, name)
|
|||
local im = self:const()
|
||||
|
||||
args.rs = args.rt
|
||||
args.immediate = withflag(im, 'portion', 'upperoff')
|
||||
args.immediate = self:token(im):set('portion', 'upperoff')
|
||||
self:format_out(lui, args)
|
||||
args.immediate = withflag(im, 'portion', 'lower')
|
||||
args.immediate = self:token(im):set('portion', 'lower')
|
||||
self:format_out(addiu, args)
|
||||
end
|
||||
|
||||
|
@ -87,7 +93,7 @@ function overrides.PUSH(self, name)
|
|||
if name == 'PUSH' then
|
||||
args.rt = 'SP'
|
||||
args.rs = 'SP'
|
||||
args.immediate = withflag(#stack*4, 'negate')
|
||||
args.immediate = self:token(#stack*4):set('negate')
|
||||
self:format_out(addi, args)
|
||||
end
|
||||
args.base = 'SP'
|
||||
|
@ -241,7 +247,7 @@ function overrides.BEQI(self, name)
|
|||
self:optional_comma()
|
||||
args.immediate = self:const()
|
||||
self:optional_comma()
|
||||
args.offset = withflag(self:const('relative'), 'signed')
|
||||
args.offset = self:token(self:const('relative')):set('signed')
|
||||
|
||||
if reg == 'AT' then
|
||||
self:error('register cannot be AT in this pseudo-instruction')
|
||||
|
@ -264,7 +270,7 @@ function overrides.BLTI(self, name)
|
|||
self:optional_comma()
|
||||
args.immediate = self:const()
|
||||
self:optional_comma()
|
||||
args.offset = withflag(self:const('relative'), 'signed')
|
||||
args.offset = self:token(self:const('relative')):set('signed')
|
||||
|
||||
if args.rs == 'AT' then
|
||||
self:error('register cannot be AT in this pseudo-instruction')
|
||||
|
@ -290,7 +296,7 @@ function overrides.BLEI(self, name)
|
|||
self:optional_comma()
|
||||
args.immediate = self:const()
|
||||
self:optional_comma()
|
||||
local offset = withflag(self:const('relative'), 'signed')
|
||||
local offset = self:token(self:const('relative')):set('signed')
|
||||
|
||||
if reg == 'AT' then
|
||||
self:error('register cannot be AT in this pseudo-instruction')
|
||||
|
|
|
@ -16,33 +16,6 @@ local function Class(inherit)
|
|||
return setmetatable(class, mt_class)
|
||||
end
|
||||
|
||||
local function construct(t)
|
||||
if type(t) == 'table' then
|
||||
return t
|
||||
elseif type(t) == 'string' then
|
||||
return {'REG', t}
|
||||
elseif type(t) == 'number' then
|
||||
return {'NUM', t}
|
||||
else
|
||||
error('Internal Error: unknown type to construct')
|
||||
end
|
||||
end
|
||||
|
||||
local function withflag(t, key, value)
|
||||
if type(t) == 'table' then
|
||||
t = {t[1], t[2]}
|
||||
else
|
||||
t = construct(t)
|
||||
end
|
||||
if value == nil then
|
||||
value = true
|
||||
end
|
||||
if key ~= nil then
|
||||
t[key] = value
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
local function readfile(fn)
|
||||
local f = open(fn, 'r')
|
||||
if not f then
|
||||
|
@ -59,8 +32,6 @@ end
|
|||
|
||||
return {
|
||||
Class = Class,
|
||||
construct = construct,
|
||||
withflag = withflag,
|
||||
readfile = readfile,
|
||||
bitrange = bitrange,
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue