Ejemplo n.º 1
0
 public virtual void VisitForEachIn(BoundForEachIn node)
 {
     DefaultVisit(node);
 }
Ejemplo n.º 2
0
            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);
            }
Ejemplo n.º 3
0
            public override void VisitForEachIn(BoundForEachIn node)
            {
                _scope.MarkWrite(node.Target, BoundValueType.String);

                base.VisitForEachIn(node);
            }
Ejemplo n.º 4
0
            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);
            }
Ejemplo n.º 5
0
        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();
        }