Пример #1
0
        internal override void EmitUnset(CodeGenerator codeGenerator)
        {
            ChainBuilder chain = codeGenerator.ChainBuilder;

            // Template: "unset(x[y])"  Operators.UnsetItem(object obj,object index)

            // 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);

            chain.QuietRead = true;

            // 1, 2, 6, 7
            if (this.isMemberOf != null)
            {
                // 6 , 7: ...->a[]_[]_ , ...->a_[]_
                chain.Create();
                chain.Begin();
                chain.Lengthen();                 // for hop over ->
                isMemberOf.Emit(codeGenerator);
                chain.IsArrayItem  = true;
                chain.IsLastMember = false;
                chain.EmitUnsetItem(array, index);
                chain.IsArrayItem = false;
                chain.End();
                return;
            }
            // 1, 2
            if (array is ItemUse || array is DirectStFldUse || array is IndirectStFldUse /* ??? */)
            {
                // 2: a[]_[]_
                chain.Create();
                chain.Begin();
                chain.IsArrayItem  = true;
                chain.IsLastMember = true;
                chain.EmitUnsetItem(array, index);
                chain.IsArrayItem = false;
                chain.End();
                return;
            }
            // 1: a_[x]_
            chain.IsArrayItem  = true;
            chain.IsLastMember = true;
            chain.EmitUnsetItem(array, index);
            chain.IsArrayItem = false;
        }
Пример #2
0
        private void EmitNodeWriteAssign(CodeGenerator codeGenerator)
        {
            ChainBuilder chain = codeGenerator.ChainBuilder;

            // Note that for cases 1,3,4,5,6,9 EmitAssign is never called!!!

            // 2,7,8
            if (chain.IsMember)
            {
                // 2,8
                if (chain.Exists)
                {
                    // 8: b[]->$a
                    chain.EmitSetObjectField();
                }
                else
                {
                    // 2: $b->a
                    Debug.Assert(this.isMemberOf is SimpleVarUse || this.isMemberOf is FunctionCall);
                    if (this.isMemberOf is FunctionCall)
                    {
                        codeGenerator.ChainBuilder.LoadAddressOfFunctionReturnValue = true;
                    }

                    assignmentCallback(codeGenerator, PhpTypeCode.Object);

                    SimpleVarUse svu = this.isMemberOf as SimpleVarUse;
                    if (svu != null)
                    {
                        svu.EmitLoadAddress_StoreBack(codeGenerator);
                    }
                    // else do nothing
                }
                chain.End();
            }
            else
            {
                // 7: $a
                //codeGenerator.EmitVariableStoreAssign(this);
                this.EmitStoreAssign(codeGenerator);
            }
        }
Пример #3
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);
        }
Пример #4
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);
        }
Пример #5
0
        /// <summary>
        /// Finishes the write operation starte by <see cref="Emit"/>.
        /// </summary>
        internal override PhpTypeCode EmitAssign(CodeGenerator /*!*/ codeGenerator)
        {
            ChainBuilder chain = codeGenerator.ChainBuilder;
            PhpTypeCode  result;

            switch (access)
            {
            case AccessType.WriteAndReadRef:
            case AccessType.WriteAndReadUnknown:
            case AccessType.ReadAndWrite:
            case AccessType.ReadAndWriteAndReadRef:
            case AccessType.ReadAndWriteAndReadUnknown:
            case AccessType.Write:
            case AccessType.WriteRef:
            {
                bool reference = access == AccessType.WriteRef;

                // Note that some work was done in Emit() !
                // In cases 3, 4, 5 EmitAssign is not called

                if (isMemberOf != null ||
                    (isMemberOf == null && (array is DirectStFldUse || array is IndirectStFldUse || array is ItemUse)))
                {
                    // 2, 6, 7
                    chain.EmitSetArrayItem(indexTypeCode, index, reference);
                    chain.End();
                }
                else
                {
                    // Note: The value which should be stored is already loaded on the evaluation stack.
                    //				Push the destination array and index and call the operator
                    // 1: a_[x]_
                    Debug.Assert(array is SimpleVarUse);
                    chain.IsArrayItem  = true;
                    chain.IsLastMember = true;
                    indexTypeCode      = codeGenerator.EmitArrayKey(chain, index);
                    array.Emit(codeGenerator);
                    chain.EmitSetItem(indexTypeCode, index, reference);

                    // Store the changed variable into table of variables (do nothing in optimalized functions)
                    ((SimpleVarUse)array).EmitLoadAddress_StoreBack(codeGenerator);
                }

                result = PhpTypeCode.Void;
                break;
            }

            case AccessType.None:
                // do nothing
                result = PhpTypeCode.Void;
                break;

            case AccessType.Read:
                // do nothing
                result = PhpTypeCode.Object;
                break;

            case AccessType.ReadRef:
                // Do nothing
                result = PhpTypeCode.PhpReference;
                break;

            default:
                Debug.Fail();
                result = PhpTypeCode.Invalid;
                break;
            }

            return(result);
        }