예제 #1
0
        /// <summary>
        /// Emits IL instructions that write a value to an instance field.
        /// </summary>
        /// <param name="codeGenerator">The current <see cref="CodeGenerator"/>.</param>
        /// <param name="writeRef">If <B>true</B> the value being written is a <see cref="PhpReference"/>
        /// instance, if <B>false</B> it is an <see cref="Object"/> instance.</param>
        /// <returns>Delegate to a method that emits code to be executed when the actual value has been
        /// loaded on the evaluation stack.</returns>
        /// <remarks>
        /// If the field could be resolved at compile time (because <see cref="VarLikeConstructUse.isMemberOf"/> is <c>$this</c> or a
        /// variable is proved to be of a certain type by type analysis), direct field writing code is emitted.
        /// Otherwise, <see cref="Operators.SetProperty"/> or <see cref="Operators.SetObjectProperty"/> call is emitted.
        /// </remarks>
        internal virtual AssignmentCallback EmitWriteField(CodeGenerator /*!*/ codeGenerator, bool writeRef)
        {
            ILEmitter il = codeGenerator.IL;

            DirectVarUse direct_instance = isMemberOf as DirectVarUse;

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

            if (isMemberOf is ItemUse || isMemberOf is StaticFieldUse || isMemberOf.IsMemberOf != null)
            {
                // we are part of a chain
                // Lengthen for hop over ->
                codeGenerator.ChainBuilder.Lengthen();
                FunctionCall funcCall = isMemberOf as FunctionCall;
                if (funcCall == null)
                {
                    isMemberOf.Emit(codeGenerator);
                    EmitName(codeGenerator);
                }
                else
                {
                    codeGenerator.ChainBuilder.LoadAddressOfFunctionReturnValue = true;
                    isMemberOf.Emit(codeGenerator);
                    codeGenerator.ChainBuilder.RecastValueReturnedByFunctionCall();

                    EmitName(codeGenerator);
                }
                return(new AssignmentCallback(EmitCallSetObjectField));
            }
            else
            {
                return(delegate(CodeGenerator codeGen, PhpTypeCode stackTypeCode)
                {
                    codeGen.ChainBuilder.Lengthen();

                    // CALL Operators.SetProperty(STACK,ref <instance>,<field name>,<handle>,<script context>);
                    isMemberOf.Emit(codeGen);
                    EmitName(codeGen);
                    codeGen.EmitLoadClassContext();
                    codeGen.EmitLoadScriptContext();

                    // invoke the operator
                    codeGen.IL.Emit(OpCodes.Call, Methods.Operators.SetProperty);
                });
            }
        }
예제 #2
0
 /// <summary>
 /// Called when derived class visited.
 /// </summary>
 /// <param name="x"></param>
 virtual public void VisitFunctionCall(FunctionCall x)
 {
     foreach (ActualParam p in x.CallSignature.Parameters)
         VisitElement(p);
 }
예제 #3
0
        /// <summary>
        /// Called when derived class visited.
        /// </summary>
        /// <param name="x"></param>
        virtual public void VisitFunctionCall(FunctionCall x)
        {
            VisitVarLikeConstructUse(x);

            foreach (ActualParam p in x.CallSignature.Parameters)
                VisitElement(p);
        }