summaryrefslogtreecommitdiff
path: root/script/vm/library.lua
diff options
context:
space:
mode:
Diffstat (limited to 'script/vm/library.lua')
-rw-r--r--script/vm/library.lua112
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,
+}