예제 #1
0
        /// <summary>
        /// Compile a Zen expression to native IL.
        /// </summary>
        /// <param name="function">The function.</param>
        /// <param name="maxUnrollingDepth">The maximum unrolling depth.</param>
        /// <returns>A native IL function.</returns>
        public static Func <T1, T2, T3, T4> Compile <T1, T2, T3, T4>(Func <Zen <T1>, Zen <T2>, Zen <T3>, Zen <T4> > function, int maxUnrollingDepth)
        {
            var args = ImmutableDictionary <string, Expression> .Empty;

            var arg1   = new ZenArgumentExpr <T1>();
            var param1 = Expression.Parameter(typeof(T1));

            args = args.Add(arg1.Id, param1);

            var arg2   = new ZenArgumentExpr <T2>();
            var param2 = Expression.Parameter(typeof(T2));

            args = args.Add(arg2.Id, param2);

            var arg3   = new ZenArgumentExpr <T3>();
            var param3 = Expression.Parameter(typeof(T3));

            args = args.Add(arg3.Id, param3);

            var env    = new ExpressionConverterEnvironment(args);
            var e      = function(arg1, arg2, arg3);
            var expr   = CompileToBlock(e, env, ImmutableDictionary <object, Expression> .Empty, 0, maxUnrollingDepth);
            var lambda = Expression.Lambda <Func <T1, T2, T3, T4> >(expr, new ParameterExpression[] { param1, param2, param3 });

            return(lambda.Compile());
        }
예제 #2
0
 /// <summary>
 /// Visit an ArgumentExpr.
 /// </summary>
 /// <param name="expression">The expression.</param>
 /// <param name="parameter">The parameter.</param>
 /// <returns>The resulting symbolic value.</returns>
 public SymbolicValue <TModel, TVar, TBool, TInt> VisitZenArgumentExpr <T1>(ZenArgumentExpr <T1> expression, SymbolicEvaluationEnvironment <TModel, TVar, TBool, TInt> parameter)
 {
     return(LookupOrCompute(expression, () =>
     {
         return parameter.ArgumentAssignment[expression.Id];
     }));
 }
예제 #3
0
        public static T2 Run <T1, T2>(Func <Zen <T1>, Zen <T2> > function, T1 value1)
        {
            var arg1 = new ZenArgumentExpr <T1>();
            var args = ImmutableDictionary <string, object> .Empty;

            args = args.Add(arg1.Id, value1);
            var expression = function(arg1);

            return(Interpret(expression, args));
        }
예제 #4
0
        public static T3 CompileRunHelper <T1, T2, T3>(
            Func <Zen <T1>, Zen <T2>, Zen <T3> > function,
            T1 value1,
            T2 value2,
            ImmutableDictionary <string, object> args)
        {
            var arg1 = new ZenArgumentExpr <T1>();
            var arg2 = new ZenArgumentExpr <T2>();

            args = args.Add(arg1.Id, value1);
            args = args.Add(arg2.Id, value2);
            var expression = function(arg1, arg2);

            return(Interpret(expression, args));
        }
예제 #5
0
        public static T4 Run <T1, T2, T3, T4>(
            Func <Zen <T1>, Zen <T2>, Zen <T3>, Zen <T4> > function,
            T1 value1,
            T2 value2,
            T3 value3)
        {
            var arg1 = new ZenArgumentExpr <T1>();
            var arg2 = new ZenArgumentExpr <T2>();
            var arg3 = new ZenArgumentExpr <T3>();
            var args = ImmutableDictionary <string, object> .Empty;

            args = args.Add(arg1.Id, value1);
            args = args.Add(arg2.Id, value2);
            args = args.Add(arg3.Id, value3);
            var expression = function(arg1, arg2, arg3);

            return(Interpret(expression, args));
        }
예제 #6
0
 public ImmutableHashSet <object> VisitZenArgumentExpr <T>(ZenArgumentExpr <T> expression, Unit parameter)
 {
     throw new UnreachableException();
 }
예제 #7
0
        public Expression VisitZenListCaseExpr <TList, TResult>(ZenListCaseExpr <TList, TResult> expression, ExpressionConverterEnvironment parameter)
        {
            return(LookupOrCompute(expression, () =>
            {
                var immutableListType = typeof(ImmutableList <TList>);

                // compile the list expression
                var listExpr = expression.ListExpr.Accept(this, parameter);

                // Console.WriteLine($"listExpr: {listExpr}");

                // cast to an immutable list, since it will return IList
                var toImmutableListMethod = typeof(CommonUtilities)
                                            .GetMethodCached("ToImmutableList")
                                            .MakeGenericMethod(typeof(TList));

                var immutableListExpr = Expression.Call(toImmutableListMethod, listExpr);

                var listVariable = FreshVariable(immutableListType);
                this.Variables.Add(listVariable);
                this.BlockExpressions.Add(Expression.Assign(listVariable, immutableListExpr));

                // check if list is empty, if so return the empty case
                var isEmptyExpr = Expression.PropertyOrField(listVariable, "IsEmpty");

                // call SplitHead to get the tuple result.
                var splitMethod = typeof(CommonUtilities).GetMethodCached("SplitHead").MakeGenericMethod(typeof(TList));
                var splitExpr = Expression.Call(splitMethod, listVariable);
                var splitVariable = FreshVariable(typeof(ValueTuple <TList, IList <TList> >));

                // extract the head and tail
                var hdExpr = Expression.PropertyOrField(splitVariable, "Item1");
                var tlExpr = Expression.PropertyOrField(splitVariable, "Item2");

                // compile the empty expression
                var emptyExpr = expression.EmptyCase.Accept(this, parameter);

                // run the cons lambda
                var runMethod = typeof(Interpreter)
                                .GetMethodCached("CompileRunHelper")
                                .MakeGenericMethod(typeof(TList), typeof(IList <TList>), typeof(TResult));

                // create the bound arguments by constructing the immutable list
                var dictType = typeof(ImmutableDictionary <long, object>);
                var dictField = dictType.GetFieldCached("Empty");
                Expression argsExpr = Expression.Field(null, dictField);
                var dictAddMethod = dictType.GetMethodCached("Add");

                foreach (var kv in parameter.ArgumentAssignment)
                {
                    argsExpr = Expression.Call(
                        argsExpr,
                        dictAddMethod,
                        Expression.Constant(kv.Key),
                        Expression.Convert(kv.Value, typeof(object)));
                }

                // either unroll the match one level, or hand off the the interpreter.
                Expression consExpr;
                if (this.currentMatchUnrollingDepth == this.maxMatchUnrollingDepth)
                {
                    var function = Expression.Constant(expression.ConsCase);
                    consExpr = Expression.Call(runMethod, function, hdExpr, tlExpr, argsExpr);
                }
                else
                {
                    var newAssignment = parameter.ArgumentAssignment;

                    var argHd = new ZenArgumentExpr <TList>();
                    newAssignment = newAssignment.Add(argHd.ArgumentId, hdExpr);
                    var argTl = new ZenArgumentExpr <IList <TList> >();
                    newAssignment = newAssignment.Add(argTl.ArgumentId, tlExpr);

                    var zenConsExpr = expression.ConsCase(argHd, argTl);

                    consExpr = CodeGenerator.CompileToBlock(
                        zenConsExpr,
                        new ExpressionConverterEnvironment(newAssignment),
                        this.SubexpressionCache,
                        this.currentMatchUnrollingDepth + 1,
                        this.maxMatchUnrollingDepth);
                }

                var nonEmptyBlock = Expression.Block(
                    new List <ParameterExpression> {
                    splitVariable
                },
                    Expression.Assign(splitVariable, splitExpr),
                    consExpr);

                return Expression.Condition(isEmptyExpr, emptyExpr, nonEmptyBlock);
            }));
        }
예제 #8
0
 public Expression VisitZenArgumentExpr <T>(ZenArgumentExpr <T> expression, ExpressionConverterEnvironment parameter)
 {
     return(parameter.ArgumentAssignment[expression.ArgumentId]);
 }
예제 #9
0
        public void TestUnrolling()
        {
            var a       = Arbitrary <bool>();
            var b       = Arbitrary <bool>();
            var x       = Arbitrary <int>();
            var y       = Arbitrary <int>();
            var byte1   = Arbitrary <byte>();
            var byte2   = Arbitrary <byte>();
            var short1  = Arbitrary <short>();
            var short2  = Arbitrary <short>();
            var ushort1 = Arbitrary <ushort>();
            var ushort2 = Arbitrary <ushort>();
            var uint1   = Arbitrary <uint>();
            var uint2   = Arbitrary <uint>();
            var long1   = Arbitrary <long>();
            var long2   = Arbitrary <long>();
            var ulong1  = Arbitrary <ulong>();
            var ulong2  = Arbitrary <ulong>();
            var bigint1 = Arbitrary <BigInteger>();
            var bigint2 = Arbitrary <BigInteger>();
            var string1 = Arbitrary <string>();
            var string2 = Arbitrary <string>();
            var string3 = Arbitrary <string>();
            var list1   = Arbitrary <IList <byte> >();
            var list2   = Arbitrary <IList <byte> >();
            var h1      = Arbitrary <IpHeader>();
            var h2      = Arbitrary <IpHeader>();
            var opt     = Arbitrary <Option <int> >();
            var arg     = new ZenArgumentExpr <int>();

            var header = IpHeader.Create(Ip.Create(1), Ip.Create(2), 3, 4, 5);

            CheckEqual(True(), True());
            CheckEqual(False(), False());
            CheckEqual(And(a, b), And(a, b));
            CheckEqual(Or(a, b), Or(a, b));
            CheckEqual(Not(a), Not(a));
            CheckEqual(x | y, x | y);
            CheckEqual(x & y, x & y);
            CheckEqual(x ^ y, x ^ y);
            CheckEqual(x + y, x + y);
            CheckEqual(~x, ~x);
            CheckEqual(byte1 + byte2, byte1 + byte2);
            CheckEqual(short1 + short2, short1 + short2);
            CheckEqual(ushort1 + ushort2, ushort1 + ushort2);
            CheckEqual(uint1 + uint2, uint1 + uint2);
            CheckEqual(long1 + long2, long1 + long2);
            CheckEqual(ulong1 + ulong2, ulong1 + ulong2);
            CheckEqual(x - y, x - y);
            CheckEqual(x * y, x * y);
            CheckEqual(x < y, x < y);
            CheckEqual(x > y, x > y);
            CheckEqual(x <= y, x <= y);
            CheckEqual(x >= y, x >= y);
            CheckEqual(bigint1 + bigint2, bigint1 + bigint2);
            CheckEqual(string1 + string2, string1 + string2);
            CheckEqual(string1.At(bigint1), string1.At(bigint1));
            CheckEqual(string1.Contains(string2), string1.Contains(string2));
            CheckEqual(string1.StartsWith(string2), string1.StartsWith(string2));
            CheckEqual(string1.EndsWith(string2), string1.EndsWith(string2));
            CheckEqual(string1.IndexOf(string2, bigint1), string1.IndexOf(string2, bigint1));
            CheckEqual(string1.Length(), string1.Length());
            CheckEqual(string1.ReplaceFirst(string2, string3), string1.ReplaceFirst(string2, string3));
            CheckEqual(string1.Substring(bigint1, bigint2), string1.Substring(bigint1, bigint2));
            CheckEqual(opt.HasValue(), opt.HasValue());
            CheckEqual(arg, arg);
            CheckEqual(If(a, x, y), If(a, x, y));
            CheckEqual(header, header);
            CheckEqual(header.WithField("DstIp", Ip.Create(99)), header.WithField("DstIp", Ip.Create(99)));
            CheckEqual(list1.AddFront(byte1), list1.AddFront(byte1));

            list1.Case(Constant(1), (hd, tl) => 2).Unroll();
            If(b, list1, list2).Case(Constant(1), (hd, tl) => 2).Unroll();
            If(b, h1, h2).GetDstIp().Unroll();
        }