Skip to content

Commit 98589dd

Browse files
committed
stash
1 parent 76bd955 commit 98589dd

File tree

4 files changed

+159
-75
lines changed

4 files changed

+159
-75
lines changed

script/vm/compiler.lua

Lines changed: 13 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -973,14 +973,11 @@ local function compileLocal(source)
973973
end
974974
end
975975
if not hasMarkValue and not hasMarkValue then
976-
if source.ref then
977-
for _, ref in ipairs(source.ref) do
978-
if ref.type == 'setlocal'
979-
and ref.value
980-
and ref.value.type == 'function' then
981-
vm.setNode(source, vm.compileNode(ref.value))
982-
end
983-
end
976+
local firstRef = source.ref and source.ref[1]
977+
if firstRef
978+
and guide.isSet(firstRef)
979+
and guide.getBlock(firstRef) == guide.getBlock(source) then
980+
vm.setNode(source, vm.compileNode(firstRef))
984981
end
985982
end
986983
-- function x.y(self, ...) --> function x:y(...)
@@ -1163,81 +1160,24 @@ local compilerSwitch = util.switch()
11631160
---@async
11641161
---@param source parser.object
11651162
: call(function (source)
1166-
vm.launchRunner(source, function ()
1167-
local myNode = vm.getNode(source)
1168-
---@cast myNode -?
1169-
myNode:setData('resolving', true)
1170-
1171-
if source.ref then
1172-
for _, ref in ipairs(source.ref) do
1173-
if ref.type == 'getlocal'
1174-
or ref.type == 'setlocal' then
1175-
vm.setNode(ref, myNode, true)
1176-
end
1177-
end
1178-
end
1179-
compileLocal(source)
1180-
1181-
myNode.resolved = true
1182-
end, function ()
1183-
local myNode = vm.getNode(source)
1184-
---@cast myNode -?
1185-
myNode:setData('resolving', nil)
1186-
local hasMark = vm.getNode(source):getData 'hasDefined'
1187-
if source.ref and not hasMark then
1188-
local parentFunc = guide.getParentFunction(source)
1189-
for _, ref in ipairs(source.ref) do
1190-
if ref.type == 'setlocal'
1191-
and guide.getParentFunction(ref) == parentFunc then
1192-
local refNode = vm.getNode(ref)
1193-
if refNode then
1194-
vm.setNode(source, refNode)
1195-
end
1196-
end
1197-
end
1198-
end
1199-
end, function (src, node)
1200-
if src.type == 'setlocal' then
1201-
if src.bindDocs then
1202-
for _, doc in ipairs(src.bindDocs) do
1203-
if doc.type == 'doc.type' then
1204-
vm.setNode(src, vm.compileNode(doc), true)
1205-
return vm.getNode(src)
1206-
end
1207-
end
1208-
end
1209-
if src.value then
1210-
if src.value.type == 'table' then
1211-
vm.setNode(src, vm.createNode(src.value), true)
1212-
vm.setNode(src, node:copy():asTable())
1213-
else
1214-
vm.setNode(src, vm.compileNode(src.value), true)
1215-
end
1216-
else
1217-
vm.setNode(src, node, true)
1218-
end
1219-
return vm.getNode(src)
1220-
elseif src.type == 'getlocal' then
1221-
if bindAs(src) then
1222-
return
1223-
end
1224-
vm.setNode(src, node, true)
1225-
node.resolved = true
1226-
matchCall(src)
1227-
end
1228-
end)
1163+
compileLocal(source)
12291164
end)
12301165
: case 'setlocal'
12311166
: call(function (source)
1232-
vm.compileNode(source.node)
1167+
local valueNode = vm.compileNode(source.value)
1168+
vm.setNode(source, valueNode)
12331169
end)
12341170
: case 'getlocal'
12351171
---@async
12361172
: call(function (source)
12371173
if bindAs(source) then
12381174
return
12391175
end
1240-
vm.compileNode(source.node)
1176+
local node = vm.traceNode(source)
1177+
if not node then
1178+
return
1179+
end
1180+
vm.setNode(source, node, true)
12411181
end)
12421182
: case 'setfield'
12431183
: case 'setmethod'

script/vm/init.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ require 'vm.field'
1111
require 'vm.doc'
1212
require 'vm.type'
1313
require 'vm.library'
14-
require 'vm.runner'
14+
require 'vm.tracer'
1515
require 'vm.infer'
1616
require 'vm.generic'
1717
require 'vm.sign'

script/vm/tracer.lua

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
---@class vm
2+
local vm = require 'vm.vm'
3+
local guide = require 'parser.guide'
4+
5+
---@class parser.object
6+
---@field package _tracer? vm.tracer
7+
---@field package _casts? parser.object[]
8+
9+
---@class vm.tracer
10+
---@field source parser.object
11+
---@field assigns parser.object[]
12+
---@field nodes table<parser.object, vm.node>
13+
---@field main parser.object
14+
---@field uri uri
15+
local mt = {}
16+
mt.__index = mt
17+
18+
---@return parser.object[]
19+
function mt:getCasts()
20+
local root = guide.getRoot(self.source)
21+
if not root._casts then
22+
root._casts = {}
23+
local docs = root.docs
24+
for _, doc in ipairs(docs) do
25+
if doc.type == 'doc.cast' and doc.loc then
26+
root._casts[#root._casts+1] = doc
27+
end
28+
end
29+
end
30+
return root._casts
31+
end
32+
33+
---@param obj parser.object
34+
---@param mark table
35+
function mt:collectBlock(obj, mark)
36+
while true do
37+
if mark[obj] then
38+
return
39+
end
40+
mark[obj] = true
41+
self.assigns[#self.assigns+1] = obj
42+
if obj == self.main then
43+
return
44+
end
45+
obj = obj.parent
46+
end
47+
end
48+
49+
function mt:collectLocal()
50+
local startPos = self.source.start
51+
local finishPos = 0
52+
53+
local mark = {}
54+
55+
for _, obj in ipairs(self.source.ref) do
56+
if obj.type == 'setlocal' then
57+
self.assigns[#self.assigns+1] = obj
58+
self:collectBlock(obj, mark)
59+
end
60+
end
61+
62+
local casts = self:getCasts()
63+
for _, cast in ipairs(casts) do
64+
if cast.loc[1] == self.source[1]
65+
and cast.start > startPos
66+
and cast.finish < finishPos
67+
and guide.getLocal(self.source, self.source[1], cast.start) == self.source then
68+
self.assigns[#self.assigns+1] = cast
69+
end
70+
end
71+
72+
table.sort(self.assigns, function (a, b)
73+
return a.start < b.start
74+
end)
75+
end
76+
77+
---@param source parser.object
78+
---@return parser.object?
79+
function mt:getLastAssign(source)
80+
local assign = self.source
81+
for _, obj in ipairs(self.assigns) do
82+
if obj.start > source.start then
83+
break
84+
end
85+
assign = obj
86+
end
87+
return assign
88+
end
89+
90+
---@param source parser.object
91+
---@return vm.node?
92+
function mt:getNode(source)
93+
if self.nodes[source] then
94+
return self.nodes[source]
95+
end
96+
local lastAssign = self:getLastAssign(source)
97+
if not lastAssign then
98+
return nil
99+
end
100+
if guide.isSet(lastAssign) then
101+
local lastNode = vm.compileNode(lastAssign)
102+
return lastNode
103+
end
104+
end
105+
106+
---@param source parser.object
107+
---@return vm.tracer?
108+
local function createTracer(source)
109+
if source._tracer then
110+
return source._tracer
111+
end
112+
local main = guide.getParentBlock(source)
113+
if not main then
114+
return nil
115+
end
116+
local tracer = setmetatable({
117+
source = source,
118+
assigns = {},
119+
nodes = {},
120+
main = main,
121+
uri = guide.getUri(source),
122+
}, mt)
123+
source._tracer = tracer
124+
125+
tracer:collectLocal()
126+
127+
return tracer
128+
end
129+
130+
---@param source parser.object
131+
---@return vm.node?
132+
function vm.traceNode(source)
133+
local loc
134+
if source.type == 'getlocal'
135+
or source.type == 'setlocal' then
136+
loc = source.node
137+
end
138+
local tracer = createTracer(loc)
139+
if not tracer then
140+
return nil
141+
end
142+
local node = tracer:getNode(source)
143+
return node
144+
end

test/type_inference/init.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1590,7 +1590,7 @@ AAA = {}
15901590
local <?x?> = AAA()
15911591
]]
15921592

1593-
TEST 'string|integer' [[
1593+
TEST 'string' [[
15941594
local <?x?>
15951595
x = '1'
15961596
x = 1

0 commit comments

Comments
 (0)