IfThenElse() public static method

Creates a ConditionalExpression.
public static IfThenElse ( Expression test, Expression ifTrue, Expression ifFalse ) : ConditionalExpression
test Expression An to set the property equal to.
ifTrue Expression An to set the property equal to.
ifFalse Expression An to set the property equal to.
return ConditionalExpression
Ejemplo n.º 1
0
        public void IfThenElse()
        {
            var param    = LinqExpression.Parameter(typeof(bool));
            var expected = LinqExpression.IfThenElse(param, param, param);

            using var g = new GraphEngine.Graph();
            g.LoadFromString(@"
@prefix : <http://example.com/> .

:s
    a :IfThenElse ;
    :conditionTest _:param ;
    :conditionIfTrue _:param ;
    :conditionIfFalse _:param ;
.

_:param
    :parameterType [
        :typeName ""System.Boolean"" ;
    ] ;
.
");
            var s = g.GetUriNode(":s");

            var actual = Expression.Parse(s).LinqExpression;

            Console.WriteLine(actual.GetDebugView());

            actual.Should().Be(expected);
        }
Ejemplo n.º 2
0
        private LambdaExpression toDictLambda(Type from, Type to)
        {
            var valueType = recordCreator.GetValueType(to);
            var recType   = typeof(IRecord <>).MakeGenericType(valueType);
            var set       = recType.GetTypeInfo().GetDeclaredMethod(nameof(IRecord <object> .SetValue));

            var input      = Ex.Parameter(from, "input");
            var tmp        = Ex.Parameter(typeof(ConversionResult <>).MakeGenericType(valueType), "tmp");
            var res        = Ex.Parameter(typeof(IDictionary <,>).MakeGenericType(typeof(string), valueType), "res");
            var rec        = Ex.Parameter(recType, "rec");
            var getters    = GetReadablePropertiesForType(from);
            var converters = getters.Select(g => Ref.GetLambda(g.PropertyType, valueType));

            var end   = Ex.Label(typeof(ConversionResult <>).MakeGenericType(to));
            var block = Ex.Block(new[] { tmp, res, rec },
                                 Ex.Assign(res, Ex.New(GetParameterlessConstructor(to))),
                                 Ex.Assign(rec, recordCreator.Creator(to).ApplyTo(res)),
                                 Ex.IfThen(Ex.MakeBinary(ExpressionType.Equal, rec, Ex.Default(rec.Type)), Ex.Goto(end, NoResult(to))),
                                 Ex.Block(getters.Zip(converters, (g, c) => new { g, c })
                                          .Select(x =>
                                                  Ex.Block(
                                                      Ex.Assign(tmp, x.c.ApplyTo(Ex.Property(input, x.g))),
                                                      Ex.IfThenElse(Ex.Property(tmp, nameof(IConversionResult.IsSuccessful)),
                                                                    Ex.Call(rec, set, Ex.Constant(x.g.Name), Ex.Property(tmp, nameof(IConversionResult.Result))),
                                                                    Ex.Goto(end, NoResult(to)))))),
                                 Ex.Label(end, Result(to, Ex.Convert(res, to))));

            return(Ex.Lambda(block, input));
        }
Ejemplo n.º 3
0
        public Expr CompileIfStatement(ParseTreeNode parseNode)
        {
            //[0] - Condition
            //[1] - True Block
            //[2] - {ElseIf Statements}
            //[3] - [Else Block]

            bool hasElseIfs = parseNode.ChildNodes[2].ChildNodes.Any();
            bool hasElse    = parseNode.ChildNodes[3].ChildNodes.Any();

            Expr ifStatement = Expr.Empty();

            //Add else component
            if (hasElse)
            {
                ifStatement = CompileBlock(parseNode.ChildNodes[3]);
            }

            foreach (var elseIf in Enumerable.Reverse(parseNode.ChildNodes[2].ChildNodes))
            {
                ifStatement = Expr.IfThenElse(
                    TypeHelpers.ToBoolean(CompileExpression(elseIf.ChildNodes[0])),
                    CompileBlock(elseIf.ChildNodes[1]),
                    ifStatement);
            }

            ifStatement = Expr.IfThenElse(
                TypeHelpers.ToBoolean(CompileExpression(parseNode.ChildNodes[0])),
                CompileBlock(parseNode.ChildNodes[1]),
                ifStatement
                );

            return(ifStatement);
        }
Ejemplo n.º 4
0
        private static Func <int[], int[]> GenerateCopyExpression()
        {
            var ctor = typeof(int[]).GetConstructor(new[] { typeof(int) });
            var get  = typeof(int[]).GetMethod("Get", new[] { typeof(int) });
            var set  = typeof(int[]).GetMethod("Set", new[] { typeof(int), typeof(int) });

            var p1     = Exp.Parameter(typeof(int[]));
            var v1     = Exp.Variable(typeof(int[]));
            var v2     = Exp.Variable(typeof(int));
            var @break = Exp.Label();

            var block = Exp.Block(
                new[] { v1, v2 },
                Exp.Assign(v1, Exp.New(ctor, Exp.Property(p1, "Length"))),
                Exp.Assign(v2, Exp.Constant(0)),
                Exp.Loop(
                    Exp.IfThenElse(
                        Exp.LessThan(v2, Exp.Property(p1, "Length")),
                        Exp.Block(
                            Exp.Call(v1, set, v2, Exp.Call(p1, get, v2)),
                            Exp.AddAssign(v2, Exp.Constant(1))
                            ),
                        Exp.Break(@break)
                        ),
                    @break),
                v1
                );

            return(Exp.Lambda <Func <int[], int[]> >(block, new ParameterExpression[] { p1 }).Compile());
        }
Ejemplo n.º 5
0
            public Expr ToExpression()
            {
                var exitLabel = Expr.Label();
                var loopBody  = Expr.Block(Body.ToExpression(), Expr.PreIncrementAssign(Iterator.ToExpression()));

                return(Expr.Loop(Expr.IfThenElse(Expr.LessThan(Iterator.ToExpression(), UpperBound.ToExpression()), loopBody, Expr.Break(exitLabel)), exitLabel));
            }
        public void IfThenElse()
        {
            var param      = LinqExpression.Parameter(typeof(bool));
            var expression = LinqExpression.IfThenElse(param, param, param);

            ShouldRoundrip(expression);
        }
Ejemplo n.º 7
0
 private static Ex enumeratorConversion(Type to, Ex enumerator, Type eType, LambdaExpression[] converters, Ex[] res, System.Linq.Expressions.LabelTarget end)
 {
     return(Ex.Block(res.Zip(converters, (r, con) =>
                             Ex.Block(
                                 Ex.IfThenElse(
                                     enumerator.Type.GetTypeInfo().GetDeclaredMethod(nameof(IEnumerator.MoveNext)) == null
                         ? Ex.Call(Ex.Convert(enumerator, typeof(IEnumerator)), nameof(IEnumerator.MoveNext), Type.EmptyTypes)
                         : Ex.Call(enumerator, enumerator.Type.GetTypeInfo().GetDeclaredMethod(nameof(IEnumerator.MoveNext))),
                                     Ex.Assign(r, con.ApplyTo(Ex.Property(enumerator, nameof(IEnumerator.Current)))),
                                     Ex.Goto(end, NoResult(to))),
                                 Ex.IfThen(Ex.Not(Ex.Property(r, nameof(IConversionResult.IsSuccessful))),
                                           Ex.Goto(end, NoResult(to)))))));
 }
Ejemplo n.º 8
0
 public static ExTP LSaveNearestEnemy() => b => {
     var key    = b.Ctx.NameWithSuffix("_LSaveNearestEnemyKey");
     var eid_in = ExUtils.V <int?>();
     var eid    = ExUtils.V <int>();
     var loc    = new TExV2();
     return(Ex.Block(new[] { eid_in, eid, loc },
                     eid_in.Is(Ex.Condition(FiringCtx.Contains <int>(b, key),
                                            FiringCtx.GetValue <int>(b, key).As <int?>(),
                                            Ex.Constant(null).As <int?>())
                               ),
                     Ex.IfThenElse(Enemy.findNearestSave.Of(b.loc, eid_in, eid, loc),
                                   FiringCtx.SetValue <int>(b, key, eid),
                                   loc.Is(Ex.Constant(new Vector2(0f, 50f)))
                                   ),
                     loc
                     ));
 };
Ejemplo n.º 9
0
        private LambdaExpression constructionLambda(Type from, Type to)
        {
            var valueType = recordCreator.GetValueType(from);
            var recType   = typeof(IRecord <>).MakeGenericType(valueType);
            var tryGet    = recType.GetTypeInfo().GetDeclaredMethod(nameof(IRecord <object> .TryGetValue));

            var input = Ex.Parameter(from, "input");
            var rec   = Ex.Parameter(recType, "rec");
            var ctor  = GetConstructorForType(to);
            var tmp   = Ex.Parameter(valueType, "tmp");
            var pars  = ctor.GetParameters().Select((p, i) => new
            {
                Converter = Ref.GetLambda(valueType, p.ParameterType),
                Var       = Ex.Parameter(typeof(ConversionResult <>).MakeGenericType(p.ParameterType), p.Name),
                Type      = p.ParameterType,
                Optional  = p.GetCustomAttributes <OptionalAttribute>().Any(),
                Default   = p.HasDefaultValue ? p.DefaultValue : p.ParameterType.GetTypeInfo().IsValueType ? Activator.CreateInstance(p.ParameterType) : null
            }).ToArray();
            var end   = Ex.Label(typeof(ConversionResult <>).MakeGenericType(to), "end");
            var block = Ex.Block(new[] { rec }.Concat(pars.Select(x => x.Var)),
                                 Ex.Assign(rec, recordCreator.Creator(from).ApplyTo(input)),
                                 Ex.Block(new[] { tmp }, pars
                                          .Select(x =>
                                                  x.Optional
                        ? Ex.Block(
                                                      Ex.IfThenElse(
                                                          Ex.MakeBinary(ExpressionType.OrElse,
                                                                        Ex.Call(rec, tryGet, Ex.Constant(x.Var.Name), tmp),
                                                                        Ex.Call(rec, tryGet, Ex.Constant(ToPascalCase(x.Var.Name)), tmp)),
                                                          Ex.Block(
                                                              Ex.Assign(x.Var, x.Converter.ApplyTo(tmp)),
                                                              Ex.IfThen(Ex.Not(Ex.Property(x.Var, nameof(IConversionResult.IsSuccessful))),
                                                                        Ex.Goto(end, NoResult(to)))),
                                                          Ex.Assign(x.Var, Result(x.Type, Ex.Constant(x.Default, x.Type)))))
                        : Ex.Block(
                                                      Ex.IfThen(Ex.Not(Ex.Call(rec, tryGet, Ex.Constant(x.Var.Name), tmp)),
                                                                Ex.IfThen(Ex.Not(Ex.Call(rec, tryGet, Ex.Constant(ToPascalCase(x.Var.Name)), tmp)),
                                                                          Ex.Goto(end, NoResult(to)))),
                                                      Ex.Assign(x.Var, x.Converter.ApplyTo(tmp)),
                                                      Ex.IfThen(Ex.Not(Ex.Property(x.Var, nameof(IConversionResult.IsSuccessful))),
                                                                Ex.Goto(end, NoResult(to)))))),
                                 Ex.Label(end, Result(to, Ex.New(ctor, pars.Select(p => Ex.Property(p.Var, nameof(IConversionResult.Result)))))));

            return(Ex.Lambda(block, input));
        }
Ejemplo n.º 10
0
        public override Expr ToExpression()
        {
            var loopBody = new List <Expr>();

            if (ReadExpression.Count > 0)
            {
                loopBody.Add(Expr.Assign(AccessExpression, ReadExpression[0]));
            }

            foreach (var child in Children)
            {
                loopBody.Add(child.ToExpression());
            }

            loopBody.Add(Expr.PreIncrementAssign(Iterator));

            var loopExitLabel = Expr.Label();
            var loopCode      = Expr.Loop(Expr.IfThenElse(LoopCondition, Expr.Block(loopBody), Expr.Break(loopExitLabel)), loopExitLabel);

            return(Expr.Block(new[] { Iterator }, IteratorInitializer, loopCode));
        }
Ejemplo n.º 11
0
        /// <summary>for(loopVar = min; i &lt; max; i++) { loopContent }</summary>
        public static E For(this ParameterExpression loopVar, int min, int max, E loopContent)
        {
            var initAssign = E.Assign(loopVar, E.Constant(min, typeof(int)));

            var breakLabel = E.Label("LoopBreak");

            var loop = E.Block(new[] { loopVar },
                               initAssign,
                               E.Loop(
                                   E.IfThenElse(
                                       E.LessThan(loopVar, E.Constant(max, typeof(int))),
                                       E.Block(
                                           loopContent,
                                           E.Assign(loopVar, E.Increment(loopVar))
                                           ),
                                       E.Break(breakLabel)
                                       ),
                                   breakLabel)
                               );

            return(loop);
        }
Ejemplo n.º 12
0
        private LambdaExpression setterLambda(Type from, Type to)
        {
            var valueType = recordCreator.GetValueType(from);
            var recType   = typeof(IRecord <>).MakeGenericType(valueType);
            var tryGet    = recType.GetTypeInfo().GetDeclaredMethod(nameof(IRecord <object> .TryGetValue));

            var input   = Ex.Parameter(from, "input");
            var rec     = Ex.Parameter(recType, "rec");
            var tmp     = Ex.Parameter(valueType, "tmp");
            var ctor    = GetParameterlessConstructor(to);
            var setters = GetWritablePropertiesForType(to);
            var res     = Ex.Parameter(to, "res");
            var pars    = setters.Select((p, i) => new
            {
                Converter = Ref.GetLambda(valueType, p.PropertyType),
                Var       = Ex.Parameter(typeof(ConversionResult <>).MakeGenericType(p.PropertyType), p.Name)
            }).ToArray();
            var end   = Ex.Label(typeof(ConversionResult <>).MakeGenericType(to), "end");
            var block = Ex.Block(new[] { tmp, res, rec }.Concat(pars.Select(x => x.Var)),
                                 Ex.Assign(res, Ex.New(ctor)),
                                 Ex.Assign(rec, recordCreator.Creator(from).ApplyTo(input)),
                                 Ex.Block(pars
                                          .Select(x =>
                                                  Ex.Block(
                                                      Ex.IfThen(
                                                          Ex.MakeBinary(ExpressionType.OrElse,
                                                                        Ex.Call(rec, tryGet, Ex.Constant(x.Var.Name), tmp),
                                                                        Ex.Call(rec, tryGet, Ex.Constant(ToCamelCase(x.Var.Name)), tmp)),
                                                          Ex.Block(
                                                              Ex.Assign(x.Var, x.Converter.ApplyTo(tmp)),
                                                              Ex.IfThenElse(Ex.Property(x.Var, nameof(IConversionResult.IsSuccessful)),
                                                                            Ex.Assign(Ex.Property(res, x.Var.Name), Ex.Property(x.Var, nameof(IConversionResult.Result))),
                                                                            Ex.Goto(end, NoResult(to)))))))),
                                 Ex.Label(end, Result(to, res)));

            return(Ex.Lambda(block, input));
        }
Ejemplo n.º 13
0
        public void TestCosSin()
        {
            var dct = new Dictionary <int, int>();
            var ex  = Ex.Constant(dct);

            var block = Ex.Block(new ParameterExpression[0],
                                 Ex.Call(ex, "Clear", new Type[0]),
                                 Ex.Constant(true)
                                 );
            var block2 = Ex.Block(new ParameterExpression[0],
                                  Ex.Call(ex, "Clear", new Type[0])
                                  );

            var ifex = Ex.Block(new ParameterExpression[0],
                                Ex.IfThenElse(block, block2, block2),
                                Ex.Constant(2f));
            var ifexs = ifex.ToCSharpString();
            //if: only the condition needs to be linearized
            //cond: condition, true, false need to be linarized

            //the library is kinda broken in that if, if/else statements will always print return statements
            //if the last statement is not a void type...
            //in other words it doesn't dewal with blocks well
        }
Ejemplo n.º 14
0
        private static CloneDelegate <T> GetObjectCloner <T>(Type type, CloneContext context)
        {
            Delegate result;
            var      cache = context.Cache;

            var key = new CacheKey(typeof(T), type);

            if (!cache.TryGetValue(key, out result))
            {
                var statements = new List <LinqExpression>();

                var param        = LinqExpression.Parameter(typeof(T).MakeByRefType(), "input");
                var output       = LinqExpression.Parameter(typeof(T).MakeByRefType(), "output");
                var contextParam = LinqExpression.Parameter(typeof(CloneContext), "context");

                ParameterExpression localCast;
                ParameterExpression localOutput;
                ParameterExpression localObj;
                bool isStruct = type.IsValueType && typeof(T) == type;
                bool isArray  = type.IsArray;

                if (isStruct || isArray)
                {
                    localCast   = param;
                    localOutput = output;
                    localObj    = null;
                }
                else
                {
                    localObj    = LinqExpression.Variable(typeof(object), "localObj");
                    localCast   = LinqExpression.Variable(type, "localCast");
                    localOutput = LinqExpression.Variable(type, "localOut");

                    statements.Add(LinqExpression.Assign(localCast, LinqExpression.Convert(param, type)));

                    if (context.IsSelfClone)
                    {
                        statements.Add(LinqExpression.Call(contextParam, MethodAdd, param, param));
                        statements.Add(LinqExpression.Assign(output, localCast));
                    }
                    else
                    {
                        // NOTE: this can fail if there is no default constructor for type.
                        // for example Dictionary<K,T>.ValueCollection, which is created when a access to members Keys or Values is performed on the dicitonary.
                        statements.Add(LinqExpression.Assign(localOutput, LinqExpression.New(type)));


                        statements.Add(LinqExpression.Assign(output, localOutput));
                        statements.Add(LinqExpression.Call(contextParam, MethodAdd, param, localOutput));
                    }
                }

                var fields = GetFields(type);

                // If we have a struct with primitive only
                if (isArray)
                {
                    var genericCloneMethod = DeepcloneArray.GetGenericMethodDefinition();
                    genericCloneMethod = genericCloneMethod.MakeGenericMethod(new[] { type.GetElementType() });

                    statements.Add(LinqExpression.Call(genericCloneMethod, localCast, localOutput, contextParam));
                }
                else if (isStruct && fields.All(field => IsPrimitive(field.FieldType)))
                {
                    statements.Add(LinqExpression.Assign(localOutput, param));
                }
                else
                {
                    foreach (var field in fields)
                    {
                        if (field.IsInitOnly)
                        {
                            throw new InvalidOperationException(String.Format("Field [{0}] in [{1}] is readonly, which is not supported in DeepClone", field.Name, type));
                        }

                        var t = field.FieldType;
                        if (t.IsSubclassOf(typeof(Delegate)))
                        {
                            continue;
                        }

                        var value = LinqExpression.Field(localCast, field);

                        LinqExpression cloneField = null;
                        if (IsPrimitive(t))
                        {
                            if (!context.IsSelfClone)
                            {
                                cloneField = LinqExpression.Assign(LinqExpression.Field(localOutput, field), value);
                            }
                        }
                        else
                        {
                            MethodInfo genericCloneMethod;
                            if (field.FieldType.IsArray)
                            {
                                genericCloneMethod = DeepcloneArray.GetGenericMethodDefinition();
                                genericCloneMethod = genericCloneMethod.MakeGenericMethod(new[] { field.FieldType.GetElementType() });
                            }
                            else
                            {
                                genericCloneMethod = DeepcloneObject.GetGenericMethodDefinition();
                                genericCloneMethod = genericCloneMethod.MakeGenericMethod(new[] { field.FieldType });
                            }

                            cloneField = LinqExpression.Call(genericCloneMethod, value, context.IsSelfClone ? value : LinqExpression.Field(localOutput, field), contextParam);
                        }

                        if (cloneField != null)
                        {
                            statements.Add(cloneField);
                        }
                    }
                }

                LinqExpression body;
                if (isStruct || isArray)
                {
                    if (statements.Count == 0)
                    {
                        body = LinqExpression.Empty();
                    }
                    else
                    {
                        body = LinqExpression.Block(statements);
                    }
                }
                else
                {
                    var innerBody = LinqExpression.Block(new[] { localCast, localOutput }, statements);

                    body = LinqExpression.Block(
                        new[] { localObj },
                        LinqExpression.IfThenElse(
                            LinqExpression.Call(contextParam, MethodTryGetValue, param, localObj), LinqExpression.Assign(output, LinqExpression.Convert(localObj, typeof(T))), innerBody));
                }

                var tempLambda = LinqExpression.Lambda <CloneDelegate <T> >(body, param, output, contextParam);
                result = tempLambda.Compile();
                cache.Add(key, result);
            }

            return((CloneDelegate <T>)result);
        }
Ejemplo n.º 15
0
        static LambdaExpression ApplyMethodHandler(string functionName, LambdaExpression functionLambda, IFunctionExecutionHandler handler)
        {
            // public static int MyMethod(object arg0, int arg1) { ... }

            // becomes:

            // (the 'handler' object is captured and called mh)
            // public static int MyMethodWrapped(object arg0, int arg1)
            // {
            //    var fhArgs = new FunctionExecutionArgs("MyMethod", new object[] { arg0, arg1});
            //    int result = default(int);
            //    try
            //    {
            //        fh.OnEntry(fhArgs);
            //        if (fhArgs.FlowBehavior == FlowBehavior.Return)
            //        {
            //            result = (int)fhArgs.ReturnValue;
            //        }
            //        else
            //        {
            //             // Inner call
            //             result = MyMethod(arg0, arg1);
            //             fhArgs.ReturnValue = result;
            //             fh.OnSuccess(fhArgs);
            //             result = (int)fhArgs.ReturnValue;
            //        }
            //    }
            //    catch ( Exception ex )
            //    {
            //        fhArgs.Exception = ex;
            //        fh.OnException(fhArgs);
            //        // Makes no sense to me yet - I've removed this FlowBehavior enum value.
            //        // if (fhArgs.FlowBehavior == FlowBehavior.Continue)
            //        // {
            //        //     // Finally will run, but can't change return value
            //        //     // Should we assign result...?
            //        //     // So Default value will be returned....?????
            //        //     fhArgs.Exception = null;
            //        // }
            //        // else
            //        if (fhArgs.FlowBehavior == FlowBehavior.Return)
            //        {
            //            // Clear the Exception and return the ReturnValue instead
            //            // Finally will run, but can't further change return value
            //            fhArgs.Exception = null;
            //            result = (int)fhArgs.ReturnValue;
            //        }
            //        else if (fhArgs.FlowBehavior == FlowBehavior.ThrowException)
            //        {
            //            throw fhArgs.Exception;
            //        }
            //        else // if (fhArgs.FlowBehavior == FlowBehavior.Default || fhArgs.FlowBehavior == FlowBehavior.RethrowException)
            //        {
            //            throw;
            //        }
            //    }
            //    finally
            //    {
            //        fh.OnExit(fhArgs);
            //        // NOTE: fhArgs.ReturnValue is not used again here...!
            //    }
            //
            //    return result;
            //  }
            // }

            // CONSIDER: There are some helpers in .NET to capture the exception context, which would allow us to preserve the stack trace in a fresh throw.

            // Ensure the handler object is captured.
            var mh       = Expression.Constant(handler);
            var funcName = Expression.Constant(functionName);

            // Prepare the functionHandlerArgs that will be threaded through the handler,
            // and a bunch of expressions that access various properties on it.
            var fhArgs              = Expr.Variable(typeof(FunctionExecutionArgs), "fhArgs");
            var fhArgsReturnValue   = SymbolExtensions.GetProperty(fhArgs, (FunctionExecutionArgs mea) => mea.ReturnValue);
            var fhArgsException     = SymbolExtensions.GetProperty(fhArgs, (FunctionExecutionArgs mea) => mea.Exception);
            var fhArgsFlowBehaviour = SymbolExtensions.GetProperty(fhArgs, (FunctionExecutionArgs mea) => mea.FlowBehavior);

            // Set up expressions to call the various handler methods.
            // TODO: Later we can determine which of these are actually implemented, and only write out the code needed in the particular case.
            var onEntry     = Expr.Call(mh, SymbolExtensions.GetMethodInfo <IFunctionExecutionHandler>(meh => meh.OnEntry(null)), fhArgs);
            var onSuccess   = Expr.Call(mh, SymbolExtensions.GetMethodInfo <IFunctionExecutionHandler>(meh => meh.OnSuccess(null)), fhArgs);
            var onException = Expr.Call(mh, SymbolExtensions.GetMethodInfo <IFunctionExecutionHandler>(meh => meh.OnException(null)), fhArgs);
            var onExit      = Expr.Call(mh, SymbolExtensions.GetMethodInfo <IFunctionExecutionHandler>(meh => meh.OnExit(null)), fhArgs);

            // Create the new parameters for the wrapper
            var outerParams = functionLambda.Parameters.Select(p => Expr.Parameter(p.Type, p.Name)).ToArray();
            // Create the array of parameter values that will be put into the method handler args.
            var paramsArray = Expr.NewArrayInit(typeof(object), outerParams.Select(p => Expr.Convert(p, typeof(object))));

            // Prepare the result and ex(ception) local variables
            var result = Expr.Variable(functionLambda.ReturnType, "result");
            var ex     = Expression.Parameter(typeof(Exception), "ex");

            // A bunch of helper expressions:
            // : new FunctionExecutionArgs(new object[] { arg0, arg1 })
            var fhArgsConstr = typeof(FunctionExecutionArgs).GetConstructor(new[] { typeof(string), typeof(object[]) });
            var newfhArgs    = Expr.New(fhArgsConstr, funcName, paramsArray);
            // : result = (int)fhArgs.ReturnValue
            var resultFromReturnValue = Expr.Assign(result, Expr.Convert(fhArgsReturnValue, functionLambda.ReturnType));
            // : fhArgs.ReturnValue = (object)result
            var returnValueFromResult = Expr.Assign(fhArgsReturnValue, Expr.Convert(result, typeof(object)));
            // : result = function(arg0, arg1)
            var resultFromInnerCall = Expr.Assign(result, Expr.Invoke(functionLambda, outerParams));

            // Build the Lambda wrapper, with the original parameters
            var lambda = Expr.Lambda(
                Expr.Block(new[] { fhArgs, result },
                           Expr.Assign(fhArgs, newfhArgs),
                           Expr.Assign(result, Expr.Default(result.Type)),
                           Expr.TryCatchFinally(
                               Expr.Block(
                                   onEntry,
                                   Expr.IfThenElse(
                                       Expr.Equal(fhArgsFlowBehaviour, Expr.Constant(FlowBehavior.Return)),
                                       resultFromReturnValue,
                                       Expr.Block(
                                           resultFromInnerCall,
                                           returnValueFromResult,
                                           onSuccess,
                                           resultFromReturnValue))),
                               onExit, // finally
                               Expr.Catch(ex,
                                          Expr.Block(
                                              Expr.Assign(fhArgsException, ex),
                                              onException,
                                              Expr.IfThenElse(
                                                  Expr.Equal(fhArgsFlowBehaviour, Expr.Constant(FlowBehavior.Return)),
                                                  Expr.Block(
                                                      Expr.Assign(fhArgsException, Expr.Constant(null, typeof(Exception))),
                                                      resultFromReturnValue),
                                                  Expr.IfThenElse(
                                                      Expr.Equal(fhArgsFlowBehaviour, Expr.Constant(FlowBehavior.ThrowException)),
                                                      Expr.Throw(fhArgsException),
                                                      Expr.Rethrow()))))
                               ),
                           result),
                functionName,
                outerParams);

            return(lambda);
        }
Ejemplo n.º 16
0
        // The resulting lambda processes N samples, using buffers provided for Input and Output:
        //  void Process(int N, double t0, double T, double[] Input0 ..., double[] Output0 ...)
        //  { ... }
        private Delegate DefineProcess()
        {
            // Map expressions to identifiers in the syntax tree.
            List <KeyValuePair <Expression, LinqExpr> > inputs  = new List <KeyValuePair <Expression, LinqExpr> >();
            List <KeyValuePair <Expression, LinqExpr> > outputs = new List <KeyValuePair <Expression, LinqExpr> >();

            // Lambda code generator.
            CodeGen code = new CodeGen();

            // Create parameters for the basic simulation info (N, t, Iterations).
            ParamExpr SampleCount = code.Decl <int>(Scope.Parameter, "SampleCount");
            ParamExpr t           = code.Decl(Scope.Parameter, Simulation.t);

            // Create buffer parameters for each input...
            foreach (Expression i in Input)
            {
                inputs.Add(new KeyValuePair <Expression, LinqExpr>(i, code.Decl <double[]>(Scope.Parameter, i.ToString())));
            }

            // ... and output.
            foreach (Expression i in Output)
            {
                outputs.Add(new KeyValuePair <Expression, LinqExpr>(i, code.Decl <double[]>(Scope.Parameter, i.ToString())));
            }

            // Create globals to store previous values of inputs.
            foreach (Expression i in Input.Distinct())
            {
                AddGlobal(i.Evaluate(t_t0));
            }

            // Define lambda body.

            // int Zero = 0
            LinqExpr Zero = LinqExpr.Constant(0);

            // double h = T / Oversample
            LinqExpr h = LinqExpr.Constant(TimeStep / (double)Oversample);

            // Load the globals to local variables and add them to the map.
            foreach (KeyValuePair <Expression, GlobalExpr <double> > i in globals)
            {
                code.Add(LinqExpr.Assign(code.Decl(i.Key), i.Value));
            }

            foreach (KeyValuePair <Expression, LinqExpr> i in inputs)
            {
                code.Add(LinqExpr.Assign(code.Decl(i.Key), code[i.Key.Evaluate(t_t0)]));
            }

            // Create arrays for linear systems.
            int      M   = Solution.Solutions.OfType <NewtonIteration>().Max(i => i.Equations.Count(), 0);
            int      N   = Solution.Solutions.OfType <NewtonIteration>().Max(i => i.UnknownDeltas.Count(), 0) + 1;
            LinqExpr JxF = code.DeclInit <double[][]>("JxF", LinqExpr.NewArrayBounds(typeof(double[]), LinqExpr.Constant(M)));

            for (int j = 0; j < M; ++j)
            {
                code.Add(LinqExpr.Assign(LinqExpr.ArrayAccess(JxF, LinqExpr.Constant(j)), LinqExpr.NewArrayBounds(typeof(double), LinqExpr.Constant(N))));
            }

            // for (int n = 0; n < SampleCount; ++n)
            ParamExpr n = code.Decl <int>("n");

            code.For(
                () => code.Add(LinqExpr.Assign(n, Zero)),
                LinqExpr.LessThan(n, SampleCount),
                () => code.Add(LinqExpr.PreIncrementAssign(n)),
                () =>
            {
                // Prepare input samples for oversampling interpolation.
                Dictionary <Expression, LinqExpr> dVi = new Dictionary <Expression, LinqExpr>();
                foreach (Expression i in Input.Distinct())
                {
                    LinqExpr Va = code[i];
                    // Sum all inputs with this key.
                    IEnumerable <LinqExpr> Vbs = inputs.Where(j => j.Key.Equals(i)).Select(j => j.Value);
                    LinqExpr Vb = LinqExpr.ArrayAccess(Vbs.First(), n);
                    foreach (LinqExpr j in Vbs.Skip(1))
                    {
                        Vb = LinqExpr.Add(Vb, LinqExpr.ArrayAccess(j, n));
                    }

                    // dVi = (Vb - Va) / Oversample
                    code.Add(LinqExpr.Assign(
                                 Decl <double>(code, dVi, i, "d" + i.ToString().Replace("[t]", "")),
                                 LinqExpr.Multiply(LinqExpr.Subtract(Vb, Va), LinqExpr.Constant(1.0 / (double)Oversample))));
                }

                // Prepare output sample accumulators for low pass filtering.
                Dictionary <Expression, LinqExpr> Vo = new Dictionary <Expression, LinqExpr>();
                foreach (Expression i in Output.Distinct())
                {
                    code.Add(LinqExpr.Assign(
                                 Decl <double>(code, Vo, i, i.ToString().Replace("[t]", "")),
                                 LinqExpr.Constant(0.0)));
                }

                // int ov = Oversample;
                // do { -- ov; } while(ov > 0)
                ParamExpr ov = code.Decl <int>("ov");
                code.Add(LinqExpr.Assign(ov, LinqExpr.Constant(Oversample)));
                code.DoWhile(() =>
                {
                    // t += h
                    code.Add(LinqExpr.AddAssign(t, h));

                    // Interpolate the input samples.
                    foreach (Expression i in Input.Distinct())
                    {
                        code.Add(LinqExpr.AddAssign(code[i], dVi[i]));
                    }

                    // Compile all of the SolutionSets in the solution.
                    foreach (SolutionSet ss in Solution.Solutions)
                    {
                        if (ss is LinearSolutions)
                        {
                            // Linear solutions are easy.
                            LinearSolutions S = (LinearSolutions)ss;
                            foreach (Arrow i in S.Solutions)
                            {
                                code.DeclInit(i.Left, i.Right);
                            }
                        }
                        else if (ss is NewtonIteration)
                        {
                            NewtonIteration S = (NewtonIteration)ss;

                            // Start with the initial guesses from the solution.
                            foreach (Arrow i in S.Guesses)
                            {
                                code.DeclInit(i.Left, i.Right);
                            }

                            // int it = iterations
                            LinqExpr it = code.ReDeclInit <int>("it", Iterations);
                            // do { ... --it } while(it > 0)
                            code.DoWhile((Break) =>
                            {
                                // Solve the un-solved system.
                                Solve(code, JxF, S.Equations, S.UnknownDeltas);

                                // Compile the pre-solved solutions.
                                if (S.KnownDeltas != null)
                                {
                                    foreach (Arrow i in S.KnownDeltas)
                                    {
                                        code.DeclInit(i.Left, i.Right);
                                    }
                                }

                                // bool done = true
                                LinqExpr done = code.ReDeclInit("done", true);
                                foreach (Expression i in S.Unknowns)
                                {
                                    LinqExpr v  = code[i];
                                    LinqExpr dv = code[NewtonIteration.Delta(i)];

                                    // done &= (|dv| < |v|*epsilon)
                                    code.Add(LinqExpr.AndAssign(done, LinqExpr.LessThan(LinqExpr.Multiply(Abs(dv), LinqExpr.Constant(1e4)), LinqExpr.Add(Abs(v), LinqExpr.Constant(1e-6)))));
                                    // v += dv
                                    code.Add(LinqExpr.AddAssign(v, dv));
                                }
                                // if (done) break
                                code.Add(LinqExpr.IfThen(done, Break));

                                // --it;
                                code.Add(LinqExpr.PreDecrementAssign(it));
                            }, LinqExpr.GreaterThan(it, Zero));

                            //// bool failed = false
                            //LinqExpr failed = Decl(code, code, "failed", LinqExpr.Constant(false));
                            //for (int i = 0; i < eqs.Length; ++i)
                            //    // failed |= |JxFi| > epsilon
                            //    code.Add(LinqExpr.OrAssign(failed, LinqExpr.GreaterThan(Abs(eqs[i].ToExpression().Compile(map)), LinqExpr.Constant(1e-3))));

                            //code.Add(LinqExpr.IfThen(failed, ThrowSimulationDiverged(n)));
                        }
                    }

                    // Update the previous timestep variables.
                    foreach (SolutionSet S in Solution.Solutions)
                    {
                        foreach (Expression i in S.Unknowns.Where(i => globals.Keys.Contains(i.Evaluate(t_t0))))
                        {
                            code.Add(LinqExpr.Assign(code[i.Evaluate(t_t0)], code[i]));
                        }
                    }

                    // Vo += i
                    foreach (Expression i in Output.Distinct())
                    {
                        LinqExpr Voi = LinqExpr.Constant(0.0);
                        try
                        {
                            Voi = code.Compile(i);
                        }
                        catch (Exception Ex)
                        {
                            Log.WriteLine(MessageType.Warning, Ex.Message);
                        }
                        code.Add(LinqExpr.AddAssign(Vo[i], Voi));
                    }

                    // Vi_t0 = Vi
                    foreach (Expression i in Input.Distinct())
                    {
                        code.Add(LinqExpr.Assign(code[i.Evaluate(t_t0)], code[i]));
                    }

                    // --ov;
                    code.Add(LinqExpr.PreDecrementAssign(ov));
                }, LinqExpr.GreaterThan(ov, Zero));

                // Output[i][n] = Vo / Oversample
                foreach (KeyValuePair <Expression, LinqExpr> i in outputs)
                {
                    code.Add(LinqExpr.Assign(LinqExpr.ArrayAccess(i.Value, n), LinqExpr.Multiply(Vo[i.Key], LinqExpr.Constant(1.0 / (double)Oversample))));
                }

                // Every 256 samples, check for divergence.
                if (Vo.Any())
                {
                    code.Add(LinqExpr.IfThen(LinqExpr.Equal(LinqExpr.And(n, LinqExpr.Constant(0xFF)), Zero),
                                             LinqExpr.Block(Vo.Select(i => LinqExpr.IfThenElse(IsNotReal(i.Value),
                                                                                               ThrowSimulationDiverged(n),
                                                                                               LinqExpr.Assign(i.Value, RoundDenormToZero(i.Value)))))));
                }
            });

            // Copy the global state variables back to the globals.
            foreach (KeyValuePair <Expression, GlobalExpr <double> > i in globals)
            {
                code.Add(LinqExpr.Assign(i.Value, code[i.Key]));
            }

            LinqExprs.LambdaExpression lambda = code.Build();
            Delegate ret = lambda.Compile();

            return(ret);
        }