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 #include "typeRelation.h"
17
18 #include <typescript/checker.h>
19 #include <typescript/types/indexInfo.h>
20 #include <typescript/types/signature.h>
21
22 namespace panda::es2panda::checker {
23
GetType() const24 const Type *AsSrc::GetType() const
25 {
26 return type_;
27 }
28
TypeRelation(Checker * checker)29 TypeRelation::TypeRelation(Checker *checker) : checker_(checker), result_(RelationResult::FALSE) {}
30
IsTrue() const31 bool TypeRelation::IsTrue() const
32 {
33 return result_ == RelationResult::TRUE;
34 }
35
GetChecker() const36 const Checker *TypeRelation::GetChecker() const
37 {
38 return checker_;
39 }
40
GetChecker()41 Checker *TypeRelation::GetChecker()
42 {
43 return checker_;
44 }
45
Allocator()46 ArenaAllocator *TypeRelation::Allocator()
47 {
48 return checker_->Allocator();
49 }
50
CacheLookup(const Type * source,const Type * target,const RelationHolder & holder,RelationType type) const51 RelationResult TypeRelation::CacheLookup(const Type *source, const Type *target, const RelationHolder &holder,
52 RelationType type) const
53 {
54 if (result_ == RelationResult::CACHE_MISS) {
55 return result_;
56 }
57
58 RelationKey relationKey {source->Id(), target->Id()};
59 auto res = holder.cached.find(relationKey);
60 if (res == holder.cached.end()) {
61 return RelationResult::CACHE_MISS;
62 }
63
64 if (res->second.type >= type && res->second.result == RelationResult::TRUE) {
65 return RelationResult::TRUE;
66 }
67
68 if (res->second.type <= type && res->second.result == RelationResult::FALSE) {
69 return RelationResult::FALSE;
70 }
71
72 return RelationResult::CACHE_MISS;
73 }
74
IsIdenticalTo(Type * source,Type * target)75 bool TypeRelation::IsIdenticalTo(Type *source, Type *target)
76 {
77 if (source == target) {
78 Result(true);
79 return true;
80 }
81
82 result_ = CacheLookup(source, target, checker_->IdenticalResults(), RelationType::IDENTICAL);
83 if (result_ == RelationResult::CACHE_MISS) {
84 checker_->ResolveStructuredTypeMembers(source);
85 checker_->ResolveStructuredTypeMembers(target);
86 result_ = RelationResult::FALSE;
87 target->Identical(this, source);
88 checker_->IdenticalResults().cached.insert({{source->Id(), target->Id()}, {result_, RelationType::IDENTICAL}});
89 }
90
91 return result_ == RelationResult::TRUE;
92 }
93
IsIdenticalTo(Signature * source,Signature * target)94 bool TypeRelation::IsIdenticalTo(Signature *source, Signature *target)
95 {
96 if (source == target) {
97 Result(true);
98 return true;
99 }
100
101 result_ = RelationResult::FALSE;
102 target->Identical(this, source);
103
104 return result_ == RelationResult::TRUE;
105 }
106
IsIdenticalTo(IndexInfo * source,IndexInfo * target)107 bool TypeRelation::IsIdenticalTo(IndexInfo *source, IndexInfo *target)
108 {
109 if (source == target) {
110 Result(true);
111 return true;
112 }
113
114 result_ = RelationResult::FALSE;
115 target->Identical(this, source);
116
117 return result_ == RelationResult::TRUE;
118 }
119
IsAssignableTo(Type * source,Type * target)120 bool TypeRelation::IsAssignableTo(Type *source, Type *target)
121 {
122 result_ = CacheLookup(source, target, checker_->AssignableResults(), RelationType::ASSIGNABLE);
123 if (result_ == RelationResult::CACHE_MISS) {
124 if (IsIdenticalTo(source, target)) {
125 return true;
126 }
127
128 result_ = RelationResult::FALSE;
129
130 if (!source->AssignmentSource(this, target)) {
131 target->AssignmentTarget(this, source);
132 }
133
134 checker_->AssignableResults().cached.insert(
135 {{source->Id(), target->Id()}, {result_, RelationType::ASSIGNABLE}});
136 }
137
138 return result_ == RelationResult::TRUE;
139 }
140
IsComparableTo(Type * source,Type * target)141 bool TypeRelation::IsComparableTo(Type *source, Type *target)
142 {
143 result_ = CacheLookup(source, target, checker_->ComparableResults(), RelationType::COMPARABLE);
144
145 if (result_ == RelationResult::CACHE_MISS) {
146 if (IsAssignableTo(source, target)) {
147 return true;
148 }
149
150 result_ = RelationResult::FALSE;
151 target->Compare(this, source);
152 checker_->ComparableResults().cached.insert(
153 {{source->Id(), target->Id()}, {result_, RelationType::COMPARABLE}});
154 }
155
156 return result_ == RelationResult::TRUE;
157 }
158
RaiseError(const std::string & errMsg,const lexer::SourcePosition & loc) const159 void TypeRelation::RaiseError(const std::string &errMsg, const lexer::SourcePosition &loc) const
160 {
161 checker_->ThrowTypeError(errMsg, loc);
162 }
163
RaiseError(std::initializer_list<TypeErrorMessageElement> list,const lexer::SourcePosition & loc) const164 void TypeRelation::RaiseError(std::initializer_list<TypeErrorMessageElement> list,
165 const lexer::SourcePosition &loc) const
166 {
167 checker_->ThrowTypeError(list, loc);
168 }
169
Result(bool res)170 void TypeRelation::Result(bool res)
171 {
172 result_ = res ? RelationResult::TRUE : RelationResult::FALSE;
173 }
174
175 } // namespace panda::es2panda::checker
176