@@ 9,6 9,6 @@ def method(*types):
gf = _METHS.get(name)
if gf is None:
gf = _METHS[name] = mm.GF()
- gf.add_rule(types, meth)
+ gf.register(types, meth)
return gf
return _wrap
@@ 5,46 5,38 @@ def proximity(klass, mro):
def lexicographic_mro(signature, matches):
"dispatch ranking similar to CLOS"
- mros = [klass.mro() for klass in signature]
- for (sig,func),i in zip(matches,xrange(1000)):
- matches[i] = (map(proximity, sig, mros), matches[i])
- matches.sort(reverse=True)
- return map(lambda t:t[1], matches)
-
-def signature(*args):
- return tuple(o.__class__ for o in args)
+ mros = tuple(klass.mro() for klass in signature)
+ return sorted((map(proximity, sig, mros), func)
+ for sig, func in matches)
class GF(object):
def __init__(self):
self._table = []
+ self._cache = {}
- def add_rule(self, sig, func):
- self._table.append((sig, func))
+ def register(self, sig, func):
+ self._table.append((tuple(sig), func))
self._cache = {}
def __call__(self, *args):
- sig = signature(*args)
- self._pos = 0
- if sig not in self._cache:
- self._funcs = self.linearized_table(sig)
- func = self._funcs.pop()
- self._cache[sig] = func
- else:
- func = self._cache[sig]
+ sig = tuple(x.__class__ for x in args)
+ func = self._cache.get(sig)
+ if func is None:
+ self._funcs = self.compute_mro(sig)
+ try:
+ self._cache[sig] = func = self._funcs.next()
+ except StopIteration:
+ raise TypeError('no defined call signature args (%s)' % args)
return func(*args)
def next_method(self, *args):
- func = self._funcs.pop()
+ func = self._funcs.next()
return func(*args)
- def linearized_table(self, sig):
- table = [(s,f) for s,f in self._table
- if len(s) == len(sig)
- and reduce(mul, map(issubclass, sig, s))]
- if not table:
- def nomatch(*a):
- raise TypeError('no defined call signature <%s> for args (%s)' %
- (','.join([str(o) for o in sig]), a))
- return [nomatch]
- return map(lambda l:l[1], lexicographic_mro(sig, table))
+ def compute_mro(self, callsig):
+ siglen = len(callsig)
+ table = ((sig, func) for sig, func in self._table
+ if len(sig) == siglen
+ and reduce(mul, map(issubclass, callsig, sig)))
+ return (x[1] for x in lexicographic_mro(callsig, table))
@@ 108,7 108,7 @@ class TestGF(unittest.TestCase):
def foo(b,x):
return b,x
b, y = B(), Y()
- print foo(b, y)
+ foo(b, y)
if __name__ == '__main__':
unittest.main()