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 260316710d52a9320eb70ed3af577fc4236aeb4f..712e5cd7a6bf875ecb956fb445f9fa01403bbe0f 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 |
| @@ -122,6 +122,7 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive> |
| BaseImplementationOfConstantsMixin<ir.Primitive, dynamic>, |
| BaseImplementationOfNewMixin<ir.Primitive, dynamic>, |
| BaseImplementationOfCompoundsMixin<ir.Primitive, dynamic>, |
| + BaseImplementationOfSetIfNullsMixin<ir.Primitive, dynamic>, |
| BaseImplementationOfIndexCompoundsMixin<ir.Primitive, dynamic> |
| implements SemanticSendVisitor<ir.Primitive, dynamic> { |
| final TreeElements elements; |
| @@ -1350,6 +1351,21 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive> |
| return rhs.kind == CompoundKind.POSTFIX ? value : result; |
| } |
| + ir.Primitive translateSetIfNull( |
| + ast.SendSet node, |
| + {ir.Primitive getValue(), |
|
karlklose
2015/08/26 12:39:22
getValue is called unconditionally, so it is not r
Johnni Winther
2015/08/28 08:12:12
Yes. Pending the introduction of required named ar
|
| + ast.Node rhs, |
| + void setValue(ir.Primitive value)}) { |
| + ir.Primitive value = getValue(); |
| + // Unlike other compound operators if-null conditionally will not do the |
| + // assignment operation. |
| + return irBuilder.buildIfNull(value, nested(() { |
| + ir.Primitive newValue = build(rhs); |
| + setValue(newValue); |
| + return newValue; |
| + })); |
| + } |
| + |
| @override |
| ir.Primitive handleDynamicSet( |
| ast.SendSet node, |
| @@ -1453,6 +1469,17 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive> |
| } |
| @override |
| + ir.Primitive handleTypeLiteralConstantSetIfNulls( |
| + ast.SendSet node, |
| + ConstantExpression constant, |
| + ast.Node rhs, |
| + _) { |
| + // The type literal is never `null`. |
| + return buildConstantExpression(constant, |
| + sourceInformationBuilder.buildGet(node)); |
| + } |
| + |
| + @override |
| ir.Primitive handleDynamicCompounds( |
| ast.SendSet node, |
| ast.Node receiver, |
| @@ -1482,6 +1509,36 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive> |
| : helper(); |
| } |
| + @override |
| + ir.Primitive handleDynamicSetIfNulls( |
| + ast.Send node, |
| + ast.Node receiver, |
| + Name name, |
| + ast.Node rhs, |
| + _) { |
| + ir.Primitive target = translateReceiver(receiver); |
| + ir.Primitive helper() { |
| + return translateSetIfNull( |
| + node, |
| + getValue: () => irBuilder.buildDynamicGet( |
| + target, |
| + new Selector.getter(name), |
| + elements.getGetterTypeMaskInComplexSendSet(node), |
| + sourceInformationBuilder.buildGet(node)), |
| + rhs: rhs, |
| + setValue: (ir.Primitive result) { |
| + irBuilder.buildDynamicSet( |
| + target, |
| + new Selector.setter(name), |
| + elements.getTypeMask(node), |
| + result); |
| + }); |
| + } |
| + return node.isConditional |
| + ? irBuilder.buildIfNotNullSend(target, nested(helper)) |
| + : helper(); |
| + } |
| + |
| ir.Primitive buildLocalNoSuchSetter(LocalElement local, ir.Primitive value) { |
| Selector selector = new Selector.setter( |
| new Name(local.name, local.library, isSetter: true)); |
| @@ -1514,6 +1571,32 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive> |
| }); |
| } |
| + @override |
| + ir.Primitive handleLocalSetIfNulls( |
| + ast.SendSet node, |
| + LocalElement local, |
| + ast.Node rhs, |
| + _, |
| + {bool isSetterValid}) { |
| + return translateSetIfNull( |
| + node, |
| + getValue: () { |
| + if (local.isFunction) { |
| + return irBuilder.buildLocalFunctionGet(local); |
| + } else { |
| + return irBuilder.buildLocalVariableGet(local); |
| + } |
| + }, |
| + rhs: rhs, |
| + setValue: (ir.Primitive result) { |
| + if (isSetterValid) { |
| + irBuilder.buildLocalVariableSet(local, result); |
| + } else { |
| + return buildLocalNoSuchSetter(local, result); |
| + } |
| + }); |
| + } |
| + |
| ir.Primitive buildStaticNoSuchGetter(Element element) { |
| return buildStaticNoSuchMethod( |
| new Selector.getter(new Name(element.name, element.library)), |
| @@ -1559,9 +1642,45 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive> |
| case CompoundSetter.SETTER: |
| return irBuilder.buildStaticSetterSet(setter, result); |
| case CompoundSetter.INVALID: |
| - // TODO(johnniwinther): Ensure [setter] is non null. |
| - return buildStaticNoSuchSetter( |
| - setter != null ? setter : getter, result); |
| + return buildStaticNoSuchSetter(setter, result); |
| + } |
| + }); |
| + } |
| + |
| + @override |
| + ir.Primitive handleStaticSetIfNulls( |
| + ast.SendSet node, |
| + Element getter, |
| + CompoundGetter getterKind, |
| + Element setter, |
| + CompoundSetter setterKind, |
| + ast.Node rhs, |
| + _) { |
| + return translateSetIfNull( |
| + node, |
| + getValue: () { |
| + switch (getterKind) { |
| + case CompoundGetter.FIELD: |
| + SourceInformation src = sourceInformationBuilder.buildGet(node); |
| + return irBuilder.buildStaticFieldGet(getter, src); |
| + case CompoundGetter.GETTER: |
| + return irBuilder.buildStaticGetterGet( |
| + getter, sourceInformationBuilder.buildGet(node)); |
| + case CompoundGetter.METHOD: |
| + return irBuilder.buildStaticFunctionGet(getter); |
| + case CompoundGetter.UNRESOLVED: |
| + return buildStaticNoSuchGetter(getter); |
| + } |
| + }, |
| + rhs: rhs, |
| + setValue: (ir.Primitive result) { |
| + switch (setterKind) { |
| + case CompoundSetter.FIELD: |
| + return irBuilder.buildStaticFieldSet(setter, result); |
| + case CompoundSetter.SETTER: |
| + return irBuilder.buildStaticSetterSet(setter, result); |
| + case CompoundSetter.INVALID: |
| + return buildStaticNoSuchSetter(setter, result); |
| } |
| }); |
| } |
| @@ -1603,9 +1722,48 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive> |
| case CompoundGetter.METHOD: |
| return irBuilder.buildSuperMethodGet(getter); |
| case CompoundGetter.UNRESOLVED: |
| - // TODO(johnniwinther): Ensure [getter] is not null. |
| return buildSuperNoSuchGetter( |
| - getter != null ? getter : setter, |
| + getter, |
| + elements.getGetterTypeMaskInComplexSendSet(node)); |
| + } |
| + }, |
| + rhs: rhs, |
| + setValue: (ir.Primitive result) { |
| + switch (setterKind) { |
| + case CompoundSetter.FIELD: |
| + return irBuilder.buildSuperFieldSet(setter, result); |
| + case CompoundSetter.SETTER: |
| + return irBuilder.buildSuperSetterSet(setter, result); |
| + case CompoundSetter.INVALID: |
| + return buildSuperNoSuchSetter( |
| + setter, elements.getTypeMask(node), result); |
| + } |
| + }); |
| + } |
| + |
| + @override |
| + ir.Primitive handleSuperSetIfNulls( |
| + ast.SendSet node, |
| + Element getter, |
| + CompoundGetter getterKind, |
| + Element setter, |
| + CompoundSetter setterKind, |
| + ast.Node rhs, |
| + _) { |
| + return translateSetIfNull( |
| + node, |
| + getValue: () { |
| + switch (getterKind) { |
| + case CompoundGetter.FIELD: |
| + return irBuilder.buildSuperFieldGet(getter); |
| + case CompoundGetter.GETTER: |
| + return irBuilder.buildSuperGetterGet( |
| + getter, sourceInformationBuilder.buildGet(node)); |
| + case CompoundGetter.METHOD: |
| + return irBuilder.buildSuperMethodGet(getter); |
| + case CompoundGetter.UNRESOLVED: |
| + return buildSuperNoSuchGetter( |
| + getter, |
| elements.getGetterTypeMaskInComplexSendSet(node)); |
| } |
| }, |
| @@ -1641,6 +1799,17 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive> |
| } |
| @override |
| + ir.Primitive visitTypeVariableTypeLiteralSetIfNull( |
| + ast.Send node, |
| + TypeVariableElement element, |
| + ast.Node rhs, |
| + _) { |
| + // The type variable is never `null`. |
| + return translateTypeVariableTypeLiteral(element, |
| + sourceInformationBuilder.buildGet(node)); |
| + } |
| + |
| + @override |
| ir.Primitive handleIndexCompounds( |
| ast.SendSet node, |
| ast.Node receiver, |