Provides binding and overload resolution to .NET methods. MethodBinder's can be used for: generating new AST code for calling a method calling a method via reflection at runtime (not implemented) performing an abstract call MethodBinder's support default arguments, optional arguments, by-ref (in and out), and keyword arguments. Implementation Details: The MethodBinder works by building up a CandidateSet for each number of effective arguments that can be passed to a set of overloads. For example a set of overloads such as: foo(object a, object b, object c) foo(int a, int b) would have 2 target sets - one for 3 parameters and one for 2 parameters. For parameter arrays we fallback and create the appropriately sized CandidateSet on demand. Each CandidateSet consists of a set of MethodCandidate's. Each MethodCandidate knows the flattened parameters that could be received. For example for a function such as: foo(params int[] args) When this method is in a CandidateSet of size 3 the MethodCandidate takes 3 parameters - all of them ints; if it's in a CandidateSet of size 4 it takes 4 parameters. Effectively a MethodCandidate is a simplified view that allows all arguments to be treated as required positional arguments. Each MethodCandidate in turn refers to a MethodTarget. The MethodTarget is composed of a set of ArgBuilder's and a ReturnBuilder which know how to consume the positional arguments and pass them to the appropriate argument of the destination method. This includes routing keyword arguments to the correct position, providing the default values for optional arguments, etc... After binding is finished the MethodCandidates are thrown away and a BindingTarget is returned. The BindingTarget indicates whether the binding was successful and if not any additional information that should be reported to the user about the failed binding. It also exposes the MethodTarget which allows consumers to get the flattened list of required parameters for the call. MethodCandidates are not exposed and are an internal implementation detail of the MethodBinder.
Example #1
0
        internal protected override Expression ToExpression(OverloadResolver resolver, RestrictedArguments args, bool[] hasBeenUsed) {
            if (_tmp == null) {
                _tmp = resolver.GetTemporary(_elementType, "outParam");
            }

            Debug.Assert(!hasBeenUsed[Index]);
            hasBeenUsed[Index] = true;
            Expression arg = args.GetObject(Index).Expression;

            return Expression.Condition(
                Expression.TypeIs(arg, Type),
                Expression.Assign(
                    _tmp,
                    Expression.Field(
                        AstUtils.Convert(arg, Type),
                        Type.GetField("Value")
                    )
                ),
                Expression.Throw(
                    Expression.Call(
                        new Func<Type, object, Exception>(RuntimeHelpers.MakeIncorrectBoxTypeError).Method,
                        AstUtils.Constant(_elementType),
                        AstUtils.Convert(arg, typeof(object))
                    ),
                    _elementType
                )
            );
        }
        internal protected override Expression ToExpression(OverloadResolver resolver, RestrictedArguments args, bool[] hasBeenUsed) {
            if (_tmp == null) {
                _tmp = resolver.GetTemporary(Type, "outParam");
            }

            return Ast.Block(Ast.Assign(_tmp, base.ToExpression(resolver, args, hasBeenUsed)), _tmp);
        }
Example #3
0
        internal override Expression ToExpression(OverloadResolver resolver, IList<ArgBuilder> builders, RestrictedArguments args, Expression ret) {
            if (_returnArgs.Count == 1) {
                if (_returnArgs[0] == -1) {
                    return ret;
                }
                return Ast.Block(ret, builders[_returnArgs[0]].ToReturnExpression(resolver));
            }

            Expression[] retValues = new Expression[_returnArgs.Count];
            int rIndex = 0;
            bool usesRet = false;
            foreach (int index in _returnArgs) {
                if (index == -1) {
                    usesRet = true;
                    retValues[rIndex++] = ret;
                } else {
                    retValues[rIndex++] = builders[index].ToReturnExpression(resolver);
                }
            }

            Expression retArray = AstUtils.NewArrayHelper(typeof(object), retValues);
            if (!usesRet) {
                retArray = Ast.Block(ret, retArray);
            }

            return resolver.GetByRefArrayExpression(retArray);
        }
Example #4
0
        internal override Expression ToReturnExpression(OverloadResolver resolver) {
            if (_isRef) {
                return _tmp;
            }

            return GetDefaultValue();
        }
        internal protected override Expression ToExpression(OverloadResolver resolver, IList<Expression> parameters, bool[] hasBeenUsed) {
            if (_tmp == null) {
                _tmp = resolver.GetTemporary(Type, "outParam");
            }

            return Ast.Block(Ast.Assign(_tmp, base.ToExpression(resolver, parameters, hasBeenUsed)), _tmp);
        }
Example #6
0
        internal protected override Expression ToExpression(OverloadResolver resolver, RestrictedArguments args, bool[] hasBeenUsed) {
            if (_tmp == null) {
                _tmp = resolver.GetTemporary(_elementType, "outParam");
            }

            Debug.Assert(!hasBeenUsed[Index]);
            hasBeenUsed[Index] = true;
            Type boxType = typeof(StrongBox<>).MakeGenericType(_elementType);
            Expression arg = args.GetObject(Index).Expression;

            return Expression.Condition(
                Expression.TypeIs(arg, Type),
                Expression.Assign(
                    _tmp,
                    Expression.Field(
                        AstUtils.Convert(arg, boxType),
                        boxType.GetField("Value")
                    )
                ),
                Expression.Call(
                    typeof(RuntimeHelpers).GetMethod("IncorrectBoxType").MakeGenericMethod(_elementType),
                    AstUtils.Convert(arg, typeof(object))
                )
            );
        }
Example #7
0
        internal protected override Expression ToExpression(OverloadResolver resolver, IList<Expression> parameters, bool[] hasBeenUsed) {
            Debug.Assert(BuilderExpectsSingleParameter(_builder));

            int index = GetKeywordIndex(parameters.Count);
            Debug.Assert(!hasBeenUsed[index]);
            hasBeenUsed[index] = true;
            return _builder.ToExpression(resolver, new Expression[] { parameters[index] }, new bool[1]);
        }
Example #8
0
        internal protected override Expression ToExpression(OverloadResolver resolver, RestrictedArguments args, bool[] hasBeenUsed) {
            Debug.Assert(BuilderExpectsSingleParameter(_builder));

            int index = GetKeywordIndex(args.Length);
            Debug.Assert(!hasBeenUsed[index]);
            hasBeenUsed[index] = true;
            return _builder.ToExpression(resolver, MakeRestrictedArg(args, index), new bool[1]);
        }
Example #9
0
        internal ParameterMapping(OverloadResolver resolver, OverloadInfo method, IList<string> argNames) {
            Assert.NotNull(resolver, method);
            _resolver = resolver;
            _overload = method;
            _argNames = argNames;
            _parameters = new List<ParameterWrapper>();
            _arguments = new List<ArgBuilder>(method.ParameterCount);
            _defaultArguments = new List<ArgBuilder>();
	    }
Example #10
0
        internal protected override Expression ToExpression(OverloadResolver resolver, IList<Expression> parameters, bool[] hasBeenUsed) {
            Expression res = Ast.Call(
                typeof(BinderOps).GetMethod("MakeSymbolDictionary"),
                Ast.NewArrayInit(typeof(string), ConstantNames()),
                AstUtils.NewArrayHelper(typeof(object), GetParameters(parameters, hasBeenUsed))
            );

            return res;
        }
Example #11
0
        internal protected override Expression ToExpression(OverloadResolver resolver, RestrictedArguments args, bool[] hasBeenUsed) {
            Type dictType = ParameterInfo.ParameterType;

            return Ast.Call(
                GetCreationDelegate(dictType).Method,
                Ast.NewArrayInit(typeof(string), ConstantNames()),
                AstUtils.NewArrayHelper(typeof(object), GetParameters(args, hasBeenUsed))
            );
        }
Example #12
0
 internal override Expression UpdateFromReturn(OverloadResolver resolver, IList<Expression> parameters) {
     return Expression.Assign(
         Expression.Field(
             Expression.Convert(parameters[Index], Type),
             Type.GetField("Value")
         ),
         _tmp
     );
 }
Example #13
0
 internal override Expression UpdateFromReturn(OverloadResolver resolver, RestrictedArguments args) {
     return Expression.Assign(
         Expression.Field(
             Expression.Convert(args.GetObject(Index).Expression, Type),
             Type.GetField("Value")
         ),
         _tmp
     );
 }
Example #14
0
        internal protected override Expression ToExpression(OverloadResolver resolver, RestrictedArguments args, bool[] hasBeenUsed) {
            if (_isRef) {
                if (_tmp == null) {
                    _tmp = resolver.GetTemporary(_parameterType, "outParam");
                }
                return _tmp;
            }

            return GetDefaultValue();
        }
        internal ParameterMapping(OverloadResolver resolver, MethodBase method, ParameterInfo[] parameterInfos, IList<string> argNames) {
            Assert.NotNull(resolver, method);
            _resolver = resolver;
            _method = method;
            _argNames = argNames;
            _parameterInfos = parameterInfos ?? method.GetParameters();
            _parameters = new List<ParameterWrapper>();
            _arguments = new List<ArgBuilder>(_parameterInfos.Length);
            _defaultArguments = new List<ArgBuilder>();
	    }
Example #16
0
        internal protected override Expression ToExpression(OverloadResolver resolver, RestrictedArguments args, bool[] hasBeenUsed) {
            object value = ParameterInfo.DefaultValue;
            if (value is Missing) {
                value = CompilerHelpers.GetMissingValue(ParameterInfo.ParameterType);
            }

            if (ParameterInfo.ParameterType.IsByRef) {
                return AstUtils.Constant(value, ParameterInfo.ParameterType.GetElementType());
            }

            var metaValue = new DynamicMetaObject(AstUtils.Constant(value), BindingRestrictions.Empty, value);
            return resolver.Convert(metaValue, CompilerHelpers.GetType(value), ParameterInfo, ParameterInfo.ParameterType);
        }
Example #17
0
        internal protected virtual Expression ToExpression(ref MethodInfo method, OverloadResolver resolver, RestrictedArguments args, bool[] hasBeenUsed) {
            if (_index == -1) {
                return AstUtils.Constant(null);
            }

            Debug.Assert(hasBeenUsed.Length == args.Length);
            Debug.Assert(_index < args.Length);
            Debug.Assert(!hasBeenUsed[_index]);
            hasBeenUsed[_index] = true;

            GetCallableMethod(args, ref method);
            return resolver.Convert(args.GetObject(_index), args.GetType(_index), null, method.DeclaringType);
        }
Example #18
0
 protected internal override Func<object[], object> ToDelegate(OverloadResolver resolver, RestrictedArguments args, bool[] hasBeenUsed) {
     if (ParameterInfo.ParameterType.IsByRef) {
         return null;
     } else if (ParameterInfo.DefaultValue is Missing && CompilerHelpers.GetMissingValue(ParameterInfo.ParameterType) is Missing) {
         // reflection throws when we do this
         return null;
     }
     
     object val = ParameterInfo.DefaultValue;
     if (val is Missing) {
         val = CompilerHelpers.GetMissingValue(ParameterInfo.ParameterType);
     }
     Debug.Assert(val != Missing.Value);
     return (_) => val;
 }
Example #19
0
        internal protected virtual Func<object[], object> ToDelegate(ref MethodInfo method, OverloadResolver resolver, RestrictedArguments args, bool[] hasBeenUsed) {
            if (_index == -1) {
                return (_) => null;
            }

            GetCallableMethod(args, ref method);

            Func<object[], object> conv = resolver.GetConvertor(_index + 1, args.GetObject(_index), null, method.DeclaringType);
            if (conv != null) {
                return conv;
            }

            return (Func<object[], object>)Delegate.CreateDelegate(
                typeof(Func<object[], object>),
                _index + 1,
                typeof(ArgBuilder).GetMethod("ArgumentRead"));
        }
Example #20
0
        internal MethodCandidate(OverloadResolver resolver, MethodBase method, List<ParameterWrapper> parameters, ParameterWrapper paramsDict,
            ReturnBuilder returnBuilder, ArgBuilder instanceBuilder, IList<ArgBuilder> argBuilders) {

            Assert.NotNull(resolver, method, instanceBuilder, returnBuilder);
            Assert.NotNullItems(parameters);
            Assert.NotNullItems(argBuilders);

            _resolver = resolver;
            _method = method;
            _instanceBuilder = instanceBuilder;
            _argBuilders = argBuilders;
            _returnBuilder = returnBuilder;
            _parameters = parameters;
            _paramsDict = paramsDict;

            _paramsArrayIndex = ParameterWrapper.IndexOfParamsArray(parameters);

            parameters.TrimExcess();
        }
Example #21
0
        internal MethodCandidate(OverloadResolver resolver, OverloadInfo method, List<ParameterWrapper> parameters, ParameterWrapper paramsDict,
            ReturnBuilder returnBuilder, InstanceBuilder instanceBuilder, IList<ArgBuilder> argBuilders, Dictionary<DynamicMetaObject, BindingRestrictions> restrictions) {

            Assert.NotNull(resolver, method, instanceBuilder, returnBuilder);
            Assert.NotNullItems(parameters);
            Assert.NotNullItems(argBuilders);

            _resolver = resolver;
            _overload = method;
            _instanceBuilder = instanceBuilder;
            _argBuilders = argBuilders;
            _returnBuilder = returnBuilder;
            _parameters = parameters;
            _paramsDict = paramsDict;
            _restrictions = restrictions;

            _paramsArrayIndex = ParameterWrapper.IndexOfParamsArray(parameters);

            parameters.TrimExcess();
        }
 internal protected override Expression ToExpression(OverloadResolver resolver, RestrictedArguments args, bool[] hasBeenUsed) {
     Debug.Assert(hasBeenUsed.Length == args.Length);
     Debug.Assert(_index < args.Length);
     Debug.Assert(!hasBeenUsed[Index]);
     
     hasBeenUsed[_index] = true;
     return resolver.Convert(args.GetObject(_index), args.GetType(_index), ParameterInfo, _parameterType);
 }
        protected internal override Func<object[], object> ToDelegate(OverloadResolver resolver, RestrictedArguments args, bool[] hasBeenUsed) {
            Func<object[], object> conv = resolver.GetConvertor(_index + 1, args.GetObject(_index), ParameterInfo, _parameterType);
            if (conv != null) {
                return conv;
            }

            return (Func<object[], object>)Delegate.CreateDelegate(
                typeof(Func<object[], object>), 
                _index + 1, 
                typeof(ArgBuilder).GetMethod("ArgumentRead"));
        }
Example #24
0
 internal override Expression ToReturnExpression(OverloadResolver resolver)
 {
     return _builder.ToReturnExpression(resolver);
 }
Example #25
0
 protected override Expression ToExpression(OverloadResolver/*!*/ resolver, RestrictedArguments/*!*/ args, bool[]/*!*/ hasBeenUsed) {
     Debug.Assert(Index < args.Length);
     Debug.Assert(Index < hasBeenUsed.Length);
     hasBeenUsed[Index] = true;
     return null;
 }
Example #26
0
        protected internal override Func<object[], object> ToDelegate(OverloadResolver resolver, RestrictedArguments args, bool[] hasBeenUsed) {
            string[] names = _names;
            int[] indexes = GetParameters(hasBeenUsed);

            Type dictType = ParameterInfo.ParameterType;

            Func<string[], object[], object> func = GetCreationDelegate(dictType);

            return (actualArgs) => {
                object[] values = new object[indexes.Length];
                for (int i = 0; i < indexes.Length; i++) {
                    values[i] = actualArgs[indexes[i] + 1];
                }
                return func(names, values);
            };
        }
 protected override Expression ToExpression(OverloadResolver resolver, RestrictedArguments args, bool[] hasBeenUsed) {
     return AstUtils.Constant(Activator.CreateInstance(ParameterInfo.ParameterType));
 }
 protected override Func<object[], object> ToDelegate(OverloadResolver resolver, RestrictedArguments args, bool[] hasBeenUsed) {
     object value = Activator.CreateInstance(ParameterInfo.ParameterType);
     return (_) => value;
 }
Example #29
0
 internal override Expression UpdateFromReturn(OverloadResolver resolver, RestrictedArguments args)
 {
     int index = GetKeywordIndex(args.Length);
     return _builder.UpdateFromReturn(resolver, MakeRestrictedArg(args, index));
 }
Example #30
0
 protected override Func<object[], object> ToDelegate(ref MethodInfo/*!*/ method, OverloadResolver/*!*/ resolver, RestrictedArguments/*!*/ args, bool[]/*!*/ hasBeenUsed) {
     return null;
 }