1 /* 2 * Copyright (c) 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_EVALUATE_VARBINDER_SCOPES_H 17 #define ES2PANDA_EVALUATE_VARBINDER_SCOPES_H 18 19 #include "parser/program/program.h" 20 #include "varbinder/ETSBinder.h" 21 #include "varbinder/recordTable.h" 22 23 namespace ark::es2panda::evaluate { 24 25 // This scope must be used before running VarBinder or Checker on nodes from another Program. 26 class ProgramScope final { 27 public: ProgramScope(varbinder::ETSBinder *varBinder, parser::Program *program)28 explicit ProgramScope(varbinder::ETSBinder *varBinder, parser::Program *program) 29 : varBinder_(varBinder), 30 prevProgram_(varBinder->Program()), 31 prevRecordTable_(varBinder->GetRecordTable()), 32 prevTopScope_(varBinder->TopScope()), 33 prevVarScope_(varBinder->VarScope()), 34 prevScope_(varBinder->GetScope()) 35 { 36 ASSERT(varBinder); 37 ASSERT(program); 38 39 varBinder_->SetProgram(program); 40 41 auto &extTables = varBinder_->GetExternalRecordTable(); 42 auto iter = extTables.find(program); 43 ASSERT(iter != extTables.end()); 44 varBinder_->SetRecordTable(iter->second); 45 46 varBinder_->ResetAllScopes(program->GlobalScope(), program->GlobalScope(), program->GlobalScope()); 47 } 48 49 ~ProgramScope() noexcept 50 { 51 varBinder_->SetProgram(prevProgram_); 52 varBinder_->SetRecordTable(prevRecordTable_); 53 varBinder_->ResetAllScopes(prevTopScope_, prevVarScope_, prevScope_); 54 } 55 56 NO_COPY_SEMANTIC(ProgramScope); 57 NO_MOVE_SEMANTIC(ProgramScope); 58 59 void *operator new(size_t) = delete; 60 void *operator new[](size_t) = delete; 61 62 private: 63 varbinder::ETSBinder *varBinder_ {nullptr}; 64 parser::Program *prevProgram_ {nullptr}; 65 varbinder::RecordTable *prevRecordTable_ {nullptr}; 66 varbinder::GlobalScope *prevTopScope_ {nullptr}; 67 varbinder::VariableScope *prevVarScope_ {nullptr}; 68 varbinder::Scope *prevScope_ {nullptr}; 69 }; 70 71 // The scope is required for running VarBinder or Checker on nodes from another class, 72 // so that entities will be registered with correct names in record table. 73 class RecordTableClassScope final { 74 public: RecordTableClassScope(varbinder::ETSBinder *varBinder, ir::AstNode *recordClass)75 explicit RecordTableClassScope(varbinder::ETSBinder *varBinder, ir::AstNode *recordClass) : varBinder_(varBinder) 76 { 77 ASSERT(varBinder_); 78 79 auto *recordTable = varBinder_->GetRecordTable(); 80 ASSERT(recordTable); 81 82 prevRecordClass_ = recordTable->ClassDefinition(); 83 if (prevRecordClass_ == nullptr) { 84 prevRecordClass_ = recordTable->InterfaceDeclaration(); 85 } 86 87 if (recordClass != nullptr) { 88 if (recordClass->IsClassDefinition()) { 89 recordTable->SetClassDefinition(recordClass->AsClassDefinition()); 90 } else { 91 recordTable->SetInterfaceDeclaration(recordClass->AsTSInterfaceDeclaration()); 92 } 93 } else { 94 ir::ClassDefinition *nullDef = nullptr; 95 recordTable->SetClassDefinition(nullDef); 96 } 97 } 98 99 // NOLINTNEXTLINE(bugprone-exception-escape) 100 ~RecordTableClassScope() noexcept 101 { 102 auto *recordTable = varBinder_->GetRecordTable(); 103 ASSERT(recordTable != nullptr); 104 105 if (prevRecordClass_ != nullptr) { 106 if (prevRecordClass_->IsClassDefinition()) { 107 recordTable->SetClassDefinition(prevRecordClass_->AsClassDefinition()); 108 } else { 109 recordTable->SetInterfaceDeclaration(prevRecordClass_->AsTSInterfaceDeclaration()); 110 } 111 } else { 112 ir::ClassDefinition *nullDef = nullptr; 113 recordTable->SetClassDefinition(nullDef); 114 } 115 } 116 117 NO_COPY_SEMANTIC(RecordTableClassScope); 118 NO_MOVE_SEMANTIC(RecordTableClassScope); 119 120 void *operator new(size_t) = delete; 121 void *operator new[](size_t) = delete; 122 123 private: 124 varbinder::ETSBinder *varBinder_ {nullptr}; 125 ir::AstNode *prevRecordClass_ {nullptr}; 126 }; 127 128 } // namespace ark::es2panda::evaluate 129 130 #endif // ES2PANDA_EVALUATE_VARBINDER_SCOPES_H 131