protected override Expression VisitBlockHelperExpression(BlockHelperExpression bhex)
        {
            var fb        = new FunctionBuilder(CompilationContext.Configuration);
            var body      = fb.Compile(((BlockExpression)bhex.Body).Expressions, CompilationContext.BindingContext);
            var inversion = fb.Compile(((BlockExpression)bhex.Inversion).Expressions, CompilationContext.BindingContext);
            var helper    = CompilationContext.Configuration.BlockHelpers[bhex.HelperName.Replace("#", "")];
            var arguments = new Expression[]
            {
                Expression.Property(
                    CompilationContext.BindingContext,
                    typeof(BindingContext).GetProperty("TextWriter")),
                Expression.New(
                    typeof(HelperOptions).GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic)[0],
                    body,
                    inversion),
                Expression.Property(
                    CompilationContext.BindingContext,
                    typeof(BindingContext).GetProperty("Value")),
                Expression.NewArrayInit(typeof(object), bhex.Arguments)
            };

            if (helper.Target != null)
            {
                return(Expression.Call(
                           Expression.Constant(helper.Target),
                           helper.Method,
                           arguments));
            }
            else
            {
                return(Expression.Call(
                           helper.Method,
                           arguments));
            }
        }
 protected override Expression VisitBlockHelperExpression(BlockHelperExpression bhex)
 {
     var fb = new FunctionBuilder(CompilationContext.Configuration);
     var body = fb.Compile(((BlockExpression)bhex.Body).Expressions, CompilationContext.BindingContext);
     var inversion = fb.Compile(((BlockExpression)bhex.Inversion).Expressions, CompilationContext.BindingContext);
     var helper = CompilationContext.Configuration.BlockHelpers[bhex.HelperName.Replace("#", "")];
     var arguments = new Expression[]
     {
         Expression.Property(
             CompilationContext.BindingContext,
             typeof(BindingContext).GetProperty("TextWriter")),
         Expression.New(
                 typeof(HelperOptions).GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic)[0],
                 body,
                 inversion),
         Expression.Property(
             CompilationContext.BindingContext,
             typeof(BindingContext).GetProperty("Value")),
         Expression.NewArrayInit(typeof(object), bhex.Arguments)
     };
     if (helper.Target != null)
     {
         return Expression.Call(
             Expression.Constant(helper.Target),
             helper.Method,
             arguments);
     }
     else
     {
         return Expression.Call(
             helper.Method,
             arguments);
     }
 }
 protected override Expression VisitBlockHelperExpression(BlockHelperExpression bhex)
 {
     return HandlebarsExpression.BlockHelper(
         bhex.HelperName,
         bhex.Arguments.Select(arg => Visit(arg)),
         Visit(bhex.Body),
         Visit(bhex.Inversion));
 }
 protected override Expression VisitBlockHelperExpression(BlockHelperExpression bhex)
 {
     return(HandlebarsExpression.BlockHelper(
                bhex.HelperName,
                bhex.Arguments.Select(arg => Visit(arg)),
                Visit(bhex.Body),
                Visit(bhex.Inversion)));
 }
Exemplo n.º 5
0
        protected override Expression VisitBlockHelperExpression(BlockHelperExpression bhex)
        {
            var isInlinePartial = bhex.HelperName == "#*inline";

            var fb = new FunctionBuilder(CompilationContext.Configuration);


            var bindingContext = isInlinePartial ? (Expression)CompilationContext.BindingContext :
                                 Expression.Property(
                CompilationContext.BindingContext,
                typeof(BindingContext).GetProperty("Value"));

            var body      = fb.Compile(((BlockExpression)bhex.Body).Expressions, CompilationContext.BindingContext);
            var inversion = fb.Compile(((BlockExpression)bhex.Inversion).Expressions, CompilationContext.BindingContext);
            var helper    = CompilationContext.Configuration.BlockHelpers[bhex.HelperName.Replace("#", "")];
            var arguments = new Expression[]
            {
                Expression.Property(
                    CompilationContext.BindingContext,
                    typeof(BindingContext).GetProperty("TextWriter")),
                Expression.Property(
                    CompilationContext.BindingContext,
                    typeof(BindingContext).GetProperty("Root")),
                Expression.New(
                    typeof(HelperOptions).GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic)[0],
                    body,
                    inversion),
                //this next arg is usually data, like { first: "Marc" }
                //but for inline partials this is the complete BindingContext.
                bindingContext,
                Expression.NewArrayInit(typeof(object), bhex.Arguments)
            };


            if (helper.Target != null)
            {
                return(Expression.Call(
                           Expression.Constant(helper.Target),
#if netstandard
                           helper.GetMethodInfo(),
#else
                           helper.Method,
#endif
                           arguments));
            }
            else
            {
                return(Expression.Call(
#if netstandard
                           helper.GetMethodInfo(),
#else
                           helper.Method,
#endif
                           arguments));
            }
        }
        protected virtual Expression VisitBlockHelperExpression(BlockHelperExpression bhex)
        {
            var arguments = VisitExpressionList(bhex.Arguments);

            // Don't visit Body/Inversion - they will be compiled separately

            if (arguments != bhex.Arguments)
            {
                return(HandlebarsExpression.BlockHelper(bhex.HelperName, arguments, bhex.BlockParams, bhex.Body, bhex.Inversion, bhex.IsRaw));
            }
            return(bhex);
        }
 protected virtual Expression VisitBlockHelperExpression(BlockHelperExpression bhex)
 {
     return bhex;
 }
Exemplo n.º 8
0
 protected override Expression VisitBlockHelperExpression(BlockHelperExpression bhex) => bhex;
Exemplo n.º 9
0
 protected virtual Expression VisitBlockHelperExpression(BlockHelperExpression bhex)
 {
     return(bhex);
 }
Exemplo n.º 10
0
 protected override Expression VisitBlockHelperExpression(BlockHelperExpression bhex)
 {
     return(bhex);
 }
        protected override Expression VisitBlockHelperExpression(BlockHelperExpression bhex)
        {
            var isInlinePartial = bhex.HelperName == "#*inline";

            var pathInfo       = PathInfoStore.Current.GetOrAdd(bhex.HelperName);
            var bindingContext = CompilationContext.Args.BindingContext;
            var context        = isInlinePartial
                ? bindingContext.As <object>()
                : bindingContext.Property(o => o.Value);

            var readerContext = bhex.Context;
            var direct        = Compile(bhex.Body);
            var inverse       = Compile(bhex.Inversion);
            var args          = FunctionBinderHelpers.CreateArguments(bhex.Arguments, CompilationContext);

            var direction   = bhex.IsRaw || pathInfo.IsBlockHelper ? BlockHelperDirection.Direct : BlockHelperDirection.Inverse;
            var blockParams = CreateBlockParams();

            var blockHelpers = CompilationContext.Configuration.BlockHelpers;

            if (blockHelpers.TryGetValue(pathInfo, out var descriptor))
            {
                return(BindByRef(pathInfo, descriptor));
            }

            var helperResolvers = CompilationContext.Configuration.HelperResolvers;

            for (var index = 0; index < helperResolvers.Count; index++)
            {
                var resolver = helperResolvers[index];
                if (!resolver.TryResolveBlockHelper(pathInfo, out var resolvedDescriptor))
                {
                    continue;
                }

                descriptor = new Ref <IHelperDescriptor <BlockHelperOptions> >(resolvedDescriptor);
                blockHelpers.AddOrReplace(pathInfo, descriptor);

                return(BindByRef(pathInfo, descriptor));
            }

            var lateBindBlockHelperDescriptor = new LateBindBlockHelperDescriptor(pathInfo);
            var lateBindBlockHelperRef        = new Ref <IHelperDescriptor <BlockHelperOptions> >(lateBindBlockHelperDescriptor);

            blockHelpers.AddOrReplace(pathInfo, lateBindBlockHelperRef);

            return(BindByRef(pathInfo, lateBindBlockHelperRef));

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

                parameters ??= ArrayEx.Empty <ChainSegment>();

                return(Arg(parameters));
            }

            TemplateDelegate Compile(Expression expression)
            {
                var blockExpression = (BlockExpression)expression;

                return(FunctionBuilder.Compile(blockExpression.Expressions, new CompilationContext(CompilationContext)));
            }

            Expression BindByRef(PathInfo name, Ref <IHelperDescriptor <BlockHelperOptions> > helperBox)
            {
                var writer = CompilationContext.Args.EncodedWriter;

                var helperOptions = direction switch
                {
                    BlockHelperDirection.Direct => New(() => new BlockHelperOptions(name, direct, inverse, blockParams, bindingContext)),
                    BlockHelperDirection.Inverse => New(() => new BlockHelperOptions(name, inverse, direct, blockParams, bindingContext)),
                    _ => throw new HandlebarsCompilerException("Helper referenced with unknown prefix", readerContext)
                };

                var callContext = New(() => new Context(bindingContext, context));

                return(Call(() => helperBox.Value.Invoke(writer, helperOptions, callContext, args)));
            }
        }
    }
        protected override Expression VisitBlockHelperExpression(BlockHelperExpression bhex)
        {
            var isInlinePartial = bhex.HelperName == "#*inline";

            var context        = ExpressionShortcuts.Arg <BindingContext>(CompilationContext.BindingContext);
            var bindingContext = isInlinePartial
                ? context.Cast <object>()
                : context.Property(o => o.Value);

            var readerContext = ExpressionShortcuts.Arg(bhex.Context);
            var body          = FunctionBuilder.CompileCore(((BlockExpression)bhex.Body).Expressions, CompilationContext.Configuration);
            var inverse       = FunctionBuilder.CompileCore(((BlockExpression)bhex.Inversion).Expressions, CompilationContext.Configuration);
            var helperName    = bhex.HelperName.TrimStart('#', '^');
            var textWriter    = context.Property(o => o.TextWriter);
            var arguments     = ExpressionShortcuts.Array <object>(bhex.Arguments.Select(o => FunctionBuilder.Reduce(o, CompilationContext)));
            var configuration = ExpressionShortcuts.Arg(CompilationContext.Configuration);

            var reducerNew = ExpressionShortcuts.New(() => new LambdaReducer(context, body, inverse));
            var reducer    = ExpressionShortcuts.Var <LambdaReducer>();

            var blockParamsProvider   = ExpressionShortcuts.Var <BlockParamsValueProvider>();
            var blockParamsExpression = ExpressionShortcuts.Call(
                () => BlockParamsValueProvider.Create(context, ExpressionShortcuts.Arg <BlockParam>(bhex.BlockParams))
                );

            var helperOptions = ExpressionShortcuts.New(
                () => new HelperOptions(
                    reducer.Property(o => o.Direct),
                    reducer.Property(o => o.Inverse),
                    blockParamsProvider,
                    configuration)
                );

            var blockHelpers = CompilationContext.Configuration.BlockHelpers;

            if (blockHelpers.TryGetValue(helperName, out var helper))
            {
                return(ExpressionShortcuts.Block()
                       .Parameter(reducer, reducerNew)
                       .Parameter(blockParamsProvider, blockParamsExpression)
                       .Line(blockParamsProvider.Using((self, builder) =>
                {
                    builder
                    .Line(context.Call(o => o.RegisterValueProvider((IValueProvider)self)))
                    .Line(ExpressionShortcuts.Try()
                          .Body(ExpressionShortcuts.Call(
                                    () => helper(textWriter, helperOptions, bindingContext, arguments)
                                    ))
                          .Finally(context.Call(o => o.UnregisterValueProvider((IValueProvider)self)))
                          );
                })));
            }

            foreach (var resolver in CompilationContext.Configuration.HelperResolvers)
            {
                if (resolver.TryResolveBlockHelper(helperName, out helper))
                {
                    return(ExpressionShortcuts.Block()
                           .Parameter(reducer, reducerNew)
                           .Parameter(blockParamsProvider, blockParamsExpression)
                           .Line(blockParamsProvider.Using((self, builder) =>
                    {
                        builder
                        .Line(context.Call(o => o.RegisterValueProvider((IValueProvider)self)))
                        .Line(ExpressionShortcuts.Try()
                              .Body(ExpressionShortcuts.Call(
                                        () => helper(textWriter, helperOptions, bindingContext, arguments)
                                        ))
                              .Finally(context.Call(o => o.UnregisterValueProvider((IValueProvider)self)))
                              );
                    })));
                }
            }

            var helperPrefix = bhex.HelperName[0];

            return(ExpressionShortcuts.Block()
                   .Parameter(reducer, reducerNew)
                   .Parameter(blockParamsProvider, blockParamsExpression)
                   .Line(blockParamsProvider.Using((self, builder) =>
            {
                builder
                .Line(context.Call(o => o.RegisterValueProvider((IValueProvider)self)))
                .Line(ExpressionShortcuts.Try()
                      .Body(ExpressionShortcuts.Call(
                                () => LateBoundCall(
                                    helperName,
                                    helperPrefix,
                                    context,
                                    (IReaderContext)readerContext,
                                    textWriter, helperOptions,
                                    body,
                                    inverse,
                                    bindingContext,
                                    self,
                                    arguments
                                    )
                                ))
                      .Finally(context.Call(o => o.UnregisterValueProvider((IValueProvider)self)))
                      );
            })));
        }
        protected override Expression VisitBlockHelperExpression(BlockHelperExpression bhex)
        {
            var isInlinePartial = bhex.HelperName == "#*inline";

            var pathInfo       = CompilationContext.Configuration.PathInfoStore.GetOrAdd(bhex.HelperName);
            var bindingContext = Arg <BindingContext>(CompilationContext.BindingContext);
            var context        = isInlinePartial
                ? bindingContext.As <object>()
                : bindingContext.Property(o => o.Value);

            var readerContext = bhex.Context;
            var direct        = Compile(bhex.Body);
            var inverse       = Compile(bhex.Inversion);
            var arguments     = CreateArguments();

            var helperName  = pathInfo.TrimmedPath;
            var direction   = bhex.IsRaw || pathInfo.IsBlockHelper ? BlockHelperDirection.Direct : BlockHelperDirection.Inverse;
            var blockParams = CreateBlockParams();

            var blockHelpers = CompilationContext.Configuration.BlockHelpers;

            if (blockHelpers.TryGetValue(pathInfo, out var descriptor))
            {
                return(BindByRef(descriptor));
            }

            var helperResolvers = CompilationContext.Configuration.HelperResolvers;

            for (var index = 0; index < helperResolvers.Count; index++)
            {
                var resolver = helperResolvers[index];
                if (!resolver.TryResolveBlockHelper(helperName, out var resolvedDescriptor))
                {
                    continue;
                }

                return(Bind(resolvedDescriptor));
            }

            var lateBindBlockHelperDescriptor = new LateBindBlockHelperDescriptor(pathInfo, CompilationContext.Configuration);
            var lateBindBlockHelperRef        = new StrongBox <BlockHelperDescriptorBase>(lateBindBlockHelperDescriptor);

            blockHelpers.Add(pathInfo, lateBindBlockHelperRef);

            return(BindByRef(lateBindBlockHelperRef));

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

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

                return(Arg(parameters));
            }

            ExpressionContainer <object[]> CreateArguments()
            {
                var args = bhex.Arguments
                           .ApplyOn((PathExpression pex) => pex.Context = PathExpression.ResolutionContext.Parameter)
                           .Select(o => FunctionBuilder.Reduce(o, CompilationContext));

                return(Array <object>(args));
            }

            Action <BindingContext, TextWriter, object> Compile(Expression expression)
            {
                var blockExpression = (BlockExpression)expression;

                return(FunctionBuilder.CompileCore(blockExpression.Expressions, CompilationContext.Configuration));
            }

            Expression BindByRef(StrongBox <BlockHelperDescriptorBase> value)
            {
                return(direction switch
                {
                    BlockHelperDirection.Direct => Call(() =>
                                                        BlockHelperCallBindingByRef(bindingContext, context, blockParams, direct, inverse, arguments, value)),

                    BlockHelperDirection.Inverse => Call(() =>
                                                         BlockHelperCallBindingByRef(bindingContext, context, blockParams, inverse, direct, arguments, value)),

                    _ => throw new HandlebarsCompilerException("Helper referenced with unknown prefix", readerContext)
                });