@@ -16,44 +16,61 @@ mt.index = 1
1616--- @field _hasSorted boolean
1717
1818--- @class vm.runner.step
19- --- @field type ' truly' | ' optional ' | ' add' | ' remove' | ' object' | ' save' | ' load'
19+ --- @field type ' truly' | ' falsy ' | ' add' | ' remove' | ' object' | ' save' | ' load' | ' merge '
2020--- @field pos integer
21+ --- @field order ? integer
2122--- @field node ? vm.node
2223--- @field object ? parser.object
23- --- @field ref ? vm.runner.step
2424--- @field name ? string
25+ --- @field copy ? boolean
26+ --- @field ref1 ? vm.runner.step
27+ --- @field ref2 ? vm.runner.step
2528
2629--- @param filter parser.object
2730--- @param pos integer
2831function mt :_compileNarrowByFilter (filter , pos )
2932 if not filter then
3033 return
3134 end
35+ if filter .type == ' paren' then
36+ if filter .exp then
37+ self :_compileNarrowByFilter (filter .exp , pos )
38+ end
39+ return
40+ end
3241 if filter .type == ' unary' then
42+ if filter .op and filter .op .type == ' not' then
43+ local exp = filter [1 ]
44+ if exp and exp .type == ' getlocal' and exp .node == self .loc then
45+ self .steps [# self .steps + 1 ] = {
46+ type = ' truly' ,
47+ pos = pos ,
48+ order = 2 ,
49+ }
50+ self .steps [# self .steps + 1 ] = {
51+ type = ' falsy' ,
52+ pos = pos ,
53+ order = 4 ,
54+ }
55+ end
56+ end
3357 elseif filter .type == ' binary' then
3458 else
3559 if filter .type == ' getlocal' and filter .node == self .loc then
3660 self .steps [# self .steps + 1 ] = {
37- type = ' truly' ,
38- pos = pos ,
61+ type = ' falsy' ,
62+ pos = pos ,
63+ order = 2 ,
64+ }
65+ self .steps [# self .steps + 1 ] = {
66+ type = ' truly' ,
67+ pos = pos ,
68+ order = 4 ,
3969 }
4070 end
4171 end
4272end
4373
44- function mt :_dropBlock (block )
45- local savePoint = {
46- type = ' save' ,
47- pos = block .start ,
48- }
49- self .steps [# self .steps + 1 ] = savePoint
50- self .steps [# self .steps + 1 ] = {
51- type = ' load' ,
52- pos = block .finish ,
53- ref = savePoint ,
54- }
55- end
56-
5774--- @param block parser.object
5875function mt :_compileBlock (block )
5976 if self .blocks [block ] then
@@ -67,19 +84,82 @@ function mt:_compileBlock(block)
6784 local parentBlock = guide .getParentBlock (block )
6885 self :_compileBlock (parentBlock )
6986
70- if block .type == ' ifblock'
71- or block .type == ' elseif' then
72- if block [1 ] then
73- self :_compileNarrowByFilter (block .filter , block [1 ].start )
74- end
75- end
76-
7787 if block .type == ' if' then
78- self :_dropBlock (block )
88+ --- @type vm.runner.step[]
89+ local finals = {}
90+ for _ , childBlock in ipairs (block ) do
91+ if # childBlock > 0 then
92+ local initState = {
93+ type = ' save' ,
94+ copy = true ,
95+ pos = childBlock .start ,
96+ order = 1 ,
97+ }
98+ local outState = {
99+ type = ' save' ,
100+ copy = true ,
101+ pos = childBlock .start ,
102+ order = 2 ,
103+ }
104+ local filterState = {
105+ type = ' save' ,
106+ copy = true ,
107+ pos = childBlock .start ,
108+ order = 3 ,
109+ }
110+ self .steps [# self .steps + 1 ] = initState
111+ self .steps [# self .steps + 1 ] = outState
112+ self .steps [# self .steps + 1 ] = filterState
113+ self .steps [# self .steps + 1 ] = {
114+ type = ' load' ,
115+ ref1 = outState ,
116+ pos = childBlock [1 ].start - 1 ,
117+ order = 1 ,
118+ }
119+ self .steps [# self .steps + 1 ] = {
120+ type = ' load' ,
121+ ref1 = initState ,
122+ pos = childBlock [1 ].start - 1 ,
123+ order = 3 ,
124+ }
125+ self :_compileNarrowByFilter (childBlock .filter , childBlock [1 ].start - 1 )
126+ local finalState = {
127+ type = ' save' ,
128+ pos = childBlock .finish ,
129+ order = 1 ,
130+ }
131+ finals [# finals + 1 ] = finalState
132+ self .steps [# self .steps + 1 ] = finalState
133+ self .steps [# self .steps + 1 ] = {
134+ type = ' load' ,
135+ ref1 = outState ,
136+ pos = childBlock .finish ,
137+ order = 2 ,
138+ }
139+ end
140+ end
141+ for i , final in ipairs (finals ) do
142+ self .steps [# self .steps + 1 ] = {
143+ type = ' merge' ,
144+ ref1 = final ,
145+ pos = block .finish ,
146+ order = i ,
147+ }
148+ end
79149 end
80150
81151 if block .type == ' function' then
82- self :_dropBlock (block )
152+ local savePoint = {
153+ type = ' save' ,
154+ copy = true ,
155+ pos = block .start ,
156+ }
157+ self .steps [# self .steps + 1 ] = savePoint
158+ self .steps [# self .steps + 1 ] = {
159+ type = ' load' ,
160+ pos = block .finish ,
161+ ref1 = savePoint ,
162+ }
83163 end
84164end
85165
@@ -94,28 +174,37 @@ function mt:_preCompile()
94174 self :_compileBlock (block )
95175 end
96176 table.sort (self .steps , function (a , b )
97- return a .pos < b .pos
177+ if a .pos == b .pos then
178+ return (a .order or 0 ) < (b .order or 0 )
179+ else
180+ return a .pos < b .pos
181+ end
98182 end )
99183end
100184
101185--- @param callback fun ( src : parser.object , node : vm.node )
102186function mt :launch (callback )
103- local node = vm .getNode (self .loc )
187+ local node = vm .getNode (self .loc ): copy ()
104188 for _ , step in ipairs (self .steps ) do
189+ if step .copy then
190+ node = node :copy ()
191+ end
105192 if step .type == ' truly' then
106- node = node : copyTruly ()
107- elseif step .type == ' optional ' then
108- node = node : copy (): addOptional ()
193+ node : setTruly ()
194+ elseif step .type == ' falsy ' then
195+ node : setFalsy ()
109196 elseif step .type == ' add' then
110- node = node : copy () :merge (globalMgr .getGlobal (' type' , step .name ))
197+ node :merge (globalMgr .getGlobal (' type' , step .name ))
111198 elseif step .type == ' remove' then
112- node = node : copyWithout (step .name )
199+ node : remove (step .name )
113200 elseif step .type == ' object' then
114201 node = callback (step .object , node ) or node
115202 elseif step .type == ' save' then
116- -- Nothing need to do
203+ -- nothing to do
117204 elseif step .type == ' load' then
118- node = step .ref .node
205+ node = step .ref1 .node
206+ elseif step .type == ' merge' then
207+ node :merge (step .ref1 .node )
119208 end
120209 step .node = node
121210 end
0 commit comments