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); }
// 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); }
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)); }
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)); }