Refactor HipHopSyntax and HackMode to play nice
Esse commit está contido em:
@@ -5245,9 +5245,10 @@ void EmitterVisitor::emitPostponedMeths() {
|
||||
dynamic_pointer_cast<ConstantExpression>(par->defaultValue());
|
||||
bool nullable = ce && ce->isNull();
|
||||
TypeConstraint tc =
|
||||
TypeConstraint(StringData::GetStaticString(
|
||||
par->getOriginalTypeHint()),
|
||||
nullable);
|
||||
TypeConstraint(
|
||||
StringData::GetStaticString(par->getOriginalTypeHint()),
|
||||
nullable,
|
||||
par->hhType());
|
||||
pi.setTypeConstraint(tc);
|
||||
TRACE(1, "Added constraint to %s\n", fe->name()->data());
|
||||
}
|
||||
@@ -7375,7 +7376,7 @@ static void emitSystemLib() {
|
||||
|
||||
AnalysisResultPtr ar(new AnalysisResult());
|
||||
Scanner scanner(slib.c_str(), slib.size(),
|
||||
RuntimeOption::ScannerType, "/:systemlib.php");
|
||||
RuntimeOption::GetScannerType(), "/:systemlib.php");
|
||||
Parser parser(scanner, "/:systemlib.php", ar, slib.size());
|
||||
parser.parse();
|
||||
FileScopePtr fsp = parser.getFileScope();
|
||||
@@ -7509,7 +7510,7 @@ Unit* hphp_compiler_parse(const char* code, int codeLen, const MD5& md5,
|
||||
}
|
||||
|
||||
AnalysisResultPtr ar(new AnalysisResult());
|
||||
Scanner scanner(code, codeLen, RuntimeOption::ScannerType, filename);
|
||||
Scanner scanner(code, codeLen, RuntimeOption::GetScannerType(), filename);
|
||||
Parser parser(scanner, filename, ar, codeLen);
|
||||
parser.parse();
|
||||
FileScopePtr fsp = parser.getFileScope();
|
||||
|
||||
@@ -49,28 +49,32 @@ TypePtr Type::Any (new Type(Type::KindOfAny ));
|
||||
TypePtr Type::Some (new Type(Type::KindOfSome ));
|
||||
|
||||
Type::TypePtrMap Type::s_TypeHintTypes;
|
||||
Type::TypePtrMap Type::s_HHTypeHintTypes;
|
||||
|
||||
void Type::InitTypeHintMap() {
|
||||
assert(s_TypeHintTypes.empty());
|
||||
assert(s_HHTypeHintTypes.empty());
|
||||
|
||||
s_TypeHintTypes["array"] = Type::Array;
|
||||
if (Option::EnableHipHopSyntax) {
|
||||
s_TypeHintTypes["bool"] = Type::Boolean;
|
||||
s_TypeHintTypes["boolean"] = Type::Boolean;
|
||||
s_TypeHintTypes["int"] = Type::Int64;
|
||||
s_TypeHintTypes["integer"] = Type::Int64;
|
||||
s_TypeHintTypes["real"] = Type::Double;
|
||||
s_TypeHintTypes["double"] = Type::Double;
|
||||
s_TypeHintTypes["float"] = Type::Double;
|
||||
s_TypeHintTypes["string"] = Type::String;
|
||||
}
|
||||
|
||||
s_HHTypeHintTypes["array"] = Type::Array;
|
||||
s_HHTypeHintTypes["bool"] = Type::Boolean;
|
||||
s_HHTypeHintTypes["boolean"] = Type::Boolean;
|
||||
s_HHTypeHintTypes["int"] = Type::Int64;
|
||||
s_HHTypeHintTypes["integer"] = Type::Int64;
|
||||
s_HHTypeHintTypes["real"] = Type::Double;
|
||||
s_HHTypeHintTypes["double"] = Type::Double;
|
||||
s_HHTypeHintTypes["float"] = Type::Double;
|
||||
s_HHTypeHintTypes["string"] = Type::String;
|
||||
}
|
||||
|
||||
const Type::TypePtrMap &Type::GetTypeHintTypes() {
|
||||
return s_TypeHintTypes;
|
||||
const Type::TypePtrMap &Type::GetTypeHintTypes(bool hhType) {
|
||||
return hhType ? s_HHTypeHintTypes : s_TypeHintTypes;
|
||||
}
|
||||
|
||||
void Type::ResetTypeHintTypes() {
|
||||
s_TypeHintTypes.clear();
|
||||
s_HHTypeHintTypes.clear();
|
||||
}
|
||||
|
||||
TypePtr Type::CreateObjectType(const std::string &classname) {
|
||||
|
||||
@@ -102,7 +102,7 @@ public:
|
||||
static TypePtr Some;
|
||||
|
||||
typedef hphp_string_imap<TypePtr> TypePtrMap;
|
||||
static const TypePtrMap &GetTypeHintTypes();
|
||||
static const TypePtrMap &GetTypeHintTypes(bool hhType);
|
||||
|
||||
/**
|
||||
* Uncertain types: types that are ambiguous yet.
|
||||
@@ -267,6 +267,7 @@ private:
|
||||
static void ResetTypeHintTypes();
|
||||
|
||||
static TypePtrMap s_TypeHintTypes;
|
||||
static TypePtrMap s_HHTypeHintTypes;
|
||||
|
||||
const KindOf m_kindOf;
|
||||
const std::string m_name;
|
||||
|
||||
@@ -334,7 +334,7 @@ bool BuiltinSymbols::Load(AnalysisResultPtr ar, bool extOnly /* = false */) {
|
||||
string slib = get_systemlib();
|
||||
|
||||
Scanner scanner(slib.c_str(), slib.size(),
|
||||
Option::ScannerType, "systemlib.php");
|
||||
Option::GetScannerType(), "systemlib.php");
|
||||
Compiler::Parser parser(scanner, "systemlib.php", ar);
|
||||
if (!parser.parse()) {
|
||||
Logger::Error("Unable to parse systemlib.php: %s",
|
||||
@@ -406,7 +406,7 @@ AnalysisResultPtr BuiltinSymbols::LoadGlobalSymbols(const char *fileName) {
|
||||
fileName = s_strings.add(phpFileName.c_str());
|
||||
|
||||
try {
|
||||
Scanner scanner(fileName, Option::ScannerType);
|
||||
Scanner scanner(fileName, Option::GetScannerType());
|
||||
Compiler::Parser parser(scanner, baseName, ar);
|
||||
if (!parser.parse()) {
|
||||
assert(false);
|
||||
|
||||
@@ -702,7 +702,7 @@ int lintTarget(const CompilerOptions &po) {
|
||||
for (unsigned int i = 0; i < po.inputs.size(); i++) {
|
||||
string filename = po.inputDir + "/" + po.inputs[i];
|
||||
try {
|
||||
Scanner scanner(filename.c_str(), Option::ScannerType);
|
||||
Scanner scanner(filename.c_str(), Option::GetScannerType());
|
||||
Compiler::Parser parser(scanner, filename.c_str(),
|
||||
AnalysisResultPtr(new AnalysisResult()));
|
||||
if (!parser.parse()) {
|
||||
|
||||
@@ -32,10 +32,10 @@ using namespace HPHP;
|
||||
|
||||
ParameterExpression::ParameterExpression
|
||||
(EXPRESSION_CONSTRUCTOR_PARAMETERS,
|
||||
TypeAnnotationPtr type, const std::string &name, bool ref,
|
||||
TypeAnnotationPtr type, bool hhType, const std::string &name, bool ref,
|
||||
ExpressionPtr defaultValue, ExpressionPtr attributeList)
|
||||
: Expression(EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES(ParameterExpression)),
|
||||
m_originalType(type), m_name(name), m_ref(ref),
|
||||
m_originalType(type), m_name(name), m_hhType(hhType), m_ref(ref),
|
||||
m_defaultValue(defaultValue), m_attributeList(attributeList) {
|
||||
m_type = Util::toLower(type ? type->simpleName() : "");
|
||||
if (m_defaultValue) {
|
||||
@@ -150,7 +150,7 @@ TypePtr ParameterExpression::getTypeSpecForClass(AnalysisResultPtr ar,
|
||||
|
||||
TypePtr ParameterExpression::getTypeSpec(AnalysisResultPtr ar,
|
||||
bool forInference) {
|
||||
const Type::TypePtrMap &types = Type::GetTypeHintTypes();
|
||||
const Type::TypePtrMap &types = Type::GetTypeHintTypes(m_hhType);
|
||||
Type::TypePtrMap::const_iterator iter;
|
||||
|
||||
TypePtr ret;
|
||||
@@ -231,7 +231,7 @@ void ParameterExpression::compatibleDefault() {
|
||||
|
||||
const char* msg = "Default value for parameter %s with type %s "
|
||||
"needs to have the same type as the type hint %s";
|
||||
if (Option::EnableHipHopSyntax) {
|
||||
if (m_hhType) {
|
||||
// Normally a named type like 'int' is compatable with Int but not integer
|
||||
// Since the default value's type is inferred from the value itself it is
|
||||
// ok to compare against the lower case version of the type hint in hint
|
||||
|
||||
@@ -31,7 +31,8 @@ DECLARE_BOOST_TYPES(TypeAnnotation);
|
||||
class ParameterExpression : public Expression {
|
||||
public:
|
||||
ParameterExpression(EXPRESSION_CONSTRUCTOR_PARAMETERS,
|
||||
TypeAnnotationPtr type, const std::string &name,
|
||||
TypeAnnotationPtr type, bool hhType,
|
||||
const std::string &name,
|
||||
bool ref, ExpressionPtr defaultValue,
|
||||
ExpressionPtr attributeList);
|
||||
|
||||
@@ -56,12 +57,14 @@ public:
|
||||
void parseHandler(ClassScopePtr cls);
|
||||
void compatibleDefault();
|
||||
void fixupSelfAndParentTypehints(ClassScopePtr cls);
|
||||
bool hhType() { return m_hhType; }
|
||||
private:
|
||||
TypePtr getTypeSpecForClass(AnalysisResultPtr ar, bool forInference);
|
||||
|
||||
std::string m_type;
|
||||
TypeAnnotationPtr m_originalType;
|
||||
std::string m_name;
|
||||
bool m_hhType;
|
||||
bool m_ref;
|
||||
ExpressionPtr m_defaultValue;
|
||||
ExpressionPtr m_attributeList;
|
||||
|
||||
@@ -120,9 +120,16 @@ bool Option::EnableShortTags = true;
|
||||
bool Option::EnableAspTags = false;
|
||||
bool Option::EnableXHP = true;
|
||||
bool Option::EnableFinallyStatement = false;
|
||||
int Option::ScannerType = Scanner::AllowShortTags;
|
||||
int Option::ParserThreadCount = 0;
|
||||
|
||||
int Option::GetScannerType() {
|
||||
int type = 0;
|
||||
if (EnableShortTags) type |= Scanner::AllowShortTags;
|
||||
if (EnableHipHopSyntax) type |= Scanner::AllowHipHopSyntax;
|
||||
if (EnableAspTags) type |= Scanner::AllowAspTags;
|
||||
return type;
|
||||
}
|
||||
|
||||
int Option::InvokeFewArgsCount = 6;
|
||||
bool Option::InvokeWithSpecificArgs = true;
|
||||
bool Option::FlattenInvoke = true;
|
||||
@@ -277,17 +284,8 @@ void Option::Load(Hdf &config) {
|
||||
EnableHipHopExperimentalSyntax =
|
||||
config["EnableHipHopExperimentalSyntax"].getBool();
|
||||
EnableShortTags = config["EnableShortTags"].getBool(true);
|
||||
if (EnableShortTags) ScannerType |= Scanner::AllowShortTags;
|
||||
else ScannerType &= ~Scanner::AllowShortTags;
|
||||
if (EnableHipHopExperimentalSyntax) {
|
||||
ScannerType |= Scanner::EnableHipHopKeywords;
|
||||
} else {
|
||||
ScannerType &= ~Scanner::EnableHipHopKeywords;
|
||||
}
|
||||
|
||||
EnableAspTags = config["EnableAspTags"].getBool();
|
||||
if (EnableAspTags) ScannerType |= Scanner::AllowAspTags;
|
||||
else ScannerType &= ~Scanner::AllowAspTags;
|
||||
|
||||
EnableXHP = config["EnableXHP"].getBool(true);
|
||||
|
||||
|
||||
@@ -235,9 +235,10 @@ public:
|
||||
static bool EnableAspTags;
|
||||
static bool EnableXHP;
|
||||
static bool EnableFinallyStatement;
|
||||
static int ScannerType;
|
||||
static int ParserThreadCount;
|
||||
|
||||
static int GetScannerType();
|
||||
|
||||
/**
|
||||
* "Dynamic" means a function or a method can be invoked dynamically.
|
||||
* "Volatile" means a class or a function can be declared dynamically.
|
||||
|
||||
@@ -297,7 +297,7 @@ bool Package::parseImpl(const char *fileName) {
|
||||
int lines = 0;
|
||||
try {
|
||||
Logger::Verbose("parsing %s ...", fullPath.c_str());
|
||||
Scanner scanner(fullPath.c_str(), Option::ScannerType, true);
|
||||
Scanner scanner(fullPath.c_str(), Option::GetScannerType(), true);
|
||||
Compiler::Parser parser(scanner, fileName, m_ar, sb.st_size);
|
||||
parser.parse();
|
||||
lines = parser.line1();
|
||||
|
||||
+801
-808
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
@@ -141,7 +141,7 @@ StatementListPtr Parser::ParseString(CStrRef input, AnalysisResultPtr ar,
|
||||
if (!fileName || !*fileName) fileName = "string";
|
||||
|
||||
int len = input.size();
|
||||
Scanner scanner(input.data(), len, Option::ScannerType, fileName, true);
|
||||
Scanner scanner(input.data(), len, Option::GetScannerType(), fileName, true);
|
||||
Parser parser(scanner, fileName, ar, len);
|
||||
parser.m_lambdaMode = lambdaMode;
|
||||
if (parser.parse()) {
|
||||
@@ -209,10 +209,6 @@ bool Parser::enableXHP() {
|
||||
return Option::EnableXHP;
|
||||
}
|
||||
|
||||
bool Parser::enableHipHopSyntax() {
|
||||
return Option::EnableHipHopSyntax;
|
||||
}
|
||||
|
||||
bool Parser::enableFinallyStatement() {
|
||||
return Option::EnableFinallyStatement;
|
||||
}
|
||||
@@ -686,7 +682,7 @@ void Parser::onQOp(Token &out, Token &exprCond, Token *expYes, Token &expNo) {
|
||||
}
|
||||
|
||||
void Parser::onArray(Token &out, Token &pairs, int op /* = T_ARRAY */) {
|
||||
if (op != T_ARRAY && !Option::EnableHipHopSyntax) {
|
||||
if (op != T_ARRAY && !m_scanner.hipHopSyntaxEnabled()) {
|
||||
PARSE_ERROR("Typed collection is not enabled");
|
||||
return;
|
||||
}
|
||||
@@ -922,16 +918,18 @@ void Parser::onParam(Token &out, Token *params, Token &type, Token &var,
|
||||
attrList = dynamic_pointer_cast<ExpressionList>(attr->exp);
|
||||
}
|
||||
TypeAnnotationPtr typeAnnotation = type.typeAnnotation;
|
||||
expList->addElement(NEW_EXP(ParameterExpression, typeAnnotation, var->text(),
|
||||
expList->addElement(NEW_EXP(ParameterExpression, typeAnnotation,
|
||||
m_scanner.hipHopSyntaxEnabled(), var->text(),
|
||||
ref, defValue ? defValue->exp : ExpressionPtr(),
|
||||
attrList));
|
||||
out->exp = expList;
|
||||
}
|
||||
|
||||
void Parser::onClassStart(int type, Token &name) {
|
||||
const Type::TypePtrMap& typeHintTypes =
|
||||
Type::GetTypeHintTypes(m_scanner.hipHopSyntaxEnabled());
|
||||
if (name.text() == "self" || name.text() == "parent" ||
|
||||
Type::GetTypeHintTypes().find(name.text()) !=
|
||||
Type::GetTypeHintTypes().end()) {
|
||||
typeHintTypes.find(name.text()) != typeHintTypes.end()) {
|
||||
PARSE_ERROR("Cannot use '%s' as class name as it is reserved",
|
||||
name.text().c_str());
|
||||
}
|
||||
@@ -1589,8 +1587,8 @@ void Parser::onClosureParam(Token &out, Token *params, Token ¶m,
|
||||
expList = NEW_EXP0(ExpressionList);
|
||||
}
|
||||
expList->addElement(NEW_EXP(ParameterExpression, TypeAnnotationPtr(),
|
||||
param->text(), ref,
|
||||
ExpressionPtr(), ExpressionPtr()));
|
||||
m_scanner.hipHopSyntaxEnabled(), param->text(),
|
||||
ref, ExpressionPtr(), ExpressionPtr()));
|
||||
out->exp = expList;
|
||||
}
|
||||
|
||||
@@ -1778,7 +1776,7 @@ TStatementPtr Parser::extractStatement(ScannerToken *stmt) {
|
||||
|
||||
bool Parser::hasType(Token &type) {
|
||||
if (!type.text().empty()) {
|
||||
if (!Option::EnableHipHopSyntax && !m_scanner.isHackMode()) {
|
||||
if (!m_scanner.hipHopSyntaxEnabled()) {
|
||||
PARSE_ERROR("Type hint is not enabled");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -113,7 +113,6 @@ public:
|
||||
bool parse();
|
||||
virtual void error(const char* fmt, ...);
|
||||
virtual bool enableXHP();
|
||||
virtual bool enableHipHopSyntax();
|
||||
virtual bool enableFinallyStatement();
|
||||
IMPLEMENT_XHP_ATTRIBUTES;
|
||||
|
||||
|
||||
@@ -366,11 +366,18 @@ bool RuntimeOption::EnableEmitSwitch = true;
|
||||
bool RuntimeOption::EnableEmitterStats = true;
|
||||
bool RuntimeOption::EnableInstructionCounts = false;
|
||||
bool RuntimeOption::CheckSymLink = false;
|
||||
int RuntimeOption::ScannerType = 0;
|
||||
int RuntimeOption::MaxUserFunctionId = (2 * 65536);
|
||||
bool RuntimeOption::EnableFinallyStatement = false;
|
||||
bool RuntimeOption::EnableArgsInBacktraces = true;
|
||||
|
||||
int RuntimeOption::GetScannerType() {
|
||||
int type = 0;
|
||||
if (EnableHipHopSyntax) type |= Scanner::AllowHipHopSyntax;
|
||||
if (EnableShortTags) type |= Scanner::AllowShortTags;
|
||||
if (EnableAspTags) type |= Scanner::AllowAspTags;
|
||||
return type;
|
||||
}
|
||||
|
||||
// Initializers for Eval flags.
|
||||
static inline bool evalJitDefault() {
|
||||
// --mode server or --mode daemon
|
||||
@@ -1114,13 +1121,6 @@ void RuntimeOption::Load(Hdf &config, StringVec *overwrites /* = NULL */,
|
||||
MaxUserFunctionId = eval["MaxUserFunctionId"].getInt32(2 * 65536);
|
||||
CheckSymLink = eval["CheckSymLink"].getBool(false);
|
||||
|
||||
if (EnableHipHopSyntax) ScannerType |= Scanner::EnableHipHopKeywords;
|
||||
else ScannerType &= ~Scanner::EnableHipHopKeywords;
|
||||
if (EnableShortTags) ScannerType |= Scanner::AllowShortTags;
|
||||
else ScannerType &= ~Scanner::AllowShortTags;
|
||||
if (EnableAspTags) ScannerType |= Scanner::AllowAspTags;
|
||||
else ScannerType &= ~Scanner::AllowAspTags;
|
||||
|
||||
EnableAlternative = eval["EnableAlternative"].getInt32(0);
|
||||
|
||||
EnableFinallyStatement = eval["EnableFinallyStatement"].getBool();
|
||||
|
||||
@@ -369,11 +369,12 @@ public:
|
||||
static bool EnableEmitterStats;
|
||||
static bool EnableInstructionCounts;
|
||||
static bool CheckSymLink;
|
||||
static int ScannerType;
|
||||
static int MaxUserFunctionId;
|
||||
static bool EnableFinallyStatement;
|
||||
static bool EnableArgsInBacktraces;
|
||||
|
||||
static int GetScannerType();
|
||||
|
||||
static std::set<std::string, stdltistr> DynamicInvokeFunctions;
|
||||
|
||||
#define EVALFLAGS() \
|
||||
|
||||
@@ -303,7 +303,7 @@ Array f_sys_getloadavg() {
|
||||
|
||||
Array f_token_get_all(CStrRef source) {
|
||||
Scanner scanner(source.data(), source.size(),
|
||||
Scanner::AllowShortTags | Scanner::ReturnAllTokens);
|
||||
RuntimeOption::GetScannerType() | Scanner::ReturnAllTokens);
|
||||
ScannerToken tok;
|
||||
Location loc;
|
||||
int tokid;
|
||||
|
||||
@@ -49,22 +49,21 @@ struct Func {
|
||||
|
||||
template<class SerDe>
|
||||
void serde(SerDe& sd) {
|
||||
const StringData* tcName = m_typeConstraint.typeName();
|
||||
bool tcNullable = m_typeConstraint.nullable();
|
||||
const StringData* tcName = m_typeConstraint.typeName();
|
||||
TypeConstraint::Flags tcFlags = m_typeConstraint.flags();
|
||||
|
||||
sd(m_builtinType)
|
||||
(m_funcletOff)
|
||||
(m_defVal)
|
||||
(m_phpCode)
|
||||
(tcName)
|
||||
(tcNullable)
|
||||
(tcFlags)
|
||||
(m_userAttributes)
|
||||
(m_userType)
|
||||
;
|
||||
|
||||
if (SerDe::deserializing) {
|
||||
setTypeConstraint(TypeConstraint(tcName,
|
||||
tcNullable));
|
||||
setTypeConstraint(TypeConstraint(tcName, tcFlags));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,9 +32,9 @@ TRACE_SET_MOD(runtime);
|
||||
|
||||
TypeConstraint::TypeMap TypeConstraint::s_typeNamesToTypes;
|
||||
|
||||
TypeConstraint::TypeConstraint(const StringData* typeName /* = NULL */,
|
||||
bool nullable /* = false */)
|
||||
: m_nullable(nullable), m_typeName(typeName), m_namedEntity(0) {
|
||||
void TypeConstraint::init() {
|
||||
const StringData* typeName = m_typeName;
|
||||
|
||||
if (UNLIKELY(s_typeNamesToTypes.empty())) {
|
||||
const struct Pair {
|
||||
const StringData* name;
|
||||
@@ -71,7 +71,7 @@ TypeConstraint::TypeConstraint(const StringData* typeName /* = NULL */,
|
||||
|
||||
Type dtype;
|
||||
TRACE(5, "TypeConstraint: this %p type %s, nullable %d\n",
|
||||
this, typeName->data(), nullable);
|
||||
this, typeName->data(), nullable());
|
||||
if (!mapGet(s_typeNamesToTypes, typeName, &dtype)) {
|
||||
TRACE(5, "TypeConstraint: this %p no such type %s, treating as object\n",
|
||||
this, typeName->data());
|
||||
@@ -80,8 +80,8 @@ TypeConstraint::TypeConstraint(const StringData* typeName /* = NULL */,
|
||||
TRACE(5, "TypeConstraint: NamedEntity: %p\n", m_namedEntity);
|
||||
return;
|
||||
}
|
||||
if (RuntimeOption::EnableHipHopSyntax || dtype.m_dt == KindOfArray ||
|
||||
dtype.isParent() || dtype.isSelf()) {
|
||||
if (hhType() || dtype.m_dt == KindOfArray || dtype.isParent() ||
|
||||
dtype.isSelf()) {
|
||||
m_type = dtype;
|
||||
} else {
|
||||
m_type = { KindOfObject, Precise };
|
||||
@@ -140,7 +140,7 @@ TypeConstraint::check(const TypedValue* tv, const Func* func) const {
|
||||
if (tv->m_type == KindOfRef) {
|
||||
tv = tv->m_data.pref->tv();
|
||||
}
|
||||
if (m_nullable && IS_NULL_TYPE(tv->m_type)) return true;
|
||||
if (nullable() && IS_NULL_TYPE(tv->m_type)) return true;
|
||||
|
||||
if (tv->m_type == KindOfObject) {
|
||||
if (!isObjectOrTypedef()) return false;
|
||||
@@ -185,7 +185,7 @@ bool
|
||||
TypeConstraint::checkPrimitive(DataType dt) const {
|
||||
assert(m_type.m_dt != KindOfObject);
|
||||
assert(dt != KindOfRef);
|
||||
if (m_nullable && IS_NULL_TYPE(dt)) return true;
|
||||
if (nullable() && IS_NULL_TYPE(dt)) return true;
|
||||
return equivDataTypes(m_type.m_dt, dt);
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,13 @@ namespace VM {
|
||||
class Func;
|
||||
|
||||
class TypeConstraint {
|
||||
public:
|
||||
enum Flags {
|
||||
NoFlags = 0x0,
|
||||
Nullable = 0x1,
|
||||
HHType = 0x2
|
||||
};
|
||||
|
||||
protected:
|
||||
enum MetaType {
|
||||
Precise,
|
||||
@@ -57,24 +64,39 @@ protected:
|
||||
// when this is set to KindOfObject we may have to look up a typedef
|
||||
// name and test for a different DataType.
|
||||
Type m_type;
|
||||
bool m_nullable;
|
||||
Flags m_flags;
|
||||
const StringData* m_typeName;
|
||||
const NamedEntity* m_namedEntity;
|
||||
typedef hphp_hash_map<const StringData*, Type,
|
||||
string_data_hash, string_data_isame> TypeMap;
|
||||
static TypeMap s_typeNamesToTypes;
|
||||
|
||||
void init();
|
||||
|
||||
public:
|
||||
void verifyFail(const Func* func, int paramNum, const TypedValue* tv) const;
|
||||
|
||||
explicit TypeConstraint(const StringData* typeName=nullptr, bool nullable=false);
|
||||
explicit TypeConstraint(const StringData* typeName, Flags flags)
|
||||
: m_flags(flags), m_typeName(typeName), m_namedEntity(0) {
|
||||
init();
|
||||
}
|
||||
|
||||
explicit TypeConstraint(const StringData* typeName = nullptr,
|
||||
bool nullable = false, bool hhType = false)
|
||||
: m_flags(NoFlags), m_typeName(typeName), m_namedEntity(0) {
|
||||
if (nullable) m_flags = (Flags)(m_flags | Nullable);
|
||||
if (hhType) m_flags = (Flags)(m_flags | HHType);
|
||||
init();
|
||||
}
|
||||
|
||||
bool exists() const { return m_typeName; }
|
||||
|
||||
const StringData* typeName() const { return m_typeName; }
|
||||
const NamedEntity* namedEntity() const { return m_namedEntity; }
|
||||
|
||||
bool nullable() const { return m_nullable; }
|
||||
bool nullable() const { return m_flags & Nullable; }
|
||||
bool hhType() const { return m_flags & HHType; }
|
||||
Flags flags() const { return m_flags; }
|
||||
|
||||
bool isSelf() const {
|
||||
return m_type.isSelf();
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
<?php
|
||||
function foo(Vector<int> $a) {}
|
||||
function bar(string $x) { echo $x . "\n"; }
|
||||
bar("Done");
|
||||
@@ -0,0 +1 @@
|
||||
Done
|
||||
@@ -0,0 +1 @@
|
||||
-vEnableHipHopSyntax=1
|
||||
@@ -0,0 +1 @@
|
||||
-vEval.EnableHipHopSyntax=1
|
||||
@@ -0,0 +1,4 @@
|
||||
<?hh
|
||||
function foo(Vector<int> $a) {}
|
||||
function bar(string $x) { echo $x . "\n"; }
|
||||
bar("Done");
|
||||
@@ -0,0 +1 @@
|
||||
Done
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
eval(<<<'EOD'
|
||||
function foo(Vector<int> $a) {}
|
||||
function bar(string $x) { echo $x . "\n"; }
|
||||
bar("Done");
|
||||
EOD
|
||||
);
|
||||
@@ -0,0 +1 @@
|
||||
Done
|
||||
@@ -0,0 +1 @@
|
||||
-vEnableHipHopSyntax=1
|
||||
@@ -0,0 +1 @@
|
||||
-vEval.EnableHipHopSyntax=1
|
||||
@@ -387,9 +387,6 @@ bool TestParserExpr::TestClosure() {
|
||||
}
|
||||
|
||||
bool TestParserExpr::TestXHP() {
|
||||
//HPHP::Option::ScannerType |= HPHP::Scanner::PreprocessXHP;
|
||||
//HPHP::RuntimeOption::ScannerType |= HPHP::Scanner::PreprocessXHP;
|
||||
|
||||
// basics
|
||||
V("<?php $x = <thing />;",
|
||||
"$x = new xhp_thing(array(), array());\n");
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
#define HH_ONLY_KEYWORD(tok) do { \
|
||||
SETTOKEN; \
|
||||
return _scanner->hipHopKeywordsEnabled() ? tok : T_STRING; \
|
||||
return _scanner->hipHopSyntaxEnabled() ? tok : T_STRING; \
|
||||
} while (0)
|
||||
|
||||
#define IS_LABEL_START(c) \
|
||||
@@ -435,7 +435,7 @@ BACKQUOTE_CHARS ("{"*([^$`\\{]|("\\"{ANY_CHAR}))|{BACKQUOTE_LITERAL_DOLLAR})
|
||||
}
|
||||
yyless(1);
|
||||
STEPPOS;
|
||||
if (_scanner->isHackMode() && (ntt & NextTokenType::TypeListMaybe)) {
|
||||
if (_scanner->hipHopSyntaxEnabled() && (ntt & NextTokenType::TypeListMaybe)) {
|
||||
// Return T_UNRESOLVED_LT; the scanner will inspect subseqent tokens
|
||||
// to resolve this.
|
||||
return T_UNRESOLVED_LT;
|
||||
@@ -445,7 +445,7 @@ BACKQUOTE_CHARS ("{"*([^$`\\{]|("\\"{ANY_CHAR}))|{BACKQUOTE_LITERAL_DOLLAR})
|
||||
|
||||
<ST_IN_SCRIPTING>"<" {
|
||||
STEPPOS;
|
||||
if (_scanner->isHackMode()) {
|
||||
if (_scanner->hipHopSyntaxEnabled()) {
|
||||
int ntt = getNextTokenType(_scanner->lastToken());
|
||||
if (ntt & NextTokenType::TypeListMaybe) {
|
||||
// Return T_UNRESOLVED_LT; the scanner will inspect subseqent tokens
|
||||
|
||||
+23
-30
@@ -248,7 +248,7 @@ void create_generator(Parser *_p, Token &out, Token ¶ms,
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void user_attribute_check(Parser *_p) {
|
||||
if (!_p->enableHipHopSyntax()) {
|
||||
if (!_p->scanner().hipHopSyntaxEnabled()) {
|
||||
HPHP_PARSER_ERROR("User attributes are not enabled", _p);
|
||||
}
|
||||
}
|
||||
@@ -646,17 +646,10 @@ static void xhp_children_stmt(Parser *_p, Token &out, Token &children) {
|
||||
}
|
||||
}
|
||||
|
||||
/* This is called from hack productions (hh_*) to throw an
|
||||
* error if we're not in hack mode */
|
||||
static void only_in_hack_mode(Parser *_p) {
|
||||
if (!_p->scanner().isHackMode()) {
|
||||
HPHP_PARSER_ERROR("Syntax only allowed in hack mode", _p);
|
||||
}
|
||||
}
|
||||
|
||||
static void only_in_hphp_syntax(Parser *_p) {
|
||||
if (!_p->enableHipHopSyntax()) {
|
||||
HPHP_PARSER_ERROR("Syntax only allowed with -v Eval.EnableHipHopSyntax=true", _p);
|
||||
static void only_in_hh_syntax(Parser *_p) {
|
||||
if (!_p->scanner().hipHopSyntaxEnabled()) {
|
||||
HPHP_PARSER_ERROR(
|
||||
"Syntax only allowed with -v Eval.EnableHipHopSyntax=true", _p);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1238,10 +1231,10 @@ new_else_single:
|
||||
|
||||
parameter_list:
|
||||
non_empty_parameter_list ',' T_VARARG
|
||||
{ only_in_hack_mode(_p); $$ = $1; }
|
||||
{ only_in_hh_syntax(_p); $$ = $1; }
|
||||
| non_empty_parameter_list
|
||||
possible_comma_in_hphp_syntax { $$ = $1;}
|
||||
| T_VARARG { only_in_hack_mode(_p); $$.reset(); }
|
||||
| T_VARARG { only_in_hh_syntax(_p); $$.reset(); }
|
||||
| { $$.reset();}
|
||||
;
|
||||
|
||||
@@ -1680,7 +1673,7 @@ static_shape_pair_list:
|
||||
;
|
||||
|
||||
shape_literal:
|
||||
T_SHAPE '(' shape_pair_list ')' { only_in_hack_mode(_p);
|
||||
T_SHAPE '(' shape_pair_list ')' { only_in_hh_syntax(_p);
|
||||
_p->onArray($$, $3, T_ARRAY); }
|
||||
;
|
||||
|
||||
@@ -1939,7 +1932,7 @@ static_scalar:
|
||||
| T_ARRAY '('
|
||||
static_array_pair_list ')' { _p->onArray($$,$3,T_ARRAY); }
|
||||
| T_SHAPE '('
|
||||
static_shape_pair_list ')' { only_in_hack_mode(_p);
|
||||
static_shape_pair_list ')' { only_in_hh_syntax(_p);
|
||||
_p->onArray($$,$3,T_ARRAY); }
|
||||
| static_class_constant { $$ = $1;}
|
||||
| static_collection_literal { $$ = $1;}
|
||||
@@ -1976,7 +1969,7 @@ possible_comma:
|
||||
| { $$.reset();}
|
||||
;
|
||||
possible_comma_in_hphp_syntax:
|
||||
',' { only_in_hphp_syntax(_p); $$.reset();}
|
||||
',' { only_in_hh_syntax(_p); $$.reset();}
|
||||
| { $$.reset();}
|
||||
;
|
||||
|
||||
@@ -2016,7 +2009,7 @@ static_scalar_ae:
|
||||
static_array_pair_list_ae ')' { _p->onArray($$,$3,T_ARRAY);}
|
||||
| '[' static_array_pair_list_ae ']' { _p->onArray($$,$2,T_ARRAY);}
|
||||
| T_SHAPE '('
|
||||
static_shape_pair_list_ae ')' { only_in_hack_mode(_p);
|
||||
static_shape_pair_list_ae ')' { only_in_hh_syntax(_p);
|
||||
_p->onArray($$,$3,T_ARRAY); }
|
||||
;
|
||||
|
||||
@@ -2342,14 +2335,14 @@ class_constant:
|
||||
|
||||
hh_typedef_statement:
|
||||
T_TYPE hh_name_with_typevar
|
||||
'=' hh_type ';' { only_in_hack_mode(_p);
|
||||
'=' hh_type ';' { only_in_hh_syntax(_p);
|
||||
_p->onTypedef($$, $2, $4);
|
||||
_p->popTypeScope(); }
|
||||
;
|
||||
|
||||
hh_name_with_type: /* foo -> int foo */
|
||||
ident { $$ = $1; }
|
||||
| hh_type ident { only_in_hack_mode(_p); $$ = $2; }
|
||||
| hh_type ident { only_in_hh_syntax(_p); $$ = $2; }
|
||||
;
|
||||
|
||||
hh_name_with_typevar: /* foo -> foo<X,Y>; this adds a typevar scope
|
||||
@@ -2360,13 +2353,13 @@ hh_name_with_typevar: /* foo -> foo<X,Y>; this adds a typevar scope
|
||||
T_TYPELIST_LT
|
||||
hh_typevar_list
|
||||
T_TYPELIST_GT { _p->pushTypeScope(); $$ = $1;
|
||||
only_in_hack_mode(_p); }
|
||||
only_in_hh_syntax(_p); }
|
||||
;
|
||||
|
||||
hh_typeargs_opt:
|
||||
T_TYPELIST_LT
|
||||
hh_type_list
|
||||
T_TYPELIST_GT { only_in_hack_mode(_p); $$ = $2; }
|
||||
T_TYPELIST_GT { only_in_hh_syntax(_p); $$ = $2; }
|
||||
| { $$.reset(); }
|
||||
;
|
||||
|
||||
@@ -2387,7 +2380,7 @@ hh_func_type_list:
|
||||
|
||||
hh_opt_return_type:
|
||||
{ $$.reset(); }
|
||||
| ':' hh_type { only_in_hack_mode(_p); $$ = $2; }
|
||||
| ':' hh_type { only_in_hh_syntax(_p); $$ = $2; }
|
||||
;
|
||||
|
||||
hh_typevar_list:
|
||||
@@ -2425,7 +2418,7 @@ hh_shape_member_list:
|
||||
|
||||
hh_shape_type:
|
||||
T_SHAPE
|
||||
'(' hh_shape_member_list ')' { only_in_hack_mode(_p);
|
||||
'(' hh_shape_member_list ')' { only_in_hh_syntax(_p);
|
||||
$$.setText("array"); }
|
||||
;
|
||||
|
||||
@@ -2433,10 +2426,10 @@ hh_shape_type:
|
||||
hh_type:
|
||||
/* double-optional types will be rejected by the typechecker; we
|
||||
* already allow plenty of nonsense types anyway */
|
||||
'?' hh_type { only_in_hack_mode(_p);
|
||||
'?' hh_type { only_in_hh_syntax(_p);
|
||||
_p->onTypeSpecialization($2, '?');
|
||||
$$ = $2; }
|
||||
| '@' hh_type { only_in_hack_mode(_p);
|
||||
| '@' hh_type { only_in_hh_syntax(_p);
|
||||
_p->onTypeSpecialization($2, '@');
|
||||
$$ = $2; }
|
||||
| namespace_string hh_typeargs_opt { _p->onTypeAnnotation($$, $1, $2); }
|
||||
@@ -2445,11 +2438,11 @@ hh_type:
|
||||
_p->onTypeAnnotation($$, $1, t); }
|
||||
| hh_shape_type { $$ = $1; }
|
||||
| T_ARRAY T_TYPELIST_LT hh_type
|
||||
T_TYPELIST_GT { only_in_hack_mode(_p);
|
||||
T_TYPELIST_GT { only_in_hh_syntax(_p);
|
||||
$1.setText("array");
|
||||
_p->onTypeAnnotation($$, $1, $3); }
|
||||
| T_ARRAY T_TYPELIST_LT hh_type ','
|
||||
hh_type T_TYPELIST_GT { only_in_hack_mode(_p);
|
||||
hh_type T_TYPELIST_GT { only_in_hh_syntax(_p);
|
||||
_p->onTypeList($3, $5);
|
||||
$1.setText("array");
|
||||
_p->onTypeAnnotation($$, $1, $3); }
|
||||
@@ -2459,11 +2452,11 @@ hh_type:
|
||||
_p->onTypeSpecialization($$, 'x'); }
|
||||
| '(' T_FUNCTION
|
||||
'(' hh_func_type_list ')'
|
||||
':' hh_type ')' { only_in_hack_mode(_p);
|
||||
':' hh_type ')' { only_in_hh_syntax(_p);
|
||||
_p->onTypeList($7, $4);
|
||||
_p->onTypeAnnotation($$, $2, $7);
|
||||
_p->onTypeSpecialization($$, 'f'); }
|
||||
| '(' hh_type_list ',' hh_type ')' { only_in_hack_mode(_p);
|
||||
| '(' hh_type_list ',' hh_type ')' { only_in_hh_syntax(_p);
|
||||
_p->onTypeList($2, $4);
|
||||
Token t; t.reset(); t.setText("array");
|
||||
_p->onTypeAnnotation($$, t, $2);
|
||||
|
||||
@@ -77821,7 +77821,7 @@ static yyconst yy_state_type yy_NUL_trans[2432] =
|
||||
|
||||
#define HH_ONLY_KEYWORD(tok) do { \
|
||||
SETTOKEN; \
|
||||
return _scanner->hipHopKeywordsEnabled() ? tok : T_STRING; \
|
||||
return _scanner->hipHopSyntaxEnabled() ? tok : T_STRING; \
|
||||
} while (0)
|
||||
|
||||
#define IS_LABEL_START(c) \
|
||||
@@ -78974,7 +78974,7 @@ YY_RULE_SETUP
|
||||
}
|
||||
yyless(1);
|
||||
STEPPOS;
|
||||
if (_scanner->isHackMode() && (ntt & NextTokenType::TypeListMaybe)) {
|
||||
if (_scanner->hipHopSyntaxEnabled() && (ntt & NextTokenType::TypeListMaybe)) {
|
||||
// Return T_UNRESOLVED_LT; the scanner will inspect subseqent tokens
|
||||
// to resolve this.
|
||||
return T_UNRESOLVED_LT;
|
||||
@@ -78987,7 +78987,7 @@ YY_RULE_SETUP
|
||||
#line 446 "hphp.ll"
|
||||
{
|
||||
STEPPOS;
|
||||
if (_scanner->isHackMode()) {
|
||||
if (_scanner->hipHopSyntaxEnabled()) {
|
||||
int ntt = getNextTokenType(_scanner->lastToken());
|
||||
if (ntt & NextTokenType::TypeListMaybe) {
|
||||
// Return T_UNRESOLVED_LT; the scanner will inspect subseqent tokens
|
||||
|
||||
@@ -113,11 +113,6 @@ public:
|
||||
*/
|
||||
virtual bool enableXHP() = 0;
|
||||
|
||||
/**
|
||||
* Check if HipHop syntax is enabled.
|
||||
*/
|
||||
virtual bool enableHipHopSyntax() = 0;
|
||||
|
||||
/**
|
||||
* Public accessors.
|
||||
*/
|
||||
|
||||
@@ -171,7 +171,7 @@ public:
|
||||
AllowShortTags = 0x01, // allow <?
|
||||
AllowAspTags = 0x02, // allow <% %>
|
||||
ReturnAllTokens = 0x08, // return comments and whitespaces
|
||||
EnableHipHopKeywords = 0x10, // allow hip-hop specific reserved words
|
||||
AllowHipHopSyntax = 0x10, // allow hip-hop specific reserved words
|
||||
};
|
||||
|
||||
public:
|
||||
@@ -285,11 +285,8 @@ public:
|
||||
return m_isHackMode;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns: whether HipHop-extension keywords are enabled.
|
||||
*/
|
||||
bool hipHopKeywordsEnabled() const {
|
||||
return m_type & EnableHipHopKeywords;
|
||||
bool hipHopSyntaxEnabled() const {
|
||||
return (m_type & AllowHipHopSyntax) || m_isHackMode;
|
||||
}
|
||||
|
||||
int getLookaheadLtDepth() {
|
||||
|
||||
@@ -56,7 +56,7 @@ int main(int argc, char** argv) try {
|
||||
using HPHP::Scanner;
|
||||
using HPHP::Test::Parser;
|
||||
Scanner scan(in, Scanner::AllowShortTags |
|
||||
Scanner::EnableHipHopKeywords);
|
||||
Scanner::AllowHipHopSyntax);
|
||||
Parser parser(scan, argv[1]);
|
||||
parser.parse();
|
||||
} catch (const std::exception& e) {
|
||||
|
||||
@@ -139,7 +139,6 @@ struct Parser : ParserBase {
|
||||
void* extractStatement(ScannerToken*) { X(); return nullptr; }
|
||||
|
||||
bool enableFinallyStatement() { return true; }
|
||||
bool enableHipHopSyntax() { return true; }
|
||||
bool enableXHP() { return true; }
|
||||
|
||||
IMPLEMENT_XHP_ATTRIBUTES;
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário