public virtual void PostWalk(ListCompIf node) { }
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); }
// ListCompIf public virtual bool Walk(ListCompIf node) { return(true); }