#1317 Multiple dispatch - proof of concept

ivan Mon 15 Nov 2010

Hi,

Today I've created pod for support of multiple dispatch at runtime, see http://bitbucket.org/ivan_inozemtsev/mdispatch. The dispatcher itself is very simple constant class whichallows to create container of functions:

d := Dispatcher {
    funcs = [
        |Foo a, Bar b -> Str | { "foo vs bar" },
        |Bar a, Foo b -> Str | { "bar vs foo" },
      ]
  }

and invoke appropriate function by calling call(Obj?[] args):

verifyEq("foo vs bar", d.call([foo, bar]))
verifyEq("bar vs foo", d.call([bar, foo]))

The more interesting thing here is DSL plugin. Sample code (synthetic example):

class SampleProcessor
{
  Obj?[] list := [,]

  @Dispatch SampleProcessor processStr(Str s) { list.add(s); return this }

  @Dispatch SampleProcessor processInt(Int i) { list.add(i); return this }

  SampleProcessor process(Obj? obj) {
    Dispatcher<|process|>.call([this, obj])
  }

  override Str toStr() { list.toStr }
}

Usage example:

s := SampleProcessor()
echo(s.process(10)) //types [10]
echo(s.process("aaa")) //types [10, aaa]

The DSL plugin searches for all methods with a given prefix marked with @Dispatch facet and the code become equivalent to this:

SampleProcessor process(Obj? obj) { processDispatcher.call([this, obj]) }
private const Dispatcher processDispatcher := Dispatcher(
  "process", 
  SampleProcessor#, 
  [#processStr.func, #processInt.func]
)

Combined with @Operator facet, this can give an ability to use operator overloading with runtime method selection.

Few notes:

  • The performance is quite low comparing to normal method calls (about 20 times)
  • right now the code uses some hacks in compiler, for example the code won't work in some "unexpected" cases:
    • Two types using @Dispatch facet are defined in the same file
    • There are no field initializers in this class
  • I'm going to play with it and probably use in F4 code (a lot of code dealing with AST nodes can be simplified)

EDIT: added bitbucket link

Login or Signup to reply.