void AstExpressionVisitor::VisitSpread(Spread* expr) {}
+void AstExpressionVisitor::VisitEmptyParentheses(EmptyParentheses* expr) {}
+
+
void AstExpressionVisitor::VisitSuperPropertyReference(
SuperPropertyReference* expr) {}
}
+void AstLiteralReindexer::VisitEmptyParentheses(EmptyParentheses* node) {}
+
+
void AstLiteralReindexer::VisitForInStatement(ForInStatement* node) {
Visit(node->each());
Visit(node->enumerable());
}
+void AstNumberingVisitor::VisitEmptyParentheses(EmptyParentheses* node) {
+ UNREACHABLE();
+}
+
+
void AstNumberingVisitor::VisitForInStatement(ForInStatement* node) {
IncrementNodeCount();
DisableSelfOptimization();
V(ThisFunction) \
V(SuperPropertyReference) \
V(SuperCallReference) \
- V(CaseClause)
+ V(CaseClause) \
+ V(EmptyParentheses)
#define AST_NODE_LIST(V) \
DECLARATION_NODE_LIST(V) \
};
+// This class is produced when parsing the () in arrow functions without any
+// arguments and is not actually a valid expression.
+class EmptyParentheses final : public Expression {
+ public:
+ DECLARE_NODE_TYPE(EmptyParentheses)
+
+ private:
+ EmptyParentheses(Zone* zone, int pos) : Expression(zone, pos) {}
+};
+
+
#undef DECLARE_NODE_TYPE
this_function_var, pos);
}
+ EmptyParentheses* NewEmptyParentheses(int pos) {
+ return new (zone_) EmptyParentheses(zone_, pos);
+ }
+
private:
Zone* zone_;
AstValueFactory* ast_value_factory_;
}
+void AstGraphBuilder::VisitEmptyParentheses(EmptyParentheses* expr) {
+ // Handled entirely by the parser itself.
+ UNREACHABLE();
+}
+
+
void AstGraphBuilder::VisitThisFunction(ThisFunction* expr) {
Node* value = GetFunctionClosure();
ast_context()->ProduceValue(value);
void ALAA::VisitSpread(Spread* e) { Visit(e->expression()); }
+void ALAA::VisitEmptyParentheses(EmptyParentheses* e) { UNREACHABLE(); }
+
+
void ALAA::VisitCaseClause(CaseClause* cc) {
if (!cc->is_default()) Visit(cc->label());
VisitStatements(cc->statements());
void FullCodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); }
+void FullCodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) {
+ UNREACHABLE();
+}
+
+
FullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit(
int* stack_depth, int* context_length) {
// The macros used here must preserve the result register.
void HOptimizedGraphBuilder::VisitSpread(Spread* expr) { UNREACHABLE(); }
+void HOptimizedGraphBuilder::VisitEmptyParentheses(EmptyParentheses* expr) {
+ UNREACHABLE();
+}
+
+
HInstruction* HOptimizedGraphBuilder::BuildThisFunction() {
// If we share optimized code between different closures, the
// this-function is not a constant, except inside an inlined body.
}
-void BytecodeGenerator::VisitSpread(Spread* node) { UNIMPLEMENTED(); }
+void BytecodeGenerator::VisitSpread(Spread* node) { UNREACHABLE(); }
+
+
+void BytecodeGenerator::VisitEmptyParentheses(EmptyParentheses* node) {
+ UNREACHABLE();
+}
void BytecodeGenerator::VisitThisFunction(ThisFunction* node) {
T(MalformedArrowFunParamList, "Malformed arrow function parameter list") \
T(MalformedRegExp, "Invalid regular expression: /%/: %") \
T(MalformedRegExpFlags, "Invalid regular expression flags") \
- T(MissingArrow, \
- "Expected () to start arrow function, but got '%' instead of '=>'") \
T(ModuleExportUndefined, "Export '%' is not defined in module") \
T(MultipleDefaultsInSwitch, \
"More than one default clause in switch statement") \
ParserFormalParameters* parameters, Expression* expr,
const Scanner::Location& params_loc,
Scanner::Location* duplicate_loc, bool* ok) {
+ if (expr->IsEmptyParentheses()) return;
+
ParseArrowFunctionFormalParameters(parameters, expr, params_loc,
duplicate_loc, ok);
if (!*ok) return;
void Parser::PatternRewriter::VisitSpread(Spread* node) {
- // TODO(dslomov): implement.
+ UNREACHABLE();
+}
+
+
+void Parser::PatternRewriter::VisitEmptyParentheses(EmptyParentheses* node) {
+ UNREACHABLE();
}
return PreParserExpression::Spread(expression);
}
+ PreParserExpression NewEmptyParentheses(int pos) {
+ return PreParserExpression::Default();
+ }
+
// Return the object itself as AstVisitor and implement the needed
// dummy method right in this class.
PreParserFactory* visitor() { return this; }
}
BindingPatternUnexpectedToken(classifier);
Consume(Token::LPAREN);
- if (allow_harmony_arrow_functions() && Check(Token::RPAREN)) {
- // As a primary expression, the only thing that can follow "()" is "=>".
+ if (Check(Token::RPAREN)) {
+ // ()=>x. The continuation that looks for the => is in
+ // ParseAssignmentExpression.
+ classifier->RecordExpressionError(scanner()->location(),
+ MessageTemplate::kUnexpectedToken,
+ Token::String(Token::RPAREN));
classifier->RecordBindingPatternError(scanner()->location(),
MessageTemplate::kUnexpectedToken,
Token::String(Token::RPAREN));
- // Give a good error to the user who might have typed e.g. "return();".
- if (peek() != Token::ARROW) {
- ReportUnexpectedTokenAt(scanner_->peek_location(), peek(),
- MessageTemplate::kMissingArrow);
+ result = factory()->NewEmptyParentheses(beg_pos);
+ } else if (allow_harmony_rest_parameters() && Check(Token::ELLIPSIS)) {
+ // (...x)=>x. The continuation that looks for the => is in
+ // ParseAssignmentExpression.
+ int ellipsis_pos = scanner()->location().beg_pos;
+ classifier->RecordExpressionError(scanner()->location(),
+ MessageTemplate::kUnexpectedToken,
+ Token::String(Token::ELLIPSIS));
+ Scanner::Location expr_loc = scanner()->peek_location();
+ Token::Value tok = peek();
+ result = this->ParseAssignmentExpression(true, classifier, CHECK_OK);
+ // Patterns are not allowed as rest parameters. There is no way we can
+ // succeed so go ahead and use the convenient ReportUnexpectedToken
+ // interface.
+ if (!Traits::IsIdentifier(result)) {
+ ReportUnexpectedTokenAt(expr_loc, tok);
*ok = false;
return this->EmptyExpression();
}
- Scope* scope =
- this->NewScope(scope_, ARROW_SCOPE, FunctionKind::kArrowFunction);
- FormalParametersT parameters(scope);
- scope->set_start_position(beg_pos);
- ExpressionClassifier args_classifier;
- result = this->ParseArrowFunctionLiteral(parameters, args_classifier,
- CHECK_OK);
- } else if (allow_harmony_arrow_functions() &&
- allow_harmony_rest_parameters() && Check(Token::ELLIPSIS)) {
- // (...x) => y
- Scope* scope =
- this->NewScope(scope_, ARROW_SCOPE, FunctionKind::kArrowFunction);
- FormalParametersT formals(scope);
- scope->set_start_position(beg_pos);
- ExpressionClassifier formals_classifier;
- formals.has_rest = true;
- this->ParseFormalParameter(&formals, &formals_classifier, CHECK_OK);
- Traits::DeclareFormalParameter(
- formals.scope, formals.at(0), formals.is_simple,
- &formals_classifier);
+ result = factory()->NewSpread(result, ellipsis_pos);
if (peek() == Token::COMMA) {
ReportMessageAt(scanner()->peek_location(),
MessageTemplate::kParamAfterRest);
return this->EmptyExpression();
}
Expect(Token::RPAREN, CHECK_OK);
- result = this->ParseArrowFunctionLiteral(formals, formals_classifier,
- CHECK_OK);
} else {
// Heuristically try to detect immediately called functions before
// seeing the call parentheses.
}
+void CallPrinter::VisitEmptyParentheses(EmptyParentheses* node) {
+ UNREACHABLE();
+}
+
+
void CallPrinter::VisitThisFunction(ThisFunction* node) {}
}
+void PrettyPrinter::VisitEmptyParentheses(EmptyParentheses* node) {
+ Print("()");
+}
+
+
void PrettyPrinter::VisitThisFunction(ThisFunction* node) {
Print("<this-function>");
}
}
+void AstPrinter::VisitEmptyParentheses(EmptyParentheses* node) {
+ IndentedScope indent(this, "()");
+}
+
+
void AstPrinter::VisitThisFunction(ThisFunction* node) {
IndentedScope indent(this, "THIS-FUNCTION");
}
void AstTyper::VisitSpread(Spread* expr) { RECURSE(Visit(expr->expression())); }
+void AstTyper::VisitEmptyParentheses(EmptyParentheses* expr) {
+ UNREACHABLE();
+}
+
+
void AstTyper::VisitThisFunction(ThisFunction* expr) {
}
-*%(basename)s:7: SyntaxError: Expected () to start arrow function, but got ';' instead of '=>'
+*%(basename)s:7: SyntaxError: Unexpected token )
function foo() { return(); }
- ^
-SyntaxError: Expected () to start arrow function, but got ';' instead of '=>'
+ ^
+SyntaxError: Unexpected token )
--- /dev/null
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Flags: --harmony-arrow-functions --harmony-rest-parameters
+
+assertThrows("()=>{}()", SyntaxError);
+assertThrows("x=>{}()", SyntaxError);
+assertThrows("(...x)=>{}()", SyntaxError);
+assertThrows("(x)=>{}()", SyntaxError);
+assertThrows("(x,y)=>{}()", SyntaxError);
+assertThrows("(x,y,...z)=>{}()", SyntaxError);