/// <summary> /// Emits code to load <see cref="PhpRuntimeChain"/> onto an evaluation stack. Supports operators chaining. /// </summary> /// <param name="codeGenerator"></param> private PhpTypeCode EmitNodeReadUnknown(CodeGenerator codeGenerator) { ChainBuilder chain = codeGenerator.ChainBuilder; PhpTypeCode result = PhpTypeCode.PhpRuntimeChain; if (chain.IsArrayItem) { // 3: a_[x]_[x] chain.Lengthen(); // for [] chain.EmitRTChainAddItem(this); return(result); } // 1,2,4,5,6,7 if (chain.IsMember) { // 4, 5 if (this.isMemberOf != null) { // 5: ...->a[]->... // Lengthen chain for isMemberOf chain.Lengthen(); // for hop over -> PhpTypeCode res = isMemberOf.Emit(codeGenerator); if (res != PhpTypeCode.PhpRuntimeChain) { codeGenerator.EmitBoxing(res); chain.EmitCreateRTChain(); } // Lengthen chain for own [] chain.Lengthen(); chain.IsArrayItem = true; chain.IsLastMember = false; chain.EmitRTChainAddItem(this); chain.IsArrayItem = false; return(result); } // 4: a[x]->... // Lengthen chain for itself chain.Lengthen(); // for own [] chain.IsArrayItem = true; chain.IsLastMember = true; chain.EmitRTChainAddItem(this); chain.IsArrayItem = false; return(result); } // 1, 2, 6, 7 if (this.isMemberOf != null) { // 6 , 7: ...->a[]_[]_ , ...->a_[]_ bool quiet_read = chain.QuietRead; chain.Create(); chain.Begin(); chain.QuietRead = quiet_read; chain.Lengthen(); // for hop over -> PhpTypeCode res = isMemberOf.Emit(codeGenerator); if (res != PhpTypeCode.PhpRuntimeChain) { codeGenerator.EmitBoxing(res); chain.EmitCreateRTChain(); } chain.IsArrayItem = true; chain.IsLastMember = false; chain.EmitRTChainAddItem(this); chain.IsArrayItem = false; chain.End(); return(result); } // 1, 2 if (array is ItemUse || array is DirectStFldUse || array is IndirectStFldUse /* ??? */) { // 2: a[]_[]_ bool quiet_read = chain.QuietRead; chain.Create(); chain.Begin(); chain.QuietRead = quiet_read; chain.IsArrayItem = true; chain.IsLastMember = true; chain.EmitRTChainAddItem(this); chain.IsArrayItem = false; chain.End(); return(result); } // 1: a_[x]_ chain.IsArrayItem = true; chain.IsLastMember = true; chain.EmitRTChainAddItem(this); chain.IsArrayItem = false; return(result); }