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

Side by Side Diff: runtime/vm/parser.cc

Issue 447003003: Introduce await (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 4 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/parser.h" 5 #include "vm/parser.h"
6 6
7 #include "lib/invocation_mirror.h" 7 #include "lib/invocation_mirror.h"
8 #include "platform/utils.h" 8 #include "platform/utils.h"
9 #include "vm/ast_transformer.h"
9 #include "vm/bootstrap.h" 10 #include "vm/bootstrap.h"
10 #include "vm/class_finalizer.h" 11 #include "vm/class_finalizer.h"
11 #include "vm/compiler.h" 12 #include "vm/compiler.h"
12 #include "vm/compiler_stats.h" 13 #include "vm/compiler_stats.h"
13 #include "vm/dart_api_impl.h" 14 #include "vm/dart_api_impl.h"
14 #include "vm/dart_entry.h" 15 #include "vm/dart_entry.h"
15 #include "vm/flags.h" 16 #include "vm/flags.h"
16 #include "vm/growable_array.h" 17 #include "vm/growable_array.h"
17 #include "vm/handles.h" 18 #include "vm/handles.h"
18 #include "vm/heap.h" 19 #include "vm/heap.h"
(...skipping 2945 matching lines...) Expand 10 before | Expand all | Expand 10 after
2964 } 2965 }
2965 ASSERT((CurrentToken() == Token::kLPAREN) || 2966 ASSERT((CurrentToken() == Token::kLPAREN) ||
2966 func.IsGetterFunction() || 2967 func.IsGetterFunction() ||
2967 func.is_async_closure()); 2968 func.is_async_closure());
2968 const bool allow_explicit_default_values = true; 2969 const bool allow_explicit_default_values = true;
2969 if (func.IsGetterFunction()) { 2970 if (func.IsGetterFunction()) {
2970 // Populate function scope with the formal parameters. Since in this case 2971 // Populate function scope with the formal parameters. Since in this case
2971 // we are compiling a getter this will at most populate the receiver. 2972 // we are compiling a getter this will at most populate the receiver.
2972 AddFormalParamsToScope(&params, current_block_->scope); 2973 AddFormalParamsToScope(&params, current_block_->scope);
2973 } else if (func.is_async_closure()) { 2974 } else if (func.is_async_closure()) {
2975 // Async closures have one optional parameter for continuation results.
2976 ParamDesc result_param;
2977 result_param.name = &Symbols::AsyncOperationParam();
2978 result_param.default_value = &Object::null_instance();
2979 result_param.type = &Type::ZoneHandle(I, Type::DynamicType());
2980 params.parameters->Add(result_param);
2981 params.num_optional_parameters++;
2982 params.has_optional_positional_parameters = true;
2983 SetupDefaultsForOptionalParams(&params, default_parameter_values);
2974 AddFormalParamsToScope(&params, current_block_->scope); 2984 AddFormalParamsToScope(&params, current_block_->scope);
2975 ASSERT(AbstractType::Handle(I, func.result_type()).IsResolved()); 2985 ASSERT(AbstractType::Handle(I, func.result_type()).IsResolved());
2976 ASSERT(func.NumParameters() == params.parameters->length()); 2986 ASSERT(func.NumParameters() == params.parameters->length());
2977 if (!Function::Handle(func.parent_function()).IsGetterFunction()) { 2987 if (!Function::Handle(func.parent_function()).IsGetterFunction()) {
2978 // Parse away any formal parameters, as they are accessed as as context 2988 // Parse away any formal parameters, as they are accessed as as context
2979 // variables. 2989 // variables.
2980 ParseFormalParameterList(allow_explicit_default_values, false, &params); 2990 ParseFormalParameterList(allow_explicit_default_values, false, &params);
2981 } 2991 }
2982 } else { 2992 } else {
2983 ParseFormalParameterList(allow_explicit_default_values, false, &params); 2993 ParseFormalParameterList(allow_explicit_default_values, false, &params);
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
3020 } 3030 }
3021 3031
3022 RawFunction::AsyncModifier func_modifier = ParseFunctionModifier(); 3032 RawFunction::AsyncModifier func_modifier = ParseFunctionModifier();
3023 func.set_modifier(func_modifier); 3033 func.set_modifier(func_modifier);
3024 3034
3025 OpenBlock(); // Open a nested scope for the outermost function block. 3035 OpenBlock(); // Open a nested scope for the outermost function block.
3026 3036
3027 Function& async_closure = Function::ZoneHandle(I); 3037 Function& async_closure = Function::ZoneHandle(I);
3028 if (func.IsAsyncFunction() && !func.is_async_closure()) { 3038 if (func.IsAsyncFunction() && !func.is_async_closure()) {
3029 async_closure = OpenAsyncFunction(formal_params_pos); 3039 async_closure = OpenAsyncFunction(formal_params_pos);
3040 } else if (func.is_async_closure()) {
3041 OpenAsyncClosure();
3030 } 3042 }
3031 3043
3032 intptr_t end_token_pos = 0; 3044 intptr_t end_token_pos = 0;
3033 if (CurrentToken() == Token::kLBRACE) { 3045 if (CurrentToken() == Token::kLBRACE) {
3034 ConsumeToken(); 3046 ConsumeToken();
3035 if (String::Handle(I, func.name()).Equals( 3047 if (String::Handle(I, func.name()).Equals(
3036 Symbols::EqualOperator())) { 3048 Symbols::EqualOperator())) {
3037 const Class& owner = Class::Handle(I, func.Owner()); 3049 const Class& owner = Class::Handle(I, func.Owner());
3038 if (!owner.IsObjectClass()) { 3050 if (!owner.IsObjectClass()) {
3039 AddEqualityNullCheck(); 3051 AddEqualityNullCheck();
(...skipping 2461 matching lines...) Expand 10 before | Expand all | Expand 10 after
5501 // We are parsing a nested function while compiling the enclosing function. 5513 // We are parsing a nested function while compiling the enclosing function.
5502 outer_scope = 5514 outer_scope =
5503 new(I) LocalScope(current_block_->scope, 5515 new(I) LocalScope(current_block_->scope,
5504 current_block_->scope->function_level() + 1, 5516 current_block_->scope->function_level() + 1,
5505 0); 5517 0);
5506 } 5518 }
5507 ChainNewBlock(outer_scope); 5519 ChainNewBlock(outer_scope);
5508 } 5520 }
5509 5521
5510 5522
5523 void Parser::OpenAsyncClosure() {
5524 parsed_function()->set_await_temps_scope(current_block_->scope);
5525 // TODO(mlippautz): Set up explicit jump table for await continuations.
5526 }
5527
5528
5511 RawFunction* Parser::OpenAsyncFunction(intptr_t formal_param_pos) { 5529 RawFunction* Parser::OpenAsyncFunction(intptr_t formal_param_pos) {
5512 // Create the closure containing the old body of this function. 5530 // Create the closure containing the old body of this function.
5513 Class& sig_cls = Class::ZoneHandle(I); 5531 Class& sig_cls = Class::ZoneHandle(I);
5514 Type& sig_type = Type::ZoneHandle(I); 5532 Type& sig_type = Type::ZoneHandle(I);
5515 Function& closure = Function::ZoneHandle(I); 5533 Function& closure = Function::ZoneHandle(I);
5516 String& sig = String::ZoneHandle(I); 5534 String& sig = String::ZoneHandle(I);
5517 ParamList closure_params; 5535 ParamList closure_params;
5518 closure_params.AddFinalParameter( 5536 closure_params.AddFinalParameter(
5519 formal_param_pos, 5537 formal_param_pos,
5520 &Symbols::ClosureParameter(), 5538 &Symbols::ClosureParameter(),
5521 &Type::ZoneHandle(I, Type::DynamicType())); 5539 &Type::ZoneHandle(I, Type::DynamicType()));
5540 ParamDesc result_param;
5541 result_param.name = &Symbols::AsyncOperationParam();
5542 result_param.default_value = &Object::null_instance();
5543 result_param.type = &Type::ZoneHandle(I, Type::DynamicType());
5544 closure_params.parameters->Add(result_param);
5545 closure_params.has_optional_positional_parameters = true;
5546 closure_params.num_optional_parameters++;
5522 closure = Function::NewClosureFunction( 5547 closure = Function::NewClosureFunction(
5523 Symbols::AnonymousClosure(), 5548 Symbols::AnonymousClosure(),
5524 innermost_function(), 5549 innermost_function(),
5525 formal_param_pos); 5550 formal_param_pos);
5526 AddFormalParamsToFunction(&closure_params, closure); 5551 AddFormalParamsToFunction(&closure_params, closure);
5527 closure.set_is_async_closure(true); 5552 closure.set_is_async_closure(true);
5553 closure.set_is_inlinable(false);
5528 closure.set_result_type(AbstractType::Handle(Type::DynamicType())); 5554 closure.set_result_type(AbstractType::Handle(Type::DynamicType()));
5529 sig = closure.Signature(); 5555 sig = closure.Signature();
5530 sig_cls = library_.LookupLocalClass(sig); 5556 sig_cls = library_.LookupLocalClass(sig);
5531 if (sig_cls.IsNull()) { 5557 if (sig_cls.IsNull()) {
5532 sig_cls = Class::NewSignatureClass(sig, closure, script_, formal_param_pos); 5558 sig_cls = Class::NewSignatureClass(sig, closure, script_, formal_param_pos);
5533 library_.AddClass(sig_cls); 5559 library_.AddClass(sig_cls);
5534 } 5560 }
5535 closure.set_signature_class(sig_cls); 5561 closure.set_signature_class(sig_cls);
5536 sig_type = sig_cls.SignatureType(); 5562 sig_type = sig_cls.SignatureType();
5537 if (!sig_type.IsFinalized()) { 5563 if (!sig_type.IsFinalized()) {
(...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after
5884 const intptr_t ident_pos = TokenPos(); 5910 const intptr_t ident_pos = TokenPos();
5885 const String& ident = *CurrentLiteral(); 5911 const String& ident = *CurrentLiteral();
5886 LocalVariable* variable = new(I) LocalVariable( 5912 LocalVariable* variable = new(I) LocalVariable(
5887 ident_pos, ident, type); 5913 ident_pos, ident, type);
5888 ConsumeToken(); // Variable identifier. 5914 ConsumeToken(); // Variable identifier.
5889 AstNode* initialization = NULL; 5915 AstNode* initialization = NULL;
5890 if (CurrentToken() == Token::kASSIGN) { 5916 if (CurrentToken() == Token::kASSIGN) {
5891 // Variable initialization. 5917 // Variable initialization.
5892 const intptr_t assign_pos = TokenPos(); 5918 const intptr_t assign_pos = TokenPos();
5893 ConsumeToken(); 5919 ConsumeToken();
5894 AstNode* expr = ParseExpr(is_const, kConsumeCascades); 5920 AstNode* expr = ParseAwaitableExpr(is_const, kConsumeCascades);
5895 initialization = new(I) StoreLocalNode( 5921 initialization = new(I) StoreLocalNode(
5896 assign_pos, variable, expr); 5922 assign_pos, variable, expr);
5897 if (is_const) { 5923 if (is_const) {
5898 ASSERT(expr->IsLiteralNode()); 5924 ASSERT(expr->IsLiteralNode());
5899 variable->SetConstValue(expr->AsLiteralNode()->literal()); 5925 variable->SetConstValue(expr->AsLiteralNode()->literal());
5900 } 5926 }
5901 } else if (is_final || is_const) { 5927 } else if (is_final || is_const) {
5902 ReportError(ident_pos, 5928 ReportError(ident_pos,
5903 "missing initialization of 'final' or 'const' variable"); 5929 "missing initialization of 'final' or 'const' variable");
5904 } else { 5930 } else {
(...skipping 1856 matching lines...) Expand 10 before | Expand all | Expand 10 after
7761 scope->LocalLookupVariable(Symbols::ExceptionVar()); 7787 scope->LocalLookupVariable(Symbols::ExceptionVar());
7762 ASSERT(excp_var != NULL); 7788 ASSERT(excp_var != NULL);
7763 LocalVariable* trace_var = 7789 LocalVariable* trace_var =
7764 scope->LocalLookupVariable(Symbols::StackTraceVar()); 7790 scope->LocalLookupVariable(Symbols::StackTraceVar());
7765 ASSERT(trace_var != NULL); 7791 ASSERT(trace_var != NULL);
7766 statement = new(I) ThrowNode( 7792 statement = new(I) ThrowNode(
7767 statement_pos, 7793 statement_pos,
7768 new(I) LoadLocalNode(statement_pos, excp_var), 7794 new(I) LoadLocalNode(statement_pos, excp_var),
7769 new(I) LoadLocalNode(statement_pos, trace_var)); 7795 new(I) LoadLocalNode(statement_pos, trace_var));
7770 } else { 7796 } else {
7771 statement = ParseExpr(kAllowConst, kConsumeCascades); 7797 statement = ParseAwaitableExpr(kAllowConst, kConsumeCascades);
7772 ExpectSemicolon(); 7798 ExpectSemicolon();
7773 } 7799 }
7774 return statement; 7800 return statement;
7775 } 7801 }
7776 7802
7777 7803
7778 void Parser::ReportError(const Error& error) { 7804 void Parser::ReportError(const Error& error) {
7779 Report::LongJump(error); 7805 Report::LongJump(error);
7780 UNREACHABLE(); 7806 UNREACHABLE();
7781 } 7807 }
(...skipping 635 matching lines...) Expand 10 before | Expand all | Expand 10 after
8417 ASSERT(field.value() != Object::sentinel().raw()); 8443 ASSERT(field.value() != Object::sentinel().raw());
8418 ASSERT(field.value() != Object::transition_sentinel().raw()); 8444 ASSERT(field.value() != Object::transition_sentinel().raw());
8419 return new(iso) LiteralNode(expr->token_pos(), 8445 return new(iso) LiteralNode(expr->token_pos(),
8420 Instance::ZoneHandle(iso, field.value())); 8446 Instance::ZoneHandle(iso, field.value()));
8421 } 8447 }
8422 } 8448 }
8423 return expr; 8449 return expr;
8424 } 8450 }
8425 8451
8426 8452
8453 AstNode* Parser::ParseAwaitableExpr(bool require_compiletime_const,
8454 bool consume_cascades) {
8455 TRACE_PARSER("ParseAwaitableExpr");
8456 parsed_function()->reset_seen_await();
8457 AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades);
8458 if (parsed_function()->seen_await()) {
8459 if (!current_block_->scope->LookupVariable(
8460 Symbols::AsyncOperation(), true)) {
8461 // Async operations are always encapsulated into a local function. We only
8462 // need to transform the expression when generating code for this inner
8463 // function.
8464 return expr;
8465 }
8466 SequenceNode* intermediates_block = new (I) SequenceNode(
8467 Scanner::kNoSourcePos, current_block_->scope);
8468 AwaitTransformer at(intermediates_block, library_, parsed_function());
8469 at.Transform(expr);
8470 current_block_->statements->Add(intermediates_block);
8471 parsed_function()->reset_seen_await();
8472 return at.Result();
8473 }
8474 return expr;
8475 }
8476
8477
8478 AstNode* Parser::ParseAwaitExpr() {
8479 TRACE_PARSER("ParseAwaitExpr");
8480 ConsumeToken();
8481 parsed_function()->record_await();
8482 return new (I) AwaitNode(
8483 TokenPos(), ParseExpr(kAllowConst, kConsumeCascades));
8484 }
8485
8486
8427 AstNode* Parser::ParseExpr(bool require_compiletime_const, 8487 AstNode* Parser::ParseExpr(bool require_compiletime_const,
8428 bool consume_cascades) { 8488 bool consume_cascades) {
8429 TRACE_PARSER("ParseExpr"); 8489 TRACE_PARSER("ParseExpr");
8430 String* expr_ident = 8490 String* expr_ident =
8431 Token::IsIdentifier(CurrentToken()) ? CurrentLiteral() : NULL; 8491 Token::IsIdentifier(CurrentToken()) ? CurrentLiteral() : NULL;
8432 const intptr_t expr_pos = TokenPos(); 8492 const intptr_t expr_pos = TokenPos();
8433 8493
8434 if (CurrentToken() == Token::kTHROW) { 8494 if (CurrentToken() == Token::kTHROW) {
8435 ConsumeToken(); 8495 ConsumeToken();
8436 if (CurrentToken() == Token::kSEMICOLON) { 8496 if (CurrentToken() == Token::kSEMICOLON) {
(...skipping 2348 matching lines...) Expand 10 before | Expand all | Expand 10 after
10785 TRACE_PARSER("ParsePrimary"); 10845 TRACE_PARSER("ParsePrimary");
10786 ASSERT(!is_top_level_); 10846 ASSERT(!is_top_level_);
10787 AstNode* primary = NULL; 10847 AstNode* primary = NULL;
10788 const Token::Kind token = CurrentToken(); 10848 const Token::Kind token = CurrentToken();
10789 if (IsFunctionLiteral()) { 10849 if (IsFunctionLiteral()) {
10790 // The name of a literal function is visible from inside the function, but 10850 // The name of a literal function is visible from inside the function, but
10791 // must not collide with names in the scope declaring the literal. 10851 // must not collide with names in the scope declaring the literal.
10792 OpenBlock(); 10852 OpenBlock();
10793 primary = ParseFunctionStatement(true); 10853 primary = ParseFunctionStatement(true);
10794 CloseBlock(); 10854 CloseBlock();
10855 } else if (IsLiteral("await")) {
Michael Lippautz (Google) 2014/08/07 00:18:55 Let's see whether this will get a keyword
10856 primary = ParseAwaitExpr();
10795 } else if (IsIdentifier()) { 10857 } else if (IsIdentifier()) {
10796 intptr_t qual_ident_pos = TokenPos(); 10858 intptr_t qual_ident_pos = TokenPos();
10797 const LibraryPrefix& prefix = LibraryPrefix::ZoneHandle(I, ParsePrefix()); 10859 const LibraryPrefix& prefix = LibraryPrefix::ZoneHandle(I, ParsePrefix());
10798 String& ident = *CurrentLiteral(); 10860 String& ident = *CurrentLiteral();
10799 ConsumeToken(); 10861 ConsumeToken();
10800 if (prefix.IsNull()) { 10862 if (prefix.IsNull()) {
10801 if (!ResolveIdentInLocalScope(qual_ident_pos, ident, &primary)) { 10863 if (!ResolveIdentInLocalScope(qual_ident_pos, ident, &primary)) {
10802 // Check whether the identifier is a type parameter. 10864 // Check whether the identifier is a type parameter.
10803 if (!current_class().IsNull()) { 10865 if (!current_class().IsNull()) {
10804 TypeParameter& type_param = TypeParameter::ZoneHandle(I, 10866 TypeParameter& type_param = TypeParameter::ZoneHandle(I,
(...skipping 520 matching lines...) Expand 10 before | Expand all | Expand 10 after
11325 void Parser::SkipQualIdent() { 11387 void Parser::SkipQualIdent() {
11326 ASSERT(IsIdentifier()); 11388 ASSERT(IsIdentifier());
11327 ConsumeToken(); 11389 ConsumeToken();
11328 if (CurrentToken() == Token::kPERIOD) { 11390 if (CurrentToken() == Token::kPERIOD) {
11329 ConsumeToken(); // Consume the kPERIOD token. 11391 ConsumeToken(); // Consume the kPERIOD token.
11330 ExpectIdentifier("identifier expected after '.'"); 11392 ExpectIdentifier("identifier expected after '.'");
11331 } 11393 }
11332 } 11394 }
11333 11395
11334 } // namespace dart 11396 } // namespace dart
OLDNEW
« runtime/vm/ast_transformer.cc ('K') | « runtime/vm/parser.h ('k') | runtime/vm/symbols.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698