def Group(g, b_type=None): ef = None def prepare(): for l in ef.listeners.itervalues(): l.prepare() for e in ef.table.values(): e.fresh = False for l in e.listeners.itervalues(): l.prepare() def push(x): y = g(x) e = None if not (ef.table.has_key(y)): e = FEvent() ef.table[y] = e for l in ef.listeners.itervalues(): l.push((y, e)) else: e = ef.table[y] for l in e.listeners.itervalues(): l.push(x) def finish(): for e in ef.table.values(): for l in e.listeners.itervalues(): l.finish() e.fresh = True for l in ef.listeners.itervalues(): l.finish() def terminate(): for e in ef.table.values(): for l in e.listeners.itervalues(): l.terminate() for l in ef.listeners.itervalues(): l.terminate() def type_fun(a): if a is not None and b_type is not None: return types.FType((b_type.type, types.FEventType(a.type))) else: return None ef = FEventFun(prepare=prepare, push=push, finish=finish, terminate=terminate, type_fun=type_fun) ef.table = {} return ef
def Ungroup(n, f, init, init_type=None): ef = None def go(x, y): for l in ef.listeners.itervalues(): l.push((x, y)) def mk_lpush(e): def g(z): (x, i, b, y) = ef.table[e] if not b: y = f(y, z) if not (n is None) and i == n - 1: b = True go(x, y) ef.table[e] = (x, i + 1, b, y) return g def mk_lterm(e): def g(): (x, i, b, y) = ef.table[e] if not b: go(x, y) return g def push((x, e)): ef.table[e] = (x, 0, False, init) e.add_listener(FListener(push=mk_lpush(e), terminate=mk_lterm(e))) def type_fun(t): if t is None or init_type is None: return None try: (c, a) = t.type except (TypeError, ValueError): raise types.FTypeException("%s not an instance of (c * E a)" % a) f_out_type = f.type_fun(types.FType((init_type.type, a.type))) if not types.is_of_type(f_out_type, init_type): raise types.FTypeException( "%s not of expected type: f generates %s instead of %s" % (t, f_out_type, init_type)) return types.FType((c, init_type.type)) ef = FEventFun(push=push, type_fun=type_fun) ef.table = {} return ef
def Lift(g, in_type=None, out_type=None, type_fun=None): """Lift function g into an EF. Optional type annotations {in,out}_type, or you can give a type conversion function, which overrides static types. Note that in_type and out_type MUST be wrapped in types.FType,or something with its interface, and type_fun should expect its input and output wrapped in the same class. A None type object acts as a signal to ignore type checking this type. It should not throw type exceptions.""" ef = None def push(x): y = g(x) for l in ef.listeners.itervalues(): l.push(y) if type_fun is None: def type_fun(test_in_type): if in_type is None or types.is_of_type(test_in_type, in_type): return out_type else: raise types.FTypeException("%s not of type %s" % (test_in_type, in_type)) ef = FEventFun(push=push, type_fun=type_fun) return ef
def LoopPre(c, ef1, c_type=None): ef = None def prepare(): ef1.prepare() for l in ef.listeners.itervalues(): l.prepare() def push(x): ef1.push((x, ef.cell.get())) def push2((y1, y2)): ef.cell.set(y2) for l in ef.listeners.itervalues(): l.push(y1) def finish(): ef1.finish() for l in ef.listeners.itervalues(): l.finish() def terminate(): ef1.terminate() for l in ef.listeners.itervalues(): l.terminate() def type_fun(a): if a is None or c_type is None: return None eftype = ef1.type_fun(types.FType((a.type, c_type.type))) if eftype is None: return None (b, c) = eftype.type if not types.is_of_type(c_type, types.FType(c)): raise types.FTypeException("%s is not of type %s" % (c, c_type)) return types.FType(b) ef = FEventFun(prepare=prepare, push=push, finish=finish, terminate=terminate, type_fun=type_fun) ef.cell = util.FRef() ef.cell.set(c) ef1.add_listener(FListener(push=push2)) return ef
def Group(g, b_type=None): ef = None def prepare(): for l in ef.listeners.itervalues(): l.prepare() for e in ef.table.values(): e.fresh = False for l in e.listeners.itervalues(): l.prepare() def push(x): y = g(x) e = None if not (ef.table.has_key(y)): e = FEvent() ef.table[y] = e for l in ef.listeners.itervalues(): l.push((y,e)) else: e = ef.table[y] for l in e.listeners.itervalues(): l.push(x) def finish(): for e in ef.table.values(): for l in e.listeners.itervalues(): l.finish() e.fresh = True for l in ef.listeners.itervalues(): l.finish() def terminate(): for e in ef.table.values(): for l in e.listeners.itervalues(): l.terminate() for l in ef.listeners.itervalues(): l.terminate() def type_fun(a): if a is not None and b_type is not None: return types.FType((b_type.type, types.FEventType(a.type))) else: return None ef = FEventFun(prepare=prepare, push=push, finish=finish, terminate=terminate, type_fun=type_fun) ef.table = {} return ef
def First(ef1): ef = None def prepare(): ef1.prepare() for l in ef.listeners.itervalues(): l.prepare() def push((x1, x2)): ef.cell.set(x2) ef1.push(x1) def push2(y1): y2 = ef.cell.get() for l in ef.listeners.itervalues(): l.push((y1, y2)) def finish(): ef1.finish() for l in ef.listeners.itervalues(): l.finish() def terminate(): ef1.terminate() for l in ef.listeners.itervalues(): l.terminate() def type_fun(in_type): if in_type is None: return None try: (a, c) = in_type.type except ValueError: raise types.FTypeException("%s not of type (a * c)" % in_type) return types.FType((ef1.type_fun(types.FType(a)).type, c)) ef = FEventFun(prepare=prepare, push=push, finish=finish, terminate=terminate, type_fun=type_fun) ef.cell = util.FRef() ef1.add_listener(FListener(push=push2)) return ef
def Filter(g): ef = None def push(x): if g(x): for l in ef.listeners.itervalues(): l.push(x) ef = FEventFun(push=push, type_fun=lambda a: a) return ef
def Ungroup(n,f,init, init_type=None): ef = None def go(x,y): for l in ef.listeners.itervalues(): l.push((x,y)) def mk_lpush(e): def g(z): (x,i,b,y) = ef.table[e] if not b: y = f(y,z) if not (n is None) and i == n - 1: b = True go(x,y) ef.table[e] = (x,i+1,b,y) return g def mk_lterm(e): def g(): (x,i,b,y) = ef.table[e] if not b: go(x,y) return g def push((x,e)): ef.table[e] = (x,0,False,init) e.add_listener(FListener(push=mk_lpush(e),terminate=mk_lterm(e))) def type_fun(t): if t is None or init_type is None: return None try: (c, a) = t.type except (TypeError, ValueError): raise types.FTypeException("%s not an instance of (c * E a)" % a) f_out_type = f.type_fun(types.FType((init_type.type, a.type))) if not types.is_of_type(f_out_type, init_type): raise types.FTypeException( "%s not of expected type: f generates %s instead of %s" % (t, f_out_type, init_type)) return types.FType((c, init_type.type)) ef = FEventFun(push=push,type_fun=type_fun) ef.table = {} return ef
def LoopPre(c, ef1, c_type=None): ef = None def prepare(): ef1.prepare() for l in ef.listeners.itervalues(): l.prepare() def push(x): ef1.push((x,ef.cell.get())) def push2((y1,y2)): ef.cell.set(y2) for l in ef.listeners.itervalues(): l.push(y1) def finish(): ef1.finish() for l in ef.listeners.itervalues(): l.finish() def terminate(): ef1.terminate() for l in ef.listeners.itervalues(): l.terminate() def type_fun(a): if a is None or c_type is None: return None eftype = ef1.type_fun(types.FType((a.type, c_type.type))) if eftype is None: return None (b, c) = eftype.type if not types.is_of_type(c_type, types.FType(c)): raise types.FTypeException("%s is not of type %s" % (c, c_type)) return types.FType(b) ef = FEventFun( prepare=prepare, push=push, finish=finish, terminate=terminate, type_fun = type_fun) ef.cell = util.FRef() ef.cell.set(c) ef1.add_listener(FListener(push=push2)) return ef
def First(ef1): ef = None def prepare(): ef1.prepare() for l in ef.listeners.itervalues(): l.prepare() def push((x1,x2)): ef.cell.set(x2) ef1.push(x1) def push2(y1): y2 = ef.cell.get() for l in ef.listeners.itervalues(): l.push((y1,y2)) def finish(): ef1.finish() for l in ef.listeners.itervalues(): l.finish() def terminate(): ef1.terminate() for l in ef.listeners.itervalues(): l.terminate() def type_fun(in_type): if in_type is None: return None try: (a, c) = in_type.type except ValueError: raise types.FTypeException("%s not of type (a * c)" % in_type) return types.FType((ef1.type_fun(types.FType(a)).type, c)) ef = FEventFun( prepare=prepare, push=push, finish=finish, terminate=terminate, type_fun=type_fun) ef.cell = util.FRef() ef1.add_listener(FListener(push=push2)) return ef
def Compose(ef1, ef2): ef1.add_listener(ef2) def type_fun(t): if t is None: return None out1 = ef1.type_fun(t) if out1 is None: return None out2 = ef2.type_fun(out1) return out2 ef = FEventFun(ef2.add_listener, ef1.prepare, ef1.push, ef1.finish, ef1.terminate, type_fun) return ef
def Regroup(feq): # helper function to split a nested subevent def mk_subevent(e, outer_prepare, outer_push): sube_cell = util.FRef() def mk(): sube = FEvent() sube.last_cell = util.FRef() return sube def subprepare(): sube = sube_cell.get() sube.fresh = False for l in sube.listeners.itervalues(): l.prepare() def subpush(x): sube = sube_cell.get() last = sube.last_cell.get() if not (last is None) and not (feq(last, x)): # terminate / create new subevent sube_old = sube sube = mk() subterminate() sube_cell.set(sube) subprepare() outer_prepare() outer_push(sube) for l in sube.listeners.itervalues(): l.push(x) sube.last_cell.set(x) def subfinish(): sube = sube_cell.get() for l in sube.listeners.itervalues(): l.finish() sube.fresh = True def subterminate(): sube = sube_cell.get() for l in sube.listeners.itervalues(): l.terminate() sube = mk() sube_cell.set(sube) e.add_listener(FListener(subprepare, subpush, subfinish, subterminate)) return sube ef = None def prepare(): for l in ef.listeners.itervalues(): l.prepare() def push((x, e)): outer_push = lambda e: push((x, e)) sube = mk_subevent(e, prepare, outer_push) for l in ef.listeners.itervalues(): l.push((x, sube)) # TODO(astory): consider checking for correctness ef = FEventFun(push=push, type_fun=lambda a: a) return ef