1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
---@class vm
local vm = require 'vm.vm'
local guide = require 'parser.guide'
---@class vm.local-compiler
---@field loc parser.object
---@field mainBlock parser.object
---@field blocks table<parser.object, table>
local mt = {}
mt.__index = mt
mt.index = 1
---@class parser.object
---@field _hasSorted boolean
---@param source parser.object
local function sortRefs(source)
if source._hasSorted then
return
end
source._hasSorted = true
table.sort(source.ref, function (a, b)
return (a.range or a.start) < (b.range or b.start)
end)
end
---@param node vm.node
---@param block parser.object
---@return vm.node
function mt:_compileBlock(node, block)
for _ = 1, 10000 do
if self.blocks[block]
or self.mainBlock == block
or block.type == 'function'
or block.type == 'main' then
return node
end
self.blocks[block] = {}
block = guide.getParentBlock(block)
end
error('compile block overstack')
end
---@param node vm.node
---@param currentBlock parser.object
---@param callback fun(src: parser.object, node: vm.node)
---@return vm.node
function mt:_runBlock(node, currentBlock, callback)
local currentNode = self:_compileBlock(node, currentBlock)
for _ = 1, 10000 do
local ref = self.loc.ref[self.index]
if not ref
or ref.start > currentBlock.finish then
return node
end
local block = guide.getParentBlock(ref)
if block == currentBlock then
callback(ref, currentNode)
self.index = self.index + 1
if ref.type == 'setlocal' then
currentNode = vm.getNode(ref)
end
else
currentNode = self:_runBlock(currentNode, block, callback)
end
end
error('run block overstack')
end
---@param callback fun(src: parser.object, node: vm.node)
function mt:launch(callback)
self:_runBlock(vm.getNode(self.loc), self.mainBlock, callback)
end
---@param loc parser.object
---@return vm.local-compiler
function vm.createRunner(loc)
local self = setmetatable({
loc = loc,
mainBlock = guide.getParentBlock(loc),
blocks = {},
}, mt)
sortRefs(loc)
return self
end
|