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)); } }
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)) )); }
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) })); }
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)) ); }
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) }))); }
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); }
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) }))); }
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; }
protected virtual Expression VisitIteratorExpression(IteratorExpression iex) { return(iex); }
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) })); }