Compile() public method

public Compile ( IEnumerable expressions, string templatePath = null ) : object>.Action
expressions IEnumerable
templatePath string
return object>.Action
Beispiel #1
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)
            })));
        }
        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);
     }
 }
Beispiel #4
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));
            }
        }
Beispiel #5
0
        protected override Expression VisitPartialExpression(PartialExpression pex)
        {
            Expression bindingContext = CompilationContext.BindingContext;

            var fb = new FunctionBuilder(CompilationContext.Configuration);
            var partialBlockTemplate = pex.Fallback == null ? null : fb.Compile(new[] { pex.Fallback }, null, null);

            if (pex.Argument != null || partialBlockTemplate != null)
            {
                bindingContext = Expression.Call(
                    bindingContext,
                    typeof(BindingContext).GetMethod("CreateChildContext"),
                    pex.Argument ?? Expression.Constant(null),
                    partialBlockTemplate ?? Expression.Constant(null, typeof(Action <TextWriter, object>)));
            }

            var partialInvocation = Expression.Call(
#if netstandard
                new Action <string, BindingContext, HandlebarsConfiguration>(InvokePartialWithFallback).GetMethodInfo(),
#else
                new Action <string, BindingContext, HandlebarsConfiguration>(InvokePartialWithFallback).Method,
#endif
                Expression.Convert(pex.PartialName, typeof(string)),
                bindingContext,
                Expression.Constant(CompilationContext.Configuration));

            return(partialInvocation);
        }
        public Action <TextWriter, object> Compile(TextReader source)
        {
            var tokens      = _tokenizer.Tokenize(source).ToList();
            var expressions = _expressionBuilder.ConvertTokensToExpressions(tokens);

            return(_functionBuilder.Compile(expressions));
        }
        protected override Expression VisitIteratorExpression(IteratorExpression iex)
        {
            var context = CompilationContext.Args.BindingContext;
            var writer  = CompilationContext.Args.EncodedWriter;

            var template = FunctionBuilder.Compile(new[] { iex.Template }, CompilationContext.Configuration);
            var ifEmpty  = FunctionBuilder.Compile(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, writer, blockParamsValues, compiledSequence, template, ifEmpty)
                        ));

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

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

                return(Arg(parameters));
            }
        }
Beispiel #8
0
        protected override Expression VisitPartialExpression(PartialExpression pex)
        {
            var bindingContext = CompilationContext.Args.BindingContext;
            var writer = CompilationContext.Args.EncodedWriter;
            
            var partialBlockTemplate = pex.Fallback != null 
                ? FunctionBuilder.Compile(new[] { pex.Fallback }, new CompilationContext(CompilationContext)) 
                : null;

            if (pex.Argument != null || partialBlockTemplate != null)
            {
                var value = pex.Argument != null
                    ? Arg<object>(FunctionBuilder.Reduce(pex.Argument, CompilationContext))
                    : bindingContext.Property(o => o.Value);
                
                var partialTemplate = Arg(partialBlockTemplate);
                bindingContext = bindingContext.Call(o => o.CreateChildContext(value, partialTemplate));
            }

            var partialName = Cast<string>(pex.PartialName);
            var configuration = Arg(CompilationContext.Configuration);
            return Call(() =>
                InvokePartialWithFallback(partialName, bindingContext, writer, (ICompiledHandlebarsConfiguration) configuration)
            );
        }
        internal Action <TextWriter, object> CompileView(string templatePath,
                                                         InternalHandlebarsConfiguration configuration)
        {
            var fs = _configuration.FileSystem;

            if (fs == null)
            {
                throw new InvalidOperationException("Cannot compile view when configuration.FileSystem is not set");
            }
            var template = fs.GetFileContent(templatePath);

            if (template == null)
            {
                throw new InvalidOperationException("Cannot find template at '" + templatePath + "'");
            }
            IEnumerable <object> tokens;

            using (var sr = new StringReader(template))
            {
                using (var reader = new ExtendedStringReader(sr))
                {
                    tokens = Tokenizer.Tokenize(reader).ToList();
                }
            }

            var layoutToken = tokens.OfType <LayoutToken>().SingleOrDefault();

            var expressionBuilder = new ExpressionBuilder(configuration);
            var expressions       = expressionBuilder.ConvertTokensToExpressions(tokens);
            var compiledView      = FunctionBuilder.Compile(expressions, configuration, templatePath);

            if (layoutToken == null)
            {
                return(compiledView);
            }

            var layoutPath = fs.Closest(templatePath, layoutToken.Value + ".hbs");

            if (layoutPath == null)
            {
                throw new InvalidOperationException("Cannot find layout '" + layoutPath + "' for template '" +
                                                    templatePath + "'");
            }

            var compiledLayout = CompileView(layoutPath, configuration);

            return((tw, vm) =>
            {
                string inner;
                using (var innerWriter = new PolledStringWriter(configuration.FormatProvider))
                {
                    compiledView(innerWriter, vm);
                    inner = innerWriter.ToString();
                }

                compiledLayout(tw, new DynamicViewModel(new[] { new { body = inner }, vm }));
            });
        }
 private Expression GetEnumerableIterator(Expression contextParameter, IteratorExpression iex)
 {
     var fb = new FunctionBuilder(CompilationContext.Configuration);
     return Expression.Block(
         Expression.Assign(contextParameter,
             Expression.New(
                 typeof(IteratorBindingContext).GetConstructor(new[] { typeof(BindingContext) }),
                 new Expression[] { CompilationContext.BindingContext })),
         Expression.Call(
             new Action<IteratorBindingContext, IEnumerable, Action<TextWriter, object>, Action<TextWriter, object>>(Iterate).Method,
             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) 
             }));
 }
        private Expression[] GetDeferredSectionTemplates(DeferredSectionExpression dsex)
        {
            var fb = new FunctionBuilder(CompilationContext.Configuration);
            var body = fb.Compile(dsex.Body.Expressions, CompilationContext.BindingContext);
            var inversion = fb.Compile(dsex.Inversion.Expressions, CompilationContext.BindingContext);

            var sectionPrefix = dsex.Path.Path.Substring(0, 1);

            switch (sectionPrefix)
            {
                case "#":
                    return new[] {body, inversion};
                case "^":
                    return new[] {inversion, body};
                default:
                    throw new HandlebarsCompilerException("Tried to compile a section expression that did not begin with # or ^");
            }
        }
Beispiel #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)
            })));
        }
        private Expression[] GetDeferredSectionTemplates(DeferredSectionExpression dsex)
        {
            var fb        = new FunctionBuilder(CompilationContext.Configuration);
            var body      = fb.Compile(dsex.Body.Expressions, CompilationContext.BindingContext);
            var inversion = fb.Compile(dsex.Inversion.Expressions, CompilationContext.BindingContext);

            var sectionPrefix = dsex.Path.Path.Substring(0, 1);

            switch (sectionPrefix)
            {
            case "#":
                return(new[] { body, inversion });

            case "^":
                return(new[] { inversion, body });

            default:
                throw new HandlebarsCompilerException("Tried to compile a section expression that did not begin with # or ^");
            }
        }
Beispiel #14
0
        protected override Expression VisitPartialExpression(PartialExpression pex)
        {
            Expression bindingContext = CompilationContext.BindingContext;

            if (pex.Argument != null)
            {
                bindingContext = Expression.Call(
                    bindingContext,
                    typeof(BindingContext).GetMethod("CreateChildContext"),
                    pex.Argument);
            }

            var fb = new FunctionBuilder(CompilationContext.Configuration);
            var partialBlockTemplate =
                fb.Compile(pex.Fallback != null ? new[] { pex.Fallback } : Enumerable.Empty <Expression>(), bindingContext);

            var partialInvocation = Expression.Call(
#if netstandard
                new Func <string, BindingContext, HandlebarsConfiguration, Action <TextWriter, object>, bool>(InvokePartial).GetMethodInfo(),
#else
                new Func <string, BindingContext, HandlebarsConfiguration, Action <TextWriter, object>, bool>(InvokePartial).Method,
#endif
                Expression.Convert(pex.PartialName, typeof(string)),
                bindingContext,
                Expression.Constant(CompilationContext.Configuration),
                partialBlockTemplate);

            var fallback = pex.Fallback;

            if (fallback == null)
            {
                fallback = Expression.Call(
#if netstandard
                    new Action <string>(HandleFailedInvocation).GetMethodInfo(),
#else
                    new Action <string>(HandleFailedInvocation).Method,
#endif
                    Expression.Convert(pex.PartialName, typeof(string)));
            }

            return(Expression.IfThen(
                       Expression.Not(partialInvocation),
                       fallback));
        }
Beispiel #15
0
        public static Action <TextWriter, object> Compile(ExtendedStringReader source, ICompiledHandlebarsConfiguration configuration)
        {
            var createdFeatures = configuration.Features;

            for (var index = 0; index < createdFeatures.Count; index++)
            {
                createdFeatures[index].OnCompiling(configuration);
            }

            var expressionBuilder = new ExpressionBuilder(configuration);
            var tokens            = Tokenizer.Tokenize(source).ToList();
            var expressions       = expressionBuilder.ConvertTokensToExpressions(tokens);
            var action            = FunctionBuilder.Compile(expressions, configuration);

            for (var index = 0; index < createdFeatures.Count; index++)
            {
                createdFeatures[index].CompilationCompleted();
            }

            return(action);
        }
Beispiel #16
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)
            });
        private Expression GetDynamicIterator(Expression contextParameter, IteratorExpression iex)
        {
            var fb = new FunctionBuilder(CompilationContext.Configuration);
            return Expression.Block(
                Expression.Assign(contextParameter,
                    Expression.New(
#if netstandard
                        typeof(ObjectEnumeratorBindingContext).GetTypeInfo().GetConstructor(new[] { typeof(BindingContext) }),
#else
                        typeof(ObjectEnumeratorBindingContext).GetConstructor(new[] { typeof(BindingContext) }),
#endif
                        new Expression[] { CompilationContext.BindingContext })),
                Expression.Call(
#if netstandard
                    new Action<ObjectEnumeratorBindingContext, IDynamicMetaObjectProvider, Action<TextWriter, object>, Action<TextWriter, object>>(Iterate).GetMethodInfo(),
#else
                    new Action<ObjectEnumeratorBindingContext, IDynamicMetaObjectProvider, Action<TextWriter, object>, Action<TextWriter, object>>(Iterate).Method,
#endif
                    new Expression[]
                    {
                        Expression.Convert(contextParameter, typeof(ObjectEnumeratorBindingContext)),
                        Expression.Convert(iex.Sequence, typeof(IDynamicMetaObjectProvider)),
                        fb.Compile(new [] { iex.Template }, contextParameter),
                        fb.Compile(new [] { iex.IfEmpty }, CompilationContext.BindingContext) 
                    }));
        }
        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)));
            }
        }
    }