/// <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); }