예제 #1
0
파일: Chains.cs 프로젝트: dw4dev/Phalanger
		/// <summary>
		/// Emits IL instructions that ensure that the specified variable is an instance of <see cref="PhpObject"/>. 
		/// </summary>
		/// <param name="variable">Variable that should be examined.</param>
		/// <remarks>
		/// This method is used in operators chains. Nothing is expected on the evaluation stack. 
		/// If the specified variable is an instance of <see cref="PhpObject"/>
		/// it is left on the evaluation stack. Otherwise the control is transfered to the end of 
		/// the chain.
		/// </remarks>
		public void EmitEnsureVariableIsObject(SimpleVarUse variable)
		{
			ILEmitter il = codeGenerator.IL;

			DirectVarUse direct_variable = variable as DirectVarUse;
			if (direct_variable != null && direct_variable.VarName.IsThisVariableName)
			{
				// special treatment of $this
				switch (codeGenerator.LocationStack.LocationType)
				{
					case LocationTypes.GlobalCode:
						{
							// load $this from one of Main's arguments and check for null
							Label this_non_null = il.DefineLabel();

							codeGenerator.EmitLoadSelf();
							il.Emit(OpCodes.Brtrue_S, this_non_null);

							codeGenerator.EmitPhpException(Methods.PhpException.ThisUsedOutOfObjectContext);

							il.Emit(OpCodes.Br, TopChain.ErrorLabel);
							il.MarkLabel(this_non_null, true);
							codeGenerator.EmitLoadSelf();
							break;
						}

					case LocationTypes.FunctionDecl:
						{
							// always throws error
							codeGenerator.EmitPhpException(Methods.PhpException.ThisUsedOutOfObjectContext);
							il.Emit(OpCodes.Br, TopChain.ErrorLabel);
							break;
						}

					case LocationTypes.MethodDecl:
						{
							CompilerLocationStack.MethodDeclContext context = codeGenerator.LocationStack.PeekMethodDecl();
							if (context.Method.IsStatic)
							{
								// always throws error
								codeGenerator.EmitPhpException(Methods.PhpException.ThisUsedOutOfObjectContext);
								il.Emit(OpCodes.Br, TopChain.ErrorLabel);
							}
							else
							{
								// arg0 or <proxy> in instance methods
								codeGenerator.EmitLoadSelf();
							}
							break;
						}

					default:
						Debug.Assert(false, "Invalid location type.");
						break;
				}
			}
			else
			{
				// Template: PhpObject    EnsureVariableIsObject(ref object,ScriptContext)

				// Load variable's address
				//				if (variable is FunctionCall)
				//				{
				//					variable.Emit(this);
				//					EmitLoadScriptContext();
				//					il.Emit(OpCodes.Call, Methods.Operators.EnsureVariableIsObject);
				//					// Store the changed destVar into table of variables (do nothing in optimalized functions)
				//				}
				//				else
				//				{
				variable.EmitLoadAddress(codeGenerator);
				codeGenerator.EmitLoadScriptContext();
				il.Emit(OpCodes.Call, Methods.Operators.EnsureVariableIsObject);
				// Store the changed destVar into table of variables (do nothing in optimalized functions)
				variable.EmitLoadAddress_StoreBack(codeGenerator);
				//				}
				EmitErrorCheck(false);
			}
		}
예제 #2
0
파일: Chains.cs 프로젝트: dw4dev/Phalanger
		/// <summary>
		/// Emits IL instructions that ensure that the specified variable is an instance of <see cref="PhpArray"/>. 
		/// </summary>
		/// <param name="variable">Variable's name-index to a table of identifiers.</param>
		/// <remarks>
		/// This method is used in operators chains. Nothing is expected on the evaluation stack. 
		/// If the specified variable is an instance of <see cref="PhpArray"/>
		/// it is left on the evaluation stack. Otherwise the control is transfered to the end of 
		/// the chain.
		/// </remarks>
		public void EmitEnsureVariableIsArray(SimpleVarUse variable)
		{
			// Template: PhpArray     EnsureVariableIsArray(ref object)

			// Load variable's address
			//this.EmitVariableLoadAddress(variable);
			variable.EmitLoadAddress(codeGenerator);
			codeGenerator.IL.Emit(OpCodes.Call, Methods.Operators.EnsureVariableIsArray);
			// Store the changed destVar into table of variables (do nothing in optimalized functions)
			variable.EmitLoadAddress_StoreBack(codeGenerator);
			EmitErrorCheck(true);
		}