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