1/** 2 * Copyright (c) 2021 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 <binder/declaration.h> 20#include <binder/variable.h> 21#include <parser/program/program.h> 22#include <util/enumbitops.h> 23#include <util/ustring.h> 24 25#include <map> 26#include <unordered_map> 27#include <vector> 28 29namespace panda::es2panda::compiler { 30class IRNode; 31} // namespace panda::es2panda::compiler 32 33namespace panda::es2panda::ir { 34class ScriptFunction; 35class Statement; 36} // namespace panda::es2panda::ir 37 38namespace panda::es2panda::parser { 39class Program; 40} // namespace panda::es2panda::parser 41 42namespace panda::es2panda::binder { 43 44#define DECLARE_CLASSES(type, className) class className; 45SCOPE_TYPES(DECLARE_CLASSES) 46#undef DECLARE_CLASSES 47 48class Scope; 49class VariableScope; 50class Variable; 51 52using VariableMap = ArenaMap<util::StringView, Variable *>; 53 54class TSBindings { 55public: 56 explicit TSBindings(ArenaAllocator *allocator) : allocator_(allocator) {} 57 58 template <TSBindingType type> 59 bool AddTSVariable(const util::StringView &name, Variable *variable) 60 { 61 static_assert(type < TSBindingType::COUNT); 62 size_t index = GetIndex(type); 63 if (tsBindings_[index] == nullptr) { 64 tsBindings_[index] = allocator_->New<VariableMap>(allocator_->Adapter()); 65 } 66 return tsBindings_[index]->insert({name, variable}).second; 67 } 68 69 template <TSBindingType type> 70 Variable *FindTSVariable(const util::StringView &name) const 71 { 72 static_assert(type < TSBindingType::COUNT); 73 size_t index = GetIndex(type); 74 if (tsBindings_[index] == nullptr) { 75 return nullptr; 76 } 77 auto res = tsBindings_[index]->find(name); 78 if (res == tsBindings_[index]->end()) { 79 return nullptr; 80 } 81 return res->second; 82 } 83 84 bool InTSBindings(const util::StringView &name) const 85 { 86 for (size_t i = 0; i < GetIndex(TSBindingType::COUNT); i++) { 87 if (tsBindings_[i] && tsBindings_[i]->find(name) != tsBindings_[i]->end()) { 88 return true; 89 } 90 } 91 return false; 92 } 93 94private: 95 size_t GetIndex(TSBindingType type) const 96 { 97 return static_cast<size_t>(type); 98 } 99 100 ArenaAllocator *allocator_; 101 std::array<VariableMap *, static_cast<size_t>(TSBindingType::COUNT)> tsBindings_ {}; 102}; 103 104class ExportBindings { 105public: 106 explicit ExportBindings(ArenaAllocator *allocator) 107 : exportBindings_(allocator->Adapter()), 108 exportTSBindings_(allocator) 109 { 110 } 111 112 Variable *FindExportVariable(const util::StringView &name) const 113 { 114 auto res = exportBindings_.find(name); 115 if (res == exportBindings_.end()) { 116 return nullptr; 117 } 118 return res->second; 119 } 120 121 bool AddExportVariable(const util::StringView &name, Variable *var) 122 { 123 return exportBindings_.insert({name, var}).second; 124 } 125 126 bool InExportBindings(const util::StringView &name) const 127 { 128 auto res = FindExportVariable(name); 129 return res != nullptr || exportTSBindings_.InTSBindings(name); 130 } 131 132 template <TSBindingType type> 133 Variable *FindExportTSVariable(const util::StringView &name) const 134 { 135 return exportTSBindings_.FindTSVariable<type>(name); 136 } 137 138 template <TSBindingType type> 139 bool AddExportTSVariable(const util::StringView &name, Variable *var) 140 { 141 return exportTSBindings_.AddTSVariable<type>(name, var); 142 } 143 144private: 145 VariableMap exportBindings_; 146 TSBindings exportTSBindings_; 147}; 148 149class ScopeFindResult { 150public: 151 ScopeFindResult() = default; 152 ScopeFindResult(util::StringView n, Scope *s, uint32_t l, Variable *v) 153 : ScopeFindResult(n, s, l, l, l, v, nullptr) 154 { 155 } 156 ScopeFindResult(Scope *s, uint32_t l, uint32_t ll, Variable *v) : scope(s), level(l), lexLevel(ll), variable(v) {} 157 ScopeFindResult(util::StringView n, Scope *s, uint32_t l, uint32_t ll, uint32_t sl, 158 Variable *v, ir::ScriptFunction *c) 159 : name(n), scope(s), level(l), lexLevel(ll), sendableLevel(sl), variable(v), concurrentFunc(c) 160 { 161 } 162 163 util::StringView name {}; 164 Scope *scope {}; 165 uint32_t level {}; 166 uint32_t lexLevel {}; 167 uint32_t sendableLevel {}; 168 Variable *variable {}; 169 ir::ScriptFunction *concurrentFunc {}; 170}; 171 172class Result { 173public: 174 uint32_t slot; 175 bool isMethod; 176 bool isStatic; 177 bool isGetter; 178 bool isSetter; 179 uint32_t validateMethodSlot; 180}; 181 182class PrivateNameFindResult { 183public: 184 int32_t lexLevel; 185 Result result; 186}; 187 188 189class Scope { 190public: 191 virtual ~Scope() = default; 192 NO_COPY_SEMANTIC(Scope); 193 NO_MOVE_SEMANTIC(Scope); 194 195 virtual ScopeType Type() const = 0; 196 197#define DECLARE_CHECKS_CASTS(scopeType, className) \ 198 bool Is##className() const \ 199 { \ 200 return Type() == ScopeType::scopeType; \ 201 } \ 202 className *As##className() \ 203 { \ 204 ASSERT(Is##className()); \ 205 return reinterpret_cast<className *>(this); \ 206 } \ 207 const className *As##className() const \ 208 { \ 209 ASSERT(Is##className()); \ 210 return reinterpret_cast<const className *>(this); \ 211 } 212 SCOPE_TYPES(DECLARE_CHECKS_CASTS) 213#undef DECLARE_CHECKS_CASTS 214 215 virtual bool IsVariableScope() const 216 { 217 return Type() > ScopeType::LOCAL; 218 } 219 220 bool IsFunctionVariableScope() const 221 { 222 return Type() >= ScopeType::FUNCTION; 223 } 224 225 FunctionScope *AsFunctionVariableScope() 226 { 227 ASSERT(IsFunctionVariableScope()); 228 return reinterpret_cast<FunctionScope *>(this); 229 } 230 231 const FunctionScope *AsFunctionVariableScope() const 232 { 233 ASSERT(IsFunctionVariableScope()); 234 return reinterpret_cast<const FunctionScope *>(this); 235 } 236 237 VariableScope *AsVariableScope() 238 { 239 ASSERT(IsVariableScope()); 240 return reinterpret_cast<VariableScope *>(this); 241 } 242 243 const VariableScope *AsVariableScope() const 244 { 245 ASSERT(IsVariableScope()); 246 return reinterpret_cast<const VariableScope *>(this); 247 } 248 249 VariableScope *EnclosingVariableScope(); 250 251 FunctionScope *EnclosingFunctionVariableScope(); 252 253 const ArenaVector<Decl *> &Decls() const 254 { 255 return decls_; 256 } 257 258 Scope *Parent() 259 { 260 return parent_; 261 } 262 263 const Scope *Parent() const 264 { 265 return parent_; 266 } 267 268 void SetParent(Scope *parent) 269 { 270 parent_ = parent; 271 SetTopScope(); 272 } 273 274 const compiler::IRNode *ScopeStart() const 275 { 276 return startIns_; 277 } 278 279 const compiler::IRNode *ScopeEnd() const 280 { 281 return endIns_; 282 } 283 284 void SetScopeStart(const compiler::IRNode *ins) 285 { 286 startIns_ = ins; 287 } 288 289 void SetScopeEnd(const compiler::IRNode *ins) 290 { 291 endIns_ = ins; 292 } 293 294 const ir::AstNode *Node() const 295 { 296 return node_; 297 } 298 299 ir::AstNode *Node() 300 { 301 return node_; 302 } 303 304 void BindNode(ir::AstNode *node) 305 { 306 node_ = node; 307 } 308 309 bool AddDecl(ArenaAllocator *allocator, Decl *decl, [[maybe_unused]] ScriptExtension extension) 310 { 311 CHECK_NOT_NULL(decl); 312 decls_.push_back(decl); 313 return AddBinding(allocator, FindLocal(decl->Name()), decl, extension); 314 } 315 316 bool AddTsDecl(ArenaAllocator *allocator, Decl *decl, [[maybe_unused]] ScriptExtension extension) 317 { 318 decls_.push_back(decl); 319 return AddBinding(allocator, FindLocal(decl->Name(), ResolveBindingOptions::ALL), decl, extension); 320 } 321 322 virtual bool HasParamScope() 323 { 324 return false; 325 } 326 327 template <typename T, typename... Args> 328 T *NewDecl(ArenaAllocator *allocator, Args &&... args); 329 330 template <typename DeclType, typename VariableType> 331 VariableType *AddDecl(ArenaAllocator *allocator, util::StringView name, VariableFlags flags); 332 333 template <typename DeclType = binder::LetDecl, typename VariableType = binder::LocalVariable> 334 static VariableType *CreateVar(ArenaAllocator *allocator, util::StringView name, VariableFlags flags, 335 const ir::AstNode *node); 336 337 template <typename T, typename... Args> 338 void PropagateBinding(ArenaAllocator *allocator, util::StringView name, Args &&... args); 339 340 VariableMap &Bindings() 341 { 342 return bindings_; 343 } 344 345 const VariableMap &Bindings() const 346 { 347 return bindings_; 348 } 349 350 virtual bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, 351 [[maybe_unused]] ScriptExtension extension) = 0; 352 353 Variable *FindLocal(const util::StringView &name, 354 ResolveBindingOptions options = ResolveBindingOptions::BINDINGS) const; 355 356 ScopeFindResult Find(const util::StringView &name, 357 ResolveBindingOptions options = ResolveBindingOptions::BINDINGS) const; 358 359 std::pair<uint32_t, uint32_t> Find(const ir::Expression *expr, bool onlyLevel = false) const; 360 361 PrivateNameFindResult FindPrivateName(const util::StringView &name, bool isSetter = false) const; 362 363 Decl *FindDecl(const util::StringView &name) const; 364 365 bool HasVarDecl(const util::StringView &name) const; 366 367 void CalculateLevelInCorrespondingFunctionScope(const FunctionParamScope *scope, uint32_t &lexLevel, 368 uint32_t &sendableLevel) const; 369 370 template <TSBindingType type> 371 Variable *FindLocalTSVariable(const util::StringView &name) const 372 { 373 return tsBindings_.FindTSVariable<type>(name); 374 } 375 376 template <TSBindingType type> 377 void AddLocalTSVariable(const util::StringView &name, Variable *var) 378 { 379 tsBindings_.AddTSVariable<type>(name, var); 380 } 381 382 bool InLocalTSBindings(const util::StringView &name) const 383 { 384 return tsBindings_.InTSBindings(name); 385 } 386 387 virtual const util::StringView &GetFullScopeName() 388 { 389 // Most scopes have no scopeName therefore their fullScopeNames should be got from their parents 390 if (parent_) { 391 return parent_->GetFullScopeName(); 392 } 393 return fullScopeName_; 394 } 395 396 virtual uint32_t GetDuplicateScopeIndex(const util::StringView &childScopeName) 397 { 398 // Most sub class has no scope name, so as duplicate index, need to get from parent. 399 if (parent_) { 400 return parent_->GetDuplicateScopeIndex(childScopeName); 401 } 402 403 return 0; 404 } 405 406 virtual void SetSelfScopeName(const util::StringView &ident) 407 { 408 if (hasSelfScopeNameSet_) { 409 return; 410 } 411 hasSelfScopeNameSet_ = true; 412 413 if (!util::Helpers::IsSpecialScopeName(ident)) { 414 selfScopeName_ = ident; 415 } 416 417 Scope *parent = GetParentWithScopeName(); 418 if (parent != nullptr) { 419 std::stringstream selfScopeName; 420 selfScopeName << GetScopeTag() << selfScopeName_; 421 scopeDuplicateIndex_ = parent->GetDuplicateScopeIndex( 422 util::UString(selfScopeName.str(), allocator_).View()); 423 } 424 } 425 426 ArenaUnorderedMap<util::StringView, int32_t> &GetScopeNames() 427 { 428 return topScope_->scopeNames_; 429 } 430 431protected: 432 explicit Scope(ArenaAllocator *allocator, Scope *parent) 433 : parent_(parent), 434 decls_(allocator->Adapter()), 435 bindings_(allocator->Adapter()), 436 tsBindings_(allocator), 437 scopesIndex_(allocator->Adapter()), 438 scopeNames_(allocator->Adapter()), 439 allocator_(allocator) 440 { 441 SetTopScope(); 442 } 443 444 /** 445 * @return true - if the variable is shadowed 446 * false - otherwise 447 */ 448 using VariableVisitior = std::function<bool(const Variable *)>; 449 450 /** 451 * @return true - if the variable is shadowed 452 * false - otherwise 453 */ 454 std::tuple<Scope *, bool> IterateShadowedVariables(const util::StringView &name, const VariableVisitior &visitor); 455 456 bool AddLocal(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, 457 [[maybe_unused]] ScriptExtension extension); 458 459 void SetFullScopeNames(); 460 461 void SetTopScope() 462 { 463 if (parent_) { 464 topScope_ = parent_->GetTopScope(); 465 } else { 466 topScope_ = this; 467 } 468 } 469 470 void OptimizeSelfScopeName(std::stringstream &selfScopeStream); 471 472 virtual Scope *GetParentWithScopeName() 473 { 474 return parent_; 475 } 476 477 virtual util::StringView GetSelfScopeName() 478 { 479 if (hasSelfScopeNameSet_) { 480 return selfScopeName_; 481 } 482 483 std::stringstream scopeName; 484 485 if (scopeDuplicateIndex_ > 0) { 486 scopeName << util::Helpers::DUPLICATED_SEPERATOR << 487 std::hex << scopeDuplicateIndex_; 488 } 489 490 return util::UString(scopeName.str(), allocator_).View(); 491 } 492 493 Scope *GetTopScope() 494 { 495 return topScope_; 496 } 497 498 Scope *parent_ {}; 499 Scope *topScope_ {}; 500 ArenaVector<Decl *> decls_; 501 VariableMap bindings_; 502 TSBindings tsBindings_; 503 ir::AstNode *node_ {}; 504 const compiler::IRNode *startIns_ {}; 505 const compiler::IRNode *endIns_ {}; 506 ArenaUnorderedMap<util::StringView, uint32_t> scopesIndex_; 507 ArenaUnorderedMap<util::StringView, int32_t> scopeNames_; 508 util::StringView fullScopeName_ {}; 509 ArenaAllocator *allocator_ {}; 510 uint32_t scopeDuplicateIndex_ = 0; 511 util::StringView selfScopeName_ {}; 512 bool hasSelfScopeNameSet_ { false }; 513 bool hasFullScopeNameSet_ { false }; 514 515private: 516 virtual util::StringView GetScopeTag() 517 { 518 return util::UString(util::Helpers::STRING_EMPTY.data(), allocator_).View(); 519 } 520}; 521 522class VariableScope : public Scope { 523public: 524 ~VariableScope() override = default; 525 NO_COPY_SEMANTIC(VariableScope); 526 NO_MOVE_SEMANTIC(VariableScope); 527 528 void AddFlag(VariableScopeFlags flag) 529 { 530 flags_ |= flag; 531 } 532 533 void ClearFlag(VariableScopeFlags flag) 534 { 535 flags_ &= ~flag; 536 } 537 538 bool HasFlag(VariableScopeFlags flag) const 539 { 540 return (flags_ & flag) != 0; 541 } 542 543 void RestoreFuncMain0LexEnv(uint32_t slotSize) 544 { 545 slotIndex_ = slotSize; 546 } 547 548 uint32_t NextSlot() 549 { 550 return slotIndex_++; 551 } 552 553 uint32_t NextSendableSlot() 554 { 555 return sendableSlotIndex_++; 556 } 557 558 uint32_t LexicalSlots() const 559 { 560 return slotIndex_; 561 } 562 563 uint32_t SendableSlots() const 564 { 565 return sendableSlotIndex_; 566 } 567 568 bool NeedLexEnv() const 569 { 570 return slotIndex_ != 0; 571 } 572 573 bool NeedSendableEnv() const 574 { 575 return sendableSlotIndex_ != 0; 576 } 577 578 void AddLexicalVarNameAndType(uint32_t slot, util::StringView name, int type) 579 { 580 lexicalVarNameAndTypes_.emplace(slot, std::pair<util::StringView, int>(name, type)); 581 } 582 583 ArenaMap<uint32_t, std::pair<util::StringView, int>> &GetLexicalVarNameAndTypes() 584 { 585 return lexicalVarNameAndTypes_; 586 } 587 588protected: 589 explicit VariableScope(ArenaAllocator *allocator, Scope *parent) : Scope(allocator, parent), 590 lexicalVarNameAndTypes_(allocator->Adapter()) {} 591 592 inline VariableFlags DeclFlagToVariableFlag(DeclarationFlags declFlag); 593 594 template <typename T> 595 bool AddVar(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl); 596 597 template <typename T> 598 bool AddFunction(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, 599 [[maybe_unused]] ScriptExtension extension); 600 601 template <typename T> 602 bool AddClass(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl); 603 604 template <typename T> 605 bool AddTSBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, VariableFlags flags); 606 607 template <typename T> 608 bool AddTSBinding(ArenaAllocator *allocator, Decl *newDecl, VariableFlags flags); 609 610 template <typename T> 611 bool AddLexical(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl); 612 613 VariableScopeFlags flags_ {}; 614 uint32_t slotIndex_ {}; 615 uint32_t sendableSlotIndex_ {}; 616 ArenaMap<uint32_t, std::pair<util::StringView, int>> lexicalVarNameAndTypes_; // for debuginfo and patchFix 617}; 618 619class ParamScope : public Scope { 620public: 621 ScopeType Type() const override 622 { 623 return ScopeType::PARAM; 624 } 625 626 ArenaVector<LocalVariable *> &Params() 627 { 628 return params_; 629 } 630 631 const ArenaVector<LocalVariable *> &Params() const 632 { 633 return params_; 634 } 635 636 bool HasParam(util::StringView name) const 637 { 638 for (auto *param : params_) { 639 if (param->Name() == name) { 640 return true; 641 } 642 } 643 644 return false; 645 } 646 647 std::tuple<ParameterDecl *, const ir::AstNode *> AddParamDecl(ArenaAllocator *allocator, const ir::AstNode *param); 648 649protected: 650 explicit ParamScope(ArenaAllocator *allocator, Scope *parent) 651 : Scope(allocator, parent), params_(allocator->Adapter()) 652 { 653 } 654 655 bool AddParam(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, VariableFlags flags); 656 657 ArenaVector<LocalVariable *> params_; 658}; 659 660class FunctionScope; 661 662class FunctionParamScope : public ParamScope { 663public: 664 explicit FunctionParamScope(ArenaAllocator *allocator, Scope *parent) : ParamScope(allocator, parent) {} 665 666 FunctionScope *GetFunctionScope() const 667 { 668 return functionScope_; 669 } 670 671 void BindFunctionScope(FunctionScope *funcScope) 672 { 673 functionScope_ = funcScope; 674 } 675 676 LocalVariable *NameVar() const 677 { 678 return nameVar_; 679 } 680 681 void BindName(ArenaAllocator *allocator, util::StringView name); 682 683 ScopeType Type() const override 684 { 685 return ScopeType::FUNCTION_PARAM; 686 } 687 688 bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, 689 [[maybe_unused]] ScriptExtension extension) override; 690 691 void RemoveThisParam(const std::string_view &thisParam) 692 { 693 params_.erase(params_.begin()); 694 bindings_.erase(thisParam); 695 } 696 697 const util::StringView &GetFullScopeName() override; 698 uint32_t GetDuplicateScopeIndex(const util::StringView &childScopeName) override; 699 700 friend class FunctionScope; 701 template <typename E, typename T> 702 friend class ScopeWithParamScope; 703 704private: 705 FunctionScope *functionScope_ {}; 706 LocalVariable *nameVar_ {}; 707}; 708 709template <typename E, typename T> 710class ScopeWithParamScope : public E { 711public: 712 explicit ScopeWithParamScope(ArenaAllocator *allocator, Scope *parent) : E(allocator, parent) {} 713 714 void BindParamScope(T *paramScope) 715 { 716 CHECK_NOT_NULL(paramScope); 717 AssignParamScope(paramScope); 718 this->bindings_ = paramScope->Bindings(); 719 } 720 721 void AssignParamScope(T *paramScope) 722 { 723 ASSERT(this->parent_ == paramScope); 724 ASSERT(this->bindings_.empty()); 725 726 paramScope_ = paramScope; 727 } 728 729 T *ParamScope() 730 { 731 return paramScope_; 732 } 733 734 const T *ParamScope() const 735 { 736 return paramScope_; 737 } 738 739 void AddBindsFromParam() 740 { 741 ASSERT(paramScope_); 742 this->bindings_.insert(paramScope_->Bindings().begin(), paramScope_->Bindings().end()); 743 } 744 745 bool HasParamScope() override 746 { 747 return true; 748 } 749 750protected: 751 T *paramScope_ {nullptr}; 752}; 753 754class FunctionScope : public ScopeWithParamScope<VariableScope, FunctionParamScope> { 755public: 756 explicit FunctionScope(ArenaAllocator *allocator, Scope *parent) : ScopeWithParamScope(allocator, parent) {} 757 758 ScopeType Type() const override 759 { 760 return ScopeType::FUNCTION; 761 } 762 763 virtual void BindNameWithScopeInfo(util::StringView name, util::StringView recordName); 764 765 void BindName(util::StringView name, util::StringView internalName) 766 { 767 name_ = name; 768 internalName_ = internalName; 769 } 770 771 const util::StringView &Name() const 772 { 773 return name_; 774 } 775 776 const util::StringView &InternalName() const 777 { 778 return internalName_; 779 } 780 781 bool InFunctionScopes() const 782 { 783 return inFunctionScopes_; 784 } 785 786 void SetInFunctionScopes() 787 { 788 inFunctionScopes_ = true; 789 } 790 791 bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, 792 [[maybe_unused]] ScriptExtension extension) override; 793 794 void SetSelfScopeName(const util::StringView &ident) override; 795 796 const util::StringView &GetFullScopeName() override 797 { 798 SetFullScopeNames(); 799 return fullScopeName_; 800 } 801 802 uint32_t GetDuplicateScopeIndex(const util::StringView &childScopeName) override 803 { 804 auto it = scopesIndex_.find(childScopeName); 805 if (it == scopesIndex_.end()) { 806 scopesIndex_.insert({childScopeName, 0}); 807 return 0; 808 } else { 809 return ++it->second; 810 } 811 } 812 813protected: 814 util::StringView GetSelfScopeName() override; 815 816 Scope *GetParentWithScopeName() override 817 { 818 Scope *parentScope = parent_; 819 // FunctionParamScope has the same scope name with functionScope 820 // But functionParamScope is the parent of functionScope, it should be skipped here. 821 if ((parentScope != nullptr) && (parentScope->IsFunctionParamScope())) { 822 parentScope = parentScope->Parent(); 823 } 824 825 return parentScope; 826 } 827 828 util::StringView name_ {}; 829 util::StringView internalName_ {}; 830 831private: 832 util::StringView GetScopeTag() override; 833 834 bool inFunctionScopes_ {false}; 835}; 836 837class LocalScope : public Scope { 838public: 839 explicit LocalScope(ArenaAllocator *allocator, Scope *parent) : Scope(allocator, parent) {} 840 841 ScopeType Type() const override 842 { 843 return ScopeType::LOCAL; 844 } 845 846 bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, 847 [[maybe_unused]] ScriptExtension extension) override; 848}; 849 850class ClassScope : public VariableScope { 851public: 852 explicit ClassScope(ArenaAllocator *allocator, Scope *parent) 853 : VariableScope(allocator, parent), 854 computedNames_(allocator->Adapter()), 855 privateNames_(allocator->Adapter()), 856 privateGetters_(allocator->Adapter()), 857 privateSetters_(allocator->Adapter()) 858 { 859 } 860 861 ~ClassScope() override = default; 862 863 bool IsVariableScope() const override; 864 865 ScopeType Type() const override 866 { 867 return ScopeType::CLASS; 868 } 869 870 void AddClassVariable(const ir::Expression *key) 871 { 872 computedNames_.insert({key, slotIndex_++}); 873 } 874 875 uint32_t GetSlot(const ir::Expression *key) const 876 { 877 ASSERT(computedNames_.find(key) != computedNames_.end()); 878 return computedNames_.find(key)->second; 879 } 880 881 bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, 882 [[maybe_unused]] ScriptExtension extension) override 883 { 884 return AddLocal(allocator, currentVariable, newDecl, extension); 885 } 886 887 bool HasPrivateName(const util::StringView &name) const 888 { 889 return (privateNames_.count(name) + privateGetters_.count(name) + privateSetters_.count(name) != 0); 890 } 891 892 const util::StringView &GetFullScopeName() override 893 { 894 SetFullScopeNames(); 895 return fullScopeName_; 896 } 897 898 uint32_t GetDuplicateScopeIndex(const util::StringView &childScopeName) override 899 { 900 auto it = scopesIndex_.find(childScopeName); 901 if (it == scopesIndex_.end()) { 902 scopesIndex_.insert({childScopeName, 0}); 903 return 0; 904 } else { 905 return ++it->second; 906 } 907 } 908 909 Result GetPrivateProperty(const util::StringView &name, bool isSetter) const; 910 void AddPrivateName(std::vector<const ir::Statement *> privateProperties, uint32_t privateFieldCnt, 911 uint32_t instancePrivateMethodCnt, uint32_t staticPrivateMethodCnt); 912 friend class ir::ClassDefinition; 913 914protected: 915 util::StringView GetSelfScopeName() override; 916 917private: 918 util::StringView GetScopeTag() override; 919 920 bool IsMethod(uint32_t slot) const 921 { 922 return slot >= instancePrivateMethodStartSlot_ && slot < privateMethodEndSlot_; 923 } 924 925 bool IsStaticMethod(uint32_t slot) const 926 { 927 return slot >= staticPrivateMethodStartSlot_; 928 } 929 930 ArenaUnorderedMap<const ir::Expression *, uint32_t> computedNames_; 931 ArenaUnorderedMap<util::StringView, uint32_t> privateNames_; 932 ArenaUnorderedMap<util::StringView, uint32_t> privateGetters_; 933 ArenaUnorderedMap<util::StringView, uint32_t> privateSetters_; 934 uint32_t privateFieldCnt_ {0}; 935 uint32_t instancePrivateMethodStartSlot_ {0}; 936 uint32_t staticPrivateMethodStartSlot_ {0}; 937 uint32_t privateMethodEndSlot_ {0}; 938 uint32_t instanceMethodValidation_ {0}; 939 uint32_t staticMethodValidation_ {0}; 940}; 941 942class CatchParamScope : public ParamScope { 943public: 944 explicit CatchParamScope(ArenaAllocator *allocator, Scope *parent) : ParamScope(allocator, parent) {} 945 946 ScopeType Type() const override 947 { 948 return ScopeType::CATCH_PARAM; 949 } 950 951 bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, 952 [[maybe_unused]] ScriptExtension extension) override; 953 954 friend class CatchScope; 955}; 956 957class CatchScope : public ScopeWithParamScope<LocalScope, CatchParamScope> { 958public: 959 explicit CatchScope(ArenaAllocator *allocator, Scope *parent) : ScopeWithParamScope(allocator, parent) {} 960 961 ScopeType Type() const override 962 { 963 return ScopeType::CATCH; 964 } 965 966 bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, 967 [[maybe_unused]] ScriptExtension extension) override; 968}; 969 970class LoopScope : public VariableScope { 971public: 972 explicit LoopScope(ArenaAllocator *allocator, Scope *parent) : VariableScope(allocator, parent) {} 973 974 ScopeType Type() const override 975 { 976 return loopType_; 977 } 978 979 void InitVariable(); 980 981 bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, 982 [[maybe_unused]] ScriptExtension extension) override 983 { 984 return AddLocal(allocator, currentVariable, newDecl, extension); 985 } 986 987protected: 988 ScopeType loopType_ {ScopeType::LOOP}; 989}; 990 991class StaticBlockScope : public VariableScope { 992public: 993 explicit StaticBlockScope(ArenaAllocator *allocator, Scope *parent) : VariableScope(allocator, parent) {} 994 995 ScopeType Type() const override 996 { 997 return staticBlockType_; 998 } 999 1000 bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, 1001 [[maybe_unused]] ScriptExtension extension) override 1002 { 1003 return AddLocal(allocator, currentVariable, newDecl, extension); 1004 } 1005 1006protected: 1007 ScopeType staticBlockType_ {ScopeType::STATIC_BLOCK}; 1008}; 1009 1010class GlobalScope : public FunctionScope { 1011public: 1012 explicit GlobalScope(ArenaAllocator *allocator) : FunctionScope(allocator, nullptr) 1013 { 1014 paramScope_ = allocator->New<FunctionParamScope>(allocator, this); 1015 } 1016 1017 ScopeType Type() const override 1018 { 1019 return ScopeType::GLOBAL; 1020 } 1021 1022 bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, 1023 [[maybe_unused]] ScriptExtension extension) override; 1024 1025 void SetSelfScopeName([[maybe_unused]] const util::StringView &ident) override; 1026 1027 void BindNameWithScopeInfo(util::StringView name, util::StringView recordName) override 1028 { 1029 // only func_main_0 will call BindNameWithScopeInfo() of GlobalScope 1030 name_ = name; 1031 std::stringstream internalName; 1032 internalName << recordName << name; 1033 internalName_ = util::UString(internalName.str(), allocator_).View(); 1034 } 1035 1036 const util::StringView &GetFullScopeName() override 1037 { 1038 return fullScopeName_; 1039 } 1040}; 1041 1042class ModuleScope : public FunctionScope { 1043public: 1044 explicit ModuleScope(ArenaAllocator *allocator, parser::Program *program) : FunctionScope(allocator, nullptr) 1045 { 1046 paramScope_ = allocator->New<FunctionParamScope>(allocator, this); 1047 program_ = program; 1048 } 1049 1050 ScopeType Type() const override 1051 { 1052 return ScopeType::MODULE; 1053 } 1054 1055 const parser::Program *Program() const 1056 { 1057 return program_; 1058 } 1059 1060 void AssignIndexToModuleVariable(util::StringView name, uint32_t index); 1061 1062 void ConvertLocalVariableToModuleVariable(ArenaAllocator *allocator, util::StringView localName); 1063 1064 bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, 1065 [[maybe_unused]] ScriptExtension extension) override; 1066 1067 void SetSelfScopeName([[maybe_unused]] const util::StringView &ident) override; 1068 1069 void BindNameWithScopeInfo(util::StringView name, util::StringView recordName) override 1070 { 1071 // only func_main_0 will call BindNameWithScopeInfo() of ModuleScope 1072 name_ = name; 1073 std::stringstream internalName; 1074 internalName << recordName << name; 1075 internalName_ = util::UString(internalName.str(), allocator_).View(); 1076 } 1077 1078 const util::StringView &GetFullScopeName() override 1079 { 1080 return fullScopeName_; 1081 } 1082 1083private: 1084 parser::Program *program_ {nullptr}; 1085}; 1086 1087class TSModuleScope : public FunctionScope { 1088public: 1089 explicit TSModuleScope(ArenaAllocator *allocator, Scope *parent, ExportBindings *exportBindings) 1090 : FunctionScope(allocator, nullptr), exportBindings_(exportBindings), variableNames_(allocator->Adapter()) 1091 { 1092 paramScope_ = allocator->New<FunctionParamScope>(allocator, parent); 1093 CHECK_NOT_NULL(paramScope_); 1094 paramScope_->BindFunctionScope(this); 1095 SetParent(paramScope_); 1096 } 1097 1098 ScopeType Type() const override 1099 { 1100 return ScopeType::TSMODULE; 1101 } 1102 1103 template <TSBindingType type> 1104 Variable *FindExportTSVariable(const util::StringView &name) const 1105 { 1106 return exportBindings_->FindExportTSVariable<type>(name); 1107 } 1108 1109 template <TSBindingType type> 1110 bool AddExportTSVariable(const util::StringView &name, Variable *var) 1111 { 1112 return exportBindings_->AddExportTSVariable<type>(name, var); 1113 } 1114 1115 Variable *FindExportVariable(const util::StringView &name) const 1116 { 1117 return exportBindings_->FindExportVariable(name); 1118 } 1119 1120 bool AddExportVariable(const util::StringView &name, Variable *var) 1121 { 1122 return exportBindings_->AddExportVariable(name, var); 1123 } 1124 1125 bool AddExportVariable(const util::StringView &name) 1126 { 1127 return exportBindings_->AddExportVariable(name, FindLocal(name)); 1128 } 1129 1130 bool InExportBindings(const util::StringView &name) const 1131 { 1132 return exportBindings_->InExportBindings(name); 1133 } 1134 1135 void AddDeclarationName(const util::StringView &name) 1136 { 1137 variableNames_.insert(name); 1138 } 1139 1140 bool HasVariableName(const util::StringView &name) const 1141 { 1142 return variableNames_.find(name) != variableNames_.end(); 1143 } 1144 1145protected: 1146 util::StringView GetSelfScopeName() override; 1147 1148private: 1149 util::StringView GetScopeTag() override; 1150 1151 ExportBindings *exportBindings_; 1152 ArenaSet<util::StringView> variableNames_; 1153}; 1154 1155class TSEnumScope : public FunctionScope { 1156public: 1157 explicit TSEnumScope(ArenaAllocator *allocator, Scope *parent, VariableMap *enumMemberBindings) : FunctionScope( 1158 allocator, nullptr), enumMemberBindings_(enumMemberBindings), variableNames_(allocator->Adapter()) 1159 { 1160 paramScope_ = allocator->New<FunctionParamScope>(allocator, parent); 1161 CHECK_NOT_NULL(paramScope_); 1162 paramScope_->BindFunctionScope(this); 1163 SetParent(paramScope_); 1164 scopeDuplicateIndex_ = parent->GetDuplicateScopeIndex(GetScopeTag()); 1165 } 1166 1167 ScopeType Type() const override 1168 { 1169 return ScopeType::TSENUM; 1170 } 1171 1172 Variable *FindEnumMemberVariable(const util::StringView &name) const 1173 { 1174 auto res = enumMemberBindings_->find(name); 1175 if (res == enumMemberBindings_->end()) { 1176 return nullptr; 1177 } 1178 return res->second; 1179 } 1180 1181 void AddDeclarationName(const util::StringView &name) 1182 { 1183 variableNames_.insert(name); 1184 } 1185 1186 bool HasDeclarationName(const util::StringView &name) const 1187 { 1188 return variableNames_.find(name) != variableNames_.end(); 1189 } 1190 1191 bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, 1192 [[maybe_unused]] ScriptExtension extension) override; 1193 1194 void SetSelfScopeName(const util::StringView &ident) override; 1195 1196protected: 1197 util::StringView GetSelfScopeName() override; 1198 1199private: 1200 util::StringView GetScopeTag() override; 1201 1202 VariableMap *enumMemberBindings_; 1203 ArenaSet<util::StringView> variableNames_; 1204}; 1205 1206inline VariableFlags VariableScope::DeclFlagToVariableFlag(DeclarationFlags declFlag) 1207{ 1208 VariableFlags varFlag = VariableFlags::NONE; 1209 if (declFlag & DeclarationFlags::EXPORT) { 1210 varFlag = VariableFlags::LOCAL_EXPORT; 1211 } else if (declFlag & DeclarationFlags::IMPORT) { 1212 varFlag = VariableFlags::IMPORT; 1213 } 1214 return varFlag; 1215} 1216 1217template <typename T> 1218bool VariableScope::AddVar(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl) 1219{ 1220 VariableFlags flags = VariableFlags::HOIST_VAR; 1221 flags |= DeclFlagToVariableFlag(newDecl->Flags()); 1222 1223 if (!currentVariable) { 1224 bindings_.insert({newDecl->Name(), allocator->New<T>(newDecl, flags)}); 1225 return true; 1226 } 1227 1228 switch (currentVariable->Declaration()->Type()) { 1229 case DeclType::VAR: { 1230 currentVariable->Reset(newDecl, flags); 1231 break; 1232 } 1233 case DeclType::PARAM: 1234 case DeclType::FUNC: { 1235 break; 1236 } 1237 default: { 1238 return false; 1239 } 1240 } 1241 1242 return true; 1243} 1244 1245template <typename T> 1246bool VariableScope::AddFunction(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, 1247 [[maybe_unused]] ScriptExtension extension) 1248{ 1249 VariableFlags flags = (extension == ScriptExtension::JS) ? VariableFlags::HOIST_VAR : VariableFlags::HOIST; 1250 flags |= DeclFlagToVariableFlag(newDecl->Flags()); 1251 1252 if (!currentVariable) { 1253 bindings_.insert({newDecl->Name(), allocator->New<T>(newDecl, flags)}); 1254 return true; 1255 } 1256 1257 auto decl = currentVariable->Declaration(); 1258 if (decl->IsClassDecl() && decl->AsClassDecl()->IsDeclare()) { 1259 newDecl->AsFunctionDecl()->SetDeclClass(decl->AsClassDecl()); 1260 bindings_[newDecl->Name()] = allocator->New<T>(newDecl, flags); 1261 return true; 1262 } 1263 1264 if (extension != ScriptExtension::JS) { 1265 return false; 1266 } 1267 1268 switch (currentVariable->Declaration()->Type()) { 1269 case DeclType::VAR: 1270 case DeclType::FUNC: { 1271 currentVariable->Reset(newDecl, flags); 1272 break; 1273 } 1274 default: { 1275 return false; 1276 } 1277 } 1278 1279 return true; 1280} 1281 1282template <typename T> 1283bool VariableScope::AddClass(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl) 1284{ 1285 ASSERT(newDecl->IsClassDecl()); 1286 1287 VariableFlags flags = DeclFlagToVariableFlag(newDecl->Flags()); 1288 1289 if (!currentVariable) { 1290 bindings_.insert({newDecl->Name(), allocator->New<T>(newDecl, flags)}); 1291 return true; 1292 } 1293 1294 auto decl = currentVariable->Declaration(); 1295 if (newDecl->AsClassDecl()->IsDeclare() && decl->IsFunctionDecl()) { 1296 decl->AsFunctionDecl()->SetDeclClass(newDecl->AsClassDecl()); 1297 return true; 1298 } 1299 1300 return false; 1301} 1302 1303template <typename T> 1304bool VariableScope::AddTSBinding(ArenaAllocator *allocator, [[maybe_unused]] Variable *currentVariable, Decl *newDecl, 1305 VariableFlags flags) 1306{ 1307 ASSERT(!currentVariable); 1308 // TODO(xucheng): move the ts variables to tsBindings_ 1309 bindings_.insert({newDecl->Name(), allocator->New<T>(newDecl, flags)}); 1310 return true; 1311} 1312 1313template <typename T> 1314bool VariableScope::AddTSBinding(ArenaAllocator *allocator, Decl *newDecl, VariableFlags flags) 1315{ 1316 switch (flags) { 1317 case VariableFlags::NAMESPACE: { 1318 return tsBindings_.AddTSVariable<TSBindingType::NAMESPACE>( 1319 newDecl->Name(), allocator->New<T>(newDecl, flags)); 1320 } 1321 case VariableFlags::ENUM_LITERAL: { 1322 return tsBindings_.AddTSVariable<TSBindingType::ENUMLITERAL>( 1323 newDecl->Name(), allocator->New<T>(newDecl, flags)); 1324 } 1325 case VariableFlags::INTERFACE: { 1326 return tsBindings_.AddTSVariable<TSBindingType::INTERFACE>( 1327 newDecl->Name(), allocator->New<T>(newDecl, flags)); 1328 } 1329 case VariableFlags::IMPORT_EQUALS: { 1330 return tsBindings_.AddTSVariable<TSBindingType::IMPORT_EQUALS>( 1331 newDecl->Name(), allocator->New<T>(newDecl, flags)); 1332 } 1333 default: { 1334 break; 1335 } 1336 } 1337 return false; 1338} 1339 1340template <typename T> 1341bool VariableScope::AddLexical(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl) 1342{ 1343 VariableFlags flags = DeclFlagToVariableFlag(newDecl->Flags()); 1344 1345 if (currentVariable) { 1346 return false; 1347 } 1348 1349 bindings_.insert({newDecl->Name(), allocator->New<T>(newDecl, flags)}); 1350 return true; 1351} 1352 1353template <typename T, typename... Args> 1354T *Scope::NewDecl(ArenaAllocator *allocator, Args &&... args) 1355{ 1356 T *decl = allocator->New<T>(std::forward<Args>(args)...); 1357 decls_.push_back(decl); 1358 1359 return decl; 1360} 1361 1362template <typename DeclType, typename VariableType> 1363VariableType *Scope::AddDecl(ArenaAllocator *allocator, util::StringView name, VariableFlags flags) 1364{ 1365 if (FindLocal(name)) { 1366 return nullptr; 1367 } 1368 1369 auto *decl = allocator->New<DeclType>(name); 1370 auto *variable = allocator->New<VariableType>(decl, flags); 1371 CHECK_NOT_NULL(decl); 1372 CHECK_NOT_NULL(variable); 1373 1374 decls_.push_back(decl); 1375 bindings_.insert({decl->Name(), variable}); 1376 1377 return variable; 1378} 1379 1380template <typename DeclType, typename VariableType> 1381VariableType *Scope::CreateVar(ArenaAllocator *allocator, util::StringView name, VariableFlags flags, 1382 const ir::AstNode *node) 1383{ 1384 auto *decl = allocator->New<DeclType>(name); 1385 CHECK_NOT_NULL(decl); 1386 auto *variable = allocator->New<VariableType>(decl, flags); 1387 CHECK_NOT_NULL(variable); 1388 decl->BindNode(node); 1389 return variable; 1390} 1391 1392template <typename T, typename... Args> 1393void Scope::PropagateBinding(ArenaAllocator *allocator, util::StringView name, Args &&... args) 1394{ 1395 auto res = bindings_.find(name); 1396 if (res == bindings_.end()) { 1397 bindings_.insert({name, allocator->New<T>(std::forward<Args>(args)...)}); 1398 return; 1399 } 1400 1401 if (!res->second->Declaration()->IsParameterDecl()) { 1402 res->second->Reset(std::forward<Args>(args)...); 1403 } 1404} 1405 1406} // namespace panda::es2panda::binder 1407 1408#endif 1409