Example #1
0
        /// <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));
        }