public static YieldTarget[] BuildYieldTargets(FuncDef func, CodeGen cg) { YieldLabelBuilder b = new YieldLabelBuilder(func, cg); func.Walk(b); return(b.topYields); }
private void EmitGenerator(CodeGen ncg) { YieldTarget[] targets = YieldLabelBuilder.BuildYieldTargets(this, ncg); Label[] jumpTable = new Label[yieldCount]; for (int i = 0; i < yieldCount; i++) { jumpTable[i] = targets[i].topBranchTarget; } ncg.yieldLabels = jumpTable; ncg.PushTryBlock(); ncg.BeginExceptionBlock(); ncg.Emit(OpCodes.Ldarg_0); ncg.EmitFieldGet(typeof(Generator), "location"); ncg.Emit(OpCodes.Switch, jumpTable); // fall-through on first pass // yield statements will insert the needed labels after their returns body.Emit(ncg); // fall-through is almost always possible in generators, so this // is almost always needed ncg.EmitReturnInGenerator(null); // special handling for StopIteration thrown in body ncg.BeginCatchBlock(typeof(StopIterationException)); ncg.EndExceptionBlock(); ncg.EmitReturnInGenerator(null); ncg.PopTargets(); ncg.Finish(); }