public static LiquidExpressionResult Eval(
            LiquidExpression expression,
            IEnumerable<Option<IExpressionConstant>> leaves, 
            ITemplateContext templateContext)
        {
            // calculate the first part of the expression
            var objResult = expression.Expression == null ? 
                LiquidExpressionResult.Success(new None<IExpressionConstant>()) : 
                expression.Expression.Eval(templateContext, leaves);

            if (objResult.IsError)
            {
                return objResult;
            }

            // Compose a chain of filters, making sure type-casting
            // is done between them.
            IEnumerable<Tuple<FilterSymbol, IFilterExpression>> filterExpressionTuples;
            try
            {
                filterExpressionTuples = expression.FilterSymbols.Select(symbol =>
                    new Tuple<FilterSymbol, IFilterExpression>(symbol, InstantiateFilter(templateContext, symbol)))
                    .ToList();
            }
            catch (Exception ex)
            {
                return LiquidExpressionResult.Error(ex.Message);
            }
            var erroringFilternames = filterExpressionTuples.Where(x => x.Item2 == null).Select(x => x.Item1).ToList();

            if (erroringFilternames.Any())
            {
                //throw new Exception("Missing filters..."); 
                //return ConstantFactory.CreateError<StringValue>();
                return LiquidExpressionResult.Error("Missing filters: " + String.Join(", ", erroringFilternames.Select(x => x.Name)));
            }

            var filterChain = FilterChain.CreateChain(
                objResult.GetType(),
                templateContext,
                filterExpressionTuples.Select(x => x.Item2));

            // apply the composed function to the object
            
            return filterChain(objResult.SuccessResult);

        }
 public void StartLiquidExpression(IExpressionDescription expressionDescription)
 {
     //Console.WriteLine("LiquidExpressionBuilder >>> PUSH");
     LiquidExpression liquidExpression = new LiquidExpression { Expression = expressionDescription };
     var child = new TreeNode<LiquidExpression>(liquidExpression);
   
     if (_liquidExpressionStack.Any())
     {
         //Console.WriteLine(" to " + _liquidExpressionStack.Peek());
         _liquidExpressionStack.Peek().AddChild(child);
     }
     else
     {
         //Console.WriteLine(" to ROOT ");
         _liquidExpressionTree = child;
     }
     _liquidExpressionStack.Push(child);
 }
 public void Visit(LiquidExpression liquidExpression)
 {
     _result += liquidExpression.ToString();
 }
 /// <summary>
 /// Process the object / filter chain
 /// </summary>
 /// <param name="liquidExpression"></param>
 public void Visit(LiquidExpression liquidExpression)
 {
     //Console.WriteLine("Visiting Object Expression ");
     LiquidExpressionEvaluator.Eval(liquidExpression, new List<Option<IExpressionConstant>>(), _templateContext)
         .WhenSuccess(x => x.WhenSome(some => AppendTextToCurrentAccumulator(Render(x.Value)))
                            .WhenNone(() => AppendTextToCurrentAccumulator("")))
         .WhenError(RenderError);
 }