@@ -16,7 +16,7 @@ mt.index = 1
1616--- @field _hasSorted boolean
1717
1818--- @class vm.runner.step
19- --- @field type ' truthy' | ' falsy' | ' as' | ' add' | ' remove' | ' object' | ' save' | ' load ' | ' merge'
19+ --- @field type ' truthy' | ' falsy' | ' as' | ' add' | ' remove' | ' object' | ' save' | ' push ' | ' merge'
2020--- @field pos integer
2121--- @field order ? integer
2222--- @field node ? vm.node
@@ -49,15 +49,18 @@ function mt:_compileNarrowByFilter(filter, outStep, blockStep)
4949 local exp = filter [1 ]
5050 if exp .type == ' getlocal' and exp .node == self .loc then
5151 self .steps [# self .steps + 1 ] = {
52- type = ' truthy' ,
52+ type = ' push' ,
53+ copy = true ,
5354 pos = filter .finish ,
54- ref1 = outStep ,
5555 }
5656 self .steps [# self .steps + 1 ] = {
5757 type = ' falsy' ,
58- copy = true ,
5958 pos = filter .finish ,
60- ref1 = blockStep ,
59+ }
60+ self .steps [# self .steps + 1 ] = {
61+ type = ' truthy' ,
62+ pos = filter .finish ,
63+ ref1 = outStep ,
6164 }
6265 end
6366 end
@@ -68,31 +71,35 @@ function mt:_compileNarrowByFilter(filter, outStep, blockStep)
6871 return
6972 end
7073 if filter .op .type == ' and' then
71- self :_compileNarrowByFilter (filter [1 ], outStep , blockStep )
72- self :_compileNarrowByFilter (filter [2 ], outStep , blockStep )
73- end
74- if filter .op .type == ' or' then
7574 local dummyStep = {
76- type = ' load' ,
77- tag = ' dummy' ,
75+ type = ' save' ,
7876 copy = true ,
7977 ref1 = outStep ,
8078 pos = filter .start - 1 ,
8179 }
8280 self .steps [# self .steps + 1 ] = dummyStep
83- self :_compileNarrowByFilter (filter [1 ], outStep , dummyStep )
84- dummyStep = {
85- type = ' load' ,
86- tag = ' dummy' ,
81+ self :_compileNarrowByFilter (filter [1 ], dummyStep , blockStep )
82+ self :_compileNarrowByFilter (filter [2 ], dummyStep , blockStep )
83+ end
84+ if filter .op .type == ' or' then
85+ local dummyStep = {
86+ type = ' save' ,
87+ tag = ' dummy out' ,
8788 copy = true ,
8889 ref1 = outStep ,
89- pos = filter .op . finish ,
90+ pos = filter .start - 1 ,
9091 }
9192 self .steps [# self .steps + 1 ] = dummyStep
93+ self :_compileNarrowByFilter (filter [1 ], dummyStep , blockStep )
94+ self .steps [# self .steps + 1 ] = {
95+ type = ' push' ,
96+ ref1 = dummyStep ,
97+ pos = filter .op .finish ,
98+ }
9299 self :_compileNarrowByFilter (filter [2 ], outStep , dummyStep )
93100 self .steps [# self .steps + 1 ] = {
94- type = ' load ' ,
95- tag = ' reset' ,
101+ type = ' push ' ,
102+ tag = ' or reset' ,
96103 ref1 = blockStep ,
97104 pos = filter .finish ,
98105 }
@@ -112,6 +119,11 @@ function mt:_compileNarrowByFilter(filter, outStep, blockStep)
112119 end
113120 if guide .isLiteral (exp ) then
114121 if filter .op .type == ' ==' then
122+ self .steps [# self .steps + 1 ] = {
123+ type = ' push' ,
124+ copy = true ,
125+ pos = filter .finish ,
126+ }
115127 self .steps [# self .steps + 1 ] = {
116128 type = ' remove' ,
117129 name = exp .type ,
@@ -121,12 +133,15 @@ function mt:_compileNarrowByFilter(filter, outStep, blockStep)
121133 self .steps [# self .steps + 1 ] = {
122134 type = ' as' ,
123135 name = exp .type ,
124- copy = true ,
125136 pos = filter .finish ,
126- ref1 = blockStep ,
127137 }
128138 end
129139 if filter .op .type == ' ~=' then
140+ self .steps [# self .steps + 1 ] = {
141+ type = ' push' ,
142+ copy = true ,
143+ pos = filter .finish ,
144+ }
130145 self .steps [# self .steps + 1 ] = {
131146 type = ' as' ,
132147 name = exp .type ,
@@ -136,25 +151,26 @@ function mt:_compileNarrowByFilter(filter, outStep, blockStep)
136151 self .steps [# self .steps + 1 ] = {
137152 type = ' remove' ,
138153 name = exp .type ,
139- copy = true ,
140154 pos = filter .finish ,
141- ref1 = blockStep ,
142155 }
143156 end
144157 end
145158 end
146159 else
147160 if filter .type == ' getlocal' and filter .node == self .loc then
148161 self .steps [# self .steps + 1 ] = {
149- type = ' falsy' ,
162+ type = ' push' ,
163+ copy = true ,
150164 pos = filter .finish ,
151- ref1 = outStep ,
152165 }
153166 self .steps [# self .steps + 1 ] = {
154167 type = ' truthy' ,
155- copy = true ,
156168 pos = filter .finish ,
157- ref1 = blockStep ,
169+ }
170+ self .steps [# self .steps + 1 ] = {
171+ type = ' falsy' ,
172+ pos = filter .finish ,
173+ ref1 = outStep ,
158174 }
159175 end
160176 end
@@ -176,39 +192,56 @@ function mt:_compileBlock(block)
176192 if block .type == ' if' then
177193 --- @type vm.runner.step[]
178194 local finals = {}
179- for _ , childBlock in ipairs (block ) do
180- local outStep = {
195+ for i , childBlock in ipairs (block ) do
196+ local blockStep = {
181197 type = ' save' ,
182- tag = ' out ' ,
198+ tag = ' block ' ,
183199 copy = true ,
184200 pos = block .start ,
185201 }
186- self .steps [# self .steps + 1 ] = outStep
187- local blockStep = {
188- type = ' load' ,
189- tag = ' block' ,
202+ local outStep = {
203+ type = ' save' ,
204+ tag = ' out' ,
190205 copy = true ,
191206 pos = childBlock .start ,
192207 }
193208 self .steps [# self .steps + 1 ] = blockStep
209+ self .steps [# self .steps + 1 ] = outStep
210+ self .steps [# self .steps + 1 ] = {
211+ type = ' push' ,
212+ ref1 = blockStep ,
213+ pos = childBlock .start ,
214+ }
194215 self :_compileNarrowByFilter (childBlock .filter , outStep , blockStep )
195216 if not childBlock .hasReturn
196217 and not childBlock .hasGoTo
197218 and not childBlock .hasBreak then
198- finals [# finals + 1 ] = blockStep
219+ local finalStep = {
220+ type = ' save' ,
221+ pos = childBlock .finish ,
222+ tag = ' final #' .. i ,
223+ }
224+ finals [# finals + 1 ] = finalStep
225+ self .steps [# self .steps + 1 ] = finalStep
199226 end
200227 self .steps [# self .steps + 1 ] = {
201- type = ' load ' ,
202- tag = ' final ' ,
228+ type = ' push ' ,
229+ tag = ' reset child ' ,
203230 ref1 = outStep ,
204231 pos = childBlock .finish ,
205232 }
206233 end
207- for i , final in ipairs (finals ) do
234+ self .steps [# self .steps + 1 ] = {
235+ type = ' push' ,
236+ tag = ' reset if' ,
237+ pos = block .finish ,
238+ copy = true ,
239+ }
240+ for _ , final in ipairs (finals ) do
208241 self .steps [# self .steps + 1 ] = {
209- type = ' merge' ,
210- ref2 = final ,
211- pos = block .finish ,
242+ type = ' merge' ,
243+ ref2 = final ,
244+ pos = block .finish ,
212245 }
213246 end
214247 end
@@ -219,18 +252,19 @@ function mt:_compileBlock(block)
219252 or block .type == ' in'
220253 or block .type == ' repeat'
221254 or block .type == ' for' then
222- self .steps [# self .steps + 1 ] = {
223- type = ' load' ,
224- pos = block .start ,
225- }
226255 local savePoint = {
227- type = ' save' ,
256+ type = ' save' ,
257+ copy = true ,
258+ pos = block .start ,
259+ }
260+ self .steps [# self .steps + 1 ] = {
261+ type = ' push' ,
228262 copy = true ,
229263 pos = block .start ,
230264 }
231265 self .steps [# self .steps + 1 ] = savePoint
232266 self .steps [# self .steps + 1 ] = {
233- type = ' load ' ,
267+ type = ' push ' ,
234268 pos = block .finish ,
235269 ref1 = savePoint ,
236270 }
@@ -300,29 +334,15 @@ end
300334--- @param callback fun ( src : parser.object , node : vm.node )
301335function mt :launch (callback )
302336 local topNode = vm .getNode (self .loc ):copy ()
303- --- @type vm.runner.step
304- local context
305337 for _ , step in ipairs (self .steps ) do
306- local node = (step .ref1 and step .ref1 .node )
307- or (context and context .node )
308- or topNode
309- if step .copy then
310- node = node :copy ()
311- if context then
312- context .node = node
313- end
314- end
338+ local node = step .ref1 and step .ref1 .node or topNode
315339 if step .type == ' truthy' then
316340 node :setTruthy ()
317341 elseif step .type == ' falsy' then
318342 node :setFalsy ()
319343 elseif step .type == ' as' then
320- topNode = vm .createNode (globalMgr .getGlobal (' type' , step .name ))
321- if step .ref1 then
322- step .ref1 .node = topNode
323- elseif context then
324- context .node = topNode
325- end
344+ node :clear ()
345+ node :merge (globalMgr .getGlobal (' type' , step .name ))
326346 elseif step .type == ' add' then
327347 node :merge (globalMgr .getGlobal (' type' , step .name ))
328348 elseif step .type == ' remove' then
@@ -332,16 +352,16 @@ function mt:launch(callback)
332352 if step .object .type == ' getlocal' then
333353 topNode = checkAssert (step .object , node )
334354 end
335- if step .ref1 then
336- step .ref1 .node = topNode
337- elseif context then
338- context .node = topNode
339- end
340355 elseif step .type == ' save' then
356+ if step .copy then
357+ node = node :copy ()
358+ end
341359 step .node = node
342- elseif step .type == ' load' then
343- step .node = node
344- context = step
360+ elseif step .type == ' push' then
361+ if step .copy then
362+ node = node :copy ()
363+ end
364+ topNode = node
345365 elseif step .type == ' merge' then
346366 node :merge (step .ref2 .node )
347367 end
0 commit comments