1/** 2 * Copyright (c) 2021-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_SCOPES_SCOPE_H 17#define ES2PANDA_COMPILER_SCOPES_SCOPE_H 18 19#include "varbinder/declaration.h" 20#include "varbinder/variable.h" 21#include "es2panda.h" 22#include "util/enumbitops.h" 23#include "util/ustring.h" 24 25#include <map> 26#include <unordered_map> 27#include <vector> 28 29namespace ark::es2panda::public_lib { 30struct Context; 31} // namespace ark::es2panda::public_lib 32 33namespace ark::es2panda::compiler { 34class IRNode; 35} // namespace ark::es2panda::compiler 36 37namespace ark::es2panda::varbinder { 38// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 39#define DECLARE_CLASSES(type, className) class className; 40SCOPE_TYPES(DECLARE_CLASSES) 41#undef DECLARE_CLASSES 42 43class Scope; 44class VariableScope; 45class Variable; 46 47template <typename ScopeT, 48 std::enable_if_t<std::is_pointer_v<ScopeT> && std::is_base_of_v<Scope, std::remove_pointer_t<ScopeT>>, bool> = 49 true> 50class ScopeFindResultT { 51public: 52 ScopeFindResultT() = default; 53 ScopeFindResultT(util::StringView n, ScopeT s, uint32_t l, Variable *v) : ScopeFindResultT(n, s, l, l, v) {} 54 ScopeFindResultT(ScopeT s, uint32_t l, uint32_t ll, Variable *v) : scope(s), level(l), lexLevel(ll), variable(v) {} 55 ScopeFindResultT(util::StringView n, ScopeT s, uint32_t l, uint32_t ll, Variable *v) 56 : name(n), scope(s), level(l), lexLevel(ll), variable(v) 57 { 58 } 59 60 // NOLINTBEGIN(misc-non-private-member-variables-in-classes) 61 util::StringView name {}; 62 ScopeT scope {}; 63 uint32_t level {}; 64 uint32_t lexLevel {}; 65 Variable *variable {}; 66 // NOLINTEND(misc-non-private-member-variables-in-classes) 67}; 68 69using ConstScopeFindResult = ScopeFindResultT<const Scope *>; 70using ScopeFindResult = ScopeFindResultT<Scope *>; 71 72class Scope { 73public: 74 virtual ~Scope() = default; 75 NO_COPY_SEMANTIC(Scope); 76 NO_MOVE_SEMANTIC(Scope); 77 78 using VariableMap = ArenaUnorderedMap<util::StringView, Variable *>; 79 using InsertResult = std::pair<VariableMap::const_iterator, bool>; 80 81 virtual ScopeType Type() const = 0; 82 83// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 84#define DECLARE_CHECKS_CASTS(scopeType, className) \ 85 bool Is##className() const \ 86 { \ 87 return Type() == ScopeType::scopeType; \ 88 } \ 89 className *As##className() \ 90 { \ 91 ASSERT(Is##className()); \ 92 return reinterpret_cast<className *>(this); \ 93 } \ 94 const className *As##className() const \ 95 { \ 96 ASSERT(Is##className()); \ 97 return reinterpret_cast<const className *>(this); \ 98 } 99 SCOPE_TYPES(DECLARE_CHECKS_CASTS) 100#undef DECLARE_CHECKS_CASTS 101 102 bool IsVariableScope() const 103 { 104 return Type() > ScopeType::LOCAL; 105 } 106 107 bool IsFunctionVariableScope() const 108 { 109 return Type() >= ScopeType::FUNCTION; 110 } 111 112 FunctionScope *AsFunctionVariableScope() 113 { 114 ASSERT(IsFunctionVariableScope()); 115 return reinterpret_cast<FunctionScope *>(this); 116 } 117 118 const FunctionScope *AsFunctionVariableScope() const 119 { 120 ASSERT(IsFunctionVariableScope()); 121 return reinterpret_cast<const FunctionScope *>(this); 122 } 123 124 VariableScope *AsVariableScope() 125 { 126 ASSERT(IsVariableScope()); 127 return reinterpret_cast<VariableScope *>(this); 128 } 129 130 const VariableScope *AsVariableScope() const 131 { 132 ASSERT(IsVariableScope()); 133 return reinterpret_cast<const VariableScope *>(this); 134 } 135 136 VariableScope *EnclosingVariableScope(); 137 138 const VariableScope *EnclosingVariableScope() const; 139 140 ClassScope *EnclosingClassScope(); 141 const ClassScope *EnclosingClassScope() const; 142 143 void AddFlag(ScopeFlags flag) 144 { 145 flags_ |= flag; 146 } 147 148 void ClearFlag(ScopeFlags flag) 149 { 150 flags_ &= ~flag; 151 } 152 153 bool HasFlag(ScopeFlags flag) const 154 { 155 return (flags_ & flag) != 0; 156 } 157 158 ArenaVector<Decl *> &Decls() 159 { 160 return decls_; 161 } 162 163 const ArenaVector<Decl *> &Decls() const 164 { 165 return decls_; 166 } 167 168 void SetParent(Scope *parent) 169 { 170 parent_ = parent; 171 } 172 173 Scope *Parent() 174 { 175 return parent_; 176 } 177 178 const Scope *Parent() const 179 { 180 return parent_; 181 } 182 183 const compiler::IRNode *ScopeStart() const 184 { 185 return startIns_; 186 } 187 188 const compiler::IRNode *ScopeEnd() const 189 { 190 return endIns_; 191 } 192 193 void SetScopeStart(const compiler::IRNode *ins) 194 { 195 startIns_ = ins; 196 } 197 198 void SetScopeEnd(const compiler::IRNode *ins) 199 { 200 endIns_ = ins; 201 } 202 203 ir::AstNode *Node() 204 { 205 return node_; 206 } 207 208 const ir::AstNode *Node() const 209 { 210 return node_; 211 } 212 213 void BindNode(ir::AstNode *node) 214 { 215 node_ = node; 216 } 217 218 Variable *AddDecl(ArenaAllocator *allocator, Decl *decl, [[maybe_unused]] ScriptExtension extension) 219 { 220 decls_.push_back(decl); 221 auto options = decl->IsTypeAliasDecl() ? varbinder::ResolveBindingOptions::TYPE_ALIASES 222 : varbinder::ResolveBindingOptions::BINDINGS; 223 return AddBinding(allocator, FindLocal(decl->Name(), options), decl, extension); 224 } 225 226 Variable *AddTsDecl(ArenaAllocator *allocator, Decl *decl, [[maybe_unused]] ScriptExtension extension) 227 { 228 decls_.push_back(decl); 229 return AddBinding(allocator, FindLocal(decl->Name(), ResolveBindingOptions::ALL), decl, extension); 230 } 231 232 template <typename T, typename... Args> 233 T *NewDecl(ArenaAllocator *allocator, Args &&...args); 234 235 template <typename DeclType, typename VariableType> 236 VariableType *AddDecl(ArenaAllocator *allocator, util::StringView name, VariableFlags flags); 237 238 template <typename DeclType = varbinder::LetDecl, typename VariableType = varbinder::LocalVariable> 239 static VariableType *CreateVar(ArenaAllocator *allocator, util::StringView name, VariableFlags flags, 240 ir::AstNode *node); 241 242 template <typename T, typename... Args> 243 Variable *PropagateBinding(ArenaAllocator *allocator, util::StringView name, Args &&...args); 244 245 virtual InsertResult InsertBinding(const util::StringView &name, Variable *var); 246 virtual InsertResult TryInsertBinding(const util::StringView &name, Variable *var); 247 virtual void MergeBindings(VariableMap const &bindings); 248 virtual VariableMap::size_type EraseBinding(const util::StringView &name); 249 250 const VariableMap &Bindings() const 251 { 252 return bindings_; 253 } 254 255 ArenaMap<util::StringView, Variable *> OrderedBindings(ArenaAllocator *allocator) const 256 { 257 ArenaMap<util::StringView, Variable *> result(allocator->Adapter()); 258 result.insert(bindings_.begin(), bindings_.end()); 259 return result; 260 } 261 262 virtual Variable *AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, 263 [[maybe_unused]] ScriptExtension extension) = 0; 264 265 virtual Variable *FindLocal(const util::StringView &name, ResolveBindingOptions options) const; 266 267 bool IsSuperscopeOf(const varbinder::Scope *subscope) const; 268 269 ConstScopeFindResult Find(const util::StringView &name, 270 ResolveBindingOptions options = ResolveBindingOptions::BINDINGS) const; 271 272 ScopeFindResult Find(const util::StringView &name, ResolveBindingOptions options = ResolveBindingOptions::BINDINGS); 273 274 ConstScopeFindResult FindInGlobal(const util::StringView &name, 275 ResolveBindingOptions options = ResolveBindingOptions::BINDINGS) const; 276 277 ConstScopeFindResult FindInFunctionScope(const util::StringView &name, 278 ResolveBindingOptions options = ResolveBindingOptions::BINDINGS) const; 279 280 Decl *FindDecl(const util::StringView &name) const; 281 282protected: 283 explicit Scope(ArenaAllocator *allocator, Scope *parent) 284 : parent_(parent), decls_(allocator->Adapter()), bindings_(allocator->Adapter()) 285 { 286 } 287 288 explicit Scope(ArenaAllocator *allocator, Scope *parent, ScopeFlags flags) 289 : parent_(parent), decls_(allocator->Adapter()), bindings_(allocator->Adapter()), flags_(flags) 290 { 291 } 292 293 /** 294 * @return true - if the variable is shadowed 295 * false - otherwise 296 */ 297 using VariableVisitor = std::function<bool(const Variable *)>; 298 299 /** 300 * @return true - if the variable is shadowed 301 * false - otherwise 302 */ 303 std::tuple<Scope *, bool> IterateShadowedVariables(const util::StringView &name, const VariableVisitor &visitor); 304 305 Variable *AddLocal(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, 306 [[maybe_unused]] ScriptExtension extension); 307 308 Variable *AddLocalVar(ArenaAllocator *allocator, Decl *newDecl); 309 310private: 311 template < 312 typename ResultT, typename ScopeT, 313 std::enable_if_t<std::is_same_v<ResultT, ConstScopeFindResult> || std::is_same_v<ResultT, ScopeFindResult>, 314 bool> = true, 315 std::enable_if_t<std::is_pointer_v<ScopeT> && std::is_base_of_v<Scope, std::remove_pointer_t<ScopeT>>, bool> = 316 true> 317 static ResultT FindImpl(ScopeT &&scope, const util::StringView &name, const ResolveBindingOptions options) 318 { 319 uint32_t level = 0; 320 uint32_t lexLevel = 0; 321 // iter will be the EXACT type of scope with cv-qualifiers 322 auto &&iter = scope; 323 324 if (iter->IsFunctionParamScope()) { 325 auto *const v = iter->FindLocal(name, options); 326 327 if (v != nullptr) { 328 return {name, iter, level, lexLevel, v}; 329 } 330 331 level++; 332 const auto *const funcVariableScope = iter->AsFunctionParamScope()->GetFunctionScope(); 333 334 if (funcVariableScope != nullptr && funcVariableScope->NeedLexEnv()) { 335 lexLevel++; 336 } 337 338 iter = iter->Parent(); 339 } 340 341 while (iter != nullptr) { 342 auto *const v = iter->FindLocal(name, options); 343 344 if (v != nullptr) { 345 return {name, iter, level, lexLevel, v}; 346 } 347 348 if (iter->IsVariableScope()) { 349 level++; 350 351 if (iter->AsVariableScope()->NeedLexEnv()) { 352 lexLevel++; 353 } 354 } 355 356 iter = iter->Parent(); 357 } 358 359 return {name, nullptr, 0, 0, nullptr}; 360 } 361 362 Scope *parent_ {}; 363 ArenaVector<Decl *> decls_; 364 VariableMap bindings_; 365 ir::AstNode *node_ {}; 366 ScopeFlags flags_ {}; 367 const compiler::IRNode *startIns_ {}; 368 const compiler::IRNode *endIns_ {}; 369}; 370 371class VariableScope : public Scope { 372public: 373 ~VariableScope() override = default; 374 NO_COPY_SEMANTIC(VariableScope); 375 NO_MOVE_SEMANTIC(VariableScope); 376 377 uint32_t NextSlot() 378 { 379 return slotIndex_++; 380 } 381 382 uint32_t LexicalSlots() const 383 { 384 return slotIndex_; 385 } 386 387 bool NeedLexEnv() const 388 { 389 return slotIndex_ != 0; 390 } 391 392 uint32_t EvalBindings() const 393 { 394 return evalBindings_; 395 } 396 397 void CheckDirectEval(public_lib::Context *context); 398 399protected: 400 explicit VariableScope(ArenaAllocator *allocator, Scope *parent) : Scope(allocator, parent) {} 401 402 template <typename T> 403 Variable *AddVar(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl); 404 405 template <typename T> 406 Variable *AddFunction(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, 407 [[maybe_unused]] ScriptExtension extension); 408 409 template <typename T> 410 Variable *AddTSBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, VariableFlags flags); 411 412 template <typename T> 413 Variable *AddLexical(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl); 414 415 // NOLINTBEGIN(misc-non-private-member-variables-in-classes) 416 uint32_t evalBindings_ {}; 417 uint32_t slotIndex_ {}; 418 // NOLINTEND(misc-non-private-member-variables-in-classes) 419}; 420 421class ParamScope : public Scope { 422public: 423 ScopeType Type() const override 424 { 425 return ScopeType::PARAM; 426 } 427 428 ArenaVector<LocalVariable *> &Params() 429 { 430 return params_; 431 } 432 433 const ArenaVector<LocalVariable *> &Params() const 434 { 435 return params_; 436 } 437 438 std::tuple<ParameterDecl *, ir::AstNode *, Variable *> AddParamDecl(ArenaAllocator *allocator, ir::AstNode *param); 439 440protected: 441 explicit ParamScope(ArenaAllocator *allocator, Scope *parent) 442 : Scope(allocator, parent), params_(allocator->Adapter()) 443 { 444 } 445 446 Variable *AddParam(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, VariableFlags flags); 447 448 // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes) 449 ArenaVector<LocalVariable *> params_; 450}; 451 452class FunctionScope; 453 454class FunctionParamScope : public ParamScope { 455public: 456 explicit FunctionParamScope(ArenaAllocator *allocator, Scope *parent) : ParamScope(allocator, parent) {} 457 458 FunctionScope *GetFunctionScope() const 459 { 460 return functionScope_; 461 } 462 463 void BindFunctionScope(FunctionScope *funcScope) 464 { 465 functionScope_ = funcScope; 466 } 467 468 LocalVariable *NameVar() const 469 { 470 return nameVar_; 471 } 472 473 void BindName(ArenaAllocator *allocator, util::StringView name); 474 475 ScopeType Type() const override 476 { 477 return ScopeType::FUNCTION_PARAM; 478 } 479 480 Variable *AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, 481 [[maybe_unused]] ScriptExtension extension) override; 482 483 friend class FunctionScope; 484 template <typename E, typename T> 485 friend class ScopeWithParamScope; 486 487private: 488 FunctionScope *functionScope_ {}; 489 LocalVariable *nameVar_ {}; 490}; 491 492template <typename E, typename T> 493class ScopeWithParamScope : public E { 494public: 495 explicit ScopeWithParamScope(ArenaAllocator *allocator, Scope *parent) : E(allocator, parent), paramScope_(nullptr) 496 { 497 } 498 499 void BindParamScope(T *paramScope) 500 { 501 AssignParamScope(paramScope); 502 this->MergeBindings(paramScope->Bindings()); 503 } 504 505 void AssignParamScope(T *paramScope) 506 { 507 ASSERT(this->Parent() == paramScope); 508 paramScope_ = paramScope; 509 } 510 511 T *ParamScope() 512 { 513 return paramScope_; 514 } 515 516 const T *ParamScope() const 517 { 518 return paramScope_; 519 } 520 521protected: 522 // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes) 523 T *paramScope_; 524}; 525 526class LocalScope : public Scope { 527public: 528 explicit LocalScope(ArenaAllocator *allocator, Scope *parent) : Scope(allocator, parent) {} 529 explicit LocalScope(ArenaAllocator *allocator, Scope *parent, ScopeFlags flags) : Scope(allocator, parent, flags) {} 530 531 ScopeType Type() const override 532 { 533 return ScopeType::LOCAL; 534 } 535 536 Variable *AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, 537 [[maybe_unused]] ScriptExtension extension) override; 538}; 539 540class LocalScopeWithTypeAlias : public LocalScope { 541public: 542 explicit LocalScopeWithTypeAlias(ArenaAllocator *allocator, Scope *parent) 543 : LocalScope(allocator, parent), 544 typeAliasScope_(allocator->New<LocalScope>(allocator, this, ScopeFlags::TYPE_ALIAS)) 545 { 546 } 547 explicit LocalScopeWithTypeAlias(ArenaAllocator *allocator, Scope *parent, ScopeFlags flags) 548 : LocalScope(allocator, parent, flags), 549 typeAliasScope_(allocator->New<LocalScope>(allocator, this, ScopeFlags::TYPE_ALIAS)) 550 { 551 } 552 553 Variable *FindLocal(const util::StringView &name, ResolveBindingOptions options) const override; 554 555 Variable *AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, 556 [[maybe_unused]] ScriptExtension extension) override; 557 558 const LocalScope *TypeAliasScope() const 559 { 560 return typeAliasScope_; 561 } 562 563 LocalScope *TypeAliasScope() 564 { 565 return typeAliasScope_; 566 } 567 568private: 569 LocalScope *typeAliasScope_; 570}; 571 572class FunctionScope : public ScopeWithParamScope<VariableScope, FunctionParamScope> { 573public: 574 explicit FunctionScope(ArenaAllocator *allocator, Scope *parent) 575 : ScopeWithParamScope(allocator, parent), 576 typeAliasScope_(allocator->New<LocalScope>(allocator, this, ScopeFlags::TYPE_ALIAS)) 577 { 578 } 579 580 ScopeType Type() const override 581 { 582 return ScopeType::FUNCTION; 583 } 584 585 void BindName(util::StringView name) 586 { 587 name_ = name; 588 } 589 590 void BindInternalName(util::StringView internalName) 591 { 592 internalName_ = internalName; 593 } 594 595 const util::StringView &Name() const 596 { 597 return name_; 598 } 599 600 const util::StringView &InternalName() const 601 { 602 return internalName_; 603 } 604 605 const LocalScope *TypeAliasScope() const 606 { 607 return typeAliasScope_; 608 } 609 610 Variable *FindLocal(const util::StringView &name, ResolveBindingOptions options) const override; 611 612 Variable *AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, 613 [[maybe_unused]] ScriptExtension extension) override; 614 615private: 616 util::StringView name_ {}; 617 util::StringView internalName_ {}; 618 LocalScope *typeAliasScope_; 619}; 620 621class ClassScope : public LocalScopeWithTypeAlias { 622public: 623 explicit ClassScope(ArenaAllocator *allocator, Scope *parent) 624 : LocalScopeWithTypeAlias(allocator, parent), 625 staticDeclScope_(allocator->New<LocalScope>(allocator, this, ScopeFlags::STATIC_DECL_SCOPE)), 626 staticFieldScope_(allocator->New<LocalScope>(allocator, staticDeclScope_, ScopeFlags::STATIC_FIELD_SCOPE)), 627 staticMethodScope_(allocator->New<LocalScope>(allocator, staticFieldScope_, ScopeFlags::STATIC_METHOD_SCOPE)), 628 instanceDeclScope_(allocator->New<LocalScope>(allocator, staticMethodScope_, ScopeFlags::DECL_SCOPE)), 629 instanceFieldScope_(allocator->New<LocalScope>(allocator, instanceDeclScope_, ScopeFlags::FIELD_SCOPE)), 630 instanceMethodScope_(allocator->New<LocalScope>(allocator, instanceFieldScope_, ScopeFlags::METHOD_SCOPE)) 631 { 632 } 633 634 ScopeType Type() const override 635 { 636 return ScopeType::CLASS; 637 } 638 639 LocalScope *StaticDeclScope() 640 { 641 return staticDeclScope_; 642 } 643 644 const LocalScope *StaticDeclScope() const 645 { 646 return staticDeclScope_; 647 } 648 649 LocalScope *StaticFieldScope() 650 { 651 return staticFieldScope_; 652 } 653 654 const LocalScope *StaticFieldScope() const 655 { 656 return staticFieldScope_; 657 } 658 659 LocalScope *StaticMethodScope() 660 { 661 return staticMethodScope_; 662 } 663 664 const LocalScope *StaticMethodScope() const 665 { 666 return staticMethodScope_; 667 } 668 669 LocalScope *InstanceFieldScope() 670 { 671 return instanceFieldScope_; 672 } 673 674 const LocalScope *InstanceFieldScope() const 675 { 676 return instanceFieldScope_; 677 } 678 679 LocalScope *InstanceMethodScope() 680 { 681 return instanceMethodScope_; 682 } 683 684 const LocalScope *InstanceMethodScope() const 685 { 686 return instanceMethodScope_; 687 } 688 689 LocalScope *InstanceDeclScope() 690 { 691 return instanceDeclScope_; 692 } 693 694 const LocalScope *InstanceDeclScope() const 695 { 696 return instanceDeclScope_; 697 } 698 699 uint32_t GetAndIncrementAnonymousClassIdx() const 700 { 701 return anonymousClassIdx_++; 702 } 703 704 Variable *FindLocal(const util::StringView &name, ResolveBindingOptions options) const override; 705 706 Variable *AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, 707 [[maybe_unused]] ScriptExtension extension) override; 708 709 class BindingProps { 710 public: 711 BindingProps() = default; 712 713 void SetFlagsType(VariableFlags flagsType) 714 { 715 flags_ |= flagsType; 716 } 717 void SetBindingProps(VariableFlags flags, ir::Identifier *ident, LocalScope *targetScope) 718 { 719 flags_ |= flags; 720 ident_ = ident; 721 targetScope_ = targetScope; 722 } 723 VariableFlags GetFlags() const 724 { 725 return flags_; 726 } 727 ir::Identifier *GetIdent() 728 { 729 return ident_; 730 } 731 LocalScope *GetTargetScope() 732 { 733 return targetScope_; 734 } 735 736 private: 737 VariableFlags flags_ = VariableFlags::NONE; 738 ir::Identifier *ident_ {}; 739 LocalScope *targetScope_ {}; 740 }; 741 742 void SetBindingProps(Decl *newDecl, BindingProps *props, bool isStatic); 743 744private: 745 LocalScope *staticDeclScope_; 746 LocalScope *staticFieldScope_; 747 LocalScope *staticMethodScope_; 748 LocalScope *instanceDeclScope_; 749 LocalScope *instanceFieldScope_; 750 LocalScope *instanceMethodScope_; 751 mutable uint32_t anonymousClassIdx_ {1}; 752}; 753 754class CatchParamScope : public ParamScope { 755public: 756 explicit CatchParamScope(ArenaAllocator *allocator, Scope *parent) : ParamScope(allocator, parent) {} 757 758 ScopeType Type() const override 759 { 760 return ScopeType::CATCH_PARAM; 761 } 762 763 Variable *AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, 764 [[maybe_unused]] ScriptExtension extension) override; 765 766 friend class CatchScope; 767}; 768 769class CatchScope : public ScopeWithParamScope<LocalScopeWithTypeAlias, CatchParamScope> { 770public: 771 explicit CatchScope(ArenaAllocator *allocator, Scope *parent) : ScopeWithParamScope(allocator, parent) {} 772 773 ScopeType Type() const override 774 { 775 return ScopeType::CATCH; 776 } 777 778 Variable *AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, 779 [[maybe_unused]] ScriptExtension extension) override; 780}; 781 782class LoopScope; 783 784class LoopDeclarationScope : public VariableScope { 785public: 786 explicit LoopDeclarationScope(ArenaAllocator *allocator, Scope *parent) : VariableScope(allocator, parent) {} 787 788 ScopeType Type() const override 789 { 790 return loopType_; 791 } 792 793 Variable *AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, 794 [[maybe_unused]] ScriptExtension extension) override 795 { 796 return AddLocal(allocator, currentVariable, newDecl, extension); 797 } 798 799 Scope *InitScope() 800 { 801 if (NeedLexEnv()) { 802 return initScope_; 803 } 804 805 return this; 806 } 807 808 void ConvertToVariableScope(ArenaAllocator *allocator); 809 810private: 811 friend class LoopScope; 812 LoopScope *loopScope_ {}; 813 LocalScope *initScope_ {}; 814 ScopeType loopType_ {ScopeType::LOCAL}; 815}; 816 817class LoopScope : public VariableScope { 818public: 819 explicit LoopScope(ArenaAllocator *allocator, Scope *parent) : VariableScope(allocator, parent) 820 { 821 // NOTE(kkonkuznetsov): currently LoopScope type has ScopeType::LOCAL 822 // therefore it does not respond to IsLoopScope() because it checks for type. 823 // This LOOP_SCOPE flag can be used to check that scope is actually a loop scope. 824 AddFlag(ScopeFlags::LOOP_SCOPE); 825 } 826 827 LoopDeclarationScope *DeclScope() 828 { 829 return declScope_; 830 } 831 832 void BindDecls(LoopDeclarationScope *declScope) 833 { 834 declScope_ = declScope; 835 declScope_->loopScope_ = this; 836 } 837 838 ScopeType Type() const override 839 { 840 return loopType_; 841 } 842 843 void ConvertToVariableScope(ArenaAllocator *allocator); 844 845 Variable *AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, 846 [[maybe_unused]] ScriptExtension extension) override 847 { 848 return AddLocal(allocator, currentVariable, newDecl, extension); 849 } 850 851protected: 852 // NOLINTBEGIN(misc-non-private-member-variables-in-classes) 853 LoopDeclarationScope *declScope_ {}; 854 ScopeType loopType_ {ScopeType::LOCAL}; 855 // NOLINTEND(misc-non-private-member-variables-in-classes) 856}; 857 858class GlobalScope : public FunctionScope { 859public: 860 explicit GlobalScope(ArenaAllocator *allocator) 861 : FunctionScope(allocator, nullptr), foreignBindings_(allocator->Adapter()) 862 { 863 auto *paramScope = allocator->New<FunctionParamScope>(allocator, this); 864 paramScope_ = paramScope; 865 paramScope_->BindFunctionScope(this); 866 } 867 868 ScopeType Type() const override 869 { 870 return ScopeType::GLOBAL; 871 } 872 873 Variable *AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, 874 [[maybe_unused]] ScriptExtension extension) override; 875 876 InsertResult InsertBinding(const util::StringView &name, Variable *var) override; 877 InsertResult TryInsertBinding(const util::StringView &name, Variable *var) override; 878 void MergeBindings(VariableMap const &bindings) override; 879 VariableMap::size_type EraseBinding(const util::StringView &name) override; 880 881 InsertResult InsertForeignBinding(const util::StringView &name, Variable *var); 882 [[nodiscard]] bool IsForeignBinding(const util::StringView &name) const; 883 884 InsertResult InsertDynamicBinding(const util::StringView &name, Variable *var); 885 886private: 887 InsertResult InsertImpl(const util::StringView &name, Variable *var, bool isForeign, bool isDynamic); 888 889 ArenaUnorderedMap<util::StringView, bool> foreignBindings_; 890}; 891 892class ModuleScope : public GlobalScope { 893public: 894 template <typename K, typename V> 895 using ModuleEntry = ArenaVector<std::pair<K, V>>; 896 using ImportDeclList = ArenaVector<ImportDecl *>; 897 using ExportDeclList = ArenaVector<ExportDecl *>; 898 using LocalExportNameMap = ArenaMultiMap<varbinder::Variable *, util::StringView>; 899 900 explicit ModuleScope(ArenaAllocator *allocator) 901 : GlobalScope(allocator), 902 allocator_(allocator), 903 imports_(allocator_->Adapter()), 904 exports_(allocator_->Adapter()), 905 localExports_(allocator_->Adapter()) 906 { 907 } 908 909 ScopeType Type() const override 910 { 911 return ScopeType::MODULE; 912 } 913 914 const ModuleEntry<ir::ImportDeclaration *, ImportDeclList> &Imports() const 915 { 916 return imports_; 917 } 918 919 const ModuleEntry<ir::AstNode *, ExportDeclList> &Exports() const 920 { 921 return exports_; 922 } 923 924 const LocalExportNameMap &LocalExports() const 925 { 926 return localExports_; 927 } 928 929 void AddImportDecl(ir::ImportDeclaration *importDecl, ImportDeclList &&decls); 930 931 void AddExportDecl(ir::AstNode *exportDecl, ExportDecl *decl); 932 933 void AddExportDecl(ir::AstNode *exportDecl, ExportDeclList &&decls); 934 935 Variable *AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, 936 [[maybe_unused]] ScriptExtension extension) override; 937 938 bool ExportAnalysis(); 939 940private: 941 Variable *AddImport(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl); 942 943 ArenaAllocator *allocator_; 944 ModuleEntry<ir::ImportDeclaration *, ImportDeclList> imports_; 945 ModuleEntry<ir::AstNode *, ExportDeclList> exports_; 946 LocalExportNameMap localExports_; 947}; 948 949template <typename T> 950Variable *VariableScope::AddVar(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl) 951{ 952 if (!currentVariable) { 953 return InsertBinding(newDecl->Name(), allocator->New<T>(newDecl, VariableFlags::HOIST_VAR)).first->second; 954 } 955 956 switch (currentVariable->Declaration()->Type()) { 957 case DeclType::VAR: { 958 currentVariable->Reset(newDecl, VariableFlags::HOIST_VAR); 959 [[fallthrough]]; 960 } 961 case DeclType::PARAM: 962 case DeclType::FUNC: { 963 return currentVariable; 964 } 965 default: { 966 return nullptr; 967 } 968 } 969} 970 971template <typename T> 972Variable *VariableScope::AddFunction(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, 973 [[maybe_unused]] ScriptExtension extension) 974{ 975 VariableFlags flags = (extension == ScriptExtension::JS) ? VariableFlags::HOIST_VAR : VariableFlags::HOIST; 976 977 if (!currentVariable) { 978 return InsertBinding(newDecl->Name(), allocator->New<T>(newDecl, flags)).first->second; 979 } 980 981 if (extension != ScriptExtension::JS || IsModuleScope()) { 982 return nullptr; 983 } 984 985 switch (currentVariable->Declaration()->Type()) { 986 case DeclType::VAR: 987 case DeclType::FUNC: { 988 currentVariable->Reset(newDecl, VariableFlags::HOIST_VAR); 989 return currentVariable; 990 } 991 default: { 992 return nullptr; 993 } 994 } 995} 996 997template <typename T> 998Variable *VariableScope::AddTSBinding(ArenaAllocator *allocator, [[maybe_unused]] Variable *currentVariable, 999 Decl *newDecl, VariableFlags flags) 1000{ 1001 ASSERT(!currentVariable); 1002 return InsertBinding(newDecl->Name(), allocator->New<T>(newDecl, flags)).first->second; 1003} 1004 1005template <typename T> 1006Variable *VariableScope::AddLexical(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl) 1007{ 1008 if (currentVariable) { 1009 return nullptr; 1010 } 1011 1012 return InsertBinding(newDecl->Name(), allocator->New<T>(newDecl, VariableFlags::NONE)).first->second; 1013} 1014 1015template <typename T, typename... Args> 1016T *Scope::NewDecl(ArenaAllocator *allocator, Args &&...args) 1017{ 1018 T *decl = allocator->New<T>(std::forward<Args>(args)...); 1019 decls_.push_back(decl); 1020 1021 return decl; 1022} 1023 1024template <typename DeclType, typename VariableType> 1025VariableType *Scope::AddDecl(ArenaAllocator *allocator, util::StringView name, VariableFlags flags) 1026{ 1027 if (FindLocal(name, varbinder::ResolveBindingOptions::BINDINGS)) { 1028 return nullptr; 1029 } 1030 1031 auto *decl = allocator->New<DeclType>(name); 1032 auto *variable = allocator->New<VariableType>(decl, flags); 1033 1034 decls_.push_back(decl); 1035 bindings_.insert({decl->Name(), variable}); 1036 variable->SetScope(this); 1037 1038 return variable; 1039} 1040 1041template <typename DeclType, typename VariableType> 1042VariableType *Scope::CreateVar(ArenaAllocator *allocator, util::StringView name, VariableFlags flags, ir::AstNode *node) 1043{ 1044 auto *decl = allocator->New<DeclType>(name); 1045 auto *variable = allocator->New<VariableType>(decl, flags); 1046 decl->BindNode(node); 1047 return variable; 1048} 1049 1050template <typename T, typename... Args> 1051Variable *Scope::PropagateBinding(ArenaAllocator *allocator, util::StringView name, Args &&...args) 1052{ 1053 auto res = bindings_.find(name); 1054 if (res == bindings_.end()) { 1055 return bindings_.insert({name, allocator->New<T>(std::forward<Args>(args)...)}).first->second; 1056 } 1057 1058 res->second->Reset(std::forward<Args>(args)...); 1059 return res->second; 1060} 1061} // namespace ark::es2panda::varbinder 1062 1063#endif 1064