| 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 #include "vm/flags.h" | 6 #include "vm/flags.h" |
| 7 | 7 |
| 8 #ifndef DART_PRECOMPILED_RUNTIME | 8 #ifndef DART_PRECOMPILED_RUNTIME |
| 9 | 9 |
| 10 #include "lib/invocation_mirror.h" | 10 #include "lib/invocation_mirror.h" |
| (...skipping 3678 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3689 ConsumeToken(); | 3689 ConsumeToken(); |
| 3690 if (String::Handle(Z, func.name()).Equals(Symbols::EqualOperator())) { | 3690 if (String::Handle(Z, func.name()).Equals(Symbols::EqualOperator())) { |
| 3691 const Class& owner = Class::Handle(Z, func.Owner()); | 3691 const Class& owner = Class::Handle(Z, func.Owner()); |
| 3692 if (!owner.IsObjectClass()) { | 3692 if (!owner.IsObjectClass()) { |
| 3693 AddEqualityNullCheck(); | 3693 AddEqualityNullCheck(); |
| 3694 } | 3694 } |
| 3695 } | 3695 } |
| 3696 const TokenPosition expr_pos = TokenPos(); | 3696 const TokenPosition expr_pos = TokenPos(); |
| 3697 AstNode* expr = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL); | 3697 AstNode* expr = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL); |
| 3698 ASSERT(expr != NULL); | 3698 ASSERT(expr != NULL); |
| 3699 current_block_->statements->Add(new ReturnNode(expr_pos, expr)); | 3699 expr = AddAsyncResultTypeCheck(expr_pos, expr); |
| 3700 current_block_->statements->Add(new (Z) ReturnNode(expr_pos, expr)); |
| 3700 end_token_pos = TokenPos(); | 3701 end_token_pos = TokenPos(); |
| 3701 if (check_semicolon) { | 3702 if (check_semicolon) { |
| 3702 ExpectSemicolon(); | 3703 ExpectSemicolon(); |
| 3703 } | 3704 } |
| 3704 } else if (IsSymbol(Symbols::Native())) { | 3705 } else if (IsSymbol(Symbols::Native())) { |
| 3705 if (String::Handle(Z, func.name()).Equals(Symbols::EqualOperator())) { | 3706 if (String::Handle(Z, func.name()).Equals(Symbols::EqualOperator())) { |
| 3706 const Class& owner = Class::Handle(Z, func.Owner()); | 3707 const Class& owner = Class::Handle(Z, func.Owner()); |
| 3707 if (!owner.IsObjectClass()) { | 3708 if (!owner.IsObjectClass()) { |
| 3708 AddEqualityNullCheck(); | 3709 AddEqualityNullCheck(); |
| 3709 } | 3710 } |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3764 new ComparisonNode(TokenPosition::kNoSource, Token::kEQ_STRICT, | 3765 new ComparisonNode(TokenPosition::kNoSource, Token::kEQ_STRICT, |
| 3765 LoadReceiver(TokenPosition::kNoSource), null_operand); | 3766 LoadReceiver(TokenPosition::kNoSource), null_operand); |
| 3766 SequenceNode* arg_is_null = | 3767 SequenceNode* arg_is_null = |
| 3767 new SequenceNode(TokenPosition::kNoSource, current_block_->scope); | 3768 new SequenceNode(TokenPosition::kNoSource, current_block_->scope); |
| 3768 arg_is_null->Add(new ReturnNode(TokenPosition::kNoSource, result)); | 3769 arg_is_null->Add(new ReturnNode(TokenPosition::kNoSource, result)); |
| 3769 IfNode* if_arg_null = | 3770 IfNode* if_arg_null = |
| 3770 new IfNode(TokenPosition::kNoSource, check_arg, arg_is_null, NULL); | 3771 new IfNode(TokenPosition::kNoSource, check_arg, arg_is_null, NULL); |
| 3771 current_block_->statements->Add(if_arg_null); | 3772 current_block_->statements->Add(if_arg_null); |
| 3772 } | 3773 } |
| 3773 | 3774 |
| 3775 AstNode* Parser::AddAsyncResultTypeCheck(TokenPosition expr_pos, |
| 3776 AstNode* expr) { |
| 3777 if (I->type_checks() && |
| 3778 (((FunctionLevel() == 0) && current_function().IsAsyncClosure()))) { |
| 3779 // In checked mode, when the declared result type is Future<T>, verify |
| 3780 // that the returned expression is of type T or Future<T> as follows: |
| 3781 // return temp = expr, temp is Future ? temp as Future<T> : temp as T; |
| 3782 // In case of a mismatch, we need a TypeError and not a CastError, so |
| 3783 // we do not actually implement an "as" test, but an "assignable" test. |
| 3784 Function& async_func = |
| 3785 Function::Handle(Z, current_function().parent_function()); |
| 3786 const AbstractType& result_type = |
| 3787 AbstractType::ZoneHandle(Z, async_func.result_type()); |
| 3788 const Class& future_class = |
| 3789 Class::ZoneHandle(Z, I->object_store()->future_class()); |
| 3790 ASSERT(!future_class.IsNull()); |
| 3791 if (result_type.type_class() == future_class.raw()) { |
| 3792 const TypeArguments& result_type_args = |
| 3793 TypeArguments::ZoneHandle(Z, result_type.arguments()); |
| 3794 if (!result_type_args.IsNull() && (result_type_args.Length() == 1)) { |
| 3795 const AbstractType& result_type_arg = |
| 3796 AbstractType::ZoneHandle(Z, result_type_args.TypeAt(0)); |
| 3797 LetNode* checked_expr = new (Z) LetNode(expr_pos); |
| 3798 LocalVariable* temp = checked_expr->AddInitializer(expr); |
| 3799 temp->set_is_final(); |
| 3800 const AbstractType& future_type = |
| 3801 AbstractType::ZoneHandle(Z, future_class.RareType()); |
| 3802 AstNode* is_future = new (Z) LoadLocalNode(expr_pos, temp); |
| 3803 is_future = |
| 3804 new (Z) ComparisonNode(expr_pos, Token::kIS, is_future, |
| 3805 new (Z) TypeNode(expr_pos, future_type)); |
| 3806 AstNode* as_future_t = new (Z) LoadLocalNode(expr_pos, temp); |
| 3807 as_future_t = new (Z) AssignableNode(expr_pos, as_future_t, result_type, |
| 3808 Symbols::FunctionResult()); |
| 3809 AstNode* as_t = new (Z) LoadLocalNode(expr_pos, temp); |
| 3810 as_t = new (Z) AssignableNode(expr_pos, as_t, result_type_arg, |
| 3811 Symbols::FunctionResult()); |
| 3812 checked_expr->AddNode(new (Z) ConditionalExprNode(expr_pos, is_future, |
| 3813 as_future_t, as_t)); |
| 3814 expr = checked_expr; |
| 3815 } |
| 3816 } |
| 3817 } |
| 3818 return expr; |
| 3819 } |
| 3820 |
| 3774 void Parser::SkipIf(Token::Kind token) { | 3821 void Parser::SkipIf(Token::Kind token) { |
| 3775 if (CurrentToken() == token) { | 3822 if (CurrentToken() == token) { |
| 3776 ConsumeToken(); | 3823 ConsumeToken(); |
| 3777 } | 3824 } |
| 3778 } | 3825 } |
| 3779 | 3826 |
| 3780 void Parser::SkipInitializers() { | 3827 void Parser::SkipInitializers() { |
| 3781 ASSERT(CurrentToken() == Token::kCOLON); | 3828 ASSERT(CurrentToken() == Token::kCOLON); |
| 3782 do { | 3829 do { |
| 3783 ConsumeToken(); // Colon or comma. | 3830 ConsumeToken(); // Colon or comma. |
| (...skipping 6746 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10530 const int function_level = FunctionLevel(); | 10577 const int function_level = FunctionLevel(); |
| 10531 if (current_function().IsGenerativeConstructor() && | 10578 if (current_function().IsGenerativeConstructor() && |
| 10532 (function_level == 0)) { | 10579 (function_level == 0)) { |
| 10533 ReportError(expr_pos, | 10580 ReportError(expr_pos, |
| 10534 "return of a value is not allowed in constructors"); | 10581 "return of a value is not allowed in constructors"); |
| 10535 } else if (current_function().IsGeneratorClosure() && | 10582 } else if (current_function().IsGeneratorClosure() && |
| 10536 (function_level == 0)) { | 10583 (function_level == 0)) { |
| 10537 ReportError(expr_pos, "generator functions may not return a value"); | 10584 ReportError(expr_pos, "generator functions may not return a value"); |
| 10538 } | 10585 } |
| 10539 AstNode* expr = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL); | 10586 AstNode* expr = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL); |
| 10540 if (I->type_checks() && | 10587 expr = AddAsyncResultTypeCheck(expr_pos, expr); |
| 10541 (((function_level == 0) && current_function().IsAsyncClosure()))) { | |
| 10542 // In checked mode, when the declared result type is Future<T>, verify | |
| 10543 // that the returned expression is of type T or Future<T> as follows: | |
| 10544 // return temp = expr, temp is Future ? temp as Future<T> : temp as T; | |
| 10545 // In case of a mismatch, we need a TypeError and not a CastError, so | |
| 10546 // we do not actually implement an "as" test, but an "assignable" test. | |
| 10547 Function& async_func = | |
| 10548 Function::Handle(Z, current_function().parent_function()); | |
| 10549 const AbstractType& result_type = | |
| 10550 AbstractType::ZoneHandle(Z, async_func.result_type()); | |
| 10551 const Class& future_class = | |
| 10552 Class::ZoneHandle(Z, I->object_store()->future_class()); | |
| 10553 ASSERT(!future_class.IsNull()); | |
| 10554 if (result_type.type_class() == future_class.raw()) { | |
| 10555 const TypeArguments& result_type_args = | |
| 10556 TypeArguments::ZoneHandle(Z, result_type.arguments()); | |
| 10557 if (!result_type_args.IsNull() && (result_type_args.Length() == 1)) { | |
| 10558 const AbstractType& result_type_arg = | |
| 10559 AbstractType::ZoneHandle(Z, result_type_args.TypeAt(0)); | |
| 10560 LetNode* checked_expr = new (Z) LetNode(expr_pos); | |
| 10561 LocalVariable* temp = checked_expr->AddInitializer(expr); | |
| 10562 temp->set_is_final(); | |
| 10563 const AbstractType& future_type = | |
| 10564 AbstractType::ZoneHandle(Z, future_class.RareType()); | |
| 10565 AstNode* is_future = new (Z) LoadLocalNode(expr_pos, temp); | |
| 10566 is_future = | |
| 10567 new (Z) ComparisonNode(expr_pos, Token::kIS, is_future, | |
| 10568 new (Z) TypeNode(expr_pos, future_type)); | |
| 10569 AstNode* as_future_t = new (Z) LoadLocalNode(expr_pos, temp); | |
| 10570 as_future_t = new (Z) AssignableNode( | |
| 10571 expr_pos, as_future_t, result_type, Symbols::FunctionResult()); | |
| 10572 AstNode* as_t = new (Z) LoadLocalNode(expr_pos, temp); | |
| 10573 as_t = new (Z) AssignableNode(expr_pos, as_t, result_type_arg, | |
| 10574 Symbols::FunctionResult()); | |
| 10575 checked_expr->AddNode(new (Z) ConditionalExprNode( | |
| 10576 expr_pos, is_future, as_future_t, as_t)); | |
| 10577 expr = checked_expr; | |
| 10578 } | |
| 10579 } | |
| 10580 } | |
| 10581 statement = new (Z) ReturnNode(statement_pos, expr); | 10588 statement = new (Z) ReturnNode(statement_pos, expr); |
| 10582 } else { | 10589 } else { |
| 10583 if (current_function().IsSyncGenClosure() && (FunctionLevel() == 0)) { | 10590 if (current_function().IsSyncGenClosure() && (FunctionLevel() == 0)) { |
| 10584 // In a synchronous generator, return without an expression | 10591 // In a synchronous generator, return without an expression |
| 10585 // returns false, signaling that the iterator terminates and | 10592 // returns false, signaling that the iterator terminates and |
| 10586 // did not yield a value. | 10593 // did not yield a value. |
| 10587 statement = new (Z) ReturnNode( | 10594 statement = new (Z) ReturnNode( |
| 10588 statement_pos, new (Z) LiteralNode(return_pos, Bool::False())); | 10595 statement_pos, new (Z) LiteralNode(return_pos, Bool::False())); |
| 10589 } else { | 10596 } else { |
| 10590 statement = new (Z) ReturnNode(statement_pos); | 10597 statement = new (Z) ReturnNode(statement_pos); |
| (...skipping 4509 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 15100 bool Parser::FieldHasFunctionLiteralInitializer(const Field& field, | 15107 bool Parser::FieldHasFunctionLiteralInitializer(const Field& field, |
| 15101 TokenPosition* start, | 15108 TokenPosition* start, |
| 15102 TokenPosition* end) { | 15109 TokenPosition* end) { |
| 15103 UNREACHABLE(); | 15110 UNREACHABLE(); |
| 15104 return false; | 15111 return false; |
| 15105 } | 15112 } |
| 15106 | 15113 |
| 15107 } // namespace dart | 15114 } // namespace dart |
| 15108 | 15115 |
| 15109 #endif // DART_PRECOMPILED_RUNTIME | 15116 #endif // DART_PRECOMPILED_RUNTIME |
| OLD | NEW |