public void AssignBinary_CustomMethod()
        {
            var p = Expression.Parameter(typeof(byte));
            var m = typeof(AssignBinaryTests).GetMethod(nameof(ByteOp), BindingFlags.NonPublic | BindingFlags.Static);
            var f = Expression.Lambda <Func <byte, byte> >(CSharpExpression.AddAssign(p, Expression.Constant((byte)1, typeof(byte)), m), p).Compile();

            Assert.AreEqual((byte)40, f(41));
        }
        public void AssignBinary_MutableStruct_Index()
        {
            var p = Expression.Parameter(typeof(MutableStruct <int>));
            var f = Expression.MakeIndex(p, p.Type.GetProperty("Item"), new[] { Expression.Constant(0) });
            var a = CSharpExpression.AddAssign(f, Expression.Constant(1));
            var b = Expression.Call(typeof(string).GetMethod("Concat", new[] { typeof(object), typeof(object) }), Expression.Convert(a, typeof(object)), Expression.Convert(f, typeof(object)));
            var l = Expression.Lambda <Func <MutableStruct <int>, string> >(b, p);
            var c = l.Compile();

            var m = new MutableStruct <int>();
            var r = c(m);

            Assert.AreEqual("11", r);
        }
        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_Parameter_Compile()
        {
            foreach (var t in new[]
            {
                typeof(byte),
                typeof(sbyte),
                typeof(short),
                typeof(ushort),
                typeof(int),
                typeof(uint),
                typeof(long),
                typeof(ulong),
                typeof(char),
                typeof(float),
                typeof(double),
                typeof(decimal),
            })
            {
                var toString = t.GetMethod("ToString", Array.Empty <Type>());

                var exp = "42";
                if (t == typeof(char))
                {
                    exp = ((char)42).ToString();
                }

                AssertCompile((log, append) =>
                {
                    var x = Expression.Parameter(t);
                    var y = Expression.Parameter(t);

                    var val = Expression.Convert(Expression.Constant(41), t);
                    var one = Expression.Convert(Expression.Constant(1), t);

                    return
                    (Expression.Block(
                         new[] { x, y },
                         Expression.Assign(x, val),
                         Expression.Assign(y, CSharpExpression.AddAssign(x, Expression.Block(log("V"), one))),
                         Expression.Invoke(append, Expression.Call(x, toString)),
                         Expression.Invoke(append, Expression.Call(y, toString))
                         ));
                }, new LogAndResult <object> {
                    Log = { "V", exp, exp }
                });
            }
        }
        public void AssignBinary_CustomConverts()
        {
            var p = Expression.Parameter(typeof(byte));

            // (byte lhs) => (int)(lhs * 2)
            var x = Expression.Parameter(typeof(byte));
            var c = Expression.Lambda(Expression.Multiply(Expression.Convert(x, typeof(int)), Expression.Constant(2)), x);

            // (int res) => (byte)(res / 3)
            var y = Expression.Parameter(typeof(int));
            var d = Expression.Lambda(Expression.Convert(Expression.Divide(y, Expression.Constant(3)), typeof(byte)), y);

            // (int lhs) => lhs + 1
            var f = Expression.Lambda <Func <byte, byte> >(CSharpExpression.AddAssign(p, Expression.Constant(1, typeof(int)), null, d, c), p).Compile();

            Assert.AreEqual((byte)7, f(10));
        }
Beispiel #6
0
        public void ArrayAccess_CompoundAssign_Int32()
        {
            var xs = Expression.Parameter(typeof(int[]));
            var i  = Expression.Parameter(typeof(int));

            var res = Expression.Lambda <Func <int[], int, int> >(CSharpExpression.AddAssign(CSharpExpression.ArrayAccess(xs, i), Expression.Constant(1)), xs, i);

            var f = res.Compile();

            var vals = new int[] { 2, 3, 5, 7 };

            for (int j = 0; j < vals.Length; j++)
            {
                var newVal = vals[j] + 1;

                var assignRes = f(vals, j);

                Assert.AreEqual(newVal, assignRes);
                Assert.AreEqual(newVal, vals[j]);
            }
        }
Beispiel #7
0
        public void ArrayAccess_CompoundAssign_SideEffects()
        {
            AssertCompile((log, append) =>
            {
                var array = Expression.Block(log("A"), Expression.Constant(new[] { 42 }));
                var index = Expression.Block(log("I"), Expression.Constant(0));
                var val   = Expression.Block(log("V"), Expression.Constant(43));

                return(CSharpExpression.AddAssign(CSharpExpression.ArrayAccess(array, index), val));
            }, new LogAndResult <object> {
                Log = { "A", "I", "V" }
            });

            AssertCompile((log, append) =>
            {
                var array = Expression.Block(log("A"), Expression.Constant(new[] { 42 }));
                var index = Expression.Block(log("I"), Expression.Constant(new Index(0)));
                var val   = Expression.Block(log("V"), Expression.Constant(43));

                return(CSharpExpression.AddAssign(CSharpExpression.ArrayAccess(array, index), val));
            }, new LogAndResult <object> {
                Log = { "A", "I", "V" }
            });


            AssertCompile((log, append) =>
            {
                var array = Expression.Block(log("A"), Expression.Constant(new[, ] {
                    { 42 }
                }));
                var index1 = Expression.Block(log("I1"), Expression.Constant(0));
                var index2 = Expression.Block(log("I2"), Expression.Constant(0));
                var val    = Expression.Block(log("V"), Expression.Constant(43));

                return(CSharpExpression.AddAssign(CSharpExpression.ArrayAccess(array, index1, index2), val));
            }, new LogAndResult <object> {
                Log = { "A", "I1", "I2", "V" }
            });
        }
        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_AddAssign()
        {
            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.AddAssign(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.AddAssign(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.AddAssign(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.AddAssign(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);
            }
        }
        public void AssignBinary_Index_Compile()
        {
            foreach (var t in new[]
            {
                typeof(byte),
                typeof(sbyte),
                typeof(short),
                typeof(ushort),
                typeof(int),
                typeof(uint),
                typeof(long),
                typeof(ulong),
                typeof(char),
                typeof(float),
                typeof(double),
                typeof(decimal),
            })
            {
                var toString = t.GetMethod("ToString", Array.Empty <Type>());

                var exp = "42";
                if (t == typeof(char))
                {
                    exp = ((char)42).ToString();
                }

                AssertCompile((log, append) =>
                {
                    var y = Expression.Parameter(t);

                    var val = Expression.Convert(Expression.Constant(41), t);
                    var one = Expression.Convert(Expression.Constant(1), t);

                    var list = typeof(List <>).MakeGenericType(t);
                    var ctor = list.GetConstructor(new[] { typeof(IEnumerable <>).MakeGenericType(t) });
                    var item = list.GetProperty("Item");

                    var index =
                        CSharpExpression.Index(
                            Expression.Block(
                                log("L"),
                                Expression.New(ctor, Expression.NewArrayInit(t, Expression.Default(t), val))
                                ),
                            item,
                            CSharpExpression.Bind(
                                item.GetIndexParameters()[0],
                                Expression.Block(
                                    log("I"),
                                    Expression.Constant(1)
                                    )
                                )
                            );

                    return
                    (Expression.Block(
                         new[] { y },
                         Expression.Assign(y, CSharpExpression.AddAssign(index, Expression.Block(log("V"), one))),
                         Expression.Invoke(append, Expression.Call(y, toString))
                         ));
                }, new LogAndResult <object> {
                    Log = { "L", "I", "V", exp }
                });
            }

            // TODO: tests with multiple indexer parameters out of order
        }