Clean up VectorEffects::init
[hiphop-php.git] / hphp / runtime / vm / type_constraint.h
blob05f906d6137a68c5084fe5c0000967258894d43b
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
16 #ifndef incl_HPHP_TYPE_CONSTRAINT_H_
17 #define incl_HPHP_TYPE_CONSTRAINT_H_
19 #include <string>
20 #include <tr1/functional>
22 #include "hphp/runtime/base/types.h"
23 #include "hphp/util/case_insensitive.h"
24 #include "hphp/runtime/vm/unit.h"
25 #include "hphp/runtime/vm/type_profile.h"
27 namespace HPHP {
29 class Func;
31 class TypeConstraint {
32 public:
33 enum Flags {
34 NoFlags = 0x0,
37 * Nullable type hints check they are either the specified type,
38 * or null.
40 Nullable = 0x1,
43 * This flag indicates either EnableHipHopSyntax was true, or the
44 * type came from a <?hh file and EnableHipHopSyntax was false.
46 HHType = 0x2,
49 * Extended hints are hints that do not apply to normal, vanilla
50 * php. For example "?Foo".
52 ExtendedHint = 0x4,
55 private:
56 enum class MetaType {
57 Precise,
58 Self,
59 Parent,
60 Callable
63 struct Type {
64 DataType m_dt;
65 MetaType m_metatype;
66 constexpr bool isParent() const {
67 return m_metatype == MetaType::Parent;
69 constexpr bool isSelf() const {
70 return m_metatype == MetaType::Self;
72 constexpr bool isCallable() const {
73 return m_metatype == MetaType::Callable;
75 constexpr bool isPrecise() const {
76 return m_metatype == MetaType::Precise;
80 // m_type represents the DataType to check on. We don't know
81 // whether a bare name is a class/interface name or a typedef, so
82 // when this is set to KindOfObject we may have to look up a typedef
83 // name and test for a different DataType.
84 Type m_type;
85 Flags m_flags;
86 const StringData* m_typeName;
87 const NamedEntity* m_namedEntity;
88 typedef hphp_hash_map<const StringData*, Type,
89 string_data_hash, string_data_isame> TypeMap;
90 static TypeMap s_typeNamesToTypes;
92 void init();
94 public:
95 void verifyFail(const Func* func, int paramNum, const TypedValue* tv) const;
97 TypeConstraint()
98 : m_flags(NoFlags)
99 , m_typeName(nullptr)
100 , m_namedEntity(nullptr)
102 init();
105 TypeConstraint(const StringData* typeName, Flags flags)
106 : m_flags(flags)
107 , m_typeName(typeName)
108 , m_namedEntity(nullptr)
110 init();
113 TypeConstraint(const TypeConstraint&) = default;
114 TypeConstraint& operator=(const TypeConstraint&) = default;
116 bool hasConstraint() const { return m_typeName; }
118 const StringData* typeName() const { return m_typeName; }
119 const NamedEntity* namedEntity() const { return m_namedEntity; }
121 bool nullable() const { return m_flags & Nullable; }
122 bool hhType() const { return m_flags & HHType; }
123 Flags flags() const { return m_flags; }
125 bool isSelf() const {
126 return m_type.isSelf();
129 bool isParent() const {
130 return m_type.isParent();
133 bool isCallable() const {
134 return m_type.isCallable();
137 bool isPrecise() const {
138 return m_type.isPrecise();
141 bool isObjectOrTypedef() const {
142 assert(IMPLIES(isParent(), m_type.m_dt == KindOfObject));
143 assert(IMPLIES(isSelf(), m_type.m_dt == KindOfObject));
144 assert(IMPLIES(isCallable(), m_type.m_dt == KindOfObject));
145 return m_type.m_dt == KindOfObject;
148 bool compat(const TypeConstraint& other) const {
149 if (other.isExtended() || isExtended()) {
151 * Rely on the ahead of time typechecker---checking here can
152 * make it harder to convert a base class or interface to <?hh,
153 * because derived classes that are still <?php would all need
154 * to be modified.
156 return true;
158 return (m_typeName == other.m_typeName
159 || (m_typeName != nullptr && other.m_typeName != nullptr
160 && m_typeName->isame(other.m_typeName)));
163 static bool equivDataTypes(DataType t1, DataType t2) {
164 return
165 (t1 == t2) ||
166 (IS_STRING_TYPE(t1) && IS_STRING_TYPE(t2)) ||
167 (IS_NULL_TYPE(t1) && IS_NULL_TYPE(t2));
170 // General check for any constraint.
171 bool check(const TypedValue* tv, const Func* func) const;
173 // Check a constraint when !isObjectOrTypedef().
174 bool checkPrimitive(DataType dt) const;
176 // Typedef checks when we know tv is or is not an object.
177 bool checkTypedefObj(const TypedValue* tv) const;
178 bool checkTypedefNonObj(const TypedValue* tv) const;
180 // NB: will throw if the check fails.
181 void verify(const TypedValue* tv,
182 const Func* func, int paramNum) const {
183 if (UNLIKELY(!check(tv, func))) {
184 verifyFail(func, paramNum, tv);
188 // Can not be private as it needs to be used by the translator
189 void selfToClass(const Func* func, const Class **cls) const;
190 void parentToClass(const Func* func, const Class **cls) const;
191 private:
192 bool isExtended() const { return m_flags & ExtendedHint; }
194 void selfToTypeName(const Func* func, const StringData **typeName) const;
195 void parentToTypeName(const Func* func, const StringData **typeName) const;
198 inline TypeConstraint::Flags
199 operator|(TypeConstraint::Flags a, TypeConstraint::Flags b) {
200 return TypeConstraint::Flags(static_cast<int>(a) | static_cast<int>(b));
205 #endif