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