Example #1
0
		/// <include file='Doc/Nodes.xml' path='doc/method[@name="Emit"]/*'/>
		internal override PhpTypeCode Emit(CodeGenerator/*!*/ codeGenerator)
		{
#if !SILVERLIGHT
			Debug.Assert(access == AccessType.Read || access == AccessType.None);
			Statistics.AST.AddNode("ShellEx");

			// CALL Execution.ShellExec(<(string) command>);
			codeGenerator.EmitConversion(command, PhpTypeCode.String);
			codeGenerator.IL.Emit(OpCodes.Call, Methods.ShellExec);

			if (access == AccessType.None)
			{
				codeGenerator.IL.Emit(OpCodes.Pop);
				return PhpTypeCode.Void;
			}
#endif

			// ShellExec returns a string containing the standard output of executed command
			return PhpTypeCode.String;
		}
Example #2
0
		/// <summary>
		/// Emits dynamic inclusion.
		/// </summary>
		private PhpTypeCode EmitDynamicInclusion(CodeGenerator/*!*/ codeGenerator)
		{
			// do not generate dynamic auto inclusions:
			if (InclusionTypesEnum.IsAutoInclusion(inclusionType))
				return PhpTypeCode.Void;

			ILEmitter il = codeGenerator.IL;

			// CALL context.DynamicInclude(<file name>,<relative includer source path>,variables,self,includer);
			codeGenerator.EmitLoadScriptContext();
			codeGenerator.EmitConversion(fileNameEx, PhpTypeCode.String);
			il.Emit(OpCodes.Ldstr, codeGenerator.SourceUnit.SourceFile.RelativePath.ToString());
			codeGenerator.EmitLoadRTVariablesTable();
			codeGenerator.EmitLoadSelf();
			codeGenerator.EmitLoadClassContext();
			il.LoadLiteral(inclusionType);
			il.Emit(OpCodes.Call, Methods.ScriptContext.DynamicInclude);

			return PhpTypeCode.Object;
		}
Example #3
0
		/// <summary>
		/// Emits load of the name to the stack.
		/// </summary>
		internal override void EmitName(CodeGenerator codeGenerator)
		{
			codeGenerator.ChainBuilder.Create();
			codeGenerator.EmitConversion(this.VarNameEx, PhpTypeCode.String);
			codeGenerator.ChainBuilder.End();
		}
Example #4
0
		/// <summary>
		/// Emits binary boolean operation (AND or OR).
		/// </summary>
		/// <param name="codeGenerator">A code generator.</param>
		/// <param name="isAnd">Whether to emit AND.</param>
		/// <returns>A type code of the result.</returns>
		private PhpTypeCode EmitBinaryBooleanOperation(CodeGenerator codeGenerator, bool isAnd)
		{
			ILEmitter il = codeGenerator.IL;
			Label partial_eval_label = il.DefineLabel();
			Label end_label = il.DefineLabel();

			// IF [!]<(bool) leftSon> THEN GOTO partial_eval;
			codeGenerator.EmitConversion(leftExpr, PhpTypeCode.Boolean);
			il.Emit(isAnd ? OpCodes.Brfalse : OpCodes.Brtrue, partial_eval_label);

			// LOAD <(bool) leftSon>;
			codeGenerator.EmitConversion(rightExpr, PhpTypeCode.Boolean);

			il.Emit(OpCodes.Br, end_label);
			il.MarkLabel(partial_eval_label, true);
			il.LdcI4(isAnd ? 0 : 1);
			il.MarkLabel(end_label, true);

			return PhpTypeCode.Boolean;
		}
Example #5
0
		/// <remarks>
		/// Nothing is expected at the evaluation stack. If AST node is read by other node,
		/// the operation result is left at the stack, otherwise it is poped from the stack.
		/// </remarks>
		/// <include file='Doc/Nodes.xml' path='doc/method[@name="Emit"]/*'/>
		internal override PhpTypeCode Emit(CodeGenerator codeGenerator)
		{
			Debug.Assert(access == AccessType.None || access == AccessType.Read);
			Statistics.AST.AddNode("BinaryEx");

			PhpTypeCode returned_typecode;
			PhpTypeCode lo_typecode;
			PhpTypeCode ro_typecode;

			switch (operation)
			{
				#region Arithmetic Operations

				case Operations.Add:
					// Template: x + y : Operators.Add(x,y) [overloads]

                    switch (lo_typecode = leftExpr.Emit(codeGenerator))
                    {
                        case PhpTypeCode.Double:
                            switch (ro_typecode = rightExpr.Emit(codeGenerator))
                            {
                                case PhpTypeCode.Integer:
                                    codeGenerator.IL.Emit(OpCodes.Conv_R8);
                                    goto case PhpTypeCode.Double;   // fallback:
                                case PhpTypeCode.Double:
                                    codeGenerator.IL.Emit(OpCodes.Add);
                                    returned_typecode = PhpTypeCode.Double;
                                    break;
                                default:
                                    codeGenerator.EmitBoxing(ro_typecode);
                                    returned_typecode = codeGenerator.EmitMethodCall(Methods.Operators.Add.Double_Object);
                                    break;
                            }
                            
                            break;
                        default:
                            codeGenerator.EmitBoxing(lo_typecode);
                            ro_typecode = rightExpr.Emit(codeGenerator);

                            switch (ro_typecode)
                            {
                                case PhpTypeCode.Integer:
                                    returned_typecode = codeGenerator.EmitMethodCall(Methods.Operators.Add.Object_Int32);
                                    break;

                                case PhpTypeCode.Double:
                                    returned_typecode = codeGenerator.EmitMethodCall(Methods.Operators.Add.Object_Double);
                                    break;

                                default:
                                    codeGenerator.EmitBoxing(ro_typecode);
                                    returned_typecode = codeGenerator.EmitMethodCall(Methods.Operators.Add.Object_Object);
                                    break;
                            }
                            break;
                    }
                    break;

				case Operations.Sub:
					//Template: "x - y"        Operators.Subtract(x,y) [overloads]
					lo_typecode = leftExpr.Emit(codeGenerator);
                    switch (lo_typecode)
                    {
                        case PhpTypeCode.Integer:
                            codeGenerator.EmitBoxing(rightExpr.Emit(codeGenerator));
                            returned_typecode = codeGenerator.EmitMethodCall(Methods.Operators.Subtract.Int32_Object);
                            break;
                        case PhpTypeCode.Double:
                            switch (ro_typecode = rightExpr.Emit(codeGenerator))
                            {
                                case PhpTypeCode.Integer:
                                    codeGenerator.IL.Emit(OpCodes.Conv_R8);
                                    goto case PhpTypeCode.Double;   // fallback:
                                case PhpTypeCode.Double:
                                    codeGenerator.IL.Emit(OpCodes.Sub);
                                    returned_typecode = PhpTypeCode.Double;
                                    break;
                                default:
                                    codeGenerator.EmitBoxing(ro_typecode);
                                    returned_typecode = codeGenerator.EmitMethodCall(Methods.Operators.Subtract.Double_Object);
                                    break;
                            }
                            
                            break;
                        default:
                            codeGenerator.EmitBoxing(lo_typecode);
                            ro_typecode = rightExpr.Emit(codeGenerator);
                            if (ro_typecode == PhpTypeCode.Integer)
                            {
                                returned_typecode = codeGenerator.EmitMethodCall(Methods.Operators.Subtract.Object_Int);
                            }
                            else
                            {
                                codeGenerator.EmitBoxing(ro_typecode);
                                returned_typecode = codeGenerator.EmitMethodCall(Methods.Operators.Subtract.Object_Object);
                            }
                            break;
                    }
					break;

				case Operations.Div:
					//Template: "x / y"   Operators.Divide(x,y)

					lo_typecode = leftExpr.Emit(codeGenerator);
					switch (lo_typecode)
					{
						case PhpTypeCode.Integer:
							codeGenerator.EmitBoxing(rightExpr.Emit(codeGenerator));
							returned_typecode = codeGenerator.EmitMethodCall(Methods.Operators.Divide.Int32_Object);
							break;

						case PhpTypeCode.Double:
                            switch (ro_typecode = rightExpr.Emit(codeGenerator))
                            {
                                case PhpTypeCode.Double:
                                    codeGenerator.IL.Emit(OpCodes.Div);
                                    returned_typecode = PhpTypeCode.Double;
                                    break;
                                default:
                                    codeGenerator.EmitBoxing(ro_typecode);
                                    returned_typecode = codeGenerator.EmitMethodCall(Methods.Operators.Divide.Double_Object);
                                    break;
                            }
                            break;

						default:
							codeGenerator.EmitBoxing(lo_typecode);
							ro_typecode = rightExpr.Emit(codeGenerator);

							switch (ro_typecode)
							{
								case PhpTypeCode.Integer:
									returned_typecode = codeGenerator.EmitMethodCall(Methods.Operators.Divide.Object_Int32);
									break;

								case PhpTypeCode.Double:
									returned_typecode = codeGenerator.EmitMethodCall(Methods.Operators.Divide.Object_Double);
									break;

								default:
									codeGenerator.EmitBoxing(ro_typecode);
									returned_typecode = codeGenerator.EmitMethodCall(Methods.Operators.Divide.Object_Object);
									break;
							}
							break;
					}
					break;

				case Operations.Mul:
					switch (lo_typecode = leftExpr.Emit(codeGenerator))
                    {
                        case PhpTypeCode.Double:
                            // "x * (double)y"
                            // Operators.Multiply((double)x,(object)y)

                            switch (ro_typecode = rightExpr.Emit(codeGenerator))
                            {
                                case PhpTypeCode.Integer:
                                    codeGenerator.IL.Emit(OpCodes.Conv_R8);
                                    goto case PhpTypeCode.Double;   // fallback:
                                case PhpTypeCode.Double:
                                    codeGenerator.IL.Emit(OpCodes.Mul);
                                    returned_typecode = PhpTypeCode.Double;
                                    break;
                                default:
                                    codeGenerator.EmitBoxing(ro_typecode);
                                    returned_typecode = codeGenerator.EmitMethodCall(Methods.Operators.Multiply.Double_Object);
							        break;
                            }
                    
                            break;
                        default:
                            //Template: "x * y"  Operators.Multiply((object)x,y) [overloads]
                            codeGenerator.EmitBoxing(lo_typecode);

                            ro_typecode = rightExpr.Emit(codeGenerator);
					        switch (ro_typecode)
					        {
						        case PhpTypeCode.Integer:
							        returned_typecode = codeGenerator.EmitMethodCall(Methods.Operators.Multiply.Object_Int32);
							        break;

						        case PhpTypeCode.Double:
							        returned_typecode = codeGenerator.EmitMethodCall(Methods.Operators.Multiply.Object_Double);
							        break;

						        default:
							        codeGenerator.EmitBoxing(ro_typecode);
							        returned_typecode = codeGenerator.EmitMethodCall(Methods.Operators.Multiply.Object_Object);
							        break;
					        }
                            break;
                    }					
					break;

				case Operations.Mod:
					//Template: "x % y"        Operators.Remainder(x,y)
					codeGenerator.EmitBoxing(leftExpr.Emit(codeGenerator));
					ro_typecode = rightExpr.Emit(codeGenerator);
					switch (ro_typecode)
					{
						case PhpTypeCode.Integer:
							returned_typecode = codeGenerator.EmitMethodCall(Methods.Operators.Remainder.Object_Int32);
							break;

						default:
							codeGenerator.EmitBoxing(ro_typecode);
							returned_typecode = codeGenerator.EmitMethodCall(Methods.Operators.Remainder.Object_Object);
							break;
					}
					break;

				case Operations.ShiftLeft:

					// LOAD Operators.ShiftLeft(box left, box right);
					codeGenerator.EmitBoxing(leftExpr.Emit(codeGenerator));
					codeGenerator.EmitBoxing(rightExpr.Emit(codeGenerator));
					returned_typecode = codeGenerator.EmitMethodCall(Methods.Operators.ShiftLeft);
					break;

				case Operations.ShiftRight:

					// LOAD Operators.ShiftRight(box left, box right);
					codeGenerator.EmitBoxing(leftExpr.Emit(codeGenerator));
					codeGenerator.EmitBoxing(rightExpr.Emit(codeGenerator));
					returned_typecode = codeGenerator.EmitMethodCall(Methods.Operators.ShiftRight);
					break;

				#endregion

				#region Boolean and Bitwise Operations

				case Operations.And:
					returned_typecode = EmitBinaryBooleanOperation(codeGenerator, true);
					break;

				case Operations.Or:
					returned_typecode = EmitBinaryBooleanOperation(codeGenerator, false);
					break;

				case Operations.Xor:

					// LOAD <(bool) leftSon> == <(bool) rightSon>;
					codeGenerator.EmitConversion(leftExpr, PhpTypeCode.Boolean);
					codeGenerator.EmitConversion(rightExpr, PhpTypeCode.Boolean);
                    codeGenerator.IL.Emit(OpCodes.Ceq);

                    codeGenerator.IL.Emit(OpCodes.Ldc_I4_0);
                    codeGenerator.IL.Emit(OpCodes.Ceq);

					returned_typecode = PhpTypeCode.Boolean;
					break;

				case Operations.BitAnd:
					returned_typecode = EmitBitOperation(codeGenerator, Operators.BitOp.And);
					break;

				case Operations.BitOr:
					returned_typecode = EmitBitOperation(codeGenerator, Operators.BitOp.Or);
					break;

				case Operations.BitXor:
					returned_typecode = EmitBitOperation(codeGenerator, Operators.BitOp.Xor);
					break;

				#endregion

				#region Comparing Operations

				case Operations.Equal:

					// LOAD PhpComparer.Default.CompareEq
					returned_typecode = EmitComparison(codeGenerator, true);
					break;

				case Operations.NotEqual:

					// LOAD PhpComparer.Default.CompareEq == false
					EmitComparison(codeGenerator, true);
                    codeGenerator.IL.Emit(OpCodes.Ldc_I4_0);
                    codeGenerator.IL.Emit(OpCodes.Ceq);

					returned_typecode = PhpTypeCode.Boolean;
					break;

				case Operations.GreaterThan:

					// LOAD PhpComparer.Default.Compare > 0;
					EmitComparison(codeGenerator, false);
                    codeGenerator.IL.Emit(OpCodes.Ldc_I4_0);
                    codeGenerator.IL.Emit(OpCodes.Cgt);

					returned_typecode = PhpTypeCode.Boolean;
					break;

				case Operations.LessThan:

					// LOAD PhpComparer.Default.Compare < 0;
					EmitComparison(codeGenerator, false);
                    codeGenerator.IL.Emit(OpCodes.Ldc_I4_0);
                    codeGenerator.IL.Emit(OpCodes.Clt);

					returned_typecode = PhpTypeCode.Boolean;
					break;

				case Operations.GreaterThanOrEqual:

					// LOAD PhpComparer.Default.Compare >= 0 (not less than)
					EmitComparison(codeGenerator, false);
                    codeGenerator.IL.Emit(OpCodes.Ldc_I4_0);
                    codeGenerator.IL.Emit(OpCodes.Clt);
                    codeGenerator.IL.Emit(OpCodes.Ldc_I4_0);
                    codeGenerator.IL.Emit(OpCodes.Ceq);

					returned_typecode = PhpTypeCode.Boolean;
					break;

				case Operations.LessThanOrEqual:

					// LOAD PhpComparer.Default.Compare >= 0 (not greater than)
					EmitComparison(codeGenerator, false);
                    codeGenerator.IL.Emit(OpCodes.Ldc_I4_0);
                    codeGenerator.IL.Emit(OpCodes.Cgt);
                    codeGenerator.IL.Emit(OpCodes.Ldc_I4_0);
                    codeGenerator.IL.Emit(OpCodes.Ceq);

					returned_typecode = PhpTypeCode.Boolean;
					break;

				case Operations.Identical:

					// LOAD Operators.StrictEquality(box left,box right);
					codeGenerator.EmitBoxing(leftExpr.Emit(codeGenerator));
					codeGenerator.EmitBoxing(rightExpr.Emit(codeGenerator));
                    codeGenerator.IL.Emit(OpCodes.Call, Methods.Operators.StrictEquality);

					returned_typecode = PhpTypeCode.Boolean;
					break;

				case Operations.NotIdentical:

					// LOAD Operators.StrictEquality(box left,box right) == false;
					codeGenerator.EmitBoxing(leftExpr.Emit(codeGenerator));
					codeGenerator.EmitBoxing(rightExpr.Emit(codeGenerator));
                    codeGenerator.IL.Emit(OpCodes.Call, Methods.Operators.StrictEquality);
                    codeGenerator.IL.Emit(OpCodes.Ldc_I4_0);
                    codeGenerator.IL.Emit(OpCodes.Ceq);

					returned_typecode = PhpTypeCode.Boolean;
					break;

				#endregion

				case Operations.Concat:
					returned_typecode = ConcatEx.EmitConcat(codeGenerator, leftExpr, rightExpr);
					break;

				default:
					throw null;
			}

			switch (access)
			{
				case AccessType.Read:
					// Result is read, do nothing.
					break;

				case AccessType.None:
					// Result is not read, pop the result
                    codeGenerator.IL.Emit(OpCodes.Pop);
					returned_typecode = PhpTypeCode.Void;
					break;
			}

			return returned_typecode;
		}
Example #6
0
		internal override PhpTypeCode Emit(CodeGenerator/*!*/ codeGenerator)
		{
			LinqBuilder builder = codeGenerator.LinqBuilder;
			ILEmitter il = builder.IL;

			codeGenerator.EmitConversion(expression, PhpTypeCode.LinqSource);
			firstOp.Emit(builder);

			return PhpTypeCode.LinqSource;
		}
Example #7
0
		/// <include file='Doc/Nodes.xml' path='doc/method[@name="Emit"]/*'/>
		internal override PhpTypeCode Emit(CodeGenerator codeGenerator)
		{
			Statistics.AST.AddNode("TernaryEx");
			Debug.Assert(access == AccessType.Read || access == AccessType.None);

			Label end_label = codeGenerator.IL.DefineLabel();
			
            if (trueExpr != null)   // standard ternary operator
            {
                Label else_label = codeGenerator.IL.DefineLabel();
                
                // IF (<(bool) condition>) THEN
                codeGenerator.EmitConversion(condExpr, PhpTypeCode.Boolean);
                codeGenerator.IL.Emit(OpCodes.Brfalse, else_label);
                {
                    codeGenerator.EmitBoxing(trueExpr.Emit(codeGenerator));
                    codeGenerator.IL.Emit(OpCodes.Br, end_label);
                }
                // ELSE
                codeGenerator.IL.MarkLabel(else_label, true);
                {
                    codeGenerator.EmitBoxing(falseExpr.Emit(codeGenerator));
                }
            }
            else
            {   // ternary shortcut:
                var il = codeGenerator.IL;

                // condExpr ?? rightExpr

                il.EmitBoxing(condExpr.Emit(codeGenerator));
                
                // IF (<stack>):
                il.Emit(OpCodes.Dup);
                il.Emit(OpCodes.Call, Methods.Convert.ObjectToBoolean);

                codeGenerator.IL.Emit(OpCodes.Brtrue, end_label);
                // ELSE:
                {
                    il.Emit(OpCodes.Pop);
                    il.EmitBoxing(falseExpr.Emit(codeGenerator));                    
                }
            }

			// END IF;
			codeGenerator.IL.MarkLabel(end_label, true);


			if (access == AccessType.None)
			{
				codeGenerator.IL.Emit(OpCodes.Pop);
				return PhpTypeCode.Void;
			}

			return PhpTypeCode.Object;
		}
Example #8
0
		/// <include file='Doc/Nodes.xml' path='doc/method[@name="Emit"]/*'/>
		internal override void Emit(CodeGenerator codeGenerator)
		{
			Statistics.AST.AddNode("JumpStmt");

			// marks a sequence point:
			codeGenerator.MarkSequencePoint(
			  position.FirstLine,
			  position.FirstColumn,
			  position.LastLine,
			  position.LastColumn + 1);

			switch (type)
			{
				case Types.Break:
					// Emit simple break; - break the most inner loop
					if (expr == null)
					{
						codeGenerator.BranchingStack.EmitBreak();
					}
					else if (expr.HasValue)
					{
						// We can get the number at compile time and generate the right branch 
						// instruction for break x; where x is Literal
						codeGenerator.BranchingStack.EmitBreak(Convert.ObjectToInteger(expr.Value));
					}
					else
					{
						// In this case we emit the switch that decides where to branch at runtime.
						codeGenerator.EmitConversion(expr, PhpTypeCode.Integer);
						codeGenerator.BranchingStack.EmitBreakRuntime();
					}
					break;

				case Types.Continue:
					// Emit simple continue; - banch back to the condition of the most inner loop
					if (expr == null)
					{
						codeGenerator.BranchingStack.EmitContinue();
					}
					else if (expr.HasValue)
					{
						// We can get the number at compile time and generate the right branch 
						// instruction for continue x; where x is Literal
						codeGenerator.BranchingStack.EmitContinue(Convert.ObjectToInteger(expr.Value));
					}
					else
					{
						// In this case we emit the switch that decides where to branch at runtime.
						codeGenerator.EmitConversion(expr, PhpTypeCode.Integer);
						codeGenerator.BranchingStack.EmitContinueRuntime();
					}
					break;

				case Types.Return:
					if (codeGenerator.ReturnsPhpReference)
						EmitReturnPhpReference(codeGenerator);
					else
						EmitReturnObject(codeGenerator);
					break;

				default:
					throw null;
			}
		}