expose return type constraint (aka hint) from the AST to the runtime and reflection

This is the first part of the work to expose type constraint and generic all the way to reflection. This first DIFF exposes the return type with generic types coming next.
Esse commit está contido em:
drussi
2013-03-22 15:01:31 -07:00
commit de Sara Golemon
commit bf740ca345
23 arquivos alterados com 1661 adições e 1445 exclusões
+13 -4
Ver Arquivo
@@ -3816,7 +3816,7 @@ bool EmitterVisitor::visitImpl(ConstructPtr node) {
TypedValue uninit;
tvWriteUninit(&uninit);
for (auto& useVar : useVars) {
pce->addProperty(useVar.first, AttrPrivate, nullptr, &uninit);
pce->addProperty(useVar.first, AttrPrivate, nullptr, nullptr, &uninit);
}
// The constructor. This is entirely generated; all it does is stash its
@@ -5273,6 +5273,9 @@ void EmitterVisitor::emitPostponedMeths() {
pi.setRef(par->isRef());
fe->appendParam(parName, pi);
}
// add return type hint
fe->setReturnTypeConstraint(
StringData::GetStaticString(p.m_meth->getReturnTypeConstraint()));
m_curFunc = fe;
@@ -6203,6 +6206,8 @@ PreClass::Hoistable EmitterVisitor::emitClass(Emitter& e, ClassScopePtr cNode,
ModifierExpressionPtr mod(cv->getModifiers());
ExpressionListPtr el(cv->getVarList());
Attr attrs = buildAttrs(mod);
StringData* typeConstraint = StringData::GetStaticString(
cv->getTypeConstraint());
int nVars = el->getCount();
for (int ii = 0; ii < nVars; ii++) {
ExpressionPtr exp((*el)[ii]);
@@ -6244,12 +6249,14 @@ PreClass::Hoistable EmitterVisitor::emitClass(Emitter& e, ClassScopePtr cNode,
tvWriteNull(&tvVal);
}
bool added UNUSED =
pce->addProperty(propName, attrs, propDoc, &tvVal);
pce->addProperty(propName, attrs, typeConstraint, propDoc, &tvVal);
assert(added);
}
} else if (ClassConstantPtr cc =
dynamic_pointer_cast<ClassConstant>((*stmts)[i])) {
ExpressionListPtr el(cc->getConList());
StringData* typeConstraint = StringData::GetStaticString(
cc->getTypeConstraint());
int nCons = el->getCount();
for (int ii = 0; ii < nCons; ii++) {
AssignmentExpressionPtr ae(
@@ -6278,7 +6285,8 @@ PreClass::Hoistable EmitterVisitor::emitClass(Emitter& e, ClassScopePtr cNode,
AnalysisResultPtr ar(new AnalysisResult());
vNode->outputPHP(cg, ar);
bool added UNUSED = pce->addConstant(
constName, &tvVal, StringData::GetStaticString(os.str()));
constName, typeConstraint, &tvVal,
StringData::GetStaticString(os.str()));
assert(added);
}
} else if (UseTraitStatementPtr useStmt =
@@ -7181,7 +7189,7 @@ static Unit* emitHHBCNativeClassUnit(const HhbcExtClassInfo* builtinClasses,
assert(false);
}
pce->addConstant(
cnsInfo->name.get(), (TypedValue*)(&val), empty_string.get());
cnsInfo->name.get(), nullptr, (TypedValue*)(&val), empty_string.get());
}
}
{
@@ -7200,6 +7208,7 @@ static Unit* emitHHBCNativeClassUnit(const HhbcExtClassInfo* builtinClasses,
pce->addProperty(
propInfo->name.get(),
Attr(attr),
nullptr,
propInfo->docComment ? StringData::GetStaticString(propInfo->docComment) : nullptr,
&tvNull
);
+1 -1
Ver Arquivo
@@ -398,7 +398,7 @@ FunctionScopePtr FileScope::createPseudoMain(AnalysisResultConstPtr ar) {
(new FunctionStatement(BlockScopePtr(), LocationPtr(),
ModifierExpressionPtr(),
false, pseudoMainName(),
ExpressionListPtr(), st, 0, "",
ExpressionListPtr(), "", st, 0, "",
ExpressionListPtr()));
f->setFileLevel();
FunctionScopePtr pseudoMain(
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+10 -21
Ver Arquivo
@@ -787,15 +787,10 @@ void Parser::fixStaticVars() {
void Parser::onFunction(Token &out, Token *modifiers, Token &ret, Token &ref,
Token &name, Token &params, Token &stmt, Token *attr) {
ModifierExpressionPtr exp = modifiers?
dynamic_pointer_cast<ModifierExpression>(modifiers->exp)
: NEW_EXP0(ModifierExpression);
const string &retType = ret.text();
if (!retType.empty() && !ret.check()) {
PARSE_ERROR("Return type hint is not supported yet");
}
if (!stmt->stmt) {
stmt->stmt = NEW_STMT0(StatementList);
}
@@ -828,6 +823,7 @@ void Parser::onFunction(Token &out, Token *modifiers, Token &ret, Token &ref,
func = NEW_STMT(FunctionStatement, exp, ref->num(), closureName,
dynamic_pointer_cast<ExpressionList>(new_params->exp),
ret.text(),
dynamic_pointer_cast<StatementList>(stmt->stmt),
attribute, comment, ExpressionListPtr());
out->stmt = func;
@@ -878,7 +874,8 @@ void Parser::onFunction(Token &out, Token *modifiers, Token &ret, Token &ref,
}
func = NEW_STMT(FunctionStatement, exp, ref->num(), funcName,
old_params, dynamic_pointer_cast<StatementList>(stmt->stmt),
old_params, ret.text(),
dynamic_pointer_cast<StatementList>(stmt->stmt),
attribute, comment, attrList);
out->stmt = func;
@@ -895,10 +892,6 @@ void Parser::onFunction(Token &out, Token *modifiers, Token &ret, Token &ref,
out->stmt = NEW_STMT0(StatementList);
}
}
if (hasType(ret)) {
// TODO
}
}
void Parser::onParam(Token &out, Token *params, Token &type, Token &var,
@@ -1080,14 +1073,12 @@ void Parser::onClassVariableStart(Token &out, Token *modifiers, Token &decl,
: NEW_EXP0(ModifierExpression);
out->stmt = NEW_STMT
(ClassVariable, exp, dynamic_pointer_cast<ExpressionList>(decl->exp));
(ClassVariable, exp, (type) ? type->text() : "",
dynamic_pointer_cast<ExpressionList>(decl->exp));
} else {
out->stmt =
NEW_STMT(ClassConstant, dynamic_pointer_cast<ExpressionList>(decl->exp));
}
if (type && hasType(*type)) {
// TODO
NEW_STMT(ClassConstant, (type) ? type->text() : "",
dynamic_pointer_cast<ExpressionList>(decl->exp));
}
}
@@ -1130,6 +1121,7 @@ void Parser::onMethod(Token &out, Token &modifiers, Token &ret, Token &ref,
ModifierExpressionPtr exp2 = Construct::Clone(exp);
mth = NEW_STMT(MethodStatement, exp2, ref->num(), closureName,
dynamic_pointer_cast<ExpressionList>(new_params->exp),
ret.text(),
dynamic_pointer_cast<StatementList>(stmt->stmt),
attribute, comment, ExpressionListPtr());
out->stmt = mth;
@@ -1161,7 +1153,8 @@ void Parser::onMethod(Token &out, Token &modifiers, Token &ret, Token &ref,
attrList = dynamic_pointer_cast<ExpressionList>(attr->exp);
}
mth = NEW_STMT(MethodStatement, exp, ref->num(), name->text(),
old_params, stmts, attribute, comment, attrList);
old_params, ret.text(), stmts, attribute, comment,
attrList);
out->stmt = mth;
if (reloc) {
mth->getLocation()->line0 = loc->line0;
@@ -1169,10 +1162,6 @@ void Parser::onMethod(Token &out, Token &modifiers, Token &ret, Token &ref,
}
completeScope(mth->onInitialParse(m_ar, m_file));
}
if (hasType(ret)) {
// TODO
}
}
void Parser::onMemberModifier(Token &out, Token *modifiers, Token &modifier) {
+3 -2
Ver Arquivo
@@ -30,9 +30,10 @@ using namespace HPHP;
// constructors/destructors
ClassConstant::ClassConstant
(STATEMENT_CONSTRUCTOR_PARAMETERS, ExpressionListPtr exp)
(STATEMENT_CONSTRUCTOR_PARAMETERS, std::string typeConstraint,
ExpressionListPtr exp)
: Statement(STATEMENT_CONSTRUCTOR_PARAMETER_VALUES(ClassConstant)),
m_exp(exp) {
m_typeConstraint(typeConstraint), m_exp(exp) {
}
StatementPtr ClassConstant::clone() {
+5 -1
Ver Arquivo
@@ -27,7 +27,8 @@ DECLARE_BOOST_TYPES(ClassConstant);
class ClassConstant : public Statement, public IParseHandler {
public:
ClassConstant(STATEMENT_CONSTRUCTOR_PARAMETERS, ExpressionListPtr exp);
ClassConstant(STATEMENT_CONSTRUCTOR_PARAMETERS, std::string typeConstraint,
ExpressionListPtr exp);
DECLARE_STATEMENT_VIRTUAL_FUNCTIONS;
StatementPtr preOptimize(AnalysisResultConstPtr ar);
@@ -35,8 +36,11 @@ public:
// implementing IParseHandler
virtual void onParseRecur(AnalysisResultConstPtr ar, ClassScopePtr scope);
std::string getTypeConstraint() const { return m_typeConstraint; }
ExpressionListPtr getConList() { return m_exp; }
private:
std::string m_typeConstraint;
ExpressionListPtr m_exp;
};
+4 -2
Ver Arquivo
@@ -32,9 +32,11 @@ using namespace HPHP;
ClassVariable::ClassVariable
(STATEMENT_CONSTRUCTOR_PARAMETERS,
ModifierExpressionPtr modifiers, ExpressionListPtr declaration)
ModifierExpressionPtr modifiers, std::string typeConstraint,
ExpressionListPtr declaration)
: Statement(STATEMENT_CONSTRUCTOR_PARAMETER_VALUES(ClassVariable)),
m_modifiers(modifiers), m_declaration(declaration) {
m_modifiers(modifiers), m_typeConstraint(typeConstraint),
m_declaration(declaration) {
}
StatementPtr ClassVariable::clone() {
+3
Ver Arquivo
@@ -31,6 +31,7 @@ class ClassVariable : public Statement, public IParseHandler {
public:
ClassVariable(STATEMENT_CONSTRUCTOR_PARAMETERS,
ModifierExpressionPtr modifiers,
std::string typeConstraint,
ExpressionListPtr declaration);
DECLARE_STATEMENT_VIRTUAL_FUNCTIONS;
@@ -39,6 +40,7 @@ public:
// implementing IParseHandler
virtual void onParseRecur(AnalysisResultConstPtr ar, ClassScopePtr scope);
std::string getTypeConstraint() const { return m_typeConstraint; }
ExpressionListPtr getVarList() const { return m_declaration; }
ModifierExpressionPtr getModifiers() const { return m_modifiers; }
@@ -47,6 +49,7 @@ public:
private:
ModifierExpressionPtr m_modifiers;
std::string m_typeConstraint;
ExpressionListPtr m_declaration;
};
+6 -5
Ver Arquivo
@@ -35,12 +35,13 @@ using namespace HPHP;
FunctionStatement::FunctionStatement
(STATEMENT_CONSTRUCTOR_PARAMETERS,
ModifierExpressionPtr modifiers, bool ref, const std::string &name,
ExpressionListPtr params, StatementListPtr stmt, int attr, const
std::string &docComment, ExpressionListPtr attrList)
ModifierExpressionPtr modifiers, bool ref, const std::string &name,
ExpressionListPtr params, const std::string &retTypeConstraint,
StatementListPtr stmt, int attr, const std::string &docComment,
ExpressionListPtr attrList)
: MethodStatement(STATEMENT_CONSTRUCTOR_PARAMETER_VALUES(FunctionStatement),
modifiers, ref, name, params, stmt, attr,
docComment, attrList, false), m_ignored(false) {
modifiers, ref, name, params, retTypeConstraint, stmt,
attr, docComment, attrList, false), m_ignored(false) {
}
StatementPtr FunctionStatement::clone() {
+3 -2
Ver Arquivo
@@ -31,8 +31,9 @@ DECLARE_BOOST_TYPES(FunctionStatement);
class FunctionStatement : public MethodStatement {
public:
FunctionStatement(STATEMENT_CONSTRUCTOR_PARAMETERS,
ModifierExpressionPtr modifiers, bool ref,
const std::string &name, ExpressionListPtr params,
ModifierExpressionPtr modifiers, bool ref,
const std::string &name, ExpressionListPtr params,
const std::string &retTypeConstraint,
StatementListPtr stmt, int attr,
const std::string &docComment,
ExpressionListPtr attrList);
+10 -8
Ver Arquivo
@@ -59,13 +59,14 @@ using std::map;
MethodStatement::MethodStatement
(STATEMENT_CONSTRUCTOR_BASE_PARAMETERS,
ModifierExpressionPtr modifiers, bool ref, const string &name,
ExpressionListPtr params, StatementListPtr stmt, int attr,
const string &docComment, ExpressionListPtr attrList,
bool method /* = true */)
ExpressionListPtr params, const std::string &retTypeConstraint,
StatementListPtr stmt, int attr, const string &docComment,
ExpressionListPtr attrList, bool method /* = true */)
: Statement(STATEMENT_CONSTRUCTOR_BASE_PARAMETER_VALUES),
m_method(method), m_ref(ref), m_attribute(attr),
m_cppLength(-1), m_modifiers(modifiers),
m_originalName(name), m_params(params), m_stmt(stmt),
m_originalName(name), m_params(params),
m_retTypeConstraint(retTypeConstraint), m_stmt(stmt),
m_docComment(docComment), m_attrList(attrList) {
m_name = Util::toLower(name);
}
@@ -73,14 +74,15 @@ MethodStatement::MethodStatement
MethodStatement::MethodStatement
(STATEMENT_CONSTRUCTOR_PARAMETERS,
ModifierExpressionPtr modifiers, bool ref, const string &name,
ExpressionListPtr params, StatementListPtr stmt, int attr,
const string &docComment, ExpressionListPtr attrList,
ExpressionListPtr params, const std::string &retTypeConstraint,
StatementListPtr stmt,
int attr, const string &docComment, ExpressionListPtr attrList,
bool method /* = true */)
: Statement(STATEMENT_CONSTRUCTOR_PARAMETER_VALUES(MethodStatement)),
m_method(method), m_ref(ref), m_attribute(attr), m_cppLength(-1),
m_modifiers(modifiers), m_originalName(name),
m_params(params), m_stmt(stmt),
m_docComment(docComment), m_attrList(attrList) {
m_params(params), m_retTypeConstraint(retTypeConstraint),
m_stmt(stmt), m_docComment(docComment), m_attrList(attrList) {
m_name = Util::toLower(name);
}
+10 -6
Ver Arquivo
@@ -34,16 +34,16 @@ protected:
MethodStatement(STATEMENT_CONSTRUCTOR_BASE_PARAMETERS,
ModifierExpressionPtr modifiers, bool ref,
const std::string &name, ExpressionListPtr params,
StatementListPtr stmt, int attr,
const std::string &docComment, ExpressionListPtr attrList,
bool method = true);
const std::string &retTypeConstraint, StatementListPtr stmt,
int attr, const std::string &docComment,
ExpressionListPtr attrList, bool method = true);
public:
MethodStatement(STATEMENT_CONSTRUCTOR_PARAMETERS,
ModifierExpressionPtr modifiers, bool ref,
const std::string &name, ExpressionListPtr params,
StatementListPtr stmt, int attr,
const std::string &docComment, ExpressionListPtr attrList,
bool method = true);
const std::string &retTypeConstraint, StatementListPtr stmt,
int attr, const std::string &docComment,
ExpressionListPtr attrList, bool method = true);
DECLARE_STATEMENT_VIRTUAL_FUNCTIONS;
void inferFunctionTypes(AnalysisResultPtr ar);
@@ -63,6 +63,9 @@ public:
std::string getOriginalFullName() const;
std::string getOriginalFullNameForInjection() const;
ExpressionListPtr getParams() { return m_params;}
const std::string getReturnTypeConstraint() const {
return m_retTypeConstraint;
}
StatementListPtr getStmts() { return m_stmt;}
bool isRef(int index = -1) const;
@@ -131,6 +134,7 @@ protected:
std::string m_className;
std::string m_originalClassName;
ExpressionListPtr m_params;
std::string m_retTypeConstraint;
StatementListPtr m_stmt;
std::string m_docComment;
MethodStatementRawPtr m_origGeneratorFunc;
+20
Ver Arquivo
@@ -82,6 +82,7 @@ static StaticString s_closure("closure");
static StaticString s___invoke("__invoke");
static StaticString s_closure_in_braces("{closure}");
static StaticString s_closureobj("closureobj");
static StaticString s_return_type("return_type");
static const VM::Class* get_cls(CVarRef class_or_object) {
VM::Class* cls = NULL;
@@ -183,6 +184,14 @@ static void set_doc_comment(Array &ret, const StringData* comment) {
}
}
static void set_return_type_constraint(Array &ret, const StringData* retType) {
if (retType && retType->size()) {
ret.set(s_return_type, VarNR(retType));
} else {
ret.set(s_return_type, false_varNR);
}
}
static void set_property_info(Array &ret, ClassInfo::PropertyInfo *info,
const ClassInfo *cls) {
ret.set(s_name, info->name);
@@ -197,6 +206,11 @@ static void set_instance_prop_info(Array &ret, const VM::Class::Prop* prop) {
set_attrs(ret, get_modifiers(prop->m_attrs, false) & ~0x66);
ret.set(s_class, VarNR(prop->m_class->name()));
set_doc_comment(ret, prop->m_docComment);
if (prop->m_typeConstraint && prop->m_typeConstraint->size()) {
ret.set(s_type, VarNR(prop->m_typeConstraint));
} else {
ret.set(s_type, false_varNR);
}
}
static void set_static_prop_info(Array &ret, const VM::Class::SProp* prop) {
@@ -204,6 +218,11 @@ static void set_static_prop_info(Array &ret, const VM::Class::SProp* prop) {
set_attrs(ret, get_modifiers(prop->m_attrs, false) & ~0x66);
ret.set(s_class, VarNR(prop->m_class->name()));
set_doc_comment(ret, prop->m_docComment);
if (prop->m_typeConstraint && prop->m_typeConstraint->size()) {
ret.set(s_type, VarNR(prop->m_typeConstraint));
} else {
ret.set(s_type, false_varNR);
}
}
static void set_function_info(Array &ret, const ClassInfo::MethodInfo *info,
@@ -313,6 +332,7 @@ static void set_function_info(Array &ret, const VM::Func* func) {
ret.set(s_hphp, true_varNR);
}
}
set_return_type_constraint(ret, func->returnTypeConstraint());
// doc comments
set_doc_comment(ret, func->docComment());
+2 -2
Ver Arquivo
@@ -1515,7 +1515,7 @@ void parse_property(AsmState& as) {
TypedValue tvInit = parse_member_tv_initializer(as);
as.pce->addProperty(StringData::GetStaticString(name),
attrs,
attrs, empty_string.get(),
empty_string.get(),
&tvInit);
}
@@ -1534,7 +1534,7 @@ void parse_constant(AsmState& as) {
TypedValue tvInit = parse_member_tv_initializer(as);
as.pce->addConstant(StringData::GetStaticString(name),
&tvInit,
empty_string.get(), &tvInit,
empty_string.get());
}
+24 -8
Ver Arquivo
@@ -85,9 +85,10 @@ static const StringData* manglePropName(const StringData* className,
// PreClass::Prop.
PreClass::Prop::Prop(PreClass* preClass, const StringData* n, Attr attrs,
const StringData* typeConstraint,
const StringData* docComment, const TypedValue& val)
: m_preClass(preClass), m_name(n), m_attrs(attrs),
m_docComment(docComment) {
m_typeConstraint(typeConstraint), m_docComment(docComment) {
m_mangledName = manglePropName(preClass->name(), n, attrs);
memcpy(&m_val, &val, sizeof(TypedValue));
}
@@ -113,8 +114,10 @@ void PreClass::Prop::prettyPrint(std::ostream& out) const {
// PreClass::Const.
PreClass::Const::Const(PreClass* preClass, const StringData* n,
const StringData* typeConstraint,
const TypedValue& val, const StringData* phpCode)
: m_preClass(preClass), m_name(n), m_phpCode(phpCode) {
: m_preClass(preClass), m_name(n), m_typeConstraint(typeConstraint),
m_phpCode(phpCode) {
memcpy(&m_val, &val, sizeof(TypedValue));
}
@@ -191,9 +194,10 @@ void PreClass::prettyPrint(std::ostream &out) const {
// PreClassEmitter::Prop.
PreClassEmitter::Prop::Prop(const PreClassEmitter* pce, const StringData* n,
Attr attrs, const StringData* docComment,
TypedValue* val)
: m_name(n), m_attrs(attrs), m_docComment(docComment) {
Attr attrs, const StringData* typeConstraint,
const StringData* docComment, TypedValue* val)
: m_name(n), m_attrs(attrs), m_typeConstraint(typeConstraint),
m_docComment(docComment) {
m_mangledName = manglePropName(pce->name(), n, attrs);
memcpy(&m_val, val, sizeof(TypedValue));
}
@@ -249,13 +253,14 @@ bool PreClassEmitter::addMethod(FuncEmitter* method) {
}
bool PreClassEmitter::addProperty(const StringData* n, Attr attrs,
const StringData* typeConstraint,
const StringData* docComment,
TypedValue* val) {
PropMap::Builder::const_iterator it = m_propMap.find(n);
if (it != m_propMap.end()) {
return false;
}
PreClassEmitter::Prop prop(this, n, attrs, docComment, val);
PreClassEmitter::Prop prop(this, n, attrs, typeConstraint, docComment, val);
m_propMap.add(prop.name(), prop);
return true;
}
@@ -268,13 +273,15 @@ PreClassEmitter::lookupProp(const StringData* propName) const {
return m_propMap[idx];
}
bool PreClassEmitter::addConstant(const StringData* n, TypedValue* val,
bool PreClassEmitter::addConstant(const StringData* n,
const StringData* typeConstraint,
TypedValue* val,
const StringData* phpCode) {
ConstMap::Builder::const_iterator it = m_constMap.find(n);
if (it != m_constMap.end()) {
return false;
}
PreClassEmitter::Const const_(n, val, phpCode);
PreClassEmitter::Const const_(n, typeConstraint, val, phpCode);
m_constMap.add(const_.name(), const_);
return true;
}
@@ -359,6 +366,7 @@ PreClass* PreClassEmitter::create(Unit& unit) const {
propBuild.add(prop.name(), PreClass::Prop(pc,
prop.name(),
prop.attrs(),
prop.typeConstraint(),
prop.docComment(),
prop.val()));
}
@@ -369,6 +377,7 @@ PreClass* PreClassEmitter::create(Unit& unit) const {
const Const& const_ = m_constMap[i];
constBuild.add(const_.name(), PreClass::Const(pc,
const_.name(),
const_.typeConstraint(),
const_.val(),
const_.phpCode()));
}
@@ -1830,6 +1839,7 @@ void Class::setProperties() {
prop.m_originalMangledName = parentProp.m_originalMangledName;
prop.m_attrs = parentProp.m_attrs;
prop.m_docComment = parentProp.m_docComment;
prop.m_typeConstraint = parentProp.m_typeConstraint;
prop.m_name = parentProp.m_name;
if (!(parentProp.m_attrs & AttrPrivate)) {
curPropMap.add(prop.m_name, prop);
@@ -1847,6 +1857,7 @@ void Class::setProperties() {
SProp sProp;
sProp.m_name = parentProp.m_name;
sProp.m_attrs = parentProp.m_attrs;
sProp.m_typeConstraint = parentProp.m_typeConstraint;
sProp.m_docComment = parentProp.m_docComment;
sProp.m_class = parentProp.m_class;
tvWriteUninit(&sProp.m_val);
@@ -1901,6 +1912,7 @@ void Class::setProperties() {
prop.m_attrs = preProp->attrs();
// This is the first class to declare this property
prop.m_class = this;
prop.m_typeConstraint = preProp->typeConstraint();
prop.m_docComment = preProp->docComment();
curPropMap.add(preProp->name(), prop);
m_declPropInit.push_back(m_preClass->lookupProp(preProp->name())
@@ -1927,6 +1939,7 @@ void Class::setProperties() {
prop.m_mangledName = preProp->mangledName();
prop.m_originalMangledName = preProp->mangledName();
prop.m_attrs = preProp->attrs();
prop.m_typeConstraint = preProp->typeConstraint();
// This is the first class to declare this property
prop.m_class = this;
prop.m_docComment = preProp->docComment();
@@ -1947,6 +1960,7 @@ void Class::setProperties() {
prop.m_mangledName = preProp->mangledName();
prop.m_originalMangledName = preProp->mangledName();
prop.m_attrs = Attr(prop.m_attrs ^ (AttrProtected|AttrPublic));
prop.m_typeConstraint = preProp->typeConstraint();
}
const TypedValue& tv = m_preClass->lookupProp(preProp->name())->val();
TypedValueAux& tvaux = m_declPropInit[it2->second];
@@ -1961,6 +1975,7 @@ void Class::setProperties() {
prop.m_mangledName = preProp->mangledName();
prop.m_originalMangledName = preProp->mangledName();
prop.m_attrs = preProp->attrs();
prop.m_typeConstraint = preProp->typeConstraint();
// This is the first class to declare this property
prop.m_class = this;
prop.m_docComment = preProp->docComment();
@@ -2013,6 +2028,7 @@ void Class::setProperties() {
SProp& sProp = curSPropMap[sPropInd];
// Finish initializing.
sProp.m_attrs = preProp->attrs();
sProp.m_typeConstraint = preProp->typeConstraint();
sProp.m_docComment = preProp->docComment();
sProp.m_class = this;
sProp.m_val = m_preClass->lookupProp(preProp->name())->val();
+26 -7
Ver Arquivo
@@ -123,7 +123,8 @@ class PreClass : public AtomicCountable {
struct Prop {
Prop() {}
Prop(PreClass* preClass, const StringData* n, Attr attrs,
const StringData* docComment, const TypedValue& val);
const StringData* typeConstraint, const StringData* docComment,
const TypedValue& val);
void prettyPrint(std::ostream& out) const;
@@ -133,6 +134,7 @@ class PreClass : public AtomicCountable {
const StringData* mangledName() const { return m_mangledName; }
CStrRef mangledNameRef() const { return *(String*)(&m_mangledName); }
Attr attrs() const { return m_attrs; }
const StringData* typeConstraint() const { return m_typeConstraint; }
const StringData* docComment() const { return m_docComment; }
const TypedValue& val() const { return m_val; }
@@ -141,13 +143,15 @@ class PreClass : public AtomicCountable {
const StringData* m_name;
const StringData* m_mangledName;
Attr m_attrs;
const StringData* m_typeConstraint;
const StringData* m_docComment;
TypedValue m_val;
};
struct Const {
Const() {}
Const(PreClass* preClass, const StringData* n, const TypedValue& val,
Const(PreClass* preClass, const StringData* n,
const StringData* typeConstraint, const TypedValue& val,
const StringData* phpCode);
void prettyPrint(std::ostream& out) const;
@@ -155,12 +159,14 @@ class PreClass : public AtomicCountable {
PreClass* preClass() const { return m_preClass; }
const StringData* name() const { return m_name; }
CStrRef nameRef() const { return *(String*)&m_name; }
const StringData* typeConstraint() const { return m_typeConstraint; }
const TypedValue& val() const { return m_val; }
const StringData* phpCode() const { return m_phpCode; }
private:
PreClass* m_preClass;
const StringData* m_name;
const StringData* m_typeConstraint;
TypedValue m_val;
const StringData* m_phpCode;
};
@@ -359,16 +365,19 @@ class PreClassEmitter {
: m_name(0)
, m_mangledName(0)
, m_attrs(AttrNone)
, m_typeConstraint(0)
, m_docComment(0)
{}
Prop(const PreClassEmitter* pce, const StringData* n, Attr attrs,
const StringData* docComment, TypedValue* val);
const StringData* typeConstraint, const StringData* docComment,
TypedValue* val);
~Prop();
const StringData* name() const { return m_name; }
const StringData* mangledName() const { return m_mangledName; }
Attr attrs() const { return m_attrs; }
const StringData* typeConstraint() const { return m_typeConstraint; }
const StringData* docComment() const { return m_docComment; }
const TypedValue& val() const { return m_val; }
@@ -376,6 +385,7 @@ class PreClassEmitter {
sd(m_name)
(m_mangledName)
(m_attrs)
(m_typeConstraint)
(m_docComment)
(m_val)
;
@@ -385,6 +395,7 @@ class PreClassEmitter {
const StringData* m_name;
const StringData* m_mangledName;
Attr m_attrs;
const StringData* m_typeConstraint;
const StringData* m_docComment;
TypedValue m_val;
};
@@ -393,15 +404,18 @@ class PreClassEmitter {
public:
Const()
: m_name(0)
, m_typeConstraint(0)
, m_phpCode(0)
{}
Const(const StringData* n, TypedValue* val, const StringData* phpCode)
: m_name(n), m_phpCode(phpCode) {
Const(const StringData* n, const StringData* typeConstraint,
TypedValue* val, const StringData* phpCode)
: m_name(n), m_typeConstraint(typeConstraint), m_phpCode(phpCode) {
memcpy(&m_val, val, sizeof(TypedValue));
}
~Const() {}
const StringData* name() const { return m_name; }
const StringData* typeConstraint() const { return m_typeConstraint; }
const TypedValue& val() const { return m_val; }
const StringData* phpCode() const { return m_phpCode; }
@@ -411,6 +425,7 @@ class PreClassEmitter {
private:
const StringData* m_name;
const StringData* m_typeConstraint;
TypedValue m_val;
const StringData* m_phpCode;
};
@@ -432,10 +447,11 @@ class PreClassEmitter {
void addInterface(const StringData* n);
bool addMethod(FuncEmitter* method);
bool addProperty(const StringData* n, Attr attrs,
const StringData* typeConstraint,
const StringData* docComment, TypedValue* val);
const Prop& lookupProp(const StringData* propName) const;
bool addConstant(const StringData* n, TypedValue* val,
const StringData* phpCode);
bool addConstant(const StringData* n, const StringData* typeConstraint,
TypedValue* val, const StringData* phpCode);
void addUsedTrait(const StringData* traitName);
void addTraitPrecRule(const PreClass::TraitPrecRule &rule);
void addTraitAliasRule(const PreClass::TraitAliasRule &rule);
@@ -544,12 +560,14 @@ public:
const StringData* m_originalMangledName;
Class* m_class; // First parent class that declares this property.
Attr m_attrs;
const StringData* m_typeConstraint;
const StringData* m_docComment;
};
struct SProp {
const StringData* m_name;
Attr m_attrs;
const StringData* m_typeConstraint;
const StringData* m_docComment;
Class* m_class; // Most derived class that declared this property.
TypedValue m_val; // Used if (m_class == this).
@@ -560,6 +578,7 @@ public:
const StringData* m_name;
TypedValue m_val;
const StringData* m_phpCode;
const StringData* m_typeConstraint;
CStrRef nameRef() const { return *(String*)&m_name; }
};
+10 -8
Ver Arquivo
@@ -673,20 +673,20 @@ const Func* Func::getGeneratorBody(const StringData* name) const {
FuncEmitter::FuncEmitter(UnitEmitter& ue, int sn, Id id, const StringData* n)
: m_ue(ue), m_pce(nullptr), m_sn(sn), m_id(id), m_name(n), m_numLocals(0),
m_numUnnamedLocals(0), m_activeUnnamedLocals(0), m_numIterators(0),
m_nextFreeIterator(0), m_returnType(KindOfInvalid), m_top(false),
m_isClosureBody(false), m_isGenerator(false),
m_isGeneratorFromClosure(false), m_hasGeneratorAsBody(false), m_info(nullptr),
m_builtinFuncPtr(nullptr) {
m_nextFreeIterator(0), m_retTypeConstraint(nullptr),
m_returnType(KindOfInvalid), m_top(false), m_isClosureBody(false),
m_isGenerator(false), m_isGeneratorFromClosure(false),
m_hasGeneratorAsBody(false), m_info(nullptr), m_builtinFuncPtr(nullptr) {
}
FuncEmitter::FuncEmitter(UnitEmitter& ue, int sn, const StringData* n,
PreClassEmitter* pce)
: m_ue(ue), m_pce(pce), m_sn(sn), m_name(n), m_numLocals(0),
m_numUnnamedLocals(0), m_activeUnnamedLocals(0), m_numIterators(0),
m_nextFreeIterator(0), m_returnType(KindOfInvalid), m_top(false),
m_isClosureBody(false), m_isGenerator(false),
m_isGeneratorFromClosure(false), m_hasGeneratorAsBody(false), m_info(nullptr),
m_builtinFuncPtr(nullptr) {
m_nextFreeIterator(0), m_retTypeConstraint(nullptr),
m_returnType(KindOfInvalid), m_top(false), m_isClosureBody(false),
m_isGenerator(false), m_isGeneratorFromClosure(false),
m_hasGeneratorAsBody(false), m_info(nullptr), m_builtinFuncPtr(nullptr) {
}
FuncEmitter::~FuncEmitter() {
@@ -915,6 +915,7 @@ Func* FuncEmitter::create(Unit& unit, PreClass* preClass /* = NULL */) const {
f->shared()->m_userAttributes = m_userAttributes;
f->shared()->m_builtinFuncPtr = m_builtinFuncPtr;
f->shared()->m_nativeFuncPtr = m_nativeFuncPtr;
f->shared()->m_retTypeConstraint = m_retTypeConstraint;
return f;
}
@@ -999,6 +1000,7 @@ void FuncEmitter::serdeMetaData(SerDe& sd) {
(m_ehtab)
(m_fpitab)
(m_userAttributes)
(m_retTypeConstraint)
;
}
+11
Ver Arquivo
@@ -313,6 +313,10 @@ struct Func {
return id < numNamedLocals() ? shared()->m_localNames[id] : 0;
}
const StringData* returnTypeConstraint() const {
return shared()->m_retTypeConstraint;
}
int numIterators() const { return shared()->m_numIterators; }
const EHEntVec& ehtab() const { return shared()->m_ehtab; }
const FPIEntVec& fpitab() const { return shared()->m_fpitab; }
@@ -457,6 +461,7 @@ private:
bool m_isGeneratorFromClosure : 1;
bool m_hasGeneratorAsBody : 1;
UserAttributeMap m_userAttributes;
const StringData* m_retTypeConstraint;
SharedData(PreClass* preClass, Id id, Offset base,
Offset past, int line1, int line2, bool top,
const StringData* docComment);
@@ -567,6 +572,10 @@ public:
bool hasVar(const StringData* name) const;
Id numParams() const { return m_params.size(); }
void setReturnTypeConstraint(const StringData* retTypeConstraint) {
m_retTypeConstraint = retTypeConstraint;
}
Id allocIterator();
void freeIterator(Id id);
void setNumIterators(Id numIterators);
@@ -651,6 +660,8 @@ private:
int m_maxStackCells;
SVInfoVec m_staticVars;
const StringData* m_retTypeConstraint;
EHEntVec m_ehtab;
FPIEntVec m_fpitab;
+14
Ver Arquivo
@@ -534,6 +534,13 @@ class ReflectionFunctionAbstract {
}
return $count;
}
public function getReturnTypehintText() {
if (isset($this->info['return_type'])) {
return $this->info['return_type'];
}
return '';
}
}
///////////////////////////////////////////////////////////////////////////////
@@ -1769,6 +1776,13 @@ class ReflectionProperty implements Reflector {
public function getDocComment() {
return $this->info['doc'];
}
public function getTypehintText() {
if (isset($this->info['type'])) {
return $this->info['type'];
}
return '';
}
}
///////////////////////////////////////////////////////////////////////////////
+118
Ver Arquivo
@@ -13799,6 +13799,124 @@ bool TestCodeRun::TestReflectionClasses() {
"$a = $r->getProperties(ReflectionProperty::IS_PROTECTED); f($a);\n"
"$a = $r->getProperties(ReflectionProperty::IS_STATIC); f($a);\n");
// return type constraints (hints)
MVCRO("<?hh\n"
"function foo(Vector<int> $z): Vector<int> { "
" return $z; "
"} "
"$rf = new ReflectionFunction('foo'); "
"var_dump($rf->getReturnTypehintText()); "
"class C { "
" function goo(): int { return 0; } "
"} "
"$rc = new ReflectionClass('C'); "
"$rm = $rc->getMethod('goo'); "
"var_dump($rm->getReturnTypehintText()); "
"class C1 extends C { "
" function goo() { return 0; } "
"} "
"$rc = new ReflectionClass('C1'); "
"$rm = $rc->getMethod('goo'); "
"var_dump($rm->getReturnTypehintText()); "
"class C2 extends C1 { "
" function goo(): string { return '0'; } "
"} "
"$rc = new ReflectionClass('C2'); "
"$rm = $rc->getMethod('goo'); "
"var_dump($rm->getReturnTypehintText()); "
"interface I { "
" function m(): string; "
"} "
"$rc = new ReflectionClass('I'); "
"$rm = $rc->getMethod('m'); "
"var_dump($rm->getReturnTypehintText()); "
"interface I1<T> { "
" function m(): T; "
"} "
"$rc = new ReflectionClass('I1'); "
"$rm = $rc->getMethod('m'); "
"var_dump($rm->getReturnTypehintText()); "
"trait T { "
" function t(): C { "
" return new C(); "
" } "
"} "
"class UseT { "
" use T; "
"} "
"$rc = new ReflectionClass('UseT'); "
"$rm = $rc->getMethod('t'); "
"var_dump($rm->getReturnTypehintText());"
,
"string(6) \"Vector\"\n"
"string(3) \"int\"\n"
"bool(false)\n"
"string(6) \"string\"\n"
"string(6) \"string\"\n"
"bool(false)\n"
"string(1) \"C\"\n");
// field type constraints (hints)
MVCRO("<?hh\n"
"class C1 { "
" private int $pp; "
" private string $pField; "
" public string $field; "
" protected int $field1; "
" public static int $sField; "
"} "
"$rc = new ReflectionClass('C1'); "
"$rp = $rc->getProperty('pp'); "
"var_dump($rp->getTypehintText()); "
"$rp = $rc->getProperty('pField'); "
"var_dump($rp->getTypehintText()); "
"$rp = $rc->getProperty('field'); "
"var_dump($rp->getTypehintText()); "
"$rp = $rc->getProperty('field1'); "
"var_dump($rp->getTypehintText()); "
"$rp = $rc->getProperty('sField'); "
"var_dump($rp->getTypehintText()); "
"class C2 extends C1 { "
" public int $field; "
" private int $pField; "
"} "
"$rc = new ReflectionClass('C2'); "
"$rp = $rc->getProperty('field'); "
"var_dump($rp->getTypehintText()); "
"$rp = $rc->getProperty('field1'); "
"var_dump($rp->getTypehintText()); "
"$rp = $rc->getProperty('pField'); "
"var_dump($rp->getTypehintText()); "
"$rp = $rc->getProperty('sField'); "
"var_dump($rp->getTypehintText()); "
"var_dump($rc->hasProperty('pp')); "
"trait T { "
" public C1 $tField; "
" private C2 $tField1; "
"} "
"class TI { "
" use T; "
" public string $tField; "
"} "
"$rc = new ReflectionClass('TI'); "
"$rp = $rc->getProperty('tField'); "
"var_dump($rp->getTypehintText()); "
"$rp = $rc->getProperty('tField1'); "
"var_dump($rp->getTypehintText()); "
,
"string(3) \"int\"\n"
"string(6) \"string\"\n"
"string(6) \"string\"\n"
"string(3) \"int\"\n"
"string(3) \"int\"\n"
"string(6) \"string\"\n"
"string(3) \"int\"\n"
"string(3) \"int\"\n"
"string(3) \"int\"\n"
"bool(false)\n"
"string(6) \"string\"\n"
"string(2) \"C2\"\n");
{
HipHopSyntax w(this);
MVCROF(
+18 -6
Ver Arquivo
@@ -6,7 +6,7 @@ array(6) {
["class"]=>
string(8) "my_child"
["info"]=>
array(13) {
array(14) {
["name"]=>
string(17) "my_other_override"
["access"]=>
@@ -15,6 +15,8 @@ array(6) {
int(256)
["class"]=>
string(8) "my_child"
["return_type"]=>
bool(false)
["doc"]=>
bool(false)
["params"]=>
@@ -45,7 +47,7 @@ array(6) {
["class"]=>
string(8) "my_child"
["info"]=>
array(13) {
array(14) {
["name"]=>
string(15) "my_child_method"
["access"]=>
@@ -54,6 +56,8 @@ array(6) {
int(256)
["class"]=>
string(8) "my_child"
["return_type"]=>
bool(false)
["doc"]=>
bool(false)
["params"]=>
@@ -84,7 +88,7 @@ array(6) {
["class"]=>
string(8) "my_class"
["info"]=>
array(13) {
array(14) {
["name"]=>
string(9) "my_method"
["access"]=>
@@ -93,6 +97,8 @@ array(6) {
int(256)
["class"]=>
string(8) "my_class"
["return_type"]=>
bool(false)
["doc"]=>
bool(false)
["params"]=>
@@ -123,7 +129,7 @@ array(6) {
["class"]=>
string(8) "my_class"
["info"]=>
array(13) {
array(14) {
["name"]=>
string(18) "my_override_method"
["access"]=>
@@ -132,6 +138,8 @@ array(6) {
int(256)
["class"]=>
string(8) "my_class"
["return_type"]=>
bool(false)
["doc"]=>
bool(false)
["params"]=>
@@ -162,7 +170,7 @@ array(6) {
["class"]=>
string(8) "my_class"
["info"]=>
array(13) {
array(14) {
["name"]=>
string(15) "my_trait_method"
["access"]=>
@@ -171,6 +179,8 @@ array(6) {
int(256)
["class"]=>
string(8) "my_class"
["return_type"]=>
bool(false)
["doc"]=>
bool(false)
["params"]=>
@@ -201,7 +211,7 @@ array(6) {
["class"]=>
string(7) "my_base"
["info"]=>
array(13) {
array(14) {
["name"]=>
string(14) "my_base_method"
["access"]=>
@@ -210,6 +220,8 @@ array(6) {
int(256)
["class"]=>
string(7) "my_base"
["return_type"]=>
bool(false)
["doc"]=>
bool(false)
["params"]=>
+4 -8
Ver Arquivo
@@ -1020,8 +1020,7 @@ function_declaration_statement:
_p->pushLabelInfo();}
'(' parameter_list ')'
sm_opt_return_type
'{' inner_statement_list '}' { Token t; t.reset();
_p->onFunction($$,0,t,$2,$3,$6,$10,0);
'{' inner_statement_list '}' { _p->onFunction($$,0,$8,$2,$3,$6,$10,0);
_p->popLabelInfo();
_p->popTypeScope();}
| non_empty_user_attributes function_loc
@@ -1030,8 +1029,7 @@ function_declaration_statement:
_p->pushLabelInfo();}
'(' parameter_list ')'
sm_opt_return_type
'{' inner_statement_list '}' { Token t; t.reset();
_p->onFunction($$,0,t,$3,$4,$7,$11,&$1);
'{' inner_statement_list '}' { _p->onFunction($$,0,$9,$3,$4,$7,$11,&$1);
_p->popLabelInfo();
_p->popTypeScope();}
;
@@ -1315,8 +1313,7 @@ class_statement:
parameter_list ')'
sm_opt_return_type
method_body
{ Token t; t.reset();
_p->onMethod($$,$1,t,$3,$4,$7,$10,0);
{ _p->onMethod($$,$1,$9,$3,$4,$7,$10,0);
_p->popLabelInfo();
_p->popTypeScope();}
| non_empty_user_attributes
@@ -1327,8 +1324,7 @@ class_statement:
parameter_list ')'
sm_opt_return_type
method_body
{ Token t; t.reset();
_p->onMethod($$,$2,t,$4,$5,$8,$11,&$1);
{ _p->onMethod($$,$2,$10,$4,$5,$8,$11,&$1);
_p->popLabelInfo();
_p->popTypeScope();}
| T_XHP_ATTRIBUTE
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff