• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2022 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 _PANDA_VERIFIER_ABSTRACT_TYPE_HPP
17 #define _PANDA_VERIFIER_ABSTRACT_TYPE_HPP
18 
19 #include "verification/value/variables.h"
20 #include "verification/type/type_set.h"
21 
22 #include "macros.h"
23 
24 #include <variant>
25 
26 namespace panda::verifier {
27 class AbstractType {
28 public:
29     struct None {
30     };
31     using ContentsData = std::variant<None, Variables::Var, Type, TypeSet>;
32     AbstractType() = default;
33     AbstractType(const AbstractType &) = default;
34     AbstractType(AbstractType &&) = default;
AbstractType(const Type & type)35     AbstractType(const Type &type) : Contents_ {type} {}
AbstractType(const Variables::Var & var)36     AbstractType(const Variables::Var &var) : Contents_ {var} {}
AbstractType(Variables::Var && var)37     AbstractType(Variables::Var &&var) : Contents_ {std::move(var)} {}
AbstractType(TypeSet && type_set)38     AbstractType(TypeSet &&type_set)
39     {
40         auto the_only_type = type_set.TheOnlyType();
41         if (the_only_type.IsValid()) {
42             Contents_ = the_only_type;
43         } else {
44             Contents_ = std::move(type_set);
45         }
46     }
47 
48     AbstractType &operator=(const AbstractType &) = default;
49     AbstractType &operator=(AbstractType &&) = default;
50     ~AbstractType() = default;
51     AbstractType &operator=(const None &)
52     {
53         Contents_ = None {};
54         return *this;
55     }
56     AbstractType &operator=(Variables::Var var)
57     {
58         Contents_ = var;
59         return *this;
60     }
61     AbstractType &operator=(Type type)
62     {
63         Contents_ = type;
64         return *this;
65     }
66     AbstractType &operator=(TypeSet &&type_set)
67     {
68         Contents_ = std::move(type_set);
69         return *this;
70     }
71 
GetVar()72     Variables::Var GetVar() const
73     {
74         ASSERT(IsVar());
75         return std::get<Variables::Var>(Contents_);
76     }
GetType()77     Type GetType() const
78     {
79         ASSERT(IsType());
80         return std::get<Type>(Contents_);
81     }
GetTypeSet()82     const TypeSet &GetTypeSet() const
83     {
84         ASSERT(IsTypeSet());
85         return std::get<TypeSet>(Contents_);
86     }
87 
IsNone()88     bool IsNone() const
89     {
90         return std::holds_alternative<None>(Contents_);
91     }
IsVar()92     bool IsVar() const
93     {
94         return std::holds_alternative<Variables::Var>(Contents_);
95     }
IsType()96     bool IsType() const
97     {
98         return std::holds_alternative<Type>(Contents_);
99     }
IsTypeSet()100     bool IsTypeSet() const
101     {
102         return std::holds_alternative<TypeSet>(Contents_);
103     }
104 
IsConsistent()105     bool IsConsistent() const
106     {
107         if (IsType()) {
108             return !GetType().IsTop();
109         } else if (IsTypeSet()) {
110             Type the_only_type = GetTypeSet().TheOnlyType();
111             return !(the_only_type.IsValid() && the_only_type.IsTop());
112         } else {
113             return false;
114         }
115     }
116 
117     AbstractType operator&(const AbstractType &rhs) const
118     {
119         if (IsType()) {
120             if (rhs.IsType()) {
121                 Type lhs_type = GetType();
122                 Type rhs_type = rhs.GetType();
123                 if (lhs_type <= rhs_type) {
124                     return rhs_type;
125                 } else if (rhs_type <= lhs_type) {
126                     return lhs_type;
127                 } else {
128                     return lhs_type & rhs_type;
129                 }
130             } else if (rhs.IsTypeSet()) {
131                 return MergeTypeAndTypeSet(GetType(), rhs.GetTypeSet());
132             } else {
133                 UNREACHABLE();
134             }
135         } else if (IsTypeSet()) {
136             if (rhs.IsType()) {
137                 return MergeTypeAndTypeSet(rhs.GetType(), GetTypeSet());
138             } else if (rhs.IsTypeSet()) {
139                 return GetTypeSet() & rhs.GetTypeSet();
140             } else {
141                 UNREACHABLE();
142             }
143         } else {
144             UNREACHABLE();
145         }
146     }
147 
148     template <typename TypeImageFunc>
Image(TypeImageFunc type_img_func)149     PandaString Image(TypeImageFunc type_img_func) const
150     {
151         if (IsNone()) {
152             return "<none>";
153         } else if (IsVar()) {
154             return GetVar().Image("<TypeVar") + ">";
155         } else if (IsType()) {
156             PandaString result = type_img_func(GetType());
157             return result;
158         } else if (IsTypeSet()) {
159             return GetTypeSet().Image(type_img_func);
160         }
161         return "<unexpected kind of AbstractType>";
162     }
163 
164     template <typename TypeHandler, typename Default>
ForAllTypes(TypeHandler && type_handler,Default && non_type_handler)165     bool ForAllTypes(TypeHandler &&type_handler, Default &&non_type_handler) const
166     {
167         if (IsType()) {
168             return type_handler(GetType());
169         } else if (IsTypeSet()) {
170             return GetTypeSet().ForAll(std::forward<TypeHandler>(type_handler));
171         } else {
172             return non_type_handler();
173         }
174     }
175 
176     template <typename TypeHandler>
ForAllTypes(TypeHandler && type_handler)177     bool ForAllTypes(TypeHandler &&type_handler) const
178     {
179         return ForAllTypes(std::forward<TypeHandler>(type_handler), []() { return true; });
180     }
181 
182     template <typename TypeHandler>
ExistsType(TypeHandler && type_handler)183     bool ExistsType(TypeHandler &&type_handler) const
184     {
185         return !ForAllTypes([&type_handler](auto t) { return !type_handler(t); });
186     }
187 
188 private:
189     ContentsData Contents_;
190 
MergeTypeAndTypeSet(Type type,const TypeSet & type_set)191     AbstractType MergeTypeAndTypeSet(Type type, const TypeSet &type_set) const
192     {
193         if (type_set.Contains(type)) {
194             return type;
195         } else {
196             return type & type_set;
197         }
198     }
199 };
200 
201 }  // namespace panda::verifier
202 
203 #endif  // !_PANDA_VERIFIER_ABSTRACT_TYPE_HPP
204