public virtual void VisitForEachIn(BoundForEachIn node) { DefaultVisit(node); }
public override void VisitForEachIn(BoundForEachIn node) { // Rules for for each in: // * _branch becomes a fork and we create an empty fork; // * Target for break/continue. // Expression is executed on the default branch. Visit(node.Expression); MarkWrite(node.Target); var block = new Block(_branch, FindLabel(node), true, true, null); PushBlock(block); _branch = block.Branch.Fork(); Visit(node.Body); block.JoinBranch(_branch); // Create an empty branch to signal that the body is optional. block.JoinBranch(block.Branch.Fork()); PopBlock(block); }
public override void VisitForEachIn(BoundForEachIn node) { _scope.MarkWrite(node.Target, BoundValueType.String); base.VisitForEachIn(node); }
public override void VisitForEachIn(BoundForEachIn node) { var temporary = node.Target as BoundTemporary; if (temporary != null) { var statistic = GetStatistic(temporary); if (statistic.WriteState != WriteType.Local) statistic.WriteState = WriteType.DoNotRemove; } base.VisitForEachIn(node); }
private void EmitForEachIn(BoundForEachIn node) { // Create break and continue labels and push them onto the stack. var breakTarget = IL.DefineLabel(GetLabel(node)); _scope.BreakTargets.Push(breakTarget); var continueTarget = IL.DefineLabel(GetLabel(node)); _scope.ContinueTargets.Push(continueTarget); // Get the keys array. var keys = IL.DeclareLocal(typeof(object[])); _scope.EmitLoad(SpecialLocal.Runtime); EmitBox(EmitExpression(node.Expression)); IL.EmitCall(_runtimeGetForEachKeys); IL.Emit(OpCodes.Stloc, keys); // Declare the index local. var index = IL.DeclareLocal(typeof(int)); IL.EmitConstant(0); IL.Emit(OpCodes.Stloc, index); // Mark the start of the loop. IL.MarkLabel(continueTarget); // Test whether we're at the end of the loop. // Load the current index. IL.Emit(OpCodes.Ldloc, index); // Load the length of the array. IL.Emit(OpCodes.Ldloc, keys); IL.Emit(OpCodes.Ldlen); // (index >= keys.Length) -> breakTarget IL.Emit(OpCodes.Bge, breakTarget.Label); // Assign the current key to the target. EmitSetVariable( node.Target, new BoundEmitExpression( BoundValueType.Unknown, () => { // Load the element out of the index array. IL.Emit(OpCodes.Ldloc, keys); IL.Emit(OpCodes.Ldloc, index); IL.Emit(OpCodes.Ldelem_Ref); } ) ); // Increment the index. IL.Emit(OpCodes.Ldloc, index); IL.EmitConstant(1); IL.Emit(OpCodes.Add); IL.Emit(OpCodes.Stloc, index); // Emit the body. EmitStatement(node.Body); // Jump back to the beginning of the loop. IL.Emit(OpCodes.Br, continueTarget.Label); // Mark the end of the loop. IL.MarkLabel(breakTarget); // Pop the break and continue labels to make the previous ones available. _scope.BreakTargets.Pop(); _scope.ContinueTargets.Pop(); }