示例#1
0
        ///// <summary>
        ///// Returns methodName from Args
        ///// </summary>
        ///// <param name="args"></param>
        ///// <returns></returns>
        //protected DynamicMetaObject GetRuntimeMethodName(DynamicMetaObject[] args)
        //{
        //    //if (args.Length == this.genericParamsCount + this.paramsCount + 3) // args contains ClassContext
        //    //    return args[this.genericParamsCount + this.paramsCount + 2];
        //    //else if (args.Length == this.genericParamsCount + this.paramsCount + 2)
        //    //    return args[this.genericParamsCount + this.paramsCount + 1];

        //    //throw new InvalidOperationException();

        //    return args[args.Length - 1];

        //}


        protected override DynamicMetaObject /*!*/ FallbackInvokeMember(
            DynamicMetaObject target,
            DynamicMetaObject[] args)
        {
            Debug.Assert(Types.String[0].IsAssignableFrom(args[args.Length - 1].LimitType), "Wrong field name type!");

            DynamicMetaObject dmoMethodName = args[args.Length - 1];

            string name = PhpVariable.AsString(dmoMethodName.Value);

            if (name == null)
            {
                //PhpException.Throw(PhpError.Error, CoreResources.GetString("invalid_method_name"));
                //return new PhpReference() | null;

                return(DoAndReturnDefault(
                           BinderHelper.ThrowError("invalid_method_name"),
                           target.Restrictions));

                throw new NotImplementedException();
            }
            else
            {
                // Restriction: PhpVariable.AsString(methodName) == |methodName|
                BindingRestrictions restrictions = BindingRestrictions.GetExpressionRestriction(
                    Expression.Equal(
                        Expression.Call(Methods.PhpVariable.AsString, dmoMethodName.Expression),
                        Expression.Constant(dmoMethodName.Value, Types.String[0])));

                actualMethodName = name;

                //transform arguments that it doesn't contains methodName
                Array.Resize <DynamicMetaObject>(ref args, args.Length - 1);

                DynamicMetaObject result = base.FallbackInvokeMember(target, args);

                return(new DynamicMetaObject(
                           result.Expression,
                           result.Restrictions.Merge(restrictions)));//TODO: Creation of this can be saved
            }
        }
示例#2
0
        protected override DynamicMetaObject /*!*/ FallbackInvokeMember(DynamicMetaObject target /*!*/, DynamicMetaObject /*!*/[] /*!*/ args)
        {
            Expression invokeMethodExpr;

            DObject obj = target.Value as DObject;// target.Value can be something else which isn't DObject ?

            WrappedClrDynamicMetaObject wrappedTarget = null;

            bool invokeCallMethod = false;

            // Restrictions
            BindingRestrictions restrictions;
            BindingRestrictions classContextRestrictions = BindingRestrictions.Empty;
            BindingRestrictions defaultRestrictions      = BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType);

            DTypeDesc classContext = this._classContext;

            if (!ClassContextIsKnown)//ClassContext wasn't supplied during creation of binder => put it into restriction
            {
                Debug.Assert(args.Length > RealMethodArgumentCount, "Not enough arguments!");

                DynamicMetaObject dmoRuntimeClassContext = GetRuntimeClassContext(args);
                Debug.Assert(dmoRuntimeClassContext.Value == null || Types.DTypeDesc[0].IsAssignableFrom(dmoRuntimeClassContext.LimitType), "Wrong class context type!");

                classContext = (DTypeDesc)dmoRuntimeClassContext.Value;
                Debug.Assert(classContext == null || !classContext.IsUnknown, "Class context should be known at run time!");

                classContextRestrictions = BindingRestrictions.GetInstanceRestriction(dmoRuntimeClassContext.Expression, classContext);
                defaultRestrictions      = defaultRestrictions.Merge(classContextRestrictions);
            }

            if (obj == null)
            {
                if (target.Value != null && Configuration.Application.Compiler.ClrSemantics)
                {
                    // TODO: some normalizing conversions (PhpString, PhpBytes -> string):
                    target = new WrappedClrDynamicMetaObject(target);
                    obj    = target.Value as DObject;

                    wrappedTarget = target as WrappedClrDynamicMetaObject;

                    Debug.Assert(obj != null);
                }
                else
                {
                    //defaultRestrictions = defaultRestrictions.Merge(BindingRestrictions.GetTypeRestriction
                    if (target.Value == null)
                    {
                        defaultRestrictions = BindingRestrictions.GetInstanceRestriction(target.Expression, null);
                    }

                    return(DoAndReturnDefault(
                               BinderHelper.ThrowError("method_called_on_non_object", ActualMethodName),
                               defaultRestrictions));
                }
            }



            // obtain the appropriate method table
            DTypeDesc type_desc = obj.TypeDesc;

            // perform method lookup
            DRoutineDesc    method;
            GetMemberResult result = type_desc.GetMethod(new Name(ActualMethodName), classContext, out method);

            //PhpStack stack = context.Stack;

            if (result == GetMemberResult.NotFound)
            {
                if ((result = type_desc.GetMethod(DObject.SpecialMethodNames.Call, classContext, out method)) == GetMemberResult.NotFound)
                {
                    return(DoAndReturnDefault(
                               Expression.Call(Methods.PhpException.UndefinedMethodCalled, Expression.Constant(obj.TypeName), Expression.Constant(ActualMethodName)),
                               defaultRestrictions
                               ));    // TODO: alter restrictions
                }
                else
                {
                    invokeCallMethod = true;
                }
            }

            // throw an error if the method was found but the caller is not allowed to call it due to its visibility
            if (result == GetMemberResult.BadVisibility)
            {
                return(DoAndReturnDefault(
                           BinderHelper.ThrowVisibilityError(method, classContext),
                           defaultRestrictions));
            }

            if (invokeCallMethod)
            {
                InvokeCallMethod(target, args, obj, method, out restrictions, out invokeMethodExpr);

                return(new DynamicMetaObject(invokeMethodExpr, restrictions.Merge(classContextRestrictions)));
            }
            else
            {
                // we are invoking the method

                // PhpRoutine (function or method)
                if (method.Member is PhpRoutine)
                {
                    InvokePhpMethod(target, args, method.PhpRoutine, out restrictions, out invokeMethodExpr);
                    return(new DynamicMetaObject(invokeMethodExpr, restrictions.Merge(classContextRestrictions)));
                }
                // ClrMethod
                else if (method.Member is ClrMethod)
                {
                    var targetwrapper = (target.LimitType == typeof(ClrObject)) ?
                                        (DynamicMetaObject) new ClrDynamicMetaObject(target) :     // ((ClrObject)target).RealType restriction
                                        (DynamicMetaObject) new ClrValueDynamicMetaObject(target); // simple type restriction, IClrValue<T> or any .NET class inheriting PhpObject

                    InvokeClrMethod(targetwrapper, args, method, out restrictions, out invokeMethodExpr);

                    if (wrappedTarget != null)
                    {
                        return(new DynamicMetaObject(Expression.Block(wrappedTarget.WrapIt(),
                                                                      invokeMethodExpr), wrappedTarget.Restrictions.Merge(classContextRestrictions)));
                    }

                    return(new DynamicMetaObject(invokeMethodExpr, restrictions.Merge(classContextRestrictions)));
                }
            }

            throw new NotImplementedException();
        }