1 /**
2 * Copyright (c) 2021-2025 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 #include "checker.h"
17
18 #include "public/public.h"
19 #include "checker/types/globalTypesHolder.h"
20 #include "checker/types/ts/unionType.h"
21
22 namespace ark::es2panda::checker {
Checker(util::DiagnosticEngine & diagnosticEngine,ArenaAllocator * programAllocator)23 Checker::Checker(util::DiagnosticEngine &diagnosticEngine, ArenaAllocator *programAllocator)
24 : allocator_(SpaceType::SPACE_TYPE_COMPILER, nullptr, true),
25 programAllocator_(programAllocator),
26 context_(this, CheckerStatus::NO_OPTS),
27 diagnosticEngine_(diagnosticEngine)
28 {
29 relation_ = ProgramAllocator()->New<TypeRelation>(this);
30 globalTypes_ = ProgramAllocator()->New<GlobalTypesHolder>(ProgramAllocator());
31 }
32
Initialize(varbinder::VarBinder * varbinder)33 void Checker::Initialize(varbinder::VarBinder *varbinder)
34 {
35 varbinder_ = varbinder;
36 scope_ = varbinder_->TopScope();
37 program_ = varbinder_->Program();
38 }
39
LogError(const diagnostic::DiagnosticKind & diagnostic,const util::DiagnosticMessageParams & diagnosticParams,const lexer::SourcePosition & pos)40 void Checker::LogError(const diagnostic::DiagnosticKind &diagnostic,
41 const util::DiagnosticMessageParams &diagnosticParams, const lexer::SourcePosition &pos)
42 {
43 diagnosticEngine_.LogDiagnostic(diagnostic, diagnosticParams, pos);
44 }
45
LogError(const diagnostic::DiagnosticKind & diagnostic,const lexer::SourcePosition & pos)46 void Checker::LogError(const diagnostic::DiagnosticKind &diagnostic, const lexer::SourcePosition &pos)
47 {
48 LogError(diagnostic, {}, pos);
49 }
50
LogTypeError(std::string_view message,const lexer::SourcePosition & pos)51 void Checker::LogTypeError(std::string_view message, const lexer::SourcePosition &pos)
52 {
53 diagnosticEngine_.LogSemanticError(message, pos);
54 }
55
LogDiagnostic(const diagnostic::DiagnosticKind & kind,const util::DiagnosticMessageParams & list,const lexer::SourcePosition & pos)56 void Checker::LogDiagnostic(const diagnostic::DiagnosticKind &kind, const util::DiagnosticMessageParams &list,
57 const lexer::SourcePosition &pos)
58 {
59 diagnosticEngine_.LogDiagnostic(kind, list, pos);
60 }
61
IsAllTypesAssignableTo(Type * source,Type * target)62 bool Checker::IsAllTypesAssignableTo(Type *source, Type *target)
63 {
64 if (source->TypeFlags() == TypeFlag::UNION) {
65 auto &types = source->AsUnionType()->ConstituentTypes();
66
67 return std::all_of(types.begin(), types.end(),
68 [this, target](auto *it) { return IsAllTypesAssignableTo(it, target); });
69 }
70
71 return relation_->IsAssignableTo(source, target);
72 }
73
IsTypeIdenticalTo(Type * source,Type * target)74 bool Checker::IsTypeIdenticalTo(Type *source, Type *target)
75 {
76 return relation_->IsIdenticalTo(source, target);
77 }
78
IsTypeIdenticalTo(Type * source,Type * target,const diagnostic::DiagnosticKind & diagKind,const util::DiagnosticMessageParams & diagParams,const lexer::SourcePosition & errPos)79 bool Checker::IsTypeIdenticalTo(Type *source, Type *target, const diagnostic::DiagnosticKind &diagKind,
80 const util::DiagnosticMessageParams &diagParams, const lexer::SourcePosition &errPos)
81 {
82 if (!IsTypeIdenticalTo(source, target)) {
83 relation_->GetChecker()->LogError(diagKind, diagParams, errPos);
84 return false;
85 }
86
87 return true;
88 }
89
IsTypeIdenticalTo(Type * source,Type * target,const diagnostic::DiagnosticKind & diagKind,const lexer::SourcePosition & errPos)90 bool Checker::IsTypeIdenticalTo(Type *source, Type *target, const diagnostic::DiagnosticKind &diagKind,
91 const lexer::SourcePosition &errPos)
92 {
93 return IsTypeIdenticalTo(source, target, diagKind, {}, errPos);
94 }
95
IsTypeAssignableTo(Type * source,Type * target)96 bool Checker::IsTypeAssignableTo(Type *source, Type *target)
97 {
98 return relation_->IsAssignableTo(source, target);
99 }
100
IsTypeAssignableTo(Type * source,Type * target,const diagnostic::DiagnosticKind & diagKind,const util::DiagnosticMessageParams & list,const lexer::SourcePosition & errPos)101 bool Checker::IsTypeAssignableTo(Type *source, Type *target, const diagnostic::DiagnosticKind &diagKind,
102 const util::DiagnosticMessageParams &list, const lexer::SourcePosition &errPos)
103 {
104 if (!IsTypeAssignableTo(source, target)) {
105 relation_->RaiseError(diagKind, list, errPos);
106 }
107
108 return true;
109 }
110
IsTypeComparableTo(Type * source,Type * target)111 bool Checker::IsTypeComparableTo(Type *source, Type *target)
112 {
113 return relation_->IsComparableTo(source, target);
114 }
115
IsTypeComparableTo(Type * source,Type * target,const diagnostic::DiagnosticKind & diagKind,const util::DiagnosticMessageParams & list,const lexer::SourcePosition & errPos)116 bool Checker::IsTypeComparableTo(Type *source, Type *target, const diagnostic::DiagnosticKind &diagKind,
117 const util::DiagnosticMessageParams &list, const lexer::SourcePosition &errPos)
118 {
119 if (!IsTypeComparableTo(source, target)) {
120 relation_->RaiseError(diagKind, list, errPos);
121 }
122
123 return true;
124 }
125
AreTypesComparable(Type * source,Type * target)126 bool Checker::AreTypesComparable(Type *source, Type *target)
127 {
128 return IsTypeComparableTo(source, target) || IsTypeComparableTo(target, source);
129 }
130
IsTypeEqualityComparableTo(Type * source,Type * target)131 bool Checker::IsTypeEqualityComparableTo(Type *source, Type *target)
132 {
133 return IsTypeComparableTo(source, target);
134 }
135
Program() const136 parser::Program *Checker::Program() const
137 {
138 return program_;
139 }
140
SetProgram(parser::Program * program)141 void Checker::SetProgram(parser::Program *program)
142 {
143 program_ = program;
144 }
145
VarBinder() const146 varbinder::VarBinder *Checker::VarBinder() const
147 {
148 return varbinder_;
149 }
150
SetAnalyzer(SemanticAnalyzer * analyzer)151 void Checker::SetAnalyzer(SemanticAnalyzer *analyzer)
152 {
153 analyzer_ = analyzer;
154 }
155
GetAnalyzer() const156 checker::SemanticAnalyzer *Checker::GetAnalyzer() const
157 {
158 return analyzer_;
159 }
160
IsAnyError()161 bool Checker::IsAnyError()
162 {
163 return DiagnosticEngine().IsAnyError();
164 }
165
ScopeContext(Checker * checker,varbinder::Scope * newScope)166 ScopeContext::ScopeContext(Checker *checker, varbinder::Scope *newScope)
167 : checker_(checker), prevScope_(checker_->scope_), prevProgram_(checker_->Program())
168 {
169 checker_->scope_ = newScope;
170 if (newScope != nullptr && newScope->Node() != nullptr) {
171 auto *topStatement = newScope->Node()->GetTopStatement();
172 if (topStatement->IsETSModule()) {
173 checker_->SetProgram(topStatement->AsETSModule()->Program());
174 }
175 }
176 }
177
CleanUp()178 void Checker::CleanUp()
179 {
180 context_ = CheckerContext(this, CheckerStatus::NO_OPTS);
181 globalTypes_ = allocator_.New<GlobalTypesHolder>(&allocator_);
182 relation_ = allocator_.New<TypeRelation>(this);
183 identicalResults_.cached.clear();
184 assignableResults_.cached.clear();
185 comparableResults_.cached.clear();
186 uncheckedCastableResults_.cached.clear();
187 supertypeResults_.cached.clear();
188 typeStack_.clear();
189 namedTypeStack_.clear();
190 }
191
192 } // namespace ark::es2panda::checker
193