Exemple #1
0
 public ImmutableHashSet <object> VisitZenListCaseExpr <TList, TResult>(ZenListCaseExpr <TList, TResult> expression, Unit parameter)
 {
     return(LookupOrCompute(expression, () =>
     {
         var x = expression.ListExpr.Accept(this, parameter);
         var e = expression.EmptyCase.Accept(this, parameter);
         return x.Union(e); // no easy way to evaluate cons case.
     }));
 }
Exemple #2
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);
            }));
        }