예제 #1
0
        public static IEnumerator ConvertAnythingToIterator(TemplateFrame frame, object o)
        {
            o = ConvertAnythingIteratableToIterator(frame, o);

            IEnumerator iter = o as IEnumerator;
            if (iter != null)
                return iter;

            Template.AttributeList singleton = new Template.AttributeList(1);
            singleton.Add(o);
            return singleton.GetEnumerator();
        }
예제 #2
0
        // <names,phones:{n,p | ...}> or <a,b:t()>
        // todo: i, i0 not set unless mentioned? map:{k,v | ..}?
        protected virtual Template.AttributeList ZipMap(TemplateFrame frame, List<object> exprs, Template prototype)
        {
            Template self = frame.Template;

            if (exprs == null || prototype == null || exprs.Count == 0)
            {
                return null; // do not apply if missing templates or empty values
            }
            // make everything iterable
            for (int i = 0; i < exprs.Count; i++)
            {
                object attr = exprs[i];
                if (attr != null)
                    exprs[i] = ConvertAnythingToIterator(frame, attr);
            }

            // ensure arguments line up
            int numExprs = exprs.Count;
            CompiledTemplate code = prototype.impl;
            List<FormalArgument> formalArguments = code.FormalArguments;
            if (!code.HasFormalArgs || formalArguments == null)
            {
                _errorManager.RuntimeError(frame, ErrorType.MISSING_FORMAL_ARGUMENTS);
                return null;
            }

            // todo: track formal args not names for efficient filling of locals
            object[] formalArgumentNames = formalArguments.Select(i => i.Name).ToArray();
            int nformalArgs = formalArgumentNames.Length;
            if (prototype.IsAnonymousSubtemplate)
                nformalArgs -= predefinedAnonSubtemplateAttributes.Length;

            if (nformalArgs != numExprs)
            {
                _errorManager.RuntimeError(frame, ErrorType.MAP_ARGUMENT_COUNT_MISMATCH, numExprs, nformalArgs);
                // TODO just fill first n
                // truncate arg list to match smaller size
                int shorterSize = Math.Min(formalArgumentNames.Length, numExprs);
                numExprs = shorterSize;
                Array.Resize(ref formalArgumentNames, shorterSize);
            }

            // keep walking while at least one attribute has values

            Template.AttributeList results = new Template.AttributeList();
            int i2 = 0; // iteration number from 0
            while (true)
            {
                // get a value for each attribute in list; put into Template instance
                int numEmpty = 0;
                Template embedded = group.CreateStringTemplateInternally(prototype);
                embedded.RawSetAttribute("i0", i2);
                embedded.RawSetAttribute("i", i2 + 1);
                for (int a = 0; a < numExprs; a++)
                {
                    IEnumerator it = (IEnumerator)exprs[a];
                    if (it != null && it.MoveNext())
                    {
                        string argName = (string)formalArgumentNames[a];
                        object iteratedValue = it.Current;
                        embedded.RawSetAttribute(argName, iteratedValue);
                    }
                    else
                    {
                        numEmpty++;
                    }
                }

                if (numEmpty == numExprs)
                    break;

                results.Add(embedded);
                i2++;
            }
            return results;
        }