public void StructForEachContinue()
        {
            var enumerable_counter = new StructEnumerableCounter(0, 10);

            var ec = Expression.Parameter(typeof(StructEnumerableCounter), "ec");

            var item            = Expression.Variable(typeof(int), "i");
            var foreachBreak    = Expression.Label("foreachBreak");
            var foreachContinue = Expression.Label("foreachContinue");

            var hitcounter = Expression.Lambda <Action <StructEnumerableCounter> >(
                ExpressionEx.ForEach(
                    item,
                    ec,
                    Expression.Block(
                        Expression.Condition(
                            Expression.Equal(Expression.Modulo(item, Expression.Constant(2)), Expression.Constant(0)),
                            Expression.Call(ec, typeof(StructEnumerableCounter).GetMethod("Hit", Type.EmptyTypes)),
                            Expression.Goto(foreachContinue))),
                    foreachBreak,
                    foreachContinue),
                ec).Compile();

            hitcounter(enumerable_counter);

            Assert.Equal(5, enumerable_counter.Count);
            Assert.True(enumerable_counter.Disposed);
        }
        public void StructForEachException()
        {
            var enumerable_counter = new StructEnumerableCounter(0, 100);

            var ec = Expression.Parameter(typeof(StructEnumerableCounter), "ec");

            var item = Expression.Variable(typeof(int), "i");

            var hitcounter = Expression.Lambda <Action <StructEnumerableCounter> >(
                ExpressionEx.ForEach(
                    item,
                    ec,
                    Expression.Block(
                        Expression.Condition(
                            Expression.LessThanOrEqual(item, Expression.Constant(10)),
                            Expression.Call(ec, typeof(StructEnumerableCounter).GetMethod("Hit", Type.EmptyTypes)),
                            Expression.Throw(Expression.New(typeof(TestException)))))),
                ec).Compile();

            Assert.Throws <TestException>(() =>
            {
                hitcounter(enumerable_counter);
            });

            Assert.Equal(10, enumerable_counter.Count);
            Assert.True(enumerable_counter.Disposed);
        }
        public void DuckTypedForEachBreak()
        {
            var enumerable_counter = new DuckTypedEnumerableCounter(0, 100);

            var ec = Expression.Parameter(typeof(DuckTypedEnumerableCounter), "ec");

            var item         = Expression.Variable(typeof(int), "i");
            var foreachBreak = Expression.Label("foreachBreak");

            var hitcounter = Expression.Lambda <Action <DuckTypedEnumerableCounter> >(
                ExpressionEx.ForEach(
                    item,
                    ec,
                    Expression.Block(
                        Expression.Condition(
                            Expression.LessThanOrEqual(item, Expression.Constant(10)),
                            Expression.Call(ec, typeof(DuckTypedEnumerableCounter).GetMethod("Hit", Type.EmptyTypes)),
                            Expression.Goto(foreachBreak))),
                    foreachBreak),
                ec).Compile();

            hitcounter(enumerable_counter);

            Assert.Equal(10, enumerable_counter.Count);
            Assert.True(enumerable_counter.Disposed);
        }
Example #4
0
        // Argument type: Expression<IEnumerable<RuleExprAst<T, RuleExprContext>>>
        // Return type: Expression<RuleExpr<ImmutableList<T>, RuleExprContext>>   -- note: RuleExpr not RuleExprAst
        private static Expression Sequence <T, RuleExprContext>(Expression fsVar)
        {
            var context = Expression.Parameter(typeof(RuleExprContext), "context");

            var valueOptionAndContextVar = Expression.Variable(typeof((Option <T>, RuleExprContext)), "valueOptionAndContextAVar");
            var valueOptionVar           = Expression.Variable(typeof(Option <T>), "valueOptionAVar");
            var contextVar = Expression.Variable(typeof(RuleExprContext), "contextAVar");
            var values     = Expression.Variable(typeof(ImmutableList <T>));
            var abortedVar = Expression.Variable(typeof(bool));
            var fVar       = Expression.Parameter(typeof(RuleExprAst <T, RuleExprContext>), "f(loopVar)");
            var breakLabel = Expression.Label("LoopBreak");
            var loopBody   = Expression.Block(
                Expression.Assign(valueOptionAndContextVar, Expression.Invoke(Expression.Property(fVar, "Expression"), contextVar)),
                Expression.Assign(valueOptionVar, Expression.Field(valueOptionAndContextVar, "Item1")),
                Expression.Assign(contextVar, Expression.Field(valueOptionAndContextVar, "Item2")),
                Expression.IfThenElse(
                    Expression.Equal(Expression.Field(valueOptionVar, "isSome"), Expression.Constant(true)),
                    Expression.Assign(values, Expression.Call(values, typeof(ImmutableList <>).MakeGenericType(typeof(T)).GetMethod("Add"), Expression.Field(valueOptionVar, "value"))),
                    Expression.Block(
                        Expression.Assign(abortedVar, Expression.Constant(true)),
                        Expression.Break(breakLabel)
                        )
                    )
                );
            var loop = ExpressionEx.ForEach(fsVar, fVar, loopBody, breakLabel);

            var functionBody =
                Expression.Block(
                    new[] { valueOptionAndContextVar, valueOptionVar, contextVar, values, abortedVar },
                    Expression.Assign(contextVar, context),
                    Expression.Assign(values, Expression.Constant(ImmutableList <T> .Empty)),
                    Expression.Assign(abortedVar, Expression.Constant(false)),
                    loop,
                    Expression.Condition(
                        Expression.Equal(abortedVar, Expression.Constant(false)),
                        MkTuple <Option <ImmutableList <T> >, RuleExprContext>(WrapSome <ImmutableList <T> >(values), contextVar),
                        MkTuple <Option <ImmutableList <T> >, RuleExprContext>(GetNoneValue <ImmutableList <T> >(), contextVar)
                        )
                    );

            return(Expression.Lambda <RuleExpr <ImmutableList <T>, RuleExprContext> >(functionBody, context));

            // context =>
            //   var as = []
            //   var aborted = false;
            //   foreach(var f in fs)
            //   {
            //      (a, context') = f(contex);
            //      context = context';
            //      if (!a) { aborted = true; break; }
            //      as.add(a);
            //   }
            //   return aborted ? (None, context) : (Just as, context)
        }
        public void ForEachNonGeneric()
        {
            var enumerable_counter = new NonGenericEnumerableCounter(0, 10);

            var ec = Expression.Parameter(typeof(NonGenericEnumerableCounter), "ec");

            var item = Expression.Variable(typeof(int), "i");

            var hitcounter = Expression.Lambda <Action <NonGenericEnumerableCounter> >(
                ExpressionEx.ForEach(
                    item,
                    ec,
                    Expression.Call(ec, typeof(NonGenericEnumerableCounter).GetMethod("Hit", Type.EmptyTypes))),
                ec).Compile();

            hitcounter(enumerable_counter);

            Assert.Equal(10, enumerable_counter.Count);
        }
        public void ForEachEnumerable()
        {
            var enumerable_counter = new EnumerableCounter(0, 10);

            var ec = Expression.Parameter(typeof(EnumerableCounter), "ec");

            var item = Expression.Variable(typeof(int), "i");

            var hitcounter = Expression.Lambda <Action <EnumerableCounter> >(
                ExpressionEx.ForEach(
                    item,
                    ec,
                    Expression.Call(ec, typeof(EnumerableCounter).GetMethod("Hit", Type.EmptyTypes))),
                ec).Compile();

            hitcounter(enumerable_counter);

            Assert.Equal(10, enumerable_counter.Count);
            Assert.True(enumerable_counter.Disposed);
            Assert.False(enumerable_counter.DisposedIncorrectly);
        }
        public void ForEachArray()
        {
            var counters = Enumerable.Range(0, 3).Select(_ => new DisposableCounter()).ToArray();

            var cs = Expression.Parameter(typeof(DisposableCounter[]), "cs");

            var c = Expression.Variable(typeof(DisposableCounter), "i");

            var hitcounter = Expression.Lambda <Action <DisposableCounter[]> >(
                ExpressionEx.ForEach(
                    c,
                    cs,
                    Expression.Call(c, typeof(DisposableCounter).GetMethod("Hit", Type.EmptyTypes))),
                cs).Compile();

            hitcounter(counters);

            foreach (var counter in counters)
            {
                Assert.Equal(1, counter.Count);
            }
        }
        public void ForEachNonGenericStructEnumerator()
        {
            var counters           = new[] { new DisposableCounter(), new DisposableCounter(), new DisposableCounter() };
            var enumerable_counter = new NonGenericStructEnumerableCounter(counters);

            var ec   = Expression.Parameter(typeof(NonGenericStructEnumerableCounter), "ec");
            var item = Expression.Variable(typeof(DisposableCounter), "c");

            var hitcounter = Expression.Lambda <Action <NonGenericStructEnumerableCounter> >(
                ExpressionEx.ForEach(
                    item,
                    ec,
                    Expression.Call(item, "Hit", Type.EmptyTypes)),
                ec).Compile();

            hitcounter(enumerable_counter);

            foreach (var counter in counters)
            {
                Assert.Equal(1, counter.Count);
                Assert.False(counter.Disposed);
            }
        }
        public void ForEach()
        {
            var args = Expression.Parameter(typeof(string[]), "args");

            var s = Expression.Variable(typeof(string), "s");

            var lambda = Expression.Lambda <Action <string[]> >(
                ExpressionEx.ForEach(
                    s,
                    args,
                    Expression.Call(typeof(Console).GetMethod("WriteLine", new[] { typeof(string) }), s)),
                args);

            AssertExpression(@"
void (string[] args)
{
	foreach (string s in args)
	{
		Console.WriteLine(s);
	}
}
", lambda);
        }
Example #10
0
        protected override Expression CreateBlockExpression(Expression source, Expression destination, CompileArgument arg)
        {
            var mapped = base.CreateBlockExpression(source, destination, arg);

            //if source is not dict type, use ClassAdapter
            var srcDictType = arg.SourceType.GetDictionaryType();

            if (srcDictType == null || arg.Settings.IgnoreNonMapped == true)
            {
                return(mapped);
            }

            var keyType   = srcDictType.GetGenericArguments().First();
            var kvpType   = source.Type.ExtractCollectionType();
            var kvp       = Expression.Variable(kvpType, "kvp");
            var key       = Expression.Variable(keyType, "key");
            var keyAssign = Expression.Assign(key, Expression.Property(kvp, "Key"));

            //dest[kvp.Key] = convert(kvp.Value);
            var set = CreateSetFromKvp(kvp, key, destination, arg);

            if (arg.Settings.NameMatchingStrategy.SourceMemberNameConverter != NameMatchingStrategy.Identity)
            {
                set = Expression.Block(
                    Expression.Assign(
                        key,
                        Expression.Call(
                            Expression.Constant(arg.Settings.NameMatchingStrategy.SourceMemberNameConverter),
                            "Invoke",
                            null,
                            key)),
                    set);
            }

            //ignore mapped
            var ignores = arg.Settings.Resolvers
                          .Select(r => r.SourceMemberName)
                          .Where(name => name != null)
                          .ToHashSet();

            //ignoreIf
            var dict = new Dictionary <string, Expression>();

            foreach (var ignoreIf in arg.Settings.IgnoreIfs)
            {
                if (ignoreIf.Value == null)
                {
                    ignores.Add(ignoreIf.Key);
                }
                else
                {
                    var setWithCondition = Expression.IfThen(
                        Expression.Not(ignoreIf.Value.Apply(source, destination)),
                        set);
                    dict.Add(ignoreIf.Key, setWithCondition);
                }
            }

            //dict to switch
            if (dict.Count > 0 || ignores.Count > 0)
            {
                var cases = dict
                            .Select(k => Expression.SwitchCase(k.Value, Expression.Constant(k.Key)))
                            .ToList();
                if (ignores.Count > 0)
                {
                    cases.Add(Expression.SwitchCase(Expression.Empty(), ignores.Select(Expression.Constant)));
                }

                set = Expression.Switch(typeof(void), key, set, null, cases);
            }

            //if (kvp.Value != null)
            //  dest[kvp.Key] = convert(kvp.Value);
            var kvpValueType = kvpType.GetGenericArguments()[1];

            if (arg.Settings.IgnoreNullValues == true && kvpValueType.CanBeNull())
            {
                set = Expression.IfThen(
                    Expression.NotEqual(
                        Expression.Property(kvp, "Value"),
                        Expression.Constant(null, kvpValueType)),
                    set);
            }

            //foreach (var kvp in source) {
            //  dest[kvp.Key] = convert(kvp.Value);
            //}
            set = Expression.Block(new[] { key }, keyAssign, set);
            var loop = ExpressionEx.ForEach(source, kvp, set);

            return(mapped.NodeType == ExpressionType.Default
                ? loop
                : Expression.Block(mapped, loop));
        }
Example #11
0
        protected override Expression CreateBlockExpression(Expression source, Expression destination, CompileArgument arg)
        {
            var dictArgs      = destination.Type.GetDictionaryType() !.GetGenericArguments();
            var shouldConvert = destination.Type.GetMethod("Add", dictArgs) == null;

            //var dict = (IDictionary<,>)dest;
            var actions = new List <Expression>();
            var dict    = destination;

            if (shouldConvert)
            {
                var dictType = typeof(IDictionary <,>).MakeGenericType(dictArgs);
                dict = Expression.Variable(dictType, "dict");
                actions.Add(ExpressionEx.Assign(dict, destination)); //convert to dict type
            }

            var mapped = base.CreateBlockExpression(source, dict, arg);

            if (mapped.NodeType != ExpressionType.Default)
            {
                actions.Add(mapped);
            }

            //if source is not dict type, use ClassAdapter only
            var srcDictType = arg.SourceType.GetDictionaryType();

            if (srcDictType == null || arg.Settings.IgnoreNonMapped == true)
            {
                return(shouldConvert && mapped.NodeType != ExpressionType.Default
                    ? Expression.Block(new[] { (ParameterExpression)dict }, actions)
                    : mapped);
            }

            var keyType   = srcDictType.GetGenericArguments().First();
            var kvpType   = source.Type.ExtractCollectionType();
            var kvp       = Expression.Variable(kvpType, "kvp");
            var key       = Expression.Variable(keyType, "key");
            var keyAssign = Expression.Assign(key, Expression.Property(kvp, "Key"));

            //dest[kvp.Key] = convert(kvp.Value);
            var set = CreateSetFromKvp(kvp, key, dict, arg);

            if (arg.Settings.NameMatchingStrategy.SourceMemberNameConverter != NameMatchingStrategy.Identity)
            {
                set = Expression.Block(
                    Expression.Assign(
                        key,
                        Expression.Call(
                            MapsterHelper.GetConverterExpression(arg.Settings.NameMatchingStrategy.SourceMemberNameConverter),
                            "Invoke",
                            null,
                            key)),
                    set);
            }

            //ignore mapped
            var ignores = arg.Settings.Resolvers
                          .Select(r => r.SourceMemberName)
                          .Where(name => name != null)
                          .ToHashSet();

            //ignore
            var ignoreIfs = new Dictionary <string, Expression>();

            foreach (var ignore in arg.Settings.Ignore)
            {
                if (ignore.Value.Condition == null)
                {
                    ignores.Add(ignore.Key);
                }
                else
                {
                    var body = ignore.Value.IsChildPath
                        ? ignore.Value.Condition.Body
                        : ignore.Value.Condition.Apply(arg.MapType, source, dict);
                    var setWithCondition = Expression.IfThen(
                        ExpressionEx.Not(body),
                        set);
                    ignoreIfs.Add(ignore.Key, setWithCondition);
                }
            }

            //dict to switch
            if (ignoreIfs.Count > 0 || ignores.Count > 0)
            {
                var cases = ignoreIfs
                            .Select(k => Expression.SwitchCase(k.Value, Expression.Constant(k.Key)))
                            .ToList();
                if (ignores.Count > 0)
                {
                    cases.Add(Expression.SwitchCase(Expression.Empty(), ignores.Select(Expression.Constant)));
                }

                set = Expression.Switch(typeof(void), key, set, null, cases);
            }

            //if (kvp.Value != null)
            //  dest[kvp.Key] = convert(kvp.Value);
            var kvpValueType = kvpType.GetGenericArguments()[1];

            if (arg.Settings.IgnoreNullValues == true && kvpValueType.CanBeNull())
            {
                set = Expression.IfThen(
                    Expression.NotEqual(
                        Expression.Property(kvp, "Value"),
                        Expression.Constant(null, kvpValueType)),
                    set);
            }

            //foreach (var kvp in source) {
            //  dest[kvp.Key] = convert(kvp.Value);
            //}
            set = Expression.Block(new[] { key }, keyAssign, set);
            var loop = ExpressionEx.ForEach(source, kvp, set);

            actions.Add(loop);
            return(shouldConvert
                ? Expression.Block(new[] { (ParameterExpression)dict }, actions)
                : Expression.Block(actions));
        }