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 #ifndef ES2PANDA_COMPILER_CORE_SCOPES_INIT_PHASE_H 17 #define ES2PANDA_COMPILER_CORE_SCOPES_INIT_PHASE_H 18 19 #include "compiler/lowering/phase.h" 20 #include "util/helpers.h" 21 #include "parser/parserFlags.h" 22 #include "varbinder/tsBinding.h" 23 #include "varbinder/ETSBinder.h" 24 #include "compiler/lowering/scopesInit/savedBindingsCtx.h" 25 #include "checker/checker.h" 26 #include "ir/visitor/IterateAstVisitor.h" 27 #include "ir/expressions/literals/undefinedLiteral.h" 28 #include "ir/expressions/blockExpression.h" 29 #include "ir/ets/etsUnionType.h" 30 #include "ir/ets/etsTuple.h" 31 32 namespace ark::es2panda::compiler { 33 34 /** 35 * Responsible for initialization of scopes. Should be called right after Parser stage. 36 */ 37 // NOLINTNEXTLINE(fuchsia-multiple-inheritance) 38 class ScopesInitPhase : public Phase, public ir::visitor::IterateAstVisitor { 39 public: 40 using PhaseContext = public_lib::Context; 41 42 static constexpr std::string_view NAME = "ScopesInitPhase"; 43 Name()44 std::string_view Name() const override 45 { 46 return NAME; 47 } 48 49 bool Perform(PhaseContext *ctx, parser::Program *program) override; 50 51 protected: 52 void SetProgram(parser::Program *program) noexcept; 53 54 void Prepare(PhaseContext *ctx, parser::Program *program); 55 56 /** 57 * Should be called at the end of each program perform 58 */ 59 void Finalize(); 60 61 /** 62 * Check if there's only one default export and no named export redeclaration, 63 * throw error if so. 64 * Side effect: fill local_exports_ 65 */ 66 void AnalyzeExports(); 67 68 protected: 69 template <typename T> CallNode(T * node)70 void CallNode(T *node) 71 { 72 if (node) { 73 node->Accept(this); 74 } 75 } 76 77 template <typename T> CallNode(const ArenaVector<T * > & nodes)78 void CallNode(const ArenaVector<T *> &nodes) 79 { 80 for (auto *node : nodes) { 81 CallNode(node); 82 } 83 } 84 85 void CallFuncParams(const ArenaVector<ir::Expression *> ¶ms); 86 void IterateNoTParams(ir::ClassDefinition *classDef); 87 88 protected: 89 void ThrowSyntaxError(std::string_view errorMessage, const lexer::SourcePosition &pos) const; 90 91 void VisitFunctionExpression(ir::FunctionExpression *funcExpr) override; 92 void VisitScriptFunction(ir::ScriptFunction *scriptFunction) override; 93 void VisitBlockStatement(ir::BlockStatement *blockStmt) override; 94 void VisitImportDeclaration(ir::ImportDeclaration *importDeclaration) override; 95 void VisitClassStaticBlock(ir::ClassStaticBlock *staticBlock) override; 96 void VisitClassDefinition(ir::ClassDefinition *classDef) override; 97 void VisitMethodDefinition(ir::MethodDefinition *methodDefinition) override; 98 void VisitForUpdateStatement(ir::ForUpdateStatement *forUpdateStmt) override; 99 void VisitForInStatement(ir::ForInStatement *forInStmt) override; 100 void VisitForOfStatement(ir::ForOfStatement *forOfStmt) override; 101 void VisitCatchClause(ir::CatchClause *catchClause) override; 102 void VisitVariableDeclarator(ir::VariableDeclarator *varDecl) override; 103 void VisitSwitchStatement(ir::SwitchStatement *switchStmt) override; 104 void VisitWhileStatement(ir::WhileStatement *whileStmt) override; 105 void VisitETSStructDeclaration(ir::ETSStructDeclaration *structDecl) override; 106 void VisitClassDeclaration(ir::ClassDeclaration *classDecl) override; 107 void VisitDoWhileStatement(ir::DoWhileStatement *doWhileStmt) override; 108 void VisitFunctionDeclaration(ir::FunctionDeclaration *funcDecl) override; 109 void VisitExportAllDeclaration(ir::ExportAllDeclaration *exportAllDecl) override; 110 void VisitImportNamespaceSpecifier(ir::ImportNamespaceSpecifier *importSpec) override; 111 void VisitImportSpecifier(ir::ImportSpecifier *importSpec) override; 112 void VisitImportDefaultSpecifier(ir::ImportDefaultSpecifier *importSpec) override; 113 void VisitExportDefaultDeclaration(ir::ExportDefaultDeclaration *exportDecl) override; 114 void VisitExportNamedDeclaration(ir::ExportNamedDeclaration *exportDecl) override; 115 void VisitArrowFunctionExpression(ir::ArrowFunctionExpression *arrowExpr) override; 116 void VisitDirectEvalExpression(ir::DirectEvalExpression *directCallExpr) override; 117 void VisitTSFunctionType(ir::TSFunctionType *funcType) override; 118 119 protected: GetScope()120 varbinder::Scope *GetScope() 121 { 122 return VarBinder()->GetScope(); 123 } 124 Allocator()125 ArenaAllocator *Allocator() 126 { 127 return program_->Allocator(); 128 } 129 Program()130 parser::Program *Program() 131 { 132 return program_; 133 } 134 Program()135 const parser::Program *Program() const 136 { 137 return program_; 138 } 139 Context()140 PhaseContext *Context() 141 { 142 return ctx_; 143 } 144 VarBinder()145 [[nodiscard]] varbinder::VarBinder *VarBinder() const 146 { 147 return program_->VarBinder(); 148 } 149 150 protected: 151 virtual void CreateFuncDecl(ir::ScriptFunction *func); 152 virtual util::StringView FormInterfaceOrEnumDeclarationIdBinding(ir::Identifier *id); 153 void HandleFunction(ir::ScriptFunction *function); 154 varbinder::FunctionParamScope *HandleFunctionSig(ir::TSTypeParameterDeclaration *typeParams, 155 const ir::FunctionSignature::FunctionParams ¶ms, 156 ir::TypeNode *returnType); 157 158 /** 159 * Handle block from existing scope 160 */ 161 void HandleBlockStmt(ir::BlockStatement *block, varbinder::Scope *scope); 162 163 template <typename ForT> HandleFor(varbinder::LoopDeclarationScope * declScope,varbinder::LoopScope * loopScope,ForT * forStmt)164 void HandleFor(varbinder::LoopDeclarationScope *declScope, varbinder::LoopScope *loopScope, ForT *forStmt) 165 { 166 loopScope->BindDecls(declScope); 167 BindScopeNode(loopScope, forStmt); 168 loopScope->DeclScope()->BindNode(forStmt); 169 } 170 171 protected: 172 virtual varbinder::Decl *BindClassName(ir::ClassDefinition *classDef); 173 174 template <class Scope, class Node> BindScopeNode(Scope * scope,Node * node)175 static void BindScopeNode(Scope *scope, Node *node) 176 { 177 if (node->Scope() == nullptr || node->IsBlockStatement()) { 178 scope->BindNode(node); 179 node->SetScope(scope); 180 } 181 } 182 183 static void BindFunctionScopes(varbinder::FunctionScope *scope, varbinder::FunctionParamScope *paramScope); 184 185 void BindClassDefinition(ir::ClassDefinition *classDef); 186 187 std::tuple<varbinder::Decl *, varbinder::Variable *> AddOrGetVarDecl(ir::VariableDeclaratorFlag flag, 188 lexer::SourcePosition startLoc, 189 const ir::Identifier *id); 190 191 virtual void BindVarDecl([[maybe_unused]] ir::Identifier *binding, ir::Expression *init, varbinder::Decl *decl, 192 [[maybe_unused]] varbinder::Variable *var); 193 virtual void AttachLabelToScope(ir::AstNode *node); 194 195 private: 196 PhaseContext *ctx_ {}; 197 parser::Program *program_ {}; 198 }; 199 200 /** 201 * Specialization for typed script languages (typescript, ets) 202 */ 203 class ScopeInitTyped : public ScopesInitPhase { 204 protected: 205 public: 206 void VisitTSModuleDeclaration(ir::TSModuleDeclaration *moduleDecl) override; 207 208 void VisitTSModuleBlock(ir::TSModuleBlock *block) override; 209 210 void VisitTSTypeAliasDeclaration(ir::TSTypeAliasDeclaration *typeAliasDecl) override; 211 212 util::StringView FormInterfaceOrEnumDeclarationIdBinding(ir::Identifier *id) override; 213 AllowInterfaceRedeclaration()214 virtual bool AllowInterfaceRedeclaration() 215 { 216 return false; 217 } 218 219 void VisitTSInterfaceDeclaration(ir::TSInterfaceDeclaration *interfDecl) override; 220 221 void VisitTSEnumMember(ir::TSEnumMember *enumMember) override; 222 223 void VisitTSEnumDeclaration(ir::TSEnumDeclaration *enumDecl) override; 224 225 void VisitTSTypeParameter(ir::TSTypeParameter *typeParam) override; 226 227 void VisitTSTypeParameterDeclaration(ir::TSTypeParameterDeclaration *paramDecl) override; 228 229 void VisitClassDefinition(ir::ClassDefinition *classDef) override; 230 }; 231 232 class InitScopesPhaseJs : public ScopesInitPhase { 233 public: 234 InitScopesPhaseJs() = default; 235 NO_COPY_SEMANTIC(InitScopesPhaseJs); 236 NO_MOVE_SEMANTIC(InitScopesPhaseJs); 237 238 ~InitScopesPhaseJs() override = default; 239 }; 240 241 class InitScopesPhaseTs : public ScopeInitTyped { 242 protected: AllowInterfaceRedeclaration()243 bool AllowInterfaceRedeclaration() override 244 { 245 return true; 246 } 247 VisitTSMappedType(ir::TSMappedType * mapped)248 void VisitTSMappedType([[maybe_unused]] ir::TSMappedType *mapped) override {} VisitTSInferType(ir::TSInferType * infer)249 void VisitTSInferType([[maybe_unused]] ir::TSInferType *infer) override {} 250 void VisitExportDefaultDeclaration(ir::ExportDefaultDeclaration *exportDecl) override; 251 void VisitExportNamedDeclaration(ir::ExportNamedDeclaration *exportDecl) override; 252 void VisitImportDeclaration(ir::ImportDeclaration *importDeclaration) override; 253 void VisitTSFunctionType(ir::TSFunctionType *constrType) override; 254 void VisitTSConstructorType(ir::TSConstructorType *constrT) override; 255 void VisitArrowFunctionExpression(ir::ArrowFunctionExpression *arrowFExpr) override; 256 void VisitTSSignatureDeclaration(ir::TSSignatureDeclaration *signDecl) override; 257 void VisitTSMethodSignature(ir::TSMethodSignature *methodSign) override; 258 259 void CreateFuncDecl(ir::ScriptFunction *func) override; 260 }; 261 262 class InitScopesPhaseETS : public ScopeInitTyped { 263 public: 264 InitScopesPhaseETS() = default; 265 NO_COPY_SEMANTIC(InitScopesPhaseETS); 266 NO_MOVE_SEMANTIC(InitScopesPhaseETS); 267 268 /** 269 * Set scopes for ast-subtree 270 * @param node ast-subtree, for this node and all children scopes will be initialized. 271 * @param varbinder ref to VarBinder. All varbinder scopes should be set to current context. 272 * Note: It's programmer responsibility to prepare VarBinder (remove previous names, set current scope, etc...) 273 * 274 * Example: 275 * f<T>(x: Int) : { 276 * let y = 0; 277 * } 278 * After ScopesInitPhase scope structure will look something like this: 279 * global_scope: 280 * [f], 281 * local_scope: 282 * [T], 283 * function_param_scope: 284 * [x], 285 * function_scope: 286 * [y] 287 * Suppose you want to rewrite function body in some lowering later to 288 * { 289 * let z = 123; 290 * } 291 * 292 * Then you should pass your new created node = ir::BlockStatement() to RunExternalNode, 293 * set varbinder to previous `function_scope` and call RunExternalNode(node, varbinder). 294 * It will update scopes to: 295 * global_scope: 296 * [f], 297 * local_scope: 298 * [T], 299 * function_param_scope: 300 * [x], 301 * function_scope: 302 * [z] 303 */ 304 static void RunExternalNode(ir::AstNode *node, varbinder::VarBinder *varbinder); 305 /** 306 * Same as previous, just uses varbinder from ctx->VarBinder() 307 */ 308 static void RunExternalNode(ir::AstNode *node, parser::Program *ctx); 309 310 /** 311 * Run scope initialization on program. 312 * It's not same as RunExternalNode(program->Ast()), because there's some specific handling for top scope. 313 * @param ctx 314 * @param program - program you want to set scopes on. 315 * @return true if successful. 316 */ 317 bool Perform(PhaseContext *ctx, parser::Program *program) override; 318 319 ~InitScopesPhaseETS() override = default; 320 321 private: 322 void HandleProgram(parser::Program *program); 323 324 void HandleETSScript(ir::BlockStatement *script); 325 326 void ParseGlobalClass(ir::ClassDefinition *global); 327 328 void AddGlobalDeclaration(ir::AstNode *node); 329 BindClassName(ir::ClassDefinition * identNode)330 varbinder::Decl *BindClassName([[maybe_unused]] ir::ClassDefinition *identNode) override 331 { 332 return nullptr; 333 } 334 335 void BindVarDecl(ir::Identifier *binding, ir::Expression *init, varbinder::Decl *decl, 336 varbinder::Variable *var) override; 337 void DeclareClassMethod(ir::MethodDefinition *method); 338 void MaybeAddOverload(ir::MethodDefinition *method, ir::Identifier *methodName, varbinder::Variable *found, 339 varbinder::ClassScope *clsScope, varbinder::LocalScope *targetScope); 340 341 void VisitClassStaticBlock(ir::ClassStaticBlock *staticBlock) override; 342 void VisitBlockExpression(ir::BlockExpression *blockExpr) override; 343 void VisitImportNamespaceSpecifier(ir::ImportNamespaceSpecifier *importSpec) override; 344 void VisitImportSpecifier([[maybe_unused]] ir::ImportSpecifier *importSpec) override; VisitImportDefaultSpecifier(ir::ImportDefaultSpecifier * importSpec)345 void VisitImportDefaultSpecifier([[maybe_unused]] ir::ImportDefaultSpecifier *importSpec) override {}; 346 void VisitETSReExportDeclaration(ir::ETSReExportDeclaration *reExport) override; 347 void VisitETSParameterExpression(ir::ETSParameterExpression *paramExpr) override; 348 void VisitETSImportDeclaration(ir::ETSImportDeclaration *importDecl) override; 349 void VisitTSEnumMember(ir::TSEnumMember *enumMember) override; 350 void VisitMethodDefinition(ir::MethodDefinition *method) override; 351 void VisitETSFunctionType(ir::ETSFunctionType *funcType) override; 352 void VisitETSNewClassInstanceExpression(ir::ETSNewClassInstanceExpression *newClassExpr) override; 353 void VisitTSTypeParameter(ir::TSTypeParameter *typeParam) override; 354 void VisitTSInterfaceDeclaration(ir::TSInterfaceDeclaration *interfaceDecl) override; 355 void VisitTSEnumDeclaration(ir::TSEnumDeclaration *enumDecl) override; 356 void VisitTSTypeAliasDeclaration(ir::TSTypeAliasDeclaration *typeAlias) override; 357 void VisitClassDefinition(ir::ClassDefinition *classDef) override; 358 void VisitTSInterfaceBody(ir::TSInterfaceBody *interfBody) override; 359 void VisitClassProperty(ir::ClassProperty *classProp) override; 360 void VisitBreakStatement(ir::BreakStatement *stmt) override; 361 void VisitContinueStatement(ir::ContinueStatement *stmt) override; 362 void AttachLabelToScope(ir::AstNode *node) override; VisitArrowFunctionExpression(ir::ArrowFunctionExpression * arrowExpr)363 void VisitArrowFunctionExpression(ir::ArrowFunctionExpression *arrowExpr) override 364 { 365 Iterate(arrowExpr); 366 } 367 FormInterfaceOrEnumDeclarationIdBinding(ir::Identifier * id)368 util::StringView FormInterfaceOrEnumDeclarationIdBinding(ir::Identifier *id) override 369 { 370 return id->Name(); 371 } 372 373 static void AddGlobalToBinder(parser::Program *program); 374 375 void FilterInterfaceOverloads(ArenaVector<ir::AstNode *> &props); 376 377 void FilterOverloads(ArenaVector<ir::AstNode *> &props); 378 }; 379 380 class InitScopesPhaseAS : public ScopesInitPhase { 381 public: 382 NO_COPY_SEMANTIC(InitScopesPhaseAS); 383 NO_MOVE_SEMANTIC(InitScopesPhaseAS); 384 InitScopesPhaseAS() = default; 385 ~InitScopesPhaseAS() override = default; 386 387 private: 388 void VisitArrowFunctionExpression(ir::ArrowFunctionExpression *arrowExpr) override; 389 void VisitExportNamedDeclaration(ir::ExportNamedDeclaration *exportDecl) override; 390 }; 391 } // namespace ark::es2panda::compiler 392 393 #endif 394