• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     CHECK_NOT_NULL(source);
59     CHECK_NOT_NULL(target);
60     RelationKey relationKey {source->Id(), target->Id()};
61     auto res = holder.cached.find(relationKey);
62     if (res == holder.cached.end()) {
63         return RelationResult::CACHE_MISS;
64     }
65 
66     if (res->second.type >= type && res->second.result == RelationResult::TRUE) {
67         return RelationResult::TRUE;
68     }
69 
70     if (res->second.type <= type && res->second.result == RelationResult::FALSE) {
71         return RelationResult::FALSE;
72     }
73 
74     return RelationResult::CACHE_MISS;
75 }
76 
IsIdenticalTo(Type * source,Type * target)77 bool TypeRelation::IsIdenticalTo(Type *source, Type *target)
78 {
79     if (source == target) {
80         Result(true);
81         return true;
82     }
83 
84     CHECK_NOT_NULL(target);
85     result_ = CacheLookup(source, target, checker_->IdenticalResults(), RelationType::IDENTICAL);
86     if (result_ == RelationResult::CACHE_MISS) {
87         checker_->ResolveStructuredTypeMembers(source);
88         checker_->ResolveStructuredTypeMembers(target);
89         result_ = RelationResult::FALSE;
90         target->Identical(this, source);
91         checker_->IdenticalResults().cached.insert({{source->Id(), target->Id()}, {result_, RelationType::IDENTICAL}});
92     }
93 
94     return result_ == RelationResult::TRUE;
95 }
96 
IsIdenticalTo(Signature * source,Signature * target)97 bool TypeRelation::IsIdenticalTo(Signature *source, Signature *target)
98 {
99     if (source == target) {
100         Result(true);
101         return true;
102     }
103 
104     result_ = RelationResult::FALSE;
105     target->Identical(this, source);
106 
107     return result_ == RelationResult::TRUE;
108 }
109 
IsIdenticalTo(IndexInfo * source,IndexInfo * target)110 bool TypeRelation::IsIdenticalTo(IndexInfo *source, IndexInfo *target)
111 {
112     if (source == target) {
113         Result(true);
114         return true;
115     }
116 
117     result_ = RelationResult::FALSE;
118     target->Identical(this, source);
119 
120     return result_ == RelationResult::TRUE;
121 }
122 
IsAssignableTo(Type * source,Type * target)123 bool TypeRelation::IsAssignableTo(Type *source, Type *target)
124 {
125     result_ = CacheLookup(source, target, checker_->AssignableResults(), RelationType::ASSIGNABLE);
126     if (result_ == RelationResult::CACHE_MISS) {
127         if (IsIdenticalTo(source, target)) {
128             return true;
129         }
130 
131         result_ = RelationResult::FALSE;
132 
133         if (!source->AssignmentSource(this, target)) {
134             target->AssignmentTarget(this, source);
135         }
136 
137         checker_->AssignableResults().cached.insert(
138             {{source->Id(), target->Id()}, {result_, RelationType::ASSIGNABLE}});
139     }
140 
141     return result_ == RelationResult::TRUE;
142 }
143 
IsComparableTo(Type * source,Type * target)144 bool TypeRelation::IsComparableTo(Type *source, Type *target)
145 {
146     result_ = CacheLookup(source, target, checker_->ComparableResults(), RelationType::COMPARABLE);
147     if (result_ == RelationResult::CACHE_MISS) {
148         if (IsAssignableTo(source, target)) {
149             return true;
150         }
151 
152         result_ = RelationResult::FALSE;
153         CHECK_NOT_NULL(target);
154         target->Compare(this, source);
155         checker_->ComparableResults().cached.insert(
156             {{source->Id(), target->Id()}, {result_, RelationType::COMPARABLE}});
157     }
158 
159     return result_ == RelationResult::TRUE;
160 }
161 
RaiseError(const std::string & errMsg,const lexer::SourcePosition & loc) const162 void TypeRelation::RaiseError(const std::string &errMsg, const lexer::SourcePosition &loc) const
163 {
164     checker_->ThrowTypeError(errMsg, loc);
165 }
166 
RaiseError(std::initializer_list<TypeErrorMessageElement> list,const lexer::SourcePosition & loc) const167 void TypeRelation::RaiseError(std::initializer_list<TypeErrorMessageElement> list,
168                               const lexer::SourcePosition &loc) const
169 {
170     checker_->ThrowTypeError(list, loc);
171 }
172 
Result(bool res)173 void TypeRelation::Result(bool res)
174 {
175     result_ = res ? RelationResult::TRUE : RelationResult::FALSE;
176 }
177 
178 }  // namespace panda::es2panda::checker
179