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( |