Example #1
0
        public void Optimizer_TakeCoalescing()
        {
            var cmp = new ExpressionEqualityComparer();

            {
                var e = Infer(() => new int[0].Take(100).Take(10)).Body;
                var q = new EnumerableToQueryTreeConverter().Convert(e);
                var c = new CoalescingOptimizer().Optimize(q);
                var o = c.Reduce();

                Assert.IsTrue(cmp.Equals(
                                  Infer(() => new int[0].Take(10)).Body,
                                  o));
            }

            {
                var e = Infer(() => new int[0].Take(10).Take(100)).Body;
                var q = new EnumerableToQueryTreeConverter().Convert(e);
                var c = new CoalescingOptimizer().Optimize(q);
                var o = c.Reduce();

                Assert.IsTrue(cmp.Equals(
                                  Infer(() => new int[0].Take(10)).Body,
                                  o));
            }

            {
                var e = Infer(() => new int[0].Take(10).Take(Math.Abs(-100))).Body;
                var q = new EnumerableToQueryTreeConverter().Convert(e);
                var c = new CoalescingOptimizer().Optimize(q);
                var o = c.Reduce();

                Assert.IsTrue(cmp.Equals(
                                  Infer(() => new int[0].Take(Math.Min(10, Math.Abs(-100)))).Body,
                                  o));
            }

            {
                var e = Infer(() => new int[0].Take(Math.Abs(-100)).Take(10)).Body;
                var q = new EnumerableToQueryTreeConverter().Convert(e);
                var c = new CoalescingOptimizer().Optimize(q);
                var o = c.Reduce();

                Assert.IsTrue(cmp.Equals(
                                  Infer(() => new int[0].Take(Math.Min(Math.Abs(-100), 10))).Body,
                                  o));
            }

            {
                var e = Infer(() => new int[0].Take(Math.Abs(-1)).Take(Math.Abs(-100))).Body;
                var q = new EnumerableToQueryTreeConverter().Convert(e);
                var c = new CoalescingOptimizer().Optimize(q);
                var o = c.Reduce();

                Assert.IsTrue(cmp.Equals(
                                  Infer(() => new int[0].Take(Math.Min(Math.Abs(-1), Math.Abs(-100)))).Body,
                                  o));
            }
        }
Example #2
0
        public static Expression RoundTripEnumerable(Expression query)
        {
            var c = new EnumerableToQueryTreeConverter();
            var t = c.Convert(query);
            var r = t.Reduce();

            return(r);
        }
Example #3
0
        public static Expression RoundTripAndTouchEnumerable(Expression query)
        {
            var c = new EnumerableToQueryTreeConverter();
            var t = c.Convert(query);
            var i = new TouchVisitor().Visit(t);
            var r = i.Reduce();

            return(r);
        }
Example #4
0
        public void Optimizer_NoOptimization()
        {
            var cmp = new ExpressionEqualityComparer();
            var e   = Infer(() => new int[0].Where(x => x >= 0).Select(_ => _).Take(100).First()).Body;
            var q   = new EnumerableToQueryTreeConverter().Convert(e);
            var c   = new CoalescingOptimizer().Optimize(q);
            var o   = c.Reduce();

            Assert.AreSame(q, c);
            Assert.IsTrue(cmp.Equals(e, o));
        }
Example #5
0
        public void Optimizer_FirstCoalescing()
        {
            var cmp = new ExpressionEqualityComparer();

            {
                var e = Infer(() => new int[0].Where(x => true).First()).Body;
                var q = new EnumerableToQueryTreeConverter().Convert(e);
                var c = new CoalescingOptimizer().Optimize(q);
                var o = c.Reduce();

                Assert.IsTrue(cmp.Equals(
                                  Infer(() => new int[0].First(x => true)).Body,
                                  o));
            }
        }
Example #6
0
        public void Optimizer_SelectCoalescing()
        {
            var cmp = new ExpressionEqualityComparer();

            {
                var e = Infer(() => new int[0].Select(i => i.ToString()).Select(s => int.Parse(s))).Body;
                var q = new EnumerableToQueryTreeConverter().Convert(e);
                var c = new CoalescingOptimizer().Optimize(q);
                var o = c.Reduce();

                Assert.AreEqual(ExpressionType.Call, o.NodeType);
                var select = (MethodCallExpression)o;
                Assert.AreEqual(ReflectionHelpers.InfoOf((IEnumerable <int> enumerable) => enumerable.Select(default(Func <int, int>))), select.Method);

                var selector = (Expression <Func <int, int> >)select.Arguments[1];

                var x = Expression.Parameter(typeof(int));
                var y = Expression.Parameter(typeof(string));
                var expectedCoalesced =
                    Expression.Lambda(
                        Expression.Invoke(
                            Expression.Lambda(
                                Expression.Call(
                                    null,
                                    (MethodInfo)ReflectionHelpers.InfoOf((string s) => int.Parse(s)),
                                    y
                                    ),
                                y
                                ),
                            Expression.Call(
                                x,
                                (MethodInfo)ReflectionHelpers.InfoOf((int i) => i.ToString())
                                )
                            ),
                        x
                        );

                Assert.IsTrue(cmp.Equals(
                                  expectedCoalesced,
                                  selector));
            }

            {
                var e = Infer(() => new int[0].Select(i => i.ToString()).Select(i => int.Parse(i))).Body;
                var q = new EnumerableToQueryTreeConverter().Convert(e);
                var c = new CoalescingOptimizer().Optimize(q);
                var o = c.Reduce();

                var r =
                    BetaReducer.Reduce(
                        Expression.Invoke(
                            Infer((Func <string, int> f) => new int[0].Select(i => f(i.ToString()))),
                            Infer((string i) => int.Parse(i))
                            ),
                        BetaReductionNodeTypes.Unrestricted,
                        BetaReductionRestrictions.None
                        );

                Assert.IsTrue(cmp.Equals(
                                  r,
                                  o));
            }

            {
                var e = Infer(() => new int[0].Select(new[] { (Func <int, string>)(i => i.ToString()) }.First()).Select(i => int.Parse(i))).Body;
                var q = new EnumerableToQueryTreeConverter().Convert(e);
                var c = new CoalescingOptimizer().Optimize(q);
                var o = c.Reduce();

                var r =
                    BetaReducer.Reduce(
                        Expression.Invoke(
                            Infer((Func <string, int> g, Func <int, string> f) => new int[0].Select(i => g(f(i)))),
                            Infer((string i) => int.Parse(i)),
                            Infer(() => new[] { (Func <int, string>)(i => i.ToString()) }.First()).Body
                            ),
                        BetaReductionNodeTypes.Unrestricted,
                        BetaReductionRestrictions.None
                        );

                Assert.IsTrue(cmp.Equals(
                                  r,
                                  o));
            }

            {
                var e = Infer(() => new int[0].Select(i => i.ToString()).Select(new[] { (Func <string, int>)(i => int.Parse(i)) }.First())).Body;
                var q = new EnumerableToQueryTreeConverter().Convert(e);
                var c = new CoalescingOptimizer().Optimize(q);
                var o = c.Reduce();

                var r =
                    BetaReducer.ReduceEager(
                        Expression.Invoke(
                            Infer((Func <string, int> g, Func <int, string> f) => new int[0].Select(i => g(f(i)))),
                            Infer(() => new[] { (Func <string, int>)(i => int.Parse(i)) }.First()).Body,
                            Infer((int i) => i.ToString())
                            ),
                        BetaReductionNodeTypes.Unrestricted,
                        BetaReductionRestrictions.None,
                        false
                        );

                Assert.IsTrue(cmp.Equals(
                                  r,
                                  o));
            }
        }
Example #7
0
        public void Optimizer_WhereCoalescing()
        {
            var cmp = new ExpressionEqualityComparer();

            {
                var e = Infer(() => new int[0].Where(x => x >= 0).Where(x => x <= 0)).Body;
                var q = new EnumerableToQueryTreeConverter().Convert(e);
                var c = new CoalescingOptimizer().Optimize(q);
                var o = c.Reduce();

                Assert.IsTrue(cmp.Equals(
                                  Infer(() => new int[0].Where(x => x >= 0 && x <= 0)).Body,
                                  o));
            }

            {
                Expression <Func <Func <int, bool>, Func <int, bool> > > id = _ => _;
                var e =
                    BetaReducer.Reduce(
                        Expression.Invoke(
                            Infer((Func <Func <int, bool>, Func <int, bool> > f) => new int[0].Where(f(x => x >= 0)).Where(x => x <= 0)),
                            id
                            ),
                        BetaReductionNodeTypes.Unrestricted,
                        BetaReductionRestrictions.None
                        );
                var q = new EnumerableToQueryTreeConverter().Convert(e);
                var c = new CoalescingOptimizer().Optimize(q);
                var o = c.Reduce();

                Assert.IsTrue(cmp.Equals(
                                  BetaReducer.Reduce(
                                      Expression.Invoke(
                                          Infer((Func <Func <int, bool>, Func <int, bool> > f) => new int[0].Where(y => f(x => x >= 0)(y) && y <= 0)),
                                          id
                                          ),
                                      BetaReductionNodeTypes.Unrestricted,
                                      BetaReductionRestrictions.None
                                      ),
                                  o));
            }

            {
                var e = Infer(() => new int[0].Where(Enumerable.Range(0, 1).Select(_ => (Func <int, bool>)(x => x >= 0)).Single()).Where(x => x <= 0)).Body;
                var q = new EnumerableToQueryTreeConverter().Convert(e);
                var c = new CoalescingOptimizer().Optimize(q);
                var o = c.Reduce();

                Assert.IsTrue(cmp.Equals(
                                  Infer(() => new int[0].Where(x => Enumerable.Range(0, 1).Select(_ => (Func <int, bool>)(y => y >= 0)).Single()(x) && x <= 0)).Body,
                                  o));
            }

            {
                var e = Infer(() => new int[0].Where(x => x >= 0).Where(Enumerable.Range(0, 1).Select(_ => (Func <int, bool>)(x => x <= 0)).Single())).Body;
                var q = new EnumerableToQueryTreeConverter().Convert(e);
                var c = new CoalescingOptimizer().Optimize(q);
                var o = c.Reduce();

                Assert.IsTrue(cmp.Equals(
                                  Infer(() => new int[0].Where(x => x >= 0 && Enumerable.Range(0, 1).Select(_ => (Func <int, bool>)(y => y <= 0)).Single()(x))).Body,
                                  o));
            }
        }
Example #8
0
        public void LetCoalescer_Simple()
        {
            {
                var e =
                    Infer(() =>
                          from i in Enumerable.Range(0, 1)
                          let x                                                                                                                                                                                                                                                                                         = 42
                                                                                          let y                                                                                                                                                                                                                         = i
                                                                                                                                                  let z                                                                                                                                                                 = 100
                                                                                                                                                                                                  let a                                                                                                                 = x
                                                                                                                                                                                                                                          let b                                                                         = i.ToString()
                                                                                                                                                                                                                                                                          let c                                         = 2
                                                                                                                                                                                                                                                                                                  let d                 = i + 1
                                                                                                                                                                                                                                                                                                                  let f = i * 3
                                                                                                                                                                                                                                                                                                                          select i
                          ).Body;

                var converter = new EnumerableToQueryTreeConverter();
                var q         = converter.Convert(e);
                var l         = new LetOptimizer();
                var o         = l.Optimize(q);
                var r         = o.Reduce();

                var counter = new SelectCountingVisitor();
                counter.Visit(r);
                Assert.AreEqual(2, counter.Count); // one for the coalesced let and one for the final select
                Assert.AreEqual(0, r.Funcletize <IEnumerable <int> >().Compile()().First());
            }

            {
                var e =
                    Infer(() =>
                          from i in Enumerable.Range(0, 1)
                          let x                                                                                                                                                                                                                                                                                         = 42
                                                                                          let y                                                                                                                                                                                                                         = i
                                                                                                                                                  let z                                                                                                                                                                 = 100
                                                                                                                                                                                                  let a                                                                                                                 = i
                                                                                                                                                                                                                                          let b                                                                         = i.ToString()
                                                                                                                                                                                                                                                                          let c                                         = 2
                                                                                                                                                                                                                                                                                                  let d                 = "b = " + b
                                                                                                                                                                                                                                                                                                                  let f = i * 3
                                                                                                                                                                                                                                                                                                                          select i
                          ).Body;

                var converter = new EnumerableToQueryTreeConverter();
                var q         = converter.Convert(e);
                var l         = new LetOptimizer();
                var o         = l.Optimize(q);
                var r         = o.Reduce();

                var counter = new SelectCountingVisitor();
                counter.Visit(r);
                Assert.AreEqual(3, counter.Count); // two for the coalesced let and one for the final select
                Assert.AreEqual(e.Funcletize <IEnumerable <int> >().Compile()().First(), r.Funcletize <IEnumerable <int> >().Compile()().First());
            }

            {
                var e =
                    Infer(() =>
                          from i in Enumerable.Range(0, 1)
                          let x                                                                                                                                                                                                                                                                                         = 42
                                                                                          let y                                                                                                                                                                                                                         = i
                                                                                                                                                  let z                                                                                                                                                                 = 100
                                                                                                                                                                                                  let a                                                                                                                 = x
                                                                                                                                                                                                                                          let b                                                                         = i.ToString()
                                                                                                                                                                                                                                                                          let c                                         = 2
                                                                                                                                                                                                                                                                                                  let d                 = i + 1
                                                                                                                                                                                                                                                                                                                  let f = i - 3
                                                                                                                                                                                                                                                                                                                          select string.Format("{0} {1} {2} {3} {4} {5} {6} {7} {8}", i, x, y, z, a, b, c, d, f)
                          ).Body;

                var converter = new EnumerableToQueryTreeConverter();
                var q         = converter.Convert(e);
                var l         = new LetOptimizer();
                var o         = l.Optimize(q);
                var r         = o.Reduce();

                var counter = new SelectCountingVisitor();
                counter.Visit(r);
                Assert.AreEqual(2, counter.Count); // one for the coalesced let and one for the final select
                Assert.AreEqual(e.Funcletize <IEnumerable <string> >().Compile()().First(), r.Funcletize <IEnumerable <string> >().Compile()().First());
            }

            {
                var e =
                    Infer(() =>
                          from p in Enumerable.Repeat(new Person {
                    Name = "Bob", Age = 25
                }, 1)
                          let n                 = p.Name
                                          let a = p.Age
                                                  select n + " is " + a
                          ).Body;

                var converter = new EnumerableToQueryTreeConverter();
                var q         = converter.Convert(e);
                var l         = new LetOptimizer();
                var o         = l.Optimize(q);
                var r         = o.Reduce();

                var counter = new SelectCountingVisitor();
                counter.Visit(r);
                Assert.AreEqual(2, counter.Count); // one for the coalesced let and one for the final select
                Assert.AreEqual(e.Funcletize <IEnumerable <string> >().Compile()().First(), r.Funcletize <IEnumerable <string> >().Compile()().First());
            }

            {
                var e =
                    Infer(() =>
                          from p in Enumerable.Repeat(new Person {
                    Name = "Alice", Age = 30
                }, 1)
                          let n                 = p.Name
                                          let s = n.Length
                                                  select n + ".Length = " + s
                          ).Body;

                var converter = new EnumerableToQueryTreeConverter();
                var q         = converter.Convert(e);
                var l         = new LetOptimizer();
                var o         = l.Optimize(q);
                var r         = o.Reduce();

                var counter = new SelectCountingVisitor();
                counter.Visit(r);
                Assert.AreEqual(3, counter.Count); // The let bindings can't be coalesced since the second one refers to the first
                Assert.AreEqual(e.Funcletize <IEnumerable <string> >().Compile()().First(), r.Funcletize <IEnumerable <string> >().Compile()().First());
            }
        }
Example #9
0
        public void LetCoalescer_VariableMasking()
        {
            var select = ((MethodInfo)ReflectionHelpers.InfoOf((IEnumerable <int> xs) => xs.Select(x => x))).GetGenericMethodDefinition();

            {
                //Enumerable
                //    .Range(0, 1)
                //    .Select(x => new { i = 1 })
                //    .Select(y => new { A = y, b = (('a y) => y.i)(new { i = 2 }) })

#pragma warning disable IDE0050 // Convert to tuple. (Test for anonymous types.)

                var a = new { i = 1 };
                var b = new { A = a, b = 1 };
                var t = a.GetType();
                var u = b.GetType();

#pragma warning restore IDE0050

                var s = Infer(() => Enumerable.Range(0, 1)).Body;

                var x = Expression.Parameter(typeof(int));
                var y = Expression.Parameter(t);
                var e =
                    Expression.Call(
                        select.MakeGenericMethod(new[] { t, u }),
                        Expression.Call(
                            select.MakeGenericMethod(new[] { typeof(int), t }),
                            s,
                            Expression.Lambda(
                                Expression.New(
                                    t.GetConstructors().Single(),
                                    new[] { Expression.Constant(1) },
                                    t.GetMember("i").Single()
                                    ),
                                x
                                )
                            ),
                        Expression.Lambda(
                            Expression.New(
                                u.GetConstructors().Single(),
                                new Expression[]
                {
                    y,
                    Expression.Invoke(
                        Expression.Lambda(Expression.MakeMemberAccess(y, t.GetMember("i").Single()), y),
                        Expression.New(
                            t.GetConstructors().Single(),
                            new[] { Expression.Constant(2) },
                            t.GetMember("i").Single()
                            )
                        )
                },
                                u.GetMember("A").Single(),
                                u.GetMember("b").Single()
                                ),
                            y
                            )
                        );

                var converter = new EnumerableToQueryTreeConverter();
                var q         = converter.Convert(e);
                var l         = new LetOptimizer();
                var o         = l.Optimize(q);
                var r         = o.Reduce();

                var counter = new SelectCountingVisitor();
                counter.Visit(r);
                Assert.AreEqual(1, counter.Count); // one for the coalesced let and one for the final select
                Assert.AreEqual(e.Funcletize <IEnumerable <object> >().Compile()().First(), r.Funcletize <IEnumerable <object> >().Compile()().First());
            }

            {
                //Enumerable
                //    .Range(0, 1)
                //    .Select(x => new { i = 1 })
                //    .Select(y => new { A = y, b = (('a z) => z.i)(new { i = 2 }) })

#pragma warning disable IDE0050 // Convert to tuple. (Test for anonymous types.)

                var a = new { i = 1 };
                var b = new { A = a, b = 1 };
                var t = a.GetType();
                var u = b.GetType();

#pragma warning restore IDE0050

                var s = Infer(() => Enumerable.Range(0, 1)).Body;

                var x = Expression.Parameter(typeof(int));
                var y = Expression.Parameter(t);
                var z = Expression.Parameter(t);
                var e =
                    Expression.Call(
                        select.MakeGenericMethod(new[] { t, u }),
                        Expression.Call(
                            select.MakeGenericMethod(new[] { typeof(int), t }),
                            s,
                            Expression.Lambda(
                                Expression.New(
                                    t.GetConstructors().Single(),
                                    new[] { Expression.Constant(1) },
                                    t.GetMember("i").Single()
                                    ),
                                x
                                )
                            ),
                        Expression.Lambda(
                            Expression.New(
                                u.GetConstructors().Single(),
                                new Expression[]
                {
                    y,
                    Expression.Invoke(
                        Expression.Lambda(Expression.MakeMemberAccess(z, t.GetMember("i").Single()), z),
                        Expression.New(
                            t.GetConstructors().Single(),
                            new[] { Expression.Constant(2) },
                            t.GetMember("i").Single()
                            )
                        )
                },
                                u.GetMember("A").Single(),
                                u.GetMember("b").Single()
                                ),
                            y
                            )
                        );

                var converter = new EnumerableToQueryTreeConverter();
                var q         = converter.Convert(e);
                var l         = new LetOptimizer();
                var o         = l.Optimize(q);
                var r         = o.Reduce();

                var counter = new SelectCountingVisitor();
                counter.Visit(r);
                Assert.AreEqual(1, counter.Count); // one for the coalesced let and one for the final select
                Assert.AreEqual(e.Funcletize <IEnumerable <object> >().Compile()().First(), r.Funcletize <IEnumerable <object> >().Compile()().First());
            }

            {
                //Enumerable
                //    .Range(0, 1)
                //    .Select(x => new { i = 1 })
                //    .Select(y => (('a y) => y.i)(new { i = y.i + 1 }))
                var a = new { i = 1 };
                var t = a.GetType();

                var s = Infer(() => Enumerable.Range(0, 1)).Body;

                var x = Expression.Parameter(typeof(int));
                var y = Expression.Parameter(t);
                var e =
                    Expression.Call(
                        select.MakeGenericMethod(new[] { t, typeof(int) }),
                        Expression.Call(
                            select.MakeGenericMethod(new[] { typeof(int), t }),
                            s,
                            Expression.Lambda(
                                Expression.New(
                                    t.GetConstructors().Single(),
                                    new[] { Expression.Constant(1) },
                                    t.GetMember("i").Single()
                                    ),
                                x
                                )
                            ),
                        Expression.Lambda(
                            Expression.Invoke(
                                Expression.Lambda(Expression.MakeMemberAccess(y, t.GetMember("i").Single()), y),
                                Expression.New(
                                    t.GetConstructors().Single(),
                                    new[] { Expression.Add(Expression.MakeMemberAccess(y, t.GetMember("i").Single()), Expression.Constant(1)) },
                                    t.GetMember("i").Single()
                                    )
                                ),
                            y
                            )
                        );

                var converter = new EnumerableToQueryTreeConverter();
                var q         = converter.Convert(e);
                var l         = new LetOptimizer();
                var o         = l.Optimize(q);
                var r         = o.Reduce();

                var counter = new SelectCountingVisitor();
                counter.Visit(r);
                Assert.AreEqual(2, counter.Count); // one for the coalesced let and one for the final select
                Assert.AreEqual(e.Funcletize <IEnumerable <int> >().Compile()().First(), r.Funcletize <IEnumerable <int> >().Compile()().First());
            }
        }