• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &params,
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 *> &params)
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