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