EvalEmitDVArray: varray
[hiphop-php.git] / hphp / runtime / base / annot-type.cpp
blobaa6ba82563f423a9b52bdfa9c25070d3b457f4b4
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
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"
26 namespace HPHP {
28 ///////////////////////////////////////////////////////////////////////////////
30 using HhvmStrToTypeMap = hphp_hash_map<
31 const StringData*, AnnotType, string_data_hash, string_data_isame
34 using StdStrToTypeMap = hphp_string_imap<AnnotType>;
36 const StaticString
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;
56 /**
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;
64 const struct Pair {
65 const char* name;
66 AnnotType type;
67 } pairs[] = {
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 },
90 "HH\\varray",
91 RuntimeOption::EvalHackArrDVArrs ? AnnotType::Vec : AnnotType::VArray
94 "HH\\darray",
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;
109 return mappedPairs;
110 }();
111 return mapPair;
114 const AnnotType* nameToAnnotType(const StringData* typeName) {
115 assertx(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);
124 return at;
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) {
275 switch (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:
300 case AnnotType::Vec:
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 ///////////////////////////////////////////////////////////////////////////////