diff options
Diffstat (limited to 'server-beta/src/parser/compile.lua')
-rw-r--r-- | server-beta/src/parser/compile.lua | 549 |
1 files changed, 0 insertions, 549 deletions
diff --git a/server-beta/src/parser/compile.lua b/server-beta/src/parser/compile.lua deleted file mode 100644 index bcd9ecc8..00000000 --- a/server-beta/src/parser/compile.lua +++ /dev/null @@ -1,549 +0,0 @@ -local guide = require 'parser.guide' -local type = type - -local specials = { - ['_G'] = true, - ['rawset'] = true, - ['rawget'] = true, - ['setmetatable'] = true, - ['require'] = true, - ['dofile'] = true, - ['loadfile'] = true, - ['pcall'] = true, - ['xpcall'] = true, -} - -_ENV = nil - -local LocalLimit = 200 -local pushError, Compile, CompileBlock, Block, GoToTag, ENVMode, Compiled, LocalCount, Version, Root - -local function addRef(node, obj) - if not node.ref then - node.ref = {} - end - node.ref[#node.ref+1] = obj - obj.node = node -end - -local function addSpecial(name, obj) - if not Root.specials then - Root.specials = {} - end - if not Root.specials[name] then - Root.specials[name] = {} - end - Root.specials[name][#Root.specials[name]+1] = obj - obj.special = name -end - -local vmMap = { - ['getname'] = function (obj) - local loc = guide.getLocal(obj, obj[1], obj.start) - if loc then - obj.type = 'getlocal' - obj.loc = loc - addRef(loc, obj) - if loc.special then - addSpecial(loc.special, obj) - end - else - obj.type = 'getglobal' - if ENVMode == '_ENV' then - local node = guide.getLocal(obj, '_ENV', obj.start) - if node then - addRef(node, obj) - end - end - local name = obj[1] - if specials[name] then - addSpecial(name, obj) - end - end - return obj - end, - ['getfield'] = function (obj) - Compile(obj.node, obj) - end, - ['call'] = function (obj) - Compile(obj.node, obj) - Compile(obj.args, obj) - end, - ['callargs'] = function (obj) - for i = 1, #obj do - Compile(obj[i], obj) - end - end, - ['binary'] = function (obj) - Compile(obj[1], obj) - Compile(obj[2], obj) - end, - ['unary'] = function (obj) - Compile(obj[1], obj) - end, - ['varargs'] = function (obj) - local func = guide.getParentFunction(obj) - if func then - local index, vararg = guide.getFunctionVarArgs(func) - if not index then - pushError { - type = 'UNEXPECT_DOTS', - start = obj.start, - finish = obj.finish, - } - end - if vararg then - if not vararg.ref then - vararg.ref = {} - end - vararg.ref[#vararg.ref+1] = obj - end - end - end, - ['paren'] = function (obj) - Compile(obj.exp, obj) - end, - ['getindex'] = function (obj) - Compile(obj.node, obj) - Compile(obj.index, obj) - end, - ['setindex'] = function (obj) - Compile(obj.node, obj) - Compile(obj.index, obj) - Compile(obj.value, obj) - end, - ['getmethod'] = function (obj) - Compile(obj.node, obj) - Compile(obj.method, obj) - end, - ['setmethod'] = function (obj) - Compile(obj.node, obj) - Compile(obj.method, obj) - local value = obj.value - value.localself = { - type = 'local', - start = 0, - finish = 0, - method = obj, - effect = obj.finish, - tag = 'self', - [1] = 'self', - } - Compile(value, obj) - end, - ['function'] = function (obj) - local lastBlock = Block - local LastLocalCount = LocalCount - Block = obj - LocalCount = 0 - if obj.localself then - Compile(obj.localself, obj) - obj.localself = nil - end - Compile(obj.args, obj) - for i = 1, #obj do - Compile(obj[i], obj) - end - Block = lastBlock - LocalCount = LastLocalCount - end, - ['funcargs'] = function (obj) - for i = 1, #obj do - Compile(obj[i], obj) - end - end, - ['table'] = function (obj) - for i = 1, #obj do - Compile(obj[i], obj) - end - end, - ['tablefield'] = function (obj) - Compile(obj.value, obj) - end, - ['tableindex'] = function (obj) - Compile(obj.index, obj) - Compile(obj.value, obj) - end, - ['index'] = function (obj) - Compile(obj.index, obj) - end, - ['select'] = function (obj) - local vararg = obj.vararg - if vararg.parent then - if not vararg.extParent then - vararg.extParent = {} - end - vararg.extParent[#vararg.extParent+1] = obj - else - Compile(vararg, obj) - end - end, - ['setname'] = function (obj) - Compile(obj.value, obj) - local loc = guide.getLocal(obj, obj[1], obj.start) - if loc then - obj.type = 'setlocal' - obj.loc = loc - addRef(loc, obj) - if loc.attrs then - local const - for i = 1, #loc.attrs do - local attr = loc.attrs[i][1] - if attr == 'const' - or attr == 'close' then - const = true - break - end - end - if const then - pushError { - type = 'SET_CONST', - start = obj.start, - finish = obj.finish, - } - end - end - else - obj.type = 'setglobal' - if ENVMode == '_ENV' then - local node = guide.getLocal(obj, '_ENV', obj.start) - if node then - addRef(node, obj) - end - end - end - end, - ['local'] = function (obj) - local attrs = obj.attrs - if attrs then - for i = 1, #attrs do - Compile(attrs[i], obj) - end - end - if Block then - if not Block.locals then - Block.locals = {} - end - Block.locals[#Block.locals+1] = obj - LocalCount = LocalCount + 1 - if LocalCount > LocalLimit then - pushError { - type = 'LOCAL_LIMIT', - start = obj.start, - finish = obj.finish, - } - end - end - if obj.localfunction then - obj.localfunction = nil - end - Compile(obj.value, obj) - if obj.value and obj.value.special then - addSpecial(obj.value.special, obj) - end - end, - ['setfield'] = function (obj) - Compile(obj.node, obj) - Compile(obj.value, obj) - end, - ['do'] = function (obj) - local lastBlock = Block - Block = obj - CompileBlock(obj, obj) - if Block.locals then - LocalCount = LocalCount - #Block.locals - end - Block = lastBlock - end, - ['return'] = function (obj) - for i = 1, #obj do - Compile(obj[i], obj) - end - if Block and Block[#Block] ~= obj then - pushError { - type = 'ACTION_AFTER_RETURN', - start = obj.start, - finish = obj.finish, - } - end - local func = guide.getParentFunction(obj) - if func then - if not func.returns then - func.returns = {} - end - func.returns[#func.returns+1] = obj - end - end, - ['label'] = function (obj) - local block = guide.getBlock(obj) - if block then - if not block.labels then - block.labels = {} - end - local name = obj[1] - local label = guide.getLabel(block, name) - if label then - if Version == 'Lua 5.4' - or block == guide.getBlock(label) then - pushError { - type = 'REDEFINED_LABEL', - start = obj.start, - finish = obj.finish, - relative = { - { - label.start, - label.finish, - } - } - } - end - end - block.labels[name] = obj - end - end, - ['goto'] = function (obj) - GoToTag[#GoToTag+1] = obj - end, - ['if'] = function (obj) - for i = 1, #obj do - Compile(obj[i], obj) - end - end, - ['ifblock'] = function (obj) - local lastBlock = Block - Block = obj - Compile(obj.filter, obj) - CompileBlock(obj, obj) - if Block.locals then - LocalCount = LocalCount - #Block.locals - end - Block = lastBlock - end, - ['elseifblock'] = function (obj) - local lastBlock = Block - Block = obj - Compile(obj.filter, obj) - CompileBlock(obj, obj) - if Block.locals then - LocalCount = LocalCount - #Block.locals - end - Block = lastBlock - end, - ['elseblock'] = function (obj) - local lastBlock = Block - Block = obj - CompileBlock(obj, obj) - if Block.locals then - LocalCount = LocalCount - #Block.locals - end - Block = lastBlock - end, - ['loop'] = function (obj) - local lastBlock = Block - Block = obj - Compile(obj.loc, obj) - Compile(obj.max, obj) - Compile(obj.step, obj) - CompileBlock(obj, obj) - if Block.locals then - LocalCount = LocalCount - #Block.locals - end - Block = lastBlock - end, - ['in'] = function (obj) - local lastBlock = Block - Block = obj - local keys = obj.keys - for i = 1, #keys do - Compile(keys[i], obj) - end - CompileBlock(obj, obj) - if Block.locals then - LocalCount = LocalCount - #Block.locals - end - Block = lastBlock - end, - ['while'] = function (obj) - local lastBlock = Block - Block = obj - Compile(obj.filter, obj) - CompileBlock(obj, obj) - if Block.locals then - LocalCount = LocalCount - #Block.locals - end - Block = lastBlock - end, - ['repeat'] = function (obj) - local lastBlock = Block - Block = obj - CompileBlock(obj, obj) - Compile(obj.filter, obj) - if Block.locals then - LocalCount = LocalCount - #Block.locals - end - Block = lastBlock - end, - ['break'] = function (obj) - local block = guide.getBreakBlock(obj) - if block then - if not block.breaks then - block.breaks = {} - end - block.breaks[#block.breaks+1] = obj - else - pushError { - type = 'BREAK_OUTSIDE', - start = obj.start, - finish = obj.finish, - } - end - end, - ['main'] = function (obj) - Block = obj - if ENVMode == '_ENV' then - Compile({ - type = 'local', - start = 0, - finish = 0, - effect = 0, - tag = '_ENV', - special= '_G', - [1] = '_ENV', - }, obj) - end - --- _ENV 是上值,不计入局部变量计数 - LocalCount = 0 - CompileBlock(obj, obj) - Block = nil - end, -} - -function CompileBlock(obj, parent) - for i = 1, #obj do - local act = obj[i] - local f = vmMap[act.type] - if f then - act.parent = parent - f(act) - end - end -end - -function Compile(obj, parent) - if not obj then - return nil - end - if Compiled[obj] then - return - end - Compiled[obj] = true - obj.parent = parent - local f = vmMap[obj.type] - if not f then - return - end - f(obj) -end - -local function compileGoTo(obj) - local name = obj[1] - local label = guide.getLabel(obj, name) - if not label then - pushError { - type = 'NO_VISIBLE_LABEL', - start = obj.start, - finish = obj.finish, - info = { - label = name, - } - } - return - end - if not label.ref then - label.ref = {} - end - label.ref[#label.ref+1] = obj - - -- 如果有局部变量在 goto 与 label 之间声明, - -- 并在 label 之后使用,则算作语法错误 - - -- 如果 label 在 goto 之前声明,那么不会有中间声明的局部变量 - if obj.start > label.start then - return - end - - local block = guide.getBlock(obj) - local locals = block and block.locals - if not locals then - return - end - - for i = 1, #locals do - local loc = locals[i] - -- 检查局部变量声明位置为 goto 与 label 之间 - if loc.start < obj.start or loc.finish > label.finish then - goto CONTINUE - end - -- 检查局部变量的使用位置在 label 之后 - local refs = loc.ref - if not refs then - goto CONTINUE - end - for j = 1, #refs do - local ref = refs[j] - if ref.finish > label.finish then - pushError { - type = 'JUMP_LOCAL_SCOPE', - start = obj.start, - finish = obj.finish, - info = { - loc = loc[1], - }, - relative = { - { - start = label.start, - finish = label.finish, - }, - { - start = loc.start, - finish = loc.finish, - } - }, - } - return - end - end - ::CONTINUE:: - end -end - -local function PostCompile() - for i = 1, #GoToTag do - compileGoTo(GoToTag[i]) - end -end - -return function (self, lua, mode, version) - local state, err = self:parse(lua, mode, version) - if not state then - return nil, err - end - pushError = state.pushError - if version == 'Lua 5.1' or version == 'LuaJIT' then - ENVMode = 'fenv' - else - ENVMode = '_ENV' - end - Compiled = {} - GoToTag = {} - LocalCount = 0 - Version = version - Root = state.ast - if type(state.ast) == 'table' then - Compile(state.ast) - end - PostCompile() - Compiled = nil - GoToTag = nil - return state -end |