Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(89)

Unified Diff: src/preparser.h

Issue 160073006: Implement handling of arrow functions in the parser (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Rebased after latest changes in runtime.{h,cc} Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« src/parser.cc ('K') | « src/parser.cc ('k') | src/preparser.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/preparser.h
diff --git a/src/preparser.h b/src/preparser.h
index ce8df77e7a8586b55b7016cd7713e4aa93faf7f9..8730ed5f402ee4dace6cc2576e3aa8a293811c6c 100644
--- a/src/preparser.h
+++ b/src/preparser.h
@@ -78,12 +78,14 @@ namespace internal {
// // ...
// };
+
template <typename Traits>
class ParserBase : public Traits {
public:
// Shorten type names defined by Traits.
typedef typename Traits::Type::Expression ExpressionT;
typedef typename Traits::Type::Identifier IdentifierT;
+ typedef typename Traits::Type::FunctionLiteral FunctionLiteralT;
ParserBase(Scanner* scanner, uintptr_t stack_limit,
v8::Extension* extension,
@@ -105,6 +107,7 @@ class ParserBase : public Traits {
allow_natives_syntax_(false),
allow_generators_(false),
allow_for_of_(false),
+ allow_arrow_functions_(false),
zone_(zone) { }
// Getters that indicate whether certain syntactical constructs are
@@ -113,6 +116,7 @@ class ParserBase : public Traits {
bool allow_natives_syntax() const { return allow_natives_syntax_; }
bool allow_generators() const { return allow_generators_; }
bool allow_for_of() const { return allow_for_of_; }
+ bool allow_arrow_functions() const { return allow_arrow_functions_; }
bool allow_modules() const { return scanner()->HarmonyModules(); }
bool allow_harmony_scoping() const { return scanner()->HarmonyScoping(); }
bool allow_harmony_numeric_literals() const {
@@ -125,6 +129,7 @@ class ParserBase : public Traits {
void set_allow_natives_syntax(bool allow) { allow_natives_syntax_ = allow; }
void set_allow_generators(bool allow) { allow_generators_ = allow; }
void set_allow_for_of(bool allow) { allow_for_of_ = allow; }
+ void set_allow_arrow_functions(bool allow) { allow_arrow_functions_ = allow; }
void set_allow_modules(bool allow) { scanner()->SetHarmonyModules(allow); }
void set_allow_harmony_scoping(bool allow) {
scanner()->SetHarmonyScoping(allow);
@@ -173,6 +178,11 @@ class ParserBase : public Traits {
typename Traits::Type::Scope** scope_stack,
typename Traits::Type::Scope* scope,
typename Traits::Type::Zone* zone = NULL);
+ FunctionState(
+ FunctionState** function_state_stack,
+ typename Traits::Type::Scope** scope_stack,
+ typename Traits::Type::Scope** scope,
+ typename Traits::Type::Zone* zone = NULL);
~FunctionState();
int NextMaterializedLiteralIndex() {
@@ -424,6 +434,9 @@ class ParserBase : public Traits {
ExpressionT ParseMemberExpression(bool* ok);
ExpressionT ParseMemberExpressionContinuation(ExpressionT expression,
bool* ok);
+ ExpressionT ParseArrowFunctionLiteral(int start_pos,
+ ExpressionT params_ast,
+ bool* ok);
// Checks if the expression is a valid reference expression (e.g., on the
// left-hand side of assignments). Although ruled out by ECMA as early errors,
@@ -508,6 +521,7 @@ class ParserBase : public Traits {
bool allow_natives_syntax_;
bool allow_generators_;
bool allow_for_of_;
+ bool allow_arrow_functions_;
typename Traits::Type::Zone* zone_; // Only used by Parser.
};
@@ -516,34 +530,47 @@ class ParserBase : public Traits {
class PreParserIdentifier {
public:
PreParserIdentifier() : type_(kUnknownIdentifier) {}
- static PreParserIdentifier Default() {
- return PreParserIdentifier(kUnknownIdentifier);
+ static PreParserIdentifier Default(int pos) {
+ return PreParserIdentifier(kUnknownIdentifier, pos);
}
- static PreParserIdentifier Eval() {
- return PreParserIdentifier(kEvalIdentifier);
+ static PreParserIdentifier Eval(int pos) {
+ return PreParserIdentifier(kEvalIdentifier, pos);
}
- static PreParserIdentifier Arguments() {
- return PreParserIdentifier(kArgumentsIdentifier);
+ static PreParserIdentifier Arguments(int pos) {
+ return PreParserIdentifier(kArgumentsIdentifier, pos);
}
- static PreParserIdentifier FutureReserved() {
- return PreParserIdentifier(kFutureReservedIdentifier);
+ static PreParserIdentifier FutureReserved(int pos) {
+ return PreParserIdentifier(kFutureReservedIdentifier, pos);
}
- static PreParserIdentifier FutureStrictReserved() {
- return PreParserIdentifier(kFutureStrictReservedIdentifier);
+ static PreParserIdentifier FutureStrictReserved(int pos) {
+ return PreParserIdentifier(kFutureStrictReservedIdentifier, pos);
}
- static PreParserIdentifier Yield() {
- return PreParserIdentifier(kYieldIdentifier);
+ static PreParserIdentifier Yield(int pos) {
+ return PreParserIdentifier(kYieldIdentifier, pos);
}
- bool IsEval() { return type_ == kEvalIdentifier; }
- bool IsArguments() { return type_ == kArgumentsIdentifier; }
+ bool IsEval() const { return type_ == kEvalIdentifier; }
+ bool IsArguments() const { return type_ == kArgumentsIdentifier; }
bool IsEvalOrArguments() { return type_ >= kEvalIdentifier; }
- bool IsYield() { return type_ == kYieldIdentifier; }
+ bool IsYield() const { return type_ == kYieldIdentifier; }
bool IsFutureReserved() { return type_ == kFutureReservedIdentifier; }
bool IsFutureStrictReserved() {
return type_ == kFutureStrictReservedIdentifier;
}
bool IsValidStrictVariable() { return type_ == kUnknownIdentifier; }
+ // Allow identifier->name()[->length()] to work
+ const PreParserIdentifier* operator->() const { return this; }
+ const PreParserIdentifier name() const { return *this; }
+ int position() const { return pos_; }
+ int length() const {
+ if (IsEval()) return 4;
+ if (IsArguments()) return 9;
+ if (IsYield()) return 5;
+
+ // TODO(aperez): Is this correct?
+ return 0;
+ }
+
private:
enum Type {
kUnknownIdentifier,
@@ -553,8 +580,9 @@ class PreParserIdentifier {
kEvalIdentifier,
kArgumentsIdentifier
};
- explicit PreParserIdentifier(Type type) : type_(type) {}
+ explicit PreParserIdentifier(Type type, int pos) : type_(type), pos_(pos) {}
Type type_;
+ int pos_;
friend class PreParserExpression;
};
@@ -567,37 +595,39 @@ class PreParserIdentifier {
// use yet.
class PreParserExpression {
public:
- static PreParserExpression Default() {
- return PreParserExpression(kUnknownExpression);
+ static PreParserExpression Default(int pos = RelocInfo::kNoPosition) {
+ return PreParserExpression(kUnknownExpression, pos);
}
- static PreParserExpression FromIdentifier(PreParserIdentifier id) {
+ static PreParserExpression FromIdentifier(PreParserIdentifier id,
+ int pos = RelocInfo::kNoPosition) {
return PreParserExpression(kIdentifierFlag |
- (id.type_ << kIdentifierShift));
+ (id.type_ << kIdentifierShift), pos);
}
- static PreParserExpression StringLiteral() {
- return PreParserExpression(kUnknownStringLiteral);
+ static PreParserExpression StringLiteral(int pos = RelocInfo::kNoPosition) {
+ return PreParserExpression(kUnknownStringLiteral, pos);
}
- static PreParserExpression UseStrictStringLiteral() {
- return PreParserExpression(kUseStrictString);
+ static PreParserExpression UseStrictStringLiteral(
+ int pos = RelocInfo::kNoPosition) {
+ return PreParserExpression(kUseStrictString, pos);
}
- static PreParserExpression This() {
- return PreParserExpression(kThisExpression);
+ static PreParserExpression This(int pos = RelocInfo::kNoPosition) {
+ return PreParserExpression(kThisExpression, pos);
}
- static PreParserExpression ThisProperty() {
- return PreParserExpression(kThisPropertyExpression);
+ static PreParserExpression ThisProperty(int pos = RelocInfo::kNoPosition) {
+ return PreParserExpression(kThisPropertyExpression, pos);
}
- static PreParserExpression Property() {
- return PreParserExpression(kPropertyExpression);
+ static PreParserExpression Property(int pos = RelocInfo::kNoPosition) {
+ return PreParserExpression(kPropertyExpression, pos);
}
- static PreParserExpression Call() {
- return PreParserExpression(kCallExpression);
+ static PreParserExpression Call(int pos = RelocInfo::kNoPosition) {
+ return PreParserExpression(kCallExpression, pos);
}
bool IsIdentifier() { return (code_ & kIdentifierFlag) != 0; }
@@ -605,7 +635,8 @@ class PreParserExpression {
PreParserIdentifier AsIdentifier() {
ASSERT(IsIdentifier());
return PreParserIdentifier(
- static_cast<PreParserIdentifier::Type>(code_ >> kIdentifierShift));
+ static_cast<PreParserIdentifier::Type>(code_ >> kIdentifierShift),
+ pos_);
}
bool IsStringLiteral() { return (code_ & kStringLiteralFlag) != 0; }
@@ -634,6 +665,8 @@ class PreParserExpression {
PreParserExpression AsFunctionLiteral() { return *this; }
+ int position() const { return pos_; }
+
// Dummy implementation for making expression->somefunc() work in both Parser
// and PreParser.
PreParserExpression* operator->() { return this; }
@@ -642,6 +675,18 @@ class PreParserExpression {
void set_index(int index) {} // For YieldExpressions
void set_parenthesized() {}
+ void set_function_token_position(int position) { pos_ = position; }
+ void set_ast_properties(int* ast_properties) {}
+ void set_slot_processor(int* slot_processor) {}
+ void set_dont_optimize_reason(BailoutReason dont_optimize_reason) {}
+
+ bool operator==(const PreParserExpression& other) const {
+ return code_ == other.code_;
+ }
+ bool operator!=(const PreParserExpression& other) const {
+ return code_ != other.code_;
+ }
+
private:
// Least significant 2 bits are used as flags. Bits 0 and 1 represent
// identifiers or strings literals, and are mutually exclusive, but can both
@@ -667,9 +712,11 @@ class PreParserExpression {
kCallExpression = 4 << 2
};
- explicit PreParserExpression(int expression_code) : code_(expression_code) {}
+ explicit PreParserExpression(int expression_code, int pos)
+ : code_(expression_code), pos_(pos) {}
int code_;
+ int pos_;
};
@@ -686,10 +733,71 @@ class PreParserExpressionList {
int length_;
};
+class PreParserStatement {
marja 2014/04/24 08:08:06 I'd be more than willing to take this kind of chan
aperez 2014/04/24 12:38:37 Fortunately I have this locally as a separate comm
+ public:
+ static PreParserStatement Default() {
+ return PreParserStatement(kUnknownStatement);
+ }
+
+ static PreParserStatement FunctionDeclaration() {
+ return PreParserStatement(kFunctionDeclaration);
+ }
+
+ // Creates expression statement from expression.
+ // Preserves being an unparenthesized string literal, possibly
+ // "use strict".
+ static PreParserStatement ExpressionStatement(
+ PreParserExpression expression) {
+ if (expression.IsUseStrictLiteral()) {
+ return PreParserStatement(kUseStrictExpressionStatement);
+ }
+ if (expression.IsStringLiteral()) {
+ return PreParserStatement(kStringLiteralExpressionStatement);
+ }
+ return Default();
+ }
+
+ bool IsStringLiteral() {
+ return code_ == kStringLiteralExpressionStatement;
+ }
+
+ bool IsUseStrictLiteral() {
+ return code_ == kUseStrictExpressionStatement;
+ }
+
+ bool IsFunctionDeclaration() {
+ return code_ == kFunctionDeclaration;
+ }
+
+ private:
+ enum Type {
+ kUnknownStatement,
+ kStringLiteralExpressionStatement,
+ kUseStrictExpressionStatement,
+ kFunctionDeclaration
+ };
+
+ explicit PreParserStatement(Type code) : code_(code) {}
+ Type code_;
+};
+
+
+// PreParserStatementList doesn't actually store the statements because
+// PreParser doesn't need to.
+class PreParserStatementList {
+ public:
+ // These functions make list->Add(some_expression) work (and do nothing).
+ PreParserStatementList() {}
+ PreParserStatementList* operator->() { return this; }
+ void Add(PreParserStatement, void*) {}
+};
+
class PreParserScope {
public:
- explicit PreParserScope(PreParserScope* outer_scope, ScopeType scope_type)
+ explicit PreParserScope(PreParserScope* outer_scope,
+ ScopeType scope_type,
+ void* = NULL)
: scope_type_(scope_type) {
strict_mode_ = outer_scope ? outer_scope->strict_mode() : SLOPPY;
}
@@ -697,6 +805,16 @@ class PreParserScope {
ScopeType type() { return scope_type_; }
StrictMode strict_mode() const { return strict_mode_; }
void SetStrictMode(StrictMode strict_mode) { strict_mode_ = strict_mode; }
+ bool AllowsLazyCompilation() const { return true; }
+
+ void set_start_position(int position) {}
+ void set_end_position(int position) {}
+
+ bool IsDeclared(const PreParserIdentifier&) const { return false; }
+ void DeclareParameter(const PreParserIdentifier&, VariableMode) {}
+
+ // Allow scope->Foo() to work.
+ PreParserScope* operator->() { return this; }
private:
ScopeType scope_type_;
@@ -709,22 +827,22 @@ class PreParserFactory {
explicit PreParserFactory(void* extra_param) {}
PreParserExpression NewLiteral(PreParserIdentifier identifier,
int pos) {
- return PreParserExpression::Default();
+ return PreParserExpression::Default(pos);
}
PreParserExpression NewNumberLiteral(double number,
int pos) {
- return PreParserExpression::Default();
+ return PreParserExpression::Default(pos);
}
PreParserExpression NewRegExpLiteral(PreParserIdentifier js_pattern,
PreParserIdentifier js_flags,
int literal_index,
int pos) {
- return PreParserExpression::Default();
+ return PreParserExpression::Default(pos);
}
PreParserExpression NewArrayLiteral(PreParserExpressionList values,
int literal_index,
int pos) {
- return PreParserExpression::Default();
+ return PreParserExpression::Default(pos);
}
PreParserExpression NewObjectLiteralProperty(bool is_getter,
PreParserExpression value,
@@ -740,68 +858,96 @@ class PreParserFactory {
int boilerplate_properties,
bool has_function,
int pos) {
- return PreParserExpression::Default();
+ return PreParserExpression::Default(pos);
}
- PreParserExpression NewVariableProxy(void* generator_variable) {
- return PreParserExpression::Default();
+ PreParserExpression NewVariableProxy(void* generator_variable, int pos) {
+ return PreParserExpression::Default(pos);
}
PreParserExpression NewProperty(PreParserExpression obj,
PreParserExpression key,
int pos) {
if (obj.IsThis()) {
- return PreParserExpression::ThisProperty();
+ return PreParserExpression::ThisProperty(pos);
}
- return PreParserExpression::Property();
+ return PreParserExpression::Property(pos);
}
PreParserExpression NewUnaryOperation(Token::Value op,
PreParserExpression expression,
int pos) {
- return PreParserExpression::Default();
+ return PreParserExpression::Default(pos);
}
PreParserExpression NewBinaryOperation(Token::Value op,
PreParserExpression left,
PreParserExpression right, int pos) {
- return PreParserExpression::Default();
+ return PreParserExpression::Default(pos);
}
PreParserExpression NewCompareOperation(Token::Value op,
PreParserExpression left,
PreParserExpression right, int pos) {
- return PreParserExpression::Default();
+ return PreParserExpression::Default(pos);
}
PreParserExpression NewAssignment(Token::Value op,
PreParserExpression left,
PreParserExpression right,
int pos) {
- return PreParserExpression::Default();
+ return PreParserExpression::Default(pos);
}
PreParserExpression NewYield(PreParserExpression generator_object,
PreParserExpression expression,
Yield::Kind yield_kind,
int pos) {
- return PreParserExpression::Default();
+ return PreParserExpression::Default(pos);
}
PreParserExpression NewConditional(PreParserExpression condition,
PreParserExpression then_expression,
PreParserExpression else_expression,
int pos) {
- return PreParserExpression::Default();
+ return PreParserExpression::Default(pos);
}
PreParserExpression NewCountOperation(Token::Value op,
bool is_prefix,
PreParserExpression expression,
int pos) {
- return PreParserExpression::Default();
+ return PreParserExpression::Default(pos);
}
PreParserExpression NewCall(PreParserExpression expression,
PreParserExpressionList arguments,
int pos) {
- return PreParserExpression::Call();
+ return PreParserExpression::Call(pos);
}
PreParserExpression NewCallNew(PreParserExpression expression,
PreParserExpressionList arguments,
int pos) {
- return PreParserExpression::Default();
+ return PreParserExpression::Default(pos);
}
+ PreParserStatement NewReturnStatement(PreParserExpression expression,
+ int pos) {
+ return PreParserStatement::Default();
+ }
+ PreParserExpression
+ NewFunctionLiteral(PreParserIdentifier name,
+ PreParserScope& scope,
+ PreParserStatementList body,
+ int materialized_literal_count,
+ int expected_property_count,
+ int handler_count,
+ int parameter_count,
+ FunctionLiteral::ParameterFlag has_duplicate_parameters,
+ FunctionLiteral::FunctionType function_type,
+ FunctionLiteral::IsFunctionFlag is_function,
+ FunctionLiteral::IsParenthesizedFlag is_parenthesized,
+ FunctionLiteral::IsGeneratorFlag is_generator,
marja 2014/04/24 08:08:06 Instead of IsGeneratorFlag and IsArrowFlag you sho
aperez 2014/04/24 12:38:37 Okay.
+ FunctionLiteral::IsArrowFlag is_arrow,
+ int position) {
+ return PreParserExpression::Default(position);
+ }
+
+ // Return the object itself as AstVisitor and implement the needed
+ // dummy method right in this class.
+ PreParserFactory* visitor() { return this; }
+ BailoutReason dont_optimize_reason() { return kNoReason; }
+ int* ast_properties() { return NULL; }
+ int* slot_processor() { return NULL; }
};
@@ -816,11 +962,17 @@ class PreParserTraits {
// Used by FunctionState and BlockState.
typedef PreParserScope Scope;
+ typedef PreParserScope ScopePtr;
+
// PreParser doesn't need to store generator variables.
typedef void GeneratorVariable;
// No interaction with Zones.
typedef void Zone;
+ typedef int AstProperties;
+ typedef int DeferredFeedbackSlotProcessor;
+ typedef Vector<const PreParserIdentifier> ParameterIdentifierVector;
+
// Return types for traversing functions.
typedef PreParserIdentifier Identifier;
typedef PreParserExpression Expression;
@@ -830,6 +982,7 @@ class PreParserTraits {
typedef PreParserExpression Literal;
typedef PreParserExpressionList ExpressionList;
typedef PreParserExpressionList PropertyList;
+ typedef PreParserStatementList StatementList;
// For constructing objects returned by the traversing functions.
typedef PreParserFactory Factory;
@@ -882,6 +1035,11 @@ class PreParserTraits {
// PreParser should not use FuncNameInferrer.
UNREACHABLE();
}
+ static void InferFunctionName(FuncNameInferrer* fni,
+ PreParserExpression expression) {
+ // PreParser should not use FuncNameInferrer.
+ UNREACHABLE();
+ }
static void CheckFunctionLiteralInsideTopLevelObjectLiteral(
PreParserScope* scope, PreParserExpression value, bool* has_function) {}
@@ -925,6 +1083,10 @@ class PreParserTraits {
const char* type, Handle<Object> arg, int pos) {
return PreParserExpression::Default();
}
+ PreParserScope NewScope(PreParserScope* outer_scope,
+ ScopeType scope_type) {
+ return PreParserScope(outer_scope, scope_type);
+ }
// Reporting errors.
void ReportMessageAt(Scanner::Location location,
@@ -943,7 +1105,10 @@ class PreParserTraits {
// "null" return type creators.
static PreParserIdentifier EmptyIdentifier() {
- return PreParserIdentifier::Default();
+ return PreParserIdentifier::Default(RelocInfo::kNoPosition);
+ }
+ static PreParserIdentifier EmptyIdentifierString() {
+ return PreParserIdentifier::Default(RelocInfo::kNoPosition);
}
static PreParserExpression EmptyExpression() {
return PreParserExpression::Default();
@@ -965,12 +1130,15 @@ class PreParserTraits {
PreParserIdentifier GetSymbol(Scanner* scanner);
static PreParserIdentifier NextLiteralString(Scanner* scanner,
PretenureFlag tenured) {
- return PreParserIdentifier::Default();
+ // This is used by the regexp parsing, which does not use the
+ // positions of items from the preparser mini-AST.
+ return PreParserIdentifier::Default(RelocInfo::kNoPosition);
}
static PreParserExpression ThisExpression(PreParserScope* scope,
- PreParserFactory* factory) {
- return PreParserExpression::This();
+ PreParserFactory* factory,
+ int pos = RelocInfo::kNoPosition) {
+ return PreParserExpression::This(pos);
}
static PreParserExpression ExpressionFromLiteral(
@@ -993,10 +1161,37 @@ class PreParserTraits {
return PreParserExpressionList();
}
+ static PreParserStatementList NewStatementList(int size, void* zone) {
+ return PreParserStatementList();
+ }
+
static PreParserExpressionList NewPropertyList(int size, void* zone) {
return PreParserExpressionList();
}
+ V8_INLINE void SkipLazyFunctionBody(
+ PreParserIdentifier function_name,
+ int* materialized_literal_count,
+ int* expected_property_count,
+ bool* ok);
+ V8_INLINE PreParserStatementList ParseEagerFunctionBody(
+ PreParserIdentifier function_name,
+ int pos,
+ Variable* fvar,
+ Token::Value fvar_init_op,
+ bool is_generator,
+ bool* ok);
+
+ // Utility functions
+ Vector<const PreParserIdentifier> ParameterListFromExpression(
+ PreParserExpression expression, bool* ok) {
+ return Vector<const PreParserIdentifier>::empty();
marja 2014/04/24 08:08:06 This makes PreParser accept a different language t
aperez 2014/04/24 12:38:37 That is actually a neat idea, I will give it a try
+ }
+
+ void CheckConflictingVarDeclarations(
+ PreParserScope scope,
+ bool* ok) {}
+
// Temporary glue; these functions will move to ParserBase.
PreParserExpression ParseV8Intrinsic(bool* ok);
PreParserExpression ParseFunctionLiteral(
@@ -1029,6 +1224,7 @@ class PreParser : public ParserBase<PreParserTraits> {
public:
typedef PreParserIdentifier Identifier;
typedef PreParserExpression Expression;
+ typedef PreParserStatement Statement;
enum PreParseResult {
kPreParseStackOverflow,
@@ -1090,53 +1286,6 @@ class PreParser : public ParserBase<PreParserTraits> {
kHasNoInitializers
};
- class Statement {
- public:
- static Statement Default() {
- return Statement(kUnknownStatement);
- }
-
- static Statement FunctionDeclaration() {
- return Statement(kFunctionDeclaration);
- }
-
- // Creates expression statement from expression.
- // Preserves being an unparenthesized string literal, possibly
- // "use strict".
- static Statement ExpressionStatement(Expression expression) {
- if (expression.IsUseStrictLiteral()) {
- return Statement(kUseStrictExpressionStatement);
- }
- if (expression.IsStringLiteral()) {
- return Statement(kStringLiteralExpressionStatement);
- }
- return Default();
- }
-
- bool IsStringLiteral() {
- return code_ == kStringLiteralExpressionStatement;
- }
-
- bool IsUseStrictLiteral() {
- return code_ == kUseStrictExpressionStatement;
- }
-
- bool IsFunctionDeclaration() {
- return code_ == kFunctionDeclaration;
- }
-
- private:
- enum Type {
- kUnknownStatement,
- kStringLiteralExpressionStatement,
- kUseStrictExpressionStatement,
- kFunctionDeclaration
- };
-
- explicit Statement(Type code) : code_(code) {}
- Type code_;
- };
-
enum SourceElements {
kUnknownSourceElements
};
@@ -1186,6 +1335,29 @@ class PreParser : public ParserBase<PreParserTraits> {
bool CheckInOrOf(bool accept_OF);
};
+
+void PreParserTraits::SkipLazyFunctionBody(
+ PreParserIdentifier function_name,
+ int* materialized_literal_count,
+ int* expected_property_count,
+ bool* ok) {
+ pre_parser_->SkipLazyFunctionBody(function_name,
+ materialized_literal_count, expected_property_count, ok);
+}
+
+
+PreParserStatementList PreParserTraits::ParseEagerFunctionBody(
+ PreParserIdentifier function_name,
+ int pos,
+ Variable* fvar,
+ Token::Value fvar_init_op,
+ bool is_generator,
+ bool* ok) {
+ return pre_parser_->ParseEagerFunctionBody(function_name,
+ pos, fvar, fvar_init_op, is_generator, ok);
+}
+
+
template<class Traits>
ParserBase<Traits>::FunctionState::FunctionState(
FunctionState** function_state_stack,
@@ -1211,6 +1383,30 @@ ParserBase<Traits>::FunctionState::FunctionState(
template<class Traits>
+ParserBase<Traits>::FunctionState::FunctionState(
+ FunctionState** function_state_stack,
+ typename Traits::Type::Scope** scope_stack,
+ typename Traits::Type::Scope** scope,
+ typename Traits::Type::Zone* extra_param)
+ : next_materialized_literal_index_(JSFunction::kLiteralsPrefixSize),
+ next_handler_index_(0),
+ expected_property_count_(0),
+ is_generator_(false),
+ generator_object_variable_(NULL),
+ function_state_stack_(function_state_stack),
+ outer_function_state_(*function_state_stack),
+ scope_stack_(scope_stack),
+ outer_scope_(*scope_stack),
+ saved_ast_node_id_(0),
+ extra_param_(extra_param),
+ factory_(extra_param) {
+ *scope_stack_ = *scope;
+ *function_state_stack = this;
+ Traits::SetUpFunctionState(this, extra_param);
+}
+
+
+template<class Traits>
ParserBase<Traits>::FunctionState::~FunctionState() {
*scope_stack_ = outer_scope_;
*function_state_stack_ = outer_function_state_;
@@ -1378,7 +1574,7 @@ ParserBase<Traits>::ParsePrimaryExpression(bool* ok) {
switch (token) {
case Token::THIS: {
Consume(Token::THIS);
- result = this->ThisExpression(scope_, factory());
+ result = this->ThisExpression(scope_, factory(), pos);
break;
}
@@ -1456,6 +1652,12 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseExpression(
// AssignmentExpression
// Expression ',' AssignmentExpression
+ if (allow_arrow_functions() && peek() == Token::RPAREN &&
+ scanner()->current_token() == Token::LPAREN) {
+ // Empty argument list for arrow functions: () => ...
+ return this->EmptyExpression();
+ }
+
ExpressionT result = this->ParseAssignmentExpression(accept_IN, CHECK_OK);
while (peek() == Token::COMMA) {
Expect(Token::COMMA, CHECK_OK);
@@ -1696,6 +1898,7 @@ typename ParserBase<Traits>::ExpressionT
ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, bool* ok) {
// AssignmentExpression ::
// ConditionalExpression
+ // ArrowFunction
// YieldExpression
// LeftHandSideExpression AssignmentOperator AssignmentExpression
@@ -1709,6 +1912,11 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, bool* ok) {
ExpressionT expression =
this->ParseConditionalExpression(accept_IN, CHECK_OK);
+ if (allow_arrow_functions() && peek() == Token::ARROW)
+ return this->ParseArrowFunctionLiteral(lhs_location.beg_pos,
+ expression,
+ CHECK_OK);
+
if (!Token::IsAssignmentOp(peek())) {
if (fni_ != NULL) fni_->Leave();
// Parsed conditional expression only (no assignment).
@@ -1762,7 +1970,8 @@ ParserBase<Traits>::ParseYieldExpression(bool* ok) {
Yield::Kind kind =
Check(Token::MUL) ? Yield::DELEGATING : Yield::SUSPEND;
ExpressionT generator_object =
- factory()->NewVariableProxy(function_state_->generator_object_variable());
+ factory()->NewVariableProxy(function_state_->generator_object_variable(),
+ pos);
ExpressionT expression =
ParseAssignmentExpression(false, CHECK_OK);
typename Traits::Type::YieldExpression yield =
@@ -2113,6 +2322,215 @@ ParserBase<Traits>::ParseMemberExpressionContinuation(ExpressionT expression,
}
+template <class Traits>
+typename ParserBase<Traits>::ExpressionT
+ParserBase<Traits>::ParseArrowFunctionLiteral(int start_pos,
+ ExpressionT params_ast,
+ bool* ok) {
+ // TODO(aperez): Change this to use ARROW_SCOPE
+ typename Traits::Type::ScopePtr scope =
+ this->NewScope(scope_, FUNCTION_SCOPE);
+
+ typename Traits::Type::StatementList body;
+ typename Traits::Type::AstProperties ast_properties;
+ typename Traits::Type::DeferredFeedbackSlotProcessor* slot_processor;
+ FunctionLiteral::IsParenthesizedFlag parenthesized = parenthesized_function_
+ ? FunctionLiteral::kIsParenthesized
+ : FunctionLiteral::kNotParenthesized;
+ FunctionLiteral::ParameterFlag duplicate_parameters;
+ BailoutReason dont_optimize_reason = kNoReason;
+ int materialized_literal_count = -1;
+ int expected_property_count = -1;
+ int handler_count = 0;
+ int num_parameters = 0;
+
+ { FunctionState function_state(&function_state_, &scope_, &scope, zone());
+ scope->set_start_position(start_pos);
+
+ Scanner::Location eval_args_error_loc = Scanner::Location::invalid();
+ Scanner::Location dupe_error_loc = Scanner::Location::invalid();
+ Scanner::Location reserved_loc = Scanner::Location::invalid();
+
+ if (peek() == Token::ARROW) {
+ // Function parameters are already parsed into an AST
+ typename Traits::Type::ParameterIdentifierVector params =
+ Traits::ParameterListFromExpression(params_ast, CHECK_OK);
+
+ if ((num_parameters = params.length()) > Code::kMaxArguments) {
+ ReportMessageAt(Scanner::Location(params_ast->position(), position()),
+ "too_many_parameters");
+ *ok = false;
+ return this->EmptyExpression();
+ }
+
+ // The vector has the items in reverse order.
+ for (int i = params.length() - 1; i >= 0; --i) {
+ const IdentifierT param_name = params.at(i)->name();
+ int param_pos = params.at(i)->position();
+
+ // Store locations for possible future error reports.
+ if (!eval_args_error_loc.IsValid() &&
+ this->IsEvalOrArguments(param_name)) {
+ eval_args_error_loc =
+ Scanner::Location(param_pos, param_pos + param_name->length());
+ }
+ if (!dupe_error_loc.IsValid() && scope_->IsDeclared(param_name)) {
+ dupe_error_loc =
+ Scanner::Location(param_pos, param_pos + param_name->length());
+ }
+
+ scope_->DeclareParameter(param_name, VAR);
+ }
+ } else {
+ if (peek() == Token::LPAREN) {
marja 2014/04/24 08:08:06 Hmm, so this function can be called in two ways, f
aperez 2014/04/24 12:38:37 Correct. In that case we know exactly where the pa
+ // Parse a parenthesized parameter list.
+ Consume(Token::LPAREN);
+ bool done = (peek() == Token::RPAREN);
+ while (!done) {
+ bool is_strict_reserved = false;
+ IdentifierT param_name =
+ ParseIdentifierOrStrictReservedWord(&is_strict_reserved,
+ CHECK_OK);
+
+ // Store locations for possible future error reports.
+ if (!eval_args_error_loc.IsValid() &&
+ this->IsEvalOrArguments(param_name)) {
+ eval_args_error_loc = scanner()->location();
+ }
+ if (!reserved_loc.IsValid() && is_strict_reserved) {
+ reserved_loc = scanner()->location();
+ }
+ if (!dupe_error_loc.IsValid() && scope_->IsDeclared(param_name)) {
+ dupe_error_loc = scanner()->location();
+ }
+
+ scope_->DeclareParameter(param_name, VAR);
+ num_parameters++;
+ if (num_parameters > Code::kMaxArguments) {
+ this->ReportMessageAt(scanner()->location(), "too_many_parameters");
+ *ok = false;
+ return this->EmptyExpression();
+ }
+ done = (peek() == Token::RPAREN);
+ if (!done) Expect(Token::COMMA, CHECK_OK);
+ }
+ Expect(Token::RPAREN, CHECK_OK);
+ } else {
+ // Parse a single parameter identifier.
+ bool is_strict_reserved = false;
+ IdentifierT param_name =
+ ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);
+
+ // Store locations for possible future error reports.
+ if (this->IsEvalOrArguments(param_name))
+ eval_args_error_loc = scanner()->location();
+ if (is_strict_reserved)
+ reserved_loc = scanner()->location();
+
+ scope_->DeclareParameter(param_name, VAR);
+ }
+ }
+
+ Expect(Token::ARROW, CHECK_OK);
+
+ if (peek() == Token::LBRACE) {
+ // Multiple statemente body
+ Consume(Token::LBRACE);
+
+ bool is_lazily_parsed = (mode() == PARSE_LAZILY &&
+ scope_->AllowsLazyCompilation() &&
+ !parenthesized_function_);
+ parenthesized_function_ = false; // This Was set for this funciton only.
+
+ if (is_lazily_parsed) {
+ this->SkipLazyFunctionBody(this->EmptyIdentifier(),
+ &materialized_literal_count,
+ &expected_property_count,
+ CHECK_OK);
+ } else {
+ body = this->ParseEagerFunctionBody(this->EmptyIdentifier(),
+ RelocInfo::kNoPosition,
+ NULL,
+ Token::INIT_VAR,
+ false, // Not a generator.
+ CHECK_OK);
+ materialized_literal_count =
+ function_state.materialized_literal_count();
+ expected_property_count = function_state.expected_property_count();
+ handler_count = function_state.handler_count();
+ }
+ } else {
+ // Single-expression body
+ int pos = position();
+ parenthesized_function_ = false;
+ ExpressionT expression = ParseAssignmentExpression(true, CHECK_OK);
+ body = this->NewStatementList(1, zone());
+ body->Add(factory()->NewReturnStatement(expression, pos), zone());
+ scope->set_end_position(scanner()->location().end_pos);
+ materialized_literal_count = function_state.materialized_literal_count();
+ expected_property_count = function_state.expected_property_count();
+ handler_count = function_state.handler_count();
+ }
+
+ // Validate strict mode.
+ if (strict_mode() == STRICT) {
+ if (eval_args_error_loc.IsValid()) {
+ this->ReportMessageAt(eval_args_error_loc, "strict_eval_arguments");
+ *ok = false;
+ return this->EmptyExpression();
+ }
+ if (dupe_error_loc.IsValid()) {
+ this->ReportMessageAt(dupe_error_loc, "strict_param_dupe");
+ *ok = false;
+ return this->EmptyExpression();
+ }
+ if (reserved_loc.IsValid()) {
+ this->ReportMessageAt(reserved_loc, "unexpected_strict_reserved");
+ *ok = false;
+ return this->EmptyExpression();
+ }
+ CheckOctalLiteral(start_pos,
+ scanner()->location().end_pos,
+ CHECK_OK);
+ }
+
+ duplicate_parameters = dupe_error_loc.IsValid()
+ ? FunctionLiteral::kHasDuplicateParameters
+ : FunctionLiteral::kNoDuplicateParameters;
+ ast_properties = *factory()->visitor()->ast_properties();
+ slot_processor = factory()->visitor()->slot_processor();
+ dont_optimize_reason = factory()->visitor()->dont_optimize_reason();
+ }
+
+ if (allow_harmony_scoping() && strict_mode() == STRICT)
+ this->CheckConflictingVarDeclarations(scope, CHECK_OK);
+
+ FunctionLiteralT function_literal =
+ factory()->NewFunctionLiteral(this->EmptyIdentifierString(),
+ scope,
+ body,
+ materialized_literal_count,
+ expected_property_count,
+ handler_count,
+ num_parameters,
+ duplicate_parameters,
+ FunctionLiteral::ANONYMOUS_EXPRESSION,
+ FunctionLiteral::kIsFunction,
+ parenthesized,
+ FunctionLiteral::kNotGenerator,
+ FunctionLiteral::kIsArrow,
+ start_pos);
+ function_literal->set_function_token_position(start_pos);
+ function_literal->set_ast_properties(&ast_properties);
+ function_literal->set_slot_processor(slot_processor);
+ function_literal->set_dont_optimize_reason(dont_optimize_reason);
+
+ if (fni_ != NULL) this->InferFunctionName(fni_, function_literal);
+
+ return function_literal;
+}
+
+
template <typename Traits>
typename ParserBase<Traits>::ExpressionT
ParserBase<Traits>::CheckAndRewriteReferenceExpression(
« src/parser.cc ('K') | « src/parser.cc ('k') | src/preparser.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698