Пример #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));
        }
Пример #2
0
        /// <summary>
        /// Emits code to prepare an evaluation stack for storing a reference into a variable.
        /// Supports operators chaining. Store is finished by calling <see cref="EmitAssign"/>.
        /// </summary>
        /// <param name="codeGenerator"></param>
        private PhpTypeCode EmitNodeWriteRef(CodeGenerator codeGenerator)
        {
            ChainBuilder chain = codeGenerator.ChainBuilder;

            // Case 3: a_[x]_[x] never reached
            Debug.Assert(chain.IsArrayItem == false);

            // Case 4,5 never reached
            // 4: a[x]->...
            // 5: ...->a[]->...
            Debug.Assert(chain.IsMember == false);

            // 1, 2, 6, 7
            if (this.isMemberOf != null)
            {
                // 6, 7: ...->a[x]_[x]_
                chain.Create();
                chain.Begin();
                // Store isMemberOf for lazy emit
                chain.SetObjectForLazyEmit(this);
                chain.IsArrayItem  = true;
                chain.IsLastMember = false;
                chain.Lengthen();                 // for own []
                array.Emit(codeGenerator);
                indexTypeCode = codeGenerator.EmitArrayKey(chain, index);

                // Note that EmitAssign will finish the work (SetArrayItem or PhpArray.Add)
            }
            else
            {
                // 1, 2
                Debug.Assert(this.isMemberOf == null);

                if (array is ItemUse || array is DirectStFldUse || array is IndirectStFldUse /* ??? */)
                {
                    // 2: a[]_[]_
                    chain.Create();
                    chain.Begin();
                    chain.IsArrayItem  = true;
                    chain.IsLastMember = true;
                    array.Emit(codeGenerator);
                    indexTypeCode = codeGenerator.EmitArrayKey(chain, index);

                    // Note that further work will be done by EmitAssign (SetArrayItem or PhpArray.Add)
                }
                // 1: a_[x]_
                // Do nothing now, let the work be done in EmitAssign()
                // Note further work will be done by EmitAssign (either SetItem or SetItemRef);
            }
            return(PhpTypeCode.Unknown);
        }
Пример #3
0
        /// <summary>
        /// Emits code to prepare an evaluation stack for storing a value into a variable.
        /// Supports operators chaining. Store is finished by calling <see cref="EmitAssign"/>.
        /// </summary>
        /// <param name="codeGenerator"></param>
        private PhpTypeCode EmitNodeWrite(CodeGenerator codeGenerator)
        {
            ChainBuilder chain = codeGenerator.ChainBuilder;

            if (chain.IsArrayItem)
            {
                // 3: a_[x]_[v]
                Debug.Assert(this.isMemberOf == null);
                return(chain.EmitEnsureItem(array, index, true));
            }

            // 1, 2, 4, 5, 6, 7
            if (chain.IsMember)
            {
                // 4, 5
                if (this.isMemberOf != null)
                {
                    // 5: ...->a[]->...
                    // Store isMemberOf for lazy emit
                    chain.SetObjectForLazyEmit(this);
                    chain.IsArrayItem  = true;
                    chain.IsLastMember = false;
                }
                else
                {
                    // 4: a_[x]_->c->..., a[x]_[x]_->c->...
                    chain.IsArrayItem  = true;
                    chain.IsLastMember = true;
                }

                PhpTypeCode result = chain.EmitEnsureItem(array, index, false);
                chain.IsArrayItem = false;
                return(result);
            }

            // 1, 2, 6, 7
            if (this.isMemberOf != null)
            {
                // 6, 7: ...->a[x]_[x]_
                chain.Create();
                chain.Begin();
                // Store isMemberOf for lazy emit
                chain.SetObjectForLazyEmit(this);
                chain.IsArrayItem  = true;
                chain.IsLastMember = false;
                chain.Lengthen();                 // for own []
                array.Emit(codeGenerator);
                indexTypeCode = codeGenerator.EmitArrayKey(chain, index);

                // Note that EmitAssign will finish the work (SetArrayItem or PhpArray.Add)
                return(PhpTypeCode.Unknown);
            }
            // 1, 2
            Debug.Assert(this.isMemberOf == null);

            if (array is ItemUse || array is DirectStFldUse || array is IndirectStFldUse /* ??? */)
            {
                // 2: a[]_[]_
                chain.Create();
                chain.Begin();
                chain.IsArrayItem  = true;
                chain.IsLastMember = true;
                array.Emit(codeGenerator);
                indexTypeCode = codeGenerator.EmitArrayKey(chain, index);


                // Note that further work will be done by EmitAssign (SetArrayItem or PhpArray.Add)
                return(PhpTypeCode.Unknown);
            }

            // 1: a_[x]_
            // Do nothing now, let the work be done in EmitAssign()
            return(PhpTypeCode.Unknown);
        }