@@ -22,19 +22,21 @@ mt.index = 1
2222--- @field node ? vm.node
2323--- @field object ? parser.object
2424--- @field name ? string
25+ --- @field tag ? string
2526--- @field copy ? boolean
2627--- @field ref1 ? vm.runner.step
2728--- @field ref2 ? vm.runner.step
2829
29- --- @param filter parser.object
30- --- @param pos integer
31- function mt :_compileNarrowByFilter (filter , pos )
30+ --- @param filter parser.object
31+ --- @param outStep vm.runner.step
32+ --- @param blockStep vm.runner.step
33+ function mt :_compileNarrowByFilter (filter , outStep , blockStep )
3234 if not filter then
3335 return
3436 end
3537 if filter .type == ' paren' then
3638 if filter .exp then
37- self :_compileNarrowByFilter (filter .exp , pos )
39+ self :_compileNarrowByFilter (filter .exp , outStep , blockStep )
3840 end
3941 return
4042 end
@@ -48,13 +50,14 @@ function mt:_compileNarrowByFilter(filter, pos)
4850 if exp .type == ' getlocal' and exp .node == self .loc then
4951 self .steps [# self .steps + 1 ] = {
5052 type = ' truly' ,
51- pos = pos ,
52- order = 2 ,
53+ pos = filter . finish ,
54+ ref1 = outStep ,
5355 }
5456 self .steps [# self .steps + 1 ] = {
5557 type = ' falsy' ,
56- pos = pos ,
57- order = 4 ,
58+ copy = true ,
59+ pos = filter .finish ,
60+ ref1 = blockStep ,
5861 }
5962 end
6063 end
@@ -65,8 +68,8 @@ function mt:_compileNarrowByFilter(filter, pos)
6568 return
6669 end
6770 if filter .op .type == ' and' then
68- self :_compileNarrowByFilter (filter [1 ], pos )
69- self :_compileNarrowByFilter (filter [2 ], pos )
71+ self :_compileNarrowByFilter (filter [1 ], outStep , blockStep )
72+ self :_compileNarrowByFilter (filter [2 ], outStep , blockStep )
7073 end
7174 if filter .op .type == ' =='
7275 or filter .op .type == ' ~=' then
@@ -86,28 +89,30 @@ function mt:_compileNarrowByFilter(filter, pos)
8689 self .steps [# self .steps + 1 ] = {
8790 type = ' remove' ,
8891 name = exp .type ,
89- pos = pos ,
90- order = 2 ,
92+ pos = filter . finish ,
93+ ref1 = outStep ,
9194 }
9295 self .steps [# self .steps + 1 ] = {
9396 type = ' as' ,
9497 name = exp .type ,
95- pos = pos ,
96- order = 4 ,
98+ copy = true ,
99+ pos = filter .finish ,
100+ ref1 = blockStep ,
97101 }
98102 end
99103 if filter .op .type == ' ~=' then
100104 self .steps [# self .steps + 1 ] = {
101105 type = ' as' ,
102106 name = exp .type ,
103- pos = pos ,
104- order = 2 ,
107+ pos = filter . finish ,
108+ ref1 = outStep ,
105109 }
106110 self .steps [# self .steps + 1 ] = {
107111 type = ' remove' ,
108112 name = exp .type ,
109- pos = pos ,
110- order = 4 ,
113+ copy = true ,
114+ pos = filter .finish ,
115+ ref1 = blockStep ,
111116 }
112117 end
113118 end
@@ -116,13 +121,14 @@ function mt:_compileNarrowByFilter(filter, pos)
116121 if filter .type == ' getlocal' and filter .node == self .loc then
117122 self .steps [# self .steps + 1 ] = {
118123 type = ' falsy' ,
119- pos = pos ,
120- order = 2 ,
124+ pos = filter . finish ,
125+ ref1 = outStep ,
121126 }
122127 self .steps [# self .steps + 1 ] = {
123128 type = ' truly' ,
124- pos = pos ,
125- order = 4 ,
129+ copy = true ,
130+ pos = filter .finish ,
131+ ref1 = blockStep ,
126132 }
127133 end
128134 end
@@ -145,80 +151,56 @@ function mt:_compileBlock(block)
145151 --- @type vm.runner.step[]
146152 local finals = {}
147153 for _ , childBlock in ipairs (block ) do
148- if # childBlock > 0 then
149- local initState = {
150- type = ' save' ,
151- copy = true ,
152- pos = childBlock .start ,
153- order = 1 ,
154- }
155- local outState = {
156- type = ' save' ,
157- copy = true ,
158- pos = childBlock .start ,
159- order = 2 ,
160- }
161- local filterState = {
162- type = ' save' ,
163- copy = true ,
164- pos = childBlock .start ,
165- order = 3 ,
166- }
167- self .steps [# self .steps + 1 ] = initState
168- self .steps [# self .steps + 1 ] = outState
169- self .steps [# self .steps + 1 ] = filterState
170- self .steps [# self .steps + 1 ] = {
171- type = ' load' ,
172- ref1 = outState ,
173- pos = childBlock [1 ].start - 1 ,
174- order = 1 ,
175- }
176- self .steps [# self .steps + 1 ] = {
177- type = ' load' ,
178- ref1 = initState ,
179- pos = childBlock [1 ].start - 1 ,
180- order = 3 ,
181- }
182- self :_compileNarrowByFilter (childBlock .filter , childBlock [1 ].start - 1 )
183- if childBlock .returns then
184- self .steps [# self .steps + 1 ] = {
185- type = ' load' ,
186- ref1 = outState ,
187- pos = childBlock .finish ,
188- order = 1 ,
189- }
190- else
191- local finalState = {
192- type = ' save' ,
193- pos = childBlock .finish ,
194- order = 1 ,
195- }
196- finals [# finals + 1 ] = finalState
197- self .steps [# self .steps + 1 ] = finalState
198- self .steps [# self .steps + 1 ] = {
199- type = ' load' ,
200- ref1 = outState ,
201- pos = childBlock .finish ,
202- order = 2 ,
203- }
204- end
154+ local outStep = {
155+ type = ' save' ,
156+ tag = ' out' ,
157+ copy = true ,
158+ pos = block .start ,
159+ order = 1 ,
160+ }
161+ self .steps [# self .steps + 1 ] = outStep
162+ local blockStep = {
163+ type = ' load' ,
164+ tag = ' block' ,
165+ copy = true ,
166+ ref = outStep ,
167+ pos = childBlock .start ,
168+ order = 2 ,
169+ }
170+ self .steps [# self .steps + 1 ] = blockStep
171+ self :_compileNarrowByFilter (childBlock .filter , outStep , blockStep )
172+ if not childBlock .returns then
173+ finals [# finals + 1 ] = blockStep
205174 end
175+ self .steps [# self .steps + 1 ] = {
176+ type = ' load' ,
177+ tag = ' final' ,
178+ ref1 = outStep ,
179+ pos = childBlock .finish ,
180+ order = 1 ,
181+ }
206182 end
207183 for i , final in ipairs (finals ) do
208184 self .steps [# self .steps + 1 ] = {
209185 type = ' merge' ,
210- ref1 = final ,
186+ ref2 = final ,
211187 pos = block .finish ,
212188 order = i ,
213189 }
214190 end
215191 end
216192
217193 if block .type == ' function' then
194+ self .steps [# self .steps + 1 ] = {
195+ type = ' load' ,
196+ pos = block .start ,
197+ order = 1 ,
198+ }
218199 local savePoint = {
219- type = ' save' ,
220- copy = true ,
221- pos = block .start ,
200+ type = ' save' ,
201+ copy = true ,
202+ pos = block .start ,
203+ order = 2 ,
222204 }
223205 self .steps [# self .steps + 1 ] = savePoint
224206 self .steps [# self .steps + 1 ] = {
@@ -286,34 +268,52 @@ end
286268
287269--- @param callback fun ( src : parser.object , node : vm.node )
288270function mt :launch (callback )
289- local node = vm .getNode (self .loc ):copy ()
271+ local topNode = vm .getNode (self .loc ):copy ()
272+ --- @type vm.runner.step
273+ local context
290274 for _ , step in ipairs (self .steps ) do
275+ local node = (step .ref1 and step .ref1 .node )
276+ or (context and context .node )
277+ or topNode
291278 if step .copy then
292279 node = node :copy ()
280+ if context then
281+ context .node = node
282+ end
293283 end
294284 if step .type == ' truly' then
295285 node :setTruly ()
296286 elseif step .type == ' falsy' then
297287 node :setFalsy ()
298288 elseif step .type == ' as' then
299- node = vm .createNode (globalMgr .getGlobal (' type' , step .name ))
289+ topNode = vm .createNode (globalMgr .getGlobal (' type' , step .name ))
290+ if step .ref1 then
291+ step .ref1 .node = topNode
292+ elseif context then
293+ context .node = topNode
294+ end
300295 elseif step .type == ' add' then
301296 node :merge (globalMgr .getGlobal (' type' , step .name ))
302297 elseif step .type == ' remove' then
303298 node :remove (step .name )
304299 elseif step .type == ' object' then
305- node = callback (step .object , node ) or node
300+ topNode = callback (step .object , node ) or node
306301 if step .object .type == ' getlocal' then
307- node = checkAssert (step .object , node )
302+ topNode = checkAssert (step .object , node )
303+ end
304+ if step .ref1 then
305+ step .ref1 .node = topNode
306+ elseif context then
307+ context .node = topNode
308308 end
309309 elseif step .type == ' save' then
310- -- nothing to do
310+ step . node = node
311311 elseif step .type == ' load' then
312- node = step .ref1 .node
312+ context = step
313+ context .node = node
313314 elseif step .type == ' merge' then
314- node :merge (step .ref1 .node )
315+ node :merge (step .ref2 .node )
315316 end
316- step .node = node
317317 end
318318end
319319
0 commit comments