# Code Review: NewMethodBinder

**URL:** <https://www.ruby-forum.com/t/code-review-newmethodbinder/164961>\
**Category:** IronRuby\
**Created:** [April 7, 2009, 9:03pm UTC](https://www.ruby-forum.com/t/code-review-newmethodbinder/164961 "2009-04-07T21:03:49Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![grujildo](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/94ad74/32.png) [@grujildo](https://www.ruby-forum.com/u/grujildo)\
**Post date:** [April 7, 2009, 9:03pm UTC](https://www.ruby-forum.com/t/code-review-newmethodbinder/164961/1 "2009-04-07T21:03:49Z")

</div>

Tfpt review /shelveset:NewMethodBinder;tomat

Affects outer DLR, Python, Ruby.

DLR, Python

Redesigns the default method binder:

- 

```
     Merges ParameterBinder into MethodBinder, moves virtual 

```

methods related to CLR method binding and parameter conversions from  
ActionBinder and DefaultBinder to MethodBinder.

- 

```
     MethodBinder is now an abstract class that provides virtuals 

```

that languages can override. DefaultMethodBinder provides simple  
implementation that languages can base their binders on or directly use.

- 

```
     Enables "partially restricted splatting" feature (only 

```

implemented in Ruby so far, but should be relatively easy to generalize  
it and use it by default):

- 

```
     Previous implementation required languages to pass the binder 

```

an array of meta-objects including all items of the splatted array. This  
is not feasible for splatting arrays containing thousands of items  
(StackOverflow exception occurred in a Ruby library due to an expression  
of depth greater than 5k constructed as a rule condition). The new  
implementation allows the binder to only construct such conditions and  
restrictions that are necessary to decide which overload to select. In  
the worse case, which occurs e.g. when the overload set is { foo(params  
int[]), foo(params object[]) } and the call-site is foo(\*([1]\*10000 +  
[‘x’])) , the condition that decides whether an overload/rule is  
applicable is implemented using a loop rather than disjunction of 10001  
type equality expressions. Usually, the overload could be selected by  
splatting the array partially, using few items of the array from  
beginning and/or end of the array. More optimizations to the partial  
splatting are certainly possible - those should be easy to implement on  
top of the new method binder architecture if needed.

- 

```
     MethodBinder builds its state in several steps (see 

```

ResolveOverload method):

1. 

```
 TargetSets and MethodCadnidates are built - MethodCandidate 

```

represents a CLR method overload tailored to a fixed arity (a follow-up  
refactoring will merge MethodTarget into MethodCandidate, they map 1:1).  
TargetSet represents a set of MethodCandidates (CanidateSet would be a  
better name - will rename in a follow-up change) that match the same  
arity. Building MethodCandidates involve creating ParameterWrappers and  
ArgBuilders. This process can be customized by languages. Languages can  
define their own wrappers and builders, their own dictionary and array  
splatting mechanisms.

1. 

```
 The ActualArguments class is created (this is also customizable 

```

by languages). ActualArguments instance holds on meta-objects of  
positional and named arguments, actual argument names, and various  
indices needed for splatting.

1. 

```
 TargetSet with arity corresponding to the number of actual 

```

arguments is created. If the binder implements partial splatting, the  
array is splatted to match arities of existing target sets but no more.  
The rest of the arguments (those that were not extracted from the array)  
are referred to as “collapsed” and are dealt with separately during  
overload resolution. The previous implementation of “MakeBindingTarget”  
is replaced by a new one, which fixes issues with named arguments and  
also takes collapsed arguments into consideration. It has several steps:

a. Match actual names of the arguments with parameter names,  
calculate permutations that map indices of the former to the latter, and  
filter out MethodCandidates whose parameter names don’t match. The  
result of this step is a set of ApplicableCandidates, each  
ApplicableCandidate comprises of a MethodCandidate and a ArgumentBinding  
permutation.

b. Then for each narrowing level: Non-collapsed arguments are  
tested for convertibility to the parameter types of the applicable  
overloads. Those overloads that don’t match are removed from applicable  
candidates set. If no overloads remain, it’s an error. If a single  
overload remains we successfully chosen the overload (note that  
collapsed arguments don’t need to be visited in this case). Otherwise we  
check whether collapsed arguments can all be converted to the element  
type of the corresponding params-array. Again, if no candidate remains,  
we failed. If a single one remains we succeeded. Otherwise we continue  
by comparing various conversions and selecting the best ones based on  
the current narrowing level.

- 

```
     During these steps the MethodBinder builds its state 

```

(candidate sets, actual arguments, etc.) and derived method binders can  
also remember some additional data/state that is used for building  
arguments or error reporting (temporary variable that stores the  
splattee, restrictions/conditions used for splatting, the signature of  
the call-site, etc.). The MethodBinder should be instantiated with all  
information that doesn’t change during overload resolution (the “input”  
to the overload resolution).

- 

```
     Renames ParameterBinderWithCodeContext to PythonMethodBinder 

```

and moves it to Python.

- 

```
     Moves SiteLocalStorage to Python. Ruby uses a different 

```

storage class and it’s very simple for languages to define and use their  
own.

- 

```
     ActionBinder.BindSpecialParameter shouldn't deal with 

```

CodeContext and SiteLocalStorage - moved to PythonMethodBinder.

- 

```
     Moved ContextArgBuilder and SiteLocalStorageArgbuilder to 

```

Python.

- 

```
     ArgBuilder.CanGenerateDelegate needs to be protected so that 

```

custom ArgBuilders can override it.

- 

```
     Improves errors reported by the method binder.

```

- 

```
     Removes old call, invoke and operation actions and related 

```

code.

Ruby:

- 

```
     Replaces calls to obsolete methods of default method binder 

```

with those using meta-objects.

- 

```
     Implements partially restricted splatting.

```

Fixes  
[http://ironpython.codeplex.com/WorkItem/View.aspx?WorkItemId=18379](http://ironpython.codeplex.com/WorkItem/View.aspx?WorkItemId=18379).
