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)); } }
public static Expression RoundTripEnumerable(Expression query) { var c = new EnumerableToQueryTreeConverter(); var t = c.Convert(query); var r = t.Reduce(); return(r); }
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); }
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)); }
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)); } }
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)); } }
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)); } }
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()); } }
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()); } }