2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present 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 +----------------------------------------------------------------------+
17 #include "hphp/runtime/base/annot-type.h"
19 #include <folly/Optional.h>
20 #include <folly/MapUtil.h>
21 #include "hphp/runtime/base/string-data.h"
22 #include "hphp/runtime/base/static-string-table.h"
23 #include "hphp/runtime/vm/runtime.h"
24 #include "hphp/util/hash-map.h"
28 ///////////////////////////////////////////////////////////////////////////////
30 using HhvmStrToTypeMap
= hphp_hash_map
<
31 const StringData
*, AnnotType
, string_data_hash
, string_data_isame
34 using StdStrToTypeMap
= hphp_string_imap
<AnnotType
>;
37 s_HH_Traversable("HH\\Traversable"),
38 s_HH_RX_Traversable("HH\\Rx\\Traversable"),
39 s_HH_KeyedTraversable("HH\\KeyedTraversable"),
40 s_HH_RX_KeyedTraversable("HH\\Rx\\KeyedTraversable"),
41 s_HH_Container("HH\\Container"),
42 s_HH_KeyedContainer("HH\\KeyedContainer"),
43 s_XHPChild("XHPChild"),
44 s_Stringish("Stringish");
46 MaybeDataType
nameToMaybeDataType(const StringData
* typeName
) {
47 auto const* type
= nameToAnnotType(typeName
);
48 return type
? MaybeDataType(getAnnotDataType(*type
)) : folly::none
;
51 MaybeDataType
nameToMaybeDataType(const std::string
& typeName
) {
52 auto const* type
= nameToAnnotType(typeName
);
53 return type
? MaybeDataType(getAnnotDataType(*type
)) : folly::none
;
57 * This is the authoritative map that determines which typehints require
58 * special handling. Any typehint not on this list is assumed to be normal
59 * "class-name" typehint.
61 static const std::pair
<HhvmStrToTypeMap
, StdStrToTypeMap
>& getAnnotTypeMaps() {
62 static const std::pair
<HhvmStrToTypeMap
, StdStrToTypeMap
> mapPair
= []() {
63 std::pair
<HhvmStrToTypeMap
, StdStrToTypeMap
> mappedPairs
;
68 { "HH\\nothing", AnnotType::Nothing
},
69 { "HH\\noreturn", AnnotType::NoReturn
},
70 { "HH\\null", AnnotType::Null
},
71 { "HH\\void", AnnotType::Null
},
72 { "HH\\bool", AnnotType::Bool
},
73 { "HH\\int", AnnotType::Int
},
74 { "HH\\float", AnnotType::Float
},
75 { "HH\\string", AnnotType::String
},
76 { "array", AnnotType::Array
},
77 { "HH\\resource", AnnotType::Resource
},
78 { "HH\\mixed", AnnotType::Mixed
},
79 { "HH\\nonnull", AnnotType::Nonnull
},
80 { "HH\\num", AnnotType::Number
},
81 { "HH\\arraykey", AnnotType::ArrayKey
},
82 { "HH\\this", AnnotType::This
},
83 { "self", AnnotType::Self
},
84 { "parent", AnnotType::Parent
},
85 { "callable", AnnotType::Callable
},
86 { "HH\\dict", AnnotType::Dict
},
87 { "HH\\vec", AnnotType::Vec
},
88 { "HH\\keyset", AnnotType::Keyset
},
91 RuntimeOption::EvalHackArrDVArrs
? AnnotType::Vec
: AnnotType::VArray
95 RuntimeOption::EvalHackArrDVArrs
? AnnotType::Dict
: AnnotType::DArray
98 "HH\\varray_or_darray",
99 RuntimeOption::EvalHackArrDVArrs
100 ? AnnotType::VecOrDict
: AnnotType::VArrOrDArr
102 { "HH\\vec_or_dict", AnnotType::VecOrDict
},
103 { "HH\\arraylike", AnnotType::ArrayLike
},
105 for (unsigned i
= 0; i
< sizeof(pairs
) / sizeof(Pair
); ++i
) {
106 mappedPairs
.first
[makeStaticString(pairs
[i
].name
)] = pairs
[i
].type
;
107 mappedPairs
.second
[pairs
[i
].name
] = pairs
[i
].type
;
114 const AnnotType
* nameToAnnotType(const StringData
* typeName
) {
116 auto const& mapPair
= getAnnotTypeMaps();
117 return folly::get_ptr(mapPair
.first
, typeName
);
120 const AnnotType
* nameToAnnotType(const std::string
& typeName
) {
121 auto const& mapPair
= getAnnotTypeMaps();
122 auto const* at
= folly::get_ptr(mapPair
.second
, typeName
);
123 assertx(!at
|| *at
!= AnnotType::Object
);
127 bool interface_supports_non_objects(const StringData
* s
) {
128 return (s
->isame(s_HH_Traversable
.get()) ||
129 s
->isame(s_HH_KeyedTraversable
.get()) ||
130 s
->isame(s_HH_RX_Traversable
.get()) ||
131 s
->isame(s_HH_RX_KeyedTraversable
.get()) ||
132 s
->isame(s_HH_Container
.get()) ||
133 s
->isame(s_HH_KeyedContainer
.get()) ||
134 s
->isame(s_XHPChild
.get()) ||
135 s
->isame(s_Stringish
.get()));
138 bool interface_supports_array(const StringData
* s
) {
139 return (s
->isame(s_HH_Traversable
.get()) ||
140 s
->isame(s_HH_KeyedTraversable
.get()) ||
141 s
->isame(s_HH_RX_Traversable
.get()) ||
142 s
->isame(s_HH_RX_KeyedTraversable
.get()) ||
143 s
->isame(s_HH_Container
.get()) ||
144 s
->isame(s_HH_KeyedContainer
.get()) ||
145 s
->isame(s_XHPChild
.get()));
148 bool interface_supports_array(const std::string
& n
) {
149 const char* s
= n
.c_str();
150 return ((n
.size() == 14 && !strcasecmp(s
, "HH\\Traversable")) ||
151 (n
.size() == 19 && !strcasecmp(s
, "HH\\KeyedTraversable")) ||
152 (n
.size() == 17 && !strcasecmp(s
, "HH\\Rx\\Traversable")) ||
153 (n
.size() == 22 && !strcasecmp(s
, "HH\\Rx\\KeyedTraversable")) ||
154 (n
.size() == 12 && !strcasecmp(s
, "HH\\Container")) ||
155 (n
.size() == 17 && !strcasecmp(s
, "HH\\KeyedContainer")) ||
156 (n
.size() == 8 && !strcasecmp(s
, "XHPChild")));
159 bool interface_supports_vec(const StringData
* s
) {
160 return (s
->isame(s_HH_Traversable
.get()) ||
161 s
->isame(s_HH_KeyedTraversable
.get()) ||
162 s
->isame(s_HH_RX_Traversable
.get()) ||
163 s
->isame(s_HH_RX_KeyedTraversable
.get()) ||
164 s
->isame(s_HH_Container
.get()) ||
165 s
->isame(s_HH_KeyedContainer
.get()) ||
166 s
->isame(s_XHPChild
.get()));
169 bool interface_supports_vec(const std::string
& n
) {
170 const char* s
= n
.c_str();
171 return ((n
.size() == 14 && !strcasecmp(s
, "HH\\Traversable")) ||
172 (n
.size() == 19 && !strcasecmp(s
, "HH\\KeyedTraversable")) ||
173 (n
.size() == 17 && !strcasecmp(s
, "HH\\Rx\\Traversable")) ||
174 (n
.size() == 22 && !strcasecmp(s
, "HH\\Rx\\KeyedTraversable")) ||
175 (n
.size() == 12 && !strcasecmp(s
, "HH\\Container")) ||
176 (n
.size() == 17 && !strcasecmp(s
, "HH\\KeyedContainer")) ||
177 (n
.size() == 8 && !strcasecmp(s
, "XHPChild")));
180 bool interface_supports_dict(const StringData
* s
) {
181 return (s
->isame(s_HH_Traversable
.get()) ||
182 s
->isame(s_HH_KeyedTraversable
.get()) ||
183 s
->isame(s_HH_RX_Traversable
.get()) ||
184 s
->isame(s_HH_RX_KeyedTraversable
.get()) ||
185 s
->isame(s_HH_Container
.get()) ||
186 s
->isame(s_HH_KeyedContainer
.get()) ||
187 s
->isame(s_XHPChild
.get()));
190 bool interface_supports_dict(const std::string
& n
) {
191 const char* s
= n
.c_str();
192 return ((n
.size() == 14 && !strcasecmp(s
, "HH\\Traversable")) ||
193 (n
.size() == 19 && !strcasecmp(s
, "HH\\KeyedTraversable")) ||
194 (n
.size() == 17 && !strcasecmp(s
, "HH\\Rx\\Traversable")) ||
195 (n
.size() == 22 && !strcasecmp(s
, "HH\\Rx\\KeyedTraversable")) ||
196 (n
.size() == 12 && !strcasecmp(s
, "HH\\Container")) ||
197 (n
.size() == 17 && !strcasecmp(s
, "HH\\KeyedContainer")) ||
198 (n
.size() == 8 && !strcasecmp(s
, "XHPChild")));
201 bool interface_supports_shape(const StringData
* s
) {
202 return (s
->isame(s_HH_Traversable
.get()) ||
203 s
->isame(s_HH_KeyedTraversable
.get()) ||
204 s
->isame(s_HH_RX_Traversable
.get()) ||
205 s
->isame(s_HH_RX_KeyedTraversable
.get()) ||
206 s
->isame(s_HH_Container
.get()) ||
207 s
->isame(s_HH_KeyedContainer
.get()) ||
208 s
->isame(s_XHPChild
.get()));
211 bool interface_supports_shape(const std::string
& n
) {
212 const char* s
= n
.c_str();
213 return ((n
.size() == 14 && !strcasecmp(s
, "HH\\Traversable")) ||
214 (n
.size() == 19 && !strcasecmp(s
, "HH\\KeyedTraversable")) ||
215 (n
.size() == 17 && !strcasecmp(s
, "HH\\Rx\\Traversable")) ||
216 (n
.size() == 22 && !strcasecmp(s
, "HH\\Rx\\KeyedTraversable")) ||
217 (n
.size() == 12 && !strcasecmp(s
, "HH\\Container")) ||
218 (n
.size() == 17 && !strcasecmp(s
, "HH\\KeyedContainer")) ||
219 (n
.size() == 8 && !strcasecmp(s
, "XHPChild")));
222 bool interface_supports_keyset(const StringData
* s
) {
223 return (s
->isame(s_HH_Traversable
.get()) ||
224 s
->isame(s_HH_KeyedTraversable
.get()) ||
225 s
->isame(s_HH_RX_Traversable
.get()) ||
226 s
->isame(s_HH_RX_KeyedTraversable
.get()) ||
227 s
->isame(s_HH_Container
.get()) ||
228 s
->isame(s_HH_KeyedContainer
.get()) ||
229 s
->isame(s_XHPChild
.get()));
232 bool interface_supports_keyset(const std::string
& n
) {
233 const char* s
= n
.c_str();
234 return ((n
.size() == 14 && !strcasecmp(s
, "HH\\Traversable")) ||
235 (n
.size() == 19 && !strcasecmp(s
, "HH\\KeyedTraversable")) ||
236 (n
.size() == 17 && !strcasecmp(s
, "HH\\Rx\\Traversable")) ||
237 (n
.size() == 22 && !strcasecmp(s
, "HH\\Rx\\KeyedTraversable")) ||
238 (n
.size() == 12 && !strcasecmp(s
, "HH\\Container")) ||
239 (n
.size() == 17 && !strcasecmp(s
, "HH\\KeyedContainer")) ||
240 (n
.size() == 8 && !strcasecmp(s
, "XHPChild")));
243 bool interface_supports_string(const StringData
* s
) {
244 return s
->isame(s_XHPChild
.get())
245 || s
->isame(s_Stringish
.get());
248 bool interface_supports_string(const std::string
& n
) {
249 const char *s
= n
.c_str();
250 return (n
.size() == 8 && !strcasecmp(s
, "XHPChild"))
251 || (n
.size() == 9 && !strcasecmp(s
, "Stringish"));
254 bool interface_supports_int(const StringData
* s
) {
255 return (s
->isame(s_XHPChild
.get()));
258 bool interface_supports_int(const std::string
& n
) {
259 const char *s
= n
.c_str();
260 return (n
.size() == 8 && !strcasecmp(s
, "XHPChild"));
263 bool interface_supports_double(const StringData
* s
) {
264 return (s
->isame(s_XHPChild
.get()));
267 bool interface_supports_double(const std::string
& n
) {
268 const char *s
= n
.c_str();
269 return (n
.size() == 8 && !strcasecmp(s
, "XHPChild"));
272 ///////////////////////////////////////////////////////////////////////////////
274 TypedValue
annotDefaultValue(AnnotType at
) {
276 case AnnotType::Mixed
:
277 case AnnotType::Self
:
278 case AnnotType::Parent
:
279 case AnnotType::This
:
280 case AnnotType::Callable
:
281 case AnnotType::Resource
:
282 case AnnotType::Object
:
283 case AnnotType::Nothing
:
284 case AnnotType::Record
:
285 case AnnotType::NoReturn
:
286 case AnnotType::Null
: return make_tv
<KindOfNull
>();
287 case AnnotType::Nonnull
:
288 case AnnotType::Number
:
289 case AnnotType::ArrayKey
:
290 case AnnotType::Int
: return make_tv
<KindOfInt64
>(0);
291 case AnnotType::Bool
: return make_tv
<KindOfBoolean
>(false);
292 case AnnotType::Float
: return make_tv
<KindOfDouble
>(0);
293 case AnnotType::DArray
:
294 return make_persistent_array_like_tv(staticEmptyDArray());
295 case AnnotType::VArray
:
296 case AnnotType::VArrOrDArr
:
297 return make_persistent_array_like_tv(staticEmptyVArray());
298 case AnnotType::ArrayLike
:
299 case AnnotType::VecOrDict
:
301 return make_tv
<KindOfPersistentVec
>(staticEmptyVecArray());
302 case AnnotType::String
:
303 return make_tv
<KindOfPersistentString
>(staticEmptyString());
304 case AnnotType::Array
:
305 return make_persistent_array_like_tv(staticEmptyArray());
306 case AnnotType::Dict
:
307 return make_tv
<KindOfPersistentDict
>(staticEmptyDictArray());
308 case AnnotType::Keyset
:
309 return make_tv
<KindOfPersistentKeyset
>(staticEmptyKeysetArray());
311 always_assert(false);
314 ///////////////////////////////////////////////////////////////////////////////