private static object LateBindHelperExpression(BindingContext context, string helperName, object[] arguments)
        {
            var configuration = context.Configuration;

            if (configuration.Helpers.TryGetValue(helperName, out var helper))
            {
                using (var write = new PolledStringWriter(configuration.FormatProvider))
                {
                    helper(write, context.Value, arguments);
                    return(write.ToString());
                }
            }

            if (configuration.ReturnHelpers.TryGetValue(helperName, out var returnHelper))
            {
                return(returnHelper(context.Value, arguments));
            }

            var pureHelperName = helperName.Substring(1);

            foreach (var resolver in configuration.HelperResolvers)
            {
                if (resolver.TryResolveReturnHelper(pureHelperName, arguments.FirstOrDefault()?.GetType(), out returnHelper))
                {
                    return(returnHelper(context.Value, arguments));
                }
            }

            throw new HandlebarsRuntimeException($"Template references a helper that is not registered. Could not find helper '{helperName}'");
        }
        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 }));
            });
        }