/// <summary> /// Emits code to load variable onto the evaluation stack. Supports operators chaining. /// </summary> /// <param name="codeGenerator">A geenrator.</param> /// <param name="itemGetterKind">Whether to load for "get", "isset", or "empty".</param> private PhpTypeCode EmitNodeRead(CodeGenerator /*!*/ codeGenerator, Operators.GetItemKinds itemGetterKind) { ChainBuilder chain = codeGenerator.ChainBuilder; PhpTypeCode result; if (chain.IsArrayItem) { // we are in the array subchain // // 3: a_[x]_[x] chain.Lengthen(); // for [] result = chain.EmitGetItem(array, index, itemGetterKind); return(result); } // 1,2,4,5,6,7 if (chain.IsMember) { // we are in the field chain // // 4, 5 if (this.isMemberOf != null) { // we are in the middle of the field chain // // 5: ...->a[]->... // Lengthen chain for isMemberOf chain.Lengthen(); // for hop over -> isMemberOf.Emit(codeGenerator); // Lengthen chain for own [] chain.Lengthen(); chain.IsArrayItem = true; chain.IsLastMember = false; result = chain.EmitGetItem(array, index, itemGetterKind); chain.IsArrayItem = false; return(result); } else { // we are at the beginning of the field chain // // 4: a[x]->... // Lengthen chain for itself chain.Lengthen(); // for own [] chain.IsArrayItem = true; chain.IsLastMember = true; result = chain.EmitGetItem(array, index, itemGetterKind); chain.IsArrayItem = false; return(result); } } // 1, 2, 6, 7 if (this.isMemberOf != null) { // last node of the field chain // // 6 , 7: ...->a[]_[]_ , ...->a_[]_ bool quiet_read = chain.QuietRead; chain.Create(); chain.Begin(); chain.QuietRead = quiet_read; chain.Lengthen(); // for hop over -> isMemberOf.Emit(codeGenerator); // let's emit the array subchain followed by the GetItem: chain.IsArrayItem = true; chain.IsLastMember = false; result = chain.EmitGetItem(array, index, itemGetterKind); chain.IsArrayItem = false; chain.End(); return(result); } // 1, 2 if (array is ItemUse || array is DirectStFldUse || array is IndirectStFldUse) { // we are at the beginning of the field chain // // 2: a[]_[]_ bool quiet_read = chain.QuietRead; chain.Create(); chain.Begin(); chain.QuietRead = quiet_read; chain.IsArrayItem = true; chain.IsLastMember = true; result = chain.EmitGetItem(array, index, itemGetterKind); chain.IsArrayItem = false; chain.End(); return(result); } // no chains // // 1: a_[x]_ chain.IsArrayItem = true; chain.IsLastMember = true; result = chain.EmitGetItem(array, index, itemGetterKind); chain.IsArrayItem = false; return(result); }