Chromium Code Reviews| Index: pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart |
| diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart |
| index 3ae2c1bd8b306e4d385366a8cd3a4fd3465aa8bd..26f2de2fceb2399ea45c8291ba0e902579bb8c7f 100644 |
| --- a/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart |
| +++ b/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart |
| @@ -1111,8 +1111,107 @@ class IrBuilderVisitor extends ast.Visitor<ir.Primitive> |
| } |
| visitAsyncForIn(ast.AsyncForIn node) { |
| - // await for is not yet implemented. |
| - return giveup(node, 'await for'); |
| + // Translate await for into a loop over a StreamIterator. The source |
| + // statement: |
| + // |
| + // await for (<decl> in <stream>) <body> |
| + // |
| + // is translated as if it were: |
| + // |
| + // var iterator = new StreamIterator(<stream>); |
| + // try { |
| + // while (await iterator.hasNext()) { |
| + // <decl> = await iterator.current; |
| + // <body> |
| + // } |
| + // } finally { |
| + // await iterator.cancel(); |
| + // } |
| + ir.Primitive stream = visit(node.expression); |
| + ir.Primitive dummyTypeArgument = irBuilder.buildNullConstant(); |
| + ConstructorElement constructor = helpers.streamIteratorConstructor; |
| + ir.Primitive iterator = irBuilder.addPrimitive(new ir.InvokeConstructor( |
| + constructor.enclosingClass.thisType, |
| + constructor, |
| + new Selector.callConstructor(constructor.memberName, 1), |
| + <ir.Primitive>[stream, dummyTypeArgument], |
| + sourceInformationBuilder.buildGeneric(node))); |
| + |
| + ir.Node buildTryBody(IrBuilder builder) { |
| + ir.Node buildLoopCondition(IrBuilder builder) { |
| + ir.Primitive moveNext = builder.buildDynamicInvocation( |
| + iterator, |
| + Selectors.moveNext, |
| + elements.getMoveNextTypeMask(node), |
| + <ir.Primitive>[]); |
| + return builder.addPrimitive(new ir.Await(moveNext)); |
| + } |
| + |
| + ir.Node buildLoopBody(IrBuilder builder) { |
| + return withBuilder(builder, () { |
| + ast.Node identifier = node.declaredIdentifier; |
| + ast.VariableDefinitions declaration = |
| + identifier.asVariableDefinitions(); |
| + if (declaration != null) { |
| + visit(declaration); |
| + } |
|
asgerf
2016/02/10 13:03:27
Instead of visiting the declaration, I think it wo
Kevin Millikin (Google)
2016/02/10 13:27:41
OK, I can do that.
I wrote it this way just becau
|
| + ir.Primitive current = irBuilder.buildDynamicInvocation( |
| + iterator, |
| + Selectors.current, |
| + elements.getCurrentTypeMask(node), |
| + <ir.Primitive>[]); |
| + Element variable = elements.getForInVariable(node); |
| + if (Elements.isLocal(variable)) { |
| + irBuilder.buildLocalVariableSet(variable, current); |
| + } else if (Elements.isError(variable) || |
| + Elements.isMalformed(variable)) { |
| + Selector selector = |
| + new Selector.setter(new Name(variable.name, variable.library)); |
| + List<ir.Primitive> args = <ir.Primitive>[current]; |
| + // Note the comparison below. It can be the case that an element |
| + // isError and isMalformed. |
| + if (Elements.isError(variable)) { |
| + irBuilder.buildStaticNoSuchMethod(selector, args); |
| + } else { |
| + irBuilder.buildErroneousInvocation(variable, selector, args); |
| + } |
| + } else if (Elements.isStaticOrTopLevel(variable)) { |
| + if (variable.isField) { |
| + irBuilder.addPrimitive(new ir.SetStatic(variable, current)); |
| + } else { |
| + irBuilder.buildStaticSetterSet(variable, current); |
| + } |
| + } else { |
| + ir.Primitive receiver = irBuilder.buildThis(); |
| + irBuilder.buildDynamicSet( |
| + receiver, |
| + elements.getSelector(identifier), |
| + elements.getTypeMask(identifier), |
| + current); |
| + } |
| + visit(node.body); |
| + }); |
| + } |
| + |
| + builder.buildWhile( |
| + buildCondition: buildLoopCondition, |
| + buildBody: buildLoopBody, |
| + target: elements.getTargetDefinition(node), |
| + closureScope: getClosureScopeForNode(node)); |
| + } |
| + |
| + ir.Node buildFinallyBody(IrBuilder builder) { |
| + ir.Primitive cancellation = builder.buildDynamicInvocation( |
| + iterator, |
| + Selectors.cancel, |
| + backend.dynamicType, |
| + <ir.Primitive>[], |
| + sourceInformation: sourceInformationBuilder.buildGeneric(node)); |
| + return builder.addPrimitive(new ir.Await(cancellation)); |
| + } |
| + |
| + irBuilder.buildTryFinally(new TryStatementInfo(), buildTryBody, |
| + buildFinallyBody); |
| } |
| visitAwait(ast.Await node) { |