Esempio n. 1
0
        /// <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);
		}
Esempio n. 2
0
		/// <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);
		}
Esempio n. 3
0
		/// <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);
		}
Esempio n. 4
0
		/// <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);
		}
Esempio n. 5
0
		/// <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();
		}