Arquivos
hhvm/hphp/tools/bootstrap/idl.h
T
Sara Golemon a3f507d58d Add reference to extension object to class_map
Add IDL component:
{
  "extension": {
    "symbol": "s_foo_extension"
  }
}

extension.symbol is the C++ HPHP::Extension symbol for the
extension (if one exists and is exported).
2013-06-27 10:45:56 -07:00

408 linhas
12 KiB
C++

/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#ifndef HPHP_IDL_H
#define HPHP_IDL_H
#include "folly/Conv.h"
#include "folly/DynamicConverter.h"
#include "folly/FBString.h"
#include "folly/FBVector.h"
#include "hphp/runtime/base/datatype.h"
using folly::fbstring;
using folly::fbvector;
namespace HPHP { namespace IDL {
/////////////////////////////////////////////////////////////////////////////
enum FuncFlags {
ZendParamMode = (1 << 0),
IsAbstract = (1 << 4),
IsFinal = (1 << 5),
IsPublic = (1 << 6),
IsProtected = (1 << 7),
IsPrivate = (1 << 8),
IgnoreRedefinition = (1 << 8),
IsStatic = (1 << 9),
IsCppAbstract = (1 << 10),
IsReference = (1 << 11),
IsConstructor = (1 << 12),
IsNothing = (1 << 13),
HasDocComment = (1 << 14),
HipHopSpecific = (1 << 16),
VariableArguments = (1 << 17),
RefVariableArguments = (1 << 18),
MixedVariableArguments = (1 << 19),
FunctionIsFoldable = (1 << 20),
NoEffect = (1 << 21),
NoInjection = (1 << 22),
HasOptFunction = (1 << 23),
AllowIntercept = (1 << 24),
NoProfile = (1 << 25),
ContextSensitive = (1 << 26),
NoDefaultSweep = (1 << 27),
IsSystem = (1 << 28),
IsTrait = (1 << 29),
NeedsActRec = (1 << 31),
};
#define VarArgsMask (VariableArguments | \
RefVariableArguments | \
MixedVariableArguments)
bool isKindOfIndirect(DataType kindof);
static inline fbstring kindOfString(DataType t) {
switch (t) {
case KindOfAny: return "Any";
case KindOfUnknown: return "Unknown";
case KindOfNull: return "Null";
case KindOfBoolean: return "Boolean";
case KindOfInt64: return "Int64";
case KindOfDouble: return "Double";
case KindOfStaticString: return "StaticString";
case KindOfString: return "String";
case KindOfArray: return "Array";
case KindOfObject: return "Object";
case KindOfRef: return "Ref";
default:
// No other enums should occur in IDL parsing
assert(false);
return "";
}
}
static inline fbstring escapeCpp(const fbstring& str) {
std::ostringstream ssb;
for (auto c : str) {
switch (c) {
case '\n': ssb << "\\n"; break;
case '\r': ssb << "\\r"; break;
case '\t': ssb << "\\t"; break;
case '\a': ssb << "\\a"; break;
case '\b': ssb << "\\b"; break;
case '\f': ssb << "\\f"; break;
case '\v': ssb << "\\v"; break;
case '\0': ssb << "\\000"; break;
case '\"': ssb << "\\\""; break;
case '\\': ssb << "\\\\"; break;
case '\?': ssb << "\\?"; break; // trigraphs
default:
if ((c >= 0x20) && (c <= 0x7f)) {
ssb << c;
} else {
char buf[6];
snprintf(buf, sizeof(buf), "\\%03o", (unsigned int)c);
ssb << buf;
}
}
}
return fbstring(ssb.str());
}
static inline fbstring strtolower(const fbstring& str) {
fbstring lcase = str;
std::transform(str.begin(), str.end(), lcase.begin(),
std::ptr_fun<int, int>(std::tolower));
return lcase;
}
fbstring phpSerialize(const folly::dynamic& d);
enum class ParamMode {
CoerceAndCall,
Zend
};
class PhpConst {
public:
explicit PhpConst(const folly::dynamic& cns, fbstring cls = "");
fbstring name() const { return m_name; }
fbstring varname() const {
return m_className.empty() ? ("k_" + m_name)
: ("q_" + m_className + "$$" + m_name);
}
bool isSystem() const { return m_className.empty(); }
fbstring getCppType() const { return m_cppType; }
DataType kindOf() const { return m_kindOf; }
bool hasValue() const {
return (m_constant.find("value") != m_constant.items().end());
}
fbstring value() const {
auto it = m_constant.find("value");
assert(it != m_constant.items().end());
auto v = it->second;
return v.isNull() ? "uninit_null()" : v.asString();
}
fbstring serialize() const { return phpSerialize(m_constant["value"]); }
private:
folly::dynamic m_constant;
fbstring m_name;
fbstring m_className;
fbstring m_cppType;
DataType m_kindOf;
bool parseType(const folly::dynamic& cns);
bool inferType(const folly::dynamic& cns);
};
class PhpParam {
public:
explicit PhpParam(const folly::dynamic& param, bool isMagicMethod = false,
ParamMode paramMode = ParamMode::CoerceAndCall);
fbstring name() const { return m_name; }
fbstring getDesc() const { return m_desc; }
fbstring getCppType() const { return m_cppType; }
fbstring getStrippedCppType() const {
fbstring ret = m_cppType;
if (!ret.compare(0, 6, "HPHP::")) {
ret = ret.substr(6);
}
if (!ret.compare(ret.length() - 7, 7, " const&")) {
ret = ret.substr(0, ret.length() - 7);
}
return ret;
}
DataType kindOf() const { return m_kindOf; }
fbstring getPhpType() const { return m_phpType; }
bool isRef() const { return m_param.getDefault("ref", false).asBool(); }
bool hasDefault() const {
return m_param.find("value") != m_param.items().end();
}
fbstring getDefault() const {
return hasDefault() ? m_param["value"].asString() : "";
}
fbstring getDefaultSerialized() const;
fbstring getDefaultPhp() const;
bool isCheckedType() const {
return !isRef() && (kindOf() != KindOfAny);
}
bool defValueNeedsVariable() const;
bool isIndirectPass() const { return isKindOfIndirect(kindOf()); }
ParamMode getParamMode() const { return m_paramMode; }
private:
fbstring m_name;
folly::dynamic m_param;
fbstring m_desc;
DataType m_kindOf;
fbstring m_cppType;
fbstring m_phpType;
ParamMode m_paramMode;
};
class PhpFunc {
public:
PhpFunc(const folly::dynamic& d, const fbstring& className);
fbstring name() const { return m_name; }
fbstring className() const { return m_className; }
fbstring getDesc() const { return m_desc; }
bool isMethod() const {
return !m_className.empty();
}
bool isMagicMethod() const {
return (isMethod() && (
(m_name == "__get") ||
(m_name == "__set") ||
(m_name == "__isset") ||
(m_name == "__unset") ||
(m_name == "__call")));
}
fbstring getCppSig() const;
fbstring getPrettyName() const {
if (isMethod()) {
return m_className + "::" + m_name;
} else {
return m_name;
}
}
fbstring getUniqueName() const {
if (isMethod()) {
return folly::to<fbstring>(m_className.length(), m_className,
'_', m_name);
} else {
return m_name;
}
}
bool isReturnRef() const { return m_returnRef; }
DataType returnKindOf() const { return m_returnKindOf; }
fbstring returnCppType() const { return m_returnCppType; }
fbstring returnPhpType() const { return m_returnPhpType; }
fbstring returnDesc() const { return m_returnDesc; }
bool isIndirectReturn() const { return isKindOfIndirect(returnKindOf()); }
bool isCtor() const { return isMethod() && (m_name == "__construct"); }
bool isStatic() const { return m_flags & IsStatic; }
bool isVarArgs() const { return m_flags & VarArgsMask; }
bool usesThis() const { return isMethod() && !isStatic(); }
unsigned int flags() const { return m_flags; }
int numParams() const { return m_params.size(); }
int minNumParams() const { return m_minNumParams; }
int numTypeChecks() const { return m_numTypeChecks; }
const PhpParam& param(int p) const { return m_params[p]; }
const fbvector<PhpParam>& params() const { return m_params; }
bool hasDocComment() const {
auto it = m_func.find("doc");
return (it != m_func.items().end()) && it->second.size();
}
fbstring docComment() const {
return hasDocComment() ? m_func["doc"].asString() : "";
}
private:
fbstring m_name;
fbstring m_className;
folly::dynamic m_func;
unsigned long m_flags;
fbstring m_desc;
// Return value
bool m_returnRef;
DataType m_returnKindOf;
fbstring m_returnCppType;
fbstring m_returnPhpType;
fbstring m_returnDesc;
fbvector<PhpParam> m_params;
// Computed properties.
int m_minNumParams;
int m_numTypeChecks;
};
class PhpProp {
public:
PhpProp(const folly::dynamic& d, fbstring cls);
fbstring name() const { return m_name; }
fbstring className() const { return m_className; }
unsigned long flags() const { return m_flags; }
DataType kindOf() const { return m_kindOf; }
private:
fbstring m_name;
fbstring m_className;
folly::dynamic m_prop;
unsigned long m_flags;
DataType m_kindOf;
};
class PhpClass {
public:
explicit PhpClass(const folly::dynamic &c);
fbstring name() const { return m_name; }
fbstring parent() const {
auto p = m_class.find("parent");
if (p == m_class.items().end()) {
return "";
}
assert(p->second.isString());
return p->second.asString();
}
int numIfaces() const { return m_ifaces.size(); }
fbvector<fbstring> ifaces() const { return m_ifaces; }
bool hasDocComment() const {
auto it = m_class.find("doc");
return (it != m_class.items().end()) && it->second.size();
}
fbstring docComment() const {
return hasDocComment() ? m_class["doc"].asString() : "";
}
fbstring getDesc() const { return m_desc; }
int numMethods() const { return m_methods.size(); }
const fbvector<PhpFunc>& methods() const { return m_methods; }
unsigned long flags() const { return m_flags; }
int numProperties() const { return m_properties.size(); }
fbvector<PhpProp> properties() const { return m_properties; }
int numConstants() const { return m_constants.size(); }
fbvector<PhpConst> constants() const { return m_constants; }
private:
folly::dynamic m_class;
fbstring m_name;
fbvector<fbstring> m_ifaces;
fbvector<PhpFunc> m_methods;
fbvector<PhpConst> m_constants;
fbvector<PhpProp> m_properties;
unsigned long m_flags;
fbstring m_desc;
};
class PhpExtension {
public:
explicit PhpExtension(const folly::dynamic& e)
: m_extension(e) { }
/* The C++ symbol name of the Extension struct.
* Only needed if s_(name)_extension is not correct.
* Set to blank if this ext doens't declare an Extension.
*/
fbstring symbol() const {
auto it = m_extension.find("symbol");
if (it != m_extension.items().end()) {
return it->second.asString();
}
return "";
}
private:
folly::dynamic m_extension;
};
void parseIDL(const char* idlFilePath,
fbvector<PhpFunc>& funcVec,
fbvector<PhpClass>& classVec);
void parseIDL(const char* idlFilePath,
fbvector<PhpFunc>& funcVec,
fbvector<PhpClass>& classVec,
fbvector<PhpConst>& constVec,
fbvector<PhpExtension>& extVec);
/////////////////////////////////////////////////////////////////////////////
}} // namespace HPHP::IDL
#endif