summaryrefslogtreecommitdiff
path: root/script
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2022-06-15 19:15:01 +0800
committer最萌小汐 <sumneko@hotmail.com>2022-06-15 19:15:01 +0800
commitc61eefc970c66da77a6428cf7ea1537e8719734a (patch)
treefdb3a26725d32a0af246b198d9176f1357ac16a0 /script
parenta86a5884ddbdb32fad8dce1b50c6d0c76c862256 (diff)
downloadlua-language-server-c61eefc970c66da77a6428cf7ea1537e8719734a.zip
cleanup
Diffstat (limited to 'script')
-rw-r--r--script/vm/compiler.lua505
1 files changed, 171 insertions, 334 deletions
diff --git a/script/vm/compiler.lua b/script/vm/compiler.lua
index acb39432..5bdb1d3c 100644
--- a/script/vm/compiler.lua
+++ b/script/vm/compiler.lua
@@ -928,6 +928,176 @@ 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.test(source[1])
+ if r1 == true then
+ vm.setNode(source, node2)
+ elseif r1 == false then
+ vm.setNode(source, node1)
+ else
+ vm.setNode(source, node2)
+ end
+ end)
+ : case 'or'
+ : call(function (source)
+ local node1 = vm.compileNode(source[1])
+ local node2 = vm.compileNode(source[2])
+ local r1 = vm.test(source[1])
+ if r1 == true then
+ vm.setNode(source, node1)
+ elseif r1 == false then
+ vm.setNode(source, node2)
+ else
+ vm.getNode(source):merge(node1)
+ vm.getNode(source):setTruthy()
+ vm.getNode(source):merge(node2)
+ 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
+ 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'
@@ -1482,340 +1652,7 @@ local compilerSwitch = util.switch()
if not source[1] or not source[2] then
return
end
- if source.op.type == 'and' then
- local node1 = vm.compileNode(source[1])
- local node2 = vm.compileNode(source[2])
- local r1 = vm.test(source[1])
- if r1 == true then
- vm.setNode(source, node2)
- elseif r1 == false then
- vm.setNode(source, node1)
- else
- vm.setNode(source, node2)
- end
- end
- if source.op.type == 'or' then
- local node1 = vm.compileNode(source[1])
- local node2 = vm.compileNode(source[2])
- local r1 = vm.test(source[1])
- if r1 == true then
- vm.setNode(source, node1)
- elseif r1 == false then
- vm.setNode(source, node2)
- else
- vm.getNode(source):merge(node1)
- vm.getNode(source):setTruthy()
- vm.getNode(source):merge(node2)
- end
- end
- if source.op.type == '==' then
- local result = vm.equal(source[1], source[2])
- 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] = result,
- })
- return
- end
- end
- if source.op.type == '~=' then
- local result = vm.equal(source[1], source[2])
- 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
- local a = vm.getInteger(source[1])
- local b = vm.getInteger(source[2])
- if a and b then
- vm.setNode(source, {
- type = 'integer',
- start = source.start,
- finish = source.finish,
- parent = source,
- [1] = a << b,
- })
- return
- else
- vm.setNode(source, vm.declareGlobal('type', 'integer'))
- return
- end
- end
- if source.op.type == '>>' then
- local a = vm.getInteger(source[1])
- local b = vm.getInteger(source[2])
- if a and b then
- vm.setNode(source, {
- type = 'integer',
- start = source.start,
- finish = source.finish,
- parent = source,
- [1] = a >> b,
- })
- return
- else
- vm.setNode(source, vm.declareGlobal('type', 'integer'))
- return
- end
- end
- if source.op.type == '&' then
- local a = vm.getInteger(source[1])
- local b = vm.getInteger(source[2])
- if a and b then
- vm.setNode(source, {
- type = 'integer',
- start = source.start,
- finish = source.finish,
- parent = source,
- [1] = a & b,
- })
- return
- else
- vm.setNode(source, vm.declareGlobal('type', 'integer'))
- return
- end
- end
- if source.op.type == '|' then
- local a = vm.getInteger(source[1])
- local b = vm.getInteger(source[2])
- if a and b then
- vm.setNode(source, {
- type = 'integer',
- start = source.start,
- finish = source.finish,
- parent = source,
- [1] = a | b,
- })
- return
- else
- vm.setNode(source, vm.declareGlobal('type', 'integer'))
- return
- end
- end
- if source.op.type == '~' then
- local a = vm.getInteger(source[1])
- local b = vm.getInteger(source[2])
- if a and b then
- vm.setNode(source, {
- type = 'integer',
- start = source.start,
- finish = source.finish,
- parent = source,
- [1] = a ~ b,
- })
- return
- else
- vm.setNode(source, vm.declareGlobal('type', 'integer'))
- return
- end
- end
- if source.op.type == '+' then
- local a = vm.getNumber(source[1])
- local b = vm.getNumber(source[2])
- if a and b then
- local result = a + b
- vm.setNode(source, {
- type = math.type(result) == 'integer' and 'integer' or 'number',
- start = source.start,
- finish = source.finish,
- parent = source,
- [1] = result,
- })
- return
- else
- vm.setNode(source, vm.declareGlobal('type', 'number'))
- return
- end
- end
- if source.op.type == '-' then
- local a = vm.getNumber(source[1])
- local b = vm.getNumber(source[2])
- if a and b then
- local result = a - b
- vm.setNode(source, {
- type = math.type(result) == 'integer' and 'integer' or 'number',
- start = source.start,
- finish = source.finish,
- parent = source,
- [1] = result,
- })
- return
- else
- vm.setNode(source, vm.declareGlobal('type', 'number'))
- return
- end
- end
- if source.op.type == '*' then
- local a = vm.getNumber(source[1])
- local b = vm.getNumber(source[2])
- if a and b then
- local result = a * b
- vm.setNode(source, {
- type = math.type(result) == 'integer' and 'integer' or 'number',
- start = source.start,
- finish = source.finish,
- parent = source,
- [1] = result,
- })
- return
- else
- vm.setNode(source, vm.declareGlobal('type', 'number'))
- return
- end
- end
- if source.op.type == '/' then
- local a = vm.getNumber(source[1])
- local b = vm.getNumber(source[2])
- if a and b then
- vm.setNode(source, {
- type = 'number',
- start = source.start,
- finish = source.finish,
- parent = source,
- [1] = a / b,
- })
- return
- else
- vm.setNode(source, vm.declareGlobal('type', 'number'))
- return
- end
- end
- if source.op.type == '%' then
- local a = vm.getNumber(source[1])
- local b = vm.getNumber(source[2])
- if a and b and b ~= 0 then
- local result = a % b
- vm.setNode(source, {
- type = math.type(result) == 'integer' and 'integer' or 'number',
- start = source.start,
- finish = source.finish,
- parent = source,
- [1] = result,
- })
- return
- else
- vm.setNode(source, vm.declareGlobal('type', 'number'))
- return
- end
- end
- if source.op.type == '^' then
- local a = vm.getNumber(source[1])
- local b = vm.getNumber(source[2])
- if a and b then
- vm.setNode(source, {
- type = 'number',
- start = source.start,
- finish = source.finish,
- parent = source,
- [1] = a ^ b,
- })
- return
- else
- vm.setNode(source, vm.declareGlobal('type', 'number'))
- return
- end
- end
- if source.op.type == '//' then
- local a = vm.getNumber(source[1])
- local b = vm.getNumber(source[2])
- if a and b and b ~= 0 then
- local result = a // b
- vm.setNode(source, {
- type = math.type(result) == 'integer' and 'integer' or 'number',
- start = source.start,
- finish = source.finish,
- parent = source,
- [1] = result,
- })
- return
- else
- vm.setNode(source, vm.declareGlobal('type', 'number'))
- return
- end
- end
- if source.op.type == '..' then
- 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,
- })
- return
- else
- vm.setNode(source, vm.declareGlobal('type', 'string'))
- return
- end
- end
- if source.op.type == '>'
- or source.op.type == '<'
- or source.op.type == '>='
- or source.op.type == '<=' then
- local a = vm.getNumber(source[1])
- local b = vm.getNumber(source[2])
- if a and b then
- local result
- if source.op.type == '>' then
- result = a > b
- elseif source.op.type == '<' then
- result = a < b
- elseif source.op.type == '>=' then
- result = a >= b
- elseif source.op.type == '<=' then
- result = a <= b
- end
- vm.setNode(source, {
- type = 'boolean',
- start = source.start,
- finish = source.finish,
- parent = source,
- [1] = result,
- })
- return
- else
- vm.setNode(source, vm.declareGlobal('type', 'boolean'))
- return
- end
- end
+ binarySwich(source.op.type, source)
end)
---@param source vm.object