예제 #1
0
        private void EmitNodeWriteAssign(CodeGenerator codeGenerator)
        {
            ChainBuilder chain = codeGenerator.ChainBuilder;

            // Note that for cases 1,3,4,5,6,9 EmitAssign is never called!!!

            // 2,7,8
            if (chain.IsMember)
            {
                // 2,8
                if (chain.Exists)
                {
                    // 8: b[]->$a
                    chain.EmitSetObjectField();
                }
                else
                {
                    // 2: $b->a
                    Debug.Assert(this.isMemberOf is SimpleVarUse || this.isMemberOf is FunctionCall);
                    if (this.isMemberOf is FunctionCall)
                    {
                        codeGenerator.ChainBuilder.LoadAddressOfFunctionReturnValue = true;
                    }

                    assignmentCallback(codeGenerator, PhpTypeCode.Object);

                    SimpleVarUse svu = this.isMemberOf as SimpleVarUse;
                    if (svu != null)
                    {
                        svu.EmitLoadAddress_StoreBack(codeGenerator);
                    }
                    // else do nothing
                }
                chain.End();
            }
            else
            {
                // 7: $a
                //codeGenerator.EmitVariableStoreAssign(this);
                this.EmitStoreAssign(codeGenerator);
            }
        }
예제 #2
0
        /// <summary>
        /// Emits IL instructions that read the value of an instance field.
        /// </summary>
        /// <param name="codeGenerator">The current <see cref="CodeGenerator"/>.</param>
        /// <param name="wantRef">If <B>false</B> the field value should be left on the evaluation stack,
        /// if <B>true</B> the <see cref="PhpReference"/> should be left on the evaluation stack.</param>
        /// <returns>
        /// Nothing is expected on the evaluation stack. A <see cref="PhpReference"/> (if <paramref name="wantRef"/>
        /// is <B>true</B>) or the field value itself (if <paramref name="wantRef"/> is <B>false</B>) is left on the
        /// evaluation stack.
        /// </returns>
        internal virtual PhpTypeCode EmitReadField(CodeGenerator codeGenerator, bool wantRef)
        {
            ILEmitter il = codeGenerator.IL;

            DirectVarUse direct_instance = isMemberOf as DirectVarUse;

            if (direct_instance != null && direct_instance.IsMemberOf == null && direct_instance.VarName.IsThisVariableName)
            {
                return(EmitReadFieldOfThis(codeGenerator, wantRef));
            }


            if (!wantRef)
            {
                //codeGenerator.ChainBuilder.Lengthen();
                //PhpTypeCode type_code = isMemberOf.Emit(codeGenerator);
                //Debug.Assert(type_code == PhpTypeCode.Object || type_code == PhpTypeCode.DObject);

                //// CALL Operators.GetProperty(STACK,<field name>,<type desc>,<quiet>);
                //EmitName(codeGenerator);
                //codeGenerator.EmitLoadClassContext();
                //il.LoadBool(codeGenerator.ChainBuilder.QuietRead);
                //il.Emit(OpCodes.Call, Methods.Operators.GetProperty);
                //return PhpTypeCode.Object;

                string     fieldName     = (this is DirectVarUse) ? ((DirectVarUse)this).VarName.Value : null;
                Expression fieldNameExpr = (this is IndirectVarUse) ? ((IndirectVarUse)this).VarNameEx : null;
                bool       quietRead     = wantRef ? false : codeGenerator.ChainBuilder.QuietRead;
                return(codeGenerator.CallSitesBuilder.EmitGetProperty(
                           codeGenerator, wantRef,
                           isMemberOf, null, null,
                           null,
                           fieldName, fieldNameExpr,
                           quietRead));
            }

            // call GetProperty/GetObjectPropertyRef
            codeGenerator.ChainBuilder.Lengthen();
            // loads the variable which field is gotten:
            PhpTypeCode var_type_code = isMemberOf.Emit(codeGenerator);

            if (codeGenerator.ChainBuilder.Exists)
            {
                Debug.Assert(var_type_code == PhpTypeCode.DObject);

                // CALL Operators.GetObjectPropertyRef(STACK,<field name>,<type desc>);
                EmitName(codeGenerator);
                codeGenerator.EmitLoadClassContext();
                il.Emit(OpCodes.Call, Methods.Operators.GetObjectPropertyRef);
            }
            else
            {
                Debug.Assert(var_type_code == PhpTypeCode.ObjectAddress);

                // CALL Operators.GetPropertyRef(ref STACK,<field name>,<type desc>,<script context>);
                EmitName(codeGenerator);
                codeGenerator.EmitLoadClassContext();
                codeGenerator.EmitLoadScriptContext();
                il.Emit(OpCodes.Call, Methods.Operators.GetPropertyRef);

                // stores the value of variable back:
                SimpleVarUse simple_var = isMemberOf as SimpleVarUse;
                if (simple_var != null)
                {
                    simple_var.EmitLoadAddress_StoreBack(codeGenerator);
                }
            }

            return(PhpTypeCode.PhpReference);
        }
예제 #3
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);
			}
		}
예제 #4
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);
		}
예제 #5
0
파일: Chains.cs 프로젝트: dw4dev/Phalanger
		/// <summary>
		/// Emits IL instructions that loads the value of array's item as a <see cref="PHP.Core.PhpReference"/>.
		/// </summary>
		/// <param name="variable">A simple variable.</param>
		/// <param name="index"><see cref="Expression"/> determining the index.</param> 
		public PhpTypeCode EmitGetItemRef(SimpleVarUse/*!*/ variable, Expression index)
		{
			IsArrayItem = true;
			IsLastMember = true;
			
			PhpTypeCode index_type_code = PhpTypeCode.Invalid;

			// index:
			if (index != null)
				index_type_code = codeGenerator.EmitArrayKey(this, index);

			// array:
			variable.Emit(codeGenerator);

			// LOAD Operators.GetItemRef([<index>], ref <variable>)
			codeGenerator.EmitGetItem(index_type_code, index, true);
			
			// store the changed variable into table of variables (do nothing in optimalized functions)
			variable.EmitLoadAddress_StoreBack(codeGenerator);

			IsArrayItem = false;

			return PhpTypeCode.PhpReference;
		}