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 6b78f6fffcf8e96d6d51e3e1766e41951f0ef459..f8223de69ac7fc498cdb9172f18fd7430625b21b 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 |
| @@ -725,6 +725,20 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive> |
| } |
| @override |
| + ir.Primitive visitIfNotNullDynamicPropertyGet( |
| + ast.Send node, |
| + ast.Node receiver, |
| + Selector selector, |
| + _) { |
| + ir.Primitive builtReceiver = visit(receiver); |
|
Kevin Millikin (Google)
2015/05/29 11:02:03
I don't completely understand how we decide what g
Siggi Cherem (dart-lang)
2015/05/29 18:14:05
Good point - I made some changes to reflect this.
|
| + ir.Primitive condition = irBuilder.buildCheckNull(builtReceiver); |
| + return irBuilder.buildConditional( |
| + condition, |
| + (builder) => builtReceiver, |
|
Kevin Millikin (Google)
2015/05/29 11:02:03
We normally give a type annotation on closures:
(
Siggi Cherem (dart-lang)
2015/05/29 18:14:05
Done.
|
| + (builder) => builder.buildDynamicGet(builtReceiver, selector)); |
| + } |
| + |
| + @override |
| ir.Primitive visitDynamicTypeLiteralGet( |
| ast.Send node, |
| ConstantExpression constant, |
| @@ -846,7 +860,12 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive> |
| @override |
| ir.Primitive visitIfNull( |
| ast.Send node, ast.Node left, ast.Node right, _) { |
| - internalError(node, "If-null not yet implemented in cps_ir"); |
| + ir.Primitive receiver = build(left); |
| + ir.Primitive condition = irBuilder.buildCheckNull(receiver); |
| + return irBuilder.buildConditional( |
| + condition, |
| + subbuild(right), |
| + (IrBuilder b) => receiver); |
|
Kevin Millikin (Google)
2015/05/29 11:02:03
Inconsistently named (the other's are all 'builder
Siggi Cherem (dart-lang)
2015/05/29 18:14:05
Done.
|
| } |
| @override |
| @@ -1065,6 +1084,23 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive> |
| translateDynamicArguments(arguments, selector.callStructure)); |
| } |
| + @override |
| + ir.Primitive visitIfNotNullDynamicPropertyInvoke( |
| + ast.Send node, |
| + ast.Node receiver, |
| + ast.NodeList arguments, |
| + Selector selector, |
| + _) { |
| + ir.Primitive builtReceiver = visit(receiver); |
| + ir.Primitive condition = irBuilder.buildCheckNull(builtReceiver); |
| + return irBuilder.buildConditional( |
| + condition, |
| + (builder) => builtReceiver, |
| + (builder) => withBuilder(builder, () => |
|
Johnni Winther
2015/05/29 10:23:24
Introduce helper function in IrBuilderMixin for th
Siggi Cherem (dart-lang)
2015/05/29 18:14:05
Done. Much better
|
| + builder.buildDynamicInvocation(builtReceiver, selector, |
| + translateDynamicArguments(arguments, selector.callStructure)))); |
| + } |
| + |
| ir.Primitive handleLocalInvoke( |
| ast.Send node, |
| LocalElement element, |
| @@ -1255,21 +1291,35 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive> |
| CompoundRhs rhs, |
| void setValue(ir.Primitive value)}) { |
| ir.Primitive value = getValue(); |
| - Selector operatorSelector = |
| - new Selector.binaryOperator(rhs.operator.selectorName); |
| - ir.Primitive rhsValue; |
| - if (rhs.kind == CompoundKind.ASSIGNMENT) { |
| - rhsValue = visit(rhs.rhs); |
| + op.BinaryOperator operator = rhs.operator; |
| + if (operator.kind == op.BinaryOperatorKind.IF_NULL) { |
| + // Unlike other compound operators if-null conditionally will not do the |
| + // assignment operation. |
| + return irBuilder.buildConditional( |
| + irBuilder.buildCheckNull(value), |
| + (builder) => withBuilder(builder, () { |
| + ir.Primitive newValue = visit(rhs.rhs); |
| + setValue(newValue); |
| + return newValue; |
| + }), |
| + (builder) => value); |
| } else { |
| - rhsValue = irBuilder.buildIntegerConstant(1); |
| + Selector operatorSelector = |
| + new Selector.binaryOperator(operator.selectorName); |
| + ir.Primitive rhsValue; |
| + if (rhs.kind == CompoundKind.ASSIGNMENT) { |
| + rhsValue = visit(rhs.rhs); |
| + } else { |
| + rhsValue = irBuilder.buildIntegerConstant(1); |
| + } |
| + List<ir.Primitive> arguments = <ir.Primitive>[rhsValue]; |
| + arguments = normalizeDynamicArguments( |
| + operatorSelector.callStructure, arguments); |
| + ir.Primitive result = |
| + irBuilder.buildDynamicInvocation(value, operatorSelector, arguments); |
| + setValue(result); |
| + return rhs.kind == CompoundKind.POSTFIX ? value : result; |
| } |
| - List<ir.Primitive> arguments = <ir.Primitive>[rhsValue]; |
| - arguments = normalizeDynamicArguments( |
| - operatorSelector.callStructure, arguments); |
| - ir.Primitive result = |
| - irBuilder.buildDynamicInvocation(value, operatorSelector, arguments); |
| - setValue(result); |
| - return rhs.kind == CompoundKind.POSTFIX ? value : result; |
| } |
| @override |
| @@ -1286,6 +1336,22 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive> |
| } |
| @override |
| + ir.Primitive visitIfNotNullDynamicPropertySet( |
| + ast.SendSet node, |
| + ast.Node receiver, |
| + Selector selector, |
| + ast.Node rhs, |
| + _) { |
| + ir.Primitive builtReceiver = visit(receiver); |
| + ir.Primitive condition = irBuilder.buildCheckNull(builtReceiver); |
| + return irBuilder.buildConditional( |
| + condition, |
| + (builder) => builtReceiver, |
| + (builder) => withBuilder(builder, () => |
| + builder.buildDynamicSet(builtReceiver, selector, visit(rhs)))); |
| + } |
| + |
| + @override |
| ir.Primitive handleLocalSet( |
| ast.SendSet node, |
| LocalElement element, |
| @@ -1361,12 +1427,22 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive> |
| Selector setterSelector, |
| arg) { |
| ir.Primitive target = translateReceiver(receiver); |
| - return translateCompounds( |
| - getValue: () => irBuilder.buildDynamicGet(target, getterSelector), |
| - rhs: rhs, |
| - setValue: (ir.Primitive result) { |
| - irBuilder.buildDynamicSet(target, setterSelector, result); |
| - }); |
| + ir.Primitive helper() { |
| + return translateCompounds( |
| + getValue: () => irBuilder.buildDynamicGet(target, getterSelector), |
| + rhs: rhs, |
| + setValue: (ir.Primitive result) { |
| + irBuilder.buildDynamicSet(target, setterSelector, result); |
| + }); |
| + } |
| + if (node.isConditional) { |
| + return irBuilder.buildConditional( |
| + irBuilder.buildCheckNull(target), |
| + (_) => target, |
| + (builder) => withBuilder(builder, helper)); |
| + } else { |
| + return helper(); |
| + } |
| } |
| ir.Primitive buildLocalNoSuchSetter(Local local, ir.Primitive value) { |