/src/moddable/xs/sources/xsScope.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2016-2017 Moddable Tech, Inc. |
3 | | * |
4 | | * This file is part of the Moddable SDK Runtime. |
5 | | * |
6 | | * The Moddable SDK Runtime is free software: you can redistribute it and/or modify |
7 | | * it under the terms of the GNU Lesser General Public License as published by |
8 | | * the Free Software Foundation, either version 3 of the License, or |
9 | | * (at your option) any later version. |
10 | | * |
11 | | * The Moddable SDK Runtime is distributed in the hope that it will be useful, |
12 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | | * GNU Lesser General Public License for more details. |
15 | | * |
16 | | * You should have received a copy of the GNU Lesser General Public License |
17 | | * along with the Moddable SDK Runtime. If not, see <http://www.gnu.org/licenses/>. |
18 | | * |
19 | | * This file incorporates work covered by the following copyright and |
20 | | * permission notice: |
21 | | * |
22 | | * Copyright (C) 2010-2016 Marvell International Ltd. |
23 | | * Copyright (C) 2002-2010 Kinoma, Inc. |
24 | | * |
25 | | * Licensed under the Apache License, Version 2.0 (the "License"); |
26 | | * you may not use this file except in compliance with the License. |
27 | | * You may obtain a copy of the License at |
28 | | * |
29 | | * http://www.apache.org/licenses/LICENSE-2.0 |
30 | | * |
31 | | * Unless required by applicable law or agreed to in writing, software |
32 | | * distributed under the License is distributed on an "AS IS" BASIS, |
33 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
34 | | * See the License for the specific language governing permissions and |
35 | | * limitations under the License. |
36 | | */ |
37 | | |
38 | | #include "xsScript.h" |
39 | | |
40 | | #define mxBindHoistPart\ |
41 | | txParser* parser;\ |
42 | | txScope* scope |
43 | | |
44 | | typedef struct sxExportlink txExportLink; |
45 | | |
46 | | typedef struct { |
47 | | mxBindHoistPart; |
48 | | txInteger scopeLevel; |
49 | | txInteger scopeMaximum; |
50 | | txClassNode* classNode; |
51 | | } txBinder; |
52 | | |
53 | | typedef struct { |
54 | | mxBindHoistPart; |
55 | | txScope* functionScope; |
56 | | txScope* bodyScope; |
57 | | txNode* environmentNode; |
58 | | txExportLink* firstExportLink; |
59 | | txClassNode* classNode; |
60 | | } txHoister; |
61 | | |
62 | | struct sxExportlink { |
63 | | txExportLink* next; |
64 | | txSymbol* symbol; |
65 | | }; |
66 | | |
67 | | static void fxHoisterAddExportLink(txHoister* self, txSpecifierNode* specifier); |
68 | | static void fxBinderPopVariables(txBinder* self, txInteger count); |
69 | | static void fxBinderPushVariables(txBinder* self, txInteger count); |
70 | | static txScope* fxScopeNew(txHoister* hoister, txNode* node, txToken token); |
71 | | static void fxScopeAddDeclareNode(txScope* self, txDeclareNode* node); |
72 | | static void fxScopeAddDefineNode(txScope* self, txDefineNode* node); |
73 | | static void fxScopeArrow(txScope* self); |
74 | | static void fxScopeBindDefineNodes(txScope* self, void* param); |
75 | | static void fxScopeBinding(txScope* self, txBinder* binder); |
76 | | static void fxScopeBound(txScope* self, txBinder* binder); |
77 | | static void fxScopeEval(txScope* self); |
78 | | static txDeclareNode* fxScopeGetDeclareNode(txScope* self, txSymbol* symbol); |
79 | | static void fxScopeHoisted(txScope* self, txHoister* hoister); |
80 | | static void fxScopeLookup(txScope* self, txAccessNode* access, txBoolean closureFlag); |
81 | | |
82 | | static void fxNodeDispatchBind(void* it, void* param); |
83 | | static void fxNodeDispatchHoist(void* it, void* param); |
84 | | static void fxFunctionNodeRename(void* it, txSymbol* symbol); |
85 | | |
86 | | void fxParserBind(txParser* parser) |
87 | 0 | { |
88 | 0 | txBinder binder; |
89 | 0 | c_memset(&binder, 0, sizeof(txBinder)); |
90 | 0 | binder.parser = parser; |
91 | 0 | if (parser->errorCount == 0) { |
92 | 0 | mxTryParser(parser) { |
93 | 0 | fxNodeDispatchBind(parser->root, &binder); |
94 | 0 | } |
95 | 0 | mxCatchParser(parser) { |
96 | 0 | } |
97 | 0 | } |
98 | 0 | } |
99 | | |
100 | | void fxParserHoist(txParser* parser) |
101 | 0 | { |
102 | 0 | txHoister hoister; |
103 | 0 | c_memset(&hoister, 0, sizeof(txHoister)); |
104 | 0 | hoister.parser = parser; |
105 | 0 | if (parser->errorCount == 0) { |
106 | 0 | mxTryParser(parser) { |
107 | 0 | fxNodeDispatchHoist(parser->root, &hoister); |
108 | 0 | } |
109 | 0 | mxCatchParser(parser) { |
110 | 0 | } |
111 | 0 | } |
112 | 0 | } |
113 | | |
114 | | void fxHoisterAddExportLink(txHoister* self, txSpecifierNode* specifier) |
115 | 0 | { |
116 | 0 | txExportLink* link = self->firstExportLink; |
117 | 0 | txSymbol* symbol = specifier->asSymbol ? specifier->asSymbol : specifier->symbol; |
118 | 0 | if (symbol) { |
119 | 0 | while (link) { |
120 | 0 | if (link->symbol == symbol) { |
121 | 0 | fxReportParserError(self->parser, specifier->line, "duplicate export %s", symbol->string); |
122 | 0 | return; |
123 | 0 | } |
124 | 0 | link = link->next; |
125 | 0 | } |
126 | 0 | link = fxNewParserChunk(self->parser, sizeof(txExportLink)); |
127 | 0 | link->next = self->firstExportLink; |
128 | 0 | link->symbol = symbol; |
129 | 0 | self->firstExportLink = link; |
130 | 0 | } |
131 | 0 | } |
132 | | |
133 | | void fxBinderPopVariables(txBinder* self, txInteger count) |
134 | 0 | { |
135 | 0 | self->scopeLevel -= count; |
136 | 0 | } |
137 | | |
138 | | void fxBinderPushVariables(txBinder* self, txInteger count) |
139 | 0 | { |
140 | 0 | self->scopeLevel += count; |
141 | 0 | if (self->scopeMaximum < self->scopeLevel) |
142 | 0 | self->scopeMaximum = self->scopeLevel; |
143 | 0 | } |
144 | | |
145 | | txScope* fxScopeNew(txHoister* hoister, txNode* node, txToken token) |
146 | 0 | { |
147 | 0 | txScope* scope = fxNewParserChunkClear(hoister->parser, sizeof(txScope)); |
148 | 0 | scope->parser = hoister->parser; |
149 | 0 | scope->scope = hoister->scope; |
150 | 0 | scope->token = token; |
151 | 0 | scope->flags = node->flags & mxStrictFlag; |
152 | 0 | scope->node = node; |
153 | 0 | hoister->scope = scope; |
154 | 0 | return scope; |
155 | 0 | } |
156 | | |
157 | | void fxScopeAddDeclareNode(txScope* self, txDeclareNode* node) |
158 | 0 | { |
159 | 0 | self->declareNodeCount++; |
160 | 0 | if (self->token == XS_TOKEN_EVAL) { |
161 | 0 | if (self->lastDeclareNode) |
162 | 0 | node->nextDeclareNode = self->firstDeclareNode; |
163 | 0 | else |
164 | 0 | self->lastDeclareNode = node; |
165 | 0 | self->firstDeclareNode = node; |
166 | 0 | } |
167 | 0 | else { |
168 | 0 | if (self->lastDeclareNode) |
169 | 0 | self->lastDeclareNode->nextDeclareNode = node; |
170 | 0 | else |
171 | 0 | self->firstDeclareNode = node; |
172 | 0 | self->lastDeclareNode = node; |
173 | 0 | } |
174 | 0 | if (node->description->token == XS_TOKEN_USING) { |
175 | 0 | txDeclareNode* node = fxDeclareNodeNew(self->parser, XS_TOKEN_CONST, C_NULL); |
176 | 0 | node->flags |= mxDeclareNodeDisposableFlag; |
177 | 0 | fxScopeAddDeclareNode(self, node); |
178 | 0 | self->disposableNodeCount++; |
179 | 0 | } |
180 | 0 | } |
181 | | |
182 | | void fxScopeAddDefineNode(txScope* self, txDefineNode* node) |
183 | 0 | { |
184 | 0 | self->defineNodeCount++; |
185 | 0 | if (self->lastDefineNode) |
186 | 0 | self->lastDefineNode->nextDefineNode = node; |
187 | 0 | else |
188 | 0 | self->firstDefineNode = node; |
189 | 0 | self->lastDefineNode = node; |
190 | 0 | } |
191 | | |
192 | | void fxScopeArrow(txScope* self) |
193 | 0 | { |
194 | 0 | if (self->token == XS_TOKEN_EVAL) { |
195 | 0 | } |
196 | 0 | else if (self->token == XS_TOKEN_FUNCTION) { |
197 | 0 | if (self->node->flags & mxArrowFlag) { |
198 | 0 | self->node->flags |= mxDefaultFlag; |
199 | 0 | if (self->scope) |
200 | 0 | fxScopeArrow(self->scope); |
201 | 0 | } |
202 | 0 | } |
203 | 0 | else if (self->token == XS_TOKEN_PROGRAM) { |
204 | 0 | } |
205 | 0 | else if (self->scope) { |
206 | 0 | fxScopeArrow(self->scope); |
207 | 0 | } |
208 | 0 | } |
209 | | |
210 | | void fxScopeBindDefineNodes(txScope* self, void* param) |
211 | 0 | { |
212 | 0 | txDefineNode* node = self->firstDefineNode; |
213 | 0 | while (node) { |
214 | 0 | fxNodeDispatchBind(node, param); |
215 | 0 | node = node->nextDefineNode; |
216 | 0 | } |
217 | 0 | } |
218 | | |
219 | | void fxScopeBinding(txScope* self, txBinder* binder) |
220 | 0 | { |
221 | 0 | self->scope = binder->scope; |
222 | 0 | binder->scope = self; |
223 | 0 | fxBinderPushVariables(binder, self->declareNodeCount); |
224 | 0 | } |
225 | | |
226 | | void fxScopeBound(txScope* self, txBinder* binder) |
227 | 0 | { |
228 | 0 | if (self->flags & mxEvalFlag) { |
229 | 0 | txDeclareNode* node = self->firstDeclareNode; |
230 | 0 | while (node) { |
231 | 0 | node->flags |= mxDeclareNodeClosureFlag; |
232 | 0 | node = node->nextDeclareNode; |
233 | 0 | } |
234 | 0 | } |
235 | 0 | if (self->token == XS_TOKEN_MODULE) { |
236 | 0 | txDeclareNode* node = self->firstDeclareNode; |
237 | 0 | while (node) { |
238 | 0 | if (!(node->flags & mxDeclareNodeDisposableFlag)) |
239 | 0 | node->flags |= mxDeclareNodeClosureFlag | mxDeclareNodeUseClosureFlag; |
240 | 0 | node = node->nextDeclareNode; |
241 | 0 | } |
242 | 0 | } |
243 | 0 | else if (self->token == XS_TOKEN_PROGRAM) { |
244 | 0 | txDeclareNode* node = self->firstDeclareNode; |
245 | 0 | while (node) { |
246 | 0 | node->flags |= mxDeclareNodeClosureFlag | mxDeclareNodeUseClosureFlag; |
247 | 0 | node = node->nextDeclareNode; |
248 | 0 | } |
249 | 0 | } |
250 | 0 | binder->scopeLevel += self->closureNodeCount; |
251 | 0 | binder->scopeMaximum += self->closureNodeCount; |
252 | 0 | fxBinderPopVariables(binder, self->declareNodeCount); |
253 | 0 | binder->scope = self->scope; |
254 | 0 | } |
255 | | |
256 | | void fxScopeEval(txScope* self) |
257 | 0 | { |
258 | 0 | while (self) { |
259 | 0 | self->flags |= mxEvalFlag; |
260 | 0 | self = self->scope; |
261 | 0 | } |
262 | 0 | } |
263 | | |
264 | | txDeclareNode* fxScopeGetDeclareNode(txScope* self, txSymbol* symbol) |
265 | 0 | { |
266 | 0 | txDeclareNode* node = self->firstDeclareNode; |
267 | 0 | while (node) { |
268 | 0 | if (node->symbol == symbol) |
269 | 0 | return node; |
270 | 0 | node = node->nextDeclareNode; |
271 | 0 | } |
272 | 0 | return NULL; |
273 | 0 | } |
274 | | |
275 | | void fxScopeHoisted(txScope* self, txHoister* hoister) |
276 | 0 | { |
277 | 0 | if (self->token == XS_TOKEN_BLOCK) { |
278 | 0 | txDeclareNode** address = &self->firstDeclareNode; |
279 | 0 | txDeclareNode* node; |
280 | 0 | txDeclareNode* last = C_NULL; |
281 | 0 | while ((node = *address)) { |
282 | 0 | if (node->description->token == XS_NO_TOKEN) { |
283 | 0 | self->declareNodeCount--; |
284 | 0 | *address = node->nextDeclareNode; |
285 | 0 | } |
286 | 0 | else { |
287 | 0 | address = &node->nextDeclareNode; |
288 | 0 | last = node; |
289 | 0 | } |
290 | 0 | } |
291 | 0 | self->lastDeclareNode = last; |
292 | 0 | } |
293 | 0 | else if (self->token == XS_TOKEN_PROGRAM) { |
294 | 0 | txDeclareNode* node = self->firstDeclareNode; |
295 | 0 | while (node) { |
296 | 0 | if ((node->description->token == XS_TOKEN_DEFINE) || (node->description->token == XS_TOKEN_VAR)) |
297 | 0 | self->declareNodeCount--; |
298 | 0 | node = node->nextDeclareNode; |
299 | 0 | } |
300 | 0 | } |
301 | 0 | else if (self->token == XS_TOKEN_EVAL) { |
302 | 0 | if (!(self->flags & mxStrictFlag)) { |
303 | 0 | txDeclareNode* node = self->firstDeclareNode; |
304 | 0 | while (node) { |
305 | 0 | if ((node->description->token == XS_TOKEN_DEFINE) || (node->description->token == XS_TOKEN_VAR)) |
306 | 0 | self->declareNodeCount--; |
307 | 0 | node = node->nextDeclareNode; |
308 | 0 | } |
309 | 0 | } |
310 | 0 | } |
311 | 0 | hoister->scope = self->scope; |
312 | 0 | } |
313 | | |
314 | | void fxScopeLookup(txScope* self, txAccessNode* access, txBoolean closureFlag) |
315 | 0 | { |
316 | 0 | txDeclareNode* declaration; |
317 | 0 | if (self->token == XS_TOKEN_EVAL) { |
318 | 0 | declaration = fxScopeGetDeclareNode(self, access->symbol); |
319 | 0 | if (declaration) { |
320 | 0 | if ((!(self->flags & mxStrictFlag)) && ((declaration->description->token == XS_TOKEN_VAR) || (declaration->description->token == XS_TOKEN_DEFINE))) { |
321 | 0 | declaration = C_NULL; |
322 | 0 | } |
323 | 0 | else if (closureFlag) |
324 | 0 | declaration->flags |= mxDeclareNodeClosureFlag; |
325 | 0 | } |
326 | 0 | else if ((self->flags & mxStrictFlag) && (access->description->token == XS_TOKEN_PRIVATE_MEMBER)) { |
327 | 0 | declaration = fxDeclareNodeNew(self->parser, XS_TOKEN_PRIVATE, access->symbol); |
328 | 0 | declaration->flags |= mxDeclareNodeClosureFlag; |
329 | 0 | declaration->line = access->line; |
330 | 0 | fxScopeAddDeclareNode(self, declaration); |
331 | 0 | self->closureNodeCount++; |
332 | 0 | } |
333 | 0 | access->declaration = declaration; |
334 | 0 | } |
335 | 0 | else if (self->token == XS_TOKEN_FUNCTION) { |
336 | 0 | declaration = fxScopeGetDeclareNode(self, access->symbol); |
337 | 0 | if (declaration) { |
338 | 0 | if (closureFlag) |
339 | 0 | declaration->flags |= mxDeclareNodeClosureFlag; |
340 | 0 | access->declaration = declaration; |
341 | 0 | } |
342 | 0 | else if ((self->node->flags & mxEvalFlag) && !(self->node->flags & mxStrictFlag)) { |
343 | | // eval can create variables that override closures |
344 | 0 | access->declaration = C_NULL; |
345 | 0 | } |
346 | 0 | else if (self->scope) { |
347 | 0 | fxScopeLookup(self->scope, access, 1); |
348 | 0 | if (access->declaration) { |
349 | 0 | txDeclareNode* closureNode = fxDeclareNodeNew(self->parser, XS_NO_TOKEN, access->symbol); |
350 | 0 | closureNode->flags |= mxDeclareNodeClosureFlag | mxDeclareNodeUseClosureFlag; |
351 | 0 | closureNode->line = access->declaration->line; |
352 | 0 | closureNode->declaration = access->declaration; |
353 | 0 | fxScopeAddDeclareNode(self, closureNode); |
354 | 0 | self->closureNodeCount++; |
355 | 0 | access->declaration = closureNode; |
356 | 0 | } |
357 | 0 | } |
358 | 0 | } |
359 | 0 | else if (self->token == XS_TOKEN_PROGRAM) { |
360 | 0 | declaration = fxScopeGetDeclareNode(self, access->symbol); |
361 | 0 | if (declaration && ((declaration->description->token == XS_TOKEN_VAR) || (declaration->description->token == XS_TOKEN_DEFINE))) { |
362 | 0 | declaration = C_NULL; |
363 | 0 | } |
364 | 0 | access->declaration = declaration; |
365 | 0 | } |
366 | 0 | else if (self->token == XS_TOKEN_WITH) { |
367 | | // with object can have properties that override variables |
368 | 0 | access->declaration = C_NULL; |
369 | 0 | } |
370 | 0 | else { |
371 | 0 | declaration = fxScopeGetDeclareNode(self, access->symbol); |
372 | 0 | if (declaration) { |
373 | 0 | if (closureFlag) |
374 | 0 | declaration->flags |= mxDeclareNodeClosureFlag; |
375 | 0 | access->declaration = declaration; |
376 | 0 | } |
377 | 0 | else if (self->scope) { |
378 | 0 | fxScopeLookup(self->scope, access, closureFlag); |
379 | 0 | } |
380 | 0 | else { |
381 | 0 | access->declaration = C_NULL; |
382 | 0 | access->symbol->usage |= 2; |
383 | 0 | } |
384 | 0 | } |
385 | 0 | } |
386 | | |
387 | | void fxNodeHoist(void* it, void* param) |
388 | 0 | { |
389 | 0 | txNode* node = it; |
390 | 0 | (*node->description->dispatch->distribute)(node, fxNodeDispatchHoist, param); |
391 | 0 | } |
392 | | |
393 | | void fxNodeDispatchHoist(void* it, void* param) |
394 | 0 | { |
395 | 0 | txNode* node = it; |
396 | 0 | fxCheckParserStack(((txHoister*)param)->parser, node->line); |
397 | 0 | (*node->description->dispatch->hoist)(it, param); |
398 | 0 | } |
399 | | |
400 | | void fxBlockNodeHoist(void* it, void* param) |
401 | 0 | { |
402 | 0 | txBlockNode* self = it; |
403 | 0 | self->scope = fxScopeNew(param, it, XS_TOKEN_BLOCK); |
404 | 0 | fxNodeDispatchHoist(self->statement, param); |
405 | 0 | fxScopeHoisted(self->scope, param); |
406 | 0 | } |
407 | | |
408 | | void fxBodyNodeHoist(void* it, void* param) |
409 | 0 | { |
410 | 0 | txBlockNode* self = it; |
411 | 0 | txHoister* hoister = param; |
412 | 0 | txNode* environmentNode = hoister->environmentNode; |
413 | 0 | hoister->bodyScope = self->scope = fxScopeNew(param, it, XS_TOKEN_BLOCK); |
414 | 0 | hoister->environmentNode = it; |
415 | 0 | fxNodeDispatchHoist(self->statement, param); |
416 | 0 | hoister->environmentNode = environmentNode; |
417 | 0 | fxScopeHoisted(self->scope, param); |
418 | 0 | } |
419 | | |
420 | | void fxCallNodeHoist(void* it, void* param) |
421 | 0 | { |
422 | 0 | txCallNewNode* self = it; |
423 | 0 | txHoister* hoister = param; |
424 | 0 | txParser* parser = hoister->parser; |
425 | 0 | if (self->reference->description->token == XS_TOKEN_ACCESS) { |
426 | 0 | txAccessNode* access = (txAccessNode*)self->reference; |
427 | 0 | if (access->symbol == parser->evalSymbol) { |
428 | 0 | fxScopeEval(hoister->scope); |
429 | 0 | hoister->functionScope->node->flags |= mxArgumentsFlag | mxEvalFlag; |
430 | 0 | hoister->environmentNode->flags |= mxEvalFlag; |
431 | 0 | self->params->flags |= mxEvalParametersFlag; |
432 | 0 | } |
433 | 0 | } |
434 | 0 | fxNodeDispatchHoist(self->reference, param); |
435 | 0 | fxNodeDispatchHoist(self->params, param); |
436 | 0 | } |
437 | | |
438 | | void fxCatchNodeHoist(void* it, void* param) |
439 | 0 | { |
440 | 0 | txCatchNode* self = it; |
441 | 0 | txHoister* hoister = param; |
442 | 0 | txDeclareNode* node; |
443 | 0 | if (self->parameter) { |
444 | 0 | self->scope = fxScopeNew(param, it, XS_TOKEN_BLOCK); |
445 | 0 | fxNodeDispatchHoist(self->parameter, param); |
446 | 0 | self->statementScope = fxScopeNew(param, it, XS_TOKEN_BLOCK); |
447 | 0 | fxNodeDispatchHoist(self->statement, param); |
448 | 0 | fxScopeHoisted(self->statementScope, param); |
449 | 0 | fxScopeHoisted(self->scope, param); |
450 | 0 | node = self->statementScope->firstDeclareNode; |
451 | 0 | while (node) { |
452 | 0 | if (fxScopeGetDeclareNode(self->scope, node->symbol)) |
453 | 0 | fxReportParserError(hoister->parser, node->line, "duplicate variable %s", node->symbol->string); |
454 | 0 | node = node->nextDeclareNode; |
455 | 0 | } |
456 | 0 | } |
457 | 0 | else { |
458 | 0 | self->statementScope = fxScopeNew(param, it, XS_TOKEN_BLOCK); |
459 | 0 | fxNodeDispatchHoist(self->statement, param); |
460 | 0 | fxScopeHoisted(self->statementScope, param); |
461 | 0 | } |
462 | 0 | } |
463 | | |
464 | | void fxClassNodeHoist(void* it, void* param) |
465 | 0 | { |
466 | 0 | txClassNode* self = it; |
467 | 0 | txHoister* hoister = param; |
468 | 0 | txClassNode* former = hoister->classNode; |
469 | 0 | txNode* item = self->items->first; |
470 | 0 | if (self->symbol) { |
471 | 0 | txDeclareNode* node = fxDeclareNodeNew(hoister->parser, XS_TOKEN_CONST, self->symbol); |
472 | 0 | node->flags |= mxDeclareNodeClosureFlag; |
473 | 0 | self->symbolScope = fxScopeNew(hoister, it, XS_TOKEN_BLOCK); |
474 | 0 | fxScopeAddDeclareNode(self->symbolScope, node); |
475 | 0 | } |
476 | 0 | if (self->heritage) |
477 | 0 | fxNodeDispatchHoist(self->heritage, param); |
478 | 0 | self->scope = fxScopeNew(hoister, it, XS_TOKEN_BLOCK); |
479 | 0 | while (item) { |
480 | 0 | if (item->description->token == XS_TOKEN_PROPERTY) { |
481 | 0 | } |
482 | 0 | else if (item->description->token == XS_TOKEN_PROPERTY_AT) { |
483 | 0 | if (item->flags & (mxMethodFlag | mxGetterFlag | mxSetterFlag)) { |
484 | 0 | } |
485 | 0 | else { |
486 | 0 | txSymbol* symbol = fxNewParserChunkClear(hoister->parser, sizeof(txSymbol)); |
487 | 0 | txDeclareNode* node = fxDeclareNodeNew(hoister->parser, XS_TOKEN_CONST, symbol); |
488 | 0 | symbol->ID = -1; |
489 | 0 | node->flags |= mxDeclareNodeClosureFlag; |
490 | 0 | fxScopeAddDeclareNode(self->scope, node); |
491 | 0 | ((txPropertyAtNode*)item)->atAccess = fxAccessNodeNew(hoister->parser, XS_TOKEN_ACCESS, symbol); |
492 | 0 | } |
493 | 0 | } |
494 | 0 | else { |
495 | 0 | txSymbol* symbol = ((txPrivatePropertyNode*)item)->symbol; |
496 | 0 | txDeclareNode* node = fxScopeGetDeclareNode(self->scope, symbol); |
497 | 0 | if (node) { |
498 | 0 | txUnsigned flags = (node->flags & (mxStaticFlag | mxGetterFlag | mxSetterFlag)) ^ (item->flags & (mxStaticFlag | mxGetterFlag | mxSetterFlag)); |
499 | 0 | if ((flags != (mxGetterFlag | mxSetterFlag))) |
500 | 0 | fxReportParserError(hoister->parser, item->line, "duplicate %s", symbol->string); |
501 | 0 | } |
502 | 0 | node = fxDeclareNodeNew(hoister->parser, XS_TOKEN_CONST, symbol); |
503 | 0 | node->flags |= mxDeclareNodeClosureFlag | (item->flags & (mxStaticFlag | mxGetterFlag | mxSetterFlag)); |
504 | 0 | fxScopeAddDeclareNode(self->scope, node); |
505 | 0 | ((txPrivatePropertyNode*)item)->symbolAccess = fxAccessNodeNew(hoister->parser, XS_TOKEN_ACCESS, symbol); |
506 | 0 | if (item->flags & (mxMethodFlag | mxGetterFlag | mxSetterFlag)) { |
507 | 0 | txSymbol* symbol = fxNewParserChunkClear(hoister->parser, sizeof(txSymbol)); |
508 | 0 | txDeclareNode* node = fxDeclareNodeNew(hoister->parser, XS_TOKEN_CONST, symbol); |
509 | 0 | symbol->ID = -1; |
510 | 0 | node->flags |= mxDeclareNodeClosureFlag; |
511 | 0 | fxScopeAddDeclareNode(self->scope, node); |
512 | 0 | ((txPrivatePropertyNode*)item)->valueAccess = fxAccessNodeNew(hoister->parser, XS_TOKEN_ACCESS, symbol); |
513 | 0 | } |
514 | 0 | } |
515 | 0 | item = item->next; |
516 | 0 | } |
517 | 0 | if (self->instanceInit) { |
518 | 0 | txSymbol* symbol = fxNewParserChunkClear(hoister->parser, sizeof(txSymbol)); |
519 | 0 | txDeclareNode* node = fxDeclareNodeNew(hoister->parser, XS_TOKEN_CONST, symbol); |
520 | 0 | symbol->ID = -1; |
521 | 0 | node->flags |= mxDeclareNodeClosureFlag; |
522 | 0 | fxScopeAddDeclareNode(self->scope, node); |
523 | 0 | self->instanceInitAccess = fxAccessNodeNew(hoister->parser, XS_TOKEN_ACCESS, symbol); |
524 | 0 | } |
525 | 0 | hoister->classNode = self; |
526 | 0 | fxNodeDispatchHoist(self->constructor, param); |
527 | 0 | fxNodeListDistribute(self->items, fxNodeDispatchHoist, param); |
528 | 0 | if (self->constructorInit) |
529 | 0 | fxNodeDispatchHoist(self->constructorInit, param); |
530 | 0 | if (self->instanceInit) |
531 | 0 | fxNodeDispatchHoist(self->instanceInit, param); |
532 | 0 | hoister->classNode = former; |
533 | 0 | fxScopeHoisted(self->scope, param); |
534 | 0 | if (self->symbol) |
535 | 0 | fxScopeHoisted(self->symbolScope, param); |
536 | 0 | } |
537 | | |
538 | | void fxCoalesceExpressionNodeHoist(void* it, void* param) |
539 | 0 | { |
540 | 0 | txBinaryExpressionNode* self = it; |
541 | 0 | txHoister* hoister = param; |
542 | 0 | txToken leftToken = self->left->description->token; |
543 | 0 | txToken rightToken = self->right->description->token; |
544 | 0 | if ((leftToken == XS_TOKEN_AND) || (rightToken == XS_TOKEN_AND)) |
545 | 0 | fxReportParserError(hoister->parser, self->line, "missing () around &&"); |
546 | 0 | else if ((leftToken == XS_TOKEN_OR) || (rightToken == XS_TOKEN_OR)) |
547 | 0 | fxReportParserError(hoister->parser, self->line, "missing () around ||"); |
548 | 0 | fxNodeDispatchHoist(self->left, param); |
549 | 0 | fxNodeDispatchHoist(self->right, param); |
550 | 0 | } |
551 | | |
552 | | void fxDeclareNodeHoist(void* it, void* param) |
553 | 0 | { |
554 | 0 | txDeclareNode* self = it; |
555 | 0 | txHoister* hoister = param; |
556 | 0 | txDeclareNode* node; |
557 | 0 | txScope* scope; |
558 | 0 | if (self->description->token == XS_TOKEN_ARG) { |
559 | 0 | node = fxScopeGetDeclareNode(hoister->functionScope, self->symbol); |
560 | 0 | if (node) { |
561 | 0 | if ((node->description->token == XS_TOKEN_ARG) && (hoister->functionScope->node->flags & (mxArrowFlag | mxAsyncFlag | mxMethodFlag | mxNotSimpleParametersFlag | mxStrictFlag))) |
562 | 0 | fxReportParserError(hoister->parser, self->line, "duplicate argument %s", self->symbol->string); |
563 | 0 | } |
564 | 0 | else { |
565 | 0 | fxScopeAddDeclareNode(hoister->functionScope, self); |
566 | 0 | } |
567 | 0 | } |
568 | 0 | else if ((self->description->token == XS_TOKEN_CONST) || (self->description->token == XS_TOKEN_LET) || (self->description->token == XS_TOKEN_USING)) { |
569 | 0 | node = fxScopeGetDeclareNode(hoister->scope, self->symbol); |
570 | 0 | if (!node && (hoister->scope == hoister->bodyScope)) { |
571 | 0 | node = fxScopeGetDeclareNode(hoister->functionScope, self->symbol); |
572 | 0 | if (node && (node->description->token != XS_TOKEN_ARG)) |
573 | 0 | node = C_NULL; |
574 | 0 | } |
575 | 0 | if (node) |
576 | 0 | fxReportParserError(hoister->parser, self->line, "duplicate variable %s", self->symbol->string); |
577 | 0 | else |
578 | 0 | fxScopeAddDeclareNode(hoister->scope, self); |
579 | 0 | } |
580 | 0 | else { |
581 | 0 | scope = hoister->scope; |
582 | 0 | node = C_NULL; |
583 | 0 | while (scope != hoister->bodyScope) { |
584 | 0 | node = fxScopeGetDeclareNode(scope, self->symbol); |
585 | 0 | if (node) { |
586 | 0 | if ((node->description->token == XS_TOKEN_CONST) || (node->description->token == XS_TOKEN_LET) || (node->description->token == XS_TOKEN_USING) || (node->description->token == XS_TOKEN_DEFINE)) |
587 | 0 | break; |
588 | 0 | node = C_NULL; |
589 | 0 | } |
590 | 0 | scope = scope->scope; |
591 | 0 | } |
592 | 0 | if (!node) { |
593 | 0 | node = fxScopeGetDeclareNode(scope, self->symbol); |
594 | 0 | if (node) { |
595 | 0 | if ((node->description->token != XS_TOKEN_CONST) && (node->description->token != XS_TOKEN_LET) && (node->description->token != XS_TOKEN_USING)) |
596 | 0 | node = C_NULL; |
597 | 0 | } |
598 | 0 | } |
599 | 0 | if (node) |
600 | 0 | fxReportParserError(hoister->parser, self->line, "duplicate variable %s", self->symbol->string); |
601 | 0 | else { |
602 | 0 | node = fxScopeGetDeclareNode(hoister->functionScope, self->symbol); |
603 | 0 | if (!node || ((node->description->token != XS_TOKEN_ARG) && (node->description->token != XS_TOKEN_VAR))) |
604 | 0 | fxScopeAddDeclareNode(hoister->bodyScope, self); |
605 | 0 | scope = hoister->scope; |
606 | 0 | while (scope != hoister->bodyScope) { |
607 | 0 | fxScopeAddDeclareNode(scope, fxDeclareNodeNew(hoister->parser, XS_NO_TOKEN, self->symbol)); |
608 | 0 | scope = scope->scope; |
609 | 0 | } |
610 | 0 | } |
611 | 0 | } |
612 | 0 | } |
613 | | |
614 | | void fxDefineNodeHoist(void* it, void* param) |
615 | 0 | { |
616 | 0 | txDefineNode* self = it; |
617 | 0 | txHoister* hoister = param; |
618 | 0 | txDeclareNode* node; |
619 | 0 | if (self->flags & mxStrictFlag) { |
620 | 0 | if ((self->symbol == hoister->parser->argumentsSymbol) || (self->symbol == hoister->parser->evalSymbol) || (self->symbol == hoister->parser->yieldSymbol)) |
621 | 0 | fxReportParserError(hoister->parser, self->line, "invalid definition %s", self->symbol->string); |
622 | 0 | } |
623 | 0 | if ((hoister->scope == hoister->bodyScope) && (hoister->scope->token != XS_TOKEN_MODULE)) { |
624 | 0 | node = fxScopeGetDeclareNode(hoister->bodyScope, self->symbol); |
625 | 0 | if (node) { |
626 | 0 | if ((node->description->token == XS_TOKEN_CONST) || (node->description->token == XS_TOKEN_LET)) |
627 | 0 | fxReportParserError(hoister->parser, self->line, "duplicate variable %s", self->symbol->string); |
628 | 0 | } |
629 | 0 | else { |
630 | 0 | if (hoister->functionScope != hoister->bodyScope) |
631 | 0 | node = fxScopeGetDeclareNode(hoister->functionScope, self->symbol); |
632 | 0 | if (!node) |
633 | 0 | fxScopeAddDeclareNode(hoister->bodyScope, (txDeclareNode*)self); |
634 | 0 | } |
635 | 0 | fxScopeAddDefineNode(hoister->bodyScope, self); |
636 | 0 | } |
637 | 0 | else { |
638 | 0 | node = fxScopeGetDeclareNode(hoister->scope, self->symbol); |
639 | 0 | if (node) |
640 | 0 | fxReportParserError(hoister->parser, self->line, "duplicate variable %s", self->symbol->string); |
641 | 0 | else |
642 | 0 | fxScopeAddDeclareNode(hoister->scope, (txDeclareNode*)self); |
643 | 0 | fxScopeAddDefineNode(hoister->scope, self); |
644 | 0 | } |
645 | 0 | ((txFunctionNode*)(self->initializer))->symbol = C_NULL; |
646 | 0 | fxNodeDispatchHoist(self->initializer, param); |
647 | 0 | ((txFunctionNode*)(self->initializer))->symbol = self->symbol; |
648 | 0 | } |
649 | | |
650 | | void fxExportNodeHoist(void* it, void* param) |
651 | 0 | { |
652 | 0 | txExportNode* self = it; |
653 | 0 | txHoister* hoister = param; |
654 | 0 | if (self->from) { |
655 | 0 | if (self->specifiers && self->specifiers->length) { |
656 | 0 | txSpecifierNode* specifier = (txSpecifierNode*)self->specifiers->first; |
657 | 0 | while (specifier) { |
658 | 0 | txDeclareNode* node = fxDeclareNodeNew(hoister->parser, XS_TOKEN_LET, C_NULL); |
659 | 0 | specifier->from = self->from; |
660 | 0 | specifier->with = self->with; |
661 | 0 | node->flags |= mxDeclareNodeClosureFlag | mxDeclareNodeUseClosureFlag; |
662 | 0 | node->line = self->line; |
663 | 0 | node->importSpecifier = specifier; |
664 | 0 | node->firstExportSpecifier = specifier; |
665 | 0 | fxScopeAddDeclareNode(hoister->scope, node); |
666 | 0 | specifier = (txSpecifierNode*)specifier->next; |
667 | 0 | } |
668 | 0 | } |
669 | 0 | else { |
670 | 0 | txSpecifierNode* specifier = fxSpecifierNodeNew(hoister->parser, XS_TOKEN_SPECIFIER); |
671 | 0 | txDeclareNode* node = fxDeclareNodeNew(hoister->parser, XS_TOKEN_LET, C_NULL); |
672 | 0 | specifier->from = self->from; |
673 | 0 | specifier->with = self->with; |
674 | 0 | node->flags |= mxDeclareNodeClosureFlag | mxDeclareNodeUseClosureFlag; |
675 | 0 | node->line = self->line; |
676 | 0 | node->importSpecifier = specifier; |
677 | 0 | node->firstExportSpecifier = C_NULL; |
678 | 0 | fxScopeAddDeclareNode(hoister->scope, node); |
679 | 0 | } |
680 | 0 | } |
681 | 0 | if (self->specifiers && self->specifiers->length) { |
682 | 0 | txSpecifierNode* specifier = (txSpecifierNode*)self->specifiers->first; |
683 | 0 | while (specifier) { |
684 | 0 | fxHoisterAddExportLink(hoister, specifier); |
685 | 0 | fxNodeDispatchHoist(specifier, param); |
686 | 0 | specifier = (txSpecifierNode*)specifier->next; |
687 | 0 | } |
688 | 0 | } |
689 | 0 | } |
690 | | |
691 | | void fxForNodeHoist(void* it, void* param) |
692 | 0 | { |
693 | 0 | txForNode* self = it; |
694 | 0 | self->scope = fxScopeNew(param, it, XS_TOKEN_BLOCK); |
695 | 0 | if (self->initialization) |
696 | 0 | fxNodeDispatchHoist(self->initialization, param); |
697 | 0 | if (self->expression) |
698 | 0 | fxNodeDispatchHoist(self->expression, param); |
699 | 0 | if (self->iteration) |
700 | 0 | fxNodeDispatchHoist(self->iteration, param); |
701 | 0 | fxNodeDispatchHoist(self->statement, param); |
702 | 0 | fxScopeHoisted(self->scope, param); |
703 | 0 | } |
704 | | |
705 | | void fxForInForOfNodeHoist(void* it, void* param) |
706 | 0 | { |
707 | 0 | txForInForOfNode* self = it; |
708 | 0 | self->scope = fxScopeNew(param, it, XS_TOKEN_BLOCK); |
709 | 0 | fxNodeDispatchHoist(self->reference, param); |
710 | 0 | fxNodeDispatchHoist(self->expression, param); |
711 | 0 | fxNodeDispatchHoist(self->statement, param); |
712 | 0 | fxScopeHoisted(self->scope, param); |
713 | 0 | } |
714 | | |
715 | | void fxFunctionNodeHoist(void* it, void* param) |
716 | 0 | { |
717 | 0 | txFunctionNode* self = it; |
718 | 0 | txHoister* hoister = param; |
719 | 0 | txScope* functionScope = hoister->functionScope; |
720 | 0 | txScope* bodyScope = hoister->bodyScope; |
721 | 0 | hoister->functionScope = self->scope = fxScopeNew(param, it, XS_TOKEN_FUNCTION); |
722 | 0 | hoister->bodyScope = C_NULL; |
723 | 0 | if (self->symbol) { |
724 | 0 | txDefineNode* node = fxDefineNodeNew(hoister->parser, XS_TOKEN_CONST, self->symbol); |
725 | 0 | node->initializer = fxValueNodeNew(hoister->parser, XS_TOKEN_CURRENT); |
726 | 0 | fxScopeAddDeclareNode(hoister->functionScope, (txDeclareNode*)node); |
727 | 0 | fxScopeAddDefineNode(hoister->functionScope, node); |
728 | 0 | } |
729 | 0 | fxNodeDispatchHoist(self->params, param); |
730 | 0 | if ((self->flags & (mxArgumentsFlag | mxEvalFlag)) && !(self->flags & mxArrowFlag)) { |
731 | 0 | txDeclareNode* declaration = fxDeclareNodeNew(hoister->parser, XS_TOKEN_VAR, hoister->parser->argumentsSymbol); |
732 | 0 | fxScopeAddDeclareNode(hoister->functionScope, declaration); |
733 | 0 | } |
734 | 0 | fxNodeDispatchHoist(self->body, param); |
735 | 0 | fxScopeHoisted(self->scope, param); |
736 | 0 | hoister->bodyScope = bodyScope; |
737 | 0 | hoister->functionScope = functionScope; |
738 | 0 | } |
739 | | |
740 | | txHostNode* fxHostNodeClone(txParser* parser, txHostNode* self) |
741 | 0 | { |
742 | 0 | txHostNode* node = fxNewParserChunkClear(parser, sizeof(txHostNode)); |
743 | 0 | c_memcpy(node, self, sizeof(txHostNode)); |
744 | 0 | return node; |
745 | 0 | } |
746 | | |
747 | | void fxHostNodeHoist(void* it, void* param) |
748 | 0 | { |
749 | 0 | txHostNode* self = it; |
750 | 0 | txHoister* hoister = param; |
751 | 0 | txScope* scope = hoister->bodyScope; |
752 | 0 | self->hostIndex = -1; |
753 | 0 | if ((scope->token != XS_TOKEN_MODULE) && (scope->token != XS_TOKEN_PROGRAM)) { |
754 | 0 | txParser* parser = hoister->parser; |
755 | 0 | while ((scope->token != XS_TOKEN_MODULE) && (scope->token != XS_TOKEN_PROGRAM)) |
756 | 0 | scope = scope->scope; |
757 | 0 | snprintf(parser->buffer, parser->bufferSize, "@%s", self->at->value); |
758 | 0 | txSymbol* symbol = fxNewParserSymbol(parser, parser->buffer); |
759 | 0 | if (!fxScopeGetDeclareNode(scope, symbol)) { |
760 | 0 | txDefineNode* definition = fxDefineNodeNew(parser, XS_TOKEN_DEFINE, symbol); |
761 | 0 | definition->initializer = (txNode*)fxHostNodeClone(parser, self); |
762 | 0 | fxScopeAddDeclareNode(scope, (txDeclareNode*)definition); |
763 | 0 | fxScopeAddDefineNode(scope, definition); |
764 | 0 | } |
765 | 0 | txAccessNode* access = it; |
766 | 0 | access->description = &gxTokenDescriptions[XS_TOKEN_ACCESS]; |
767 | 0 | access->symbol = symbol; |
768 | 0 | access->initializer = C_NULL; |
769 | 0 | access->declaration = C_NULL; |
770 | 0 | } |
771 | 0 | } |
772 | | |
773 | | void fxImportNodeHoist(void* it, void* param) |
774 | 0 | { |
775 | 0 | txImportNode* self = it; |
776 | 0 | txHoister* hoister = param; |
777 | 0 | if (self->specifiers && self->specifiers->length) { |
778 | 0 | txSpecifierNode* specifier = (txSpecifierNode*)self->specifiers->first; |
779 | 0 | while (specifier) { |
780 | 0 | txDeclareNode* node; |
781 | 0 | txSymbol* symbol = specifier->asSymbol ? specifier->asSymbol : specifier->symbol; |
782 | 0 | if (self->flags & mxStrictFlag) { |
783 | 0 | if ((symbol == hoister->parser->argumentsSymbol) || (symbol == hoister->parser->evalSymbol)) |
784 | 0 | fxReportParserError(hoister->parser, self->line, "invalid import %s", symbol->string); |
785 | 0 | } |
786 | 0 | node = fxScopeGetDeclareNode(hoister->scope, symbol); |
787 | 0 | if (node) |
788 | 0 | fxReportParserError(hoister->parser, self->line, "duplicate variable %s", symbol->string); |
789 | 0 | else { |
790 | 0 | specifier->declaration = node = fxDeclareNodeNew(hoister->parser, XS_TOKEN_LET, symbol); |
791 | 0 | specifier->from = self->from; |
792 | 0 | specifier->with = self->with; |
793 | 0 | node->flags |= mxDeclareNodeClosureFlag | mxDeclareNodeUseClosureFlag; |
794 | 0 | node->line = self->line; |
795 | 0 | node->importSpecifier = specifier; |
796 | 0 | fxScopeAddDeclareNode(hoister->scope, node); |
797 | 0 | } |
798 | 0 | specifier = (txSpecifierNode*)specifier->next; |
799 | 0 | } |
800 | 0 | } |
801 | 0 | else { |
802 | 0 | txSpecifierNode* specifier = fxSpecifierNodeNew(hoister->parser, XS_TOKEN_SPECIFIER); |
803 | 0 | txDeclareNode* node = fxDeclareNodeNew(hoister->parser, XS_TOKEN_LET, C_NULL); |
804 | 0 | specifier->from = self->from; |
805 | 0 | specifier->with = self->with; |
806 | 0 | node->flags |= mxDeclareNodeClosureFlag | mxDeclareNodeUseClosureFlag; |
807 | 0 | node->line = self->line; |
808 | 0 | node->importSpecifier = specifier; |
809 | 0 | fxScopeAddDeclareNode(hoister->scope, node); |
810 | 0 | } |
811 | 0 | } |
812 | | |
813 | | void fxModuleNodeHoist(void* it, void* param) |
814 | 0 | { |
815 | 0 | txModuleNode* self = it; |
816 | 0 | txHoister* hoister = param; |
817 | 0 | hoister->functionScope = hoister->bodyScope = self->scope = fxScopeNew(param, it, XS_TOKEN_MODULE); // @@ |
818 | 0 | hoister->environmentNode = it; |
819 | 0 | fxNodeDispatchHoist(self->body, param); |
820 | 0 | hoister->environmentNode = C_NULL; |
821 | 0 | fxScopeHoisted(self->scope, param); |
822 | 0 | } |
823 | | |
824 | | void fxParamsBindingNodeHoist(void* it, void* param) |
825 | 0 | { |
826 | 0 | txParamsNode* self = it; |
827 | 0 | txNode* item = self->items->first; |
828 | 0 | while (item) { |
829 | 0 | fxNodeDispatchHoist(item, param); |
830 | 0 | item = item->next; |
831 | 0 | } |
832 | 0 | } |
833 | | |
834 | | void fxProgramNodeHoist(void* it, void* param) |
835 | 0 | { |
836 | 0 | txProgramNode* self = it; |
837 | 0 | txHoister* hoister = param; |
838 | 0 | hoister->functionScope = hoister->bodyScope = self->scope = fxScopeNew(param, it, (hoister->parser->flags & mxEvalFlag) ? XS_TOKEN_EVAL : XS_TOKEN_PROGRAM); |
839 | 0 | hoister->environmentNode = it; |
840 | 0 | fxNodeDispatchHoist(self->body, param); |
841 | 0 | hoister->environmentNode = C_NULL; |
842 | 0 | self->variableCount = hoister->functionScope->declareNodeCount; |
843 | 0 | fxScopeHoisted(self->scope, param); |
844 | 0 | } |
845 | | |
846 | | void fxStatementNodeHoist(void* it, void* param) |
847 | 0 | { |
848 | 0 | txStatementNode* self = it; |
849 | 0 | fxNodeDispatchHoist(self->expression, param); |
850 | 0 | } |
851 | | |
852 | | void fxPropertyNodeHoist(void* it, void* param) |
853 | 0 | { |
854 | 0 | txPropertyNode* self = it; |
855 | 0 | if (self->value) { |
856 | 0 | if (self->value->description->token == XS_TOKEN_HOST) |
857 | 0 | ((txHostNode*)(self->value))->symbol = self->symbol; |
858 | 0 | fxNodeDispatchHoist(self->value, param); |
859 | 0 | } |
860 | 0 | } |
861 | | |
862 | | void fxStringNodeHoist(void* it, void* param) |
863 | 0 | { |
864 | 0 | txStringNode* self = it; |
865 | 0 | txHoister* hoister = param; |
866 | 0 | if ((self->flags & mxStringLegacyFlag) && (hoister->scope->flags & mxStrictFlag)) |
867 | 0 | self->flags |= mxStringErrorFlag; |
868 | 0 | } |
869 | | |
870 | | void fxSwitchNodeHoist(void* it, void* param) |
871 | 0 | { |
872 | 0 | txSwitchNode* self = it; |
873 | 0 | fxNodeDispatchHoist(self->expression, param); |
874 | 0 | self->scope = fxScopeNew(param, it, XS_TOKEN_BLOCK); |
875 | 0 | fxNodeListDistribute(self->items, fxNodeDispatchHoist, param); |
876 | 0 | fxScopeHoisted(self->scope, param); |
877 | 0 | } |
878 | | |
879 | | void fxWithNodeHoist(void* it, void* param) |
880 | 0 | { |
881 | 0 | txWithNode* self = it; |
882 | 0 | txHoister* hoister = param; |
883 | 0 | fxNodeDispatchHoist(self->expression, param); |
884 | 0 | self->scope = fxScopeNew(param, it, XS_TOKEN_WITH); |
885 | 0 | fxScopeEval(hoister->scope); |
886 | 0 | fxNodeDispatchHoist(self->statement, param); |
887 | 0 | fxScopeHoisted(self->scope, param); |
888 | 0 | } |
889 | | |
890 | | void fxNodeDispatchBind(void* it, void* param) |
891 | 0 | { |
892 | 0 | txNode* node = it; |
893 | 0 | fxCheckParserStack(((txBinder*)param)->parser, node->line); |
894 | 0 | (*node->description->dispatch->bind)(it, param); |
895 | 0 | } |
896 | | |
897 | | void fxNodeBind(void* it, void* param) |
898 | 0 | { |
899 | 0 | txNode* node = it; |
900 | 0 | (*node->description->dispatch->distribute)(node, fxNodeDispatchBind, param); |
901 | 0 | } |
902 | | |
903 | | void fxAccessNodeBind(void* it, void* param) |
904 | 0 | { |
905 | 0 | txAccessNode* self = it; |
906 | 0 | txBinder* binder = param; |
907 | 0 | fxScopeLookup(binder->scope, (txAccessNode*)self, 0); |
908 | 0 | } |
909 | | |
910 | | void fxArrayNodeBind(void* it, void* param) |
911 | 0 | { |
912 | 0 | txArrayNode* self = it; |
913 | 0 | fxBinderPushVariables(param, 1); |
914 | 0 | if (self->flags & mxSpreadFlag) { |
915 | 0 | fxBinderPushVariables(param, 2); |
916 | 0 | fxNodeListDistribute(self->items, fxNodeDispatchBind, param); |
917 | 0 | fxBinderPopVariables(param, 2); |
918 | 0 | } |
919 | 0 | else |
920 | 0 | fxNodeListDistribute(self->items, fxNodeDispatchBind, param); |
921 | 0 | fxBinderPopVariables(param, 1); |
922 | 0 | } |
923 | | |
924 | | void fxArrayBindingNodeBind(void* it, void* param) |
925 | 0 | { |
926 | 0 | txArrayBindingNode* self = it; |
927 | 0 | fxBinderPushVariables(param, 6); |
928 | 0 | fxNodeListDistribute(self->items, fxNodeDispatchBind, param); |
929 | 0 | fxBinderPopVariables(param, 6); |
930 | 0 | } |
931 | | |
932 | | void fxAssignNodeBind(void* it, void* param) |
933 | 0 | { |
934 | 0 | txAssignNode* self = it; |
935 | 0 | txToken token = self->reference->description->token; |
936 | 0 | fxNodeDispatchBind(self->reference, param); |
937 | 0 | if ((token == XS_TOKEN_ACCESS) || (token == XS_TOKEN_ARG) || (token == XS_TOKEN_CONST) || (token == XS_TOKEN_LET) || (token == XS_TOKEN_USING) || (token == XS_TOKEN_VAR)) |
938 | 0 | fxFunctionNodeRename(self->value, ((txAccessNode*)self->reference)->symbol); |
939 | 0 | fxNodeDispatchBind(self->value, param); |
940 | 0 | } |
941 | | |
942 | | void fxBindingNodeBind(void* it, void* param) |
943 | 0 | { |
944 | 0 | txBindingNode* self = it; |
945 | 0 | txToken token = self->target->description->token; |
946 | 0 | fxNodeDispatchBind(self->target, param); |
947 | 0 | if ((token == XS_TOKEN_ACCESS) || (token == XS_TOKEN_ARG) || (token == XS_TOKEN_CONST) || (token == XS_TOKEN_LET) || (token == XS_TOKEN_USING) || (token == XS_TOKEN_VAR)) |
948 | 0 | fxFunctionNodeRename(self->initializer, ((txAccessNode*)self->target)->symbol); |
949 | 0 | fxNodeDispatchBind(self->initializer, param); |
950 | 0 | } |
951 | | |
952 | | void fxBlockNodeBind(void* it, void* param) |
953 | 0 | { |
954 | 0 | txBlockNode* self = it; |
955 | 0 | fxScopeBinding(self->scope, param); |
956 | 0 | fxScopeBindDefineNodes(self->scope, param); |
957 | 0 | if (self->scope->disposableNodeCount) |
958 | 0 | fxBinderPushVariables(param, 2); |
959 | 0 | fxNodeDispatchBind(self->statement, param); |
960 | 0 | if (self->scope->disposableNodeCount) |
961 | 0 | fxBinderPopVariables(param, 2); |
962 | 0 | fxScopeBound(self->scope, param); |
963 | 0 | } |
964 | | |
965 | | void fxCatchNodeBind(void* it, void* param) |
966 | 0 | { |
967 | 0 | txCatchNode* self = it; |
968 | 0 | if (self->parameter) { |
969 | 0 | fxScopeBinding(self->scope, param); |
970 | 0 | fxNodeDispatchBind(self->parameter, param); |
971 | 0 | fxScopeBinding(self->statementScope, param); |
972 | 0 | fxScopeBindDefineNodes(self->statementScope, param); |
973 | 0 | if (self->statementScope->disposableNodeCount) |
974 | 0 | fxBinderPushVariables(param, 2); |
975 | 0 | fxNodeDispatchBind(self->statement, param); |
976 | 0 | if (self->statementScope->disposableNodeCount) |
977 | 0 | fxBinderPushVariables(param, 2); |
978 | 0 | fxScopeBound(self->statementScope, param); |
979 | 0 | fxScopeBound(self->scope, param); |
980 | 0 | } |
981 | 0 | else { |
982 | 0 | fxScopeBinding(self->statementScope, param); |
983 | 0 | fxScopeBindDefineNodes(self->statementScope, param); |
984 | 0 | if (self->statementScope->disposableNodeCount) |
985 | 0 | fxBinderPushVariables(param, 2); |
986 | 0 | fxNodeDispatchBind(self->statement, param); |
987 | 0 | if (self->statementScope->disposableNodeCount) |
988 | 0 | fxBinderPushVariables(param, 2); |
989 | 0 | fxScopeBound(self->statementScope, param); |
990 | 0 | } |
991 | 0 | } |
992 | | |
993 | | void fxClassNodeBind(void* it, void* param) |
994 | 0 | { |
995 | 0 | txClassNode* self = it; |
996 | 0 | txBinder* binder = param; |
997 | 0 | txClassNode* former = binder->classNode; |
998 | 0 | fxBinderPushVariables(param, 2); |
999 | 0 | if (self->symbol) |
1000 | 0 | fxScopeBinding(self->symbolScope, param); |
1001 | 0 | if (self->heritage) |
1002 | 0 | fxNodeDispatchBind(self->heritage, param); |
1003 | 0 | fxScopeBinding(self->scope, param); |
1004 | 0 | binder->classNode = self; |
1005 | 0 | fxNodeDispatchBind(self->constructor, param); |
1006 | 0 | fxNodeListDistribute(self->items, fxNodeDispatchBind, param); |
1007 | 0 | if (self->constructorInit) |
1008 | 0 | fxNodeDispatchBind(self->constructorInit, param); |
1009 | 0 | if (self->instanceInit) |
1010 | 0 | fxNodeDispatchBind(self->instanceInit, param); |
1011 | 0 | binder->classNode = former; |
1012 | 0 | fxScopeBound(self->scope, param); |
1013 | 0 | if (self->symbol) |
1014 | 0 | fxScopeBound(self->symbolScope, param); |
1015 | 0 | fxBinderPopVariables(param, 2); |
1016 | 0 | } |
1017 | | |
1018 | | void fxDeclareNodeBind(void* it, void* param) |
1019 | 0 | { |
1020 | 0 | txBindingNode* self = it; |
1021 | 0 | txBinder* binder = param; |
1022 | 0 | fxScopeLookup(binder->scope, (txAccessNode*)self, 0); |
1023 | 0 | } |
1024 | | |
1025 | | void fxDefineNodeBind(void* it, void* param) |
1026 | 0 | { |
1027 | 0 | txDefineNode* self = it; |
1028 | 0 | txBinder* binder = param; |
1029 | 0 | if (self->flags & mxDefineNodeBoundFlag) |
1030 | 0 | return; |
1031 | 0 | self->flags |= mxDefineNodeBoundFlag; |
1032 | 0 | fxScopeLookup(binder->scope, (txAccessNode*)self, 0); |
1033 | 0 | fxNodeDispatchBind(self->initializer, param); |
1034 | 0 | } |
1035 | | |
1036 | | void fxDelegateNodeBind(void* it, void* param) |
1037 | 0 | { |
1038 | 0 | txStatementNode* self = it; |
1039 | 0 | fxBinderPushVariables(param, 5); |
1040 | 0 | fxNodeDispatchBind(self->expression, param); |
1041 | 0 | fxBinderPopVariables(param, 5); |
1042 | 0 | } |
1043 | | |
1044 | | void fxExportNodeBind(void* it, void* param) |
1045 | 0 | { |
1046 | 0 | txExportNode* self = it; |
1047 | 0 | txBinder* binder = param; |
1048 | 0 | if (self->from) |
1049 | 0 | return; |
1050 | 0 | if (self->specifiers) { |
1051 | 0 | txSpecifierNode* specifier = (txSpecifierNode*)self->specifiers->first; |
1052 | 0 | while (specifier) { |
1053 | 0 | txAccessNode* node = fxAccessNodeNew(binder->parser, XS_TOKEN_ACCESS, specifier->symbol); |
1054 | 0 | fxScopeLookup(binder->scope, node, 0); |
1055 | 0 | if (node->declaration) { |
1056 | 0 | specifier->declaration = node->declaration; |
1057 | 0 | specifier->declaration->flags |= mxDeclareNodeClosureFlag | mxDeclareNodeUseClosureFlag; |
1058 | 0 | specifier->nextSpecifier = specifier->declaration->firstExportSpecifier; |
1059 | 0 | specifier->declaration->firstExportSpecifier = specifier; |
1060 | 0 | } |
1061 | 0 | else |
1062 | 0 | fxReportParserError(binder->parser, specifier->line, "unknown variable %s", specifier->symbol->string); |
1063 | 0 | specifier = (txSpecifierNode*)specifier->next; |
1064 | 0 | } |
1065 | 0 | } |
1066 | 0 | } |
1067 | | |
1068 | | void fxFieldNodeBind(void* it, void* param) |
1069 | 0 | { |
1070 | 0 | txFieldNode* self = it; |
1071 | 0 | txBinder* binder = param; |
1072 | 0 | txNode* item = self->item; |
1073 | 0 | if (item->description->token == XS_TOKEN_PROPERTY_AT) |
1074 | 0 | fxScopeLookup(binder->scope, ((txPropertyAtNode*)item)->atAccess, 0); |
1075 | 0 | else if (item->description->token == XS_TOKEN_PRIVATE_PROPERTY) { |
1076 | 0 | if (item->flags & (mxMethodFlag | mxGetterFlag | mxSetterFlag)) |
1077 | 0 | fxScopeLookup(binder->scope, ((txPrivatePropertyNode*)item)->valueAccess, 0); |
1078 | 0 | fxScopeLookup(binder->scope, ((txPrivatePropertyNode*)item)->symbolAccess, 0); |
1079 | 0 | } |
1080 | 0 | if (self->value) |
1081 | 0 | fxNodeDispatchBind(self->value, param); |
1082 | 0 | } |
1083 | | |
1084 | | void fxForNodeBind(void* it, void* param) |
1085 | 0 | { |
1086 | 0 | txForNode* self = it; |
1087 | 0 | fxScopeBinding(self->scope, param); |
1088 | 0 | fxScopeBindDefineNodes(self->scope, param); |
1089 | 0 | if (self->scope->disposableNodeCount) |
1090 | 0 | fxBinderPushVariables(param, 2); |
1091 | 0 | if (self->initialization) |
1092 | 0 | fxNodeDispatchBind(self->initialization, param); |
1093 | 0 | if (self->expression) |
1094 | 0 | fxNodeDispatchBind(self->expression, param); |
1095 | 0 | if (self->iteration) |
1096 | 0 | fxNodeDispatchBind(self->iteration, param); |
1097 | 0 | fxNodeDispatchBind(self->statement, param); |
1098 | 0 | if (self->scope->disposableNodeCount) |
1099 | 0 | fxBinderPopVariables(param, 2); |
1100 | 0 | fxScopeBound(self->scope, param); |
1101 | 0 | } |
1102 | | |
1103 | | void fxForInForOfNodeBind(void* it, void* param) |
1104 | 0 | { |
1105 | 0 | txForInForOfNode* self = it; |
1106 | 0 | fxBinderPushVariables(param, 6); |
1107 | 0 | fxScopeBinding(self->scope, param); |
1108 | 0 | fxScopeBindDefineNodes(self->scope, param); |
1109 | 0 | fxNodeDispatchBind(self->reference, param); |
1110 | 0 | fxNodeDispatchBind(self->expression, param); |
1111 | 0 | fxNodeDispatchBind(self->statement, param); |
1112 | 0 | fxScopeBound(self->scope, param); |
1113 | 0 | fxBinderPopVariables(param, 6); |
1114 | 0 | } |
1115 | | |
1116 | | void fxFunctionNodeBind(void* it, void* param) |
1117 | 0 | { |
1118 | 0 | txFunctionNode* self = it; |
1119 | 0 | txBinder* binder = param; |
1120 | 0 | txInteger scopeLevel = binder->scopeLevel; |
1121 | 0 | txInteger scopeMaximum = binder->scopeMaximum; |
1122 | 0 | scopeLevel = binder->scopeLevel; |
1123 | 0 | scopeMaximum = binder->scopeMaximum; |
1124 | 0 | binder->scopeLevel = 0; |
1125 | 0 | binder->scopeMaximum = 0; |
1126 | 0 | fxScopeBinding(self->scope, param); |
1127 | 0 | fxNodeDispatchBind(self->params, param); |
1128 | 0 | if (self->flags & mxBaseFlag) { |
1129 | 0 | if (binder->classNode->instanceInitAccess) { |
1130 | 0 | fxScopeLookup(binder->scope, binder->classNode->instanceInitAccess, 0); |
1131 | 0 | } |
1132 | 0 | } |
1133 | 0 | fxScopeBindDefineNodes(self->scope, param); |
1134 | 0 | fxNodeDispatchBind(self->body, param); |
1135 | 0 | fxScopeBound(self->scope, param); |
1136 | 0 | self->scopeCount = binder->scopeMaximum; |
1137 | 0 | binder->scopeMaximum = scopeMaximum; |
1138 | 0 | binder->scopeLevel = scopeLevel; |
1139 | 0 | } |
1140 | | |
1141 | | void fxFunctionNodeRename(void* it, txSymbol* symbol) |
1142 | 0 | { |
1143 | 0 | txNode* self = it; |
1144 | 0 | txToken token = self->description->token; |
1145 | 0 | if (token == XS_TOKEN_EXPRESSIONS) { |
1146 | 0 | self = ((txExpressionsNode*)self)->items->first; |
1147 | 0 | if (self->next) |
1148 | 0 | return; |
1149 | 0 | token = self->description->token; |
1150 | 0 | } |
1151 | 0 | if (token == XS_TOKEN_CLASS) { |
1152 | 0 | txClassNode* node = (txClassNode*)self; |
1153 | 0 | if (!node->symbol) |
1154 | 0 | ((txFunctionNode*)(node->constructor))->symbol = symbol; |
1155 | 0 | } |
1156 | 0 | else if ((token == XS_TOKEN_FUNCTION) || (token == XS_TOKEN_GENERATOR) || (token == XS_TOKEN_HOST)) { |
1157 | 0 | txFunctionNode* node = (txFunctionNode*)self; |
1158 | 0 | if (!node->symbol) |
1159 | 0 | node->symbol = symbol; |
1160 | 0 | } |
1161 | 0 | } |
1162 | | |
1163 | | void fxHostNodeBind(void* it, void* param) |
1164 | 0 | { |
1165 | 0 | } |
1166 | | |
1167 | | void fxModuleNodeBind(void* it, void* param) |
1168 | 0 | { |
1169 | 0 | txModuleNode* self = it; |
1170 | 0 | txBinder* binder = param; |
1171 | 0 | fxScopeBinding(self->scope, param); |
1172 | 0 | fxScopeBindDefineNodes(self->scope, param); |
1173 | 0 | fxNodeDispatchBind(self->body, param); |
1174 | 0 | fxScopeBound(self->scope, param); |
1175 | 0 | self->scopeCount = binder->scopeMaximum; |
1176 | 0 | } |
1177 | | |
1178 | | void fxObjectNodeBind(void* it, void* param) |
1179 | 0 | { |
1180 | 0 | txObjectNode* self = it; |
1181 | 0 | txNode* item = self->items->first; |
1182 | 0 | fxBinderPushVariables(param, 1); |
1183 | 0 | while (item) { |
1184 | 0 | txNode* value; |
1185 | 0 | if (item->description->token == XS_TOKEN_SPREAD) { |
1186 | 0 | } |
1187 | 0 | else { |
1188 | 0 | if (item->description->token == XS_TOKEN_PROPERTY) { |
1189 | 0 | value = ((txPropertyNode*)item)->value; |
1190 | 0 | } |
1191 | 0 | else { |
1192 | 0 | value = ((txPropertyAtNode*)item)->value; |
1193 | 0 | } |
1194 | 0 | if ((value->description->token == XS_TOKEN_FUNCTION) || (value->description->token == XS_TOKEN_GENERATOR) || (value->description->token == XS_TOKEN_HOST)) { |
1195 | 0 | txFunctionNode* node = (txFunctionNode*)value; |
1196 | 0 | node->flags |= item->flags & (mxMethodFlag | mxGetterFlag | mxSetterFlag); |
1197 | 0 | } |
1198 | 0 | else if (value->description->token == XS_TOKEN_CLASS) { |
1199 | | // txFunctionNode* node = (txFunctionNode*)(((txClassNode*)value)->constructor); |
1200 | 0 | } |
1201 | 0 | } |
1202 | 0 | fxNodeDispatchBind(item, param); |
1203 | 0 | item = item->next; |
1204 | 0 | } |
1205 | 0 | fxBinderPopVariables(param, 1); |
1206 | 0 | } |
1207 | | |
1208 | | void fxObjectBindingNodeBind(void* it, void* param) |
1209 | 0 | { |
1210 | 0 | txObjectBindingNode* self = it; |
1211 | 0 | fxBinderPushVariables(param, 2); |
1212 | 0 | fxNodeListDistribute(self->items, fxNodeDispatchBind, param); |
1213 | 0 | fxBinderPopVariables(param, 2); |
1214 | 0 | } |
1215 | | |
1216 | | void fxParamsNodeBind(void* it, void* param) |
1217 | 0 | { |
1218 | 0 | txParamsNode* self = it; |
1219 | 0 | if (self->flags & mxSpreadFlag) { |
1220 | 0 | fxBinderPushVariables(param, 1); |
1221 | 0 | fxNodeListDistribute(self->items, fxNodeDispatchBind, param); |
1222 | 0 | fxBinderPopVariables(param, 1); |
1223 | 0 | } |
1224 | 0 | else |
1225 | 0 | fxNodeListDistribute(self->items, fxNodeDispatchBind, param); |
1226 | 0 | } |
1227 | | |
1228 | | void fxParamsBindingNodeBind(void* it, void* param) |
1229 | 0 | { |
1230 | 0 | txParamsBindingNode* self = it; |
1231 | 0 | txBinder* binder = param; |
1232 | 0 | txScope* functionScope = binder->scope; |
1233 | 0 | txFunctionNode* functionNode = (txFunctionNode*)(functionScope->node); |
1234 | 0 | txInteger count = self->items->length; |
1235 | 0 | if (functionNode->flags & mxGetterFlag) { |
1236 | 0 | if (count != 0) |
1237 | 0 | fxReportParserError(binder->parser, self->line, "invalid getter arguments"); |
1238 | 0 | } |
1239 | 0 | else if (functionNode->flags & mxSetterFlag) { |
1240 | 0 | if ((count != 1) || (self->items->first->description->token == XS_TOKEN_REST_BINDING)) |
1241 | 0 | fxReportParserError(binder->parser, self->line, "invalid setter arguments"); |
1242 | 0 | } |
1243 | 0 | else { |
1244 | 0 | if (count > 255) |
1245 | 0 | fxReportParserError(binder->parser, self->line, "too many arguments"); |
1246 | 0 | } |
1247 | 0 | if (functionNode->flags & mxArgumentsFlag) { |
1248 | 0 | txNode* item; |
1249 | 0 | self->declaration = fxScopeGetDeclareNode(functionScope, binder->parser->argumentsSymbol); |
1250 | 0 | if (functionNode->flags & mxStrictFlag) |
1251 | 0 | goto bail; |
1252 | 0 | item = self->items->first; |
1253 | 0 | while (item) { |
1254 | 0 | if (item->description->token != XS_TOKEN_ARG) |
1255 | 0 | goto bail; |
1256 | 0 | item = item->next; |
1257 | 0 | } |
1258 | 0 | item = self->items->first; |
1259 | 0 | while (item) { |
1260 | 0 | ((txDeclareNode*)item)->flags |= mxDeclareNodeClosureFlag; |
1261 | 0 | item = item->next; |
1262 | 0 | } |
1263 | 0 | self->mapped = 1; |
1264 | 0 | } |
1265 | 0 | bail: |
1266 | 0 | fxNodeListDistribute(self->items, fxNodeDispatchBind, param); |
1267 | 0 | } |
1268 | | |
1269 | | void fxPostfixExpressionNodeBind(void* it, void* param) |
1270 | 0 | { |
1271 | 0 | txPostfixExpressionNode* self = it; |
1272 | 0 | fxNodeDispatchBind(self->left, param); |
1273 | 0 | fxBinderPushVariables(param, 1); |
1274 | 0 | fxBinderPopVariables(param, 1); |
1275 | 0 | } |
1276 | | |
1277 | | void fxPrivateMemberNodeBind(void* it, void* param) |
1278 | 0 | { |
1279 | 0 | txBinder* binder = param; |
1280 | 0 | txPrivateMemberNode* self = it; |
1281 | 0 | fxScopeLookup(binder->scope, (txAccessNode*)self, 0); |
1282 | 0 | if (!self->declaration) |
1283 | 0 | fxReportParserError(binder->parser, self->line, "invalid private identifier"); |
1284 | 0 | fxNodeDispatchBind(self->reference, param); |
1285 | 0 | } |
1286 | | |
1287 | | void fxProgramNodeBind(void* it, void* param) |
1288 | 0 | { |
1289 | 0 | txProgramNode* self = it; |
1290 | 0 | txBinder* binder = param; |
1291 | 0 | fxScopeBinding(self->scope, param); |
1292 | 0 | fxScopeBindDefineNodes(self->scope, param); |
1293 | 0 | fxNodeDispatchBind(self->body, param); |
1294 | 0 | fxScopeBound(self->scope, param); |
1295 | 0 | self->scopeCount = binder->scopeMaximum; |
1296 | 0 | } |
1297 | | |
1298 | | void fxSpreadNodeBind(void* it, void* param) |
1299 | 0 | { |
1300 | 0 | txSpreadNode* self = it; |
1301 | 0 | fxBinderPushVariables(param, 1); |
1302 | 0 | fxNodeDispatchBind(self->expression, param); |
1303 | 0 | fxBinderPopVariables(param, 1); |
1304 | 0 | } |
1305 | | |
1306 | | void fxSuperNodeBind(void* it, void* param) |
1307 | 0 | { |
1308 | 0 | txSuperNode* self = it; |
1309 | 0 | txBinder* binder = param; |
1310 | 0 | fxScopeArrow(binder->scope); |
1311 | 0 | fxNodeDispatchBind(self->params, param); |
1312 | 0 | if (binder->classNode->instanceInitAccess) { |
1313 | 0 | self->instanceInitAccess = fxAccessNodeNew(binder->parser, XS_TOKEN_ACCESS, binder->classNode->instanceInitAccess->symbol); |
1314 | 0 | fxScopeLookup(binder->scope, self->instanceInitAccess, 0); |
1315 | 0 | } |
1316 | 0 | } |
1317 | | |
1318 | | void fxSwitchNodeBind(void* it, void* param) |
1319 | 0 | { |
1320 | 0 | txSwitchNode* self = it; |
1321 | 0 | fxNodeDispatchBind(self->expression, param); |
1322 | 0 | fxScopeBinding(self->scope, param); |
1323 | 0 | fxScopeBindDefineNodes(self->scope, param); |
1324 | 0 | if (self->scope->disposableNodeCount) |
1325 | 0 | fxBinderPushVariables(param, 2); |
1326 | 0 | fxNodeListDistribute(self->items, fxNodeDispatchBind, param); |
1327 | 0 | if (self->scope->disposableNodeCount) |
1328 | 0 | fxBinderPopVariables(param, 2); |
1329 | 0 | fxScopeBound(self->scope, param); |
1330 | 0 | } |
1331 | | |
1332 | | void fxTargetNodeBind(void* it, void* param) |
1333 | 0 | { |
1334 | 0 | txBinder* binder = param; |
1335 | 0 | fxScopeArrow(binder->scope); |
1336 | 0 | } |
1337 | | |
1338 | | void fxTemplateNodeBind(void* it, void* param) |
1339 | 0 | { |
1340 | 0 | txTemplateNode* self = it; |
1341 | 0 | if (self->reference) { |
1342 | 0 | fxBinderPushVariables(param, 2); |
1343 | 0 | fxNodeDispatchBind(self->reference, param); |
1344 | 0 | fxNodeListDistribute(self->items, fxNodeDispatchBind, param); |
1345 | 0 | fxBinderPopVariables(param, 2); |
1346 | 0 | } |
1347 | 0 | else { |
1348 | 0 | fxNodeListDistribute(self->items, fxNodeDispatchBind, param); |
1349 | 0 | } |
1350 | 0 | } |
1351 | | |
1352 | | void fxThisNodeBind(void* it, void* param) |
1353 | 0 | { |
1354 | 0 | txBinder* binder = param; |
1355 | 0 | fxScopeArrow(binder->scope); |
1356 | 0 | } |
1357 | | |
1358 | | void fxTryNodeBind(void* it, void* param) |
1359 | 0 | { |
1360 | 0 | txTryNode* self = it; |
1361 | 0 | fxBinderPushVariables(param, 3); |
1362 | 0 | fxNodeDispatchBind(self->tryBlock, param); |
1363 | 0 | if (self->catchBlock) |
1364 | 0 | fxNodeDispatchBind(self->catchBlock, param); |
1365 | 0 | if (self->finallyBlock) |
1366 | 0 | fxNodeDispatchBind(self->finallyBlock, param); |
1367 | 0 | fxBinderPopVariables(param, 3); |
1368 | 0 | } |
1369 | | |
1370 | | void fxWithNodeBind(void* it, void* param) |
1371 | 0 | { |
1372 | 0 | txWithNode* self = it; |
1373 | 0 | fxNodeDispatchBind(self->expression, param); |
1374 | 0 | fxScopeBinding(self->scope, param); |
1375 | 0 | fxNodeDispatchBind(self->statement, param); |
1376 | 0 | fxScopeBound(self->scope, param); |
1377 | 0 | } |
1378 | | |
1379 | | |
1380 | | |