示例#1
0
        internal static object GetUserArrayItem(DObject /*!*/ arrayAccess, object index, Operators.GetItemKinds kind)
        {
            PhpStack stack = ScriptContext.CurrentContext.Stack;

            switch (kind)
            {
            case Operators.GetItemKinds.Isset:
                // pass isset() ""/null to say true/false depending on the value returned from "offsetExists":
                stack.AddFrame(index);
                return(Core.Convert.ObjectToBoolean(arrayAccess.InvokeMethod(offsetExists, null, stack.Context)) ? "" : null);

            case Operators.GetItemKinds.Empty:
                // if "offsetExists" returns false, the empty()/isset() returns false (pass null to say true/false):
                // otherwise, "offsetGet" is called to retrieve the value, which is passed to isset():
                stack.AddFrame(index);
                if (!Core.Convert.ObjectToBoolean(arrayAccess.InvokeMethod(offsetExists, null, stack.Context)))
                {
                    return(null);
                }
                else
                {
                    goto default;
                }

            default:
                // regular getter:
                stack.AddFrame(index);
                return(PhpVariable.Dereference(arrayAccess.InvokeMethod(offsetGet, null, stack.Context)));
            }
        }
示例#2
0
        /// <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);
        }