public IEnumerable <string> Transform(ForNode item) { _EncounteredOutputStyleBlock = true; if (!(ShouldRender && _EncounteredOutputStyleBlock)) { yield break; } object?evalObj; if (item.Expression != null) { evalObj = Environment.Evaluation.EvaluateDynamic(item.Expression.Expression, Scopes); } else { evalObj = item.AlreadyEvaluatedObject; } Func <object?[], object?> loopFunction = args => { if (args?.Length != 1) { throw new NotImplementedException(); } return(new ForNode(item.PrimaryBlock, item.ElseBlock, item.VariableNames, args[0], item.Filter, item.Recursive, item.EndParsingNode, item.WhiteSpaceControl)); }; var arr = CollectionEx.ToArray(evalObj) ?? Array.Empty <object>(); if (item.Filter != null) { var filtered = new List <object?>(); foreach (var arrItem in arr) { var unpacked = ReflectionHelpers.Unpack(arrItem, item.VariableNames.Length); Scopes.Push($"ForNode | Filter: {item.Filter} Item: {arrItem}"); for (var i = 0; i < unpacked.Length; ++i) { Scopes.Current.DefineAndSetVariable(item.VariableNames[i], unpacked[i]); } var result = Environment.Evaluation.EvaluateDynamic(item.Filter.Expression, Scopes); Scopes.Pop($"ForNode | Filter: {item.Filter} Item: {arrItem}"); if (TypeCoercion.GetTruthy(result)) { filtered.Add(arrItem); } } arr = filtered.ToArray(); } if (arr.Length == 0 && item.ElseBlock != null) { foreach (var output in item.ElseBlock.Transform(this)) { yield return(output); } yield break; } var depth = 0; if (Scopes.Current.TryGetVariable <LoopInfo>("loop", out var previousLoopInfo) && previousLoopInfo != null) { depth = previousLoopInfo.depth0 + 1; } var loopInfo = new LoopInfo(arr, loopFunction, depth); for (var index = 0; index < arr.Length; ++index) { loopInfo.index0 = index; var arrItem = arr[index]; var unpacked = ReflectionHelpers.Unpack(arrItem, item.VariableNames.Length); Scopes.Push($"ForNode: {item.Expression} Item: {arrItem}"); for (var i = 0; i < unpacked.Length; ++i) { Scopes.Current.DefineAndSetVariable(item.VariableNames[i], unpacked[i]); } Scopes.Current.DefineAndSetVariable("loop", loopInfo); foreach (var output in item.PrimaryBlock.Transform(this)) { yield return(output); } Scopes.Pop($"ForNode: {item.Expression} Item: {arrItem}"); } yield break; }