Esempio n. 1
0
        public void AnonymousTypeTupletizer_TransparentIdentifiers()
        {
            Expression <Func <IEnumerable <int>, IEnumerable <string>, IEnumerable <bool> > > f = (xs, ys) => from x in xs
                                                                                                  from y in ys
                                                                                                  let l                 = y.Length
                                                                                                                  let k = x * l
                                                                                                                          where l > 0
                                                                                                                          where k != 1
                                                                                                                          let b = x + l < 42
                                                                                                                                  select !b;

            //Expression<Func<IEnumerable<int>, IEnumerable<string>, IEnumerable<bool>>> g = (xs, ys) => xs
            //                                                                                           .SelectMany(x => ys, (x, y) => new { x = x, y = y })
            //                                                                                           .Select(t => new { t, l = t.y.Length })
            //                                                                                           .Select(t => new { t, k = t.t.x * t.l })
            //                                                                                           .Where(t => t.t.l > 0)
            //                                                                                           .Where(t => t.k != 1)
            //                                                                                           .Select(t => new { t, b = t.t.t.x + t.t.l < 42 })
            //                                                                                           .Select(t => !t.b);

            Expression <Func <IEnumerable <int>, IEnumerable <string>, IEnumerable <bool> > > g = (xs, ys) => xs
                                                                                                  .SelectMany(x => ys, (x, y) => new Tuple <int, string>(x, y))
                                                                                                  .Select(t => new Tuple <Tuple <int, string>, int>(t, t.Item2.Length))
                                                                                                  .Select(t => new Tuple <Tuple <Tuple <int, string>, int>, int>(t, t.Item1.Item1 * t.Item2))
                                                                                                  .Where(t => t.Item1.Item2 > 0)
                                                                                                  .Where(t => t.Item2 != 1)
                                                                                                  .Select(t => new Tuple <Tuple <Tuple <Tuple <int, string>, int>, int>, bool>(t, t.Item1.Item1.Item1 + t.Item1.Item2 < 42))
                                                                                                  .Select(t => !t.Item2);

            var te = AnonymousTypeTupletizer.Tupletize(f, Expression.Constant(value: null));

            var eq = new ExpressionEqualityComparer();

            Assert.IsTrue(eq.Equals(g, te));
        }
Esempio n. 2
0
        public void Quoter_Environment_Expressible2()
        {
            var quoter = new Quoter(DefaultExpressionPolicy.Instance);

            var expr = (Expression <Func <int, Quotable> >)(x => new Quotable()
            {
                X = x
            });

            var res = quoter.Visit(expr);

            var obj   = (Func <int, Quotable>)res.Evaluate();
            var value = obj(42);

            var quote = value.Expression;

            var eq = new ExpressionEqualityComparer();

            var mi = (MemberInitExpression)expr.Body;
            var b  = (MemberAssignment)mi.Bindings[0];

            Assert.IsTrue(
                eq.Equals(
                    mi.Update(
                        mi.NewExpression,
                        new[]
            {
                b.Update(Expression.Constant(42))
            }
                        ),
                    quote
                    )
                );
        }
Esempio n. 3
0
        protected override bool Equals(Expression x, Expression y)
        {
            var comparer = new ExpressionEqualityComparer(() => new Comparator(new StructuralTypeEqualityComparator()));
            var res      = comparer.Equals(x, y);

            return(res);
        }
Esempio n. 4
0
        private static void AssertRoundtrip(Expression expected, IExpressionSerializer serializer)
        {
            var actual   = Roundtrip(expected, serializer);
            var comparer = new ExpressionEqualityComparer(() => new SimpleComparator());

            Assert.IsTrue(comparer.Equals(expected, actual), "Expected: {0}\nActual: {1}", expected.ToString(), actual.ToString());
        }
        public void TestConstantFunction()
        {
            var expected = Expression.Invoke(Expression.Constant((Func <int>)TestFunction));
            var actual   = Expression.Invoke(Expression.Constant((Func <int>)TestFunction)).InlineInvokes();

            ExpressionEqualityComparer.AssertExpressionsEqual(expected, actual);
        }
Esempio n. 6
0
        public void InvocationInlining2()
        {
            var eq = new ExpressionEqualityComparer();

            var x = Expression.Parameter(typeof(int));
            var y = Expression.Parameter(typeof(int));

            var e =
                Expression.Invoke(
                    Expression.Lambda(Expression.Add(x, y), x, y),
                    Expression.Constant(1),
                    Expression.Constant(2)
                    );

            foreach (var f in new[] { Optimizations.InvocationInlining, Optimizations.All })
            {
                var o = Optimizer.Optimize(e, f);

                Assert.IsTrue(
                    eq.Equals(o,
                              Expression.Block(new[] { x, y },
                                               Expression.Assign(x, Expression.Constant(1)),
                                               Expression.Assign(y, Expression.Constant(2)),
                                               Expression.Add(x, y)
                                               )
                              )
                    );
            }
        }
Esempio n. 7
0
        public void Quoter_WithEnvironment()
        {
            var quoter = new Quoter(DefaultExpressionPolicy.Instance);

            var expr = (Expression <Func <int, ISubscribable <int> > >)(x => Subscribable.Return(x));

            var res = quoter.Visit(expr);

            var obj   = (Func <int, ISubscribable <int> >)res.Evaluate();
            var value = obj(42);

            var quote = ((IExpressible)value).Expression;

            var eq = new ExpressionEqualityComparer();

            Assert.IsTrue(
                eq.Equals(
                    Expression.Invoke(
                        expr,
                        Expression.Constant(42)
                        ),
                    quote
                    )
                );
        }
Esempio n. 8
0
        public void BlockFlattening3()
        {
            var eq = new ExpressionEqualityComparer();

            var x = Expression.Parameter(typeof(int));
            var y = Expression.Parameter(typeof(int));
            var z = Expression.Parameter(typeof(int));

            var e =
                Expression.Block(new[] { x },
                                 Expression.Block(new[] { y },
                                                  Expression.Block(new[] { z },
                                                                   Expression.Add(x, Expression.Multiply(y, z))
                                                                   ),
                                                  Expression.Empty()
                                                  )
                                 );

            foreach (var f in new[] { Optimizations.BlockFlattening, Optimizations.All })
            {
                var o = Optimizer.Optimize(e, f);

                Assert.IsTrue(
                    eq.Equals(o,
                              Expression.Block(new[] { x, y },
                                               Expression.Block(new[] { z },
                                                                Expression.Add(x, Expression.Multiply(y, z))
                                                                ),
                                               Expression.Empty() // NB: Flattening would be valid here, but we don't analyze this case.
                                               )
                              )
                    );
            }
        }
Esempio n. 9
0
        public void BlockFlattening2()
        {
            var eq = new ExpressionEqualityComparer();

            var x = Expression.Parameter(typeof(int));
            var y = Expression.Parameter(typeof(int));
            var z = Expression.Parameter(typeof(int));

            var e =
                Expression.Block(new[] { x },
                                 Expression.Block(new[] { y },
                                                  Expression.Block(new[] { z },
                                                                   Expression.Add(x, Expression.Multiply(y, z))
                                                                   )
                                                  )
                                 );

            foreach (var f in new[] { Optimizations.BlockFlattening, Optimizations.All })
            {
                var o = Optimizer.Optimize(e, f);

                Assert.IsTrue(
                    eq.Equals(o,
                              Expression.Block(new[] { x, y, z },
                                               Expression.Add(x, Expression.Multiply(y, z))
                                               )
                              )
                    );
            }
        }
Esempio n. 10
0
        public void ExpressionVisitorGeneric_Simple13()
        {
            var v = new MyVisitor();

            var add = Microsoft.CSharp.RuntimeBinder.Binder.BinaryOperation(
                Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags.None,
                ExpressionType.Add,
                typeof(ExpressionEqualityComparerTests),
                new[]
            {
                Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create(Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags.None, name: null),
                Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create(Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags.None, name: null)
            }
                );

            var o = Expression.Dynamic(
                add,
                typeof(object),
                Expression.Constant(1),
                Expression.Constant(2)
                );

            var r = v.Visit(o);

            var n = Expression.Dynamic(
                add,
                typeof(object),
                Expression.Constant(2),
                Expression.Constant(4)
                );

            var e = new ExpressionEqualityComparer();

            Assert.IsTrue(e.Equals(r, n));
        }
        public void TestObjectFilters()
        {
            QueryInjector.RegisterGlobal(
                ib => ib.WhenEncountering <IQueryable <Student> >().ReplaceWith(students => students.Where(student => !student.Deleted))
                );

            var collection = new[]
            {
                new Student {
                    Deleted = false
                },
                new Student {
                    Deleted = true
                },
                new Student {
                    Deleted = false
                },
                new Student {
                    Deleted = true
                },
                new Student {
                    Deleted = false
                },
            }.AsQueryable();

            var actualQuery = collection.AsInjectableQueryable() as IInjectableQueryable;
            var expected    = collection.Where(student => !student.Deleted);

            Assert.NotNull(actualQuery);
            ExpressionEqualityComparer.AssertExpressionsEqual(expected.Expression, actualQuery.GetInjectedExpression());
        }
Esempio n. 12
0
        public void ExpressionSlimExtensions_ToExpressionSlim_RoundtripMore()
        {
            var exprs = new Expression[]
            {
                Expression.Constant(value: null, typeof(object)),
                Expression.Constant(1),
                Expression.Constant("foo"),

                Expression.Add(Expression.Constant(1), Expression.Constant(2)),
                Expression.Add(Expression.Constant(DateTime.Now), Expression.Constant(TimeSpan.Zero)),

                (Expression <Func <int, int> >)(x => x),

#pragma warning disable IDE0004 // Remove Unnecessary Cast. (Only unnecessary on C# 10 or later.)
                (Expression <Func <DateTime> >)(() => DateTime.Now),
                (Expression <Func <int> >)(() => "Bart".Length),

                //(Expression<Func<TimeSpan>>)(() => new TimeSpan()), // REVIEW
                (Expression <Func <TimeSpan> >)(() => new TimeSpan(1, 2, 3)),
#pragma warning restore IDE0004 // Remove Unnecessary Cast
            };

            var eq = new ExpressionEqualityComparer();

            foreach (var ex in exprs)
            {
                var r1 = Roundtrip(ex);
                Assert.IsTrue(eq.Equals(ex, r1), ex.ToString());

                var r2 = RoundtripFactories(ex);
                Assert.IsTrue(eq.Equals(ex, r2), ex.ToString());
            }
        }
Esempio n. 13
0
        public void Quoter_Expressible2()
        {
            var quoter = new Quoter(DefaultExpressionPolicy.Instance);

            var expr = (Expression <Func <Quotable> >)(() => new Quotable()
            {
                X = 1
            });

            var res = quoter.Visit(expr);

            var obj   = (Func <Quotable>)res.Evaluate();
            var value = obj();

            var quote = value.Expression;

            var eq = new ExpressionEqualityComparer();

            Assert.IsTrue(
                eq.Equals(
                    expr.Body,
                    quote
                    )
                );
        }
 public ReplaceConstsTests()
 {
     _expressionEqualityComparer = new ExpressionEqualityComparer();
     _replaceMap = new Dictionary <string, object> {
         { "x", 2 }, { "y", "string" }
     };
 }
Esempio n. 15
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));
            }
        }
        public void Issue_27_EqualityComparer_Ignored_Lambda_Body_Evaluation()
        {
            var target = new ExpressionEqualityComparer(UnknownExpression.EqualityComparer);
            var x      = Expression.Lambda(StubExpression.Unknown(3));
            var y      = Expression.Lambda(StubExpression.Unknown(3));

            AssertExpressions.Equal(x, y, target);
        }
        private static void AssertRewrite(Expression before, Expression after)
        {
            var rewriter  = new AsyncToSyncRewriter(new Dictionary <Type, Type>());
            var comparer  = new ExpressionEqualityComparer(() => new Comparator());
            var rewritten = rewriter.Rewrite(before);

            Assert.IsTrue(comparer.Equals(rewritten, after), string.Format(CultureInfo.InvariantCulture, "Expected: {0}, Actual: {1}", after, rewritten));
        }
        public void ShouldBeEqual_ExpressionEqualityComparer_Composition_UnknownExpressionNode()
        {
            var target = new ExpressionEqualityComparer(UnknownExpression.EqualityComparer);
            var x      = Expression.Property(StubExpression.Unknown(3), "Id");
            var y      = Expression.Property(StubExpression.Unknown(3), "Id");

            AssertAreEqual(x, y, target);
        }
 public void Setup()
 {
     _target      = new ExpressionEqualityComparer();
     _nameGetters = new List <Expression <Func <Person, string> > >()
     {
         person => person.Name,
         person => person.Name
     };
 }
Esempio n. 20
0
        public void ExpressionTupletizer_PackAndUnpack_Lambda_NoVoid()
        {
#if USE_SLIM
            var packs = new Func <LambdaExpression, LambdaExpression>[]
            {
                f => (LambdaExpression)ExpressionSlimTupletizer.Pack((LambdaExpressionSlim)f.ToExpressionSlim()).ToExpression(),
                f => { var s = (LambdaExpressionSlim)f.ToExpressionSlim(); return((LambdaExpression)ExpressionSlimTupletizer.Pack(s.Body, s.Parameters).ToExpression()); },
            };
#else
            var packs = new Func <LambdaExpression, LambdaExpression>[]
            {
                f => ExpressionTupletizer.Pack(f),
                f => ExpressionTupletizer.Pack(f.Body, f.Parameters),
            };
#endif

            foreach (var f in new LambdaExpression[] {
#pragma warning disable IDE0004 // Remove Unnecessary Cast. (Only unnecessary on C# 10 or later.)
                (Expression <Func <int> >)(() => 42),
#pragma warning restore IDE0004 // Remove Unnecessary Cast
                (Expression <Func <string, int> >)(s => s.Length),
                (Expression <Func <string, int, int> >)((s, i) => s.Length + i),
                (Expression <Func <int, int, int, int> >)((a, b, c) => a * b + c),
                (Expression <Func <int, int, int, int, int> >)((a, b, c, d) => a * b + c - d),
                (Expression <Func <int, int, int, int, int, int> >)((a, b, c, d, e) => a * b + c - d / e),
                (Expression <Func <int, int, int, int, int, int, int> >)((a, b, c, d, e, f) => a * b + c - d / e + f),
                (Expression <Func <int, int, int, int, int, int, int, int> >)((a, b, c, d, e, f, g) => a * b + c - d / e + f * g),
                (Expression <Func <int, int, int, int, int, int, int, int, int> >)((a, b, c, d, e, f, g, h) => a * b + c - d / e + f * g / h),
                (Expression <Func <int, int, int, int, int, int, int, int, int, int> >)((a, b, c, d, e, f, g, h, i) => a * b + c - d / e + f * g / h + i),
                (Expression <Func <int, int, int, int, int, int, int, int, int, int, int> >)((a, b, c, d, e, f, g, h, i, j) => a * b + c - d / e + f * g / h + i - j),
                (Expression <Func <int, int, int, int, int, int, int, int, int, int, int, int> >)((a, b, c, d, e, f, g, h, i, j, k) => a * b + c - d / e + f * g / h + i - j * k),
                (Expression <Func <int, int, int, int, int, int, int, int, int, int, int, int, int> >)((a, b, c, d, e, f, g, h, i, j, k, l) => a * b + c - d / e + f * g / h + i - j * k / l),
                (Expression <Func <int, int, int, int, int, int, int, int, int, int, int, int, int, int> >)((a, b, c, d, e, f, g, h, i, j, k, l, m) => a * b + c - d / e + f * g / h + i - j * k / l + m),
                (Expression <Func <int, int, int, int, int, int, int, int, int, int, int, int, int, int, int> >)((a, b, c, d, e, f, g, h, i, j, k, l, m, n) => a * b + c - d / e + f * g / h + i - j * k / l + m % n),
                (Expression <Func <int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int> >)((a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) => a * b + c - d / e + f * g / h + i - j * k / l + m % n + o),
                (Expression <Func <string, Uri, int, double, DateTime, float, byte, TimeSpan, long, short, Guid, char, uint, AppDomain, decimal[], List <int>, bool> >)((a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) => (a + b.ToString() + new string(l, 10) + n.FriendlyName).Length + i * d - e.Year % j + f * g / h.Days + k.ToByteArray().Length + m * p[c] > 0 && o[c] < 12.45m),
            })
            {
                foreach (var pack in packs)
                {
                    var g = pack(f);

                    var n = g.Parameters.Count;
                    Assert.IsTrue(n is 0 or 1, "Parameter count: " + f.ToString());

                    if (n == 1)
                    {
                        Assert.IsTrue(g.Parameters[0].Type.FullName.StartsWith("System.Tuple`"), "Parameter type: " + f.ToString());
                    }

                    var h = ExpressionTupletizer.Unpack(g);

                    var res = new ExpressionEqualityComparer().Equals(f, h);
                    Assert.IsTrue(res, "Equality: " + f.ToString());
                }
            }
        }
Esempio n. 21
0
        public void ExpressionVisitorGeneric_Simple5()
        {
            var v = new MyVisitor();

            var r = v.Visit(Expression.TypeIs(Expression.Constant(2), typeof(int)));

            var e = new ExpressionEqualityComparer();

            Assert.IsTrue(e.Equals(r, Expression.TypeIs(Expression.Constant(4), typeof(string))));
        }
Esempio n. 22
0
        // TODO: checked arithmetic

        private static void Test(PartialExpressionEvaluatorBase eval, Dictionary <Expression, Expression> tests)
        {
            var eq = new ExpressionEqualityComparer();

            foreach (var test in tests)
            {
                var r = eval.Reduce(test.Key);
                Assert.IsTrue(eq.Equals(test.Value, r), test.Value.ToString() + " != " + r.ToString());
            }
        }
Esempio n. 23
0
        public void ExpressionVisitorGeneric_Simple6()
        {
            var v = new MyVisitor();

            var r = v.Visit(Expression.Condition(Expression.Constant(true), Expression.Constant(2), Expression.Constant(3)));

            var e = new ExpressionEqualityComparer();

            Assert.IsTrue(e.Equals(r, Expression.Condition(Expression.Constant(false), Expression.Constant(6), Expression.Constant(4))));
        }
Esempio n. 24
0
        public void ExpressionVisitorGeneric_Simple9()
        {
            var v = new MyVisitor();

            var r = v.Visit(Expression.NewArrayInit(typeof(int), Expression.Constant(2), Expression.Constant(3)));

            var e = new ExpressionEqualityComparer();

            Assert.IsTrue(e.Equals(r, Expression.NewArrayInit(typeof(int), Expression.Constant(6), Expression.Constant(4))));
        }
Esempio n. 25
0
        public void ExpressionVisitorGeneric_Simple1()
        {
            var v = new MyVisitor();

            var r = v.Visit(Expression.Add(Expression.Constant(2), Expression.Constant(3)));

            var e = new ExpressionEqualityComparer();

            Assert.IsTrue(e.Equals(r, Expression.Subtract(Expression.Constant(4), Expression.Constant(6))));
        }
Esempio n. 26
0
        public void TestInitialize()
        {
            ExpressionEqualityComparer = new ExpressionEqualityComparer();

            var methods = typeof(SqlFunctions).GetMethods().Where(x => x.Name == "StringConvert").ToArray();

            MethodProvider.UserFunctions.Clear();

            MethodProvider.RegisterFunction("StringConvert", methods);
        }
Esempio n. 27
0
        public void SyntaxTrie_Unchanged5()
        {
            Expression <Action> f = () => Foo(x => x, x => x, x => x, x => x);
            var g = AlphaRenamer.EliminateNameConflicts(f);

            var eq = new ExpressionEqualityComparer();

            Assert.IsTrue(eq.Equals(f, g));
            Assert.AreSame(f, g);
        }
Esempio n. 28
0
        public void SyntaxTrie_Unchanged4()
        {
            Expression <Func <int, Func <int, int> > > f = x => y => y;
            var g = AlphaRenamer.EliminateNameConflicts(f.Body);

            var eq = new ExpressionEqualityComparer();

            Assert.IsTrue(eq.Equals(f.Body, g));
            Assert.AreSame(f.Body, g);
        }
Esempio n. 29
0
        public void ExpressionVisitorGeneric_Simple2()
        {
            var v = new MyVisitor();

            var r = v.Visit(Expression.UnaryPlus(Expression.Constant(2)));

            var e = new ExpressionEqualityComparer();

            Assert.IsTrue(e.Equals(r, Expression.Negate(Expression.Constant(4))));
        }
Esempio n. 30
0
        public void ExpressionVisitorGeneric_Simple3()
        {
            var v = new MyVisitor();

            var r = v.Visit(Expression.Default(typeof(int)));

            var e = new ExpressionEqualityComparer();

            Assert.IsTrue(e.Equals(r, Expression.Default(typeof(string))));
        }
		static void Main(String[] args)
		{
			using (OrdersContext ctx = new OrdersContext())
			{
				ExpressionEqualityComparer comparer = new ExpressionEqualityComparer();
				var e1 = ctx.Customers.Where(x => x.Orders.Any()).OrderBy(x => x.Name);
				var e2 = ctx.Customers.Where(y => y.Orders.Any()).OrderBy(y => y.Name);
				var e = comparer.Equals(e1.Expression, e2.Expression);

				//miss
				var c1 = ctx.Customers.Where(x => x.Orders.Any()).OrderBy(x => x.Name).AsCacheable(TimeSpan.FromSeconds(10)).ToList();

				//hit
				var c2 = ctx.Customers.Where(o => o.Orders.Any()).OrderBy(x => x.Name).AsCacheable(TimeSpan.FromSeconds(10)).ToList();

				//hit
				var c3 = (from c in ctx.Customers where c.Orders.Any() orderby c.Name select c).AsCacheable(TimeSpan.FromSeconds(10)).ToList();

				Thread.Sleep(10000);

				//miss
				var c4 = ctx.Customers.Where(x => x.Orders.Any()).OrderBy(x => x.Name).AsCacheable(TimeSpan.FromSeconds(10)).ToList();
			}
		}
 public void Setup()
 {
     _target = new ExpressionEqualityComparer();
     _nameGetters = new List<Expression<Func<Person, string>>>()
     {
         person => person.Name,
         person => person.Name
     };
 }