示例#1
0
        /// <summary>
        /// Evaluates this chain as if it had the <see cref="PHP.Core.AST.AccessType.ReadRef"/> access type.
        /// </summary>
        /// <param name="context">Current script context.</param>
        /// <returns>The result of chain evaluation.</returns>
        public PhpReference GetReference(ScriptContext context)
        {
            PhpReference reference;

            RuntimeChainElement element = Chain;

            if (element == null)
            {
                // if we are just wrapping the variable with a PhpReference, make a copy
                reference = Variable as PhpReference;
                if (reference == null)
                {
                    reference = new PhpReference(PhpVariable.Copy(Variable, CopyReason.Unknown));
                }

                return(reference);
            }

            // make sure that we have a PhpReference
            reference = PhpVariable.MakeReference(Variable);

            if (element == lastElement)
            {
                // GetPropertyRef/GetItemRef
                return(element.GetRef(ref reference.value, context, Caller));
            }

            // EnsureVariableIsObject/EnsureVariableIsArray
            object var = element.EnsureVariable(ref reference.value, context, Caller);

            if (var == null)
            {
                return(new PhpReference());
            }

            while (element.Next != null)
            {
                // Ensure{Field,Item}Is{Object,Array}
                var = element.Ensure(var, context, Caller);
                if (var == null)
                {
                    return(new PhpReference());
                }

                element = element.Next;
            }

            // GetObjectPropertyRef/GetArrayItemRef
            return(element.GetEnsuredRef(var, context, Caller));
        }
示例#2
0
        public PhpReference PeekReferenceUnchecked(int i)
        {
            object          item = Items[Top - i];
            PhpReference    result;
            PhpRuntimeChain php_chain;

            // the caller may not pushed a reference although the formal argument is a reference:
            // it doesn't matter if called by callback:
            if ((result = item as PhpReference) == null)
            {
                // caller may have pushed a runtime chain => evaluate it:
                if ((php_chain = item as PhpRuntimeChain) != null)
                {
                    // call state has to be stored since chain can call arbitrary user code:
                    CallState call_state = SaveCallState();
                    result = php_chain.GetReference(Context);
                    RestoreCallState(call_state);
                }
                else
                {
                    // the reason of copy is not exactly known (it may be returning by copy as well as passing by copy):
                    result = new PhpReference(PhpVariable.Copy(item, CopyReason.Unknown));

                    // Reports an error in the case that we are not called by callback.
                    // Although, this error is fatal one can switch throwing exceptions off.
                    // If this is the case the afterwards behavior will be the same as if callback was called.
                    if (!Callback)
                    {
                        // warning (can invoke user code => we have to save and restore callstate):
                        CallState call_state = SaveCallState();

                        PhpException.ArgumentNotPassedByRef(i, CalleeName);
                        RestoreCallState(call_state);
                    }
                }
            }
            return(result);
        }
示例#3
0
 /// <summary>
 /// Retrieves a copy of this instance.
 /// </summary>
 /// <returns>The copy.</returns>
 /// <remarks>
 /// If this <see cref="PhpSmartReference"/> <see cref="IsAliased"/>, this instance is returned without copying.
 /// That is because (deep) copying stops on references in PHP. If this instance is not <see cref="IsAliased"/>,
 /// a new <see cref="PhpSmartReference"/> referencing a copy of the current value is returned.
 /// </remarks>
 public override object Copy(CopyReason reason)
 {
     return(IsAliased ? this : new PhpSmartReference(PhpVariable.Copy(value, reason)));
 }