• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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