/// <include file='Doc/Nodes.xml' path='doc/method[@name="Emit"]/*'/> internal override PhpTypeCode Emit(CodeGenerator/*!*/ codeGenerator) { Statistics.AST.AddNode("IndirectVarUse"); PhpTypeCode result = PhpTypeCode.Invalid; switch (codeGenerator.SelectAccess(access)) { // This case occurs everytime we want to get current variable value // All we do is push the value onto the IL stack case AccessType.Read: // Push value onto a IL stack result = EmitNodeRead(codeGenerator); break; // This case occurs when the varible is written ($a = $b, then $a has Write mark) // We only prepare the stack for storing, the work will be done later, // by EmitAssign() case AccessType.Write: result = EmitNodeWrite(codeGenerator); break; case AccessType.None: EmitNodeRead(codeGenerator); codeGenerator.IL.Emit(OpCodes.Pop); result = PhpTypeCode.Void; break; case AccessType.ReadRef: // if the selector is set to the ReadRef, the chain is emitted as if it was written // (chained nodes are marked as ReadAndWrite): if (codeGenerator.AccessSelector == AccessType.ReadRef) codeGenerator.AccessSelector = AccessType.Write; result = EmitNodeReadRef(codeGenerator); Debug.Assert(result == PhpTypeCode.PhpReference); break; case AccessType.ReadUnknown: result = EmitNodeReadUnknown(codeGenerator); break; case AccessType.WriteRef: EmitNodeWriteRef(codeGenerator); result = PhpTypeCode.PhpReference; break; default: result = PhpTypeCode.Invalid; Debug.Fail(); break; } return result; }
/// <include file='Doc/Nodes.xml' path='doc/method[@name="Emit"]/*'/> internal override PhpTypeCode Emit(CodeGenerator/*!*/ codeGenerator) { Statistics.AST.AddNode("ItemUse"); PhpTypeCode result = PhpTypeCode.Invalid; switch (codeGenerator.SelectAccess(access)) { case AccessType.None: result = EmitNodeRead(codeGenerator, Operators.GetItemKinds.Get); codeGenerator.IL.Emit(OpCodes.Pop); break; case AccessType.Read: result = EmitNodeRead(codeGenerator, Operators.GetItemKinds.Get); break; case AccessType.Write: // prepares for write: result = EmitNodeWrite(codeGenerator); break; case AccessType.ReadRef: // if the selector is set to the ReadRef, the chain is emitted as if it was written // (chained nodes are marked as ReadAndWrite): if (codeGenerator.AccessSelector == AccessType.ReadRef) codeGenerator.AccessSelector = AccessType.Write; result = EmitNodeReadRef(codeGenerator); break; case AccessType.ReadUnknown: result = EmitNodeReadUnknown(codeGenerator); break; case AccessType.WriteRef: // prepares for write: result = EmitNodeWriteRef(codeGenerator); break; default: Debug.Fail(); break; } return result; }
/// <include file='Doc/Nodes.xml' path='doc/method[@name="Emit"]/*'/> internal override PhpTypeCode Emit(CodeGenerator/*!*/ codeGenerator) { Statistics.AST.AddNode("FieldUse.Static"); ChainBuilder chain = codeGenerator.ChainBuilder; PhpTypeCode result = PhpTypeCode.Invalid; switch (codeGenerator.SelectAccess(access)) { case AccessType.Read: result = EmitRead(codeGenerator, false); if (chain.IsMember) chain.Lengthen(); break; case AccessType.ReadUnknown: result = EmitRead(codeGenerator, true); if (chain.IsMember) chain.Lengthen(); break; case AccessType.ReadRef: if (chain.IsMember) { chain.Lengthen(); result = EmitRead(codeGenerator, false); } else { result = EmitRead(codeGenerator, true); } break; case AccessType.Write: if (chain.IsMember) { result = EmitEnsure(codeGenerator, chain); chain.Lengthen(); } else { assignmentCallback = EmitWrite(codeGenerator, false); result = PhpTypeCode.Unknown; } break; case AccessType.WriteRef: if (chain.IsMember) { result = EmitEnsure(codeGenerator, chain); chain.Lengthen(); } else { assignmentCallback = EmitWrite(codeGenerator, true); result = PhpTypeCode.Unknown; } break; case AccessType.None: result = PhpTypeCode.Void; break; } return result; }