diff options
Diffstat (limited to 'script/vm/library.lua')
-rw-r--r-- | script/vm/library.lua | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/script/vm/library.lua b/script/vm/library.lua new file mode 100644 index 00000000..018d69f3 --- /dev/null +++ b/script/vm/library.lua @@ -0,0 +1,112 @@ +local sourceMgr = require 'vm.source' + +local valueMgr +local functionMgr + +local CHILD_CACHE = {} +local VALUE_CACHE = {} +local Special = {} + +local buildLibValue +local buildLibChild + +function buildLibValue(lib) + if VALUE_CACHE[lib] then + return VALUE_CACHE[lib] + end + if not valueMgr then + valueMgr = require 'vm.value' + functionMgr = require 'vm.function' + end + local tp = lib.type + local value + if tp == 'table' then + value = valueMgr.create('table', sourceMgr.dummy()) + elseif tp == 'function' then + local dummySource = sourceMgr.dummy() + value = valueMgr.create('function', dummySource) + local func = functionMgr.create(dummySource) + value:setFunction(func) + if lib.args then + for _, arg in ipairs(lib.args) do + func:createLibArg(arg, sourceMgr.dummy()) + end + end + if lib.returns then + for i, rtn in ipairs(lib.returns) do + if rtn.type == '...' then + func:returnDots(i) + else + func:setReturn(i, buildLibValue(rtn)) + end + end + if lib.special == 'pairs' then + func:setReturn(1, Special['next']) + end + if lib.special == 'ipairs' then + func:setReturn(1, Special['@ipairs']) + end + end + elseif tp == 'string' then + value = valueMgr.create('string', sourceMgr.dummy()) + elseif tp == 'boolean' then + value = valueMgr.create('boolean', sourceMgr.dummy()) + elseif tp == 'number' then + value = valueMgr.create('number', sourceMgr.dummy()) + elseif tp == 'integer' then + value = valueMgr.create('integer', sourceMgr.dummy()) + elseif tp == 'nil' then + value = valueMgr.create('nil', sourceMgr.dummy()) + else + value = valueMgr.create(tp or 'any', sourceMgr.dummy()) + end + value:setLib(lib) + VALUE_CACHE[lib] = value + + if lib.child then + for fName, fLib in pairs(lib.child) do + local fValue = buildLibValue(fLib) + value:rawSet(fName, fValue) + value:addInfo('set child', sourceMgr.dummy(), fName, fValue) + end + end + + if lib.special == 'next' then + Special['next'] = value + end + if lib.special == '@ipairs' then + Special['@ipairs'] = value + return nil + end + + return value +end + +function buildLibChild(lib) + if not valueMgr then + valueMgr = require 'vm.value' + functionMgr = require 'vm.function' + end + if CHILD_CACHE[lib] then + return CHILD_CACHE[lib] + end + local child = {} + for fName, fLib in pairs(lib.child) do + local fValue = buildLibValue(fLib) + child[fName] = fValue + end + CHILD_CACHE[lib] = child + return child +end + +local function clearCache() + CHILD_CACHE = {} + VALUE_CACHE = {} +end + +return { + value = buildLibValue, + child = buildLibChild, + clear = clearCache, + special = Special, +} |