Beispiel #1
0
        /// <summary>
        /// Emits the try block and the catch blocks.
        /// </summary>
        /// <param name="codeGenerator">A code generator.</param>
        /// <remarks>
        /// <code>
        ///	try
        /// {
        ///   // guarded code //
        /// }
        /// catch(E1 $e1)
        /// {
        ///   // E1 //
        /// }
        /// catch(E2 $e2)
        /// {
        ///   // E2 //
        /// }
        /// </code>
        /// is translated as follows:
        /// <code>
        /// try
        /// {
        ///   // guarded code //
        /// }
        /// catch(PhpUserException _e)
        /// {
        ///   PhpObject _o = _e.UserException;
        ///   if (_o instanceOf E1)
        ///   {
        ///     $e1 = _o;
        ///     // E1 //
        ///   }
        ///   else if (_o instanceOf E2)
        ///   {
        ///     $e2 = _o;
        ///     // E2 //
        ///   }
        ///   else
        ///   {
        ///     throw;
        ///   }
        /// }
        /// </code>
        /// </remarks>
        internal override void Emit(CodeGenerator /*!*/ codeGenerator)
        {
            Statistics.AST.AddNode("TryStmt");

            // emit try block without CLR exception block if possible

            if (!HasCatches && !HasFinallyStatements)
            {
                this.Statements.Emit(codeGenerator);
                return;
            }

            // emit CLR exception block

            ILEmitter il = codeGenerator.IL;

            codeGenerator.ExceptionBlockNestingLevel++;

            // TRY
            Label end_label = il.BeginExceptionBlock();

            this.Statements.Emit(codeGenerator);

            // catches

            if (HasCatches)
            {
                // catch (PHP.Core.ScriptDiedException)
                // { throw; }

                il.BeginCatchBlock(typeof(PHP.Core.ScriptDiedException));
                il.Emit(OpCodes.Rethrow);

                // catch (System.Exception ex)

                il.BeginCatchBlock(typeof(System.Exception));

                // <exception_local> = (DObject) (STACK is PhpUserException) ? ((PhpUserException)STACK).UserException : ClrObject.WrapRealObject(STACK)

                Label        clrExceptionLabel = il.DefineLabel();
                Label        wrapEndLabel      = il.DefineLabel();
                LocalBuilder exception_local   = il.GetTemporaryLocal(typeof(DObject));

                il.Emit(OpCodes.Dup);
                il.Emit(OpCodes.Isinst, typeof(PHP.Core.PhpUserException)); // <STACK> as PhpUserException
                il.Emit(OpCodes.Brfalse, clrExceptionLabel);

                // if (<STACK> as PhpUserException != null)
                {
                    il.Emit(OpCodes.Ldfld, Fields.PhpUserException_UserException);
                    il.Emit(OpCodes.Br, wrapEndLabel);
                }

                // else
                il.MarkLabel(clrExceptionLabel);
                {
                    il.Emit(OpCodes.Call, Methods.ClrObject_WrapRealObject);
                }
                il.MarkLabel(wrapEndLabel);
                il.Stloc(exception_local);

                // emits all PHP catch-blocks processing into a single CLI catch-block:
                foreach (CatchItem c in catches)
                {
                    Label next_catch_label = il.DefineLabel();

                    // IF (exception <instanceOf> <type>);
                    c.Emit(codeGenerator, exception_local, end_label, next_catch_label);

                    // ELSE
                    il.MarkLabel(next_catch_label);
                }

                il.ReturnTemporaryLocal(exception_local);

                // emits the "else" branch invoked if the exceptions is not catched:
                il.Emit(OpCodes.Rethrow);
            }

            // finally

            if (HasFinallyStatements)
            {
                finallyItem.Emit(codeGenerator);
            }

            //
            il.EndExceptionBlock();

            codeGenerator.ExceptionBlockNestingLevel--;
        }