Пример #1
0
        void ISpecialParamHolder.Process(CallSiteContext info, Expression valueExpr)
        {
            Debug.Assert(Value != null);

            info.AddRestriction(BindingRestrictions.GetInstanceRestriction(valueExpr, Value));  // {arg} != null && {arg} == Value
            info.TargetType = Value;
        }
Пример #2
0
        protected override MethodBase[] ResolveMethods(CallSiteContext bound)
        {
            // check bound.TargetType is assignable from bound.TargetInstance
            if (bound.TargetType == null ||
                bound.CurrentTargetInstance == null ||
                bound.TargetType.Type.IsAssignableFrom(bound.CurrentTargetInstance.GetType()) == false)
            {
                // target instance cannot be used
                bound.TargetInstance = null;
            }

            //
            if (bound.Name != null)
            {
                // candidates:
                IEnumerable <MethodBase> candidates =
                    bound.TargetType
                    .SelectRuntimeMethods(bound.Name, bound.ClassContext)
                    .SelectVisible(bound.ClassContext);

                if (bound.TargetInstance == null)
                {
                    candidates = candidates.SelectStatic();
                }

                //
                return(candidates.Construct(bound.TypeArguments).ToArray());
            }
            else
            {
                throw new ArgumentException();
            }
        }
Пример #3
0
        protected override Expression BindMissingMethod(CallSiteContext bound)
        {
            if (bound.TargetType == null)   // already reported - class cannot be found
            {
                return(ConvertExpression.BindDefault(this.ReturnType));
            }

            var call = BinderHelpers.FindMagicMethod(bound.TargetType, (bound.TargetInstance == null) ? TypeMethods.MagicMethods.__callstatic : TypeMethods.MagicMethods.__call);

            if (call != null)
            {
                var name_expr = (_name != null) ? Expression.Constant(_name) : bound.IndirectName;

                // T.__callStatic(name, array)
                var call_args = new Expression[]
                {
                    name_expr,
                    BinderHelpers.NewPhpArray(bound.Arguments),
                };
                return(OverloadBinder.BindOverloadCall(_returnType, bound.TargetInstance, call.Methods, bound.Context, call_args, true, lateStaticType: bound.TargetType));
            }

            //
            return(base.BindMissingMethod(bound));
        }
Пример #4
0
        protected virtual Expression BindMissingMethod(CallSiteContext bound)
        {
            string nameText = bound.Name ?? "???";

            // TODO: ErrCode method not found
            throw new ArgumentException(string.Format("Function '{0}' not found!", nameText));
        }
Пример #5
0
        protected override Expression BindMissingMethod(CallSiteContext bound)
        {
            var name_expr = (_name != null) ? Expression.Constant(_name) : bound.IndirectName;

            // resolve target expression:
            var isobject = bound.TargetType != null;

            if (isobject == false)
            {
                /* Template:
                 * PhpException.MethodOnNonObject(name_expr); // aka PhpException.Throw(Error, method_called_on_non_object, name_expr)
                 * return NULL;
                 */
                var throwcall = Expression.Call(typeof(PhpException), "MethodOnNonObject", Array.Empty <Type>(), ConvertExpression.Bind(name_expr, typeof(string), bound.Context));
                return(Expression.Block(throwcall, ConvertExpression.BindDefault(this.ReturnType)));
            }

            var call = BinderHelpers.FindMagicMethod(bound.TargetType, TypeMethods.MagicMethods.__call);

            if (call != null)
            {
                // target.__call(name, array)
                var call_args = new Expression[]
                {
                    name_expr,
                    BinderHelpers.NewPhpArray(bound.Arguments),
                };
                return(OverloadBinder.BindOverloadCall(_returnType, bound.TargetInstance, call.Methods, bound.Context, call_args, false));
            }

            return(base.BindMissingMethod(bound));
        }
Пример #6
0
        protected virtual Expression BindMissingMethod(CallSiteContext bound)
        {
            /* Template:
             * PhpException.UndefinedFunctionCalled(name); // aka PhpException.Throw(Error, undefined_function_called, name)
             * return NULL;
             */
            var throwcall = Expression.Call(typeof(PhpException), "UndefinedFunctionCalled", Array.Empty <Type>(), bound.IndirectName ?? Expression.Constant(bound.Name));

            return(Expression.Block(throwcall, ConvertExpression.BindDefault(this.ReturnType)));
        }
Пример #7
0
        public override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObject[] args)
        {
            bool hasTargetInstance = (target.LimitType != typeof(TargetTypeParam));

            var bound = new CallSiteContext(!hasTargetInstance)
            {
                ClassContext = _classContext,
                Name         = _name
            }
            .ProcessArgs(target, args, hasTargetInstance);

            if (hasTargetInstance)
            {
                var isobject = bound.TargetType != null;
                if (isobject == false)
                {
                    var defaultexpr = ConvertExpression.BindDefault(_returnType);

                    if (!_access.Quiet())
                    {
                        // PhpException.VariableMisusedAsObject(target, _access.ReadRef)
                        var throwcall = BinderHelpers.VariableMisusedAsObject(target.Expression, _access.EnsureAlias());
                        defaultexpr = Expression.Block(throwcall, defaultexpr);
                    }

                    return(new DynamicMetaObject(defaultexpr, bound.Restrictions));
                }

                // instance := (T)instance
                bound.TargetInstance = Expression.Convert(bound.TargetInstance, bound.TargetType.Type);
            }

            Debug.Assert(IsClassConst ? (bound.TargetInstance == null) : true);

            //
            var getter = IsClassConst
                ? BinderHelpers.BindClassConstant(bound.TargetType, bound.ClassContext, bound.Name, bound.Context)
                : BinderHelpers.BindField(bound.TargetType, bound.ClassContext, bound.TargetInstance, bound.Name, bound.Context, _access, null);

            if (getter != null)
            {
                //
                return(new DynamicMetaObject(ConvertExpression.Bind(getter, _returnType, bound.Context), bound.Restrictions));
            }

            if (IsClassConst)
            {
                // error: constant not defined
                // ...
            }

            // unreachable: property not found
            throw new InvalidOperationException($"{bound.TargetType.Name}::{bound.Name} could not be resolved.");
        }
Пример #8
0
 protected override MethodBase[] ResolveMethods(CallSiteContext bound)
 {
     if (_name != null)
     {
         return(ResolveMethods(bound, _name, _nameOpt));
     }
     else
     {
         throw new NotImplementedException();
     }
 }
Пример #9
0
        protected virtual Expression BindMissingMethod(CallSiteContext bound)
        {
            /* Template:
             * PhpException.UndefinedFunctionCalled(name);
             * return NULL;
             */
            var throwcall = bound.TargetType != null
                ? Expression.Call(typeof(PhpException), "UndefinedMethodCalled", Array.Empty <Type>(), Expression.Constant(bound.TargetType.Name), bound.IndirectName ?? Expression.Constant(bound.Name))
                : Expression.Call(typeof(PhpException), "UndefinedFunctionCalled", Array.Empty <Type>(), bound.IndirectName ?? Expression.Constant(bound.Name));

            return(Expression.Block(throwcall, ConvertExpression.BindDefault(this.ReturnType)));
        }
Пример #10
0
        public override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObject[] args)
        {
            bool hasTargetInstance = (target.LimitType != typeof(TargetTypeParam));

            var bound = new CallSiteContext()
            {
                ClassContext = _classContext,
                Name         = _name
            }
            .ProcessArgs(target, args, hasTargetInstance);

            if (hasTargetInstance)
            {
                var isobject = bound.TargetType != null;
                if (isobject == false)
                {
                    var defaultexpr = ConvertExpression.BindDefault(_returnType);

                    if (!_access.Quiet())
                    {
                        // PhpException.VariableMisusedAsObject(target, _access.ReadRef)
                        var throwcall = Expression.Call(typeof(PhpException), "VariableMisusedAsObject", Array.Empty <Type>(),
                                                        ConvertExpression.BindToValue(target.Expression), Expression.Constant(_access.EnsureAlias()));
                        defaultexpr = Expression.Block(throwcall, defaultexpr);
                    }

                    return(new DynamicMetaObject(defaultexpr, bound.Restrictions));
                }

                // instance := (T)instance
                bound.TargetInstance = Expression.Convert(bound.TargetInstance, bound.TargetType.Type.AsType());
            }

            Debug.Assert(IsClassConst ? (bound.TargetInstance == null) : true);

            //
            var getter = IsClassConst
                ? BinderHelpers.BindClassConstant(bound.TargetType, bound.ClassContext, bound.Name, bound.Context)
                : BinderHelpers.BindField(bound.TargetType, bound.ClassContext, bound.TargetInstance, bound.Name, bound.Context, _access, null);

            if (getter != null)
            {
                //
                return(new DynamicMetaObject(ConvertExpression.Bind(getter, _returnType, bound.Context), bound.Restrictions));
            }

            // field not found
            throw new NotImplementedException();
        }
Пример #11
0
        protected override Expression BindMissingMethod(CallSiteContext bound)
        {
            var type = bound.TargetType;

            if (type == null)   // already reported - class cannot be found
            {
                return(ConvertExpression.BindDefault(this.ReturnType));
            }

            if (bound.TargetInstance != null && bound.CurrentTargetInstance != null) // it has been checked it is a subclass of TargetType
            {
                // ensure current scope's __call() is favoured over the specified class
                type = bound.CurrentTargetInstance.GetPhpTypeInfo();
            }

            var call = BinderHelpers.FindMagicMethod(type, (bound.TargetInstance == null) ? TypeMethods.MagicMethods.__callstatic : TypeMethods.MagicMethods.__call);

            if (call != null)
            {
                Expression[] call_args;

                var name_expr = (_name != null) ? Expression.Constant(_name) : bound.IndirectName;

                if (call.Methods.All(IsClrMagicCallWithParams))
                {
                    // Template: target.__call(name, arg1, arg2, ...)
                    // flatterns the arguments:
                    call_args = ArrayUtils.AppendRange(name_expr, bound.Arguments);
                }
                else
                {
                    // Template: target.__call(name, array)
                    // regular PHP behavior:
                    call_args = new Expression[]
                    {
                        name_expr,
                        BinderHelpers.NewPhpArray(bound.Arguments, bound.Context, bound.ClassContext),
                    };
                }

                return(OverloadBinder.BindOverloadCall(_returnType, bound.TargetInstance, call.Methods, bound.Context, call_args,
                                                       isStaticCallSyntax: true,
                                                       lateStaticType: bound.TargetType,
                                                       classContext: bound.ClassContext));
            }

            //
            return(base.BindMissingMethod(bound));
        }
Пример #12
0
        protected override MethodBase[] ResolveMethods(CallSiteContext bound)
        {
            // resolve target expression:
            var isobject = bound.TargetType != null;

            if (isobject == false)
            {
                return(null);    // no methods
            }

            // candidates:
            return(bound.TargetType
                   .SelectRuntimeMethods(bound.Name)
                   .SelectVisible(bound.ClassContext)
                   .ToArray());
        }
Пример #13
0
        void ISpecialParamHolder.Process(CallSiteContext info, Expression valueExpr)
        {
            if (valueExpr.Type != typeof(string))
            {
                throw new InvalidOperationException();
            }

            var name = (string)(object)Value;

            info.IndirectName = valueExpr;
            info.AddRestriction(Expression.Equal(valueExpr, Expression.Constant(name)));

            if (info.Name == null)
            {
                info.Name = name;
            }
        }
Пример #14
0
        protected override Expression BindMissingMethod(CallSiteContext bound)
        {
            var name_expr = (_name != null) ? Expression.Constant(_name) : bound.IndirectName;

            // resolve target expression:
            var isobject = bound.TargetType != null;

            if (isobject == false)
            {
                /* Template:
                 * PhpException.MethodOnNonObject(name_expr);
                 * return NULL;
                 */
                var throwcall = Expression.Call(typeof(PhpException), "MethodOnNonObject", Array.Empty <Type>(), ConvertExpression.Bind(name_expr, typeof(string), bound.Context));
                return(Expression.Block(throwcall, ConvertExpression.BindDefault(this.ReturnType)));
            }

            var call = BinderHelpers.FindMagicMethod(bound.TargetType, TypeMethods.MagicMethods.__call);

            if (call != null)
            {
                Expression[] call_args;

                if (call.Methods.All(IsClrMagicCallWithParams))
                {
                    // Template: target.__call(name, arg1, arg2, ...)
                    // flatterns the arguments:
                    call_args = ArrayUtils.AppendRange(name_expr, bound.Arguments);
                }
                else
                {
                    // Template: target.__call(name, array)
                    // regular PHP behavior:
                    call_args = new Expression[]
                    {
                        name_expr,
                        BinderHelpers.NewPhpArray(bound.Arguments, bound.Context, bound.ClassContext),
                    };
                }

                return(OverloadBinder.BindOverloadCall(_returnType, bound.TargetInstance, call.Methods, bound.Context, call_args, false));
            }

            return(base.BindMissingMethod(bound));
        }
Пример #15
0
        MethodBase[] ResolveMethods(CallSiteContext bound, string name, string nameOpt)
        {
            var routine = bound.CurrentContext.GetDeclaredFunction(name) ?? ((nameOpt != null) ? bound.CurrentContext.GetDeclaredFunction(nameOpt) : null);

            if (routine == null)
            {
                return(null);
            }

            if (routine is PhpRoutineInfo || routine is DelegateRoutineInfo)
            {
                Debug.Assert(routine.Index != 0);

                // restriction: ctx.CheckFunctionDeclared(index, routine.GetHashCode())
                var checkExpr = Expression.Call(
                    bound.Context,
                    typeof(Context).GetMethod("CheckFunctionDeclared", typeof(int), typeof(int)),
                    Expression.Constant(routine.Index), Expression.Constant(routine.GetHashCode()));

                bound.AddRestriction(checkExpr);
            }
            else if (routine is ClrRoutineInfo)
            {
                // CLR routines persist across whole app, no restriction needed
            }

            //
            var targetInstance = routine.Target;

            if (targetInstance != null)
            {
                bound.TargetInstance = Expression.Constant(targetInstance);
            }

            if (bound.TypeArguments != null && bound.TypeArguments.Length != 0)
            {
                // global functions cannot be (should not be) generic!
                throw new InvalidOperationException();  // NS
            }

            //
            return(routine.Methods);
        }
Пример #16
0
        public override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObject[] args)
        {
            bool hasTargetInstance = (target.LimitType != typeof(TargetTypeParam));

            var bound = new CallSiteContext(!hasTargetInstance)
            {
                ClassContext = _classContext,
                Name         = _name,
            }
            .ProcessArgs(target, args, hasTargetInstance);

            //
            if (hasTargetInstance)
            {
                var isobject = bound.TargetType != null;
                if (isobject == false)
                {
                    // VariableMisusedAsObject
                    return(new DynamicMetaObject(
                               BinderHelpers.VariableMisusedAsObject(target.Expression, false),
                               bound.Restrictions));
                }

                // instance := (T)instance
                bound.TargetInstance = Expression.Convert(bound.TargetInstance, bound.TargetType.Type.AsType());
            }

            //
            var setter = BinderHelpers.BindField(bound.TargetType, bound.ClassContext, bound.TargetInstance, bound.Name, bound.Context, _access, bound.Arguments.FirstOrDefault());

            if (setter != null)
            {
                //
                return(new DynamicMetaObject(setter, bound.Restrictions));
            }

            // field not found
            throw new NotImplementedException();
        }
Пример #17
0
 void ISpecialParamHolder.Process(CallSiteContext info, Expression valueExpr)
 {
     info.Context = valueExpr;
 }
Пример #18
0
 void ISpecialParamHolder.Process(CallSiteContext info, Expression valueExpr)
 {
     throw new InvalidOperationException();
 }
Пример #19
0
 void ISpecialParamHolder.Process(CallSiteContext info, Expression valueExpr)
 {
     info.AddRestriction(Expression.Call(valueExpr, Cache.Operators.RuntimeTypeHandle_Equals_RuntimeTypeHandle, Expression.Constant(Value)));
     info.ClassContext = Type.GetTypeFromHandle(Value);
 }
Пример #20
0
 void ISpecialParamHolder.Process(CallSiteContext info, Expression valueExpr)
 {
     throw new NotImplementedException();
 }
Пример #21
0
        MethodBase[] ResolveMethods(CallSiteContext bound, string name, string nameOpt)
        {
            var routine = bound.CurrentContext.GetDeclaredFunction(name) ?? ((nameOpt != null) ? bound.CurrentContext.GetDeclaredFunction(nameOpt) : null);

            if (routine == null)
            {
                // add restriction // https://github.com/iolevel/wpdotnet-sdk/issues/92

                // restriction: ctx.GetDeclaredFunction(name) == null
                var checkExpr = Expression.ReferenceEqual(
                    Expression.Call(bound.Context, Cache.Operators.GetDeclaredFunction_Context_String, Expression.Constant(name)),
                    Cache.Expressions.Null);

                bound.AddRestriction(checkExpr);

                if (nameOpt != null)
                {
                    // restriction: ctx.GetDeclaredFunction(nameOpt) == null
                    checkExpr = Expression.ReferenceEqual(
                        Expression.Call(bound.Context, Cache.Operators.GetDeclaredFunction_Context_String, Expression.Constant(nameOpt)),
                        Cache.Expressions.Null);

                    bound.AddRestriction(checkExpr);
                }

                return(null);
            }

            if (routine is PhpRoutineInfo || routine is DelegateRoutineInfo)
            {
                Debug.Assert(routine.Index != 0);

                // restriction: CheckFunctionDeclared(ctx, index, routine.GetHashCode())
                var checkExpr = Expression.Call(
                    Cache.Operators.CheckFunctionDeclared_Context_Int_Int,
                    bound.Context, Expression.Constant(routine.Index), Expression.Constant(routine.GetHashCode()));

                bound.AddRestriction(checkExpr);
            }
            else if (routine is ClrRoutineInfo)
            {
                // CLR routines persist across whole app, no restriction needed
            }

            //
            var targetInstance = routine.Target;

            if (targetInstance != null)
            {
                bound.TargetInstance = Expression.Constant(targetInstance);
            }

            if (bound.TypeArguments != null && bound.TypeArguments.Length != 0)
            {
                // global functions cannot be (should not be) generic!
                throw new InvalidOperationException();  // NS
            }

            //
            return(routine.Methods);
        }
Пример #22
0
 void ISpecialParamHolder.Process(CallSiteContext info, Expression valueExpr)
 {
     info.AddRestriction(BindingRestrictions.GetInstanceRestriction(valueExpr, Value));
     info.TargetType = Value;
 }
Пример #23
0
 void ISpecialParamHolder.Process(CallSiteContext info, Expression valueExpr)
 {
     info.LateStaticType = valueExpr;
 }
Пример #24
0
 /// <summary>
 /// Resolves methods to be called.
 /// </summary>
 protected abstract MethodBase[] ResolveMethods(CallSiteContext bound);