示例#1
0
        private static Expression /*!*/ PeekReferenceUnchecked(PhpRoutine routine, DynamicMetaObject scriptContext, DynamicMetaObject arg, int argIndex)
        {
            // the caller may not pushed a reference although the formal argument is a reference:
            // it doesn't matter if called by callback:
            if (!Types.PhpReference[0].IsAssignableFrom(arg.LimitType))
            {
                // caller may have pushed a runtime chain => evaluate it:
                if (arg.LimitType == Types.PhpRuntimeChain[0])
                {
                    //result = php_chain.GetReference(Context);
                    return(Expression.Call(
                               Expression.Convert(arg.Expression, Types.PhpRuntimeChain[0]),
                               Methods.PhpRuntimeChain.GetReference,
                               scriptContext.Expression));
                }
                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(arg_i, CopyReason.Unknown));

                    ParameterExpression   resultVariable = Expression.Parameter(Types.PhpReference[0], "result");
                    ParameterExpression[] vars           = new ParameterExpression[] { resultVariable };

                    return(Expression.Block(vars,
                                            Expression.Assign(
                                                resultVariable,
                                                Expression.New(Constructors.PhpReference_Object, Expression.Call(Methods.PhpVariable.Copy, arg.Expression, Expression.Constant(CopyReason.Unknown)))),
                                            BinderHelper.ThrowArgumentNotPassedByRef(argIndex, routine.FullName),
                                            resultVariable));

                    //(MB) I'm not sure if it's necessary to execute these two in this order


                    //Original code
                    //
                    //(MB) I don't have to solve this now, PhpCallback is called in a old manner. So I can just throw exception always now.
                    //
                    // 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);
                    //}
                }
            }
            else
            {
                return(Expression.Convert(arg.Expression, arg.LimitType));
            }
        }