Add gen-class-map.cpp for bootstrapping constants.h and class_map.cpp

Conversion of PHP versions so we don't need PHP to build HHVM

For the most part, the generated files haven't changed from the
PHP sourced versions (apart from minor indentation and whitespace
changes).

Except for one major exception:
An IDL's function/method argument list includes a "value" field
for default parameters which takes psuedo-serialized values in
several forms. Most are simple scalarish values like:
  "true", "null", "null_array", "null_variant",
  "123", "0x456", "0123", "1.23", "\"foo\""
However referencing other constants is also supported:
  "k_FOO", "q_Bar$$BAZ"
Or even bitmask compositions like:
  "k_FOO|k_BAR|k_BAZ"

Runtime uses of these values are encoded directly into *.ext_hhvm.cpp
files, so they reach userspace code just fine.

The value placed in g_class_map are used exclusively by ext_reflection
to allow introspection at runtime.  Under the old class_map.php parameter
default constant references would be resolved in a (somewhat buggy) eval(),
since we don't have eval within gen-class-map, we reuse the
kUnserializable deferral.

This diff provides a mechanism to resolve this in ReflectionMethod
uses (an improvement from previous behavior), and leaves the current
eval-on-demand behavior for ReflectionFunction.  These two code paths
are different due to the partial state of migration away from using
ClassInfo.
Esse commit está contido em:
Sara Golemon
2013-06-12 11:57:37 -07:00
commit 13a055efa4
22 arquivos alterados com 1112 adições e 26997 exclusões
+2 -1
Ver Arquivo
@@ -22,7 +22,7 @@ SET(USE_HHVM TRUE)
SET(ENV{HHVM} 1)
ADD_DEFINITIONS("-DHHVM -DHHVM_BINARY=1 -DHHVM_PATH=\\\"${HPHP_HOME}/hphp/hhvm/hhvm\\\"")
set(RECURSIVE_SOURCE_SUBDIRS runtime/base runtime/debugger runtime/eval runtime/ext runtime/vm system util)
set(RECURSIVE_SOURCE_SUBDIRS runtime/base runtime/debugger runtime/eval runtime/ext runtime/vm util)
foreach (dir ${RECURSIVE_SOURCE_SUBDIRS})
auto_sources(files "*.cpp" "RECURSE" "${CMAKE_CURRENT_SOURCE_DIR}/${dir}")
@@ -96,6 +96,7 @@ add_subdirectory("tools/gen-ext-hhvm")
add_subdirectory(compiler)
add_subdirectory(runtime/ext_hhvm)
add_subdirectory(hhvm)
add_subdirectory(system)
if (NOT "$ENV{HPHP_NOTEST}" STREQUAL "1")
add_subdirectory(test)
+1 -1
Ver Arquivo
@@ -3,7 +3,7 @@ auto_sources(files "*.cpp" "")
list(APPEND CXX_SOURCES ${files})
add_executable(hhvm ${CXX_SOURCES})
target_link_libraries(hhvm hphp_analysis hphp_runtime_static ext_hhvm_static
target_link_libraries(hhvm hphp_analysis hphp_runtime_static ext_hhvm_static hphp_system
-Wl,-uregister_libevent_server)
add_custom_command(TARGET hhvm POST_BUILD
-251
Ver Arquivo
@@ -1,251 +0,0 @@
<?php
// Copyright 2004-2013 Facebook. All Rights Reserved.
require_once "base.php";
$args = $argv;
array_shift($args);
$target = array_shift($args);
foreach ($args as $arg) {
ReadIDLFile(realpath($arg));
}
if (substr($target, -4) == '.cpp') {
ob_start();
printf("// @"."generated by idl/class_map.php\n");
printf("#include \"hphp/runtime/base/base_includes.h\"\n");
printf("#include \"hphp/runtime/ext/ext.h\"\n");
printf("namespace HPHP {\n");
write_constants(false);
echo "const char *g_class_map[] = {\n";
echo ' (const char *)ClassInfo::IsSystem, NULL, "",';
echo ' "", NULL, NULL, NULL, ', "\n";
foreach ($funcs as $func) {
functionClassMap($func);
}
printf(" NULL,\n");
printf(" NULL,\n");
printf(' "false", (const char*)4, "b:0;",'."\n");
printf(' "true", (const char*)4, "b:1;",'."\n");
printf(' "null", (const char*)2, "N;",'."\n");
foreach ($constants as $constant) {
constantClassMap($constant);
}
printf(' "SID", (const char *)((offsetof(GlobalVariables, k_SID) - '.
'offsetof(GlobalVariables, stgv_Variant)) / sizeof(Variant)), '.
"(const char *)1,\n");
printf(' "PHP_SAPI", (const char *)((offsetof(GlobalVariables, k_PHP_SAPI) '.
'- offsetof(GlobalVariables, stgv_Variant)) / sizeof(Variant)), '.
"(const char *)1,\n");
printf(" NULL, // End of constants\n");
printf(" NULL,\n");
foreach ($classes as $cls) {
classClassMap($cls);
}
printf(" NULL,\n");
printf(" NULL\n");
printf("};\n");
printf("}\n");
file_put_contents($target, ob_get_clean());
} else {
ob_start();
printf("#ifndef _H_SYSTEM_CONSTANTS\n");
printf("#define _H_SYSTEM_CONSTANTS\n");
printf("// @"."generated by idl/class_map.php\n");
printf("namespace HPHP {\n");
printf("class StaticString;\n");
printf("class Variant;\n");
write_constants(true);
printf("}\n");
printf("#endif\n");
file_put_contents($target, ob_get_clean());
}
return true;
function functionClassMap($func, $cls = null) {
if (!array_key_exists('flags', $func)) {
var_dump($func);
exit(1);
}
$attribute = (($func['flags'] &
(IsProtected|IsPrivate|IsPublic|IsAbstract|IsStatic|IsFinal|
AllowIntercept|NoProfile|ContextSensitive|HipHopSpecific|
VariableArguments|RefVariableArguments|MixedVariableArguments|
HasDocComment|NeedsActRec|FunctionIsFoldable|NoInjection|
NoEffect|HasOptFunction)) |
IsSystem | IsNothing);
if ($attribute & RefVariableArguments) {
$attribute |= VariableArguments;
}
if ($attribute & MixedVariableArguments) {
$attribute |= RefVariableArguments | VariableArguments;
}
if ($cls === null) {
$attribute |= IsPublic;
} else if (!($attribute & (IsProtected|IsPrivate|IsPublic))) {
$attribute |= IsPublic;
}
if (isset($func['ref'])) $attribute |= IsReference;
printf(' (const char *)0x%04X, "%s", "", (const char*)0, '.
"(const char*)0,\n",
$attribute, $func['name'], "", 0, 0);
if (!empty($func['doc'])) {
printf(' "%s",'."\n", escape_cpp($func['doc']));
}
printf(" ");
printDataType($func['return']);
foreach ($func['args'] as $arg) {
$attr = IsNothing;
if (isset($arg['ref'])) $attr |= IsReference;
printf('(const char *)0x%04X, "%s", "", ',
$attr, $arg['name']);
printDataType($arg['type']);
if (array_key_exists('value', $arg)) {
printf('"%s", (const char *)%d, "%s", (const char *)%d, ',
escape_cpp($arg['defaultSerialized']),
strlen($arg['defaultSerialized']),
escape_cpp($arg['defaultText']),
strlen($arg['defaultText']));
} else {
printf('"", (const char *)0, "", (const char *)0, ');
}
print("NULL,\n ");
}
print("NULL,\n");
print(" NULL,\n");
print(" NULL,\n");
}
function classClassMap($cls) {
$attribute = (($cls['flags'] &
(IsAbstract|IsFinal|HasDocComment|NoDefaultSweep|
HipHopSpecific)) |
IsSystem | IsNothing);
printf(' (const char *)0x%04X, "%s", "%s", "", (const char *)0, ' .
"(const char *)0,\n",
$attribute,
$cls['name'], strtolower($cls['parent'])); # revert strtolower
if (!empty($cls['doc'])) {
printf(' "%s",'."\n", escape_cpp($cls['doc']));
}
printf(" ");
foreach ($cls['ifaces'] as $iface) {
printf('"%s", ', strtolower($iface));
}
printf("NULL,\n");
foreach ($cls['methods'] as $m) {
functionClassMap($m, $cls);
}
printf(" NULL,\n");
foreach ($cls['properties'] as $p) {
$att = $p['flags'] & (IsProtected|IsPrivate|IsPublic|IsStatic);
$att |= IsNothing;
if (!($att & (IsProtected|IsPrivate|IsPublic))) $att |= IsPublic;
printf(" (const char *)0x%04X, \"%s\",\n", $att, $p['name']);
printDataType($p['type']);
}
printf(" NULL,\n");
foreach ($cls['consts'] as $k) {
constantClassMap($k, $cls['name']);
}
printf(" NULL,\n");
// no attributes
printf(" NULL,\n");
}
function constantClassMap($constant, $cls = null) {
printf(' "%s", ', escape_cpp($constant['name']));
if (array_key_exists('value', $constant)) {
$v = serialize($constant['value']);
printf('(const char*)%d, "%s",'."\n",
strlen($v), escape_cpp($v));
} else {
switch ($constant['name']) {
case 'STDOUT':
case 'STDERR':
case 'STDIN':
printf("(const char *)&BuiltinFiles::Get%s, nullptr,\n",
$constant['name']);
return;
}
if ($cls !== null) {
printf('(const char*)&q_%s$$%s, ',
$cls, $constant['name']);
printDataType($constant['type'], 2);
} else {
printf("(const char *)&k_%s, ",
$constant['name']);
printDataType($constant['type'], 2);
}
printf("\n");
}
}
function printDataType($t, $off = 0) {
switch (typename($t)) {
case 'null':
case 'void': $s = 'KindOfNull'; $n = 8; break;
case 'bool': $s = 'KindOfBoolean'; $n = 9; break;
case 'int':
case 'int64_t':$s = 'KindOfInt64'; $n = 10; break;
case 'double': $s = 'KindOfDouble'; $n = 11; break;
case 'String': $s = 'KindOfString'; $n = 20; break;
case 'Array': $s = 'KindOfArray'; $n = 32; break;
case 'Object': $s = 'KindOfObject'; $n = 64; break;
default:
if (is_string($t)) {
$s = 'KindOfObject'; $n = 64;
break;
}
$s = 'KindOfUnknown: $t: ' . typename($t); $n = -1;
break;
}
printf('(const char *)0x%x /* %s */, ', ($n + $off) & 0xffffffff, $s);
}
function write_constants($extern) {
global $constants;
foreach ($constants as $constant) {
if (array_key_exists('value', $constant)) {
$v = $constant['value'];
if (is_bool($v)) {
$type = 'bool';
} else if (is_int($v)) {
$type = 'int64_t';
} else if (is_double($v)) {
$type = 'double';
} else if (is_string($v)) {
$type = 'StaticString';
} else if (is_null($v)) {
$type = 'Variant';
} else {
throw new Exception("bad value for constant '$constant'");
}
if ($extern) {
printf("extern const %s k_%s;\n",
$type, $constant['name']);
} else if (is_string($v)) {
printf("extern const StaticString k_%s(%s,%d);\n",
$constant['name'],
php_escape_val($v), strlen($v));
} else {
printf("const %s k_%s = %s;\n",
$type, $constant['name'], php_escape_val($v));
}
}
}
}
+4 -1
Ver Arquivo
@@ -545,7 +545,7 @@ ClassInfo::MethodInfo *ClassInfo::MethodInfo::getDeclared() {
ClassInfo::MethodInfo::MethodInfo(const char **&p) {
attribute = (Attribute)(int64_t)(*p++);
name = makeStaticString(*p++);
docComment = 0;
docComment = "";
if (attribute & ClassInfo::IsRedeclared) {
volatile_redec_offset = (int)(int64_t)(*p++);
while (*p) {
@@ -632,6 +632,8 @@ ClassInfoUnique::ClassInfoUnique(const char **&p) {
if (m_attribute & HasDocComment) {
m_docComment = *p++;
} else {
m_docComment = "";
}
while (*p) {
@@ -822,3 +824,4 @@ ClassInfo::MethodInfo::~MethodInfo() {
///////////////////////////////////////////////////////////////////////////////
}
+74 -10
Ver Arquivo
@@ -17,6 +17,7 @@
#include "hphp/runtime/ext/ext_reflection.h"
#include "hphp/runtime/ext/ext_closure.h"
#include "hphp/runtime/ext/ext_misc.h"
#include "hphp/runtime/base/externals.h"
#include "hphp/runtime/base/class_info.h"
#include "hphp/runtime/base/runtime_option.h"
@@ -227,6 +228,54 @@ static void set_static_prop_info(Array &ret, const Class::SProp* prop) {
}
}
static bool resolveConstant(const char *p, int64_t len, Variant &cns) {
// ltrim
while (len && (*p == ' ')) {
p++;
len--;
}
// rtrim
while (len && (p[len-1] == ' ')) {
len--;
}
String cname(p, len, CopyString);
if (!f_defined(cname)) {
cns = uninit_null();
return false;
}
cns = f_constant(cname);
return true;
}
static bool resolveDefaultParameterConstant(const char *value,
int64_t valueLen,
Variant &cns) {
const char *p = value;
const char *e = value + valueLen;
const char *s;
bool isLval = false;
int64_t lval = 0;
while ((s = strchr(p, '|'))) {
isLval = true;
if (!resolveConstant(p, s - p, cns)) {
return false;
}
lval |= cns.toInt64();
p = s + 1;
}
if (!resolveConstant(p, e - p, cns)) {
return false;
}
if (isLval) {
cns = cns.toInt64() | lval;
}
return true;
}
static void set_function_info(Array &ret, const ClassInfo::MethodInfo *info,
const String *classname) {
// return type
@@ -263,23 +312,38 @@ static void set_function_info(Array &ret, const ClassInfo::MethodInfo *info,
param.set(s_class, VarNR(*classname));
}
const char *defText = p->valueText;
if (defText == nullptr) defText = "";
int64_t defTextLen = p->valueTextLen;
if (defText == nullptr) {
defText = "";
defTextLen = 0;
}
if (!p->type || !*p->type || !strcasecmp("null", defText)) {
param.set(s_nullable, true_varNR);
}
if (p->value && *p->value) {
if (*p->value == '\x01') {
const char *sep = strchr(defText, ':');
Object v(SystemLib::AllocStdClassObject());
if (sep && sep[1] == ':') {
String cls = String(defText, sep - defText, CopyString);
String con = String(sep + 2, CopyString);
v.o_set(s_class, cls);
v.o_set(s_name, con);
Variant v;
if ((defTextLen > 2) &&
!strcmp(defText + defTextLen - 2, "()")) {
const char *sep = strchr(defText, ':');
v = SystemLib::AllocStdClassObject();
if (sep && sep[1] == ':') {
String cls = String(defText, sep - defText, CopyString);
String con = String(sep + 2, CopyString);
v.o_set(s_class, cls);
v.o_set(s_name, con);
} else {
v.o_set(s_name, String(defText, defTextLen, CopyString));
}
param.set(s_default, v);
} else if (resolveDefaultParameterConstant(defText, defTextLen, v)) {
param.set(s_default, v);
} else {
v.o_set(s_msg, String("unable to eval ") + defText);
v = SystemLib::AllocStdClassObject();
v.o_set(s_msg, String("Unknown unserializable default value: ")
+ defText);
param.set(s_default, v);
}
param.set(s_default, v);
} else {
param.set(s_default, unserialize_from_string(p->value));
}
+3
Ver Arquivo
@@ -0,0 +1,3 @@
Makefile
class_map.cpp
constants.h
+21
Ver Arquivo
@@ -0,0 +1,21 @@
auto_sources(IDL_SRCS "*.idl.json" "RECURSE" "${HPHP_HOME}/hphp/idl")
string(REPLACE ";" " " IDL_SRCS_STR "${IDL_SRCS}")
set(CONSTDEF "${CMAKE_CURRENT_SOURCE_DIR}/globals/constdef.json")
add_custom_command(OUTPUT "class_map.cpp" "constants.h"
DEPENDS ${CONSTDEF} ${IDL_SRCS} gen-class-map
COMMAND "${HPHP_HOME}/hphp/tools/gen-ext-hhvm/gen-class-map.sh"
ARGS "${CMAKE_CURRENT_SOURCE_DIR}/class_map.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/constants.h"
${CONSTDEF} ${IDL_SRCS_STR}
COMMENT "Generating class_map.cpp and constants.h")
set(CXX_SOURCES "class_map.cpp" "lib/systemlib.cpp")
add_library(hphp_system STATIC ${CXX_SOURCES})
# Needed to force system/constants.h to generate prior to files which need it
add_dependencies(hphp_runtime_static hphp_system)
add_dependencies(hphp_analysis hphp_system)
-12
Ver Arquivo
@@ -1,12 +0,0 @@
PROJECT_ROOT = ../..
include $(PROJECT_ROOT)/src/dirs.mk
PHP_FILES = $(wildcard classes/*.php) $(wildcard globals/*.php)
PHP := $(wildcard /usr/local/hphpi/bin/hhvm)
PHP := $(if $(PHP),$(PHP) -v Preg.ErrorLog=false,php)
all:
$(HPHP) --opts=none -t cpp -f sys --input-dir . -i $(PHP_FILES) -o gen 1>/dev/null
$(V)$(PHP) $(PROJECT_ROOT)/bin/license.php
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+22
Ver Arquivo
@@ -1,6 +1,28 @@
{
"preamble": "",
"consts": [
{
"name": "true",
"value": true
},
{
"name": "false",
"value": false
},
{
"name": "null",
"value": null
},
{
"name": "SID",
"type": "String",
"desc": "Dynamic constant: session_id()"
},
{
"name": "PHP_SAPI",
"type": "String",
"desc": "Dynamic constant: php_sapi_name()"
},
{
"name": "ABDAY_1",
"value": 131072
+1 -1
Ver Arquivo
@@ -12,5 +12,5 @@ list(APPEND CXX_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/../hhvm/process_init.cpp")
list(APPEND CXX_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/../hhvm/global_variables.cpp")
add_executable(test ${CXX_SOURCES})
target_link_libraries(test hphp_analysis hphp_runtime_static ext_hhvm_static
target_link_libraries(test hphp_analysis hphp_runtime_static ext_hhvm_static hphp_system
-Wl,-uregister_libevent_server)
+6 -7
Ver Arquivo
@@ -15,15 +15,14 @@ function info1($c) {
$c->processCmd('@', null);
$o = $c->processCmd('info', array('array_key_exists'));
VS(trim($o['text']), '/**
* ( excerpt from http://php.net/manual/en/function.array-key-exists.php )
* ( excerpt from http://php.net/manual/en/function.array_key_exists.php )
* array_key_exists() returns TRUE if the given key is set in the array.'.
' key can be any value possible for an array index.
*
* array_key_exists() returns TRUE if the given key is set in the array.
* key can be any value possible for an array index.
* @key mixed Value to check.
* @search mixed An array with keys to check.
*
* @key mixed Value to check.
* @search mixed An array with keys to check.
*
* @return bool Returns TRUE on success or FALSE on failure.
* @return bool Returns TRUE on success or FALSE on failure.
*/
function array_key_exists($key, $search);');
$o = $c->processCmd('info', array('stdClass'));
@@ -0,0 +1,8 @@
<?php
echo "--SQLite3::open--\n";
$ro = new ReflectionClass('SQLite3');
$mo = $ro->getMethod('open');
$params = $mo->getParameters();
var_dump($params[1]->getDefaultValue());
var_dump(str_replace(' ', '', $params[1]->getDefaultValueText()));
@@ -0,0 +1,3 @@
--SQLite3::open--
int(6)
string(42) "SQLITE3_OPEN_READWRITE|SQLITE3_OPEN_CREATE"
+1
Ver Arquivo
@@ -1,3 +1,4 @@
Makefile
gen-ext-hhvm
gen-infotabs
gen-class-map
+3
Ver Arquivo
@@ -3,3 +3,6 @@ target_link_libraries(gen-ext-hhvm folly ${LIBGLOG_LIBRARY} double-conversion ${
add_executable(gen-infotabs "gen-infotabs.cpp" "idl.cpp")
target_link_libraries(gen-infotabs folly ${LIBGLOG_LIBRARY} double-conversion ${LIBPTHREAD_LIBRARIES} ${DL_LIB})
add_executable(gen-class-map "gen-class-map.cpp" "idl.cpp")
target_link_libraries(gen-class-map folly ${LIBGLOG_LIBRARY} double-conversion ${LIBPTHREAD_LIBRARIES} ${DL_LIB})
+395
Ver Arquivo
@@ -0,0 +1,395 @@
/*
+----------------------------------------------------------------------+
| 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. |
+----------------------------------------------------------------------+
*/
#include <algorithm>
#include <iostream>
#include <fstream>
#include <unordered_map>
#include <unordered_set>
#include "folly/FBString.h"
#include "folly/FBVector.h"
#include "hphp/tools/gen-ext-hhvm/idl.h"
using folly::fbstring;
using folly::fbvector;
using namespace HPHP::IDL;
using namespace HPHP;
#define VISIBILITY_MASK (IsPublic|IsProtected|IsPrivate)
/////////////////////////////////////////////////////////////////////////////
// Helpers
static inline fbstring castLong(unsigned long lval, bool hex = false) {
if (hex) {
char buffer[10];
snprintf(buffer, sizeof(buffer), "%lx", lval & 0xffffffff);
return folly::to<fbstring>("(const char *)0x", buffer);
}
return folly::to<fbstring>("(const char*)", lval);
}
/////////////////////////////////////////////////////////////////////////////
// Generated doc comments
static fbstring formatDocComment(const fbstring& comment) {
const char *p = comment.c_str();
const char *s;
const char *e = p + comment.size();
fbstring ret("/**\n");
while ((s = strchr(p, '\n'))) {
ret += " *";
if ((s - p) > 1) {
ret += " " + fbstring(p, (s - p));
}
ret += "\n";
p = s + 1;
}
if (p < e) {
ret += " * " + fbstring(p) + "\n";
}
return ret + " */";
}
static fbstring genDocCommentPreamble(const fbstring& name,
const fbstring& desc,
long flags,
const fbstring& classname) {
fbstring ret;
if (flags & HipHopSpecific) {
ret = "( HipHop specific )";
} else {
ret = "( excerpt from http://php.net/manual/en/";
if (classname.size()) {
ret += classname + ".";
} else {
ret += "function.";
}
ret += name + ".php )";
}
if (desc.size()) {
ret += "\n" + desc;
}
return ret + "\n\n";
}
static fbstring genDocComment(const PhpFunc& func,
const fbstring& classname) {
fbstring ret(genDocCommentPreamble(func.name(), func.getDesc(),
func.flags(), classname));
for (auto &param : func.params()) {
ret += "@" + param.name() + " " + param.getPhpType() + " ";
if (param.isRef()) {
ret += "(output) ";
}
ret += param.getDesc() + "\n";
}
if (func.numParams() > 0) {
ret += "\n";
}
auto rko = func.returnKindOf();
if ((rko != KindOfNull) && (rko != KindOfInvalid)) {
ret += "@return " + func.returnPhpType() + " ";
if (func.isReturnRef()) {
ret += "(output) ";
}
ret += func.returnDesc() + "\n";
}
return formatDocComment(ret);
}
static fbstring genDocComment(const PhpClass& cls) {
return formatDocComment(
genDocCommentPreamble(cls.name(), cls.getDesc(), cls.flags(), "")
);
}
/////////////////////////////////////////////////////////////////////////////
// System constants
static void declareConstants(std::ostream &out,
const fbvector<PhpConst>& consts,
bool extrn) {
for (auto c : consts) {
if (!c.hasValue()) {
continue;
}
if (extrn) {
out << "extern const " << c.getCppType() << " " << c.varname() << ";\n";
} else if (c.kindOf() == KindOfString) {
fbstring val = c.value();
out << "extern const StaticString " << c.varname()
<< "(\"" << escapeCpp(val) << "\"," << val.size() << ");\n";
} else {
out << "const " << c.getCppType() << " " << c.varname()
<< " = " << escapeCpp(c.value()) << ";\n";
}
}
}
static int outputConstants(const char *outputfn,
const fbvector<PhpConst>& consts) {
std::ofstream out(outputfn);
out << "// @" "generated by gen-class-map.cpp\n"
<< "#ifndef _H_SYSTEM_CONSTANTS\n"
<< "#define _H_SYSTEM_CONSTANTS\n"
<< "namespace HPHP {\n"
<< "class StaticString;\n"
<< "class Variant;\n";
declareConstants(out, consts, true);
out << "} // namespace HPHP\n"
<< "#endif // _H_SYSTEM_CONSTANTS\n";
return 0;
}
/////////////////////////////////////////////////////////////////////////////
// Class Map
#define FUNC_FLAG_MASK (IsProtected|IsPrivate|IsPublic|\
IsAbstract|IsStatic|IsFinal|HasDocComment|\
AllowIntercept|NoProfile|ContextSensitive|\
HipHopSpecific|VariableArguments|\
RefVariableArguments|MixedVariableArguments|\
NeedsActRec|FunctionIsFoldable|\
NoInjection|NoEffect|HasOptFunction)
static void writeFunction(std::ostream& out, const PhpFunc& func) {
auto flags = (func.flags() & FUNC_FLAG_MASK) | IsSystem | IsNothing;
if (flags & RefVariableArguments) {
flags |= VariableArguments;
}
if (flags & MixedVariableArguments) {
flags |= RefVariableArguments | VariableArguments;
}
if (!func.isMethod() || !(flags & VISIBILITY_MASK)) {
flags |= IsPublic;
}
if (func.isReturnRef()) {
flags |= IsReference;
}
out << " " << castLong(flags, true) << ", \"" << func.name() << "\", "
<< "\"\", "
<< castLong(0) << ", "
<< castLong(0) << ",\n";
if (flags & HasDocComment) {
out << " \""
<< escapeCpp(genDocComment(func, func.className()))
<< "\",\n";
}
DataType rko = func.returnKindOf();
if (rko == KindOfAny) {
// ClassInfo::MethodInfo expects this for Any/Variant
// TODO: Fix that broken assumption
rko = KindOfInvalid;
}
out << " " << castLong(rko, true) << ",\n";
for (auto &p : func.params()) {
long attr = IsNothing;
DataType ko = p.kindOf();
if (p.isRef()) {
// We don't declare param type as KindOfRef
// as then the caller will try to cast it as such
attr |= IsReference;
ko = KindOfAny;
}
if (ko == KindOfAny) {
// TODO: See above
ko = KindOfInvalid;
}
out << " "
<< castLong(attr, true) << ", "
<< "\"" << escapeCpp(p.name()) << "\", \"\", "
<< castLong(ko, true) << ",\n";
auto ser = p.getDefaultSerialized();
auto val = p.getDefaultPhp();
out << " "
<< "\"" << escapeCpp(ser) << "\", " << castLong(ser.size()) << ", "
<< "\"" << escapeCpp(val) << "\", " << castLong(val.size()) << ", "
<< "NULL,\n";
}
out << " NULL,\n"
<< " NULL,\n"
<< " NULL,\n";
}
static void writeConstant(std::ostream& out, const PhpConst& cns) {
auto name = cns.name();
out << " \"" << escapeCpp(name) << "\", ";
if (cns.hasValue()) {
auto ser = cns.serialize();
out << castLong(ser.size())
<< ", \"" << escapeCpp(ser) << "\",\n";
return;
}
if (cns.isSystem()) {
// Special "magic" constants
if ((name == "SID") || (name == "PHP_SAPI")) {
out << "(const char *)((offsetof(GlobalVariables, k_" << name << ") - "
<< "offsetof(GlobalVariables, stgv_Variant)) / sizeof(Variant)), "
<< castLong(1) << ",\n";
return;
}
if ((name == "STDIN") || (name == "STDOUT") || (name == "STDERR")) {
out << "(const char *)&BuiltinFiles::Get" << name << ", NULL,\n";
return;
}
}
out << "(const char *)&" << cns.varname() << ", "
<< castLong((int)cns.kindOf() + 2) << ",\n";
}
#define CLASS_FLAG_MASK (IsAbstract|IsFinal|NoDefaultSweep|\
HipHopSpecific|HasDocComment)
#define PROP_FLAG_MASK (IsProtected|IsPrivate|IsPublic|IsStatic)
static void writeClass(std::ostream& out, const PhpClass& cls) {
auto flags = (cls.flags() & CLASS_FLAG_MASK) | IsSystem | IsNothing;
out << " " << castLong(flags, true) << ", "
<< "\"" << escapeCpp(cls.name()) << "\", "
<< "\"" << escapeCpp(strtolower(cls.parent())) << "\", "
<< "\"\", "
<< castLong(0) << ", "
<< castLong(0) << ",\n";
if (flags & HasDocComment) {
out << " \"" << escapeCpp(genDocComment(cls)) << "\",\n";
}
out << " ";
for (auto &iface : cls.ifaces()) {
out << "\"" << escapeCpp(strtolower(iface)) << "\", ";
}
out << "NULL,\n";
for (auto &method : cls.methods()) {
writeFunction(out, method);
}
out << " NULL,\n";
for (auto &prop : cls.properties()) {
auto propflag = (prop.flags() & PROP_FLAG_MASK) | IsNothing;
if (!(propflag & VISIBILITY_MASK)) {
propflag |= IsPublic;
}
out << " " << castLong(propflag, true) << ", "
<< "\"" << escapeCpp(prop.name()) << "\", "
<< castLong((int)prop.kindOf(), true) << ",\n";
}
out << " NULL,\n";
for (auto &cns : cls.constants()) {
writeConstant(out, cns);
}
out << " NULL,\n";
out << " NULL,\n"; // no attributes
}
static int outputClassMap(const char *outputfn, const char *classmap_name,
const fbvector<PhpClass>& classes,
const fbvector<PhpFunc>& funcs,
const fbvector<PhpConst>& consts) {
std::ofstream out(outputfn);
out << "// @" "generated by gen-class-map.cpp\n"
<< "#include \"hphp/runtime/base/base_includes.h\"\n"
<< "#include \"hphp/runtime/ext/ext.h\"\n"
<< "namespace HPHP {\n";
declareConstants(out, consts, false);
out << "const char *" << classmap_name << "[] = {\n"
<< " (const char *)ClassInfo::IsSystem, NULL, "
<< "\"\", \"\", NULL, NULL, NULL,\n";
for (auto &f : funcs) {
writeFunction(out, f);
}
out << " NULL,\n" // End of functions
<< " NULL,\n"; // End of system "properties"
for (auto &c : consts) {
writeConstant(out, c);
}
out << " NULL,\n" // End of constants
<< " NULL,\n"; // End of system "attributes"
for (auto &c : classes) {
writeClass(out, c);
}
out << " NULL,\n" // End of classes
<< " NULL,\n" // End of classmap
<< "};\n"
<< "} // namespace HPHP\n";
return 0;
}
/////////////////////////////////////////////////////////////////////////////
int main(int argc, const char* argv[]) {
if (argc < 4) {
std::cout << "Usage: " << argv[0]
<< " [constants | classmap(:g_class_map)] "
<< "<outputfile> <*.idl.json>...\n";
return 0;
}
fbvector<PhpFunc> funcs;
fbvector<PhpClass> classes;
fbvector<PhpConst> consts;
for (auto i = 3; i < argc; ++i) {
try {
parseIDL(argv[i], funcs, classes, consts);
} catch (const std::exception& exc) {
std::cerr << argv[i] << ": " << exc.what() << "\n";
return 1;
}
}
// System-wide class map e.g.: hphp/system/class_map.cpp
if (!strcmp(argv[1], "classmap")) {
return outputClassMap(argv[2], "g_class_map",
classes, funcs, consts);
}
// Extension-local class map
if (!strncmp(argv[1], "classmap:", sizeof("classmap:") - 1)) {
return outputClassMap(argv[2], argv[1] + (sizeof("classmap:") - 1),
classes, funcs, consts);
}
// Externs for system constants from constdef.json
if (!strcmp(argv[1], "constants")) {
return outputConstants(argv[2], consts);
}
return 0;
}
+18
Ver Arquivo
@@ -0,0 +1,18 @@
#!/bin/sh
# $1 class_map cpp file to build
# $2 constants.h file to build
# $3 globals/constdef.json
# $4- Additional IDL files to parse for class_map
CLASSMAP=$1
CONSTANTS=$2
CONSTDEF=$3
shift; shift; shift;
$HPHP_HOME/hphp/tools/gen-ext-hhvm/gen-class-map \
constants $CONSTANTS $CONSTDEF
$HPHP_HOME/hphp/tools/gen-ext-hhvm/gen-class-map \
classmap $CLASSMAP $CONSTDEF $@
+404 -9
Ver Arquivo
@@ -52,6 +52,7 @@ static const std::unordered_map<fbstring, DataType> g_kindOfMap =
static const std::unordered_map<int, fbstring> g_typeMap =
{
{(int)KindOfInvalid, "void"},
{(int)KindOfNull, "HPHP::Variant"},
{(int)KindOfBoolean, "bool"},
{(int)KindOfInt64, "long"},
{(int)KindOfDouble, "double"},
@@ -61,6 +62,19 @@ static const std::unordered_map<int, fbstring> g_typeMap =
{(int)KindOfAny, "HPHP::Variant"},
};
static const std::unordered_map<int, fbstring> g_phpTypeMap =
{
{(int)KindOfInvalid, "void"},
{(int)KindOfNull, "void"},
{(int)KindOfBoolean, "bool"},
{(int)KindOfInt64, "long"},
{(int)KindOfDouble, "double"},
{(int)KindOfString, "String"},
{(int)KindOfArray, "Array"},
{(int)KindOfObject, "Object"},
{(int)KindOfAny, "mixed"},
};
static const std::unordered_map<fbstring, FuncFlags> g_flagsMap =
{
{"IsAbstract", IsAbstract},
@@ -99,9 +113,11 @@ bool isKindOfIndirect(DataType kindof) {
return (kindof != KindOfBoolean) &&
(kindof != KindOfInt64) &&
(kindof != KindOfDouble) &&
(kindof != KindOfInvalid);
(kindof != KindOfInvalid) &&
(kindof != KindOfNull);
}
// Parse type from a descriptive string, e.g. "int", "bool", etc...
static DataType kindOfFromDynamic(const folly::dynamic& t) {
if (!t.isString()) {
return KindOfInvalid;
@@ -114,6 +130,40 @@ static DataType kindOfFromDynamic(const folly::dynamic& t) {
return it->second;
}
// Infer type from an actual value, e.g. 123, "foo", null, true, etc...
static DataType kindOfFromValue(const folly::dynamic& v) {
if (v.isNull()) {
return KindOfNull;
}
if (v.isBool()) {
return KindOfBoolean;
}
if (v.isInt()) {
return KindOfInt64;
}
if (v.isDouble()) {
return KindOfDouble;
}
if (v.isString()) {
return KindOfString;
}
if (v.isArray()) {
return KindOfArray;
}
if (v.isObject()) {
return KindOfObject;
}
return KindOfInvalid;
}
static fbstring phpTypeFromDataType(DataType dt) {
auto it = g_phpTypeMap.find((int)dt);
if (it == g_phpTypeMap.end()) {
return "mixed";
}
return it->second;
}
static fbstring typeString(const folly::dynamic& typeNode, bool isReturnType) {
if (typeNode == "Int32") {
return "int";
@@ -150,13 +200,289 @@ static unsigned long parseFlags(const folly::dynamic &flags) {
return ret;
}
static const std::unordered_map<fbstring,fbstring> g_serializedDefaults = {
{"true", "b:1;"},
{"false", "b:0;"},
{"null", "N;"},
{"empty_array", "a:0:{}"},
{"null_string", "N;"},
{"null_array", "N;"},
{"null_object", "N;"},
{"null_variant", "N;"},
{"INT_MAX", "i:2147483647;"}, // (1 << 31) - 1
};
static const std::unordered_map<fbstring,fbstring> g_phpDefaults = {
{"true", "true"},
{"false", "false"},
{"null", "null"},
{"empty_array", "array()"},
{"null_string", "null"},
{"null_array", "null"},
{"null_object", "null"},
{"null_variant", "null"},
{"INT_MAX", "null"},
};
/**
* From idl/base.php:get_serialized_default()
*/
fbstring PhpParam::getDefaultSerialized() const {
auto valIt = m_param.find("value");
if (valIt == m_param.items().end()) {
return ""; // No default
}
auto dval = valIt->second;
if (!dval.isString()) {
throw std::logic_error(
folly::format("Parameter '{0}' default value is non-string",
m_name).str()
);
}
auto val = dval.asString();
if (!val.size()) {
throw std::logic_error(
folly::format("Parameter '{0}' default value malformed (empty string), "
"specify \"\" as default value for actual empty string",
m_name).str()
);
}
// Function calls "foo()" or "foo::bar()" to C/C++ functions/static methods,
// a constant, or a bitmask of constants
//
// Used by ext_reflection to resolve the value at runtime or
// represent the function/method call.
if ((val.size() > 2) &&
(!strncmp(val.c_str(), "k_", 2) ||
!strncmp(val.c_str(), "q_", 2) ||
!strcmp(val.c_str() + val.size() - 2, "()"))) {
return "\x01";
}
// Fixed substitutions
auto it = g_serializedDefaults.find(val);
if (it != g_serializedDefaults.end()) {
return it->second;
}
if (val == "RAND_MAX") {
return folly::to<fbstring>("i:", RAND_MAX, ";");
}
// Quoted string: "foo"
if ((val.size() >= 2) && (val[0] == '"') && (val[val.size()-1] == '"')) {
return phpSerialize(val.substr(1, val.size() - 2));
}
// Integers and Floats
if (strchr(val.c_str(), '.')) {
// Decimal float?
char *e = nullptr;
double dval = strtod(val.c_str(), &e);
if (e && !*e) {
return folly::to<fbstring>("d:", dval, ";");
}
}
if (val[0] == '0') {
if ((val.size() > 1) && (val[1] == 'x')) {
// Hex?
char *e = nullptr;
long lval = strtol(val.c_str() + 2, &e, 16);
if (e && !*e) {
return folly::to<fbstring>("i:", lval, ";");
}
} else {
// Octal?
char *e = nullptr;
long lval = strtol(val.c_str() + 1, &e, 8);
if (e && !*e) {
return folly::to<fbstring>("i:", lval, ";");
}
}
}
// Decimal?
char *e = nullptr;
long lval = strtol(val.c_str(), &e, 10);
if (e && !*e) {
return folly::to<fbstring>("i:", lval, ";");
}
throw std::logic_error(
folly::format("'{0}' is not a valid default arg value", val).str()
);
}
static fbstring transformConstants(const fbstring val) {
fbstring ret = val;
int i = 0;
int len = ret.size();
while (i < len) {
while ((i < len) && (ret[i] == ' ')) i++;
if ((len - i) < 2) break;
if ((ret[i+1] == '_') &&
((ret[i] == 'k') || (ret[i] == 'q'))) {
ret[i] = ret[i+1] = ' ';
}
while ((i < len) && (ret[i] != '|')) {
if (ret[i] == '$') {
ret[i] = ':';
}
i++;
}
i++;
}
return ret;
}
fbstring PhpParam::getDefaultPhp() const {
fbstring val = getDefault();
if (!val.size()) {
return "";
}
auto it = g_phpDefaults.find(val);
if (it != g_phpDefaults.end()) {
return it->second;
}
if (val == "RAND_MAX") {
return folly::to<fbstring>(RAND_MAX);
}
if ((val.size() > 2) && (val[1] == '_') &&
((val[0] == 'k') || (val[0] == 'q'))) {
return transformConstants(val);
}
return val;
}
fbstring phpSerialize(const folly::dynamic& d) {
if (d.isNull()) {
return "N;";
}
if (d.isBool()) {
return d.asBool() ? "b:1;" : "b:0;";
}
if (d.isInt()) {
return "i:" + d.asString() + ";";
}
if (d.isDouble()) {
return "d:" + d.asString() + ";";
}
if (d.isString()) {
auto str = d.asString();
return folly::to<fbstring>("s:", str.size(), ":\"", str, "\";");
}
if (d.isArray()) {
fbstring ret = folly::to<fbstring>("a:", d.size(), ":{");
int i = 0;
for (auto &v : d) {
ret += folly::to<fbstring>("i:", i, ";", phpSerialize(v));
}
return ret + "};";
}
if (d.isObject()) {
fbstring ret = folly::to<fbstring>("a:", d.size(), ":{");
int nextindex = 0;
for (auto &k : d.keys()) {
if (k.isNull()) {
ret += "i:0;";
if (nextindex <= 0) {
nextindex = 1;
}
} else if (k.isInt() || k.isDouble()) {
int i = k.asInt();
ret += folly::to<fbstring>("i:", i, ";");
if (nextindex <= i) {
nextindex = i + 1;
}
} else if (k.isString()) {
ret += folly::to<fbstring>("s:", k.size(), ":\"",
escapeCpp(k.asString()), "\";");
} else {
/* Should never be reached, but cover it to be safe */
ret += folly::to<fbstring>("i:", nextindex++, ";");
}
ret += phpSerialize(d[k]);
}
return ret + "};";
}
throw std::logic_error("Unhandled dynamic type in php serialization");
return "N;";
}
static fbstring getFollyDynamicDefaultString(const folly::dynamic& d,
const fbstring& key,
const fbstring& def) {
auto it = d.find(key);
if (it == d.items().end()) {
return def;
}
auto val = it->second;
if (val.isNull()) {
return def;
}
return val.asString();
}
/////////////////////////////////////////////////////////////////////////////
// PhpConst
bool PhpConst::parseType(const folly::dynamic& cns) {
auto it = cns.find("type");
if (it != cns.items().end()) {
m_kindOf = kindOfFromDynamic(it->second);
m_cppType = typeString(it->second, false);
return true;
}
return false;
}
bool PhpConst::inferType(const folly::dynamic& cns) {
auto it = cns.find("value");
if (it != cns.items().end()) {
m_kindOf = kindOfFromValue(it->second);
auto typeIt = g_typeMap.find((int)m_kindOf);
if (typeIt != g_typeMap.end()) {
m_cppType = typeIt->second;
return true;
}
}
return false;
}
PhpConst::PhpConst(const folly::dynamic& cns,
fbstring cls /* = "" */) :
m_constant(cns),
m_name(cns["name"].asString()),
m_className(cls) {
if (!parseType(cns) && !inferType(cns)) {
// Constant has neither explicit type nor implicit type from 'value'
assert(false);
m_kindOf = KindOfInvalid;
m_cppType = "void";
}
// Override typeString()'s selection for string values
if (m_kindOf == KindOfString) {
m_cppType = "HPHP::StaticString";
}
}
/////////////////////////////////////////////////////////////////////////////
// PhpParam
PhpParam::PhpParam(const folly::dynamic& param,
bool isMagicMethod /*= false */) :
m_name(param["name"].asString()),
m_param(param) {
m_param(param),
m_desc(getFollyDynamicDefaultString(param, "desc", "")) {
if (isMagicMethod) {
m_kindOf = KindOfAny;
m_cppType = "HPHP::Variant";
@@ -170,6 +496,8 @@ PhpParam::PhpParam(const folly::dynamic& param,
m_kindOf = kindOfFromDynamic(param["type"]);
m_cppType = typeString(param["type"], false);
}
m_phpType = phpTypeFromDataType(m_kindOf);
}
bool PhpParam::defValueNeedsVariable() const {
@@ -208,13 +536,28 @@ PhpFunc::PhpFunc(const folly::dynamic& d,
m_name(d["name"].asString()),
m_className(className),
m_func(d),
m_desc(getFollyDynamicDefaultString(d, "desc", "")),
m_returnRef(d.getDefault("ref", "false") == "true"),
m_returnKindOf(m_returnRef ? KindOfRef :
kindOfFromDynamic(d["return"]["type"])),
m_returnCppType(typeString(d["return"]["type"], true)),
m_returnKindOf(KindOfNull),
m_returnCppType("void"),
m_returnPhpType("void"),
m_minNumParams(0),
m_numTypeChecks(0) {
// Better at least have a name
auto returnIt = d.find("return");
if (returnIt != d.items().end()) {
auto retNode = returnIt->second;
auto typeIt = retNode.find("type");
if (typeIt != retNode.items().end()) {
auto type = typeIt->second;
if ((type.isString()) && (type != "void") && (type != "null")) {
m_returnKindOf = m_returnRef ? KindOfRef : kindOfFromDynamic(type);
m_returnCppType = typeString(type, true);
m_returnPhpType = phpTypeFromDataType(m_returnKindOf);
}
}
m_returnDesc = getFollyDynamicDefaultString(retNode, "desc", "");
}
auto args = d.find("args");
if (args == d.items().end() || !args->second.isArray()) {
throw std::logic_error(
@@ -289,24 +632,65 @@ fbstring PhpFunc::getCppSig() const {
return out.str();
}
/////////////////////////////////////////////////////////////////////////////
// PhpProp
PhpProp::PhpProp(const folly::dynamic& d, fbstring cls) :
m_name(d["name"].asString()),
m_className(cls),
m_prop(d),
m_flags(parseFlags(m_prop["flags"])),
m_kindOf(kindOfFromDynamic(m_prop["type"])) {
}
/////////////////////////////////////////////////////////////////////////////
// PhpClass
PhpClass::PhpClass(const folly::dynamic &c) :
m_class(c),
m_name(c["name"].asString()) {
m_name(c["name"].asString()),
m_flags(parseFlags(m_class["flags"])),
m_desc(getFollyDynamicDefaultString(c, "desc", "")) {
auto ifacesIt = m_class.find("ifaces");
if (ifacesIt != m_class.items().end()) {
auto ifaces = ifacesIt->second;
if (!ifaces.isArray()) {
throw std::logic_error(
folly::format("Class {0}.ifaces field must be an array", m_name).str()
);
}
for (auto &interface : ifaces) {
m_ifaces.push_back(interface.asString());
}
}
for (auto const& f : c["funcs"]) {
PhpFunc func(f, m_name);
m_methods.push_back(func);
}
m_flags = parseFlags(m_class["flags"]);
if (c.find("consts") != c.items().end()) {
for (auto const& cns : c["consts"]) {
PhpConst cons(cns, m_name);
m_constants.push_back(cons);
}
}
if (c.find("properties") != c.items().end()) {
for (auto const& prp : c["properties"]) {
PhpProp prop(prp, m_name);
m_properties.push_back(prop);
}
}
}
/////////////////////////////////////////////////////////////////////////////
void parseIDL(const char* idlFilePath,
fbvector<PhpFunc>& funcVec,
fbvector<PhpClass>& classVec) {
fbvector<PhpClass>& classVec,
fbvector<PhpConst>& constVec) {
std::ostringstream jsonString;
std::ifstream infile(idlFilePath);
infile >> jsonString.rdbuf();
@@ -321,6 +705,17 @@ void parseIDL(const char* idlFilePath,
PhpClass klass(c);
classVec.push_back(klass);
}
for (auto const& c : parsed["consts"]) {
PhpConst cns(c);
constVec.push_back(cns);
}
}
void parseIDL(const char* idlFilePath,
fbvector<PhpFunc>& funcVec,
fbvector<PhpClass>& classVec) {
fbvector<PhpConst> consts; // dummy
parseIDL(idlFilePath, funcVec, classVec, consts);
}
/////////////////////////////////////////////////////////////////////////////
+146 -2
Ver Arquivo
@@ -86,11 +86,84 @@ static inline fbstring kindOfString(DataType t) {
}
}
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);
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);
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;
@@ -103,6 +176,7 @@ class PhpParam {
return ret;
}
DataType kindOf() const { return m_kindOf; }
fbstring getPhpType() const { return m_phpType; }
bool isRef() const { return m_param.getDefault("ref", false).asBool(); }
@@ -112,6 +186,8 @@ class PhpParam {
fbstring getDefault() const {
return hasDefault() ? m_param["value"].asString() : "";
}
fbstring getDefaultSerialized() const;
fbstring getDefaultPhp() const;
bool isCheckedType() const {
return !isRef() && (kindOf() != KindOfAny);
@@ -123,8 +199,10 @@ class PhpParam {
private:
fbstring m_name;
folly::dynamic m_param;
fbstring m_desc;
DataType m_kindOf;
fbstring m_cppType;
fbstring m_phpType;
};
class PhpFunc {
@@ -133,6 +211,7 @@ class PhpFunc {
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();
@@ -169,6 +248,8 @@ class PhpFunc {
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()); }
@@ -176,6 +257,7 @@ class PhpFunc {
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; }
@@ -184,16 +266,27 @@ class PhpFunc {
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;
@@ -202,30 +295,81 @@ private:
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;
void initFlagsProperty();
fbstring m_desc;
};
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);
/////////////////////////////////////////////////////////////////////////////
}} // namespace HPHP::IDL
#endif
-8
Ver Arquivo
@@ -27,7 +27,6 @@ HPHP_TOOLS=$HPHP_HOME/hphp/tools/
if [ "$1" = "help" ]; then
echo "$0 systemlib - Build bin/systemlib.php"
echo "$0 constants - Build hphp/system/constants.h"
echo "$0 class_map - Build hphp/system/class_map.cpp"
echo "$0 lexer - Regenerate the lexer"
echo "$0 parser - Regenerate the parser"
echo "$0 license - Add license headers to all files"
@@ -50,13 +49,6 @@ if [ "$1" = "constants" -o "$1" = "all" ]; then
$HHVM hphp/idl/class_map.php hphp/system/constants.h hphp/system/globals/constdef.json
fi
if [ "$1" = "class_map" -o "$1" = "all" ]; then
cd $HPHP_HOME
[ $VERBOSE -eq 1 ] && echo "Generating hphp/system/class_map.h"
$HHVM hphp/idl/class_map.php hphp/system/class_map.cpp hphp/system/globals/constdef.json \
`find hphp/idl -name '*.idl.json'`
fi
if [ "$1" = "lexer" -o "$1" = "all" ]; then
cd $HPHP_HOME/hphp/util/parser
[ $VERBOSE -eq 1 ] && echo "Generating lexer"