Пример #1
0
        public override void GenerateCode(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            // Get the previous root - we'll be changing it:
            Expression prevRoot = optimizationInfo.RootExpression;

            // Labelled is now the root:
            Labelled.SetRoot(optimizationInfo);

            if (Labelled.DefaultBreakStatementBehaviour)
            {
                // Set up the information needed by the break statement.
                ILLabel endOfStatement = generator.CreateLabel();
                optimizationInfo.PushBreakOrContinueInfo(labels, endOfStatement, null, true);

                Labelled.GenerateCode(generator, optimizationInfo);

                // Revert the information needed by the break statement.
                generator.DefineLabelPosition(endOfStatement);
                optimizationInfo.PopBreakOrContinueInfo();
            }
            else
            {
                // Loop, For-In, For-Of or Switch only.
                optimizationInfo.Labels = labels;
                Labelled.GenerateCode(generator, optimizationInfo);
            }

            // Restore root:
            optimizationInfo.RootExpression = prevRoot;
        }
Пример #2
0
        /// <summary>
        /// Generates CIL for the statement.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        public override void GenerateCode(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            List <string> labels = optimizationInfo.Labels;

            optimizationInfo.Labels = null;

            // We need a label for each case clause and one for the default case.
            var     jumpTargets  = new ILLabel[this.CaseClauses.Count];
            int     defaultIndex = -1;
            ILLabel endOfSwitch  = generator.CreateLabel();

            // Generate code for the switch value.
            var startOfSwitch = generator.CreateLabel();

            this.Value.GenerateCode(generator, optimizationInfo);
            EmitConversion.ToAny(generator, this.Value.GetResultType(optimizationInfo));

            // Save the switch value in a variable.
            var switchValue = generator.CreateTemporaryVariable(typeof(object));

            generator.StoreVariable(switchValue);

            for (int i = 0; i < this.CaseClauses.Count; i++)
            {
                var caseClause = this.CaseClauses[i];

                // Create a label for each clause.
                jumpTargets[i] = generator.CreateLabel();

                if (caseClause.Value == null)
                {
                    // This is a default clause.
                    defaultIndex = i;
                    continue;
                }

                // TypeComparer.StrictEquals(switchValue, caseValue)
                generator.LoadVariable(switchValue);
                caseClause.Value.GenerateCode(generator, optimizationInfo);
                EmitConversion.ToAny(generator, caseClause.Value.GetResultType(optimizationInfo));
                generator.Call(ReflectionHelpers.TypeComparer_StrictEquals);

                // if (TypeComparer.StrictEquals(switchValue, caseValue) == true)
                //	 goto case i
                generator.BranchIfTrue(jumpTargets[i]);
            }

            // None of the cases matched, jump to the default clause or the end of the switch.
            if (defaultIndex >= 0)
            {
                generator.Branch(jumpTargets[defaultIndex]);
            }
            else
            {
                generator.Branch(endOfSwitch);
            }

            // Get the previous root - we'll be changing it:
            Expression prevRoot = optimizationInfo.RootExpression;

            for (int i = 0; i < this.CaseClauses.Count; i++)
            {
                // Define a label at the start of the case clause.
                generator.DefineLabelPosition(jumpTargets[i]);

                // Set up the information needed by the break statement.
                optimizationInfo.PushBreakOrContinueInfo(labels, endOfSwitch, null, false);

                // Emit the case clause statements.
                foreach (var statement in this.CaseClauses[i].BodyStatements)
                {
                    // Mark as root:
                    statement.SetRoot(optimizationInfo);

                    // Emit:
                    statement.GenerateCode(generator, optimizationInfo);
                }

                // Revert the information needed by the break statement.
                optimizationInfo.PopBreakOrContinueInfo();
            }

            // Define a label for the end of the switch statement.
            generator.DefineLabelPosition(endOfSwitch);

            // Release the switch value variable for use elsewhere.
            generator.ReleaseTemporaryVariable(switchValue);

            // Restore root:
            optimizationInfo.RootExpression = prevRoot;
        }
Пример #3
0
        /// <summary>
        /// Generates CIL for the statement.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        public override void GenerateCode(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            // Get the previous root - we'll be changing it:
            Expression prevRoot = optimizationInfo.RootExpression;

            List <string> labels = optimizationInfo.Labels;

            optimizationInfo.Labels = null;

            // Construct a loop expression.
            // var enumerator = TypeUtilities.EnumeratePropertyNames(rhs).GetEnumerator();
            // while (true) {
            //   continue-target:
            //   if (enumerator.MoveNext() == false)
            //	 goto break-target;
            //   lhs = enumerator.Current;
            //
            //   <body statements>
            // }
            // break-target:

            // Call IEnumerable<string> EnumeratePropertyNames(ScriptEngine engine, object obj)
            // optimizationInfo.MarkSequencePoint(generator, this.TargetObjectSourceSpan);
            EmitHelpers.LoadEngine(generator);
            this.TargetObject.GenerateCode(generator, optimizationInfo);
            EmitConversion.ToAny(generator, this.TargetObject.GetResultType(optimizationInfo));
            generator.Call(ReflectionHelpers.TypeUtilities_EnumeratePropertyNames);

            // Store the enumerator in a temporary variable.
            var enumerator = generator.CreateTemporaryVariable(typeof(IEnumerator <string>));

            generator.StoreVariable(enumerator);

            var breakTarget    = generator.CreateLabel();
            var continueTarget = generator.DefineLabelPosition();

            // Emit debugging information.
            // if (optimizationInfo.DebugDocument != null)
            //  generator.MarkSequencePoint(optimizationInfo.DebugDocument, this.VariableSourceSpan);

            //   if (enumerator.MoveNext() == false)
            //	 goto break-target;
            generator.LoadVariable(enumerator);
            generator.Call(ReflectionHelpers.IEnumerator_MoveNext);
            generator.BranchIfFalse(breakTarget);

            // lhs = enumerator.Current;
            this.Variable.GenerateSet(generator, optimizationInfo, false, typeof(string), delegate(bool two){
                generator.LoadVariable(enumerator);
                generator.Call(ReflectionHelpers.IEnumerator_Current);

                if (two)
                {
                    generator.Duplicate();
                }
            }, false);



            // Emit the body statement(s).
            optimizationInfo.PushBreakOrContinueInfo(labels, breakTarget, continueTarget, false);

            // Mark the body as root:
            Body.SetRoot(optimizationInfo);

            Body.GenerateCode(generator, optimizationInfo);
            optimizationInfo.PopBreakOrContinueInfo();

            generator.Branch(continueTarget);
            generator.DefineLabelPosition(breakTarget);

            // Restore root:
            optimizationInfo.RootExpression = prevRoot;
        }
Пример #4
0
        /// <summary>
        /// Generates CIL for the statement.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        public override void GenerateCode(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            // Get the previous root - we'll be changing it:
            Expression prevRoot = optimizationInfo.RootExpression;

            List <string> labels = optimizationInfo.Labels;

            optimizationInfo.Labels = null;

            // Emit the initialization statement.
            if (InitStatement != null)
            {
                // Init isn't in use. Mark it as root:
                InitStatement.SetRoot(optimizationInfo);

                InitStatement.GenerateCode(generator, optimizationInfo);

                // Restore root:
                optimizationInfo.RootExpression = prevRoot;
            }

            var startOfLoop    = generator.DefineLabelPosition();
            var continueTarget = generator.CreateLabel();
            var endOfLoop      = generator.CreateLabel();

            bool conditionAtEnd = CheckConditionAtEnd;

            // AT END..
            // top:
            // <body statements>
            // continue:
            // <increment>
            // if(condition)
            // <goto top>
            // break:

            // top:
            // if(!condition)
            // <goto break>
            // <body statements>
            // continue:
            // <increment>
            // <goto top>
            // break:

            if (!conditionAtEnd)
            {
                if (ConditionStatement != null)
                {
                    Condition.GenerateCode(generator, optimizationInfo);
                    EmitConversion.ToBool(generator, Condition.GetResultType(optimizationInfo));
                    generator.BranchIfFalse(endOfLoop);
                }
            }

            // Emit the loop body.
            optimizationInfo.PushBreakOrContinueInfo(labels, endOfLoop, continueTarget, false);

            // Mark the body as root:
            Body.SetRoot(optimizationInfo);

            Body.GenerateCode(generator, optimizationInfo);
            optimizationInfo.PopBreakOrContinueInfo();

            generator.DefineLabelPosition(continueTarget);

            // Increment the loop variable.
            if (IncrementStatement != null)
            {
                // Increment isn't in use. Mark it as root:
                IncrementStatement.SetRoot(optimizationInfo);

                IncrementStatement.GenerateCode(generator, optimizationInfo);
            }

            // Restore root:
            optimizationInfo.RootExpression = prevRoot;

            if (conditionAtEnd)
            {
                if (ConditionStatement != null)
                {
                    // Emit now:
                    Condition.GenerateCode(generator, optimizationInfo);
                    EmitConversion.ToBool(generator, Condition.GetResultType(optimizationInfo));
                    generator.BranchIfTrue(startOfLoop);
                }
            }
            else
            {
                generator.Branch(startOfLoop);
            }

            generator.DefineLabelPosition(endOfLoop);
        }