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