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

			ILEmitter il = codeGenerator.IL;

			PhpTypeCode returned_typecode, o_typecode;

			switch (operation)
			{
				case Operations.AtSign:	// special arrangement
					// Template:
					//		context.DisableErrorReporting();
					//		s;
					//		context.EnableErrorReporting();
					codeGenerator.EmitLoadScriptContext();
					il.Emit(OpCodes.Call, Methods.ScriptContext.DisableErrorReporting);
					returned_typecode = expr.Emit(codeGenerator);
					codeGenerator.EmitLoadScriptContext();
					il.Emit(OpCodes.Call, Methods.ScriptContext.EnableErrorReporting);
					break;

				case Operations.BitNegation:
					//Template: "~x" Operators.BitNot(x)                                     
					codeGenerator.EmitBoxing(expr.Emit(codeGenerator));
					il.Emit(OpCodes.Call, Methods.Operators.BitNot);
					returned_typecode = PhpTypeCode.Object;
					break;

				case Operations.Clone:
					// Template: clone x        Operators.Clone(x,DTypeDesc,ScriptContext)
					codeGenerator.EmitBoxing(expr.Emit(codeGenerator));
					codeGenerator.EmitLoadClassContext();
					codeGenerator.EmitLoadScriptContext();
					il.Emit(OpCodes.Call, Methods.Operators.Clone);
					returned_typecode = PhpTypeCode.Object;
					break;

				case Operations.LogicNegation:
					//Template: "!x"  !Convert.ObjectToBoolean(x);                              
                    if (((returned_typecode = expr.Emit(codeGenerator)) != PhpTypeCode.Boolean))
                    {
                        codeGenerator.EmitBoxing(returned_typecode);
                        il.Emit(OpCodes.Call, Methods.Convert.ObjectToBoolean);
                    }
					il.Emit(OpCodes.Ldc_I4_0);
					il.Emit(OpCodes.Ceq);
					returned_typecode = PhpTypeCode.Boolean;
					break;

				case Operations.Minus:
					//Template: "-x"  Operators.Minus(x)
                    switch (o_typecode = expr.Emit(codeGenerator))
                    {
                        case PhpTypeCode.Double:
                            il.Emit(OpCodes.Neg);
                            returned_typecode = PhpTypeCode.Double;
                            break;
                        default:
					        codeGenerator.EmitBoxing(o_typecode);
                            returned_typecode = codeGenerator.EmitMethodCall(Methods.Operators.Minus);
					        break;
                    }
                    break;

				case Operations.ObjectCast:
					//Template: "(object)x"   Convert.ObjectToDObject(x,ScriptContext)
					codeGenerator.EmitBoxing(expr.Emit(codeGenerator));
					codeGenerator.EmitLoadScriptContext();
					il.Emit(OpCodes.Call, Methods.Convert.ObjectToDObject);
					returned_typecode = PhpTypeCode.Object;
					break;

				case Operations.Plus:
					//Template: "+x"  Operators.Plus(x)
					codeGenerator.EmitBoxing(expr.Emit(codeGenerator));
					il.Emit(OpCodes.Call, Methods.Operators.Plus);
					returned_typecode = PhpTypeCode.Object;
					break;

				case Operations.Print:
					codeGenerator.EmitEcho(this.expr);
					// Always returns 1
					il.Emit(OpCodes.Ldc_I4_1);
					returned_typecode = PhpTypeCode.Integer;
					break;

				case Operations.BoolCast:
					//Template: "(bool)x"     Convert.ObjectToBoolean(x)
                    if (((returned_typecode = expr.Emit(codeGenerator)) != PhpTypeCode.Boolean))
                    {
                        codeGenerator.EmitBoxing(returned_typecode);
                        il.Emit(OpCodes.Call, Methods.Convert.ObjectToBoolean);
                        returned_typecode = PhpTypeCode.Boolean;
                    }
					break;

				case Operations.Int8Cast:
				case Operations.Int16Cast:
				case Operations.Int32Cast:
				case Operations.UInt8Cast:
				case Operations.UInt16Cast:
					// CALL int Convert.ObjectToInteger(<expr>)
                    o_typecode = expr.Emit(codeGenerator);
                    if (o_typecode != PhpTypeCode.Integer)
                    {
                        codeGenerator.EmitBoxing(o_typecode);
                        il.Emit(OpCodes.Call, Methods.Convert.ObjectToInteger);
                    }

					// CONV for unsigned:
					switch (operation)
					{
						case Operations.UInt8Cast: il.Emit(OpCodes.Conv_U1); il.Emit(OpCodes.Conv_I4); break;
						case Operations.UInt16Cast: il.Emit(OpCodes.Conv_U2); il.Emit(OpCodes.Conv_I4); break;
					}

					returned_typecode = PhpTypeCode.Integer;
					break;

				case Operations.UInt64Cast:
				case Operations.UInt32Cast:
				case Operations.Int64Cast:
					// CALL long Convert.ObjectToLongInteger(<expr>)
                    o_typecode = expr.Emit(codeGenerator);
                    if (o_typecode != PhpTypeCode.LongInteger)
                    {
                        codeGenerator.EmitBoxing(o_typecode);
                        il.Emit(OpCodes.Call, Methods.Convert.ObjectToLongInteger);
                    }

					// CONV for unsigned:
					switch (operation)
					{
						case Operations.UInt32Cast: il.Emit(OpCodes.Conv_U4); il.Emit(OpCodes.Conv_I8); break;
						case Operations.UInt64Cast: il.Emit(OpCodes.Conv_U8); il.Emit(OpCodes.Conv_I8); break;
					}

					returned_typecode = PhpTypeCode.LongInteger;
					break;

				case Operations.DecimalCast:
				case Operations.DoubleCast:
				case Operations.FloatCast:
					// CALL double Convert.ObjectToDouble(<expr>)
                    o_typecode = expr.Emit(codeGenerator);
                    if (o_typecode != PhpTypeCode.Double)
                    {
                        codeGenerator.EmitBoxing(o_typecode);
                        il.Emit(OpCodes.Call, Methods.Convert.ObjectToDouble);
                    }
					returned_typecode = PhpTypeCode.Double;
					break;

				case Operations.UnicodeCast: // TODO
				case Operations.StringCast:
                    if ((returned_typecode = expr.Emit(codeGenerator)) != PhpTypeCode.String)
                    {
                        codeGenerator.EmitBoxing(returned_typecode);
                        //codeGenerator.EmitLoadClassContext();
                        il.Emit(OpCodes.Call, Methods.Convert.ObjectToString);
                        returned_typecode = PhpTypeCode.String;
                    }
					break;

                case Operations.BinaryCast:
                    if ((returned_typecode = expr.Emit(codeGenerator)) != PhpTypeCode.PhpBytes)
                    {
                        codeGenerator.EmitBoxing(returned_typecode);
                        //codeGenerator.EmitLoadClassContext();
                        il.Emit(OpCodes.Call, Methods.Convert.ObjectToPhpBytes);
                        returned_typecode = PhpTypeCode.PhpBytes;
                    }
                    break;

				case Operations.ArrayCast:
					//Template: "(array)x"   Convert.ObjectToArray(x)
                    o_typecode = expr.Emit(codeGenerator);
                    if (o_typecode != PhpTypeCode.PhpArray)
                    {
                        codeGenerator.EmitBoxing(o_typecode);
                        il.Emit(OpCodes.Call, Methods.Convert.ObjectToPhpArray);
                    }
					returned_typecode = PhpTypeCode.PhpArray;
					break;

				case Operations.UnsetCast:
					// Template: "(unset)x"  null
					il.Emit(OpCodes.Ldnull);
					returned_typecode = PhpTypeCode.Object;
					break;

				default:
					Debug.Assert(false, "illegal type of operation!");
					returned_typecode = PhpTypeCode.Void;
					break;
			}

			switch (access)
			{
				case AccessType.Read:
					// do nothing
					break;
				case AccessType.None:
					// pop operation's result value from stack
					if (returned_typecode != PhpTypeCode.Void)
						il.Emit(OpCodes.Pop);
					return PhpTypeCode.Void;
			}

			return returned_typecode;
		}
Пример #2
0
		/// <include file='Doc/Nodes.xml' path='doc/method[@name="Emit"]/*'/>
		/// <remarks>
		/// Nothing is expected on the evaluation stack. Nothing is left on the evaluation stack.
		/// </remarks>
		internal override void Emit(CodeGenerator/*!*/ codeGenerator)
		{
			Statistics.AST.AddNode("EchoStmt");

			codeGenerator.MarkSequencePoint(position.FirstLine, position.FirstColumn, position.LastLine, position.LastColumn + 2);
			foreach (Expression parameter in parameters)
			{
                // skip empty evaluated expression
                if (parameter.HasValue &&
                    (
                        parameter.Value == null ||
                        (parameter.Value is string && ((string)parameter.Value) == string.Empty) ||
                        Convert.ObjectToPhpBytes(parameter.Value).Length == 0
                    ))
                {
                    continue;
                }

                // emit the echo of parameter expression
				codeGenerator.EmitEcho(parameter);
			}
		}