Commit cf820126 authored by marja@chromium.org's avatar marja@chromium.org

Move ParseObjectLiteral to ParserBase.

BUG=v8:3126
LOG=N
R=ulan@chromium.org

Review URL: https://codereview.chromium.org/192993002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19805 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 62fc0993
......@@ -28,9 +28,13 @@
#ifndef V8_FUNC_NAME_INFERRER_H_
#define V8_FUNC_NAME_INFERRER_H_
#include "handles.h"
#include "zone.h"
namespace v8 {
namespace internal {
class FunctionLiteral;
class Isolate;
// FuncNameInferrer is a stateful class that is used to perform name
......
......@@ -33,7 +33,6 @@
#include "char-predicates-inl.h"
#include "codegen.h"
#include "compiler.h"
#include "func-name-inferrer.h"
#include "messages.h"
#include "parser.h"
#include "platform.h"
......@@ -520,7 +519,7 @@ Expression* ParserTraits::ThisExpression(
}
Expression* ParserTraits::ExpressionFromLiteral(
Literal* ParserTraits::ExpressionFromLiteral(
Token::Value token, int pos,
Scanner* scanner,
AstNodeFactory<AstConstructionVisitor>* factory) {
......@@ -577,11 +576,6 @@ Literal* ParserTraits::GetLiteralTheHole(
}
Expression* ParserTraits::ParseObjectLiteral(bool* ok) {
return parser_->ParseObjectLiteral(ok);
}
Expression* ParserTraits::ParseAssignmentExpression(bool accept_IN, bool* ok) {
return parser_->ParseAssignmentExpression(accept_IN, ok);
}
......@@ -592,6 +586,20 @@ Expression* ParserTraits::ParseV8Intrinsic(bool* ok) {
}
FunctionLiteral* ParserTraits::ParseFunctionLiteral(
Handle<String> name,
Scanner::Location function_name_location,
bool name_is_strict_reserved,
bool is_generator,
int function_token_position,
FunctionLiteral::FunctionType type,
bool* ok) {
return parser_->ParseFunctionLiteral(name, function_name_location,
name_is_strict_reserved, is_generator,
function_token_position, type, ok);
}
Parser::Parser(CompilationInfo* info)
: ParserBase<ParserTraits>(&scanner_,
info->isolate()->stack_guard()->real_climit(),
......@@ -606,7 +614,6 @@ Parser::Parser(CompilationInfo* info)
original_scope_(NULL),
target_stack_(NULL),
pre_parse_data_(NULL),
fni_(NULL),
info_(info) {
ASSERT(!script_.is_null());
isolate_->set_ast_node_id(0);
......@@ -3494,169 +3501,6 @@ Handle<FixedArray> CompileTimeValue::GetElements(Handle<FixedArray> value) {
}
Expression* Parser::ParseObjectLiteral(bool* ok) {
// ObjectLiteral ::
// '{' ((
// ((IdentifierName | String | Number) ':' AssignmentExpression) |
// (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
// ) ',')* '}'
// (Except that trailing comma is not required and not allowed.)
int pos = peek_position();
ZoneList<ObjectLiteral::Property*>* properties =
new(zone()) ZoneList<ObjectLiteral::Property*>(4, zone());
int number_of_boilerplate_properties = 0;
bool has_function = false;
ObjectLiteralChecker checker(this, strict_mode());
Expect(Token::LBRACE, CHECK_OK);
while (peek() != Token::RBRACE) {
if (fni_ != NULL) fni_->Enter();
Literal* key = NULL;
Token::Value next = peek();
int next_pos = peek_position();
switch (next) {
case Token::FUTURE_RESERVED_WORD:
case Token::FUTURE_STRICT_RESERVED_WORD:
case Token::IDENTIFIER: {
bool is_getter = false;
bool is_setter = false;
Handle<String> id =
ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
if (fni_ != NULL) fni_->PushLiteralName(id);
if ((is_getter || is_setter) && peek() != Token::COLON) {
// Special handling of getter and setter syntax:
// { ... , get foo() { ... }, ... , set foo(v) { ... v ... } , ... }
// We have already read the "get" or "set" keyword.
Token::Value next = Next();
if (next != i::Token::IDENTIFIER &&
next != i::Token::FUTURE_RESERVED_WORD &&
next != i::Token::FUTURE_STRICT_RESERVED_WORD &&
next != i::Token::NUMBER &&
next != i::Token::STRING &&
!Token::IsKeyword(next)) {
ReportUnexpectedToken(next);
*ok = false;
return NULL;
}
// Validate the property.
PropertyKind type = is_getter ? kGetterProperty : kSetterProperty;
checker.CheckProperty(next, type, CHECK_OK);
Handle<String> name = GetSymbol();
FunctionLiteral* value =
ParseFunctionLiteral(name,
scanner()->location(),
false, // reserved words are allowed here
false, // not a generator
RelocInfo::kNoPosition,
FunctionLiteral::ANONYMOUS_EXPRESSION,
CHECK_OK);
// Allow any number of parameters for compatibilty with JSC.
// Specification only allows zero parameters for get and one for set.
ObjectLiteral::Property* property =
factory()->NewObjectLiteralProperty(is_getter, value, next_pos);
if (ObjectLiteral::IsBoilerplateProperty(property)) {
number_of_boilerplate_properties++;
}
properties->Add(property, zone());
if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
if (fni_ != NULL) {
fni_->Infer();
fni_->Leave();
}
continue; // restart the while
}
// Failed to parse as get/set property, so it's just a normal property
// (which might be called "get" or "set" or something else).
key = factory()->NewLiteral(id, next_pos);
break;
}
case Token::STRING: {
Consume(Token::STRING);
Handle<String> string = GetSymbol();
if (fni_ != NULL) fni_->PushLiteralName(string);
uint32_t index;
if (!string.is_null() && string->AsArrayIndex(&index)) {
key = factory()->NewNumberLiteral(index, next_pos);
break;
}
key = factory()->NewLiteral(string, next_pos);
break;
}
case Token::NUMBER: {
Consume(Token::NUMBER);
ASSERT(scanner()->is_literal_ascii());
double value = StringToDouble(isolate()->unicode_cache(),
scanner()->literal_ascii_string(),
ALLOW_HEX | ALLOW_OCTAL |
ALLOW_IMPLICIT_OCTAL | ALLOW_BINARY);
key = factory()->NewNumberLiteral(value, next_pos);
break;
}
default:
if (Token::IsKeyword(next)) {
Consume(next);
Handle<String> string = GetSymbol();
key = factory()->NewLiteral(string, next_pos);
} else {
Token::Value next = Next();
ReportUnexpectedToken(next);
*ok = false;
return NULL;
}
}
// Validate the property
checker.CheckProperty(next, kValueProperty, CHECK_OK);
Expect(Token::COLON, CHECK_OK);
Expression* value = ParseAssignmentExpression(true, CHECK_OK);
ObjectLiteral::Property* property =
factory()->NewObjectLiteralProperty(key, value);
// Mark top-level object literals that contain function literals and
// pretenure the literal so it can be added as a constant function
// property.
if (scope_->DeclarationScope()->is_global_scope() &&
value->AsFunctionLiteral() != NULL) {
has_function = true;
value->AsFunctionLiteral()->set_pretenure();
}
// Count CONSTANT or COMPUTED properties to maintain the enumeration order.
if (ObjectLiteral::IsBoilerplateProperty(property)) {
number_of_boilerplate_properties++;
}
properties->Add(property, zone());
// TODO(1240767): Consider allowing trailing comma.
if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
if (fni_ != NULL) {
fni_->Infer();
fni_->Leave();
}
}
Expect(Token::RBRACE, CHECK_OK);
// Computation of literal_index must happen before pre parse bailout.
int literal_index = function_state_->NextMaterializedLiteralIndex();
return factory()->NewObjectLiteral(properties,
literal_index,
number_of_boilerplate_properties,
has_function,
pos);
}
ZoneList<Expression*>* Parser::ParseArguments(bool* ok) {
// Arguments ::
// '(' (AssignmentExpression)*[','] ')'
......
......@@ -39,7 +39,6 @@ namespace v8 {
namespace internal {
class CompilationInfo;
class FuncNameInferrer;
class ParserLog;
class PositionStack;
class Target;
......@@ -420,7 +419,11 @@ class ParserTraits {
// Return types for traversing functions.
typedef Handle<String> Identifier;
typedef v8::internal::Expression* Expression;
typedef v8::internal::FunctionLiteral* FunctionLiteral;
typedef v8::internal::Literal* Literal;
typedef ObjectLiteral::Property* ObjectLiteralProperty;
typedef ZoneList<v8::internal::Expression*>* ExpressionList;
typedef ZoneList<ObjectLiteral::Property*>* PropertyList;
};
explicit ParserTraits(Parser* parser) : parser_(parser) {}
......@@ -445,6 +448,27 @@ class ParserTraits {
// Helper functions for recursive descent.
bool IsEvalOrArguments(Handle<String> identifier) const;
static bool IsBoilerplateProperty(ObjectLiteral::Property* property) {
return ObjectLiteral::IsBoilerplateProperty(property);
}
static bool IsArrayIndex(Handle<String> string, uint32_t* index) {
return !string.is_null() && string->AsArrayIndex(index);
}
static void PushLiteralName(FuncNameInferrer* fni, Handle<String> id) {
fni->PushLiteralName(id);
}
static void CheckFunctionLiteralInsideTopLevelObjectLiteral(
Scope* scope, Expression* value, bool* has_function) {
if (scope->DeclarationScope()->is_global_scope() &&
value->AsFunctionLiteral() != NULL) {
*has_function = true;
value->AsFunctionLiteral()->set_pretenure();
}
}
// Reporting errors.
void ReportMessageAt(Scanner::Location source_location,
const char* message,
......@@ -461,6 +485,9 @@ class ParserTraits {
static Expression* EmptyExpression() {
return NULL;
}
static Literal* EmptyLiteral() {
return NULL;
}
// Odd-ball literal creators.
Literal* GetLiteralTheHole(int position,
......@@ -472,7 +499,7 @@ class ParserTraits {
PretenureFlag tenured);
Expression* ThisExpression(Scope* scope,
AstNodeFactory<AstConstructionVisitor>* factory);
Expression* ExpressionFromLiteral(
Literal* ExpressionFromLiteral(
Token::Value token, int pos, Scanner* scanner,
AstNodeFactory<AstConstructionVisitor>* factory);
Expression* ExpressionFromIdentifier(
......@@ -484,11 +511,21 @@ class ParserTraits {
ZoneList<v8::internal::Expression*>* NewExpressionList(int size, Zone* zone) {
return new(zone) ZoneList<v8::internal::Expression*>(size, zone);
}
ZoneList<ObjectLiteral::Property*>* NewPropertyList(int size, Zone* zone) {
return new(zone) ZoneList<ObjectLiteral::Property*>(size, zone);
}
// Temporary glue; these functions will move to ParserBase.
Expression* ParseObjectLiteral(bool* ok);
Expression* ParseAssignmentExpression(bool accept_IN, bool* ok);
Expression* ParseV8Intrinsic(bool* ok);
FunctionLiteral* ParseFunctionLiteral(
Handle<String> name,
Scanner::Location function_name_location,
bool name_is_strict_reserved,
bool is_generator,
int function_token_position,
FunctionLiteral::FunctionType type,
bool* ok);
private:
Parser* parser_;
......@@ -749,7 +786,6 @@ class Parser : public ParserBase<ParserTraits> {
Scope* original_scope_; // for ES5 function declarations in sloppy eval
Target* target_stack_; // for break, continue statements
ScriptDataImpl* pre_parse_data_;
FuncNameInferrer* fni_;
Mode mode_;
......
......@@ -122,11 +122,6 @@ PreParserExpression PreParserTraits::ExpressionFromString(
}
PreParserExpression PreParserTraits::ParseObjectLiteral(bool* ok) {
return pre_parser_->ParseObjectLiteral(ok);
}
PreParserExpression PreParserTraits::ParseAssignmentExpression(bool accept_IN,
bool* ok) {
return pre_parser_->ParseAssignmentExpression(accept_IN, ok);
......@@ -138,6 +133,20 @@ PreParserExpression PreParserTraits::ParseV8Intrinsic(bool* ok) {
}
PreParserExpression PreParserTraits::ParseFunctionLiteral(
PreParserIdentifier name,
Scanner::Location function_name_location,
bool name_is_strict_reserved,
bool is_generator,
int function_token_position,
FunctionLiteral::FunctionType type,
bool* ok) {
return pre_parser_->ParseFunctionLiteral(
name, function_name_location, name_is_strict_reserved, is_generator,
function_token_position, type, ok);
}
PreParser::PreParseResult PreParser::PreParseLazyFunction(
StrictMode strict_mode, bool is_generator, ParserRecorder* log) {
log_ = log;
......@@ -1126,91 +1135,6 @@ PreParser::Expression PreParser::ParseMemberExpressionContinuation(
}
PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) {
// ObjectLiteral ::
// '{' ((
// ((IdentifierName | String | Number) ':' AssignmentExpression) |
// (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
// ) ',')* '}'
// (Except that trailing comma is not required and not allowed.)
ObjectLiteralChecker checker(this, strict_mode());
Expect(Token::LBRACE, CHECK_OK);
while (peek() != Token::RBRACE) {
Token::Value next = peek();
switch (next) {
case Token::IDENTIFIER:
case Token::FUTURE_RESERVED_WORD:
case Token::FUTURE_STRICT_RESERVED_WORD: {
bool is_getter = false;
bool is_setter = false;
ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
if ((is_getter || is_setter) && peek() != Token::COLON) {
Token::Value next = Next();
if (next != Token::IDENTIFIER &&
next != Token::FUTURE_RESERVED_WORD &&
next != Token::FUTURE_STRICT_RESERVED_WORD &&
next != Token::NUMBER &&
next != Token::STRING &&
!Token::IsKeyword(next)) {
ReportUnexpectedToken(next);
*ok = false;
return Expression::Default();
}
// Validate the property
PropertyKind type = is_getter ? kGetterProperty : kSetterProperty;
checker.CheckProperty(next, type, CHECK_OK);
PreParserIdentifier name = GetSymbol(scanner());
ParseFunctionLiteral(name,
scanner()->location(),
false, // reserved words are allowed here
false, // not a generator
RelocInfo::kNoPosition,
FunctionLiteral::ANONYMOUS_EXPRESSION,
CHECK_OK);
if (peek() != Token::RBRACE) {
Expect(Token::COMMA, CHECK_OK);
}
continue; // restart the while
}
break;
}
case Token::STRING:
Consume(next);
LogSymbol();
break;
case Token::NUMBER:
Consume(next);
break;
default:
if (Token::IsKeyword(next)) {
Consume(next);
LogSymbol();
} else {
Token::Value next = Next();
ReportUnexpectedToken(next);
*ok = false;
return Expression::Default();
}
}
// Validate the property
checker.CheckProperty(next, kValueProperty, CHECK_OK);
Expect(Token::COLON, CHECK_OK);
ParseAssignmentExpression(true, CHECK_OK);
// TODO(1240767): Consider allowing trailing comma.
if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
}
Expect(Token::RBRACE, CHECK_OK);
function_state_->NextMaterializedLiteralIndex();
return Expression::Default();
}
PreParser::Arguments PreParser::ParseArguments(bool* ok) {
// Arguments ::
// '(' (AssignmentExpression)*[','] ')'
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment