1 /*
2 * Copyright (c) 2023-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "util/errorHandler.h"
17 #include "scopesInitPhase.h"
18 #include "util/errorLogger.h"
19
20 namespace ark::es2panda::compiler {
21
22 template <typename T>
LexicalScopeCreateOrEnter(varbinder::VarBinder * varBinder,ir::AstNode * ast)23 varbinder::LexicalScope<T> LexicalScopeCreateOrEnter(varbinder::VarBinder *varBinder, ir::AstNode *ast)
24 {
25 if (ast != nullptr && ast->Scope() != nullptr) {
26 return varbinder::LexicalScope<T>::Enter(varBinder, reinterpret_cast<T *>(ast->Scope()));
27 }
28 return varbinder::LexicalScope<T>(varBinder);
29 }
30
31 template <typename T, typename... Args>
AddOrGetDecl(varbinder::VarBinder * varBinder,util::StringView name,ir::AstNode * ast,const lexer::SourcePosition & pos,Args &&...args)32 T *AddOrGetDecl(varbinder::VarBinder *varBinder, util::StringView name, ir::AstNode *ast,
33 const lexer::SourcePosition &pos, Args &&...args)
34 {
35 if (auto *var = varBinder->GetScope()->FindLocal(name, varbinder::ResolveBindingOptions::BINDINGS);
36 var != nullptr && var->Declaration() != nullptr && var->Declaration()->Node() == ast) {
37 return reinterpret_cast<T *>(var->Declaration());
38 }
39 return varBinder->AddDecl<T>(pos, args...);
40 }
41
Perform(PhaseContext * ctx,parser::Program * program)42 bool ScopesInitPhase::Perform(PhaseContext *ctx, parser::Program *program)
43 {
44 Prepare(ctx, program);
45 program->VarBinder()->InitTopScope();
46 HandleBlockStmt(program->Ast(), GetScope());
47 Finalize();
48 return true;
49 }
50
VisitScriptFunction(ir::ScriptFunction * scriptFunction)51 void ScopesInitPhase::VisitScriptFunction(ir::ScriptFunction *scriptFunction)
52 {
53 if (auto *const id = scriptFunction->Id(); id != nullptr && id->Variable() == nullptr) {
54 auto const *const curScope = VarBinder()->GetScope();
55 auto const &functionName = id->Name();
56 auto const res =
57 curScope->Find(functionName, scriptFunction->IsStatic() ? varbinder::ResolveBindingOptions::ALL_STATIC
58 : varbinder::ResolveBindingOptions::ALL_NON_STATIC);
59 if (res.variable != nullptr && res.variable->Declaration()->IsFunctionDecl()) {
60 id->SetVariable(res.variable);
61 }
62 }
63
64 HandleFunction(scriptFunction);
65 }
66
VisitBlockStatement(ir::BlockStatement * blockStmt)67 void ScopesInitPhase::VisitBlockStatement(ir::BlockStatement *blockStmt)
68 {
69 auto localCtx = LexicalScopeCreateOrEnter<varbinder::LocalScopeWithTypeAlias>(VarBinder(), blockStmt);
70 HandleBlockStmt(blockStmt, GetScope());
71 }
72
VisitImportDeclaration(ir::ImportDeclaration * importDeclaration)73 void ScopesInitPhase::VisitImportDeclaration(ir::ImportDeclaration *importDeclaration)
74 {
75 ImportDeclarationContext importCtx(VarBinder());
76 Iterate(importDeclaration);
77 importCtx.BindImportDecl(importDeclaration);
78 }
79
VisitClassStaticBlock(ir::ClassStaticBlock * staticBlock)80 void ScopesInitPhase::VisitClassStaticBlock(ir::ClassStaticBlock *staticBlock)
81 {
82 Iterate(staticBlock);
83 }
84
VisitMethodDefinition(ir::MethodDefinition * methodDefinition)85 void ScopesInitPhase::VisitMethodDefinition(ir::MethodDefinition *methodDefinition)
86 {
87 Iterate(methodDefinition);
88 }
89
HandleFunctionSig(ir::TSTypeParameterDeclaration * typeParams,const ir::FunctionSignature::FunctionParams & params,ir::TypeNode * returnType)90 varbinder::FunctionParamScope *ScopesInitPhase::HandleFunctionSig(ir::TSTypeParameterDeclaration *typeParams,
91 const ir::FunctionSignature::FunctionParams ¶ms,
92 ir::TypeNode *returnType)
93 {
94 auto typeParamsCtx = varbinder::LexicalScope<varbinder::LocalScope>(VarBinder());
95 CallNode(typeParams);
96
97 auto lexicalScope = varbinder::LexicalScope<varbinder::FunctionParamScope>(VarBinder());
98 CallFuncParams(params);
99 CallNode(returnType);
100
101 return lexicalScope.GetScope();
102 }
103
HandleFunction(ir::ScriptFunction * function)104 void ScopesInitPhase::HandleFunction(ir::ScriptFunction *function)
105 {
106 CallNode(function->Id());
107 // NOTE(gogabr): this will skip type/value parameters when they are added to an existing function sig
108 auto funcParamScope = (function->Scope() == nullptr) ? HandleFunctionSig(function->TypeParams(), function->Params(),
109 function->ReturnTypeAnnotation())
110 : function->Scope()->ParamScope();
111 auto paramCtx = varbinder::LexicalScope<varbinder::FunctionParamScope>::Enter(VarBinder(), funcParamScope, false);
112
113 auto functionCtx = LexicalScopeCreateOrEnter<varbinder::FunctionScope>(VarBinder(), function);
114 auto *functionScope = functionCtx.GetScope();
115 BindFunctionScopes(functionScope, funcParamScope);
116
117 if (function->Body() != nullptr && function->Body()->IsBlockStatement()) {
118 HandleBlockStmt(function->Body()->AsBlockStatement(), functionScope);
119 } else {
120 Iterate(function->Body());
121 }
122 BindScopeNode(functionScope, function);
123 funcParamScope->BindNode(function);
124 CallNode(function->Annotations());
125 }
126
HandleBlockStmt(ir::BlockStatement * block,varbinder::Scope * scope)127 void ScopesInitPhase::HandleBlockStmt(ir::BlockStatement *block, varbinder::Scope *scope)
128 {
129 if (block->Scope() == nullptr) {
130 BindScopeNode(scope, block);
131 }
132 Iterate(block);
133 }
134
VisitClassDefinition(ir::ClassDefinition * classDef)135 void ScopesInitPhase::VisitClassDefinition(ir::ClassDefinition *classDef)
136 {
137 auto classCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), classDef);
138 AddOrGetDecl<varbinder::ConstDecl>(VarBinder(), classDef->PrivateId(), classDef, classDef->Start(),
139 classDef->PrivateId());
140 BindClassName(classDef);
141
142 auto *classScope = classCtx.GetScope();
143 BindScopeNode(classScope, classDef);
144 Iterate(classDef);
145 }
146
VisitForUpdateStatement(ir::ForUpdateStatement * forUpdateStmt)147 void ScopesInitPhase::VisitForUpdateStatement(ir::ForUpdateStatement *forUpdateStmt)
148 {
149 auto declCtx = (forUpdateStmt->Scope() == nullptr)
150 ? varbinder::LexicalScope<varbinder::LoopDeclarationScope>(VarBinder())
151 : varbinder::LexicalScope<varbinder::LoopDeclarationScope>::Enter(
152 // CC-OFFNXT(G.FMT.06-CPP) project code style
153 VarBinder(), forUpdateStmt->Scope()->DeclScope());
154 CallNode(forUpdateStmt->Init());
155
156 auto lexicalScope = LexicalScopeCreateOrEnter<varbinder::LoopScope>(VarBinder(), forUpdateStmt);
157 AttachLabelToScope(forUpdateStmt);
158 CallNode(forUpdateStmt->Test());
159 CallNode(forUpdateStmt->Update());
160 CallNode(forUpdateStmt->Body());
161 lexicalScope.GetScope()->BindDecls(declCtx.GetScope());
162 HandleFor(declCtx.GetScope(), lexicalScope.GetScope(), forUpdateStmt);
163 }
164
VisitForInStatement(ir::ForInStatement * forInStmt)165 void ScopesInitPhase::VisitForInStatement(ir::ForInStatement *forInStmt)
166 {
167 auto declCtx = (forInStmt->Scope() == nullptr)
168 ? varbinder::LexicalScope<varbinder::LoopDeclarationScope>(VarBinder())
169 : varbinder::LexicalScope<varbinder::LoopDeclarationScope>::Enter(
170 // CC-OFFNXT(G.FMT.06-CPP) project code style
171 VarBinder(), forInStmt->Scope()->DeclScope());
172 CallNode(forInStmt->Left());
173
174 auto lexicalScope = LexicalScopeCreateOrEnter<varbinder::LoopScope>(VarBinder(), forInStmt);
175 CallNode(forInStmt->Right());
176 CallNode(forInStmt->Body());
177 HandleFor(declCtx.GetScope(), lexicalScope.GetScope(), forInStmt);
178 }
VisitForOfStatement(ir::ForOfStatement * forOfStmt)179 void ScopesInitPhase::VisitForOfStatement(ir::ForOfStatement *forOfStmt)
180 {
181 auto declCtx = (forOfStmt->Scope() == nullptr)
182 ? varbinder::LexicalScope<varbinder::LoopDeclarationScope>(VarBinder())
183 : varbinder::LexicalScope<varbinder::LoopDeclarationScope>::Enter(
184 // CC-OFFNXT(G.FMT.06-CPP) project code style
185 VarBinder(), forOfStmt->Scope()->DeclScope());
186 CallNode(forOfStmt->Left());
187
188 auto lexicalScope = LexicalScopeCreateOrEnter<varbinder::LoopScope>(VarBinder(), forOfStmt);
189 AttachLabelToScope(forOfStmt);
190 CallNode(forOfStmt->Right());
191 CallNode(forOfStmt->Body());
192 HandleFor(declCtx.GetScope(), lexicalScope.GetScope(), forOfStmt);
193 }
194
VisitCatchClause(ir::CatchClause * catchClause)195 void ScopesInitPhase::VisitCatchClause(ir::CatchClause *catchClause)
196 {
197 auto catchParamCtx = (catchClause->Scope() == nullptr)
198 ? varbinder::LexicalScope<varbinder::CatchParamScope>(VarBinder())
199 : varbinder::LexicalScope<varbinder::CatchParamScope>::Enter(
200 // CC-OFFNXT(G.FMT.06-CPP) project code style
201 VarBinder(), catchClause->Scope()->ParamScope());
202 auto *catchParamScope = catchParamCtx.GetScope();
203 auto *param = catchClause->Param();
204
205 CallNode(param);
206
207 if (param != nullptr) {
208 auto [param_decl, var] = VarBinder()->AddParamDecl(param);
209 (void)param_decl;
210 if (param->IsIdentifier()) {
211 var->SetScope(catchParamScope);
212 param->AsIdentifier()->SetVariable(var);
213 }
214 }
215
216 // Catch Clause is scope bearer
217 catchParamScope->BindNode(catchClause);
218
219 auto catchCtx = LexicalScopeCreateOrEnter<varbinder::CatchScope>(VarBinder(), catchClause);
220 auto *catchScope = catchCtx.GetScope();
221
222 catchScope->AssignParamScope(catchParamScope);
223 auto body = catchClause->Body();
224 HandleBlockStmt(body, catchScope);
225
226 BindScopeNode(catchScope, catchClause);
227 }
228
VisitVariableDeclarator(ir::VariableDeclarator * varDecl)229 void ScopesInitPhase::VisitVariableDeclarator(ir::VariableDeclarator *varDecl)
230 {
231 auto init = varDecl->Id();
232 std::vector<ir::Identifier *> bindings = util::Helpers::CollectBindingNames(init);
233 for (auto *binding : bindings) {
234 auto [decl, var] = AddOrGetVarDecl(varDecl->Flag(), varDecl->Start(), binding);
235 BindVarDecl(binding, init, decl, var);
236 }
237 Iterate(varDecl);
238 }
239
VisitSwitchStatement(ir::SwitchStatement * switchStmt)240 void ScopesInitPhase::VisitSwitchStatement(ir::SwitchStatement *switchStmt)
241 {
242 CallNode(switchStmt->Discriminant());
243 auto localCtx = LexicalScopeCreateOrEnter<varbinder::LocalScopeWithTypeAlias>(VarBinder(), switchStmt);
244 AttachLabelToScope(switchStmt);
245 BindScopeNode(localCtx.GetScope(), switchStmt);
246 CallNode(switchStmt->Cases());
247 }
248
VisitWhileStatement(ir::WhileStatement * whileStmt)249 void ScopesInitPhase::VisitWhileStatement(ir::WhileStatement *whileStmt)
250 {
251 CallNode(whileStmt->Test());
252 auto lexicalScope = LexicalScopeCreateOrEnter<varbinder::LoopScope>(VarBinder(), whileStmt);
253 AttachLabelToScope(whileStmt);
254 BindScopeNode(lexicalScope.GetScope(), whileStmt);
255 CallNode(whileStmt->Body());
256 }
257
VisitETSStructDeclaration(ir::ETSStructDeclaration * structDecl)258 void ScopesInitPhase::VisitETSStructDeclaration(ir::ETSStructDeclaration *structDecl)
259 {
260 Iterate(structDecl);
261 BindClassDefinition(structDecl->Definition());
262 }
263
VisitClassDeclaration(ir::ClassDeclaration * classDecl)264 void ScopesInitPhase::VisitClassDeclaration(ir::ClassDeclaration *classDecl)
265 {
266 Iterate(classDecl);
267 BindClassDefinition(classDecl->Definition());
268 }
269
VisitAnnotationDeclaration(ir::AnnotationDeclaration * annoDecl)270 void ScopesInitPhase::VisitAnnotationDeclaration(ir::AnnotationDeclaration *annoDecl)
271 {
272 // First check if there is any redefinition in the current scope
273 const auto locStart = annoDecl->GetBaseName()->Start();
274 const auto &annoName = annoDecl->GetBaseName()->Name();
275 AddOrGetDecl<varbinder::AnnotationDecl>(VarBinder(), annoName, annoDecl, locStart, annoName, annoDecl);
276 // Create and enter annotation scope
277 auto annoCtx = LexicalScopeCreateOrEnter<varbinder::AnnotationScope>(VarBinder(), annoDecl);
278 auto *classScope = annoCtx.GetScope();
279 BindScopeNode(classScope, annoDecl);
280 Iterate(annoDecl);
281 }
282
VisitAnnotationUsage(ir::AnnotationUsage * annoUsage)283 void ScopesInitPhase::VisitAnnotationUsage(ir::AnnotationUsage *annoUsage)
284 {
285 auto annoCtx = LexicalScopeCreateOrEnter<varbinder::AnnotationParamScope>(VarBinder(), annoUsage);
286 auto *curScope = annoCtx.GetScope();
287 BindScopeNode(curScope, annoUsage);
288 CallNode(annoUsage->Properties());
289 }
290
VisitDoWhileStatement(ir::DoWhileStatement * doWhileStmt)291 void ScopesInitPhase::VisitDoWhileStatement(ir::DoWhileStatement *doWhileStmt)
292 {
293 auto lexicalScope = LexicalScopeCreateOrEnter<varbinder::LoopScope>(VarBinder(), doWhileStmt);
294 AttachLabelToScope(doWhileStmt);
295 BindScopeNode(lexicalScope.GetScope(), doWhileStmt);
296 Iterate(doWhileStmt);
297 }
298
VisitFunctionDeclaration(ir::FunctionDeclaration * funcDecl)299 void ScopesInitPhase::VisitFunctionDeclaration(ir::FunctionDeclaration *funcDecl)
300 {
301 const auto func = funcDecl->Function();
302 if (!funcDecl->IsAnonymous()) {
303 CreateFuncDecl(func);
304 }
305 Iterate(funcDecl);
306 }
307
VisitExportAllDeclaration(ir::ExportAllDeclaration * exportAllDecl)308 void ScopesInitPhase::VisitExportAllDeclaration(ir::ExportAllDeclaration *exportAllDecl)
309 {
310 Iterate(exportAllDecl);
311 const auto name = exportAllDecl->Exported() != nullptr ? exportAllDecl->Exported()->Name() : "*";
312 auto *decl =
313 AddOrGetDecl<varbinder::ExportDecl>(VarBinder(), name, exportAllDecl, exportAllDecl->Start(), name, "*");
314 VarBinder()->GetScope()->AsModuleScope()->AddExportDecl(exportAllDecl, decl);
315 }
316
VisitImportNamespaceSpecifier(ir::ImportNamespaceSpecifier * importSpec)317 void ScopesInitPhase::VisitImportNamespaceSpecifier(ir::ImportNamespaceSpecifier *importSpec)
318 {
319 Iterate(importSpec);
320 AddOrGetDecl<varbinder::ImportDecl>(VarBinder(), importSpec->Local()->Name(), importSpec, importSpec->Start(), "*",
321 importSpec->Local()->Name(), importSpec);
322 }
323
VisitImportSpecifier(ir::ImportSpecifier * importSpec)324 void ScopesInitPhase::VisitImportSpecifier(ir::ImportSpecifier *importSpec)
325 {
326 Iterate(importSpec);
327 const auto *imported = importSpec->Imported();
328 AddOrGetDecl<varbinder::ImportDecl>(VarBinder(), importSpec->Local()->Name(), importSpec, importSpec->Start(),
329 imported->Name(), importSpec->Local()->Name(), importSpec);
330 }
331
VisitImportDefaultSpecifier(ir::ImportDefaultSpecifier * importSpec)332 void ScopesInitPhase::VisitImportDefaultSpecifier(ir::ImportDefaultSpecifier *importSpec)
333 {
334 Iterate(importSpec);
335 const auto *local = importSpec->Local();
336 AddOrGetDecl<varbinder::ImportDecl>(VarBinder(), local->Name(), importSpec, local->Start(), "default",
337 local->Name(), importSpec);
338 }
339
VisitExportDefaultDeclaration(ir::ExportDefaultDeclaration * exportDecl)340 void ScopesInitPhase::VisitExportDefaultDeclaration(ir::ExportDefaultDeclaration *exportDecl)
341 {
342 ExportDeclarationContext exportDeclCtx(VarBinder());
343 Iterate(exportDecl);
344 exportDeclCtx.BindExportDecl(exportDecl);
345 }
346
VisitArrowFunctionExpression(ir::ArrowFunctionExpression * arrowExpr)347 void ScopesInitPhase::VisitArrowFunctionExpression(ir::ArrowFunctionExpression *arrowExpr)
348 {
349 Iterate(arrowExpr);
350 }
351
VisitDirectEvalExpression(ir::DirectEvalExpression * directCallExpr)352 void ScopesInitPhase::VisitDirectEvalExpression(ir::DirectEvalExpression *directCallExpr)
353 {
354 VarBinder()->PropagateDirectEval();
355 Iterate(directCallExpr);
356 }
357
VisitExportNamedDeclaration(ir::ExportNamedDeclaration * exportDecl)358 void ScopesInitPhase::VisitExportNamedDeclaration(ir::ExportNamedDeclaration *exportDecl)
359 {
360 if (exportDecl->Decl() != nullptr) {
361 ExportDeclarationContext exportDeclCtx(VarBinder());
362 Iterate(exportDecl);
363 exportDeclCtx.BindExportDecl(exportDecl);
364 } else {
365 varbinder::ModuleScope::ExportDeclList exportDecls(program_->Allocator()->Adapter());
366
367 for (auto *spec : exportDecl->Specifiers()) {
368 auto *decl =
369 AddOrGetDecl<varbinder::ExportDecl>(VarBinder(), spec->Local()->Name(), spec, exportDecl->Start(),
370 spec->Exported()->Name(), spec->Local()->Name(), spec);
371 exportDecls.push_back(decl);
372 }
373 VarBinder()->GetScope()->AsModuleScope()->AddExportDecl(exportDecl, std::move(exportDecls));
374 }
375 }
376
VisitTSFunctionType(ir::TSFunctionType * funcType)377 void ScopesInitPhase::VisitTSFunctionType(ir::TSFunctionType *funcType)
378 {
379 auto lexicalScope = LexicalScopeCreateOrEnter<varbinder::FunctionParamScope>(VarBinder(), funcType);
380 auto *funcParamScope = lexicalScope.GetScope();
381 BindScopeNode(funcParamScope, funcType);
382 Iterate(funcType);
383 }
384
SetProgram(parser::Program * program)385 void ScopesInitPhase::SetProgram(parser::Program *program) noexcept
386 {
387 program_ = program;
388 }
389
CallFuncParams(const ArenaVector<ir::Expression * > & params)390 void ScopesInitPhase::CallFuncParams(const ArenaVector<ir::Expression *> ¶ms)
391 {
392 // NOTE: extract params to separate class
393 for (auto *param : params) {
394 if (!param->IsETSParameterExpression()) {
395 VarBinder()->AddParamDecl(param);
396 }
397 }
398 CallNode(params);
399 }
400
IterateNoTParams(ir::ClassDefinition * classDef)401 void ScopesInitPhase::IterateNoTParams(ir::ClassDefinition *classDef)
402 {
403 CallNode(classDef->Super());
404 CallNode(classDef->SuperTypeParams());
405 CallNode(classDef->Annotations());
406 CallNode(classDef->Implements());
407 CallNode(classDef->Ctor());
408 CallNode(classDef->Body());
409 }
410
LogSyntaxError(std::string_view errorMessage,const lexer::SourcePosition & pos) const411 void ScopesInitPhase::LogSyntaxError(std::string_view errorMessage, const lexer::SourcePosition &pos) const
412 {
413 util::ErrorHandler::LogSyntaxError(ctx_->parser->ErrorLogger(), Program(), errorMessage, pos);
414 }
415
CreateFuncDecl(ir::ScriptFunction * func)416 void ScopesInitPhase::CreateFuncDecl(ir::ScriptFunction *func)
417 {
418 AddOrGetDecl<varbinder::FunctionDecl>(VarBinder(), func->Id()->Name(), func, func->Id()->Start(), Allocator(),
419 func->Id()->Name(), func);
420 }
421
FormInterfaceOrEnumDeclarationIdBinding(ir::Identifier * id)422 util::StringView ScopesInitPhase::FormInterfaceOrEnumDeclarationIdBinding(ir::Identifier *id)
423 {
424 return id->Name();
425 }
426
BindClassName(ir::ClassDefinition * classDef)427 varbinder::Decl *ScopesInitPhase::BindClassName(ir::ClassDefinition *classDef)
428 {
429 const auto identNode = classDef->Ident();
430 if (identNode == nullptr) {
431 return nullptr;
432 }
433
434 auto identDecl = AddOrGetDecl<varbinder::ConstDecl>(VarBinder(), identNode->Name(), classDef, identNode->Start(),
435 identNode->Name());
436 if (identDecl != nullptr) {
437 identDecl->BindNode(classDef);
438 }
439 return identDecl;
440 }
441
BindFunctionScopes(varbinder::FunctionScope * scope,varbinder::FunctionParamScope * paramScope)442 void ScopesInitPhase::BindFunctionScopes(varbinder::FunctionScope *scope, varbinder::FunctionParamScope *paramScope)
443 {
444 scope->BindParamScope(paramScope);
445 paramScope->BindFunctionScope(scope);
446 }
447
BindClassDefinition(ir::ClassDefinition * classDef)448 void ScopesInitPhase::BindClassDefinition(ir::ClassDefinition *classDef)
449 {
450 if (classDef->IsGlobal()) {
451 return; // We handle it in ClassDeclaration
452 }
453 const auto locStart = classDef->Ident()->Start();
454 const auto &className = classDef->Ident()->Name();
455 if ((classDef->Modifiers() & ir::ClassDefinitionModifiers::CLASS_DECL) != 0U) {
456 AddOrGetDecl<varbinder::ClassDecl>(VarBinder(), className, classDef, locStart, className, classDef);
457 } else {
458 AddOrGetDecl<varbinder::LetDecl>(VarBinder(), className, classDef, locStart, className, classDef);
459 }
460 }
461
AddOrGetVarDecl(ir::VariableDeclaratorFlag flag,lexer::SourcePosition startLoc,const ir::Identifier * id)462 std::tuple<varbinder::Decl *, varbinder::Variable *> ScopesInitPhase::AddOrGetVarDecl(ir::VariableDeclaratorFlag flag,
463 lexer::SourcePosition startLoc,
464 const ir::Identifier *id)
465 {
466 if (auto var = id->Variable(); var != nullptr) {
467 return {var->Declaration(), var};
468 }
469 auto name = id->Name();
470 switch (flag) {
471 case ir::VariableDeclaratorFlag::LET:
472 return VarBinder()->NewVarDecl<varbinder::LetDecl>(startLoc, name);
473 case ir::VariableDeclaratorFlag::VAR:
474 return VarBinder()->NewVarDecl<varbinder::VarDecl>(startLoc, name);
475 case ir::VariableDeclaratorFlag::CONST:
476 return VarBinder()->NewVarDecl<varbinder::ConstDecl>(startLoc, name);
477 default:
478 UNREACHABLE();
479 }
480 }
481
BindVarDecl(ir::Identifier * binding,ir::Expression * init,varbinder::Decl * decl,varbinder::Variable * var)482 void ScopesInitPhase::BindVarDecl([[maybe_unused]] ir::Identifier *binding, ir::Expression *init, varbinder::Decl *decl,
483 [[maybe_unused]] varbinder::Variable *var)
484 {
485 decl->BindNode(init);
486 }
487
AttachLabelToScope(ir::AstNode * node)488 void ScopesInitPhase::AttachLabelToScope([[maybe_unused]] ir::AstNode *node) {}
489
VisitFunctionExpression(ir::FunctionExpression * funcExpr)490 void ScopesInitPhase::VisitFunctionExpression(ir::FunctionExpression *funcExpr)
491 {
492 Iterate(funcExpr);
493 if (!funcExpr->IsAnonymous()) {
494 auto func = funcExpr->Function();
495 auto id = funcExpr->Id();
496 auto *funcParamScope = func->Scope()->ParamScope();
497 funcParamScope->BindName(Allocator(), id->Name());
498 func->SetIdent(id->Clone(Allocator(), nullptr));
499 }
500 }
501
Prepare(ScopesInitPhase::PhaseContext * ctx,parser::Program * program)502 void ScopesInitPhase::Prepare(ScopesInitPhase::PhaseContext *ctx, parser::Program *program)
503 {
504 ctx_ = ctx;
505 program_ = program;
506 }
507
Finalize()508 void ScopesInitPhase::Finalize()
509 {
510 AnalyzeExports();
511 }
512
AnalyzeExports()513 void ScopesInitPhase::AnalyzeExports()
514 {
515 if (Program()->Kind() == parser::ScriptKind::MODULE && VarBinder()->TopScope()->IsModuleScope() &&
516 !VarBinder()->TopScope()->AsModuleScope()->ExportAnalysis()) {
517 LogSyntaxError("Invalid exported binding", Program()->Ast()->End());
518 }
519 }
520
VisitTSModuleDeclaration(ir::TSModuleDeclaration * moduleDecl)521 void ScopeInitTyped::VisitTSModuleDeclaration(ir::TSModuleDeclaration *moduleDecl)
522 {
523 if (!moduleDecl->IsExternalOrAmbient()) {
524 auto name = moduleDecl->Name()->AsIdentifier()->Name();
525 auto *decl = AddOrGetDecl<varbinder::VarDecl>(VarBinder(), name, moduleDecl, moduleDecl->Name()->Start(), name);
526 decl->BindNode(moduleDecl);
527 }
528 auto localCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), moduleDecl);
529 BindScopeNode(localCtx.GetScope(), moduleDecl);
530 Iterate(moduleDecl);
531 }
532
VisitTSModuleBlock(ir::TSModuleBlock * block)533 void ScopeInitTyped::VisitTSModuleBlock(ir::TSModuleBlock *block)
534 {
535 auto localCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), block);
536 Iterate(block);
537 BindScopeNode(localCtx.GetScope(), block);
538 }
539
VisitTSTypeAliasDeclaration(ir::TSTypeAliasDeclaration * typeAliasDecl)540 void ScopeInitTyped::VisitTSTypeAliasDeclaration(ir::TSTypeAliasDeclaration *typeAliasDecl)
541 {
542 const auto id = typeAliasDecl->Id();
543 varbinder::TSBinding tsBinding(Allocator(), id->Name());
544 auto *decl = VarBinder()->AddTsDecl<varbinder::TypeAliasDecl>(id->Start(), tsBinding.View());
545 auto typeParamsCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), typeAliasDecl->TypeParams());
546 decl->BindNode(typeAliasDecl);
547 Iterate(typeAliasDecl);
548 }
549
FormInterfaceOrEnumDeclarationIdBinding(ir::Identifier * id)550 util::StringView ScopeInitTyped::FormInterfaceOrEnumDeclarationIdBinding(ir::Identifier *id)
551 {
552 varbinder::TSBinding tsBinding(Allocator(), id->Name());
553 return tsBinding.View();
554 }
555
VisitTSInterfaceDeclaration(ir::TSInterfaceDeclaration * interfDecl)556 void ScopeInitTyped::VisitTSInterfaceDeclaration(ir::TSInterfaceDeclaration *interfDecl)
557 {
558 const auto &bindings = VarBinder()->GetScope()->Bindings();
559 const auto ident = interfDecl->Id();
560 const auto name = FormInterfaceOrEnumDeclarationIdBinding(ident);
561 auto res = bindings.find(name);
562
563 varbinder::InterfaceDecl *decl {};
564
565 bool alreadyExists = false;
566 if (res == bindings.end()) {
567 decl = VarBinder()->AddTsDecl<varbinder::InterfaceDecl>(ident->Start(), Allocator(), name);
568 } else if (!AllowInterfaceRedeclaration()) {
569 LogSyntaxError("Interface redeclaration is not allowed", interfDecl->Start());
570 } else if (!res->second->Declaration()->IsInterfaceDecl()) {
571 VarBinder()->ThrowRedeclaration(ident->Start(), ident->Name());
572 } else {
573 decl = res->second->Declaration()->AsInterfaceDecl();
574 alreadyExists = true;
575 }
576
577 CallNode(ident);
578 auto typeParamsCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), interfDecl->TypeParams());
579 CallNode(interfDecl->TypeParams());
580 CallNode(interfDecl->Extends());
581
582 auto localScope = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), interfDecl);
583 auto *identDecl =
584 AddOrGetDecl<varbinder::ConstDecl>(VarBinder(), ident->Name(), interfDecl, ident->Start(), ident->Name());
585 identDecl->BindNode(interfDecl);
586 BindScopeNode(localScope.GetScope(), interfDecl);
587
588 CallNode(interfDecl->Body());
589 if (decl == nullptr) { // Error processing.
590 return;
591 }
592
593 if (!alreadyExists) {
594 decl->BindNode(interfDecl);
595 }
596 decl->Add(interfDecl);
597 }
598
VisitTSEnumMember(ir::TSEnumMember * enumMember)599 void ScopeInitTyped::VisitTSEnumMember(ir::TSEnumMember *enumMember)
600 {
601 const auto key = enumMember->Key();
602 util::StringView name;
603 if (key->IsIdentifier()) {
604 name = key->AsIdentifier()->Name();
605 } else if (key->IsStringLiteral()) {
606 name = key->AsStringLiteral()->Str();
607 } else {
608 UNREACHABLE();
609 }
610 auto *decl = AddOrGetDecl<varbinder::EnumDecl>(VarBinder(), name, enumMember, key->Start(), name);
611 decl->BindNode(enumMember);
612 }
613
VisitTSEnumDeclaration(ir::TSEnumDeclaration * enumDecl)614 void ScopeInitTyped::VisitTSEnumDeclaration(ir::TSEnumDeclaration *enumDecl)
615 {
616 util::StringView ident = FormInterfaceOrEnumDeclarationIdBinding(enumDecl->Key());
617 const auto &bindings = VarBinder()->GetScope()->Bindings();
618 auto res = bindings.find(ident);
619
620 varbinder::EnumLiteralDecl *decl {};
621 if (res == bindings.end()) {
622 decl = VarBinder()->AddTsDecl<varbinder::EnumLiteralDecl>(enumDecl->Start(), ident, enumDecl->IsConst());
623 varbinder::LexicalScope enumCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), enumDecl);
624 decl->BindScope(enumCtx.GetScope());
625 BindScopeNode(VarBinder()->GetScope()->AsLocalScope(), enumDecl);
626 } else if (!res->second->Declaration()->IsEnumLiteralDecl() ||
627 (enumDecl->IsConst() ^ res->second->Declaration()->AsEnumLiteralDecl()->IsConst()) != 0) {
628 auto loc = enumDecl->Key()->End();
629 loc.index++;
630 VarBinder()->ThrowRedeclaration(loc, enumDecl->Key()->Name());
631 } else {
632 decl = res->second->Declaration()->AsEnumLiteralDecl();
633
634 auto scopeCtx = varbinder::LexicalScope<varbinder::LocalScope>::Enter(VarBinder(), decl->Scope());
635 }
636 decl->BindNode(enumDecl);
637 Iterate(enumDecl);
638 }
639
VisitTSTypeParameter(ir::TSTypeParameter * typeParam)640 void ScopeInitTyped::VisitTSTypeParameter(ir::TSTypeParameter *typeParam)
641 {
642 auto name = typeParam->Name()->Name();
643 auto decl = AddOrGetDecl<varbinder::TypeParameterDecl>(VarBinder(), name, typeParam, typeParam->Start(), name);
644 decl->BindNode(typeParam);
645 Iterate(typeParam);
646 }
647
VisitTSTypeParameterDeclaration(ir::TSTypeParameterDeclaration * paramDecl)648 void ScopeInitTyped::VisitTSTypeParameterDeclaration(ir::TSTypeParameterDeclaration *paramDecl)
649 {
650 BindScopeNode(VarBinder()->GetScope()->AsLocalScope(), paramDecl);
651 Iterate(paramDecl);
652 }
653
VisitClassDefinition(ir::ClassDefinition * classDef)654 void ScopeInitTyped::VisitClassDefinition(ir::ClassDefinition *classDef)
655 {
656 auto typeParamsCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), classDef->TypeParams());
657 CallNode(classDef->TypeParams());
658
659 auto classCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), classDef);
660 BindClassName(classDef);
661 AddOrGetDecl<varbinder::ConstDecl>(VarBinder(), classDef->PrivateId(), classDef, classDef->Start(),
662 classDef->PrivateId());
663 BindScopeNode(classCtx.GetScope(), classDef);
664 IterateNoTParams(classDef);
665 }
666
VisitExportDefaultDeclaration(ir::ExportDefaultDeclaration * exportDecl)667 void InitScopesPhaseTs::VisitExportDefaultDeclaration(ir::ExportDefaultDeclaration *exportDecl)
668 {
669 ExportDeclarationContext exportDeclCtx(VarBinder());
670 Iterate(exportDecl);
671 }
672
VisitExportNamedDeclaration(ir::ExportNamedDeclaration * exportDecl)673 void InitScopesPhaseTs::VisitExportNamedDeclaration(ir::ExportNamedDeclaration *exportDecl)
674 {
675 ExportDeclarationContext exportDeclCtx(VarBinder());
676 Iterate(exportDecl);
677 }
678
VisitImportDeclaration(ir::ImportDeclaration * importDeclaration)679 void InitScopesPhaseTs::VisitImportDeclaration(ir::ImportDeclaration *importDeclaration)
680 {
681 ImportDeclarationContext importCtx(VarBinder());
682 Iterate(importDeclaration);
683 }
684
VisitTSFunctionType(ir::TSFunctionType * constrType)685 void InitScopesPhaseTs::VisitTSFunctionType(ir::TSFunctionType *constrType)
686 {
687 auto lexicalScope =
688 (constrType->Scope() == nullptr)
689 ? HandleFunctionSig(constrType->TypeParams(), constrType->Params(), constrType->ReturnType())
690 : constrType->Scope();
691 BindScopeNode(lexicalScope, constrType);
692 }
693
CreateFuncDecl(ir::ScriptFunction * func)694 void InitScopesPhaseTs::CreateFuncDecl(ir::ScriptFunction *func)
695 {
696 const auto identNode = func->Id();
697 const auto startLoc = identNode->Start();
698 const auto &bindings = VarBinder()->GetScope()->Bindings();
699 auto res = bindings.find(identNode->Name());
700 varbinder::FunctionDecl *decl {};
701
702 if (res == bindings.end()) {
703 decl = VarBinder()->AddDecl<varbinder::FunctionDecl>(startLoc, Allocator(), identNode->Name(), func);
704 } else {
705 varbinder::Decl *currentDecl = res->second->Declaration();
706
707 auto &existing = currentDecl->AsFunctionDecl()->Decls();
708 if (std::find(existing.begin(), existing.end(), func) != existing.end()) {
709 return;
710 }
711
712 if (!currentDecl->IsFunctionDecl() ||
713 !currentDecl->AsFunctionDecl()->Node()->AsScriptFunction()->IsOverload()) {
714 VarBinder()->ThrowRedeclaration(startLoc, currentDecl->Name());
715 }
716 decl = currentDecl->AsFunctionDecl();
717 }
718
719 decl->Add(func);
720 }
721
VisitTSConstructorType(ir::TSConstructorType * constrT)722 void InitScopesPhaseTs::VisitTSConstructorType(ir::TSConstructorType *constrT)
723 {
724 auto funcParamScope = (constrT->Scope() == nullptr)
725 ? HandleFunctionSig(constrT->TypeParams(), constrT->Params(), constrT->ReturnType())
726 : constrT->Scope();
727 BindScopeNode(funcParamScope, constrT);
728 }
729
VisitArrowFunctionExpression(ir::ArrowFunctionExpression * arrowFExpr)730 void InitScopesPhaseTs::VisitArrowFunctionExpression(ir::ArrowFunctionExpression *arrowFExpr)
731 {
732 auto typeParamsCtx =
733 LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), arrowFExpr->Function()->TypeParams());
734 Iterate(arrowFExpr);
735 }
736
VisitTSSignatureDeclaration(ir::TSSignatureDeclaration * signDecl)737 void InitScopesPhaseTs::VisitTSSignatureDeclaration(ir::TSSignatureDeclaration *signDecl)
738 {
739 auto funcParamScope = (signDecl->Scope() == nullptr) ? HandleFunctionSig(signDecl->TypeParams(), signDecl->Params(),
740 signDecl->ReturnTypeAnnotation())
741 : signDecl->Scope();
742 BindScopeNode(funcParamScope, signDecl);
743 }
744
VisitTSMethodSignature(ir::TSMethodSignature * methodSign)745 void InitScopesPhaseTs::VisitTSMethodSignature(ir::TSMethodSignature *methodSign)
746 {
747 auto funcParamScope =
748 (methodSign->Scope() == nullptr)
749 ? HandleFunctionSig(methodSign->TypeParams(), methodSign->Params(), methodSign->ReturnTypeAnnotation())
750 : methodSign->Scope();
751 BindScopeNode(funcParamScope, methodSign);
752 }
753
RunExternalNode(ir::AstNode * node,varbinder::VarBinder * varbinder)754 void InitScopesPhaseETS::RunExternalNode(ir::AstNode *node, varbinder::VarBinder *varbinder)
755 {
756 auto program = parser::Program(varbinder->Allocator(), varbinder);
757 RunExternalNode(node, &program);
758 }
759
RunExternalNode(ir::AstNode * node,parser::Program * ctx)760 void InitScopesPhaseETS::RunExternalNode(ir::AstNode *node, parser::Program *ctx)
761 {
762 auto scopesPhase = InitScopesPhaseETS();
763 scopesPhase.SetProgram(ctx);
764 scopesPhase.CallNode(node);
765 }
766
Perform(PhaseContext * ctx,parser::Program * program)767 bool InitScopesPhaseETS::Perform(PhaseContext *ctx, parser::Program *program)
768 {
769 Prepare(ctx, program);
770
771 if (program->VarBinder()->TopScope() == nullptr) {
772 program->VarBinder()->InitTopScope();
773 BindScopeNode(GetScope(), program->Ast());
774 AddGlobalToBinder(program);
775 }
776 HandleProgram(program);
777 Finalize();
778 return true;
779 }
780
HandleProgram(parser::Program * program)781 void InitScopesPhaseETS::HandleProgram(parser::Program *program)
782 {
783 for (auto &[_, prog_list] : program->ExternalSources()) {
784 (void)_;
785 auto savedTopScope(program->VarBinder()->TopScope());
786 auto mainProg = prog_list.front();
787 mainProg->VarBinder()->InitTopScope();
788 AddGlobalToBinder(mainProg);
789 BindScopeNode(mainProg->VarBinder()->GetScope(), mainProg->Ast());
790 auto globalClass = mainProg->GlobalClass();
791 auto globalScope = mainProg->GlobalScope();
792 for (auto &prog : prog_list) {
793 prog->SetGlobalClass(globalClass);
794 BindScopeNode(prog->VarBinder()->GetScope(), prog->Ast());
795 prog->VarBinder()->ResetTopScope(globalScope);
796 if (mainProg->Ast() != nullptr) {
797 InitScopesPhaseETS().Perform(Context(), prog);
798 }
799 }
800 program->VarBinder()->ResetTopScope(savedTopScope);
801 }
802 ASSERT(program->Ast() != nullptr);
803
804 HandleETSScript(program->Ast());
805 }
806
BindVarDecl(ir::Identifier * binding,ir::Expression * init,varbinder::Decl * decl,varbinder::Variable * var)807 void InitScopesPhaseETS::BindVarDecl(ir::Identifier *binding, ir::Expression *init, varbinder::Decl *decl,
808 varbinder::Variable *var)
809 {
810 binding->SetVariable(var);
811 var->SetScope(VarBinder()->GetScope());
812 var->AddFlag(varbinder::VariableFlags::LOCAL);
813 decl->BindNode(init);
814 }
815
VisitBlockExpression(ir::BlockExpression * blockExpr)816 void InitScopesPhaseETS::VisitBlockExpression(ir::BlockExpression *blockExpr)
817 {
818 auto localCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), blockExpr);
819 if (blockExpr->Scope() == nullptr) {
820 BindScopeNode(GetScope(), blockExpr);
821 }
822 Iterate(blockExpr);
823 }
824
VisitClassStaticBlock(ir::ClassStaticBlock * staticBlock)825 void InitScopesPhaseETS::VisitClassStaticBlock(ir::ClassStaticBlock *staticBlock)
826 {
827 const auto func = staticBlock->Function();
828
829 {
830 auto funcParamCtx = (func->Scope() == nullptr)
831 ? varbinder::LexicalScope<varbinder::FunctionParamScope>(VarBinder())
832 : varbinder::LexicalScope<varbinder::FunctionParamScope>::Enter(
833 // CC-OFFNXT(G.FMT.06-CPP) project code style
834 VarBinder(), func->Scope()->ParamScope());
835 auto *funcParamScope = funcParamCtx.GetScope();
836 auto funcCtx = LexicalScopeCreateOrEnter<varbinder::FunctionScope>(VarBinder(), func);
837 auto *funcScope = funcCtx.GetScope();
838
839 func->Body()->AsBlockStatement()->SetScope(funcScope);
840 BindScopeNode(funcScope, func);
841 funcParamScope->BindNode(func);
842 BindFunctionScopes(funcScope, funcParamScope);
843 Iterate(func->Body()->AsBlockStatement());
844 }
845
846 auto classCtx = varbinder::LexicalScope<varbinder::LocalScope>::Enter(
847 VarBinder(), VarBinder()->GetScope()->AsClassScope()->StaticMethodScope());
848
849 if (func->Id()->Variable() != nullptr) {
850 return;
851 }
852
853 auto [_, var] = VarBinder()->NewVarDecl<varbinder::FunctionDecl>(staticBlock->Start(), Allocator(),
854 func->Id()->Name(), staticBlock);
855 (void)_;
856 var->AddFlag(varbinder::VariableFlags::METHOD);
857 func->Id()->SetVariable(var);
858 }
859
VisitImportNamespaceSpecifier(ir::ImportNamespaceSpecifier * importSpec)860 void InitScopesPhaseETS::VisitImportNamespaceSpecifier(ir::ImportNamespaceSpecifier *importSpec)
861 {
862 if (importSpec->Local()->Name().Empty()) {
863 return;
864 }
865 AddOrGetDecl<varbinder::ImportDecl>(VarBinder(), importSpec->Local()->Name(), importSpec, importSpec->Start(),
866 importSpec->Local()->Name(), importSpec->Local()->Name(), importSpec);
867 auto var =
868 VarBinder()->GetScope()->FindLocal(importSpec->Local()->Name(), varbinder::ResolveBindingOptions::BINDINGS);
869 importSpec->Local()->SetVariable(var);
870 Iterate(importSpec);
871 }
872
VisitImportSpecifier(ir::ImportSpecifier * importSpec)873 void InitScopesPhaseETS::VisitImportSpecifier(ir::ImportSpecifier *importSpec)
874 {
875 if (importSpec->Parent()->AsETSImportDeclaration()->IsPureDynamic()) {
876 auto [decl, var] =
877 VarBinder()->NewVarDecl<varbinder::LetDecl>(importSpec->Start(), importSpec->Local()->Name(), importSpec);
878 var->AddFlag(varbinder::VariableFlags::INITIALIZED);
879 }
880 Iterate(importSpec);
881 }
882
883 // Auxiliary method to avoid extra nested levels and too large function size
AddOverload(ir::MethodDefinition * overload,varbinder::Variable * variable)884 void AddOverload(ir::MethodDefinition *overload, varbinder::Variable *variable) noexcept
885 {
886 auto *currentNode = variable->Declaration()->Node();
887 currentNode->AsMethodDefinition()->AddOverload(overload);
888 overload->Id()->SetVariable(variable);
889 overload->SetParent(currentNode);
890 }
891
DeclareClassMethod(ir::MethodDefinition * method)892 void InitScopesPhaseETS::DeclareClassMethod(ir::MethodDefinition *method)
893 {
894 ASSERT(VarBinder()->GetScope()->IsClassScope());
895
896 if ((method->AsMethodDefinition()->Function()->Flags() & ir::ScriptFunctionFlags::OVERLOAD) != 0) {
897 return;
898 }
899
900 const auto methodName = method->Id();
901 auto *const clsScope = VarBinder()->GetScope()->AsClassScope();
902 auto options =
903 method->IsStatic()
904 ? varbinder::ResolveBindingOptions::STATIC_VARIABLES | varbinder::ResolveBindingOptions::STATIC_DECLARATION
905 : varbinder::ResolveBindingOptions::VARIABLES | varbinder::ResolveBindingOptions::DECLARATION;
906 if (clsScope->FindLocal(methodName->Name(), options) != nullptr) {
907 VarBinder()->ThrowRedeclaration(methodName->Start(), methodName->Name());
908 }
909
910 varbinder::LocalScope *targetScope {};
911 if (method->IsStatic() || method->IsConstructor()) {
912 targetScope = clsScope->StaticMethodScope();
913 } else {
914 targetScope = clsScope->InstanceMethodScope();
915 }
916 auto *found = targetScope->FindLocal(methodName->Name(), varbinder::ResolveBindingOptions::BINDINGS);
917
918 MaybeAddOverload(method, methodName, found, clsScope, targetScope);
919 }
920
MaybeAddOverload(ir::MethodDefinition * method,ir::Identifier * methodName,varbinder::Variable * found,varbinder::ClassScope * clsScope,varbinder::LocalScope * targetScope)921 void InitScopesPhaseETS::MaybeAddOverload(ir::MethodDefinition *method, ir::Identifier *methodName,
922 varbinder::Variable *found, varbinder::ClassScope *clsScope,
923 varbinder::LocalScope *targetScope)
924 {
925 if (found == nullptr) {
926 auto classCtx = varbinder::LexicalScope<varbinder::LocalScope>::Enter(VarBinder(), targetScope);
927
928 auto *var = methodName->Variable();
929 if (var == nullptr) {
930 var = std::get<1>(VarBinder()->NewVarDecl<varbinder::FunctionDecl>(methodName->Start(), Allocator(),
931 methodName->Name(), method));
932 var->SetScope(clsScope);
933 var->AddFlag(varbinder::VariableFlags::METHOD);
934 methodName->SetVariable(var);
935 }
936 for (auto *overload : method->Overloads()) {
937 ASSERT((overload->Function()->Flags() & ir::ScriptFunctionFlags::OVERLOAD));
938 overload->Id()->SetVariable(var);
939 overload->SetParent(var->Declaration()->Node());
940 }
941 } else {
942 if (methodName->Name().Is(compiler::Signatures::MAIN) && clsScope->Parent()->IsGlobalScope()) {
943 LogSyntaxError("Main overload is not enabled", methodName->Start());
944 }
945 AddOverload(method, found);
946 method->Function()->AddFlag(ir::ScriptFunctionFlags::OVERLOAD);
947
948 // default params overloads
949 for (auto *overload : method->Overloads()) {
950 ASSERT((overload->Function()->Flags() & ir::ScriptFunctionFlags::OVERLOAD));
951 AddOverload(overload, found);
952 }
953 method->ClearOverloads();
954 }
955 }
956
VisitETSReExportDeclaration(ir::ETSReExportDeclaration * reExport)957 void InitScopesPhaseETS::VisitETSReExportDeclaration(ir::ETSReExportDeclaration *reExport)
958 {
959 if (reExport->GetETSImportDeclarations()->Language().IsDynamic()) {
960 VarBinder()->AsETSBinder()->AddDynamicImport(reExport->GetETSImportDeclarations());
961 }
962 VarBinder()->AsETSBinder()->AddReExportImport(reExport);
963 }
964
VisitETSParameterExpression(ir::ETSParameterExpression * paramExpr)965 void InitScopesPhaseETS::VisitETSParameterExpression(ir::ETSParameterExpression *paramExpr)
966 {
967 auto *const var = std::get<1>(VarBinder()->AddParamDecl(paramExpr));
968 paramExpr->Ident()->SetVariable(var);
969 var->SetScope(VarBinder()->GetScope());
970 Iterate(paramExpr);
971 }
972
VisitETSImportDeclaration(ir::ETSImportDeclaration * importDecl)973 void InitScopesPhaseETS::VisitETSImportDeclaration(ir::ETSImportDeclaration *importDecl)
974 {
975 ImportDeclarationContext importCtx(VarBinder());
976 if (importDecl->Language().IsDynamic()) {
977 VarBinder()->AsETSBinder()->AddDynamicImport(importDecl);
978 }
979 Iterate(importDecl);
980 }
981
VisitTSEnumMember(ir::TSEnumMember * enumMember)982 void InitScopesPhaseETS::VisitTSEnumMember(ir::TSEnumMember *enumMember)
983 {
984 auto ident = enumMember->Key()->AsIdentifier();
985 if (ident->Variable() != nullptr) {
986 return;
987 }
988 auto [decl, var] = VarBinder()->NewVarDecl<varbinder::LetDecl>(ident->Start(), ident->Name());
989 var->SetScope(VarBinder()->GetScope());
990 var->AddFlag(varbinder::VariableFlags::STATIC);
991 ident->SetVariable(var);
992 decl->BindNode(enumMember);
993 Iterate(enumMember);
994 }
995
VisitMethodDefinition(ir::MethodDefinition * method)996 void InitScopesPhaseETS::VisitMethodDefinition(ir::MethodDefinition *method)
997 {
998 auto *curScope = VarBinder()->GetScope();
999 const auto methodName = method->Id();
1000 auto res =
1001 curScope->Find(methodName->Name(), method->IsStatic() ? varbinder::ResolveBindingOptions::ALL_STATIC
1002 : varbinder::ResolveBindingOptions::ALL_NON_STATIC);
1003 if (res.variable != nullptr && !res.variable->Declaration()->IsFunctionDecl() && res.scope == curScope) {
1004 VarBinder()->ThrowRedeclaration(methodName->Start(), res.name);
1005 }
1006 Iterate(method);
1007 DeclareClassMethod(method);
1008 }
1009
VisitETSFunctionType(ir::ETSFunctionType * funcType)1010 void InitScopesPhaseETS::VisitETSFunctionType(ir::ETSFunctionType *funcType)
1011 {
1012 auto typeParamsCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), funcType->TypeParams());
1013
1014 // Check for existing scope
1015 // In some cases we can visit function again with scope that already exists
1016 // Example: async lambda, we "move" original function to another place and visit it again
1017 if (funcType->Scope() == nullptr) {
1018 varbinder::LexicalScope<varbinder::FunctionParamScope> lexicalScope(VarBinder());
1019 auto *funcParamScope = lexicalScope.GetScope();
1020 BindScopeNode(funcParamScope, funcType);
1021 Iterate(funcType);
1022 }
1023 }
1024
VisitETSNewClassInstanceExpression(ir::ETSNewClassInstanceExpression * newClassExpr)1025 void InitScopesPhaseETS::VisitETSNewClassInstanceExpression(ir::ETSNewClassInstanceExpression *newClassExpr)
1026 {
1027 CallNode(newClassExpr->GetArguments());
1028 CallNode(newClassExpr->GetTypeRef());
1029 if (newClassExpr->ClassDefinition() != nullptr) {
1030 const auto classDef = newClassExpr->ClassDefinition();
1031 auto *parentClassScope = VarBinder()->GetScope();
1032 while (!parentClassScope->IsClassScope()) {
1033 ASSERT(parentClassScope->Parent());
1034 parentClassScope = parentClassScope->Parent();
1035 }
1036 auto classCtx = LexicalScopeCreateOrEnter<varbinder::ClassScope>(VarBinder(), newClassExpr->ClassDefinition());
1037 util::UString anonymousName(util::StringView("#"), Allocator());
1038 anonymousName.Append(std::to_string(parentClassScope->AsClassScope()->GetAndIncrementAnonymousClassIdx()));
1039 classDef->SetInternalName(anonymousName.View());
1040 classDef->Ident()->SetName(anonymousName.View());
1041 AddOrGetDecl<varbinder::ClassDecl>(VarBinder(), anonymousName.View(), classDef, classDef->Start(),
1042 anonymousName.View(), classDef);
1043 CallNode(classDef);
1044 }
1045 }
1046
VisitTSTypeParameter(ir::TSTypeParameter * typeParam)1047 void InitScopesPhaseETS::VisitTSTypeParameter(ir::TSTypeParameter *typeParam)
1048 {
1049 if (typeParam->Name()->Variable() != nullptr) {
1050 return;
1051 }
1052 auto [decl, var] =
1053 VarBinder()->NewVarDecl<varbinder::TypeParameterDecl>(typeParam->Name()->Start(), typeParam->Name()->Name());
1054 typeParam->Name()->SetVariable(var);
1055 var->SetScope(VarBinder()->GetScope());
1056 var->AddFlag(varbinder::VariableFlags::TYPE_PARAMETER);
1057 decl->BindNode(typeParam);
1058 }
1059
VisitTSInterfaceDeclaration(ir::TSInterfaceDeclaration * interfaceDecl)1060 void InitScopesPhaseETS::VisitTSInterfaceDeclaration(ir::TSInterfaceDeclaration *interfaceDecl)
1061 {
1062 {
1063 auto typeParamsCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), interfaceDecl->TypeParams());
1064 CallNode(interfaceDecl->TypeParams());
1065 CallNode(interfaceDecl->Extends());
1066 auto localScope = LexicalScopeCreateOrEnter<varbinder::ClassScope>(VarBinder(), interfaceDecl);
1067 CallNode(interfaceDecl->Body());
1068 BindScopeNode(localScope.GetScope(), interfaceDecl);
1069 }
1070 auto name = FormInterfaceOrEnumDeclarationIdBinding(interfaceDecl->Id());
1071 auto *decl = AddOrGetDecl<varbinder::InterfaceDecl>(VarBinder(), name, interfaceDecl, interfaceDecl->Start(),
1072 Allocator(), name, interfaceDecl);
1073 decl->AsInterfaceDecl()->Add(interfaceDecl);
1074 }
1075
VisitTSEnumDeclaration(ir::TSEnumDeclaration * enumDecl)1076 void InitScopesPhaseETS::VisitTSEnumDeclaration(ir::TSEnumDeclaration *enumDecl)
1077 {
1078 {
1079 const auto enumCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), enumDecl);
1080 BindScopeNode(enumCtx.GetScope(), enumDecl);
1081 Iterate(enumDecl);
1082 }
1083 auto name = FormInterfaceOrEnumDeclarationIdBinding(enumDecl->Key());
1084 auto *decl = AddOrGetDecl<varbinder::EnumLiteralDecl>(VarBinder(), name, enumDecl, enumDecl->Start(), name,
1085 enumDecl, enumDecl->IsConst());
1086 decl->BindScope(enumDecl->Scope());
1087 }
1088
VisitTSTypeAliasDeclaration(ir::TSTypeAliasDeclaration * typeAlias)1089 void InitScopesPhaseETS::VisitTSTypeAliasDeclaration(ir::TSTypeAliasDeclaration *typeAlias)
1090 {
1091 AddOrGetDecl<varbinder::TypeAliasDecl>(VarBinder(), typeAlias->Id()->Name(), typeAlias, typeAlias->Id()->Start(),
1092 typeAlias->Id()->Name(), typeAlias);
1093 auto typeParamsCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), typeAlias->TypeParams());
1094 Iterate(typeAlias);
1095 }
1096
AddGlobalToBinder(parser::Program * program)1097 void InitScopesPhaseETS::AddGlobalToBinder(parser::Program *program)
1098 {
1099 auto globalId = program->GlobalClass()->Ident();
1100 if (globalId->Variable() != nullptr) {
1101 return;
1102 }
1103
1104 auto [decl2, var] = program->VarBinder()->NewVarDecl<varbinder::ClassDecl>(globalId->Start(), globalId->Name());
1105
1106 auto classCtx = LexicalScopeCreateOrEnter<varbinder::ClassScope>(program->VarBinder(), program->GlobalClass());
1107 classCtx.GetScope()->BindNode(program->GlobalClass());
1108 program->GlobalClass()->SetScope(classCtx.GetScope());
1109
1110 auto *classDecl = program->GlobalClass()->Parent();
1111 decl2->BindNode(classDecl);
1112 globalId->SetVariable(var);
1113 }
1114
HandleETSScript(ir::BlockStatement * script)1115 void InitScopesPhaseETS::HandleETSScript(ir::BlockStatement *script)
1116 {
1117 for (auto decl : script->Statements()) {
1118 if (decl->IsETSImportDeclaration()) {
1119 CallNode(decl);
1120 } else {
1121 auto classCtx =
1122 varbinder::LexicalScope<varbinder::ClassScope>::Enter(VarBinder(), Program()->GlobalClassScope());
1123 CallNode(decl);
1124 }
1125 }
1126 auto classCtx = varbinder::LexicalScope<varbinder::ClassScope>::Enter(VarBinder(), Program()->GlobalClassScope());
1127
1128 for (auto decl : script->Statements()) {
1129 AddGlobalDeclaration(decl);
1130 }
1131 }
1132
VisitClassDefinition(ir::ClassDefinition * classDef)1133 void InitScopesPhaseETS::VisitClassDefinition(ir::ClassDefinition *classDef)
1134 {
1135 if (classDef->IsGlobal()) {
1136 ParseGlobalClass(classDef);
1137 return;
1138 }
1139 auto typeParamsCtx = LexicalScopeCreateOrEnter<varbinder::LocalScope>(VarBinder(), classDef->TypeParams());
1140 CallNode(classDef->TypeParams());
1141 auto classCtx = LexicalScopeCreateOrEnter<varbinder::ClassScope>(VarBinder(), classDef);
1142
1143 IterateNoTParams(classDef);
1144 FilterOverloads(classDef->Body());
1145 auto *classScope = classCtx.GetScope();
1146 BindScopeNode(classScope, classDef);
1147 }
1148
VisitTSInterfaceBody(ir::TSInterfaceBody * interfBody)1149 void InitScopesPhaseETS::VisitTSInterfaceBody(ir::TSInterfaceBody *interfBody)
1150 {
1151 Iterate(interfBody);
1152 FilterInterfaceOverloads(interfBody->Body());
1153 }
1154
FilterInterfaceOverloads(ArenaVector<ir::AstNode *,false> & props)1155 void InitScopesPhaseETS::FilterInterfaceOverloads(ArenaVector<ir::AstNode *, false> &props)
1156 {
1157 auto condition = [](ir::AstNode *prop) {
1158 if (prop->IsMethodDefinition()) {
1159 const auto func = prop->AsMethodDefinition()->Function();
1160 return func->IsOverload() && func->Body() != nullptr;
1161 }
1162 return false;
1163 };
1164 props.erase(std::remove_if(props.begin(), props.end(), condition), props.end());
1165 }
1166
FilterOverloads(ArenaVector<ir::AstNode *,false> & props)1167 void InitScopesPhaseETS::FilterOverloads(ArenaVector<ir::AstNode *, false> &props)
1168 {
1169 auto condition = [](ir::AstNode *prop) {
1170 if (prop->IsMethodDefinition()) {
1171 const auto func = prop->AsMethodDefinition()->Function();
1172 return func->IsOverload();
1173 }
1174 return false;
1175 };
1176 props.erase(std::remove_if(props.begin(), props.end(), condition), props.end());
1177 }
1178
VisitClassProperty(ir::ClassProperty * classProp)1179 void InitScopesPhaseETS::VisitClassProperty(ir::ClassProperty *classProp)
1180 {
1181 auto curScope = VarBinder()->GetScope();
1182 const auto name = classProp->Key()->AsIdentifier()->Name();
1183 if (classProp->IsClassStaticBlock()) {
1184 ASSERT(curScope->IsClassScope());
1185 auto classCtx = varbinder::LexicalScope<varbinder::LocalScope>::Enter(
1186 VarBinder(), curScope->AsClassScope()->StaticMethodScope());
1187 auto *var = classProp->Id()->Variable();
1188 if (var == nullptr) {
1189 var = std::get<1>(VarBinder()->NewVarDecl<varbinder::FunctionDecl>(classProp->Start(), Allocator(),
1190 classProp->Id()->Name(), classProp));
1191 }
1192 var->AddFlag(varbinder::VariableFlags::METHOD);
1193 classProp->AsClassStaticBlock()->Function()->Id()->SetVariable(var);
1194 } else if (classProp->IsConst()) {
1195 ASSERT(curScope->Parent() != nullptr);
1196 const auto initializer = classProp->Value();
1197 if (initializer == nullptr && curScope->Parent()->IsGlobalScope() && !classProp->IsDeclare()) {
1198 auto pos = classProp->End();
1199 // NOTE: Just use property Name?
1200 if (!classProp->TypeAnnotation()->IsETSPrimitiveType()) {
1201 pos.index--;
1202 }
1203 LogSyntaxError("Missing initializer in const declaration", pos);
1204 }
1205 AddOrGetDecl<varbinder::ConstDecl>(VarBinder(), name, classProp, classProp->Key()->Start(), name, classProp);
1206 } else if (classProp->IsReadonly()) {
1207 AddOrGetDecl<varbinder::ReadonlyDecl>(VarBinder(), name, classProp, classProp->Key()->Start(), name, classProp);
1208 } else {
1209 AddOrGetDecl<varbinder::LetDecl>(VarBinder(), name, classProp, classProp->Key()->Start(), name, classProp);
1210 }
1211 Iterate(classProp);
1212 }
1213
VisitBreakStatement(ir::BreakStatement * stmt)1214 void InitScopesPhaseETS::VisitBreakStatement(ir::BreakStatement *stmt)
1215 {
1216 auto label = stmt->Ident();
1217 if (label != nullptr) {
1218 auto scope = VarBinder()->GetScope();
1219 auto var = scope->FindInFunctionScope(label->Name(), varbinder::ResolveBindingOptions::ALL).variable;
1220 label->SetVariable(var);
1221 }
1222 }
1223
VisitContinueStatement(ir::ContinueStatement * stmt)1224 void InitScopesPhaseETS::VisitContinueStatement(ir::ContinueStatement *stmt)
1225 {
1226 auto label = stmt->Ident();
1227 if (label != nullptr) {
1228 auto scope = VarBinder()->GetScope();
1229 auto var = scope->FindInFunctionScope(label->Name(), varbinder::ResolveBindingOptions::ALL).variable;
1230 label->SetVariable(var);
1231 }
1232 }
1233
AttachLabelToScope(ir::AstNode * node)1234 void InitScopesPhaseETS::AttachLabelToScope(ir::AstNode *node)
1235 {
1236 if (node->Parent() == nullptr) {
1237 return;
1238 }
1239
1240 if (!node->Parent()->IsLabelledStatement()) {
1241 return;
1242 }
1243
1244 auto stmt = node->Parent()->AsLabelledStatement();
1245 auto label = stmt->Ident();
1246 if (label == nullptr) {
1247 return;
1248 }
1249
1250 auto decl = AddOrGetDecl<varbinder::LabelDecl>(VarBinder(), label->Name(), stmt, label->Start(), label->Name());
1251 decl->BindNode(stmt);
1252
1253 auto var = VarBinder()->GetScope()->FindLocal(label->Name(), varbinder::ResolveBindingOptions::BINDINGS);
1254 if (var != nullptr) {
1255 label->SetVariable(var);
1256 var->SetScope(VarBinder()->GetScope());
1257 var->AddFlag(varbinder::VariableFlags::LOCAL);
1258 }
1259 }
1260
ParseGlobalClass(ir::ClassDefinition * global)1261 void InitScopesPhaseETS::ParseGlobalClass(ir::ClassDefinition *global)
1262 {
1263 for (auto decl : global->Body()) {
1264 if (decl->IsDefaultExported()) {
1265 if (VarBinder()->AsETSBinder()->DefaultExport() != nullptr) {
1266 LogSyntaxError("Only one default export is allowed in a module", decl->Start());
1267 }
1268 VarBinder()->AsETSBinder()->SetDefaultExport(decl);
1269 }
1270 CallNode(decl);
1271 }
1272 FilterOverloads(global->Body());
1273 }
1274
AddGlobalDeclaration(ir::AstNode * node)1275 void InitScopesPhaseETS::AddGlobalDeclaration(ir::AstNode *node)
1276 {
1277 ir::Identifier *ident = nullptr;
1278 bool isBuiltin = false;
1279 switch (node->Type()) {
1280 case ir::AstNodeType::CLASS_DECLARATION: {
1281 auto def = node->AsClassDeclaration()->Definition();
1282 if (def->IsGlobal()) {
1283 return;
1284 }
1285 ident = def->Ident();
1286 isBuiltin = def->IsFromExternal();
1287 break;
1288 }
1289 case ir::AstNodeType::ANNOTATION_DECLARATION: {
1290 ident = node->AsAnnotationDeclaration()->GetBaseName();
1291 isBuiltin = false;
1292 break;
1293 }
1294 case ir::AstNodeType::STRUCT_DECLARATION: {
1295 ident = node->AsETSStructDeclaration()->Definition()->Ident();
1296 isBuiltin = node->AsETSStructDeclaration()->Definition()->IsFromExternal();
1297 break;
1298 }
1299 case ir::AstNodeType::TS_INTERFACE_DECLARATION: {
1300 ident = node->AsTSInterfaceDeclaration()->Id();
1301 isBuiltin = node->AsTSInterfaceDeclaration()->IsFromExternal();
1302 break;
1303 }
1304 case ir::AstNodeType::TS_ENUM_DECLARATION: {
1305 ident = node->AsTSEnumDeclaration()->Key();
1306 break;
1307 }
1308 case ir::AstNodeType::TS_TYPE_ALIAS_DECLARATION: {
1309 ident = node->AsTSTypeAliasDeclaration()->Id();
1310 break;
1311 }
1312 default: {
1313 break;
1314 }
1315 }
1316 if (ident != nullptr) {
1317 VarBinder()->TopScope()->InsertBinding(ident->Name(), ident->Variable());
1318 if (isBuiltin) {
1319 ident->Variable()->AddFlag(varbinder::VariableFlags::BUILTIN_TYPE);
1320 }
1321 }
1322 }
1323
VisitArrowFunctionExpression(ir::ArrowFunctionExpression * arrowExpr)1324 void InitScopesPhaseAS::VisitArrowFunctionExpression(ir::ArrowFunctionExpression *arrowExpr)
1325 {
1326 Iterate(arrowExpr);
1327 }
1328
VisitExportNamedDeclaration(ir::ExportNamedDeclaration * exportDecl)1329 void InitScopesPhaseAS::VisitExportNamedDeclaration(ir::ExportNamedDeclaration *exportDecl)
1330 {
1331 ExportDeclarationContext exportDeclCtx(VarBinder());
1332 Iterate(exportDecl);
1333 }
1334
1335 } // namespace ark::es2panda::compiler
1336