void CompoundAssignmentIsInheriting()
        {
            var or = new Or();

            or |= new Or();

            var and = new And();

            and &= new And();

            var xor = new ExclusiveOr();

            xor ^= new ExclusiveOr();
        }
        public override IExpression VisitBinaryExpression(BinaryExpressionSyntax node)
        {
            var o = this.semanticModel.GetTypeInfo(node);
            var t = this.mapper.Map(o.Type);

            if (node.Kind == SyntaxKind.AssignExpression)
            {
                this.lhs = true;
            }
            var left = this.Visit(node.Left);

            this.lhs = false;
            var             right = this.Visit(node.Right);
            BinaryOperation op    = null;
            var             locs  = Helper.SourceLocation(this.tree, node);

            switch (node.Kind)
            {
            case SyntaxKind.AddAssignExpression: {
                var a = new Assignment()
                {
                    Locations = locs,
                    Source    = new Addition()
                    {
                        LeftOperand  = left,
                        RightOperand = right,
                    },
                    Target = Helper.MakeTargetExpression(left),
                    Type   = t,
                };
                return(a);
            }

            case SyntaxKind.AddExpression:
                op = new Addition();
                break;

            case SyntaxKind.AssignExpression: {
                var mc = left as MethodCall;
                if (mc != null)
                {
                    // then this is really o.P = e for some property P
                    // and the property access has been translated into a call
                    // to set_P.
                    mc.Arguments = new List <IExpression> {
                        right,
                    };
                    return(mc);
                }
                var be = left as BoundExpression;
                if (be != null)
                {
                    var a = new Assignment()
                    {
                        Locations = locs,
                        Source    = right,
                        Target    = new TargetExpression()
                        {
                            Definition = be.Definition,
                            Instance   = be.Instance,
                            Type       = be.Type,
                        },
                        Type = t,
                    };
                    return(a);
                }
                var arrayIndexer = left as ArrayIndexer;
                if (arrayIndexer != null)
                {
                    var a = new Assignment()
                    {
                        Locations = locs,
                        Source    = right,
                        Target    = new TargetExpression()
                        {
                            Definition = arrayIndexer,
                            Instance   = arrayIndexer.IndexedObject,
                            Type       = right.Type,
                        },
                        Type = t,
                    };
                    return(a);
                }
                var addressDereference = left as AddressDereference;
                if (addressDereference != null)
                {
                    var a = new Assignment()
                    {
                        Locations = locs,
                        Source    = right,
                        Target    = new TargetExpression()
                        {
                            Definition = addressDereference,
                            Instance   = null,
                            Type       = t,
                        },
                        Type = t,
                    };
                    return(a);
                }
                throw new InvalidDataException("VisitBinaryExpression: Can't figure out lhs in assignment" + left.Type.ToString());
            }

            case SyntaxKind.BitwiseAndExpression: op = new BitwiseAnd(); break;

            case SyntaxKind.BitwiseOrExpression: op = new BitwiseOr(); break;

            case SyntaxKind.DivideExpression: op = new Division(); break;

            case SyntaxKind.EqualsExpression: op = new Equality(); break;

            case SyntaxKind.ExclusiveOrExpression: op = new ExclusiveOr(); break;

            case SyntaxKind.GreaterThanExpression: op = new GreaterThan(); break;

            case SyntaxKind.GreaterThanOrEqualExpression: op = new GreaterThanOrEqual(); break;

            case SyntaxKind.LeftShiftExpression: op = new LeftShift(); break;

            case SyntaxKind.LessThanExpression: op = new LessThan(); break;

            case SyntaxKind.LessThanOrEqualExpression: op = new LessThanOrEqual(); break;

            case SyntaxKind.LogicalAndExpression:
                return(new Conditional()
                {
                    Condition = left,
                    Locations = locs,
                    ResultIfTrue = right,
                    ResultIfFalse = new CompileTimeConstant()
                    {
                        Type = t, Value = false
                    },
                    Type = t,
                });

            case SyntaxKind.LogicalOrExpression:
                return(new Conditional()
                {
                    Condition = left,
                    Locations = Helper.SourceLocation(this.tree, node),
                    ResultIfTrue = new CompileTimeConstant()
                    {
                        Type = t, Value = true
                    },
                    ResultIfFalse = right,
                    Type = t,
                });

            case SyntaxKind.ModuloExpression: op = new Modulus(); break;

            case SyntaxKind.MultiplyExpression: op = new Multiplication(); break;

            case SyntaxKind.NotEqualsExpression: op = new NotEquality(); break;

            case SyntaxKind.RightShiftExpression: op = new RightShift(); break;

            case SyntaxKind.SubtractAssignExpression: {
                var a = new Assignment()
                {
                    Locations = locs,
                    Source    = new Subtraction()
                    {
                        LeftOperand  = left,
                        RightOperand = right,
                    },
                    Target = Helper.MakeTargetExpression(left),
                    Type   = t,
                };
                return(a);
            }

            case SyntaxKind.MultiplyAssignExpression:
            {
                var a = new Assignment()
                {
                    Locations = locs,
                    Source    = new Multiplication()
                    {
                        LeftOperand  = left,
                        RightOperand = right,
                    },
                    Target = Helper.MakeTargetExpression(left),
                    Type   = t,
                };
                return(a);
            }

            case SyntaxKind.DivideAssignExpression:
            {
                var a = new Assignment()
                {
                    Locations = locs,
                    Source    = new Division()
                    {
                        LeftOperand  = left,
                        RightOperand = right,
                    },
                    Target = Helper.MakeTargetExpression(left),
                    Type   = t,
                };
                return(a);
            }

            case SyntaxKind.ModuloAssignExpression:
            {
                var a = new Assignment()
                {
                    Locations = locs,
                    Source    = new Modulus()
                    {
                        LeftOperand  = left,
                        RightOperand = right,
                    },
                    Target = Helper.MakeTargetExpression(left),
                    Type   = t,
                };
                return(a);
            }

            case SyntaxKind.SubtractExpression: op = new Subtraction(); break;

            default:
                throw new InvalidDataException("VisitBinaryExpression: unknown node = " + node.Kind);
            }
            op.Locations    = locs;
            op.LeftOperand  = left;
            op.RightOperand = right;
            op.Type         = t;
            return(op);
        }
 void ExclusiveOrCanBeExplicitly()
 {
     var a = new ExclusiveOr();
     var b = a ^ a;
 }