Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(22)

Unified Diff: runtime/vm/parser.cc

Issue 447003003: Introduce await (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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(&params, 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++;
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
+ params.has_optional_positional_parameters = true;
+ SetupDefaultsForOptionalParams(&params, default_parameter_values);
AddFormalParamsToScope(&params, 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,
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 = ((
+ 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() {
hausner 2014/08/07 21:48:43 Could maybe inline this code in ParsePrimary.
Michael Lippautz (Google) 2014/08/08 18:12:18 Done.
+ 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")) {
+ primary = ParseAwaitExpr();
} else if (IsIdentifier()) {
intptr_t qual_ident_pos = TokenPos();
const LibraryPrefix& prefix = LibraryPrefix::ZoneHandle(I, ParsePrefix());

Powered by Google App Engine
This is Rietveld 408576698