Exemplo n.º 1
0
        private Node RenderFold(
            Node n,
            IEnumerable <Node> folds,
            Stack <Configuration> configStack)
        {
            if (n.NodeKind == NodeKind.Config)
            {
                return(n);
            }

            Configuration conf;

            if (n.TryGetConfiguration(out conf))
            {
                Contract.Assert(configStack.Count > 0 && configStack.Peek() == conf);
                configStack.Pop();
            }

            if (folds.IsEmpty <Node>())
            {
                return(n);
            }
            else if (n.NodeKind == NodeKind.FuncTerm)
            {
                var rendered = folds.First <Node>() as Cnst;
                Contract.Assert(rendered != null && rendered.CnstKind == CnstKind.String);

                ImmutableCollection <Flag> flags;
                var pres = Factory.Instance.ParseDataTerm(rendered.GetStringValue(), out flags);
                Contract.Assert(pres == null || pres.Node.IsFuncOrAtom);

                result.AddFlags(flags);

                if (pres == null)
                {
                    result.Failed();
                    return(n);
                }
                else
                {
                    return(pres.Node);
                }
            }

            Node resultNode = n;
            //// TODO: This could be a performance bottle-neck if many children
            //// have children with quotations. In this case, a new ShallowClone
            //// function must implemented, which simultaneously replaces many children.
            bool mF, mC;
            int  pos = 0;

            using (var itF = folds.GetEnumerator())
            {
                using (var itC = n.Children.GetEnumerator())
                {
                    while ((mF = itF.MoveNext()) & (mC = itC.MoveNext()))
                    {
                        if (itF.Current != itC.Current)
                        {
                            resultNode = resultNode.ShallowClone(itF.Current, pos);
                        }

                        ++pos;
                    }

                    Contract.Assert(!mF && !mC);
                }
            }

            return(resultNode);
        }