コード例 #1
0
        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;
        }