/// <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()); }
/// <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]; })); }
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)); }
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)); }
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)); }
public ImmutableHashSet <object> VisitZenArgumentExpr <T>(ZenArgumentExpr <T> expression, Unit parameter) { throw new UnreachableException(); }
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); })); }
public Expression VisitZenArgumentExpr <T>(ZenArgumentExpr <T> expression, ExpressionConverterEnvironment parameter) { return(parameter.ArgumentAssignment[expression.ArgumentId]); }
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(); }