Fix __HALT_COMPILER() support

Actually halt the compiler, and set __COMPILER_HALT_OFFSET__ constant
Esse commit está contido em:
Sara Golemon
2013-04-30 16:03:41 -07:00
commit 38f9fab773
23 arquivos alterados com 58090 adições e 57175 exclusões
+14 -4
Ver Arquivo
@@ -528,6 +528,9 @@ interface JsonSerializable {
interface Traversable {
}
interface KeyedTraversable extends Traversable {
}
// Do NOT modifiy this doc comment block generated by idl/sysdoc.php
/**
* ( excerpt from http://php.net/manual/en/class.iterator.php )
@@ -592,7 +595,7 @@ interface Iterator extends Traversable {
public function valid();
}
interface KeyedIterator extends Iterator {
interface KeyedIterator extends Iterator, KeyedTraversable {
}
// Do NOT modifiy this doc comment block generated by idl/sysdoc.php
@@ -1217,7 +1220,7 @@ interface IteratorAggregate extends Traversable {
interface Iterable extends IteratorAggregate {
}
interface KeyedIterable extends Iterable {
interface KeyedIterable extends Iterable, KeyedTraversable {
}
///////////////////////////////////////////////////////////////////////////////
@@ -3813,6 +3816,13 @@ class ReflectionParameter implements Reflector {
return '';
}
public function getTypeText() {
if (isset($this->info['type_hint'])) {
return $this->info['type_hint'];
}
return '';
}
// Do NOT modifiy this doc comment block generated by idl/sysdoc.php
/**
* ( excerpt from http://php.net/manual/en/reflectionparameter.isarray.php
@@ -4180,7 +4190,7 @@ class ReflectionFunctionAbstract {
return $count;
}
public function getReturnTypehintText() {
public function getReturnTypeText() {
if (isset($this->info['return_type'])) {
return $this->info['return_type'];
}
@@ -5422,7 +5432,7 @@ class ReflectionProperty implements Reflector {
return $this->info['doc'];
}
public function getTypehintText() {
public function getTypeText() {
if (isset($this->info['type'])) {
return $this->info['type'];
}
+12 -2
Ver Arquivo
@@ -243,6 +243,7 @@ TypePtr ScalarExpression::inferenceImpl(AnalysisResultConstPtr ar,
break;
case T_LINE:
case T_COMPILER_HALT_OFFSET:
actualType = Type::Int64;
break;
@@ -393,6 +394,7 @@ void ScalarExpression::outputPHP(CodeGenerator &cg, AnalysisResultPtr ar) {
case T_NUM_STRING:
case T_LNUMBER:
case T_DNUMBER:
case T_COMPILER_HALT_OFFSET:
cg_printf("%s", m_originalValue.c_str());
break;
case T_NS_C:
@@ -450,6 +452,7 @@ Variant ScalarExpression::getVariant() const {
case T_NUM_STRING:
return String(m_value);
case T_LNUMBER:
case T_COMPILER_HALT_OFFSET:
return strtoll(m_value.c_str(), nullptr, 0);
case T_LINE:
return String(m_translated).toInt64();
@@ -488,14 +491,13 @@ bool ScalarExpression::getString(const std::string *&s) const {
}
bool ScalarExpression::getInt(int64_t &i) const {
if (m_type == T_LNUMBER) {
if (m_type == T_LNUMBER || m_type == T_COMPILER_HALT_OFFSET) {
i = strtoll(m_value.c_str(), nullptr, 0);
return true;
} else if (m_type == T_LINE) {
i = getLocation() ? getLocation()->line1 : 0;
return true;
}
return false;
}
@@ -508,3 +510,11 @@ bool ScalarExpression::getDouble(double &d) const {
}
return false;
}
void ScalarExpression::setCompilerHaltOffset(int64_t ofs) {
assert(m_type == T_COMPILER_HALT_OFFSET);
std::ostringstream ss;
ss << ofs;
m_value = ss.str();
m_originalValue = ss.str();
}
@@ -76,6 +76,8 @@ public:
bool getString(const std::string *&s) const;
bool getInt(int64_t &i) const;
bool getDouble(double &d) const;
void setCompilerHaltOffset(int64_t ofs);
private:
int m_type;
std::string m_serializedValue;
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+32 -9
Ver Arquivo
@@ -529,6 +529,7 @@ void Parser::onScalar(Token &out, int type, Token &scalar) {
case T_LNUMBER:
case T_DNUMBER:
case T_LINE:
case T_COMPILER_HALT_OFFSET:
case T_FUNC_C:
case T_CLASS_C:
exp = NEW_EXP(ScalarExpression, type, scalar->text());
@@ -546,6 +547,12 @@ void Parser::onScalar(Token &out, int type, Token &scalar) {
default:
assert(false);
}
if (type == T_COMPILER_HALT_OFFSET) {
// Keep track of this expression for later backpatching
// If it doesn't get backpatched (because there was no HALT_COMPILER
// then the constant will return (int)"__COMPILER_HALT_OFFSET__" (zero)
m_compilerHaltOffsetVec.push_back(exp);
}
out->exp = exp;
}
@@ -1190,13 +1197,11 @@ void Parser::onMemberModifier(Token &out, Token *modifiers, Token &modifier) {
///////////////////////////////////////////////////////////////////////////////
// statements
void Parser::saveParseTree(Token &tree) {
if (tree->stmt) {
m_tree = dynamic_pointer_cast<StatementList>(tree->stmt);
} else {
m_tree = NEW_STMT0(StatementList);
}
void Parser::initParseTree() {
m_tree = NEW_STMT0(StatementList);
}
void Parser::finiParseTree() {
if (m_staticVars.size()) fixStaticVars();
FunctionScopePtr pseudoMain = m_file->setTree(m_ar, m_tree);
completeScope(pseudoMain);
@@ -1208,28 +1213,46 @@ void Parser::saveParseTree(Token &tree) {
pseudoMain->getStmt()->setLocation(loc);
}
void Parser::onHaltCompiler() {
if (m_nsState == InsideNamespace && !m_nsFileScope) {
error("__HALT_COMPILER() can only be used from the outermost scope");
return;
}
// Backpatch instances of __COMPILER_HALT_OFFSET__
for(auto &cho : m_compilerHaltOffsetVec) {
cho->setCompilerHaltOffset(m_scanner.getLocation()->cursor);
}
}
void Parser::onStatementListStart(Token &out) {
out.reset();
}
void Parser::addTopStatement(Token &new_stmt) {
addStatement(m_tree, new_stmt->stmt);
}
void Parser::addStatement(Token &out, Token &stmts, Token &new_stmt) {
if (!stmts->stmt) {
out->stmt = NEW_STMT0(StatementList);
} else {
out->stmt = stmts->stmt;
}
addStatement(out->stmt, new_stmt->stmt);
}
void Parser::addStatement(StatementPtr stmt, StatementPtr new_stmt) {
assert(!m_prependingStatements.empty());
vector<StatementPtr> &prepending = m_prependingStatements.back();
if (!prepending.empty()) {
assert(prepending.size() == 1);
for (unsigned i = 0; i < prepending.size(); i++) {
out->stmt->addElement(prepending[i]);
stmt->addElement(prepending[i]);
}
prepending.clear();
}
if (new_stmt->stmt) {
out->stmt->addElement(new_stmt->stmt);
if (new_stmt) {
stmt->addElement(new_stmt);
}
}
+8 -1
Ver Arquivo
@@ -22,6 +22,7 @@
#include "compiler/construct.h"
#include "compiler/option.h"
#include "compiler/type_annotation.h"
#include "compiler/expression/scalar_expression.h"
#ifdef HPHP_PARSER_NS
#undef HPHP_PARSER_NS
@@ -123,7 +124,9 @@ public:
StatementListPtr getTree() const { return m_tree;}
// parser handlers
void saveParseTree(Token &tree);
void initParseTree();
void finiParseTree();
void onHaltCompiler();
void onName(Token &out, Token &name, NameKind kind);
void onVariable(Token &out, Token *exprs, Token &var, Token *value,
bool constant = false,
@@ -202,6 +205,7 @@ public:
void onMemberModifier(Token &out, Token *modifiers, Token &modifier);
void onStatementListStart(Token &out);
void addStatement(Token &out, Token &stmts, Token &new_stmt);
void addTopStatement(Token &new_stmt);
void onClassStatement(Token &out, Token &stmts, Token &new_stmt) {
addStatement(out, stmts, new_stmt);
}
@@ -290,6 +294,7 @@ private:
std::vector<BlockScopePtrVec> m_scopes;
std::vector<FunctionContext> m_funcContexts;
std::vector<std::vector<StatementPtr> > m_prependingStatements;
std::vector<ScalarExpressionPtr> m_compilerHaltOffsetVec;
std::string m_clsName; // for T_CLASS_C inside a closure
std::string m_funcName;
bool m_inTrait;
@@ -318,6 +323,8 @@ private:
bool hasType(Token &type);
void checkAssignThis(Token &var);
void addStatement(StatementPtr stmt, StatementPtr new_stmt);
};
///////////////////////////////////////////////////////////////////////////////
+2 -1
Ver Arquivo
@@ -13,7 +13,6 @@
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
// @generated by idl/class_map.php
#include <runtime/base/base_includes.h>
#include <runtime/ext/ext.h>
namespace HPHP {
@@ -1644,6 +1643,7 @@ const int64_t k_T_CLASS_C = 361;
const int64_t k_T_CLONE = 298;
const int64_t k_T_CLOSE_TAG = 370;
const int64_t k_T_COMMENT = 366;
const int64_t k_T_COMPILER_HALT_OFFSET = 405;
const int64_t k_T_CONCAT_EQUAL = 273;
const int64_t k_T_CONST = 335;
const int64_t k_T_CONSTANT_ENCAPSED_STRING = 315;
@@ -19132,6 +19132,7 @@ const char *g_class_map[] = {
"T_CLONE", (const char*)6, "i:298;",
"T_CLOSE_TAG", (const char*)6, "i:370;",
"T_COMMENT", (const char*)6, "i:366;",
"T_COMPILER_HALT_OFFSET", (const char*)6, "i:405;",
"T_CONCAT_EQUAL", (const char*)6, "i:273;",
"T_CONST", (const char*)6, "i:335;",
"T_CONSTANT_ENCAPSED_STRING", (const char*)6, "i:315;",
+1
Ver Arquivo
@@ -1646,6 +1646,7 @@ extern const int64_t k_T_CLASS_C;
extern const int64_t k_T_CLONE;
extern const int64_t k_T_CLOSE_TAG;
extern const int64_t k_T_COMMENT;
extern const int64_t k_T_COMPILER_HALT_OFFSET;
extern const int64_t k_T_CONCAT_EQUAL;
extern const int64_t k_T_CONST;
extern const int64_t k_T_CONSTANT_ENCAPSED_STRING;
+5 -1
Ver Arquivo
@@ -6509,6 +6509,10 @@
"name": "T_COMMENT",
"value": 366
},
{
"name": "T_COMPILER_HALT_OFFSET",
"value": 405
},
{
"name": "T_CONCAT_EQUAL",
"value": 273
@@ -7986,4 +7990,4 @@
],
"classes": [
]
}
}
+4 -1
Ver Arquivo
@@ -220,8 +220,11 @@ bool TestParserStmt::TestStatementList() {
V("<?php function test() {} ; class Test {} __halt_compiler();",
"function test() {\n}\nclass Test {\n}\n");
V("<?php function test() {} ; __halt_compiler(); function test() {}",
"function test() {\n}\n");
V("<?php ; __halt_compiler(); function test() {} class Test {}",
"function test() {\n}\nclass Test {\n}\n");
"");
return true;
}
+4
Ver Arquivo
@@ -363,6 +363,10 @@ BACKQUOTE_CHARS ("{"*([^$`\\{]|("\\"{ANY_CHAR}))|{BACKQUOTE_LITERAL_DOLLAR})
<ST_IN_SCRIPTING>"isset" { SETTOKEN; return T_ISSET;}
<ST_IN_SCRIPTING>"empty" { SETTOKEN; return T_EMPTY;}
<ST_IN_SCRIPTING>"__halt_compiler" { SETTOKEN; return T_HALT_COMPILER;}
<ST_IN_SCRIPTING>"__compiler_halt_offset__" {
SETTOKEN;
return T_COMPILER_HALT_OFFSET;
}
<ST_IN_SCRIPTING>"static" { SETTOKEN; return T_STATIC;}
<ST_IN_SCRIPTING>"abstract" { SETTOKEN; return T_ABSTRACT;}
<ST_IN_SCRIPTING>"final" { SETTOKEN; return T_FINAL;}
+8 -8
Ver Arquivo
@@ -43,9 +43,6 @@
#define YYTOKEN(num, name) name = num
#endif
YYTOKEN_MAP {
#ifndef YYTOKEN_MIN
#define YYTOKEN_MIN 258
#endif
YYTOKEN(258, T_REQUIRE_ONCE),
YYTOKEN(259, T_REQUIRE),
YYTOKEN(260, T_EVAL),
@@ -192,12 +189,9 @@
YYTOKEN(401, T_COLLECTION),
YYTOKEN(402, T_SHAPE),
YYTOKEN(403, T_TYPE),
YYTOKEN(404, T_UNRESOLVED_TYPE)
YYTOKEN(404, T_UNRESOLVED_TYPE),
YYTOKEN(405, T_COMPILER_HALT_OFFSET)
};
#ifndef YYTOKEN_MAX
#define YYTOKEN_MAX 404
#endif
#endif
@@ -226,3 +220,9 @@ typedef struct YYLTYPE
#ifndef YYTOKEN_MIN
#define YYTOKEN_MIN 258
#endif
#ifndef YYTOKEN_MAX
#define YYTOKEN_MAX 405
#endif
+12 -6
Ver Arquivo
@@ -814,17 +814,19 @@ static int yylex(YYSTYPE *token, HPHP::Location *loc, Parser *_p) {
%token T_TYPE
%token T_UNRESOLVED_TYPE
%token T_COMPILER_HALT_OFFSET
%%
start:
top_statement_list { _p->popLabelInfo();
_p->saveParseTree($$);}
{ _p->initParseTree(); } top_statement_list { _p->popLabelInfo();
_p->finiParseTree();}
;
top_statement_list:
top_statement_list
top_statement { _p->addStatement($$,$1,$2);}
| { _p->onStatementListStart($$);}
top_statement { _p->addTopStatement($2);}
| { }
;
top_statement:
statement { _p->nns($1.num() == T_DECLARE);
@@ -833,8 +835,10 @@ top_statement:
| class_declaration_statement { _p->nns(); $$ = $1;}
| trait_declaration_statement { _p->nns(); $$ = $1;}
| sm_typedef_statement { $$ = $1; }
| T_HALT_COMPILER '(' ')' ';' { $$.reset();}
| T_NAMESPACE namespace_name ';' { _p->onNamespaceStart($2.text());
| T_HALT_COMPILER '(' ')' ';' { _p->onHaltCompiler();
_p->finiParseTree();
YYACCEPT;}
| T_NAMESPACE namespace_name ';' { _p->onNamespaceStart($2.text(), true);
$$.reset();}
| T_NAMESPACE namespace_name '{' { _p->onNamespaceStart($2.text());}
top_statement_list '}' { _p->onNamespaceEnd(); $$ = $5;}
@@ -1859,6 +1863,7 @@ xhp_bareword:
| T_FILE { $$ = $1;}
| T_DIR { $$ = $1;}
| T_NS_C { $$ = $1;}
| T_COMPILER_HALT_OFFSET { $$ = $1;}
| T_TRAIT { $$ = $1;}
| T_TRAIT_C { $$ = $1;}
| T_TYPE { $$ = $1;}
@@ -1915,6 +1920,7 @@ common_scalar:
| T_METHOD_C { _p->onScalar($$, T_METHOD_C, $1);}
| T_FUNC_C { _p->onScalar($$, T_FUNC_C, $1);}
| T_NS_C { _p->onScalar($$, T_NS_C, $1);}
| T_COMPILER_HALT_OFFSET { _p->onScalar($$, T_COMPILER_HALT_OFFSET, $1);}
| T_START_HEREDOC
T_ENCAPSED_AND_WHITESPACE
T_END_HEREDOC { _p->onScalar($$, T_CONSTANT_ENCAPSED_STRING, $2);}
+53438 -52760
Ver Arquivo
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+2 -1
Ver Arquivo
@@ -25,13 +25,14 @@ namespace HPHP {
DECLARE_BOOST_TYPES(Location);
class Location {
public:
Location() : file(""), line0(1), char0(1), line1(1), char1(1) {}
Location() : file(""), line0(1), char0(1), line1(1), char1(1), cursor(0) {}
const char *file;
int line0;
int char0;
int line1;
int char1;
int cursor;
void first(int line, char pos) {
line0 = line; char0 = pos;
+4 -1
Ver Arquivo
@@ -114,6 +114,7 @@ LocationPtr ParserBase::getLocation() const {
location->char0 = char0();
location->line1 = line1();
location->char1 = char1();
location->cursor = cursor();
return location;
}
@@ -297,13 +298,15 @@ void ParserBase::nns(bool declare /* = false */) {
}
}
void ParserBase::onNamespaceStart(const std::string &ns) {
void ParserBase::onNamespaceStart(const std::string &ns,
bool file_scope /* =false */) {
if (m_nsState == SeenNonNamespaceStatement) {
error("Namespace declaration statement has to be the very first "
"statement in the script: %s", getMessage().c_str());
return;
}
m_nsState = InsideNamespace;
m_nsFileScope = file_scope;
m_namespace = ns;
}
+3 -1
Ver Arquivo
@@ -134,6 +134,7 @@ public:
int char0() const { return m_loc.char0;}
int line1() const { return m_loc.line1;}
int char1() const { return m_loc.char1;}
int cursor() const { return m_loc.cursor;}
// called by generated code
int scan(ScannerToken *token, Location *loc) {
@@ -168,7 +169,7 @@ public:
void popLabelInfo();
// for namespace support
void onNamespaceStart(const std::string &ns);
void onNamespaceStart(const std::string &ns, bool file_scope = false);
void onNamespaceEnd();
void onUse(const std::string &ns, const std::string &as);
void nns(bool declare = false);
@@ -235,6 +236,7 @@ protected:
InsideNamespace,
};
NamespaceState m_nsState;
bool m_nsFileScope;
std::string m_namespace; // current namespace
hphp_string_imap<std::string> m_aliases;
+2
Ver Arquivo
@@ -489,6 +489,8 @@ void Scanner::incLoc(const char *rawText, int rawLeng) {
assert(rawText);
assert(rawLeng > 0);
m_loc->cursor += rawLeng;
switch (m_state) {
case Start:
break; // scanner set to (1, 1, 1, 1) already
+5 -1
Ver Arquivo
@@ -144,7 +144,8 @@ struct Parser : ParserBase {
IMPLEMENT_XHP_ATTRIBUTES;
void saveParseTree(Token& tree) { X(); }
void initParseTree() { X(); }
void finiParseTree() { X(); }
void onName(Token& out, Token& name, NameKind kind) {
X(name, kind);
@@ -385,6 +386,9 @@ struct Parser : ParserBase {
void onStatementListStart(Token &out) { X(); }
void addTopStatement(Token &new_stmt) { X(new_stmt); }
void onHaltCompiler() { X(); }
void addStatement(Token& out, Token& stmts, Token& new_stmt) {
X(stmts, new_stmt);
}