/// <summary> /// Emits the catch-block. /// </summary> /// <param name="codeGenerator">A code generator.</param> /// <param name="exceptionLocal">A local variable containing an instance of <see cref="Library.SPL.Exception"/>.</param> /// <param name="endLabel">A label in IL stream where the processing of the try-catch blocks ends.</param> /// <param name="nextCatchLabel">A label in IL stream where the next catch block processing begins.</param> internal void Emit(CodeGenerator /*!*/ codeGenerator, LocalBuilder /*!*/ exceptionLocal, Label endLabel, Label nextCatchLabel) { ILEmitter il = codeGenerator.IL; codeGenerator.MarkSequencePoint( variable.Position.FirstLine, variable.Position.FirstColumn, variable.Position.LastLine, variable.Position.LastColumn + 1 ); // IF !InstanceOf(<class name>) GOTO next_catch; il.Ldloc(exceptionLocal); resolvedType.EmitInstanceOf(codeGenerator, null); il.Emit(OpCodes.Brfalse, nextCatchLabel); // variable = exception; variable.Emit(codeGenerator); il.Ldloc(exceptionLocal); variable.EmitAssign(codeGenerator); foreach (Statement statement in statements) { statement.Emit(codeGenerator); } // LEAVE end; il.Emit(OpCodes.Leave, endLabel); }
/// <summary> /// Emits type hint test on the argument if specified. /// </summary> internal void EmitTypeHintTest(CodeGenerator /*!*/ codeGenerator) { int real_index = routine.FirstPhpParameterIndex + index; // not type hint specified: if (typeHint == null) { return; } Debug.Assert(resolvedTypeHint != null); ILEmitter il = codeGenerator.IL; Label endif_label = il.DefineLabel(); // IF (DEREF(ARG[argIdx]) is not of hint type) THEN il.Ldarg(real_index); if (PassedByRef) { il.Emit(OpCodes.Ldfld, Fields.PhpReference_Value); } resolvedTypeHint.EmitInstanceOf(codeGenerator, null); il.Emit(OpCodes.Brtrue, endif_label); // add a branch allowing null values if the argument is optional with null default value (since PHP 5.1.0); if (initValue != null && initValue.HasValue && initValue.Value == null) { // IF (DEREF(ARG[argIdx]) != null) THEN il.Ldarg(real_index); if (PassedByRef) { il.Emit(OpCodes.Ldfld, Fields.PhpReference_Value); } il.Emit(OpCodes.Brfalse, endif_label); } // CALL PhpException.InvalidArgumentType(<param_name>, <class_name>); il.Emit(OpCodes.Ldstr, name.ToString()); il.Emit(OpCodes.Ldstr, resolvedTypeHint.FullName); codeGenerator.EmitPhpException(Methods.PhpException.InvalidArgumentType); // END IF; // END IF; il.MarkLabel(endif_label); }
/// <summary> /// Emits the catch-block. /// </summary> /// <param name="node">Instance.</param> /// <param name="codeGenerator">A code generator.</param> /// <param name="exceptionLocal">A local variable containing an instance of <see cref="Library.SPL.Exception"/>.</param> /// <param name="endLabel">A label in IL stream where the processing of the try-catch blocks ends.</param> /// <param name="nextCatchLabel">A label in IL stream where the next catch block processing begins.</param> public void Emit(CatchItem /*!*/ node, CodeGenerator /*!*/ codeGenerator, LocalBuilder /*!*/ exceptionLocal, Label endLabel, Label nextCatchLabel) { ILEmitter il = codeGenerator.IL; codeGenerator.MarkSequencePoint(node.Variable); // IF !InstanceOf(<class name>) GOTO next_catch; il.Ldloc(exceptionLocal); resolvedType.EmitInstanceOf(codeGenerator, null); il.Emit(OpCodes.Brfalse, nextCatchLabel); // variable = exception; node.Variable.Emit(codeGenerator); il.Ldloc(exceptionLocal); SimpleVarUseHelper.EmitAssign(node.Variable, codeGenerator); node.Statements.Emit(codeGenerator); // LEAVE end; il.Emit(OpCodes.Leave, endLabel); }