예제 #1
0
        /// <summary>
        /// Finishes the write operation starte by <see cref="Emit"/>.
        /// </summary>
        internal override PhpTypeCode EmitAssign(CodeGenerator /*!*/ codeGenerator)
        {
            ChainBuilder chain = codeGenerator.ChainBuilder;
            PhpTypeCode  result;

            switch (access)
            {
            case AccessType.WriteAndReadRef:
            case AccessType.WriteAndReadUnknown:
            case AccessType.ReadAndWrite:
            case AccessType.ReadAndWriteAndReadRef:
            case AccessType.ReadAndWriteAndReadUnknown:
            case AccessType.Write:
            case AccessType.WriteRef:
            {
                bool reference = access == AccessType.WriteRef;

                // Note that some work was done in Emit() !
                // In cases 3, 4, 5 EmitAssign is not called

                if (isMemberOf != null ||
                    (isMemberOf == null && (array is DirectStFldUse || array is IndirectStFldUse || array is ItemUse)))
                {
                    // 2, 6, 7
                    chain.EmitSetArrayItem(indexTypeCode, index, reference);
                    chain.End();
                }
                else
                {
                    // Note: The value which should be stored is already loaded on the evaluation stack.
                    //				Push the destination array and index and call the operator
                    // 1: a_[x]_
                    Debug.Assert(array is SimpleVarUse);
                    chain.IsArrayItem  = true;
                    chain.IsLastMember = true;
                    indexTypeCode      = codeGenerator.EmitArrayKey(chain, index);
                    array.Emit(codeGenerator);
                    chain.EmitSetItem(indexTypeCode, index, reference);

                    // Store the changed variable into table of variables (do nothing in optimalized functions)
                    ((SimpleVarUse)array).EmitLoadAddress_StoreBack(codeGenerator);
                }

                result = PhpTypeCode.Void;
                break;
            }

            case AccessType.None:
                // do nothing
                result = PhpTypeCode.Void;
                break;

            case AccessType.Read:
                // do nothing
                result = PhpTypeCode.Object;
                break;

            case AccessType.ReadRef:
                // Do nothing
                result = PhpTypeCode.PhpReference;
                break;

            default:
                Debug.Fail();
                result = PhpTypeCode.Invalid;
                break;
            }

            return(result);
        }