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 10010 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10021 const TokenPosition expr_pos = TokenPos(); | 10021 const TokenPosition expr_pos = TokenPos(); |
10022 if (current_function().IsGenerativeConstructor() && | 10022 if (current_function().IsGenerativeConstructor() && |
10023 (current_block_->scope->function_level() == 0)) { | 10023 (current_block_->scope->function_level() == 0)) { |
10024 ReportError(expr_pos, | 10024 ReportError(expr_pos, |
10025 "return of a value is not allowed in constructors"); | 10025 "return of a value is not allowed in constructors"); |
10026 } else if (current_function().IsGeneratorClosure() && | 10026 } else if (current_function().IsGeneratorClosure() && |
10027 (current_block_->scope->function_level() == 0)) { | 10027 (current_block_->scope->function_level() == 0)) { |
10028 ReportError(expr_pos, "generator functions may not return a value"); | 10028 ReportError(expr_pos, "generator functions may not return a value"); |
10029 } | 10029 } |
10030 AstNode* expr = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL); | 10030 AstNode* expr = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL); |
| 10031 if (I->type_checks() && |
| 10032 current_function().IsAsyncClosure() && |
| 10033 (current_block_->scope->function_level() == 0)) { |
| 10034 // In checked mode, when the declared result type is Future<T>, verify |
| 10035 // that the returned expression is of type T or Future<T> as follows: |
| 10036 // return temp = expr, temp is Future ? temp as Future<T> : temp as T; |
| 10037 // In case of a mismatch, we need a TypeError and not a CastError, so |
| 10038 // we do not actually implement an "as" test, but an "assignable" test. |
| 10039 const Function& async_func = |
| 10040 Function::Handle(Z, current_function().parent_function()); |
| 10041 const AbstractType& result_type = |
| 10042 AbstractType::ZoneHandle(Z, async_func.result_type()); |
| 10043 const Class& future_class = |
| 10044 Class::ZoneHandle(Z, I->object_store()->future_class()); |
| 10045 ASSERT(!future_class.IsNull()); |
| 10046 if (result_type.type_class() == future_class.raw()) { |
| 10047 const TypeArguments& result_type_args = |
| 10048 TypeArguments::ZoneHandle(Z, result_type.arguments()); |
| 10049 if (!result_type_args.IsNull() && (result_type_args.Length() == 1)) { |
| 10050 const AbstractType& result_type_arg = |
| 10051 AbstractType::ZoneHandle(Z, result_type_args.TypeAt(0)); |
| 10052 LetNode* checked_expr = new(Z) LetNode(expr_pos); |
| 10053 LocalVariable* temp = checked_expr->AddInitializer(expr); |
| 10054 temp->set_is_final(); |
| 10055 const AbstractType& future_type = |
| 10056 AbstractType::ZoneHandle(Z, future_class.RareType()); |
| 10057 AstNode* is_future = new(Z) LoadLocalNode(expr_pos, temp); |
| 10058 is_future = new(Z) ComparisonNode(expr_pos, |
| 10059 Token::kIS, |
| 10060 is_future, |
| 10061 new(Z) TypeNode(expr_pos, |
| 10062 future_type)); |
| 10063 AstNode* as_future_t = new(Z) LoadLocalNode(expr_pos, temp); |
| 10064 as_future_t = new(Z) AssignableNode(expr_pos, |
| 10065 as_future_t, |
| 10066 result_type, |
| 10067 Symbols::FunctionResult()); |
| 10068 AstNode* as_t = new(Z) LoadLocalNode(expr_pos, temp); |
| 10069 as_t = new(Z) AssignableNode(expr_pos, |
| 10070 as_t, |
| 10071 result_type_arg, |
| 10072 Symbols::FunctionResult()); |
| 10073 checked_expr->AddNode(new(Z) ConditionalExprNode(expr_pos, |
| 10074 is_future, |
| 10075 as_future_t, |
| 10076 as_t)); |
| 10077 expr = checked_expr; |
| 10078 } |
| 10079 } |
| 10080 } |
10031 statement = new(Z) ReturnNode(statement_pos, expr); | 10081 statement = new(Z) ReturnNode(statement_pos, expr); |
10032 } else { | 10082 } else { |
10033 if (current_function().IsSyncGenClosure() && | 10083 if (current_function().IsSyncGenClosure() && |
10034 (current_block_->scope->function_level() == 0)) { | 10084 (current_block_->scope->function_level() == 0)) { |
10035 // In a synchronous generator, return without an expression | 10085 // In a synchronous generator, return without an expression |
10036 // returns false, signaling that the iterator terminates and | 10086 // returns false, signaling that the iterator terminates and |
10037 // did not yield a value. | 10087 // did not yield a value. |
10038 statement = new(Z) ReturnNode(statement_pos, | 10088 statement = new(Z) ReturnNode(statement_pos, |
10039 new(Z) LiteralNode(return_pos, Bool::False())); | 10089 new(Z) LiteralNode(return_pos, Bool::False())); |
10040 } else { | 10090 } else { |
(...skipping 4444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14485 const ArgumentListNode& function_args, | 14535 const ArgumentListNode& function_args, |
14486 const LocalVariable* temp_for_last_arg, | 14536 const LocalVariable* temp_for_last_arg, |
14487 bool is_super_invocation) { | 14537 bool is_super_invocation) { |
14488 UNREACHABLE(); | 14538 UNREACHABLE(); |
14489 return NULL; | 14539 return NULL; |
14490 } | 14540 } |
14491 | 14541 |
14492 } // namespace dart | 14542 } // namespace dart |
14493 | 14543 |
14494 #endif // DART_PRECOMPILED_RUNTIME | 14544 #endif // DART_PRECOMPILED_RUNTIME |
OLD | NEW |