Revert "Move ParseUnaryExpression into ParserBase and add tests."
This reverts revision 20077. Reason: build fail on some compilers. BUG= TBR=marja@chromium.org,rossberg@chromium.org Review URL: https://codereview.chromium.org/203413009 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20078 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
f4ef82309a
commit
c04dd3fb7f
161
src/parser.cc
161
src/parser.cc
@ -433,12 +433,6 @@ bool ParserTraits::IsThisProperty(Expression* expression) {
|
||||
}
|
||||
|
||||
|
||||
bool ParserTraits::IsIdentifier(Expression* expression) {
|
||||
VariableProxy* operand = expression->AsVariableProxy();
|
||||
return operand != NULL && !operand->is_this();
|
||||
}
|
||||
|
||||
|
||||
void ParserTraits::CheckAssigningFunctionLiteralToProperty(Expression* left,
|
||||
Expression* right) {
|
||||
ASSERT(left != NULL);
|
||||
@ -531,52 +525,6 @@ bool ParserTraits::ShortcutNumericLiteralBinaryExpression(
|
||||
}
|
||||
|
||||
|
||||
Expression* ParserTraits::BuildUnaryExpression(
|
||||
Expression* expression, Token::Value op, int pos,
|
||||
AstNodeFactory<AstConstructionVisitor>* factory) {
|
||||
ASSERT(expression != NULL);
|
||||
if (expression->AsLiteral() != NULL) {
|
||||
Handle<Object> literal = expression->AsLiteral()->value();
|
||||
if (op == Token::NOT) {
|
||||
// Convert the literal to a boolean condition and negate it.
|
||||
bool condition = literal->BooleanValue();
|
||||
Handle<Object> result =
|
||||
parser_->isolate()->factory()->ToBoolean(!condition);
|
||||
return factory->NewLiteral(result, pos);
|
||||
} else if (literal->IsNumber()) {
|
||||
// Compute some expressions involving only number literals.
|
||||
double value = literal->Number();
|
||||
switch (op) {
|
||||
case Token::ADD:
|
||||
return expression;
|
||||
case Token::SUB:
|
||||
return factory->NewNumberLiteral(-value, pos);
|
||||
case Token::BIT_NOT:
|
||||
return factory->NewNumberLiteral(~DoubleToInt32(value), pos);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Desugar '+foo' => 'foo*1'
|
||||
if (op == Token::ADD) {
|
||||
return factory->NewBinaryOperation(
|
||||
Token::MUL, expression, factory->NewNumberLiteral(1, pos), pos);
|
||||
}
|
||||
// The same idea for '-foo' => 'foo*(-1)'.
|
||||
if (op == Token::SUB) {
|
||||
return factory->NewBinaryOperation(
|
||||
Token::MUL, expression, factory->NewNumberLiteral(-1, pos), pos);
|
||||
}
|
||||
// ...and one more time for '~foo' => 'foo^(~0)'.
|
||||
if (op == Token::BIT_NOT) {
|
||||
return factory->NewBinaryOperation(
|
||||
Token::BIT_XOR, expression, factory->NewNumberLiteral(~0, pos), pos);
|
||||
}
|
||||
return factory->NewUnaryOperation(op, expression, pos);
|
||||
}
|
||||
|
||||
|
||||
void ParserTraits::ReportMessageAt(Scanner::Location source_location,
|
||||
const char* message,
|
||||
Vector<const char*> args,
|
||||
@ -740,8 +688,8 @@ FunctionLiteral* ParserTraits::ParseFunctionLiteral(
|
||||
}
|
||||
|
||||
|
||||
Expression* ParserTraits::ParsePostfixExpression(bool* ok) {
|
||||
return parser_->ParsePostfixExpression(ok);
|
||||
Expression* ParserTraits::ParseUnaryExpression(bool* ok) {
|
||||
return parser_->ParseUnaryExpression(ok);
|
||||
}
|
||||
|
||||
|
||||
@ -3042,6 +2990,111 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
|
||||
}
|
||||
|
||||
|
||||
Expression* Parser::ParseUnaryExpression(bool* ok) {
|
||||
// UnaryExpression ::
|
||||
// PostfixExpression
|
||||
// 'delete' UnaryExpression
|
||||
// 'void' UnaryExpression
|
||||
// 'typeof' UnaryExpression
|
||||
// '++' UnaryExpression
|
||||
// '--' UnaryExpression
|
||||
// '+' UnaryExpression
|
||||
// '-' UnaryExpression
|
||||
// '~' UnaryExpression
|
||||
// '!' UnaryExpression
|
||||
|
||||
Token::Value op = peek();
|
||||
if (Token::IsUnaryOp(op)) {
|
||||
op = Next();
|
||||
int pos = position();
|
||||
Expression* expression = ParseUnaryExpression(CHECK_OK);
|
||||
|
||||
if (expression != NULL && (expression->AsLiteral() != NULL)) {
|
||||
Handle<Object> literal = expression->AsLiteral()->value();
|
||||
if (op == Token::NOT) {
|
||||
// Convert the literal to a boolean condition and negate it.
|
||||
bool condition = literal->BooleanValue();
|
||||
Handle<Object> result = isolate()->factory()->ToBoolean(!condition);
|
||||
return factory()->NewLiteral(result, pos);
|
||||
} else if (literal->IsNumber()) {
|
||||
// Compute some expressions involving only number literals.
|
||||
double value = literal->Number();
|
||||
switch (op) {
|
||||
case Token::ADD:
|
||||
return expression;
|
||||
case Token::SUB:
|
||||
return factory()->NewNumberLiteral(-value, pos);
|
||||
case Token::BIT_NOT:
|
||||
return factory()->NewNumberLiteral(~DoubleToInt32(value), pos);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// "delete identifier" is a syntax error in strict mode.
|
||||
if (op == Token::DELETE && strict_mode() == STRICT) {
|
||||
VariableProxy* operand = expression->AsVariableProxy();
|
||||
if (operand != NULL && !operand->is_this()) {
|
||||
ReportMessage("strict_delete", Vector<const char*>::empty());
|
||||
*ok = false;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Desugar '+foo' into 'foo*1', this enables the collection of type feedback
|
||||
// without any special stub and the multiplication is removed later in
|
||||
// Crankshaft's canonicalization pass.
|
||||
if (op == Token::ADD) {
|
||||
return factory()->NewBinaryOperation(Token::MUL,
|
||||
expression,
|
||||
factory()->NewNumberLiteral(1, pos),
|
||||
pos);
|
||||
}
|
||||
// The same idea for '-foo' => 'foo*(-1)'.
|
||||
if (op == Token::SUB) {
|
||||
return factory()->NewBinaryOperation(Token::MUL,
|
||||
expression,
|
||||
factory()->NewNumberLiteral(-1, pos),
|
||||
pos);
|
||||
}
|
||||
// ...and one more time for '~foo' => 'foo^(~0)'.
|
||||
if (op == Token::BIT_NOT) {
|
||||
return factory()->NewBinaryOperation(Token::BIT_XOR,
|
||||
expression,
|
||||
factory()->NewNumberLiteral(~0, pos),
|
||||
pos);
|
||||
}
|
||||
|
||||
return factory()->NewUnaryOperation(op, expression, pos);
|
||||
|
||||
} else if (Token::IsCountOp(op)) {
|
||||
op = Next();
|
||||
Scanner::Location lhs_location = scanner()->peek_location();
|
||||
Expression* expression = ParseUnaryExpression(CHECK_OK);
|
||||
if (expression == NULL || !expression->IsValidLeftHandSide()) {
|
||||
ReportMessageAt(lhs_location, "invalid_lhs_in_prefix_op", true);
|
||||
*ok = false;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (strict_mode() == STRICT) {
|
||||
// Prefix expression operand in strict mode may not be eval or arguments.
|
||||
CheckStrictModeLValue(expression, CHECK_OK);
|
||||
}
|
||||
MarkExpressionAsLValue(expression);
|
||||
|
||||
return factory()->NewCountOperation(op,
|
||||
true /* prefix */,
|
||||
expression,
|
||||
position());
|
||||
|
||||
} else {
|
||||
return ParsePostfixExpression(ok);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Expression* Parser::ParsePostfixExpression(bool* ok) {
|
||||
// PostfixExpression ::
|
||||
// LeftHandSideExpression ('++' | '--')?
|
||||
|
19
src/parser.h
19
src/parser.h
@ -460,8 +460,6 @@ class ParserTraits {
|
||||
// Returns true if the expression is of type "this.foo".
|
||||
static bool IsThisProperty(Expression* expression);
|
||||
|
||||
static bool IsIdentifier(Expression* expression);
|
||||
|
||||
static bool IsBoilerplateProperty(ObjectLiteral::Property* property) {
|
||||
return ObjectLiteral::IsBoilerplateProperty(property);
|
||||
}
|
||||
@ -511,21 +509,6 @@ class ParserTraits {
|
||||
Expression** x, Expression* y, Token::Value op, int pos,
|
||||
AstNodeFactory<AstConstructionVisitor>* factory);
|
||||
|
||||
// Rewrites the following types of unary expressions:
|
||||
// not <literal> -> true / false
|
||||
// + <numeric literal> -> <numeric literal>
|
||||
// - <numeric literal> -> <numeric literal with value negated>
|
||||
// ! <literal> -> true / false
|
||||
// The following rewriting rules enable the collection of type feedback
|
||||
// without any special stub and the multiplication is removed later in
|
||||
// Crankshaft's canonicalization pass.
|
||||
// + foo -> foo * 1
|
||||
// - foo -> foo * (-1)
|
||||
// ~ foo -> foo ^(~0)
|
||||
Expression* BuildUnaryExpression(
|
||||
Expression* expression, Token::Value op, int pos,
|
||||
AstNodeFactory<AstConstructionVisitor>* factory);
|
||||
|
||||
// Reporting errors.
|
||||
void ReportMessageAt(Scanner::Location source_location,
|
||||
const char* message,
|
||||
@ -589,7 +572,7 @@ class ParserTraits {
|
||||
int function_token_position,
|
||||
FunctionLiteral::FunctionType type,
|
||||
bool* ok);
|
||||
Expression* ParsePostfixExpression(bool* ok);
|
||||
Expression* ParseUnaryExpression(bool* ok);
|
||||
|
||||
private:
|
||||
Parser* parser_;
|
||||
|
@ -146,8 +146,8 @@ PreParserExpression PreParserTraits::ParseFunctionLiteral(
|
||||
}
|
||||
|
||||
|
||||
PreParserExpression PreParserTraits::ParsePostfixExpression(bool* ok) {
|
||||
return pre_parser_->ParsePostfixExpression(ok);
|
||||
PreParserExpression PreParserTraits::ParseUnaryExpression(bool* ok) {
|
||||
return pre_parser_->ParseUnaryExpression(ok);
|
||||
}
|
||||
|
||||
|
||||
@ -842,6 +842,37 @@ PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) {
|
||||
#undef DUMMY
|
||||
|
||||
|
||||
PreParser::Expression PreParser::ParseUnaryExpression(bool* ok) {
|
||||
// UnaryExpression ::
|
||||
// PostfixExpression
|
||||
// 'delete' UnaryExpression
|
||||
// 'void' UnaryExpression
|
||||
// 'typeof' UnaryExpression
|
||||
// '++' UnaryExpression
|
||||
// '--' UnaryExpression
|
||||
// '+' UnaryExpression
|
||||
// '-' UnaryExpression
|
||||
// '~' UnaryExpression
|
||||
// '!' UnaryExpression
|
||||
|
||||
Token::Value op = peek();
|
||||
if (Token::IsUnaryOp(op)) {
|
||||
op = Next();
|
||||
ParseUnaryExpression(ok);
|
||||
return Expression::Default();
|
||||
} else if (Token::IsCountOp(op)) {
|
||||
op = Next();
|
||||
Expression expression = ParseUnaryExpression(CHECK_OK);
|
||||
if (strict_mode() == STRICT) {
|
||||
CheckStrictModeLValue(expression, CHECK_OK);
|
||||
}
|
||||
return Expression::Default();
|
||||
} else {
|
||||
return ParsePostfixExpression(ok);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PreParser::Expression PreParser::ParsePostfixExpression(bool* ok) {
|
||||
// PostfixExpression ::
|
||||
// LeftHandSideExpression ('++' | '--')?
|
||||
|
@ -394,7 +394,6 @@ class ParserBase : public Traits {
|
||||
ExpressionT ParseYieldExpression(bool* ok);
|
||||
ExpressionT ParseConditionalExpression(bool accept_IN, bool* ok);
|
||||
ExpressionT ParseBinaryExpression(int prec, bool accept_IN, bool* ok);
|
||||
ExpressionT ParseUnaryExpression(bool* ok);
|
||||
|
||||
// Used to detect duplicates in object literals. Each of the values
|
||||
// kGetterProperty, kSetterProperty and kValueProperty represents
|
||||
@ -743,13 +742,6 @@ class PreParserFactory {
|
||||
int pos) {
|
||||
return PreParserExpression::Default();
|
||||
}
|
||||
|
||||
PreParserExpression NewCountOperation(Token::Value op,
|
||||
bool is_prefix,
|
||||
PreParserExpression expression,
|
||||
int pos) {
|
||||
return PreParserExpression::Default();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -802,10 +794,6 @@ class PreParserTraits {
|
||||
return expression.IsThisProperty();
|
||||
}
|
||||
|
||||
static bool IsIdentifier(PreParserExpression expression) {
|
||||
return expression.IsIdentifier();
|
||||
}
|
||||
|
||||
static bool IsBoilerplateProperty(PreParserExpression property) {
|
||||
// PreParser doesn't count boilerplate properties.
|
||||
return false;
|
||||
@ -853,12 +841,6 @@ class PreParserTraits {
|
||||
return false;
|
||||
}
|
||||
|
||||
PreParserExpression BuildUnaryExpression(PreParserExpression expression,
|
||||
Token::Value op, int pos,
|
||||
PreParserFactory* factory) {
|
||||
return PreParserExpression::Default();
|
||||
}
|
||||
|
||||
// Reporting errors.
|
||||
void ReportMessageAt(Scanner::Location location,
|
||||
const char* message,
|
||||
@ -940,7 +922,7 @@ class PreParserTraits {
|
||||
int function_token_position,
|
||||
FunctionLiteral::FunctionType type,
|
||||
bool* ok);
|
||||
PreParserExpression ParsePostfixExpression(bool* ok);
|
||||
PreParserExpression ParseUnaryExpression(bool* ok);
|
||||
|
||||
private:
|
||||
PreParser* pre_parser_;
|
||||
@ -1104,6 +1086,7 @@ class PreParser : public ParserBase<PreParserTraits> {
|
||||
Statement ParseTryStatement(bool* ok);
|
||||
Statement ParseDebuggerStatement(bool* ok);
|
||||
Expression ParseConditionalExpression(bool accept_IN, bool* ok);
|
||||
Expression ParseUnaryExpression(bool* ok);
|
||||
Expression ParsePostfixExpression(bool* ok);
|
||||
Expression ParseLeftHandSideExpression(bool* ok);
|
||||
Expression ParseMemberExpression(bool* ok);
|
||||
@ -1795,64 +1778,6 @@ ParserBase<Traits>::ParseBinaryExpression(int prec, bool accept_IN, bool* ok) {
|
||||
}
|
||||
|
||||
|
||||
template <class Traits>
|
||||
typename ParserBase<Traits>::ExpressionT
|
||||
ParserBase<Traits>::ParseUnaryExpression(bool* ok) {
|
||||
// UnaryExpression ::
|
||||
// PostfixExpression
|
||||
// 'delete' UnaryExpression
|
||||
// 'void' UnaryExpression
|
||||
// 'typeof' UnaryExpression
|
||||
// '++' UnaryExpression
|
||||
// '--' UnaryExpression
|
||||
// '+' UnaryExpression
|
||||
// '-' UnaryExpression
|
||||
// '~' UnaryExpression
|
||||
// '!' UnaryExpression
|
||||
|
||||
Token::Value op = peek();
|
||||
if (Token::IsUnaryOp(op)) {
|
||||
op = Next();
|
||||
int pos = position();
|
||||
ExpressionT expression = ParseUnaryExpression(CHECK_OK);
|
||||
|
||||
// "delete identifier" is a syntax error in strict mode.
|
||||
if (op == Token::DELETE && strict_mode() == STRICT &&
|
||||
this->IsIdentifier(expression)) {
|
||||
ReportMessage("strict_delete", Vector<const char*>::empty());
|
||||
*ok = false;
|
||||
return this->EmptyExpression();
|
||||
}
|
||||
|
||||
// Allow Traits do rewrite the expression.
|
||||
return BuildUnaryExpression(expression, op, pos, factory());
|
||||
} else if (Token::IsCountOp(op)) {
|
||||
op = Next();
|
||||
Scanner::Location lhs_location = scanner()->peek_location();
|
||||
ExpressionT expression = ParseUnaryExpression(CHECK_OK);
|
||||
if (!this->IsValidLeftHandSide(expression)) {
|
||||
ReportMessageAt(lhs_location, "invalid_lhs_in_prefix_op", true);
|
||||
*ok = false;
|
||||
return this->EmptyExpression();
|
||||
}
|
||||
|
||||
if (strict_mode() == STRICT) {
|
||||
// Prefix expression operand in strict mode may not be eval or arguments.
|
||||
CheckStrictModeLValue(expression, CHECK_OK);
|
||||
}
|
||||
MarkExpressionAsLValue(expression);
|
||||
|
||||
return factory()->NewCountOperation(op,
|
||||
true /* prefix */,
|
||||
expression,
|
||||
position());
|
||||
|
||||
} else {
|
||||
return this->ParsePostfixExpression(ok);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#undef CHECK_OK
|
||||
#undef CHECK_OK_CUSTOM
|
||||
|
||||
|
@ -2472,57 +2472,3 @@ TEST(TooManyArguments) {
|
||||
static const ParserFlag empty_flags[] = {kAllowLazy};
|
||||
RunParserSyncTest(context_data, statement_data, kError, empty_flags, 1);
|
||||
}
|
||||
|
||||
|
||||
TEST(StrictDelete) {
|
||||
// "delete <Identifier>" is not allowed in strict mode.
|
||||
const char* strict_context_data[][2] = {
|
||||
{"\"use strict\"; ", ""},
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
const char* sloppy_context_data[][2] = {
|
||||
{"", ""},
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
// These are errors in the strict mode.
|
||||
const char* sloppy_statement_data[] = {
|
||||
"delete foo;",
|
||||
"delete foo + 1;",
|
||||
"delete (foo);",
|
||||
"delete eval;",
|
||||
"delete interface;",
|
||||
NULL
|
||||
};
|
||||
|
||||
// These are always OK
|
||||
const char* good_statement_data[] = {
|
||||
"delete this;",
|
||||
"delete 1;",
|
||||
"delete 1 + 2;",
|
||||
"delete foo();",
|
||||
"delete foo.bar;",
|
||||
"delete foo[bar];",
|
||||
"delete foo--;",
|
||||
"delete --foo;",
|
||||
"delete new foo();",
|
||||
"delete new foo(bar);",
|
||||
NULL
|
||||
};
|
||||
|
||||
// These are always errors
|
||||
const char* bad_statement_data[] = {
|
||||
"delete if;",
|
||||
NULL
|
||||
};
|
||||
|
||||
RunParserSyncTest(strict_context_data, sloppy_statement_data, kError);
|
||||
RunParserSyncTest(sloppy_context_data, sloppy_statement_data, kSuccess);
|
||||
|
||||
RunParserSyncTest(strict_context_data, good_statement_data, kSuccess);
|
||||
RunParserSyncTest(sloppy_context_data, good_statement_data, kSuccess);
|
||||
|
||||
RunParserSyncTest(strict_context_data, bad_statement_data, kError);
|
||||
RunParserSyncTest(sloppy_context_data, bad_statement_data, kError);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user