Example #1
0
        /// <summary>
        /// Emits code to load <see cref="PhpRuntimeChain"/> onto an evaluation stack. Supports operators chaining.
        /// </summary>
        /// <param name="codeGenerator"></param>
        private PhpTypeCode EmitNodeReadUnknown(CodeGenerator codeGenerator)
        {
            ChainBuilder chain  = codeGenerator.ChainBuilder;
            PhpTypeCode  result = PhpTypeCode.PhpRuntimeChain;

            if (chain.IsArrayItem)
            {
                // 3: a_[x]_[x]
                chain.Lengthen();                 // for []
                chain.EmitRTChainAddItem(this);
                return(result);
            }
            // 1,2,4,5,6,7
            if (chain.IsMember)
            {
                // 4, 5
                if (this.isMemberOf != null)
                {
                    // 5: ...->a[]->...

                    // Lengthen chain for isMemberOf
                    chain.Lengthen();                     // for hop over ->
                    PhpTypeCode res = isMemberOf.Emit(codeGenerator);
                    if (res != PhpTypeCode.PhpRuntimeChain)
                    {
                        codeGenerator.EmitBoxing(res);
                        chain.EmitCreateRTChain();
                    }
                    // Lengthen chain for own []
                    chain.Lengthen();
                    chain.IsArrayItem  = true;
                    chain.IsLastMember = false;
                    chain.EmitRTChainAddItem(this);
                    chain.IsArrayItem = false;
                    return(result);
                }
                // 4: a[x]->...
                // Lengthen chain for itself
                chain.Lengthen();                 // for own []
                chain.IsArrayItem  = true;
                chain.IsLastMember = true;
                chain.EmitRTChainAddItem(this);
                chain.IsArrayItem = false;
                return(result);
            }
            // 1, 2, 6, 7
            if (this.isMemberOf != null)
            {
                // 6 , 7: ...->a[]_[]_ , ...->a_[]_
                bool quiet_read = chain.QuietRead;
                chain.Create();
                chain.Begin();
                chain.QuietRead = quiet_read;
                chain.Lengthen();                 // for hop over ->
                PhpTypeCode res = isMemberOf.Emit(codeGenerator);
                if (res != PhpTypeCode.PhpRuntimeChain)
                {
                    codeGenerator.EmitBoxing(res);
                    chain.EmitCreateRTChain();
                }
                chain.IsArrayItem  = true;
                chain.IsLastMember = false;
                chain.EmitRTChainAddItem(this);
                chain.IsArrayItem = false;
                chain.End();
                return(result);
            }
            // 1, 2
            if (array is ItemUse || array is DirectStFldUse || array is IndirectStFldUse /* ??? */)
            {
                // 2: a[]_[]_
                bool quiet_read = chain.QuietRead;
                chain.Create();
                chain.Begin();
                chain.QuietRead    = quiet_read;
                chain.IsArrayItem  = true;
                chain.IsLastMember = true;
                chain.EmitRTChainAddItem(this);
                chain.IsArrayItem = false;
                chain.End();
                return(result);
            }
            // 1: a_[x]_
            chain.IsArrayItem  = true;
            chain.IsLastMember = true;
            chain.EmitRTChainAddItem(this);
            chain.IsArrayItem = false;
            return(result);
        }