/// <summary>
        /// this calls the renderer with the astRenderer to render
        /// the block.
        /// </summary>
        public void Render(ForBlockTag forBlockTag, ITemplateContext templateContext)
        {
            var localBlockScope = new SymbolTable();
            templateContext.SymbolTableStack.Push(localBlockScope);
            try
            {
                var iterableFactory = forBlockTag.IterableCreator;

                // TODO: the Eval may result in an ArrayValue with no Array
                // (i.e. it's undefined).  THe ToList therefore fails....
                // this should use Bind
                var iterable = iterableFactory.Eval(templateContext).ToList();

                if (forBlockTag.Reversed.BoolValue)
                {
                    iterable.Reverse(); // stupid thing does it in-place.
                }
                IterateBlock(forBlockTag, templateContext, iterable);
            }
            finally
            {
                templateContext.SymbolTableStack.Pop();
            }
        }
 public void Visit(ForBlockTag forBlockTag)
 {
     _result += forBlockTag.ToString();
 }
        private void IterateBlock(ForBlockTag forBlockTag, ITemplateContext templateContext, List<IExpressionConstant> iterable)
        {
            var offset = NumericValue.Create(0);
            NumericValue limit = null;
            if (!templateContext.Options.NoForLimit)
            {
                limit = NumericValue.Create(50); // see: https://docs.shopify.com/themes/liquid-documentation/tags/iteration-tags#for             
            }
            if (forBlockTag.Offset != null)
            {
                var result = LiquidExpressionEvaluator.Eval(forBlockTag.Offset, templateContext);
                if (result.IsSuccess)
                {
                    offset = result.SuccessValue<NumericValue>();
                }
            }
            if (forBlockTag.Limit != null)
            {
                var result = LiquidExpressionEvaluator.Eval(forBlockTag.Limit, templateContext);
                if (result.IsSuccess)
                {
                    limit = result.SuccessValue<NumericValue>();
                }
            }

            var subset = iterable.Skip(offset.IntValue);
            if (limit != null)
            {
                subset = subset.Take(limit.IntValue);
            }
            var subsetList = subset.ToList();
            var length = subsetList.Count();
            if (length <= 0) 
            {
                _renderingVisitor.StartWalking(forBlockTag.ElseBlock);
                return;
            }

            int iter = 0;
            //foreach (var item in iterable.Skip(offset.IntValue).Take(limit.IntValue))
            foreach (var item in subsetList)
            {
                String typename = item == null ? "null" : item.LiquidTypeName;
                templateContext.SymbolTableStack.Define("forloop", CreateForLoopDescriptor(
                    forBlockTag.LocalVariable + "-" + typename, iter, length, templateContext.SymbolTableStack));
                templateContext.SymbolTableStack.Define(forBlockTag.LocalVariable, item);

                try
                {
                    _renderingVisitor.StartWalking(forBlockTag.LiquidBlock);
                }
                catch (ContinueException)
                {
                    continue;
                }
                catch (BreakException)
                {
                    break;
                }
                iter ++;
            }
        }
 public void Visit(ForBlockTag forBlockTag)
 {
     new ForRenderer(this).Render(forBlockTag, _templateContext);
 }