2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-2014 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/compiler/type_annotation.h"
18 #include "hphp/util/util.h"
22 ///////////////////////////////////////////////////////////////////////////////
23 // constructors/destructors
25 TypeAnnotation::TypeAnnotation(const std::string
&name
,
26 TypeAnnotationPtr typeArgs
) : m_name(name
),
28 m_typeList(TypeAnnotationPtr()),
36 std::string
TypeAnnotation::vanillaName() const {
37 // filter out types that should not be exposed to the runtime
38 if (m_nullable
|| m_soft
|| m_typevar
|| m_function
) {
41 if (!m_name
.compare("mixed") || !m_name
.compare("this")) {
47 std::string
TypeAnnotation::fullName() const {
57 functionTypeName(name
);
62 } else if (m_typeArgs
) {
63 genericTypeName(name
);
70 DataType
TypeAnnotation::dataType(bool expectedType
/*= false */) const {
71 if (m_function
|| m_xhp
|| m_tuple
) {
75 return !m_name
.compare("array") ? KindOfArray
: KindOfObject
;
77 if (!expectedType
&& (m_nullable
|| m_soft
)) {
80 if (!m_name
.compare("null") || !m_name
.compare("void")) {
83 if (!m_name
.compare("bool")) return KindOfBoolean
;
84 if (!m_name
.compare("int")) return KindOfInt64
;
85 if (!m_name
.compare("float")) return KindOfDouble
;
86 if (!m_name
.compare("num")) return KindOfUnknown
;
87 if (!m_name
.compare("string")) return KindOfString
;
88 if (!m_name
.compare("array")) return KindOfArray
;
89 if (!m_name
.compare("resource")) return KindOfResource
;
90 if (!m_name
.compare("mixed")) return KindOfUnknown
;
95 void TypeAnnotation::getAllSimpleNames(std::vector
<std::string
>& names
) const {
96 names
.push_back(m_name
);
98 m_typeList
->getAllSimpleNames(names
);
99 } else if (m_typeArgs
) {
100 m_typeArgs
->getAllSimpleNames(names
);
104 void TypeAnnotation::functionTypeName(std::string
&name
) const {
105 name
+= "(function (";
106 // return value of function types is the first element of type list
107 TypeAnnotationPtr retType
= m_typeArgs
;
108 TypeAnnotationPtr typeEl
= m_typeArgs
->m_typeList
;
109 bool hasArgs
= (typeEl
!= nullptr);
111 name
+= typeEl
->fullName();
112 typeEl
= typeEl
->m_typeList
;
115 // replace the trailing ", " (if any) with "): "
117 name
.replace(name
.size() - 2, 2, "): ");
121 // add function return value
122 name
+= retType
->fullName();
126 // xhp names are mangled so we get them back to their original definition
127 // @see the mangling in ScannerToken::xhpLabel
128 void TypeAnnotation::xhpTypeName(std::string
&name
) const {
129 // remove prefix if any
130 if (m_name
.compare(0, sizeof("xhp_") - 1, "xhp_") == 0) {
131 name
+= std::string(m_name
).replace(0, sizeof("xhp_") - 1, ":");
136 Util::replaceAll(name
, "__", ":");
137 Util::replaceAll(name
, "_", "-");
140 void TypeAnnotation::tupleTypeName(std::string
&name
) const {
142 TypeAnnotationPtr typeEl
= m_typeArgs
;
144 name
+= typeEl
->fullName();
145 typeEl
= typeEl
->m_typeList
;
148 // replace the trailing ", " with ")"
149 name
.replace(name
.size() - 2, 2, ")");
152 void TypeAnnotation::genericTypeName(std::string
&name
) const {
155 TypeAnnotationPtr typeEl
= m_typeArgs
;
157 name
+= typeEl
->fullName();
158 typeEl
= typeEl
->m_typeList
;
161 // replace the trailing ", " with ">"
162 name
.replace(name
.size() - 2, 2, ">");
165 void TypeAnnotation::appendToTypeList(TypeAnnotationPtr typeList
) {
167 TypeAnnotationPtr current
= m_typeList
;
168 while (current
->m_typeList
) {
169 current
= current
->m_typeList
;
171 current
->m_typeList
= typeList
;
173 m_typeList
= typeList
;
177 void TypeAnnotation::outputCodeModel(CodeGenerator
& cg
) {
178 TypeAnnotationPtr typeArgsElem
= m_typeArgs
;
179 auto numTypeArgs
= 0;
180 while (typeArgsElem
!= nullptr) {
182 typeArgsElem
= typeArgsElem
->m_typeList
;
184 typeArgsElem
= m_typeArgs
;
187 if (m_nullable
) numProps
++;
188 if (m_soft
) numProps
++;
191 // Since this is a function type, the first type argument is the return type
192 // and no typeArguments property will be serialized unless there are at
193 // least two type arguments.
194 if (numTypeArgs
> 1) numProps
++;
196 if (numTypeArgs
> 0) numProps
++;
198 cg
.printObjectHeader("TypeExpression", numProps
);
199 cg
.printPropertyHeader("name");
200 cg
.printValue(m_tuple
? "tuple" : m_name
);
202 cg
.printPropertyHeader("isNullable");
206 cg
.printPropertyHeader("isSoft");
210 cg
.printPropertyHeader("returnType");
211 typeArgsElem
->outputCodeModel(cg
);
212 typeArgsElem
= typeArgsElem
->m_typeList
;
213 // Since we've grabbed the first element of the list as the return
214 // type, make sure that the logic for serializing type arguments gets
215 // disabled unless there is at least one more type argument.
218 if (numTypeArgs
> 0) {
219 cg
.printPropertyHeader("typeArguments");
220 cg
.printf("V:9:\"HH\\Vector\":%d:{", numTypeArgs
);
221 while (typeArgsElem
!= nullptr) {
222 typeArgsElem
->outputCodeModel(cg
);
223 typeArgsElem
= typeArgsElem
->m_typeList
;
227 cg
.printObjectFooter();