My pet project is PEC which is a Java compiler with pattern
enforcement, one of the patterns I have implement is multiple dispatch
(http://pec.dev.java.net/nonav/compile/javadoc/pec/compile/
multipledispatch/package-summary.html).

Selecting the method in multiple dispatch is not as tricky as in some
dynamic languages; all that can happen in multiple dispatch is that
new methods that are more specific than existing methods can be added,
you can't take a method away and you can't introduce a completely new
method signature. These restrictions obviously make life easier, but I
thought people might still be interested to see what I did since the
source is well documented and available (LPGL).

The long explanation is here:
https://pec.dev.java.net/nonav/compile/javadoc/pec/compile/multipledispatch/package-summary.html#HowItWorks
and the long form includes an example.

The short explanation is best illustrated with an example. Suppose you
wanted to implement a visitor but use multiple dispatch to clean up
the code (there are other benefits in addition to clearer code -
http://pec.dev.java.net/nonav/compile/javadoc/pec/compile/multipledispatch/package-summary.html#WalkingAnExpressionTree):

interface Visitor extends MultipleDispatch { void visit( Object ); }
class AbstractTree implements Visitor {
  public final void visit( Object o ) {} // Body replaced by PEC
  public static final void visit( Visitor self, Map m ) { ... } //
Could be in *any* class
  public static final void visit( Visitor self, List l ) { ... } //
Could be in *any* class
}

The process is:

1. For multiple-dispatch interfaces (Visitor) an abstract-dispatcher
class and a proxy class are written for each method (visit)

1a. An abstract-dispatcher class (VisitorDispatcher) is written by the
PEC that contains a method (dispatch) with the same signature as the
multiple-dispatch method (visit), but with the receiver (Visitor)
added as the first argument, i.e. void dispatch( Visitor, Object )

1b. A proxy class (VistitorProxy) is written by the PEC contains two
fields: a list (methods) which is a TreeList and an abstract-
dispatcher given a name based on the method's name, visit. TreeList is
a sorted list that ranks the methods depending on 'how far' they are
from the definition in the interface, there is one unit of depth per
level in the type hierarchy per argument.

2. The body of the dummy-instance method is replaced by a call to a
specific dispatcher via the proxy class's dispatch field, i.e.
VisitorProxy.visit.dispatch( this, o );

3. Adds a static initializer to each multiple-dispatch class that adds
a multiple-dispatch methods in the class to the list of methods in the
proxy field methods, writes a new dispatcher class, and assigns an
instance of this new dispatcher class to dispatching proxy field.

3a. When a multiple-dispatch class is loaded the Javassist API is used
to find the multiple-dispatch methods in the class

3b. The multiple-dispatch methods found are remembered in the proxy
class's list field, methods

3c. The list, methods, is sorted so that the most specific methods
come first

3d. Generates a new dispatcher class that decides which of the
multiple-dispatch methods available is the most specific

3e. Assigns the new dispatcher class to the dispatching proxy field


(In the above example short names are given for the classes written by
the PEC - in practice longer names that guarantee uniqueness are used
- but the above code reads better with short names!)


On Dec 7, 11:20 am, Jochen Theodorou <[EMAIL PROTECTED]> wrote:
> Hi all,
>
> I am sorry that I can not spend much time on this list atm, I am feed up
> with the 1.1 Groovy release... yesterday I fixed some bugs in the method
> selection process and I began to as how other languages do the selection
> process, because the Groovy way is a bit complicated and maybe we find
> some improvements. This will could speed up the method selection process
> very much for more than only Groovy. Of course I know that this depends
> on the language very much too.. I am which calls are valid and which
> overloaded method should be preferred over another overloaded method and
> these things.  And I am not sure that many languages have to deal with
> this kind of thing at runtime...
>
> anyway I will outline the process in Groovy:
>
> 1) build a list of all methods with the name of the method we want to calls
> 2) remove the methods that are not valid for the call
> 3) if more than one method remains calculate the "method distance"
> between the call and the method
> 4) the method with my minimum distance will be selected
> 5) if at the end I have two or more methods with the same minimum
> distance I have to report an error
>
> this distance calculation consists of calculating a distance between
> parameter class and argument class (class distance) and then sum it up
> for all of them plus additional functionality for vargs. This class
> distance consists for normal classes of counting how many super classes
> of the argument class I have to go through until I meat the parameter
> class. the algorithm gets even more complicated through interfaces and
> primitive types.
>
> An improvement would be to not to calculate this distance directly, but
> to calculate a distance to a generalized call and then cache it for the
> method... if it works well, then a simple subtraction (plus vargs) would
> give the distance and this would be pretty fast then.
>
> So.. how do other languages do that?
>
> bye blackdrag
>
> --
> Jochen "blackdrag" Theodorou
> The Groovy Project Tech Lead 
> (http://groovy.codehaus.org)http://blackdragsview.blogspot.com/http://www.g2one.com/
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "JVM 
Languages" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/jvm-languages?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to