internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen)
        {
            // TODO:
            // {target}[{arguments}] op= rhs
            // we need to evaluate {arguments} once: http://ironruby.codeplex.com/workitem/4525

            // first, read target into a temp:
            MSA.Expression transformedLeftTarget = _left.TransformTargetRead(gen);
            MSA.Expression leftTargetTemp;

            if (transformedLeftTarget != null)
            {
                leftTargetTemp = gen.CurrentScope.DefineHiddenVariable(String.Empty, transformedLeftTarget.Type);
            }
            else
            {
                leftTargetTemp = null;
            }

            MSA.Expression transformedRight = _right.TransformRead(gen);

            // lhs &&= rhs  -->  lhs && (lhs = rhs)
            // lhs ||= rhs  -->  lhs || (lhs = rhs)
            if (Operation == Symbols.And || Operation == Symbols.Or)
            {
                MSA.Expression transformedLeftRead = _left.TransformRead(gen,
                                                                         (transformedLeftTarget != null) ? Ast.Assign(leftTargetTemp, transformedLeftTarget) : null,
                                                                         true // tryRead
                                                                         );

                MSA.Expression transformedWrite = _left.TransformWrite(gen, leftTargetTemp, transformedRight);

                if (Operation == Symbols.And)
                {
                    return(AndExpression.TransformRead(gen, transformedLeftRead, transformedWrite));
                }
                else
                {
                    return(OrExpression.TransformRead(gen, transformedLeftRead, transformedWrite));
                }
            }
            else
            {
                // lhs op= rhs  -->  lhs = lhs op rhs
                if (Operation != null)
                {
                    MSA.Expression transformedLeftRead = _left.TransformRead(gen, leftTargetTemp, false);
                    transformedRight = MethodCall.TransformRead(this, gen, false, Operation, transformedLeftRead, null, null, transformedRight, null);
                }

                // transform lhs write assigning lhs-target temp:
                return(_left.TransformWrite(gen,
                                            (transformedLeftTarget != null) ? Ast.Assign(leftTargetTemp, transformedLeftTarget) : null,
                                            transformedRight
                                            ));
            }
        }
        internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen)
        {
            string setterName = _memberName + "=";

            MSA.Expression transformedLeftTarget = _leftTarget.TransformRead(gen);
            MSA.Expression transformedRight      = _right.TransformRead(gen);

            MSA.Expression leftTemp = gen.CurrentScope.DefineHiddenVariable(String.Empty, transformedLeftTarget.Type);

            bool leftIsSelf = _leftTarget.NodeType == NodeTypes.SelfReference;

            // lhs &&= rhs  -->  left.member && (left.member = rhs)
            // lhs ||= rhs  -->  left.member || (left.member = rhs)
            if (Operation == Symbols.And || Operation == Symbols.Or)
            {
                MSA.Expression leftMemberRead   = MethodCall.TransformRead(this, gen, false, _memberName, Ast.Assign(leftTemp, transformedLeftTarget), null, null, null, null);
                MSA.Expression transformedWrite = MethodCall.TransformRead(this, gen, leftIsSelf, setterName, leftTemp, null, null, null, transformedRight);

                if (Operation == Symbols.And)
                {
                    return(AndExpression.TransformRead(gen, leftMemberRead, transformedWrite));
                }
                else
                {
                    return(OrExpression.TransformRead(gen, leftMemberRead, transformedWrite));
                }
            }
            else
            {
                // left.member= left.member().op(right)
                MSA.Expression leftMemberRead   = MethodCall.TransformRead(this, gen, false, _memberName, leftTemp, null, null, null, null);
                MSA.Expression operationCall    = MethodCall.TransformRead(this, gen, false, Operation, leftMemberRead, null, null, transformedRight, null);
                MSA.Expression transformedWrite = MethodCall.TransformRead(this, gen, leftIsSelf, setterName, Ast.Assign(leftTemp, transformedLeftTarget), null, null, null, operationCall);
                return(transformedWrite);
            }
        }