summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--script/vm/node.lua3
-rw-r--r--script/vm/runner.lua51
2 files changed, 43 insertions, 11 deletions
diff --git a/script/vm/node.lua b/script/vm/node.lua
index 6a86350a..e15788a5 100644
--- a/script/vm/node.lua
+++ b/script/vm/node.lua
@@ -152,6 +152,7 @@ function mt:setTruthy()
if hasBoolean then
self[#self+1] = vm.declareGlobal('type', 'true')
end
+ return self
end
---@return vm.node
@@ -180,6 +181,7 @@ function mt:setFalsy()
if hasBoolean then
self[#self+1] = vm.declareGlobal('type', 'false')
end
+ return self
end
---@param name string
@@ -200,6 +202,7 @@ function mt:remove(name)
self[c] = nil
end
end
+ return self
end
---@param node vm.node
diff --git a/script/vm/runner.lua b/script/vm/runner.lua
index 87630512..65992bea 100644
--- a/script/vm/runner.lua
+++ b/script/vm/runner.lua
@@ -63,14 +63,14 @@ end
---@param pos integer
---@param node vm.node
----@return parser.object
---@return vm.node
+---@return parser.object?
function mt:_fastWard(pos, node)
for i = self._index, #self._objs do
local obj = self._objs[i]
if obj.start > pos then
self._index = i
- return obj, node
+ return node, obj
end
if obj.type == 'getlocal' then
self._callback(obj, node)
@@ -83,37 +83,66 @@ function mt:_fastWard(pos, node)
error('unexpected type: ' .. obj.type)
end
end
+ self._index = math.huge
+ return node, nil
end
----@param action parser.object
----@param topNode vm.node
-function mt:_lookInto(action, topNode)
+---@param action parser.object
+---@param topNode vm.node
+---@param outNode? vm.node
+---@return vm.node
+function mt:_lookInto(action, topNode, outNode)
action = vm.getObjectValue(action) or action
if action.type == 'function' then
self:_launchBlock(action, topNode:copy())
+ elseif action.type == 'if' then
+ local mainNode = topNode:copy()
+ local blockNode = topNode:copy()
+ for _, subBlock in ipairs(action) do
+ if subBlock.type == 'ifblock' then
+ blockNode, mainNode = self:_lookInto(subBlock.filter, blockNode, mainNode)
+ blockNode = self:_launchBlock(subBlock, blockNode)
+ mainNode:merge(blockNode)
+ end
+ end
+ elseif action.type == 'getlocal' then
+ if action.node == self._loc then
+ topNode = self:_fastWard(action.finish, topNode)
+ topNode = topNode:copy():setTruthy()
+ if outNode then
+ outNode:setFalsy()
+ end
+ end
+ elseif action.type == 'unary' then
+ if action.op.type == 'not' then
+ outNode, topNode = self:_lookInto(action[1], topNode, outNode)
+ end
end
+ return topNode, outNode
end
---@param block parser.object
---@param node vm.node
+---@return vm.node
function mt:_launchBlock(block, node)
- local top, topNode = self:_fastWard(block.start, node)
+ local topNode, top = self:_fastWard(block.start, node)
if not top then
- return
+ return topNode
end
for _, action in ipairs(block) do
local finish = action.range or action.finish
if finish < top.start then
goto CONTINUE
end
- self:_lookInto(action, topNode)
- top, topNode = self:_fastWard(action.finish, topNode)
+ topNode = self:_lookInto(action, topNode)
+ topNode, top = self:_fastWard(action.finish, topNode)
if not top then
- return
+ return topNode
end
::CONTINUE::
end
- self:_fastWard(block.finish, topNode)
+ topNode = self:_fastWard(block.finish, topNode)
+ return topNode
end
---@param loc parser.object