Пример #1
0
        public override void Emit(CodeGen cg)
        {
            Slot list = cg.GetLocalTmp(typeof(List));

            cg.EmitCall(typeof(Ops), "MakeList", Type.EmptyTypes);
            list.EmitSet(cg);

            // first loop: how many For; initialize labels/slots
            int iFors = 0;

            foreach (ListCompIter iter in iters)
            {
                if (iter is ListCompFor)
                {
                    iFors++;
                }
            }

            Label[] continueTargets = new Label[iFors];
            Slot[]  enumerators     = new Slot[iFors];
            int     jIters          = iters.Length;

            Label[] exitTargets = new Label[jIters];

            for (int i = 0; i < iFors; i++)
            {
                continueTargets[i] = cg.DefineLabel();
                enumerators[i]     = cg.GetLocalTmp(typeof(IEnumerator));
            }
            for (int i = 0; i < jIters; i++)
            {
                exitTargets[i] = cg.DefineLabel();
            }

            // second loop: before emiting item
            iFors = jIters = 0;
            foreach (ListCompIter iter in iters)
            {
                if (iter is ListCompFor)
                {
                    ListCompFor cfor = iter as ListCompFor;
                    cfor.list.Emit(cg);
                    cg.EmitCall(typeof(Ops), "GetEnumerator");
                    enumerators[iFors].EmitSet(cg);

                    cg.MarkLabel(continueTargets[iFors]);

                    enumerators[iFors].EmitGet(cg);
                    cg.EmitCall(typeof(IEnumerator), "MoveNext", Type.EmptyTypes);
                    cg.Emit(OpCodes.Brfalse, exitTargets[jIters]);

                    enumerators[iFors].EmitGet(cg);
                    cg.EmitCall(typeof(IEnumerator).GetProperty("Current").GetGetMethod());

                    cfor.lhs.EmitSet(cg);
                    iFors++;
                }
                else if (iter is ListCompIf)
                {
                    ListCompIf cif = iter as ListCompIf;

                    cg.EmitTestTrue(cif.test);
                    cg.Emit(OpCodes.Brfalse, exitTargets[jIters]);
                }

                jIters++;
            }

            // append the item
            list.EmitGet(cg);
            this.item.Emit(cg);
            cg.EmitCall(typeof(List), "Append");

            // third loop: in reverse order
            iFors  = continueTargets.Length - 1;
            jIters = iters.Length - 1;
            while (jIters >= 0)
            {
                ListCompIter iter = iters[jIters];
                if (iter is ListCompFor)
                {
                    cg.Emit(OpCodes.Br, continueTargets[iFors]);
                    cg.FreeLocalTmp(enumerators[iFors]);
                    iFors--;
                }

                cg.MarkLabel(exitTargets[jIters]);
                jIters--;
            }

            list.EmitGet(cg);
            cg.FreeLocalTmp(list);
        }
Пример #2
0
 public virtual void PostWalk(ListCompFor node)
 {
 }
Пример #3
0
 // ListCompFor
 public override bool Walk(ListCompFor node)
 {
     node.lhs.Walk(define);
     return(true);
 }
Пример #4
0
 // ListCompFor
 public virtual bool Walk(ListCompFor node)
 {
     return(true);
 }