OLD | NEW |
---|---|
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 Loading... | |
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(¶ms, current_block_->scope); | 2973 AddFormalParamsToScope(¶ms, 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++; | |
hausner
2014/08/07 21:48:43
Why is this parameter optional? The caller will al
Michael Lippautz (Google)
2014/08/08 18:12:18
Maybe I am missing something, but the first time w
| |
2982 params.has_optional_positional_parameters = true; | |
2983 SetupDefaultsForOptionalParams(¶ms, default_parameter_values); | |
2974 AddFormalParamsToScope(¶ms, current_block_->scope); | 2984 AddFormalParamsToScope(¶ms, 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, ¶ms); | 2990 ParseFormalParameterList(allow_explicit_default_values, false, ¶ms); |
2981 } | 2991 } |
2982 } else { | 2992 } else { |
2983 ParseFormalParameterList(allow_explicit_default_values, false, ¶ms); | 2993 ParseFormalParameterList(allow_explicit_default_values, false, ¶ms); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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, | |
hausner
2014/08/07 21:48:43
As discussed offline, I believe all expressions ar
Michael Lippautz (Google)
2014/08/08 18:12:18
Again discussed offline :)
Example:
var x = ((
| |
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() { | |
hausner
2014/08/07 21:48:43
Could maybe inline this code in ParsePrimary.
Michael Lippautz (Google)
2014/08/08 18:12:18
Done.
| |
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 Loading... | |
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")) { | |
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 Loading... | |
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 |
OLD | NEW |