示例#1
0
        protected override Expression VisitIteratorExpression(IteratorExpression iex)
        {
            var context = Arg <BindingContext>(CompilationContext.BindingContext);

            var template = FunctionBuilder.CompileCore(new[] { iex.Template }, CompilationContext.Configuration);
            var ifEmpty  = FunctionBuilder.CompileCore(new[] { iex.IfEmpty }, CompilationContext.Configuration);

            if (iex.Sequence is PathExpression pathExpression)
            {
                pathExpression.Context = PathExpression.ResolutionContext.Parameter;
            }

            var compiledSequence  = Arg <object>(FunctionBuilder.Reduce(iex.Sequence, CompilationContext));
            var blockParamsValues = CreateBlockParams();

            return(Call(() =>
                        Iterator.Iterate(context, blockParamsValues, compiledSequence, template, ifEmpty)
                        ));

            ExpressionContainer <ChainSegment[]> CreateBlockParams()
            {
                var parameters = iex.BlockParams?.BlockParam?.Parameters;

                if (parameters == null)
                {
                    parameters = ArrayEx.Empty <ChainSegment>();
                }

                return(Arg(parameters));
            }
        }
示例#2
0
        protected override Expression VisitIteratorExpression(IteratorExpression iex)
        {
            var iteratorBindingContext = Expression.Variable(typeof(BindingContext), "context");

            return(Expression.Block(
                       new ParameterExpression[]
            {
                iteratorBindingContext
            },
                       Expression.IfThenElse(
                           Expression.TypeIs(iex.Sequence, typeof(IEnumerable)),
                           Expression.IfThenElse(
#if netstandard
                               Expression.Call(new Func <object, bool>(IsNonListDynamic).GetMethodInfo(), new[] { iex.Sequence }),
#else
                               Expression.Call(new Func <object, bool>(IsNonListDynamic).Method, new[] { iex.Sequence }),
#endif
                               GetDynamicIterator(iteratorBindingContext, iex),
                               Expression.IfThenElse(
#if netstandard
                                   Expression.Call(new Func <object, bool>(IsGenericDictionary).GetMethodInfo(), new[] { iex.Sequence }),
#else
                                   Expression.Call(new Func <object, bool>(IsGenericDictionary).Method, new[] { iex.Sequence }),
#endif
                                   GetDictionaryIterator(iteratorBindingContext, iex),
                                   GetEnumerableIterator(iteratorBindingContext, iex))),
                           GetObjectIterator(iteratorBindingContext, iex))
                       ));
        }
示例#3
0
        private Expression GetEnumerableIterator(Expression contextParameter, IteratorExpression iex)
        {
            var fb = new FunctionBuilder(CompilationContext.Configuration);
            return Expression.Block(
                Expression.Assign(contextParameter,
                    Expression.New(
#if netstandard
                        typeof(IteratorBindingContext).GetTypeInfo().GetConstructor(new[] { typeof(BindingContext) }),
#else
                        typeof(IteratorBindingContext).GetConstructor(new[] { typeof(BindingContext) }),
#endif
                        new Expression[] { CompilationContext.BindingContext })),
                Expression.Call(
#if netstandard
                    new Action<IteratorBindingContext, IEnumerable, Action<TextWriter, object>, Action<TextWriter, object>>(Iterate).GetMethodInfo(),
#else
                    new Action<IteratorBindingContext, IEnumerable, Action<TextWriter, object>, Action<TextWriter, object>>(Iterate).Method,
#endif
                    new Expression[]
                    {
                        Expression.Convert(contextParameter, typeof(IteratorBindingContext)),
                        Expression.Convert(iex.Sequence, typeof(IEnumerable)),
                        fb.Compile(new [] { iex.Template }, contextParameter),
                        fb.Compile(new [] { iex.IfEmpty }, CompilationContext.BindingContext) 
                    }));
        }
示例#4
0
        protected override Expression VisitIteratorExpression(IteratorExpression iex)
        {
            var iteratorBindingContext = Expression.Variable(typeof(BindingContext), "context");
            return Expression.Block(
                new ParameterExpression[]
                {
                    iteratorBindingContext
                },
                Expression.IfThenElse(
                    Expression.TypeIs(iex.Sequence, typeof(IEnumerable)),
                    Expression.IfThenElse(
#if netstandard
                        Expression.Call(new Func<object, bool>(IsNonListDynamic).GetMethodInfo(), new[] { iex.Sequence }),
#else
                        Expression.Call(new Func<object, bool>(IsNonListDynamic).Method, new[] { iex.Sequence }),
#endif
                        GetDynamicIterator(iteratorBindingContext, iex),
                        Expression.IfThenElse(
#if netstandard
                            Expression.Call(new Func<object, bool>(IsGenericDictionary).GetMethodInfo(), new[] { iex.Sequence }),
#else
                            Expression.Call(new Func<object, bool>(IsGenericDictionary).Method, new[] { iex.Sequence }),
#endif
                            GetDictionaryIterator(iteratorBindingContext, iex),
                            GetEnumerableIterator(iteratorBindingContext, iex))),
                    GetObjectIterator(iteratorBindingContext, iex))
            );
        }
示例#5
0
        private Expression GetEnumerableIterator(Expression contextParameter, IteratorExpression iex)
        {
            var fb = new FunctionBuilder(CompilationContext.Configuration);

            return(Expression.Block(
                       Expression.Assign(contextParameter,
                                         Expression.New(
#if netstandard
                                             typeof(IteratorBindingContext).GetTypeInfo().GetConstructor(new[] { typeof(BindingContext) }),
#else
                                             typeof(IteratorBindingContext).GetConstructor(new[] { typeof(BindingContext) }),
#endif
                                             new Expression[] { CompilationContext.BindingContext })),
                       Expression.Call(
#if netstandard
                           new Action <IteratorBindingContext, IEnumerable, Action <TextWriter, object>, Action <TextWriter, object> >(Iterate).GetMethodInfo(),
#else
                           new Action <IteratorBindingContext, IEnumerable, Action <TextWriter, object>, Action <TextWriter, object> >(Iterate).Method,
#endif
                           new Expression[]
            {
                Expression.Convert(contextParameter, typeof(IteratorBindingContext)),
                Expression.Convert(iex.Sequence, typeof(IEnumerable)),
                fb.Compile(new [] { iex.Template }, contextParameter),
                fb.Compile(new [] { iex.IfEmpty }, CompilationContext.BindingContext)
            })));
        }
示例#6
0
        protected override Expression VisitIteratorExpression(IteratorExpression iex)
        {
            var context  = ExpressionShortcuts.Arg <BindingContext>(CompilationContext.BindingContext);
            var sequence = ExpressionShortcuts.Var <object>("sequence");

            var template = FunctionBuilder.CompileCore(new[] { iex.Template }, CompilationContext.Configuration);
            var ifEmpty  = FunctionBuilder.CompileCore(new[] { iex.IfEmpty }, CompilationContext.Configuration);

            var compiledSequence       = ExpressionShortcuts.Arg <object>(FunctionBuilder.Reduce(iex.Sequence, CompilationContext));
            var blockParams            = ExpressionShortcuts.Arg <BlockParam>(iex.BlockParams);
            var blockParamsProvider    = ExpressionShortcuts.Call(() => BlockParamsValueProvider.Create(context, blockParams));
            var blockParamsProviderVar = ExpressionShortcuts.Var <BlockParamsValueProvider>();

            return(ExpressionShortcuts.Block()
                   .Parameter(sequence, compiledSequence)
                   .Parameter(blockParamsProviderVar, blockParamsProvider)
                   .Line(blockParamsProviderVar.Using((self, builder) =>
            {
                builder
                .Line(context.Call(o => o.RegisterValueProvider((IValueProvider)self)))
                .Line(ExpressionShortcuts.Try()
                      .Body(ExpressionShortcuts.Call(() =>
                                                     Iterator.Iterate(context, self, sequence, template, ifEmpty)
                                                     ))
                      .Finally(context.Call(o => o.UnregisterValueProvider((IValueProvider)self)))
                      );
            })));
        }
        protected virtual Expression VisitIteratorExpression(IteratorExpression iex)
        {
            Expression sequence = Visit(iex.Sequence);

            // Don't visit Template/IfEmpty - they will be compiled separately

            if (sequence != iex.Sequence)
            {
                return(HandlebarsExpression.Iterator(sequence, iex.BlockParams, iex.Template, iex.IfEmpty));
            }
            return(iex);
        }
示例#8
0
        private Expression GetObjectIterator(Expression contextParameter, IteratorExpression iex)
        {
            var fb = new FunctionBuilder(CompilationContext.Configuration);

            return(Expression.Block(
                       Expression.Assign(contextParameter,
                                         Expression.New(
                                             typeof(ObjectEnumeratorBindingContext).GetConstructor(new[] { typeof(BindingContext) }),
                                             new Expression[] { CompilationContext.BindingContext })),
                       Expression.Call(
                           new Action <ObjectEnumeratorBindingContext, object, Action <TextWriter, object>, Action <TextWriter, object> >(Iterate).Method,
                           new Expression[]
            {
                Expression.Convert(contextParameter, typeof(ObjectEnumeratorBindingContext)),
                iex.Sequence,
                fb.Compile(new [] { iex.Template }, contextParameter),
                fb.Compile(new [] { iex.IfEmpty }, CompilationContext.BindingContext)
            })));
        }
示例#9
0
        protected override Expression VisitIteratorExpression(IteratorExpression iex)
        {
            var context = CompilationContext.Args.BindingContext;
            var writer  = CompilationContext.Args.EncodedWriter;

            var template = FunctionBuilder.Compile(new[] { iex.Template }, new CompilationContext(CompilationContext));
            var ifEmpty  = FunctionBuilder.Compile(new[] { iex.IfEmpty }, new CompilationContext(CompilationContext));

            if (iex.Sequence is PathExpression pathExpression)
            {
                pathExpression.Context = PathExpression.ResolutionContext.Parameter;
            }

            var compiledSequence  = Arg <object>(FunctionBuilder.Reduce(iex.Sequence, CompilationContext));
            var blockParamsValues = CreateBlockParams();

            return(iex.HelperName[0] switch
            {
                '#' => Call(() => Iterator.Iterate(context, writer, blockParamsValues, compiledSequence, template, ifEmpty)),
                '^' => Call(() => Iterator.Iterate(context, writer, blockParamsValues, compiledSequence, ifEmpty, template)),
                _ => throw new HandlebarsCompilerException($"Tried to convert {iex.HelperName} expression to iterator block", iex.Context)
            });
 protected virtual Expression VisitIteratorExpression(IteratorExpression iex)
 {
     return iex;
 }
示例#11
0
 protected virtual Expression VisitIteratorExpression(IteratorExpression iex)
 {
     return(iex);
 }
示例#12
0
 private Expression GetObjectIterator(Expression contextParameter, IteratorExpression iex)
 {
     var fb = new FunctionBuilder(CompilationContext.Configuration);
     return Expression.Block(
         Expression.Assign(contextParameter,
             Expression.New(
                 typeof(ObjectEnumeratorBindingContext).GetConstructor(new[] { typeof(BindingContext) }),
                 new Expression[] { CompilationContext.BindingContext })),
         Expression.Call(
             new Action<ObjectEnumeratorBindingContext, object, Action<TextWriter, object>, Action<TextWriter, object>>(Iterate).Method,
             new Expression[]
             {
                 Expression.Convert(contextParameter, typeof(ObjectEnumeratorBindingContext)),
                 iex.Sequence,
                 fb.Compile(new [] { iex.Template }, contextParameter),
                 fb.Compile(new [] { iex.IfEmpty }, CompilationContext.BindingContext) 
             }));
 }