public void AssignBinary_Compile_Overflow()
        {
            var p = Expression.Parameter(typeof(byte));
            var f = Expression.Lambda <Func <byte, byte> >(CSharpExpression.AddAssignChecked(p, Expression.Constant((byte)1, typeof(byte))), p).Compile();

            Assert.AreEqual((byte)42, f(41));
            AssertEx.Throws <OverflowException>(() => f(byte.MaxValue));
        }
        public void AssignBinary_Factory_String_ArgumentChecking()
        {
            var s = Expression.Parameter(typeof(string));

            AssertEx.Throws <ArgumentException>(() => CSharpExpression.SubtractAssign(s, Expression.Default(typeof(string))));
            AssertEx.Throws <ArgumentException>(() => CSharpExpression.SubtractAssign(s, Expression.Default(typeof(object))));

            // the following are valid
            Assert.IsNotNull(CSharpExpression.AddAssign(s, Expression.Default(typeof(string))));
            Assert.IsNotNull(CSharpExpression.AddAssign(s, Expression.Default(typeof(int))));
            Assert.IsNotNull(CSharpExpression.AddAssign(s, Expression.Default(typeof(object))));
            Assert.IsNotNull(CSharpExpression.AddAssignChecked(s, Expression.Default(typeof(string))));
            Assert.IsNotNull(CSharpExpression.AddAssignChecked(s, Expression.Default(typeof(int))));
            Assert.IsNotNull(CSharpExpression.AddAssignChecked(s, Expression.Default(typeof(object))));
        }
        public void AssignBinary_Factory_Delegate_ArgumentChecking()
        {
            // NB: LINQ checks this one
            AssertEx.Throws <InvalidOperationException>(() => CSharpExpression.AddAssignChecked(Expression.Parameter(typeof(Delegate)), Expression.Default(typeof(Delegate))));

            // NB: Our library checks this one (TODO: should we make the exceptions consistent?)
            AssertEx.Throws <ArgumentException>(() => CSharpExpression.SubtractAssignChecked(Expression.Parameter(typeof(MulticastDelegate)), Expression.Default(typeof(MulticastDelegate))));

            var d = Expression.Parameter(typeof(Action <string>));

            AssertEx.Throws <ArgumentException>(() => CSharpExpression.AddAssignChecked(d, Expression.Default(typeof(Action))));
            AssertEx.Throws <ArgumentException>(() => CSharpExpression.SubtractAssign(d, Expression.Default(typeof(Action <int>))));
            AssertEx.Throws <ArgumentException>(() => CSharpExpression.DivideAssign(d, Expression.Default(typeof(Action <string>))));

            // the following are valid
            Assert.IsNotNull(CSharpExpression.AddAssign(d, Expression.Default(typeof(Action <string>))));
            Assert.IsNotNull(CSharpExpression.AddAssign(d, Expression.Default(typeof(Action <object>))));
            Assert.IsNotNull(CSharpExpression.AddAssignChecked(d, Expression.Default(typeof(Action <string>))));
            Assert.IsNotNull(CSharpExpression.AddAssignChecked(d, Expression.Default(typeof(Action <object>))));
            Assert.IsNotNull(CSharpExpression.SubtractAssign(d, Expression.Default(typeof(Action <string>))));
            Assert.IsNotNull(CSharpExpression.SubtractAssign(d, Expression.Default(typeof(Action <object>))));
            Assert.IsNotNull(CSharpExpression.SubtractAssignChecked(d, Expression.Default(typeof(Action <string>))));
            Assert.IsNotNull(CSharpExpression.SubtractAssignChecked(d, Expression.Default(typeof(Action <object>))));
        }
        public void AssignBinary_Factory_AddAssignChecked()
        {
            var a  = Expression.Parameter(typeof(int));
            var b  = Expression.Constant(1);
            var x  = Expression.Parameter(typeof(int));
            var dl = Expression.Lambda(x, x);
            var df = Expression.Lambda(x, x);

            foreach (var l in GetLhs())
            {
                var r  = Expression.Constant(2);
                var m  = MethodInfoOf(() => Op(0, 0));
                var cl = Expression.Lambda(x, x);
                var cf = Expression.Lambda(x, x);

                var a1 = CSharpExpression.AddAssignChecked(l, r);
                Assert.AreSame(l, a1.Left);
                Assert.AreSame(r, a1.Right);
                Assert.IsNull(a1.Method);
                Assert.IsNull(a1.LeftConversion);
                Assert.IsNull(a1.FinalConversion);

                var a2 = CSharpExpression.AddAssignChecked(l, r, m);
                Assert.AreSame(l, a2.Left);
                Assert.AreSame(r, a2.Right);
                Assert.AreSame(m, a2.Method);
                Assert.IsNull(a2.LeftConversion);
                Assert.IsNull(a2.FinalConversion);

                var a3 = CSharpExpression.AddAssignChecked(l, r, m, cf);
                Assert.AreSame(l, a3.Left);
                Assert.AreSame(r, a3.Right);
                Assert.AreSame(m, a3.Method);
                Assert.AreSame(cf, a3.FinalConversion);
                Assert.IsNull(a3.LeftConversion);

                var a4 = CSharpExpression.AddAssignChecked(l, r, m, cf, cl);
                Assert.AreSame(l, a4.Left);
                Assert.AreSame(r, a4.Right);
                Assert.AreSame(m, a4.Method);
                Assert.AreSame(cf, a4.FinalConversion);
                Assert.AreSame(cl, a4.LeftConversion);

                var a5 = a4.Update(l, cl, r, cf);
                Assert.AreSame(a5, a4);

                var a6 = a4.Update(a, cl, r, cf);
                Assert.AreSame(a, a6.Left);
                Assert.AreSame(r, a6.Right);
                Assert.AreSame(m, a6.Method);
                Assert.AreSame(cf, a6.FinalConversion);
                Assert.AreSame(cl, a6.LeftConversion);

                var a7 = a4.Update(l, dl, r, cf);
                Assert.AreSame(l, a7.Left);
                Assert.AreSame(r, a7.Right);
                Assert.AreSame(m, a7.Method);
                Assert.AreSame(dl, a7.LeftConversion);
                Assert.AreSame(cf, a7.FinalConversion);

                var a8 = a4.Update(l, cl, b, cf);
                Assert.AreSame(l, a8.Left);
                Assert.AreSame(b, a8.Right);
                Assert.AreSame(m, a8.Method);
                Assert.AreSame(cl, a8.LeftConversion);
                Assert.AreSame(cf, a8.FinalConversion);

                var a9 = a4.Update(l, cl, r, df);
                Assert.AreSame(l, a9.Left);
                Assert.AreSame(r, a9.Right);
                Assert.AreSame(m, a9.Method);
                Assert.AreSame(cl, a9.LeftConversion);
                Assert.AreSame(df, a9.FinalConversion);
            }
        }