Chromium Code Reviews| Index: runtime/vm/parser.cc |
| diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc |
| index 4d0e741c47c372fae22fc0e384917383cc8aa14e..8897907f38ba1750af61971318da6c80a273e54e 100644 |
| --- a/runtime/vm/parser.cc |
| +++ b/runtime/vm/parser.cc |
| @@ -6,6 +6,7 @@ |
| #include "lib/invocation_mirror.h" |
| #include "platform/utils.h" |
| +#include "vm/ast_transformer.h" |
| #include "vm/bootstrap.h" |
| #include "vm/class_finalizer.h" |
| #include "vm/compiler.h" |
| @@ -2971,6 +2972,15 @@ SequenceNode* Parser::ParseFunc(const Function& func, |
| // we are compiling a getter this will at most populate the receiver. |
| AddFormalParamsToScope(¶ms, current_block_->scope); |
| } else if (func.is_async_closure()) { |
| + // Async closures have one optional parameter for continuation results. |
| + ParamDesc result_param; |
| + result_param.name = &Symbols::AsyncOperationParam(); |
| + result_param.default_value = &Object::null_instance(); |
| + result_param.type = &Type::ZoneHandle(I, Type::DynamicType()); |
| + params.parameters->Add(result_param); |
| + params.num_optional_parameters++; |
| + params.has_optional_positional_parameters = true; |
| + SetupDefaultsForOptionalParams(¶ms, default_parameter_values); |
| AddFormalParamsToScope(¶ms, current_block_->scope); |
| ASSERT(AbstractType::Handle(I, func.result_type()).IsResolved()); |
| ASSERT(func.NumParameters() == params.parameters->length()); |
| @@ -3027,6 +3037,8 @@ SequenceNode* Parser::ParseFunc(const Function& func, |
| Function& async_closure = Function::ZoneHandle(I); |
| if (func.IsAsyncFunction() && !func.is_async_closure()) { |
| async_closure = OpenAsyncFunction(formal_params_pos); |
| + } else if (func.is_async_closure()) { |
| + OpenAsyncClosure(); |
| } |
| intptr_t end_token_pos = 0; |
| @@ -5508,6 +5520,12 @@ void Parser::OpenFunctionBlock(const Function& func) { |
| } |
| +void Parser::OpenAsyncClosure() { |
| + parsed_function()->set_await_temps_scope(current_block_->scope); |
| + // TODO(mlippautz): Set up explicit jump table for await continuations. |
| +} |
| + |
| + |
| RawFunction* Parser::OpenAsyncFunction(intptr_t formal_param_pos) { |
| // Create the closure containing the old body of this function. |
| Class& sig_cls = Class::ZoneHandle(I); |
| @@ -5519,12 +5537,20 @@ RawFunction* Parser::OpenAsyncFunction(intptr_t formal_param_pos) { |
| formal_param_pos, |
| &Symbols::ClosureParameter(), |
| &Type::ZoneHandle(I, Type::DynamicType())); |
| + ParamDesc result_param; |
| + result_param.name = &Symbols::AsyncOperationParam(); |
| + result_param.default_value = &Object::null_instance(); |
| + result_param.type = &Type::ZoneHandle(I, Type::DynamicType()); |
| + closure_params.parameters->Add(result_param); |
| + closure_params.has_optional_positional_parameters = true; |
| + closure_params.num_optional_parameters++; |
| closure = Function::NewClosureFunction( |
| Symbols::AnonymousClosure(), |
| innermost_function(), |
| formal_param_pos); |
| AddFormalParamsToFunction(&closure_params, closure); |
| closure.set_is_async_closure(true); |
| + closure.set_is_inlinable(false); |
| closure.set_result_type(AbstractType::Handle(Type::DynamicType())); |
| sig = closure.Signature(); |
| sig_cls = library_.LookupLocalClass(sig); |
| @@ -5891,7 +5917,7 @@ AstNode* Parser::ParseVariableDeclaration(const AbstractType& type, |
| // Variable initialization. |
| const intptr_t assign_pos = TokenPos(); |
| ConsumeToken(); |
| - AstNode* expr = ParseExpr(is_const, kConsumeCascades); |
| + AstNode* expr = ParseAwaitableExpr(is_const, kConsumeCascades); |
| initialization = new(I) StoreLocalNode( |
| assign_pos, variable, expr); |
| if (is_const) { |
| @@ -7768,7 +7794,7 @@ AstNode* Parser::ParseStatement() { |
| new(I) LoadLocalNode(statement_pos, excp_var), |
| new(I) LoadLocalNode(statement_pos, trace_var)); |
| } else { |
| - statement = ParseExpr(kAllowConst, kConsumeCascades); |
| + statement = ParseAwaitableExpr(kAllowConst, kConsumeCascades); |
| ExpectSemicolon(); |
| } |
| return statement; |
| @@ -8424,6 +8450,40 @@ static AstNode* LiteralIfStaticConst(Isolate* iso, AstNode* expr) { |
| } |
| +AstNode* Parser::ParseAwaitableExpr(bool require_compiletime_const, |
| + bool consume_cascades) { |
| + TRACE_PARSER("ParseAwaitableExpr"); |
| + parsed_function()->reset_seen_await(); |
| + AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades); |
| + if (parsed_function()->seen_await()) { |
| + if (!current_block_->scope->LookupVariable( |
| + Symbols::AsyncOperation(), true)) { |
| + // Async operations are always encapsulated into a local function. We only |
| + // need to transform the expression when generating code for this inner |
| + // function. |
| + return expr; |
| + } |
| + SequenceNode* intermediates_block = new (I) SequenceNode( |
| + Scanner::kNoSourcePos, current_block_->scope); |
| + AwaitTransformer at(intermediates_block, library_, parsed_function()); |
| + at.Transform(expr); |
| + current_block_->statements->Add(intermediates_block); |
| + parsed_function()->reset_seen_await(); |
| + return at.Result(); |
| + } |
| + return expr; |
| +} |
| + |
| + |
| +AstNode* Parser::ParseAwaitExpr() { |
| + TRACE_PARSER("ParseAwaitExpr"); |
| + ConsumeToken(); |
| + parsed_function()->record_await(); |
| + return new (I) AwaitNode( |
| + TokenPos(), ParseExpr(kAllowConst, kConsumeCascades)); |
| +} |
| + |
| + |
| AstNode* Parser::ParseExpr(bool require_compiletime_const, |
| bool consume_cascades) { |
| TRACE_PARSER("ParseExpr"); |
| @@ -10792,6 +10852,8 @@ AstNode* Parser::ParsePrimary() { |
| OpenBlock(); |
| primary = ParseFunctionStatement(true); |
| CloseBlock(); |
| + } else if (IsLiteral("await")) { |
|
Michael Lippautz (Google)
2014/08/07 00:18:55
Let's see whether this will get a keyword
|
| + primary = ParseAwaitExpr(); |
| } else if (IsIdentifier()) { |
| intptr_t qual_ident_pos = TokenPos(); |
| const LibraryPrefix& prefix = LibraryPrefix::ZoneHandle(I, ParsePrefix()); |