Index: src/parsing/parser.cc |
diff --git a/src/parsing/parser.cc b/src/parsing/parser.cc |
index 33934c23fdf58a4ddc61bbb9880cedc4c8ca294e..3bf995244c3ca0678e1f99cf6abf7b72a9914b70 100644 |
--- a/src/parsing/parser.cc |
+++ b/src/parsing/parser.cc |
@@ -750,10 +750,10 @@ FunctionLiteral* ParserTraits::ParseFunctionLiteral( |
const AstRawString* name, Scanner::Location function_name_location, |
FunctionNameValidity function_name_validity, FunctionKind kind, |
int function_token_position, FunctionLiteral::FunctionType type, |
- LanguageMode language_mode, bool* ok) { |
+ LanguageMode language_mode, typesystem::TypeFlags type_flags, bool* ok) { |
return parser_->ParseFunctionLiteral( |
name, function_name_location, function_name_validity, kind, |
- function_token_position, type, language_mode, ok); |
+ function_token_position, type, language_mode, type_flags, ok); |
} |
@@ -1094,11 +1094,11 @@ FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info, |
BlockState block_state(&scope_, scope); |
if (Check(Token::LPAREN)) { |
// '(' StrictFormalParameters ')' |
- ParseFormalParameterList(&formals, &formals_classifier, &ok); |
+ ParseFormalParameterList(&formals, true, &formals_classifier, &ok); |
if (ok) ok = Check(Token::RPAREN); |
} else { |
// BindingIdentifier |
- ParseFormalParameter(&formals, &formals_classifier, &ok); |
+ ParseFormalParameter(&formals, false, &formals_classifier, &ok); |
if (ok) { |
DeclareFormalParameter(formals.scope, formals.at(0), |
&formals_classifier); |
@@ -1135,10 +1135,10 @@ FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info, |
shared_info->start_position(), shared_info->end_position(), |
shared_info->language_mode()); |
} else { |
- result = ParseFunctionLiteral(raw_name, Scanner::Location::invalid(), |
- kSkipFunctionNameCheck, shared_info->kind(), |
- RelocInfo::kNoPosition, function_type, |
- shared_info->language_mode(), &ok); |
+ result = ParseFunctionLiteral( |
+ raw_name, Scanner::Location::invalid(), kSkipFunctionNameCheck, |
+ shared_info->kind(), RelocInfo::kNoPosition, function_type, |
+ shared_info->language_mode(), typesystem::kNormalTypes, &ok); |
} |
// Make sure the results agree. |
DCHECK(ok == (result != NULL)); |
@@ -1605,7 +1605,7 @@ Statement* Parser::ParseExportDefault(bool* ok) { |
Consume(Token::FUNCTION); |
int pos = position(); |
bool is_generator = Check(Token::MUL); |
- if (peek() == Token::LPAREN) { |
+ if (peek() == Token::LPAREN || (scope_->typed() && Check(Token::LT))) { |
// FunctionDeclaration[+Default] :: |
// 'function' '(' FormalParameters ')' '{' FunctionBody '}' |
// |
@@ -1616,7 +1616,8 @@ Statement* Parser::ParseExportDefault(bool* ok) { |
kSkipFunctionNameCheck, |
is_generator ? FunctionKind::kGeneratorFunction |
: FunctionKind::kNormalFunction, |
- pos, FunctionLiteral::kDeclaration, language_mode(), CHECK_OK); |
+ pos, FunctionLiteral::kDeclaration, language_mode(), |
+ typesystem::kAllowSignature, CHECK_OK); |
result = factory()->NewEmptyStatement(RelocInfo::kNoPosition); |
} else { |
result = ParseFunctionDeclaration(pos, is_generator, &names, CHECK_OK); |
@@ -2167,13 +2168,17 @@ Statement* Parser::ParseFunctionDeclaration( |
FuncNameInferrer::State fni_state(fni_); |
if (fni_ != NULL) fni_->PushEnclosingName(name); |
- FunctionLiteral* fun = ParseFunctionLiteral( |
- name, scanner()->location(), |
- is_strict_reserved ? kFunctionNameIsStrictReserved |
- : kFunctionNameValidityUnknown, |
- is_generator ? FunctionKind::kGeneratorFunction |
- : FunctionKind::kNormalFunction, |
- pos, FunctionLiteral::kDeclaration, language_mode(), CHECK_OK); |
+ FunctionLiteral* fun = |
+ ParseFunctionLiteral(name, scanner()->location(), |
+ is_strict_reserved ? kFunctionNameIsStrictReserved |
+ : kFunctionNameValidityUnknown, |
+ is_generator ? FunctionKind::kGeneratorFunction |
+ : FunctionKind::kNormalFunction, |
+ pos, FunctionLiteral::kDeclaration, language_mode(), |
+ typesystem::kAllowSignature, CHECK_OK); |
+ // Return no function declaration if just the signature was given. |
+ EmptyStatement* empty = factory()->NewEmptyStatement(RelocInfo::kNoPosition); |
+ if (fun == nullptr) return empty; |
// Even if we're not at the top-level of the global or a function |
// scope, we treat it as such and introduce the function with its |
@@ -2190,7 +2195,6 @@ Statement* Parser::ParseFunctionDeclaration( |
factory()->NewFunctionDeclaration(proxy, mode, fun, scope_, pos); |
Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK); |
if (names) names->Add(name, zone()); |
- EmptyStatement* empty = factory()->NewEmptyStatement(RelocInfo::kNoPosition); |
if (is_sloppy(language_mode()) && allow_harmony_sloppy_function() && |
!scope_->is_declaration_scope()) { |
SloppyBlockFunctionStatement* delegate = |
@@ -2397,11 +2401,12 @@ Block* Parser::ParseVariableDeclarations( |
} |
} |
- // Optional type annotation. |
- if (scope_->typed() && Check(Token::COLON)) { |
- typename TypeSystem::Type type = ParseValidType(CHECK_OK); |
- USE(type); |
+ // Parse optional type annotation. |
+ typename TypeSystem::Type type = this->EmptyType(); |
+ if (scope_->typed() && Check(Token::COLON)) { // Braces required here. |
+ type = ParseValidType(CHECK_OK); |
} |
+ USE(type); // TODO(nikolaos): really use it! |
Scanner::Location variable_loc = scanner()->location(); |
const AstRawString* single_name = |
@@ -4094,11 +4099,13 @@ void ParserTraits::ReindexLiterals(const ParserFormalParameters& parameters) { |
} |
+// This function may return a nullptr with *ok==true in typed mode, |
+// if (type_flags & kAllowSignature) and a function signature is parsed. |
FunctionLiteral* Parser::ParseFunctionLiteral( |
const AstRawString* function_name, Scanner::Location function_name_location, |
FunctionNameValidity function_name_validity, FunctionKind kind, |
int function_token_pos, FunctionLiteral::FunctionType function_type, |
- LanguageMode language_mode, bool* ok) { |
+ LanguageMode language_mode, typesystem::TypeFlags type_flags, bool* ok) { |
// Function :: |
// '(' FormalParameterList? ')' '{' FunctionBody '}' |
// |
@@ -4193,17 +4200,46 @@ FunctionLiteral* Parser::ParseFunctionLiteral( |
function_state.set_generator_object_variable(temp); |
} |
+ // Parse optional type parameters. |
+ typename TypeSystem::TypeParameters type_parameters = |
+ this->NullTypeParameters(); |
+ if (scope_->typed() && |
+ !(type_flags & typesystem::kDisallowTypeParameters) && |
+ peek() == Token::LT) { // Braces required here. |
+ type_parameters = ParseTypeParameters(CHECK_OK); |
+ } |
+ USE(type_parameters); // TODO(nikolaos): really use them! |
+ |
Expect(Token::LPAREN, CHECK_OK); |
int start_position = scanner()->location().beg_pos; |
scope_->set_start_position(start_position); |
ParserFormalParameters formals(scope); |
- ParseFormalParameterList(&formals, &formals_classifier, CHECK_OK); |
+ ParseFormalParameterList(&formals, kind != FunctionKind::kSetterFunction, |
+ &formals_classifier, CHECK_OK); |
arity = formals.Arity(); |
Expect(Token::RPAREN, CHECK_OK); |
int formals_end_position = scanner()->location().end_pos; |
CheckArityRestrictions(arity, kind, formals.has_rest, start_position, |
formals_end_position, CHECK_OK); |
+ |
+ // Parse optional type annotation. |
+ typename TypeSystem::Type result_type = this->EmptyType(); |
+ if (scope_->typed() && |
+ !(type_flags & typesystem::kDisallowTypeAnnotation) && |
+ Check(Token::COLON)) { // Braces required here. |
+ result_type = ParseValidType(CHECK_OK); |
+ } |
+ USE(result_type); // TODO(nikolaos): really use it! |
+ |
+ // Allow for a function signature (i.e., a literal without body). |
+ // In that case, return a nullptr instead of a function literal. |
+ if (peek() != Token::LBRACE && scope_->typed() && |
+ (type_flags & typesystem::kAllowSignature)) { |
+ ExpectSemicolon(CHECK_OK); |
+ return nullptr; |
+ } |
+ |
Expect(Token::LBRACE, CHECK_OK); |
// Don't include the rest parameter into the function's formal parameter |