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

Unified Diff: runtime/vm/parser.cc

Issue 362153002: Transform functions marked as async (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: first round of comments Created 6 years, 5 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 a82fff7c43f308c942dce08fd5be3fd7181f61e1..d5b17108d374d0b8d70127057825e3a55d19c3b4 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -39,6 +39,7 @@ DEFINE_FLAG(bool, enable_asserts, false, "Enable assert statements.");
DEFINE_FLAG(bool, enable_type_checks, false, "Enable type checks.");
DEFINE_FLAG(bool, trace_parser, false, "Trace parser operations.");
DEFINE_FLAG(bool, warn_mixin_typedef, true, "Warning on legacy mixin typedef.");
+DEFINE_FLAG(bool, enable_async, false, "Enable async operations.");
DECLARE_FLAG(bool, error_on_bad_type);
DECLARE_FLAG(bool, throw_on_javascript_int_overflow);
DECLARE_FLAG(bool, warn_on_javascript_compatibility);
@@ -2877,6 +2878,99 @@ SequenceNode* Parser::ParseConstructor(const Function& func,
}
+// TODO(mlippautz): Once we know where Future should come from, adjust how we
+// get it's definition.
hausner 2014/07/12 00:05:24 its
Michael Lippautz (Google) 2014/07/14 20:22:48 Done.
+RawClass* Parser::GetFutureClass() {
+ const Class& cls = Class::Handle(library_.LookupClass(Symbols::Future()));
+ if (cls.IsNull()) {
+ ReportError("async modifier requires dart:async to be imported");
+ }
+ return cls.raw();
+}
+
+
+SequenceNode* Parser::BuildAsyncFuture(const Function& outer,
+ SequenceNode* parsed_body,
+ ParamList* params,
+ intptr_t saved_pos) {
+ const Class& future = Class::ZoneHandle(I, GetFutureClass());
+ ASSERT(!future.IsNull());
+ const Function& constructor = Function::ZoneHandle(I,
+ future.LookupFunction(Symbols::FutureConstructor()));
+ ASSERT(!constructor.IsNull());
+ // Create the closure containing the parsed_body of this function.
+ Class& sig_cls = Class::ZoneHandle(I);
+ Type& sig_type = Type::ZoneHandle(I);
+ Function& closure = Function::ZoneHandle(I);
+ String& sig = String::ZoneHandle(I);
+ ParamList closure_params;
+ closure_params.AddFinalParameter(
+ saved_pos,
+ &Symbols::ClosureParameter(),
+ &Type::ZoneHandle(I, Type::DynamicType()));
+ closure = Function::NewClosureFunction(
+ Symbols::AnonymousClosure(),
+ innermost_function(),
+ saved_pos);
+ AddFormalParamsToFunction(&closure_params, closure);
+ closure.set_is_synthetic_container(true);
+ // TODO(mlippautz): For an async outer function declared with Future<T> the
+ // result type of the synthesized closure should be T.
+ closure.set_result_type(AbstractType::Handle(Type::DynamicType()));
+ sig = closure.Signature();
+ sig_cls = library_.LookupLocalClass(sig);
+ if (sig_cls.IsNull()) {
+ sig_cls = Class::NewSignatureClass(sig, closure, script_, saved_pos);
+ library_.AddClass(sig_cls);
+ }
+ closure.set_signature_class(sig_cls);
+ sig_type = sig_cls.SignatureType();
+ if (!sig_type.IsFinalized()) {
+ ClassFinalizer::FinalizeType(
+ sig_cls, sig_type, ClassFinalizer::kCanonicalize);
+ }
+ ASSERT(AbstractType::Handle(I, closure.result_type()).IsResolved());
+ ASSERT(closure.NumParameters() == closure_params.parameters->length());
+ OpenFunctionBlock(closure);
+ AddFormalParamsToScope(&closure_params, current_block_->scope);
+ LocalScope* cur_scope = current_block_->scope;
+ String& var_name = String::ZoneHandle(I);
+ bool var_captured = false;
+ // Capture parameters of the enclosing function.
+ for (intptr_t i = 0; i < params->parameters->length(); i++) {
+ ParamDesc& param_desc = (*params->parameters)[i];
+ var_name = param_desc.var->name().raw();
+ // Ignore implicit closure parameter, but capture 'this' from any enclosing
+ // methods.
+ if (var_name.Equals(Symbols::ClosureParameter())) {
+ continue;
+ }
+ var_captured = cur_scope->CaptureVariable(var_name);
+ ASSERT(var_captured);
+ }
+ LocalScope* parsed_body_scope = parsed_body->scope();
+ // Capture all variables that have already been captured by the enclosing
+ // function.
+ for (intptr_t j = 0; j < parsed_body->scope()->num_variables(); j++) {
+ if (parsed_body_scope->VariableAt(j)->is_captured()) {
+ var_captured =
+ cur_scope->CaptureVariable(parsed_body_scope->VariableAt(j)->name());
+ ASSERT(var_captured);
+ }
+ }
+ ClosureNode* cn = new(I) ClosureNode(
+ Scanner::kNoSourcePos, closure, NULL, cur_scope);
+ ArgumentListNode* arguments = new (I) ArgumentListNode(saved_pos);
+ arguments->Add(cn);
+ ConstructorCallNode* ccn = new (I) ConstructorCallNode(
+ Scanner::kNoSourcePos, TypeArguments::ZoneHandle(I), constructor,
+ arguments);
+ ReturnNode* rn = new (I) ReturnNode(Scanner::kNoSourcePos, ccn);
+ current_block_->statements->Add(rn);
+ return CloseBlock();
+}
+
+
// Parser is at the opening parenthesis of the formal parameter
// declaration of the function or constructor.
// Parse the formal parameters and code.
@@ -2891,6 +2985,7 @@ SequenceNode* Parser::ParseFunc(const Function& func,
intptr_t saved_try_index = last_used_try_index_;
last_used_try_index_ = 0;
+ intptr_t formal_params_pos = TokenPos();
// TODO(12455) : Need better validation mechanism.
if (func.IsConstructor()) {
@@ -2925,12 +3020,24 @@ SequenceNode* Parser::ParseFunc(const Function& func,
&Symbols::TypeArgumentsParameter(),
&Type::ZoneHandle(I, Type::DynamicType()));
}
- ASSERT((CurrentToken() == Token::kLPAREN) || func.IsGetterFunction());
+ ASSERT((CurrentToken() == Token::kLPAREN) || func.IsGetterFunction() ||
+ func.is_synthetic_container());
const bool allow_explicit_default_values = true;
if (func.IsGetterFunction()) {
// Populate function scope with the formal parameters. Since in this case
// we are compiling a getter this will at most populate the receiver.
AddFormalParamsToScope(&params, current_block_->scope);
+ } else if (func.is_synthetic_container() && Function::Handle(
+ func.parent_function()).IsGetterFunction()) {
+ AddFormalParamsToScope(&params, current_block_->scope);
+ ASSERT(AbstractType::Handle(I, func.result_type()).IsResolved());
+ ASSERT(func.NumParameters() == params.parameters->length());
+ } else if (func.is_synthetic_container()) {
+ AddFormalParamsToScope(&params, current_block_->scope);
+ ASSERT(AbstractType::Handle(I, func.result_type()).IsResolved());
+ ASSERT(func.NumParameters() == params.parameters->length());
+ ParseFormalParameterList(allow_explicit_default_values, false, &params);
+ // Parse them away.
} else {
ParseFormalParameterList(allow_explicit_default_values, false, &params);
@@ -2971,6 +3078,9 @@ SequenceNode* Parser::ParseFunc(const Function& func,
}
}
+ RawFunction::Modifier func_modifier = ParseFunctionModifier();
+ func.set_modifier(func_modifier);
+
OpenBlock(); // Open a nested scope for the outermost function block.
intptr_t end_token_pos = 0;
if (CurrentToken() == Token::kLBRACE) {
@@ -3032,6 +3142,9 @@ SequenceNode* Parser::ParseFunc(const Function& func,
func.end_token_pos() == end_token_pos);
func.set_end_token_pos(end_token_pos);
SequenceNode* body = CloseBlock();
+ if (func.IsAsyncFunction() && !func.is_synthetic_container()) {
+ body = BuildAsyncFuture(func, body, &params, formal_params_pos);
+ }
current_block_->statements->Add(body);
innermost_function_ = saved_innermost_function.raw();
last_used_try_index_ = saved_try_index;
@@ -3345,6 +3458,8 @@ void Parser::ParseMethodOrConstructor(ClassDesc* members, MemberDesc* method) {
method->name->ToCString());
}
+ ParseFunctionModifier();
+
intptr_t method_end_pos = TokenPos();
if ((CurrentToken() == Token::kLBRACE) ||
(CurrentToken() == Token::kARROW)) {
@@ -4779,6 +4894,17 @@ void Parser::ParseTopLevelVariable(TopLevel* top_level,
}
+RawFunction::Modifier Parser::ParseFunctionModifier() {
+ if (FLAG_enable_async) {
+ if (CurrentLiteral()->raw() == Symbols::Async().raw()) {
+ ConsumeToken();
+ return RawFunction::kAsync;
+ }
+ }
+ return RawFunction::kNoModifier;
+}
+
+
void Parser::ParseTopLevelFunction(TopLevel* top_level,
intptr_t metadata_pos) {
TRACE_PARSER("ParseTopLevelFunction");
@@ -4832,6 +4958,8 @@ void Parser::ParseTopLevelFunction(TopLevel* top_level,
const bool allow_explicit_default_values = true;
ParseFormalParameterList(allow_explicit_default_values, false, &params);
+ RawFunction::Modifier func_modifier = ParseFunctionModifier();
+
intptr_t function_end_pos = function_pos;
bool is_native = false;
if (is_external) {
@@ -4866,6 +4994,7 @@ void Parser::ParseTopLevelFunction(TopLevel* top_level,
decl_begin_pos));
func.set_result_type(result_type);
func.set_end_token_pos(function_end_pos);
+ func.set_modifier(func_modifier);
if (is_native && library_.is_dart_scheme() && library_.IsPrivate(func_name)) {
func.set_is_visible(false);
}
@@ -4968,6 +5097,8 @@ void Parser::ParseTopLevelAccessor(TopLevel* top_level,
field_name->ToCString());
}
+ RawFunction::Modifier func_modifier = ParseFunctionModifier();
+
intptr_t accessor_end_pos = accessor_pos;
bool is_native = false;
if (is_external) {
@@ -5003,6 +5134,7 @@ void Parser::ParseTopLevelAccessor(TopLevel* top_level,
decl_begin_pos));
func.set_result_type(result_type);
func.set_end_token_pos(accessor_end_pos);
+ func.set_modifier(func_modifier);
if (is_native && library_.is_dart_scheme() &&
library_.IsPrivate(accessor_name)) {
func.set_is_visible(false);
@@ -6207,7 +6339,9 @@ bool Parser::IsFunctionDeclaration() {
if ((CurrentToken() == Token::kLBRACE) ||
(CurrentToken() == Token::kARROW) ||
(is_top_level_ && IsLiteral("native")) ||
- is_external) {
+ is_external ||
+ (FLAG_enable_async &&
+ CurrentLiteral()->raw() == Symbols::Async().raw())) {
SetPosition(saved_pos);
return true;
}
@@ -10746,6 +10880,7 @@ void Parser::SkipFunctionLiteral() {
params.skipped = true;
ParseFormalParameterList(allow_explicit_default_values, false, &params);
}
+ ParseFunctionModifier();
if (CurrentToken() == Token::kLBRACE) {
SkipBlock();
ExpectToken(Token::kRBRACE);
« no previous file with comments | « runtime/vm/parser.h ('k') | runtime/vm/raw_object.h » ('j') | runtime/vm/raw_object.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698