|
1 | 1 | ---@class vm |
2 | 2 | local vm = require 'vm.vm' |
3 | 3 | local guide = require 'parser.guide' |
| 4 | +local util = require 'utility' |
4 | 5 |
|
5 | 6 | ---@class parser.object |
6 | 7 | ---@field package _tracer? vm.tracer |
@@ -102,106 +103,120 @@ function mt:getLastAssign(block, pos) |
102 | 103 | return assign |
103 | 104 | end |
104 | 105 |
|
105 | | ----@param filter parser.object |
106 | | ----@param node vm.node? |
107 | | ----@return vm.node |
108 | | -function mt:narrowByFilter(filter, node) |
| 106 | +---@param source parser.object |
| 107 | +---@return vm.node? |
| 108 | +function mt:narrow(source) |
| 109 | + local node = self:getNode(source) |
109 | 110 | if not node then |
110 | | - node = vm.createNode() |
111 | | - end |
112 | | - if filter.type == 'filter' then |
113 | | - node = self:narrowByFilter(filter.exp, node) |
114 | | - return node |
| 111 | + return nil |
115 | 112 | end |
116 | | - if filter.type == 'getlocal' then |
117 | | - if filter.node == self.source then |
118 | | - node = node:copy() |
119 | | - node:removeOptional() |
120 | | - end |
| 113 | + |
| 114 | + if source.type == 'getlocal' then |
| 115 | + node = node:copy():setTruthy() |
121 | 116 | return node |
122 | 117 | end |
123 | | - return node |
| 118 | + |
| 119 | + return nil |
124 | 120 | end |
125 | 121 |
|
126 | 122 | ---@param source parser.object |
127 | 123 | ---@return vm.node? |
128 | 124 | function mt:calcNode(source) |
129 | 125 | if source.type == 'getlocal' then |
130 | | - return nil |
131 | | - end |
132 | | - if source.type == 'local' then |
133 | | - if source ~= self.source then |
| 126 | + if source.node ~= self.source then |
134 | 127 | return nil |
135 | 128 | end |
| 129 | + local block = guide.getParentBlock(source) |
| 130 | + if not block then |
| 131 | + return nil |
| 132 | + end |
| 133 | + local lastAssign = self:getLastAssign(block, source.start) |
| 134 | + if lastAssign then |
| 135 | + local node = self:getNode(lastAssign) |
| 136 | + return node |
| 137 | + end |
| 138 | + local parent = source.parent |
| 139 | + while true do |
| 140 | + if parent.type == 'filter' |
| 141 | + or parent.type == 'unary' |
| 142 | + or parent.type == 'ifblock' |
| 143 | + or parent.type == 'elseifblock' then |
| 144 | + parent = parent.parent |
| 145 | + else |
| 146 | + break |
| 147 | + end |
| 148 | + end |
| 149 | + local node = self:getNode(parent) |
| 150 | + return node |
136 | 151 | end |
137 | 152 | if source.type == 'setlocal' then |
138 | 153 | if source.node ~= self.source then |
139 | 154 | return nil |
140 | 155 | end |
| 156 | + local node = vm.compileNode(source) |
| 157 | + return node |
141 | 158 | end |
142 | | - if guide.isSet(source) then |
| 159 | + if source.type == 'local' |
| 160 | + or source.type == 'self' then |
| 161 | + if source ~= self.source then |
| 162 | + return nil |
| 163 | + end |
143 | 164 | local node = vm.compileNode(source) |
144 | 165 | return node |
145 | 166 | end |
| 167 | + if source.type == 'filter' then |
| 168 | + local node = self:narrow(source.exp) |
| 169 | + return node |
| 170 | + end |
146 | 171 | if source.type == 'do' then |
147 | 172 | local lastAssign = self:getLastAssign(source, source.finish) |
148 | | - return self:getNode(lastAssign or source.parent) |
| 173 | + local node = self:getNode(lastAssign or source.parent) |
| 174 | + return node |
149 | 175 | end |
150 | 176 | if source.type == 'ifblock' then |
151 | | - local currentNode = self:getNode(source.parent) |
152 | | - local narrowedNode = self:narrowByFilter(source.filter, currentNode) |
153 | | - return narrowedNode |
| 177 | + local filter = source.filter |
| 178 | + if filter then |
| 179 | + local node = self:getNode(filter) |
| 180 | + return node |
| 181 | + end |
154 | 182 | end |
155 | | - if source.type == 'filter' then |
156 | | - local parent = source.parent |
157 | | - ---@type parser.object |
158 | | - local outBlock |
159 | | - if parent.type == 'ifblock' then |
160 | | - outBlock = parent.parent.parent |
161 | | - local lastAssign = self:getLastAssign(outBlock, parent.start) |
162 | | - return self:getNode(lastAssign or source.parent) |
163 | | - elseif parent.type == 'elseifblock' then |
164 | | - outBlock = parent.parent.parent |
165 | | - local lastAssign = self:getLastAssign(outBlock, parent.start) |
166 | | - return self:getNode(lastAssign or source.parent) |
167 | | - elseif parent.type == 'while' then |
168 | | - outBlock = parent.parent |
169 | | - local lastAssign = self:getLastAssign(outBlock, parent.start) |
170 | | - return self:getNode(lastAssign or source.parent) |
171 | | - elseif parent.type == 'repeat' then |
172 | | - outBlock = parent.parent |
173 | | - local lastAssign = self:getLastAssign(outBlock, parent.start) |
174 | | - return self:getNode(lastAssign or source.parent) |
175 | | - end |
176 | | - assert(outBlock, parent.type) |
| 183 | + if source.type == 'unary' then |
| 184 | + if source.op.type == 'not' then |
| 185 | + local node = self:getNode(source[1]) |
| 186 | + if node then |
| 187 | + node = node:copy() |
| 188 | + node:setFalsy() |
| 189 | + return node |
| 190 | + end |
| 191 | + end |
177 | 192 | end |
178 | | - return nil |
| 193 | + |
| 194 | + local block = guide.getParentBlock(source) |
| 195 | + if not block then |
| 196 | + return nil |
| 197 | + end |
| 198 | + local lastAssign = self:getLastAssign(block, source.start) |
| 199 | + local node = self:getNode(lastAssign or source.parent) |
| 200 | + return node |
179 | 201 | end |
180 | 202 |
|
181 | 203 | ---@param source parser.object |
182 | 204 | ---@return vm.node? |
183 | 205 | function mt:getNode(source) |
184 | | - if self.nodes[source] ~= nil then |
185 | | - return self.nodes[source] or nil |
186 | | - end |
187 | | - local parentBlock = guide.getParentBlock(source) |
188 | | - if not parentBlock then |
189 | | - self.nodes[source] = false |
190 | | - return nil |
| 206 | + local cache = self.nodes[source] |
| 207 | + if cache ~= nil then |
| 208 | + return cache or nil |
191 | 209 | end |
192 | 210 | if source == self.main then |
193 | 211 | self.nodes[source] = false |
194 | 212 | return nil |
195 | 213 | end |
| 214 | + self.nodes[source] = false |
196 | 215 | local node = self:calcNode(source) |
197 | 216 | if node then |
198 | 217 | self.nodes[source] = node |
199 | | - return node |
200 | 218 | end |
201 | | - local lastAssign = self:getLastAssign(parentBlock, source.start) |
202 | | - local parentNode = self:getNode(lastAssign or source.parent) |
203 | | - self.nodes[source] = parentNode or false |
204 | | - return parentNode |
| 219 | + return node |
205 | 220 | end |
206 | 221 |
|
207 | 222 | ---@param source parser.object |
|
0 commit comments