Chromium Code Reviews| 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++; | |
| 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, | |
| 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 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")) { | |
|
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 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 |