diff options
author | 最萌小汐 <sumneko@hotmail.com> | 2022-07-06 17:34:21 +0800 |
---|---|---|
committer | 最萌小汐 <sumneko@hotmail.com> | 2022-07-06 17:34:21 +0800 |
commit | 91ab8e7b4c3c17da0a1bcdfb02a38c23cc786910 (patch) | |
tree | b8b9637292bf7656e9b3acefc11e71d98ffd6c9c /script | |
parent | f407cb07ed559daf7a5a943d8896e849791ae5b7 (diff) | |
download | lua-language-server-91ab8e7b4c3c17da0a1bcdfb02a38c23cc786910.zip |
cleanup
Diffstat (limited to 'script')
-rw-r--r-- | script/parser/luadoc.lua | 39 | ||||
-rw-r--r-- | script/vm/compiler.lua | 247 | ||||
-rw-r--r-- | script/vm/init.lua | 1 | ||||
-rw-r--r-- | script/vm/operator.lua | 269 |
4 files changed, 311 insertions, 245 deletions
diff --git a/script/parser/luadoc.lua b/script/parser/luadoc.lua index 2e0125c5..a94f89cd 100644 --- a/script/parser/luadoc.lua +++ b/script/parser/luadoc.lua @@ -1353,6 +1353,45 @@ local docSwitch = util.switch() return result end) + : case 'operator' + : call(function () + local result = { + type = 'doc.operator', + start = getFinish(), + finish = getFinish(), + } + + local op = parseName('doc.operator.name', result) + if not op then + pushWarning { + type = 'LUADOC_MISS_OPERATOR_NAME', + start = getFinish(), + finish = getFinish(), + } + return nil + end + result.op = op + result.finish = op.finish + + if checkToken('symbol', '(', 1) then + local exp = parseType(result) + if exp then + result.exp = exp + result.finish = exp.finish + end + nextSymbolOrError ')' + end + + nextSymbolOrError ':' + + local ret = parseType(result) + if ret then + result.ret = ret + result.finish = ret.finish + end + + return result + end) local function convertTokens() local tp, text = nextToken() diff --git a/script/vm/compiler.lua b/script/vm/compiler.lua index 12cf102b..beb6e4e5 100644 --- a/script/vm/compiler.lua +++ b/script/vm/compiler.lua @@ -1022,193 +1022,6 @@ local function compileLocal(source) vm.getNode(source):setData('hasDefined', hasMarkDoc or hasMarkParam or hasMarkValue) end -local binarySwich = util.switch() - : case 'and' - : call(function (source) - local node1 = vm.compileNode(source[1]) - local node2 = vm.compileNode(source[2]) - local r1 = vm.testCondition(source[1]) - if r1 == true then - vm.setNode(source, node2) - elseif r1 == false then - vm.setNode(source, node1) - else - local node = node1:copy():setFalsy():merge(node2) - vm.setNode(source, node) - end - end) - : case 'or' - : call(function (source) - local node1 = vm.compileNode(source[1]) - local node2 = vm.compileNode(source[2]) - local r1 = vm.testCondition(source[1]) - if r1 == true then - vm.setNode(source, node1) - elseif r1 == false then - vm.setNode(source, node2) - else - local node = node1:copy():setTruthy():merge(node2) - vm.setNode(source, node) - end - end) - : case '==' - : case '~=' - : call(function (source) - local result = vm.equal(source[1], source[2]) - if result == nil then - vm.setNode(source, vm.declareGlobal('type', 'boolean')) - else - if source.op.type == '~=' then - result = not result - end - vm.setNode(source, { - type = 'boolean', - start = source.start, - finish = source.finish, - parent = source, - [1] = result, - }) - end - end) - : case '<<' - : case '>>' - : case '&' - : case '|' - : case '~' - : call(function (source) - local a = vm.getInteger(source[1]) - local b = vm.getInteger(source[2]) - if a and b then - local op = source.op.type - local result = op.type == '<<' and a << b - or op.type == '>>' and a >> b - or op.type == '&' and a & b - or op.type == '|' and a | b - or op.type == '~' and a ~ b - vm.setNode(source, { - type = 'integer', - start = source.start, - finish = source.finish, - parent = source, - [1] = result, - }) - else - vm.setNode(source, vm.declareGlobal('type', 'integer')) - end - end) - : case '+' - : case '-' - : case '*' - : case '/' - : case '%' - : case '//' - : case '^' - : call(function (source) - local a = vm.getNumber(source[1]) - local b = vm.getNumber(source[2]) - local op = source.op.type - local zero = b == 0 - and ( op == '%' - or op == '/' - or op == '//' - ) - if a and b and not zero then - local result = op == '+' and a + b - or op == '-' and a - b - or op == '*' and a * b - or op == '/' and a / b - or op == '%' and a % b - or op == '//' and a // b - or op == '^' and a ^ b - vm.setNode(source, { - type = math.type(result) == 'integer' and 'integer' or 'number', - start = source.start, - finish = source.finish, - parent = source, - [1] = result, - }) - else - if op == '+' - or op == '-' - or op == '*' - or op == '//' - or op == '%' then - local uri = guide.getUri(source) - local infer1 = vm.getInfer(source[1]) - local infer2 = vm.getInfer(source[2]) - if infer1:hasType(uri, 'integer') - or infer2:hasType(uri, 'integer') then - if not infer1:hasType(uri, 'number') - and not infer2:hasType(uri, 'number') then - vm.setNode(source, vm.declareGlobal('type', 'integer')) - return - end - end - end - vm.setNode(source, vm.declareGlobal('type', 'number')) - end - end) - : case '..' - : call(function (source) - local a = vm.getString(source[1]) - or vm.getNumber(source[1]) - local b = vm.getString(source[2]) - or vm.getNumber(source[2]) - if a and b then - if type(a) == 'number' or type(b) == 'number' then - local uri = guide.getUri(source) - local version = config.get(uri, 'Lua.runtime.version') - if math.tointeger(a) and math.type(a) == 'float' then - if version == 'Lua 5.3' or version == 'Lua 5.4' then - a = ('%.1f'):format(a) - else - a = ('%.0f'):format(a) - end - end - if math.tointeger(b) and math.type(b) == 'float' then - if version == 'Lua 5.3' or version == 'Lua 5.4' then - b = ('%.1f'):format(b) - else - b = ('%.0f'):format(b) - end - end - end - vm.setNode(source, { - type = 'string', - start = source.start, - finish = source.finish, - parent = source, - [1] = a .. b, - }) - else - vm.setNode(source, vm.declareGlobal('type', 'string')) - end - end) - : case '>' - : case '<' - : case '>=' - : case '<=' - : call(function (source) - local a = vm.getNumber(source[1]) - local b = vm.getNumber(source[2]) - if a and b then - local op = source.op.type - local result = op.type == '>' and a > b - or op.type == '<' and a < b - or op.type == '>=' and a >= b - or op.type == '<=' and a <= b - vm.setNode(source, { - type = 'boolean', - start = source.start, - finish = source.finish, - parent = source, - [1] =result, - }) - else - vm.setNode(source, vm.declareGlobal('type', 'boolean')) - end - end) - local compilerSwitch = util.switch() : case 'nil' : case 'boolean' @@ -1818,63 +1631,7 @@ local compilerSwitch = util.switch() if not source[1] then return end - if source.op.type == 'not' then - local result = vm.testCondition(source[1]) - if result == nil then - vm.setNode(source, vm.declareGlobal('type', 'boolean')) - return - else - vm.setNode(source, { - type = 'boolean', - start = source.start, - finish = source.finish, - parent = source, - [1] = not result, - }) - return - end - end - if source.op.type == '#' then - vm.setNode(source, vm.declareGlobal('type', 'integer')) - return - end - if source.op.type == '-' then - local v = vm.getNumber(source[1]) - if v == nil then - local infer = vm.getInfer(source[1]) - if infer:hasType(guide.getUri(source), 'integer') then - vm.setNode(source, vm.declareGlobal('type', 'integer')) - else - vm.setNode(source, vm.declareGlobal('type', 'number')) - end - return - else - vm.setNode(source, { - type = 'number', - start = source.start, - finish = source.finish, - parent = source, - [1] = -v, - }) - return - end - end - if source.op.type == '~' then - local v = vm.getInteger(source[1]) - if v == nil then - vm.setNode(source, vm.declareGlobal('type', 'integer')) - return - else - vm.setNode(source, { - type = 'integer', - start = source.start, - finish = source.finish, - parent = source, - [1] = ~v, - }) - return - end - end + vm.unarySwich(source.op.type, source) end) : case 'binary' : call(function (source) @@ -1884,7 +1641,7 @@ local compilerSwitch = util.switch() if not source[1] or not source[2] then return end - binarySwich(source.op.type, source) + vm.binarySwitch(source.op.type, source) end) ---@param source parser.object diff --git a/script/vm/init.lua b/script/vm/init.lua index 24e75f95..87c046f0 100644 --- a/script/vm/init.lua +++ b/script/vm/init.lua @@ -18,4 +18,5 @@ require 'vm.sign' require 'vm.local-id' require 'vm.global' require 'vm.function' +require 'vm.operator' return vm diff --git a/script/vm/operator.lua b/script/vm/operator.lua new file mode 100644 index 00000000..0ed3ff1d --- /dev/null +++ b/script/vm/operator.lua @@ -0,0 +1,269 @@ +---@class vm +local vm = require 'vm.vm' +local util = require 'utility' +local guide = require 'parser.guide' +local config = require 'config' + +vm.UNARY_OP = { + 'unm', + 'bnot', + 'len', +} +vm.BINARY_OP = { + 'add', + 'sub', + 'mul', + 'div', + 'mod', + 'pow', + 'idiv', + 'band', + 'bor', + 'bxor', + 'shl', + 'shr', + 'concat', +} + +vm.unarySwich = util.switch() + : case 'not' + : call(function (source) + local result = vm.testCondition(source[1]) + if result == nil then + vm.setNode(source, vm.declareGlobal('type', 'boolean')) + else + vm.setNode(source, { + type = 'boolean', + start = source.start, + finish = source.finish, + parent = source, + [1] = not result, + }) + end + end) + : case '#' + : call(function (source) + vm.setNode(source, vm.declareGlobal('type', 'integer')) + end) + : case '-' + : call(function (source) + local v = vm.getNumber(source[1]) + if v == nil then + local infer = vm.getInfer(source[1]) + if infer:hasType(guide.getUri(source), 'integer') then + vm.setNode(source, vm.declareGlobal('type', 'integer')) + else + vm.setNode(source, vm.declareGlobal('type', 'number')) + end + else + vm.setNode(source, { + type = 'number', + start = source.start, + finish = source.finish, + parent = source, + [1] = -v, + }) + end + end) + : case '~' + : call(function (source) + local v = vm.getInteger(source[1]) + if v == nil then + vm.setNode(source, vm.declareGlobal('type', 'integer')) + else + vm.setNode(source, { + type = 'integer', + start = source.start, + finish = source.finish, + parent = source, + [1] = ~v, + }) + end + end) + +vm.binarySwitch = util.switch() + : case 'and' + : call(function (source) + local node1 = vm.compileNode(source[1]) + local node2 = vm.compileNode(source[2]) + local r1 = vm.testCondition(source[1]) + if r1 == true then + vm.setNode(source, node2) + elseif r1 == false then + vm.setNode(source, node1) + else + local node = node1:copy():setFalsy():merge(node2) + vm.setNode(source, node) + end + end) + : case 'or' + : call(function (source) + local node1 = vm.compileNode(source[1]) + local node2 = vm.compileNode(source[2]) + local r1 = vm.testCondition(source[1]) + if r1 == true then + vm.setNode(source, node1) + elseif r1 == false then + vm.setNode(source, node2) + else + local node = node1:copy():setTruthy():merge(node2) + vm.setNode(source, node) + end + end) + : case '==' + : case '~=' + : call(function (source) + local result = vm.equal(source[1], source[2]) + if result == nil then + vm.setNode(source, vm.declareGlobal('type', 'boolean')) + else + if source.op.type == '~=' then + result = not result + end + vm.setNode(source, { + type = 'boolean', + start = source.start, + finish = source.finish, + parent = source, + [1] = result, + }) + end + end) + : case '<<' + : case '>>' + : case '&' + : case '|' + : case '~' + : call(function (source) + local a = vm.getInteger(source[1]) + local b = vm.getInteger(source[2]) + if a and b then + local op = source.op.type + local result = op.type == '<<' and a << b + or op.type == '>>' and a >> b + or op.type == '&' and a & b + or op.type == '|' and a | b + or op.type == '~' and a ~ b + vm.setNode(source, { + type = 'integer', + start = source.start, + finish = source.finish, + parent = source, + [1] = result, + }) + else + vm.setNode(source, vm.declareGlobal('type', 'integer')) + end + end) + : case '+' + : case '-' + : case '*' + : case '/' + : case '%' + : case '//' + : case '^' + : call(function (source) + local a = vm.getNumber(source[1]) + local b = vm.getNumber(source[2]) + local op = source.op.type + local zero = b == 0 + and ( op == '%' + or op == '/' + or op == '//' + ) + if a and b and not zero then + local result = op == '+' and a + b + or op == '-' and a - b + or op == '*' and a * b + or op == '/' and a / b + or op == '%' and a % b + or op == '//' and a // b + or op == '^' and a ^ b + vm.setNode(source, { + type = math.type(result) == 'integer' and 'integer' or 'number', + start = source.start, + finish = source.finish, + parent = source, + [1] = result, + }) + else + if op == '+' + or op == '-' + or op == '*' + or op == '//' + or op == '%' then + local uri = guide.getUri(source) + local infer1 = vm.getInfer(source[1]) + local infer2 = vm.getInfer(source[2]) + if infer1:hasType(uri, 'integer') + or infer2:hasType(uri, 'integer') then + if not infer1:hasType(uri, 'number') + and not infer2:hasType(uri, 'number') then + vm.setNode(source, vm.declareGlobal('type', 'integer')) + return + end + end + end + vm.setNode(source, vm.declareGlobal('type', 'number')) + end + end) + : case '..' + : call(function (source) + local a = vm.getString(source[1]) + or vm.getNumber(source[1]) + local b = vm.getString(source[2]) + or vm.getNumber(source[2]) + if a and b then + if type(a) == 'number' or type(b) == 'number' then + local uri = guide.getUri(source) + local version = config.get(uri, 'Lua.runtime.version') + if math.tointeger(a) and math.type(a) == 'float' then + if version == 'Lua 5.3' or version == 'Lua 5.4' then + a = ('%.1f'):format(a) + else + a = ('%.0f'):format(a) + end + end + if math.tointeger(b) and math.type(b) == 'float' then + if version == 'Lua 5.3' or version == 'Lua 5.4' then + b = ('%.1f'):format(b) + else + b = ('%.0f'):format(b) + end + end + end + vm.setNode(source, { + type = 'string', + start = source.start, + finish = source.finish, + parent = source, + [1] = a .. b, + }) + else + vm.setNode(source, vm.declareGlobal('type', 'string')) + end + end) + : case '>' + : case '<' + : case '>=' + : case '<=' + : call(function (source) + local a = vm.getNumber(source[1]) + local b = vm.getNumber(source[2]) + if a and b then + local op = source.op.type + local result = op.type == '>' and a > b + or op.type == '<' and a < b + or op.type == '>=' and a >= b + or op.type == '<=' and a <= b + vm.setNode(source, { + type = 'boolean', + start = source.start, + finish = source.finish, + parent = source, + [1] =result, + }) + else + vm.setNode(source, vm.declareGlobal('type', 'boolean')) + end + end) |