/// <summary> /// Emits code to load a reference to a variable onto an evaluation stack. Supports operators chaining. /// </summary> /// <param name="codeGenerator"></param> private PhpTypeCode EmitNodeReadRef(CodeGenerator codeGenerator) { ChainBuilder chain = codeGenerator.ChainBuilder; LocalBuilder local = codeGenerator.IL.DeclareLocal(typeof(object)); // Case 3: a_[x]_[x] never reached Debug.Assert(chain.IsArrayItem == false, "ReadRef access shouldn't be set to array subchain nodes"); // Case 4,5 never reached // 4: a[x]->... // 5: ...->a[]->... Debug.Assert(chain.IsMember == false); // 1, 2, 6, 7 if (this.isMemberOf != null) { // last node of the field chain // // 6 , 7: ...->a[]_[]_ , ...->a_[]_ chain.Create(); chain.Begin(); if (this.isMemberOf is FunctionCall) { chain.LoadAddressOfFunctionReturnValue = true; } chain.SetObjectForLazyEmit(this); // let's emit the array subchain followed by the GetArrayItemRef: chain.IsArrayItem = true; chain.IsLastMember = false; chain.Lengthen(); // for own [] chain.EmitGetArrayItemRef(array, index); chain.IsArrayItem = false; chain.EndRef(); return(PhpTypeCode.PhpReference); } // 1, 2 if (array is ItemUse || array is DirectStFldUse || array is IndirectStFldUse) { // we are at the beginning of the field chain // // 2: a[]_[]_ chain.Create(); chain.Begin(); chain.IsArrayItem = true; chain.IsLastMember = true; chain.Lengthen(); chain.EmitGetArrayItemRef(array, index); chain.IsArrayItem = false; chain.EndRef(); return(PhpTypeCode.PhpReference); } // no chains // // 1: a_[x]_ return(chain.EmitGetItemRef((SimpleVarUse)array, index)); }