• 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 
20 namespace panda::es2panda::checker {
21 
GetType() const22 const Type *AsSrc::GetType() const
23 {
24     return type_;
25 }
26 
TypeRelation(Checker * checker)27 TypeRelation::TypeRelation(Checker *checker) : checker_(checker), result_(RelationResult::FALSE) {}
28 
IsTrue() const29 bool TypeRelation::IsTrue() const
30 {
31     return result_ == RelationResult::TRUE;
32 }
33 
GetChecker() const34 const Checker *TypeRelation::GetChecker() const
35 {
36     return checker_;
37 }
38 
GetChecker()39 Checker *TypeRelation::GetChecker()
40 {
41     return checker_;
42 }
43 
Allocator()44 ArenaAllocator *TypeRelation::Allocator()
45 {
46     return checker_->Allocator();
47 }
48 
CacheLookup(const Type * source,const Type * target,const RelationHolder & holder,RelationType type) const49 RelationResult TypeRelation::CacheLookup(const Type *source, const Type *target, const RelationHolder &holder,
50                                          RelationType type) const
51 {
52     if (result_ == RelationResult::CACHE_MISS) {
53         return result_;
54     }
55 
56     CHECK_NOT_NULL(source);
57     CHECK_NOT_NULL(target);
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     CHECK_NOT_NULL(target);
83     result_ = CacheLookup(source, target, checker_->IdenticalResults(), RelationType::IDENTICAL);
84     if (result_ == RelationResult::CACHE_MISS) {
85         CHECK_NOT_NULL(source);
86         checker_->ResolveStructuredTypeMembers(source);
87         checker_->ResolveStructuredTypeMembers(target);
88         result_ = RelationResult::FALSE;
89         target->Identical(this, source);
90         checker_->IdenticalResults().cached.insert({{source->Id(), target->Id()}, {result_, RelationType::IDENTICAL}});
91     }
92 
93     return result_ == RelationResult::TRUE;
94 }
95 
IsIdenticalTo(Signature * source,Signature * target)96 bool TypeRelation::IsIdenticalTo(Signature *source, Signature *target)
97 {
98     if (source == target) {
99         Result(true);
100         return true;
101     }
102 
103     result_ = RelationResult::FALSE;
104     target->Identical(this, source);
105 
106     return result_ == RelationResult::TRUE;
107 }
108 
IsIdenticalTo(IndexInfo * source,IndexInfo * target)109 bool TypeRelation::IsIdenticalTo(IndexInfo *source, IndexInfo *target)
110 {
111     if (source == target) {
112         Result(true);
113         return true;
114     }
115 
116     result_ = RelationResult::FALSE;
117     target->Identical(this, source);
118 
119     return result_ == RelationResult::TRUE;
120 }
121 
IsAssignableTo(Type * source,Type * target)122 bool TypeRelation::IsAssignableTo(Type *source, Type *target)
123 {
124     result_ = CacheLookup(source, target, checker_->AssignableResults(), RelationType::ASSIGNABLE);
125     if (result_ == RelationResult::CACHE_MISS) {
126         if (IsIdenticalTo(source, target)) {
127             return true;
128         }
129 
130         result_ = RelationResult::FALSE;
131 
132         if (!source->AssignmentSource(this, target)) {
133             target->AssignmentTarget(this, source);
134         }
135 
136         checker_->AssignableResults().cached.insert(
137             {{source->Id(), target->Id()}, {result_, RelationType::ASSIGNABLE}});
138     }
139 
140     return result_ == RelationResult::TRUE;
141 }
142 
IsComparableTo(Type * source,Type * target)143 bool TypeRelation::IsComparableTo(Type *source, Type *target)
144 {
145     result_ = CacheLookup(source, target, checker_->ComparableResults(), RelationType::COMPARABLE);
146     if (result_ == RelationResult::CACHE_MISS) {
147         if (IsAssignableTo(source, target)) {
148             return true;
149         }
150 
151         result_ = RelationResult::FALSE;
152         CHECK_NOT_NULL(target);
153         target->Compare(this, source);
154         checker_->ComparableResults().cached.insert(
155             {{source->Id(), target->Id()}, {result_, RelationType::COMPARABLE}});
156     }
157 
158     return result_ == RelationResult::TRUE;
159 }
160 
RaiseError(const std::string & errMsg,const lexer::SourcePosition & loc) const161 void TypeRelation::RaiseError(const std::string &errMsg, const lexer::SourcePosition &loc) const
162 {
163     checker_->ThrowTypeError(errMsg, loc);
164 }
165 
RaiseError(std::initializer_list<TypeErrorMessageElement> list,const lexer::SourcePosition & loc) const166 void TypeRelation::RaiseError(std::initializer_list<TypeErrorMessageElement> list,
167                               const lexer::SourcePosition &loc) const
168 {
169     checker_->ThrowTypeError(list, loc);
170 }
171 
Result(bool res)172 void TypeRelation::Result(bool res)
173 {
174     result_ = res ? RelationResult::TRUE : RelationResult::FALSE;
175 }
176 
177 }  // namespace panda::es2panda::checker
178