1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
|
from rpython.tool.pairtype import (
pairtype, pair, extendabletype, pairmro, DoubleDispatchRegistry,
doubledispatch)
def test_binop():
### Binary operation example
class __extend__(pairtype(int, int)):
def add((x, y)):
return 'integer: %s+%s' % (x, y)
def sub((x, y)):
return 'integer: %s-%s' % (x, y)
class __extend__(pairtype(bool, bool)):
def add((x, y)):
return 'bool: %s+%s' % (x, y)
assert pair(3, 4).add() == 'integer: 3+4'
assert pair(3, 4).sub() == 'integer: 3-4'
assert pair(3, True).add() == 'integer: 3+True'
assert pair(3, True).sub() == 'integer: 3-True'
assert pair(False, 4).add() == 'integer: False+4'
assert pair(False, 4).sub() == 'integer: False-4'
assert pair(False, True).add() == 'bool: False+True'
assert pair(False, True).sub() == 'integer: False-True'
def test_somebuiltin():
### Operation on built-in types
class MiniPickler:
def __init__(self):
self.data = []
def emit(self, datum):
self.data.append(datum)
class __extend__(pairtype(MiniPickler, int)):
def write((pickler, x)):
pickler.emit('I%d' % x)
class __extend__(pairtype(MiniPickler, str)):
def write((pickler, x)):
pickler.emit('S%s' % x)
class __extend__(pairtype(MiniPickler, list)):
def write((pickler, x)):
for item in x:
pair(pickler, item).write()
pickler.emit('L%d' % len(x))
p = MiniPickler()
pair(p, [1, 2, ['hello', 3]]).write()
assert p.data == ['I1', 'I2', 'Shello', 'I3', 'L2', 'L3']
def test_some_multimethod():
### Another multimethod example
class Block:
def __init__(self, exit):
self.exit = exit
class Jump:
pass
class Switch:
pass
class C_Generator:
def __init__(self):
self.lines = []
class __extend__(pairtype(C_Generator, Block)):
def emit((gen, block), inputvars):
gen.lines.append("C code for block")
outputvars = inputvars + ['v4', 'v5']
pair(gen, block.exit).emit(outputvars)
class __extend__(pairtype(C_Generator, Jump)):
def emit((gen, jump), inputvars):
gen.lines.append("goto xyz")
class __extend__(pairtype(C_Generator, Switch)):
def emit((gen, jump), inputvars):
gen.lines.append("switch (%s) { ... }" % inputvars[-1])
g = C_Generator()
pair(g, Block(Switch())).emit(['v1', 'v2'])
assert g.lines == ["C code for block", "switch (v5) { ... }"]
class Lisp_Generator:
def __init__(self):
self.progn = []
class __extend__(pairtype(Lisp_Generator, Block)):
def emit((gen, block), inputvars):
gen.progn.append("(do 'something)")
g = Lisp_Generator()
pair(g, Block(Switch())).emit(['v1', 'v2'])
assert g.progn == ["(do 'something)"]
def test_multiple_extend():
class A:
__metaclass__ = extendabletype
class B:
__metaclass__ = extendabletype
class __extend__(A, B):
def f(self):
pass
assert hasattr(A, 'f')
assert hasattr(B, 'f')
def test_pairmro():
class A(object): pass
class A2(A): pass
class A3(A2): pass
class B(object): pass
class B2(B): pass
parent_pairtypes = pairtype(A3, B2).__mro__[:-2]
assert (tuple(pairtype(a, b) for a, b in pairmro(A3, B2)) == parent_pairtypes)
def test_doubledispatch_registry():
class A(object): pass
class A2(A): pass
class A3(A2): pass
class B(object): pass
class B2(B): pass
reg = DoubleDispatchRegistry()
reg[object, object] = "default"
assert reg[A3, B2] == "default"
reg[A2, B2] = "A2-B2"
assert reg[A, B2] == "default"
assert reg[A3, B2] == "A2-B2"
reg[A3, B] = "A3-B"
assert reg[A3, B2] == "A2-B2" # note that A2,B2 wins over A3,B
def test_doubledispatch_function():
@doubledispatch
def f(x, y, z):
return z
@f.register(int, int)
def f_int(x, y, z):
return 42
assert f(1., 1., 0) == 0
assert f(1, 1, 0) == 42
|