コード例 #1
0
ファイル: LoopStmt.cs プロジェクト: gongfuPanada/Phalanger
        /// <include file='Doc/Nodes.xml' path='doc/method[@name="Emit"]/*'/>
        internal override void Emit(CodeGenerator codeGenerator)
        {
            Statistics.AST.AddNode("Loop.While");

            ILEmitter il         = codeGenerator.IL;
            Label     cond_label = il.DefineLabel();
            Label     exit_label = il.DefineLabel();
            Label     stat_label = il.DefineLabel();

            codeGenerator.BranchingStack.BeginLoop(cond_label, exit_label, codeGenerator.ExceptionBlockNestingLevel);

            if (this.type == Type.While)
            {
                il.Emit(OpCodes.Br, cond_label);
            }

            // body:
            il.MarkLabel(stat_label);
            body.Emit(codeGenerator);

            // marks a sequence point containing condition:
            codeGenerator.MarkSequencePoint(
                condExpr.Position.FirstLine,
                condExpr.Position.FirstColumn,
                condExpr.Position.LastLine,
                condExpr.Position.LastColumn + 1);

            // condition:
            il.MarkLabel(cond_label);

            // bounded loop:
            if (condExpr != null)
            {
                // IF (<(bool) condition>) GOTO stat;
                codeGenerator.EmitConversion(condExpr, PhpTypeCode.Boolean);
                il.Emit(OpCodes.Brtrue, stat_label);
            }

            il.MarkLabel(exit_label);
            codeGenerator.BranchingStack.EndLoop();

            il.ForgetLabel(cond_label);
            il.ForgetLabel(exit_label);
            il.ForgetLabel(stat_label);
        }
コード例 #2
0
        /// <include file='Doc/Nodes.xml' path='doc/method[@name="Emit"]/*'/>
        internal override void Emit(CodeGenerator /*!*/ codeGenerator)
        {
            Statistics.AST.AddNode("SwitchStmt");
            ILEmitter il = codeGenerator.IL;

            // Note:
            //  SwitchStmt is now implemented in the most general (and unefficient) way. The whole switch
            //  is understood as a series of if-elseif-else statements.

            Label        exit_label            = il.DefineLabel();
            bool         fall_through          = false;
            Label        fall_through_label    = il.DefineLabel();
            Label        last_default_label    = il.DefineLabel();
            DefaultItem  last_default          = GetLastDefaultItem();
            LocalBuilder branch_to_lastdefault = null;

            if (last_default != null)
            {
                branch_to_lastdefault = il.DeclareLocal(Types.Bool[0]);
                il.LdcI4(0);
                il.Stloc(branch_to_lastdefault);
            }

            codeGenerator.BranchingStack.BeginLoop(exit_label, exit_label,
                                                   codeGenerator.ExceptionBlockNestingLevel);

            // marks a sequence point containing the discriminator evaluation:
            codeGenerator.MarkSequencePoint(
                switchValue.Position.FirstLine,
                switchValue.Position.FirstColumn,
                switchValue.Position.LastLine,
                switchValue.Position.LastColumn + 1);

            // Evaluate condition value and store the result into local variable
            codeGenerator.EmitBoxing(switchValue.Emit(codeGenerator));
            LocalBuilder condition_value = il.DeclareLocal(Types.Object[0]);

            il.Stloc(condition_value);

            foreach (SwitchItem item in switchItems)
            {
                item.MarkSequencePoint(codeGenerator);

                // switch item is either CaseItem ("case xxx:") or DefaultItem ("default") item:
                CaseItem case_item = item as CaseItem;
                if (case_item != null)
                {
                    Label false_label = il.DefineLabel();

                    // PhpComparer.Default.CompareEq(<switch expr. value>,<case value>);
                    /*changed to static method*/ //il.Emit(OpCodes.Ldsfld, Fields.PhpComparer_Default);
                    codeGenerator.EmitCompareEq(
                        cg => { cg.IL.Ldloc(condition_value); return(PhpTypeCode.Object); },
                        cg => case_item.EmitCaseValue(cg));

                    // IF (!STACK) GOTO false_label;
                    il.Emit(OpCodes.Brfalse, false_label);
                    if (fall_through == true)
                    {
                        il.MarkLabel(fall_through_label, true);
                        fall_through = false;
                    }

                    case_item.EmitStatements(codeGenerator);

                    if (fall_through == false)
                    {
                        fall_through_label = il.DefineLabel();
                        fall_through       = true;
                    }

                    il.Emit(OpCodes.Br, fall_through_label);

                    il.MarkLabel(false_label, true);
                }
                else
                {
                    DefaultItem default_item = (DefaultItem)item;

                    // Only the last default branch defined in source code is used.
                    // So skip default while testing "case" items at runtime.
                    Label false_label = il.DefineLabel();
                    il.Emit(OpCodes.Br, false_label);

                    if (default_item == last_default)
                    {
                        il.MarkLabel(last_default_label, false);
                    }

                    if (fall_through == true)
                    {
                        il.MarkLabel(fall_through_label, true);
                        fall_through = false;
                    }

                    default_item.EmitStatements(codeGenerator);

                    if (fall_through == false)
                    {
                        fall_through_label = il.DefineLabel();
                        fall_through       = true;
                    }

                    il.Emit(OpCodes.Br, fall_through_label);
                    il.MarkLabel(false_label, true);
                }
            }

            // If no case branch matched, branch to last default case if any is defined
            if (last_default != null)
            {
                // marks a sequence point containing the condition evaluation or skip of the default case:
                codeGenerator.MarkSequencePoint(
                    last_default.Position.FirstLine,
                    last_default.Position.FirstColumn,
                    last_default.Position.LastLine,
                    last_default.Position.LastColumn + 1);

                Debug.Assert(branch_to_lastdefault != null);
                Label temp = il.DefineLabel();

                // IF (!branch_to_lastdefault) THEN
                il.Ldloc(branch_to_lastdefault);
                il.LdcI4(0);
                il.Emit(OpCodes.Bne_Un, temp);
                if (true)
                {
                    // branch_to_lastdefault = TRUE;
                    il.LdcI4(1);
                    il.Stloc(branch_to_lastdefault);

                    // GOTO last_default_label;
                    il.Emit(OpCodes.Br, last_default_label);
                }
                il.MarkLabel(temp, true);
                // END IF;

                il.ForgetLabel(last_default_label);
            }

            if (fall_through == true)
            {
                il.MarkLabel(fall_through_label, true);
            }

            il.MarkLabel(exit_label);
            codeGenerator.BranchingStack.EndLoop();
            il.ForgetLabel(exit_label);
        }
コード例 #3
0
ファイル: LoopStmt.cs プロジェクト: gongfuPanada/Phalanger
        /// <author>Tomas Matousek</author>
        /// <remarks>
        /// Emits the following code:
        /// <code>
        /// IPhpEnumerable enumerable = ARRAY as IPhpEnumerable;
        /// if (enumerable==null)
        /// {
        ///   PhpException.InvalidForeachArgument();
        /// }
        /// else
        /// FOREACH_BEGIN:
        /// {
        ///   IDictionaryEnumerator enumerator = enumerable.GetForeachEnumerator(KEYED,ALIASED,TYPE_HANDLE);
        ///
        ///   goto LOOP_TEST;
        ///   LOOP_BEGIN:
        ///   {
        ///     ASSIGN(value,enumerator.Value);
        ///     ASSIGN(key,enumerator.Key);
        ///
        ///     BODY;
        ///   }
        ///   LOOP_TEST:
        ///   if (enumerator.MoveNext()) goto LOOP_BEGIN;
        /// }
        /// FOREACH_END:
        /// </code>
        /// </remarks>
        /// <include file='Doc/Nodes.xml' path='doc/method[@name="Emit"]/*'/>
        internal override void Emit(CodeGenerator codeGenerator)
        {
            Statistics.AST.AddNode("Loop.Foreach");
            ILEmitter il = codeGenerator.IL;

            Label foreach_end   = il.DefineLabel();
            Label foreach_begin = il.DefineLabel();
            Label loop_begin    = il.DefineLabel();
            Label loop_test     = il.DefineLabel();

            codeGenerator.BranchingStack.BeginLoop(loop_test, foreach_end,
                                                   codeGenerator.ExceptionBlockNestingLevel);

            LocalBuilder enumerable = il.GetTemporaryLocal(typeof(IPhpEnumerable));

            // marks foreach "header" (the first part of the IL code):
            codeGenerator.MarkSequencePoint(
                enumeree.Position.FirstLine,
                enumeree.Position.FirstColumn,
                valueVariable.Position.LastLine,
                valueVariable.Position.LastColumn + 1);

            // enumerable = array as IPhpEnumerable;
            enumeree.Emit(codeGenerator);
            il.Emit(OpCodes.Isinst, typeof(IPhpEnumerable));
            il.Stloc(enumerable);

            // if (enumerable==null)
            il.Ldloc(enumerable);
            il.Emit(OpCodes.Brtrue, foreach_begin);
            {
                // CALL PhpException.InvalidForeachArgument();
                codeGenerator.EmitPhpException(Methods.PhpException.InvalidForeachArgument);
                il.Emit(OpCodes.Br, foreach_end);
            }
            // FOREACH_BEGIN:
            il.MarkLabel(foreach_begin);
            {
                LocalBuilder enumerator = il.GetTemporaryLocal(typeof(System.Collections.IDictionaryEnumerator));

                // enumerator = enumerable.GetForeachEnumerator(KEYED,ALIASED,TYPE_HANDLE);
                il.Ldloc(enumerable);
                il.LoadBool(keyVariable != null);
                il.LoadBool(valueVariable.Alias);
                codeGenerator.EmitLoadClassContext();
                il.Emit(OpCodes.Callvirt, Methods.IPhpEnumerable_GetForeachEnumerator);
                il.Stloc(enumerator);

                // goto LOOP_TEST;
                il.Emit(OpCodes.Br, loop_test);

                // LOOP_BEGIN:
                il.MarkLabel(loop_begin);
                {
                    // enumerator should do dereferencing and deep copying (if applicable):
                    // ASSIGN(value,enumerator.Value);
                    valueVariable.Emit(codeGenerator);
                    il.Ldloc(enumerator);
                    il.Emit(OpCodes.Callvirt, Properties.IDictionaryEnumerator_Value.GetGetMethod());
                    if (valueVariable.Alias)
                    {
                        il.Emit(OpCodes.Castclass, typeof(PhpReference));
                    }
                    valueVariable.EmitAssign(codeGenerator);

                    if (keyVariable != null)
                    {
                        // enumerator should do dereferencing and deep copying (if applicable):
                        // ASSIGN(key,enumerator.Key);
                        keyVariable.Emit(codeGenerator);
                        il.Ldloc(enumerator);
                        il.Emit(OpCodes.Callvirt, Properties.IDictionaryEnumerator_Key.GetGetMethod());
                        keyVariable.EmitAssign(codeGenerator);
                    }

                    // BODY:
                    body.Emit(codeGenerator);
                }
                // LOOP_TEST:
                il.MarkLabel(loop_test);

                // marks foreach "header" (the second part of the code):
                codeGenerator.MarkSequencePoint(
                    enumeree.Position.FirstLine,
                    enumeree.Position.FirstColumn,
                    valueVariable.Position.LastLine,
                    valueVariable.Position.LastColumn + 1);

                // if (enumerator.MoveNext()) goto LOOP_BEGIN;
                il.Ldloc(enumerator);
                il.Emit(OpCodes.Callvirt, Methods.IEnumerator_MoveNext);
                il.Emit(OpCodes.Brtrue, loop_begin);

                //
                il.ReturnTemporaryLocal(enumerator);
            }
            // FOREACH_END:
            il.MarkLabel(foreach_end);

            il.ReturnTemporaryLocal(enumerable);

            codeGenerator.BranchingStack.EndLoop();

            il.ForgetLabel(foreach_end);
            il.ForgetLabel(foreach_begin);
            il.ForgetLabel(loop_begin);
            il.ForgetLabel(loop_test);
        }