Ejemplo n.º 1
0
        public void BottomUpExpressionRewriter_ElementInit()
        {
            var log = new StringWriter();

            var burs = new BottomUpExpressionRewriter <ArithExpr>
            {
                Leaves =
                {
                    { (ConstantExpression c) => new Const((int)c.Value), c => c.Type == typeof(int), 1 },
                },

                Rules =
                {
                    { (int x, int y) => new List <int> {
                          x, 1, y, 2
                      }, (x, y) => new Add(new Const(3), new Mul(x, y)), 2 },
                },

                Log = log
            };

            AssertCount(burs.Leaves, 1);
            AssertCount(burs.Rules, 1);
            AssertCount(burs.Fallbacks, 0);

            var e = ((Expression <Func <List <int> > >)(() => new List <int> {
                3, 1, 4, 2
            })).Body;
            var a = burs.Rewrite(e);

            Assert.AreEqual("Add(Const(3), Mul(Const(3), Const(4)))", a.ToString());
        }
Ejemplo n.º 2
0
        private static Func <bool, Action <Expression> > GetAsserter <T1, T2, R>(Expression <Func <T1, T2, R> > rule)
        {
            var log = new StringWriter();

            var burs = new BottomUpExpressionRewriter <NumExpr>
            {
                Leaves =
                {
                    { (Expression e) => Val.Zero, 1 },
                },

                Rules =
                {
                    { rule, (x, y) => Val.One, 1 },
                },

                Log = log
            };

            return(succeed => subject =>
            {
                if (succeed)
                {
                    var res = burs.Rewrite(subject);
                    Assert.AreEqual("1", res.ToString());
                }
                else
                {
                    Assert.ThrowsException <InvalidOperationException>(() => burs.Rewrite(subject));
                }
            });
        }
Ejemplo n.º 3
0
        public void BottomUpExpressionRewriter_MemberBinding3()
        {
            var log = new StringWriter();

            var burs = new BottomUpExpressionRewriter <NumExpr>
            {
                Leaves =
                {
                    { (ConstantExpression c) => new Val((int)c.Value), c => c.Type == typeof(int), 1 },
                },

                Rules =
                {
                    { (int x, int y, int z) => new Summer {
                          Xs ={ x,      y,     z }
                      }, (x, y, z) => new Plus(new Plus(x, y), z), 2 },
                },

                Log = log
            };

            AssertCount(burs.Leaves, 1);
            AssertCount(burs.Rules, 1);
            AssertCount(burs.Fallbacks, 0);

            var e1 = ((Expression <Func <Summer> >)(() => new Summer {
                Xs = { 1, 2, 3 }
            })).Body;
            var a1 = burs.Rewrite(e1);

            Assert.AreEqual("Plus(Plus(1, 2), 3)", a1.ToString());

            var e2 = ((Expression <Func <Summer> >)(() => new Summer {
            })).Body;

            Assert.ThrowsException <InvalidOperationException>(() => burs.Rewrite(e2));

            var e3 = ((Expression <Func <Summer> >)(() => new Summer {
                Xs = { 1, 2 }
            })).Body;

            Assert.ThrowsException <InvalidOperationException>(() => burs.Rewrite(e3));

            var e4 = ((Expression <Func <Summer> >)(() => new Summer {
                Xs = { 1, 2, 3, 4 }
            })).Body;

            Assert.ThrowsException <InvalidOperationException>(() => burs.Rewrite(e4));
        }
Ejemplo n.º 4
0
        public void BottomUpExpressionRewriter_Simple3()
        {
            var log = new StringWriter();

            var burs = new BottomUpExpressionRewriter <NumExpr>
            {
                Leaves =
                {
                    { (DefaultExpression d) => Val.Zero,               1 },
                    { (ConstantExpression c) => new Val((int)c.Value), c => c.Type == typeof(int), 1},
                },

                Rules =
                {
                    { () => 1, () => Val.One, 1 },
                },

                Log = log
            };

            AssertCount(burs.Leaves, 2);
            AssertCount(burs.Rules, 1);
            AssertCount(burs.Fallbacks, 0);

            var e1 = Expression.Default(typeof(int));
            var a1 = burs.Rewrite(e1);

            Assert.AreSame(Val.Zero, a1);
            Assert.AreEqual("0", a1.ToString());

            var e2 = Expression.Constant(0, typeof(int));
            var a2 = burs.Rewrite(e2);

            Assert.AreNotSame(Val.Zero, a2);
            Assert.AreEqual("0", a2.ToString());

            var e3 = Expression.Constant(1, typeof(int));
            var a3 = burs.Rewrite(e3);

            Assert.AreSame(Val.One, a3);
            Assert.AreEqual("1", a3.ToString());

            var e4 = Expression.Constant(2, typeof(int));
            var a4 = burs.Rewrite(e4);

            Assert.AreEqual("2", a4.ToString());
        }
Ejemplo n.º 5
0
        public void BottomUpExpressionRewriter_Simple4()
        {
            var log = new StringWriter();

            var burs = new BottomUpExpressionRewriter <ArithExpr>
            {
                Leaves =
                {
                    { (ConstantExpression c) => new Const((int)c.Value), c => c.Type == typeof(int), 1 },
                },

                Rules =
                {
                    { (int x, int y) => x + y, (x, y) => new Add(x, y), 2 },
                    { (int x, int y) => x * y, (x, y) => new Mul(x, y), 3 },
                },

                Fallbacks =
                {
                    { (Expression e) => new Lazy(e.Funcletize <int>()), 9 },
                },

                Log = log
            };

            AssertCount(burs.Leaves, 1);
            AssertCount(burs.Rules, 2);
            AssertCount(burs.Fallbacks, 1);

            var e1 =
                Expression.Add(
                    Expression.Multiply(
                        Expression.Constant(1),
                        Expression.Constant(2)
                        ),
                    Expression.Modulo(
                        Expression.Constant(3),
                        Expression.Constant(4)
                        )
                    );

            var a1 = burs.Rewrite(e1);

            Assert.AreEqual("Add(Mul(Const(1), Const(2)), Lazy(() => (3 % 4)))", a1.ToString());
        }
Ejemplo n.º 6
0
        public void BottomUpExpressionRewriter_MemberBinding2()
        {
            var log = new StringWriter();

            var burs = new BottomUpExpressionRewriter <NumExpr>
            {
                Leaves =
                {
                    { (ConstantExpression c) => new Val((int)c.Value), c => c.Type == typeof(int), 1 },
                },

                Rules =
                {
                    { (int x, int y, int z) => new MullerAdder {
                          M ={ x = x,  Y = y },z = z
                      }, (x, y, z) => new TimesPlus(x, y, z), 2 },
                },

                Log = log
            };

            AssertCount(burs.Leaves, 1);
            AssertCount(burs.Rules, 1);
            AssertCount(burs.Fallbacks, 0);

            var e1 = ((Expression <Func <MullerAdder> >)(() => new MullerAdder {
                M = { x = 2, Y = 3 }, z = 4
            })).Body;
            var a1 = burs.Rewrite(e1);

            Assert.AreEqual("TimesPlus(2, 3, 4)", a1.ToString());

            var e2 = ((Expression <Func <MullerAdder> >)(() => new MullerAdder {
                z = 4, M = { x = 2, Y = 3 }
            })).Body;

            Assert.ThrowsException <InvalidOperationException>(() => burs.Rewrite(e2));

            var e3 = ((Expression <Func <MullerAdder> >)(() => new MullerAdder {
                M = { Y = 3, x = 2 }, z = 4
            })).Body;

            Assert.ThrowsException <InvalidOperationException>(() => burs.Rewrite(e3));
        }
Ejemplo n.º 7
0
        public static void BottomUpExpressionRewriter_MixedTypes()
        {
            var log = new StringWriter();

            var burs = new BottomUpExpressionRewriter <ArithExpr>
            {
                Leaves =
                {
                    { (ConstantExpression c) => new Const((int)c.Value), c => c.Type == typeof(int),  1 },
                    { (ConstantExpression c) => new Const(42),           c => c.Type == typeof(long), 1 },
                },

                Rules =
                {
                    { (int x,  int y) => x + y,  (x, y) => new Add(x, y), 3 },
                    { (long x, long y) => x + y, (x, y) => new Mul(x, y), 2 },
                },

                Log = log
            };

            AssertCount(burs.Leaves, 2);
            AssertCount(burs.Rules, 2);

            var e1 =
                Expression.Add(
                    Expression.Constant(1),
                    Expression.Constant(2)
                    );

            var a1 = burs.Rewrite(e1);

            Assert.AreEqual("Add(Const(1), Const(2))", a1.ToString());

            var e2 =
                Expression.Add(
                    Expression.Constant(1L),
                    Expression.Constant(2L)
                    );

            var a2 = burs.Rewrite(e2);

            Assert.AreEqual("Mul(Const(42), Const(42))", a2.ToString());
        }
Ejemplo n.º 8
0
        public void BottomUpExpressionRewriter_Simple1()
        {
            var log = new StringWriter();

            var burs = new BottomUpExpressionRewriter <ArithExpr>
            {
                Leaves =
                {
                    { (ConstantExpression c) => new Const((int)c.Value), c => c.Type == typeof(int), 1 },
                },

                Rules =
                {
                    { (int x) => - x,         (x) => new Neg(x), 1 },
                    { (int x) => Math.Abs(x), (x) => new Abs(x), 1 },
                    { (int x,                 int y) => x + y,   (x, y) => new Add(x, y), 2},
                    { (int x,                 int y) => x * y,   (x, y) => new Mul(x, y), 3},
                },

                Log = log
            };

            AssertCount(burs.Leaves, 1);
            AssertCount(burs.Rules, 4);
            AssertCount(burs.Fallbacks, 0);

            var e1 =
                Expression.Add(
                    Expression.Multiply(
                        Expression.Constant(1),
                        Expression.Call((MethodInfo)ReflectionHelpers.InfoOf((int x) => Math.Abs(x)),
                                        Expression.Constant(-2)
                                        )
                        ),
                    Expression.Negate(
                        Expression.Constant(3)
                        )
                    );

            var a1 = burs.Rewrite(e1);

            Assert.AreEqual("Add(Mul(Const(1), Abs(Const(-2))), Neg(Const(3)))", a1.ToString());
        }
Ejemplo n.º 9
0
        public void BottomUpExpressionRewriter_ArgumentChecks()
        {
            var burs = new BottomUpExpressionRewriter <ArithExpr>();

#pragma warning disable IDE0034 // Simplify 'default' expression (illustrative of method signature)
            AssertEx.ThrowsException <ArgumentNullException>(() => burs.Leaves.Add(default(Expression <Func <ConstantExpression, ArithExpr> >), 1), ex => Assert.AreEqual("convert", ex.ParamName));
            AssertEx.ThrowsException <ArgumentOutOfRangeException>(() => burs.Leaves.Add((ConstantExpression ce) => new Const(1), -1), ex => Assert.AreEqual("cost", ex.ParamName));

            AssertEx.ThrowsException <ArgumentNullException>(() => burs.Leaves.Add(default(Expression <Func <ConstantExpression, ArithExpr> >), _ => true, 1), ex => Assert.AreEqual("convert", ex.ParamName));
            AssertEx.ThrowsException <ArgumentNullException>(() => burs.Leaves.Add((ConstantExpression ce) => new Const(1), default(Expression <Func <ConstantExpression, bool> >), 1), ex => Assert.AreEqual("predicate", ex.ParamName));
            AssertEx.ThrowsException <ArgumentOutOfRangeException>(() => burs.Leaves.Add((ConstantExpression ce) => new Const(1), _ => true, -1), ex => Assert.AreEqual("cost", ex.ParamName));

            AssertEx.ThrowsException <ArgumentNullException>(() => burs.Rules.Add(default(Expression <Func <int> >), () => new Const(1), 1), ex => Assert.AreEqual("pattern", ex.ParamName));
            AssertEx.ThrowsException <ArgumentNullException>(() => burs.Rules.Add(default(Expression <Func <int, int> >), (x) => new Const(1), 1), ex => Assert.AreEqual("pattern", ex.ParamName));
            AssertEx.ThrowsException <ArgumentNullException>(() => burs.Rules.Add(default(Expression <Func <int, int, int> >), (x, y) => new Const(1), 1), ex => Assert.AreEqual("pattern", ex.ParamName));
            AssertEx.ThrowsException <ArgumentNullException>(() => burs.Rules.Add(default(Expression <Func <int, int, int, int> >), (x, y, z) => new Const(1), 1), ex => Assert.AreEqual("pattern", ex.ParamName));
            AssertEx.ThrowsException <ArgumentNullException>(() => burs.Rules.Add(default(Expression <Func <int, int, int, int, int> >), (x, y, z, a) => new Const(1), 1), ex => Assert.AreEqual("pattern", ex.ParamName));

            AssertEx.ThrowsException <ArgumentNullException>(() => burs.Rules.Add(() => 1, default(Expression <Func <ArithExpr> >), 1), ex => Assert.AreEqual("goal", ex.ParamName));
            AssertEx.ThrowsException <ArgumentNullException>(() => burs.Rules.Add((int x) => x + 1, default(Expression <Func <ArithExpr, ArithExpr> >), 1), ex => Assert.AreEqual("goal", ex.ParamName));
            AssertEx.ThrowsException <ArgumentNullException>(() => burs.Rules.Add((int x, int y) => x + y + 1, default(Expression <Func <ArithExpr, ArithExpr, ArithExpr> >), 1), ex => Assert.AreEqual("goal", ex.ParamName));
            AssertEx.ThrowsException <ArgumentNullException>(() => burs.Rules.Add((int x, int y, int z) => x + y + z + 1, default(Expression <Func <ArithExpr, ArithExpr, ArithExpr, ArithExpr> >), 1), ex => Assert.AreEqual("goal", ex.ParamName));
            AssertEx.ThrowsException <ArgumentNullException>(() => burs.Rules.Add((int x, int y, int z, int a) => x + y + z + a + 1, default(Expression <Func <ArithExpr, ArithExpr, ArithExpr, ArithExpr, ArithExpr> >), 1), ex => Assert.AreEqual("goal", ex.ParamName));

            AssertEx.ThrowsException <ArgumentOutOfRangeException>(() => burs.Rules.Add(() => 1, () => new Const(1), -1), ex => Assert.AreEqual("cost", ex.ParamName));
            AssertEx.ThrowsException <ArgumentOutOfRangeException>(() => burs.Rules.Add((int x) => x + 1, (x) => new Const(1), -1), ex => Assert.AreEqual("cost", ex.ParamName));
            AssertEx.ThrowsException <ArgumentOutOfRangeException>(() => burs.Rules.Add((int x, int y) => x + y + 1, (x, y) => new Const(1), -1), ex => Assert.AreEqual("cost", ex.ParamName));
            AssertEx.ThrowsException <ArgumentOutOfRangeException>(() => burs.Rules.Add((int x, int y, int z) => x + y + z + 1, (x, y, z) => new Const(1), -1), ex => Assert.AreEqual("cost", ex.ParamName));
            AssertEx.ThrowsException <ArgumentOutOfRangeException>(() => burs.Rules.Add((int x, int y, int z, int a) => x + y + z + a + 1, (x, y, z, a) => new Const(1), -1), ex => Assert.AreEqual("cost", ex.ParamName));

            AssertEx.ThrowsException <ArgumentNullException>(() => burs.Fallbacks.Add(default(Expression <Func <Expression, ArithExpr> >), 1), ex => Assert.AreEqual("convert", ex.ParamName));
            AssertEx.ThrowsException <ArgumentOutOfRangeException>(() => burs.Fallbacks.Add((Expression e) => new Const(1), -1), ex => Assert.AreEqual("cost", ex.ParamName));

            AssertEx.ThrowsException <ArgumentNullException>(() => burs.Fallbacks.Add(default(Expression <Func <Expression, ArithExpr> >), _ => true, 1), ex => Assert.AreEqual("convert", ex.ParamName));
            AssertEx.ThrowsException <ArgumentNullException>(() => burs.Fallbacks.Add((Expression e) => new Const(1), default(Expression <Func <Expression, bool> >), 1), ex => Assert.AreEqual("predicate", ex.ParamName));
            AssertEx.ThrowsException <ArgumentOutOfRangeException>(() => burs.Fallbacks.Add((Expression e) => new Const(1), _ => true, -1), ex => Assert.AreEqual("cost", ex.ParamName));

            AssertEx.ThrowsException <ArgumentNullException>(() => burs.Rewrite(default(Expression)), ex => Assert.AreEqual("expression", ex.ParamName));
#pragma warning restore IDE0034 // Simplify 'default' expression
        }
Ejemplo n.º 10
0
        public void BottomUpExpressionRewriter_MemberBinding1()
        {
            var log = new StringWriter();

            var burs = new BottomUpExpressionRewriter <ArithExpr>
            {
                Leaves =
                {
                    { (ConstantExpression c) => new Const((int)c.Value), c => c.Type == typeof(int), 1 },
                },

                Rules =
                {
                    { (int x, int y) => new Adder {
                          x = x, Y = y
                      }, (x, y) => new Add(x, y), 2 },
                },

                Log = log
            };

            AssertCount(burs.Leaves, 1);
            AssertCount(burs.Rules, 1);
            AssertCount(burs.Fallbacks, 0);

            var e1 = ((Expression <Func <Adder> >)(() => new Adder {
                x = 2, Y = 3
            })).Body;
            var a1 = burs.Rewrite(e1);

            Assert.AreEqual("Add(Const(2), Const(3))", a1.ToString());

            var e2 = ((Expression <Func <Adder> >)(() => new Adder(2)
            {
                x = 2, Y = 3
            })).Body;

            Assert.ThrowsException <InvalidOperationException>(() => burs.Rewrite(e2));

            var e3 = ((Expression <Func <Adder> >)(() => new Adder {
                x = 2
            })).Body;

            Assert.ThrowsException <InvalidOperationException>(() => burs.Rewrite(e3));

            var e4 = ((Expression <Func <Muller> >)(() => new Muller {
                x = 2, Y = 3
            })).Body;

            Assert.ThrowsException <InvalidOperationException>(() => burs.Rewrite(e4));

            var e5 = ((Expression <Func <Adder> >)(() => new Adder {
                Y = 3, x = 2
            })).Body;                                                                    // Order matters due to side-effects

            Assert.ThrowsException <InvalidOperationException>(() => burs.Rewrite(e5));

            var e6 = ((Expression <Func <Adder> >)(() => new Adder {
                x = 2, Y = 3, z = 4
            })).Body;

            Assert.ThrowsException <InvalidOperationException>(() => burs.Rewrite(e6));
        }
Ejemplo n.º 11
0
        public void BottomUpExpressionRewriter_Simple5()
        {
            var log = new StringWriter();

            var burs = new BottomUpExpressionRewriter <ArithExpr>
            {
                Leaves =
                {
                    { (ConstantExpression c) => new Const((int)c.Value), c => c.Type == typeof(int), 1 },
                },

                Rules =
                {
                    { (int x, int y) => x + y, (x,    y) => new Add(x,         y), 2 },
                    { (int x, int y) => x * y, (x,    y) => new Mul(x,         y), 3 },
                    { (int a, int b,           int c, int d) => a * b + c * d, (a, b, c, d) => new Add(new Mul(c, d), new Mul(a, b)), 7},
                },

                Fallbacks =
                {
                    { (Expression e) => new Lazy(e.Funcletize <int>()), e => e.NodeType != ExpressionType.Modulo, 9 },
                },

                Log = log
            };

            AssertCount(burs.Leaves, 1);
            AssertCount(burs.Rules, 3);
            AssertCount(burs.Fallbacks, 1);

            var e1 =
                Expression.Add(
                    Expression.Multiply(
                        Expression.Constant(1),
                        Expression.Constant(2)
                        ),
                    Expression.Modulo(
                        Expression.Constant(3),
                        Expression.Constant(4)
                        )
                    );

            Assert.ThrowsException <InvalidOperationException>(() => burs.Rewrite(e1));

            var e2 =
                Expression.Add(
                    Expression.Multiply(
                        Expression.Constant(1),
                        Expression.Constant(2)
                        ),
                    Expression.Divide(
                        Expression.Constant(3),
                        Expression.Constant(4)
                        )
                    );

            var a2 = burs.Rewrite(e2);

            Assert.AreEqual("Add(Mul(Const(1), Const(2)), Lazy(() => (3 / 4)))", a2.ToString());

            var e3 =
                Expression.Add(
                    Expression.Multiply(
                        Expression.Constant(1),
                        Expression.Constant(2)
                        ),
                    Expression.Multiply(
                        Expression.Constant(3),
                        Expression.Constant(4)
                        )
                    );

            var a3 = burs.Rewrite(e3);

            Assert.AreEqual("Add(Mul(Const(3), Const(4)), Mul(Const(1), Const(2)))", a3.ToString());
        }
Ejemplo n.º 12
0
        public void BottomUpExpressionRewriter_Simple2()
        {
            var log = new StringWriter();

            var burs = new BottomUpExpressionRewriter <NumExpr>
            {
                Leaves =
                {
                    { (ConstantExpression c) => new Val((int)c.Value), c => c.Type == typeof(int), 1 },
                },

                Rules =
                {
                    { (int x) => x + 1, (x) => new Inc(x), 1 },
                    { (int x) => 1 + x, (x) => new Inc(x), 1 },
                    { (int x,           int y) => x + y,   (x, y) => new Plus(x, y), 2},
                    { (int x,           int y) => x * y,   (x, y) => new Times(x, y), 3},
                    { (int x,           int y,             int z) => x * y + z, (x, y, z) => new TimesPlus(x, y, z), 4},
                },

                Log = log
            };

            AssertCount(burs.Leaves, 1);
            AssertCount(burs.Rules, 5);
            AssertCount(burs.Fallbacks, 0);

            var e1 =
                Expression.Add(
                    Expression.Multiply(
                        Expression.Add(
                            Expression.Multiply(
                                Expression.Constant(2),
                                Expression.Constant(3)
                                ),
                            Expression.Constant(1)
                            ),
                        Expression.Multiply(
                            Expression.Constant(4),
                            Expression.Constant(5)
                            )
                        ),
                    Expression.Constant(6)
                    );

            var a1 = burs.Rewrite(e1);

            Assert.AreEqual("TimesPlus(Inc(Times(2, 3)), Times(4, 5), 6)", a1.ToString());

            var e2 =
                Expression.Add(
                    Expression.Multiply(
                        Expression.Add(
                            Expression.Constant(1),
                            Expression.Multiply(
                                Expression.Constant(2),
                                Expression.Constant(3)
                                )
                            ),
                        Expression.Multiply(
                            Expression.Constant(4),
                            Expression.Constant(5)
                            )
                        ),
                    Expression.Constant(6)
                    );

            var a2 = burs.Rewrite(e2);

            Assert.AreEqual("TimesPlus(Inc(Times(2, 3)), Times(4, 5), 6)", a2.ToString());
        }