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 ~ProgramScope()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 if (recordClass->IsAnnotationDeclaration()) { 91 recordTable->SetAnnotationDeclaration(recordClass->AsAnnotationDeclaration()); 92 } else { 93 recordTable->SetInterfaceDeclaration(recordClass->AsTSInterfaceDeclaration()); 94 } 95 } else { 96 ir::ClassDefinition *nullDef = nullptr; 97 recordTable->SetClassDefinition(nullDef); 98 } 99 } 100 101 // NOLINTNEXTLINE(bugprone-exception-escape) ~RecordTableClassScope()102 ~RecordTableClassScope() noexcept 103 { 104 auto *recordTable = varBinder_->GetRecordTable(); 105 ASSERT(recordTable != nullptr); 106 107 if (prevRecordClass_ != nullptr) { 108 if (prevRecordClass_->IsClassDefinition()) { 109 recordTable->SetClassDefinition(prevRecordClass_->AsClassDefinition()); 110 } else { 111 recordTable->SetInterfaceDeclaration(prevRecordClass_->AsTSInterfaceDeclaration()); 112 } 113 } else { 114 ir::ClassDefinition *nullDef = nullptr; 115 recordTable->SetClassDefinition(nullDef); 116 } 117 } 118 119 NO_COPY_SEMANTIC(RecordTableClassScope); 120 NO_MOVE_SEMANTIC(RecordTableClassScope); 121 122 void *operator new(size_t) = delete; 123 void *operator new[](size_t) = delete; 124 125 private: 126 varbinder::ETSBinder *varBinder_ {nullptr}; 127 ir::AstNode *prevRecordClass_ {nullptr}; 128 }; 129 130 } // namespace ark::es2panda::evaluate 131 132 #endif // ES2PANDA_EVALUATE_VARBINDER_SCOPES_H 133