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