/// <include file='Doc/Nodes.xml' path='doc/method[@name="Emit"]/*'/> internal override void Emit(CodeGenerator codeGenerator) { Statistics.AST.AddNode("IfStmt"); Debug.Assert(conditions.Count > 0); // marks a sequence point containing whole condition: codeGenerator.MarkSequencePoint(conditions[0].Condition); // NOTE: (J) when emitting a statement, sequence point has to be marked. Normally it is done in Statement.Emit() ILEmitter il = codeGenerator.IL; Label exit_label = il.DefineLabel(); Label false_label = il.DefineLabel(); // IF codeGenerator.EmitConversion(conditions[0].Condition, PhpTypeCode.Boolean); il.Emit(OpCodes.Brfalse, false_label); conditions[0].Statement.Emit(codeGenerator); codeGenerator.MarkSequencePoint( // (J) Mark the end of condition body so debugger will jump off the block properly conditions[0].Statement.Position.LastLine, conditions[0].Statement.Position.LastColumn, conditions[0].Statement.Position.LastLine, conditions[0].Statement.Position.LastColumn + 1); il.Emit(OpCodes.Br, exit_label); // ELSEIF: for (int i = 1; i < conditions.Count && conditions[i].Condition != null; i++) { il.MarkLabel(false_label, true); false_label = il.DefineLabel(); // IF (!<(bool) condition>) codeGenerator.MarkSequencePoint(conditions[i].Condition); // marks a sequence point of the condition "statement" codeGenerator.EmitConversion(conditions[i].Condition, PhpTypeCode.Boolean); il.Emit(OpCodes.Brfalse, false_label); conditions[i].Statement.Emit(codeGenerator); il.Emit(OpCodes.Br, exit_label); } il.MarkLabel(false_label, true); // ELSE if (conditions[conditions.Count - 1].Condition == null) conditions[conditions.Count - 1].Statement.Emit(codeGenerator); il.MarkLabel(exit_label, true); }
/// <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); }
/// <include file='Doc/Nodes.xml' path='doc/method[@name="Emit"]/*'/> internal override void Emit(CodeGenerator codeGenerator) { Statistics.AST.AddNode("Loop.For"); // Template: // we expand the for-statement // for (<expr1>; <expr2>; <expr3>) <loop body> // in the while form // { // <expr1>; // while (<expr2>) { // <loop body>; // <expr 3>; // } // } Label cond_label = codeGenerator.IL.DefineLabel(); Label iterate_label = codeGenerator.IL.DefineLabel(); Label exit_label = codeGenerator.IL.DefineLabel(); Label stat_label = codeGenerator.IL.DefineLabel(); codeGenerator.BranchingStack.BeginLoop(iterate_label, exit_label, codeGenerator.ExceptionBlockNestingLevel); // marks a sequence point containing initialization statements (if any): if (initExList.Count > 0) { codeGenerator.MarkSequencePoint( initExList[0].Position.FirstLine, initExList[0].Position.FirstColumn, initExList[initExList.Count - 1].Position.LastLine, initExList[initExList.Count - 1].Position.LastColumn + 1); } // Emit <expr1> foreach (Expression expr in initExList) expr.Emit(codeGenerator); // Branch unconditionally to the begin of condition evaluation codeGenerator.IL.Emit(OpCodes.Br, cond_label); // Emit loop body codeGenerator.IL.MarkLabel(stat_label); body.Emit(codeGenerator); codeGenerator.IL.MarkLabel(iterate_label); // marks a sequence point containing action statements (if any): if (actionExList.Count > 0) { codeGenerator.MarkSequencePoint( actionExList[0].Position.FirstLine, actionExList[0].Position.FirstColumn, actionExList[actionExList.Count - 1].Position.LastLine, actionExList[actionExList.Count - 1].Position.LastColumn + 1); } // Emit <expr3> foreach (Expression expr in actionExList) expr.Emit(codeGenerator); // marks a sequence point containing condition (if any): if (condExList.Count > 0) { codeGenerator.MarkSequencePoint( condExList[0].Position.FirstLine, condExList[0].Position.FirstColumn, condExList[condExList.Count - 1].Position.LastLine, condExList[condExList.Count - 1].Position.LastColumn + 1); } // Emit <expr2> codeGenerator.IL.MarkLabel(cond_label); if (condExList.Count > 0) { for (int i = 0; i < (condExList.Count - 1); i++) condExList[i].Emit(codeGenerator); // LOAD <(bool) condition> codeGenerator.EmitConversion(condExList[condExList.Count - 1], PhpTypeCode.Boolean); } else codeGenerator.IL.LdcI4(1); codeGenerator.IL.Emit(OpCodes.Brtrue, stat_label); codeGenerator.IL.MarkLabel(exit_label); codeGenerator.BranchingStack.EndLoop(); codeGenerator.IL.ForgetLabel(cond_label); codeGenerator.IL.ForgetLabel(iterate_label); codeGenerator.IL.ForgetLabel(exit_label); codeGenerator.IL.ForgetLabel(stat_label); }
/// <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); }
/// <include file='Doc/Nodes.xml' path='doc/method[@name="Emit"]/*'/> internal void Emit(CodeGenerator/*!*/ codeGenerator) { // TODO: improve codeGenerator.EnterGlobalCodeDeclaration(this.varTable, labels, sourceUnit); // custom body prolog emittion: PluginHandler.EmitBeforeBody(codeGenerator.IL, statements); // if (codeGenerator.CompilationUnit.IsTransient) { codeGenerator.DefineLabels(labels); codeGenerator.ChainBuilder.Create(); foreach (Statement statement in statements) statement.Emit(codeGenerator); codeGenerator.ChainBuilder.End(); // return + appended file emission: codeGenerator.EmitRoutineEpilogue(this, true); } #if !SILVERLIGHT else if (codeGenerator.CompilationUnit.IsPure) { codeGenerator.ChainBuilder.Create(); foreach (Statement statement in statements) { // skip empty statements in global code (they emit sequence points, which is undesirable): if (!(statement is EmptyStmt)) statement.Emit(codeGenerator); } codeGenerator.ChainBuilder.End(); } else { ScriptCompilationUnit unit = (ScriptCompilationUnit)codeGenerator.CompilationUnit; ILEmitter il = codeGenerator.IL; if (codeGenerator.Context.Config.Compiler.Debug) { codeGenerator.MarkSequencePoint(1, 1, 1, 2); il.Emit(OpCodes.Nop); } codeGenerator.DefineLabels(labels); // CALL <self>.<Declare>(context); codeGenerator.EmitLoadScriptContext(); il.Emit(OpCodes.Call, unit.ScriptBuilder.DeclareHelperBuilder); // IF (<is main script>) CALL <prepended script>.Main() if (prependedInclusion != null) prependedInclusion.Emit(codeGenerator); codeGenerator.ChainBuilder.Create(); foreach (Statement statement in statements) statement.Emit(codeGenerator); codeGenerator.ChainBuilder.End(); // return + appended file emission: codeGenerator.EmitRoutineEpilogue(this, false); } #endif codeGenerator.LeaveGlobalCodeDeclaration(); }