import inspect from rpython.rlib.objectmodel import import_from_mixin class InvalidCammy(Exception): def __init__(self, message): self.message = message class Cammy(object): # holes def hole(self, i): raise InvalidCammy("Holes not permitted in semantic domain " + self.__class__.__name__) def substitute(self, args): pass # category def id(self): pass def comp(self, arrs): pass # terminal object def ignore(self): pass # products def project(self, k, n): pass def tuple(self, arrs): pass # sums def inject(self, k, n): pass def case(self, arrs): pass # internal homs def curry(self, arr): pass def uncurry(self, arr): pass # natural numbers object def nat(self, k): pass def succ(self): pass def pr(self, f, g): pass # ordinal objects def ord(self, k, n): pass # free monoids def nil(self): pass def cons(self): pass def fold(self, f, g): pass # free binary trees def tnil(self): pass def tcons(self): pass def tfold(self, f, g): pass # boolean object def t(self): pass def f(self): pass def either(self): pass def conj(self): pass def disj(self): pass def not_(self): pass # floating-point object def f0(self): pass def f1(self): pass def pi(self): pass def f_sign(self): pass def f_lt(self): pass def f_negate(self): pass def f_recip(self): pass def f_add(self): pass def f_mul(self): pass def f_floor(self): pass def f_sqrt(self): pass def f_sin(self): pass def f_cos(self): pass def f_atan2(self): pass def f_exp(self): pass def f_log1p(self): pass # jets def dup(self): return self.tuple([self.id()] * 2) def zero(self): return self.nat(0) def fst(self): return self.project(0, 2) def snd(self): return self.project(1, 2) def swap(self): return self.tuple([self.snd(), self.fst()]) def left(self): return self.inject(0, 2) def right(self): return self.inject(1, 2) def app(self): return self.uncurry(self.id()) def n_double(self): return self.pr(self.zero(), self.comp([self.succ()] * 2)) def n_add(self): return self.uncurry(self.pr(self.curry(self.snd()), self.curry(self.comp([self.app(), self.succ()])))) def n_pred_maybe(self): return self.pr(self.right(), self.comp([self.case([self.succ(), self.zero()]), self.left()])) def n_mul(self): return self.uncurry(self.pr(self.curry(self.comp([self.ignore(), self.zero()])), self.curry(self.comp([self.tuple([self.app(), self.snd()]), self.n_add()])))) def PairOf(d1, d2): class PairDomain(object): import_from_mixin(Cammy) def __init__(self, d1, d2): self.d1 = d1 self.d2 = d2 def hole(self, i): return self.d1.hole(i), self.d2.hole(i) def substitute(self, args): return (self.d1.substitute([arg[0] for arg in args]), self.d2.substitute([arg[1] for arg in args])) def comp(self, arrs): return (self.d1.comp([arr[0] for arr in arrs]), self.d2.comp([arr[1] for arr in arrs])) def project(self, k, n): return self.d1.project(k, n), self.d2.project(k, n) def tuple(self, arrs): return (self.d1.tuple([arr[0] for arr in arrs]), self.d2.tuple([arr[1] for arr in arrs])) def inject(self, k, n): return self.d1.inject(k, n), self.d2.inject(k, n) def case(self, arrs): return (self.d1.case([arr[0] for arr in arrs]), self.d2.case([arr[1] for arr in arrs])) def curry(self, arr): return self.d1.curry(arr[0]), self.d2.curry(arr[1]) def uncurry(self, arr): return self.d1.uncurry(arr[0]), self.d2.uncurry(arr[1]) def nat(self, k): return self.d1.nat(k), self.d2.nat(k) def pr(self, f, g): return self.d1.pr(f[0], g[0]), self.d2.pr(f[1], g[1]) def ord(self, k, n): return self.d1.ord(k, n), self.d2.ord(k, n) def fold(self, f, g): return self.d1.fold(f[0], g[0]), self.d2.fold(f[1], g[1]) def tfold(self, f, g): return self.d1.tfold(f[0], g[0]), self.d2.tfold(f[1], g[1]) for verb, meth in inspect.getmembers(Cammy, inspect.ismethod): if verb.startswith("__"): continue argspec = inspect.getargspec(meth) if len(argspec[0]) != 1: continue exec """def {verb}(self): return self.d1.{verb}(), self.d2.{verb}()""".format(verb=verb) return PairDomain(d1, d2)