~nch/glue

64861b62dfc6919722ac5c983d6888c35c3d4715 — nc 1 year, 2 months ago f0ec6f8
low level implementation of the goal
1 files changed, 55 insertions(+), 106 deletions(-)

M dataflow.py
M dataflow.py => dataflow.py +55 -106
@@ 1,125 1,74 @@
from inspect import isgenerator
import functools
from dataclasses import dataclass
from typing import *

def stream(f):
    @functools.wraps(f)
    def g(*args):
        return _Stream(f, *args).copy()
    return g

@stream
def add(a, b):
    while True:
        yield next(a) + next(b)

@stream
def mul(a, b):
    while True:
        yield next(a) * next(b)


@stream
def var_stream(env, v):
    while True:
        yield env[v]

@stream
def bind_stream(env, result_var, bindings):
    while True:
        for k, v in bindings.items():
            env[k] = next(v)
        yield env[result_var]
class Stream:
    def __init__(self, f):
        self.f = f
        self.i = 0
        self.vals = []
        self.nexting = False

    def __getitem__(self, i):
        if self.nexting:
            raise Exception("Already nexting!")
        if i > len(self.vals) - 1:
            self.nexting = True
            r = self.f()
            self.nexting = False
            if isinstance(r, Stream):
                r = next(r)
            self.vals.append(r)
        return self.vals[i]

@stream
def int_(i):
    while True:
        yield i
    def __next__(self):
        r = self[self.i]
        self.i += 1
        return r

@stream
def fby(x, y):
    yield x
    while True:
        yield y
    y.vals.insert(0, x)
    return y

@stream
def var(name):
    pass
def where(env, target, **kwargs):
    for k, v in kwargs.items():
        env[k] = v
    return Stream(lambda: env[target])

@stream
def next_(s):
    next(s) # advance one step further
    while True:
        yield next(s)

class _StreamHandle:
    def __init__(self, stream, i):
        self.stream = stream
        self.i = i

    def __iter__(self):
        return self

    @property
    def first(self):
        return self.stream.vals[0]

    def __next__(self):
        i = self.i
        self.i += 1 # stream advances...
        if i > len(self.stream.vals) - 1:
            return next(self.stream)
        else:
            return self.stream.vals[i]

    def __repr__(self):
        if self.stream.f:
            return f'<streamhandle {self.stream.f.__name__}>'
        else:
            return '<streamhandle>'
    it = Stream(s)
    next(it)
    return it

    def copy(self):
        return _StreamHandle(self.stream, self.i)

    __add__ = add
s1 = Stream(lambda: 1)
assert next(s1) == 1
assert next(s1) == 1
assert next(s1) == 1

class _Stream:
    def __init__(self, f, *args):
        self.gen = f(*args)
        self.deps = [a for a in args if isinstance(a, _Stream) or isinstance(a, _StreamHandle)]
        self.f = f
        self.vals = []
s2 = fby(1, fby(2, Stream(lambda: 3)))
assert next(s2) == 1
assert next(s2) == 2
assert next(s2) == 3
assert next(s2) == 3

    def __iter__(self):
        return self

    def __next__(self):
        r = next(self.gen)
        if isinstance(r, _Stream) or isinstance(r, _StreamHandle):
            r = next(r)
        self.vals.append(r)
        return r

    def copy(self):
        return _StreamHandle(self, len(self.vals))
def next_(s):
    return Stream(lambda: s[s.i + 1])

@dataclass
class Var:
    name: str
    env: Dict

    def __next__(self): # Uuhhhhh does this actually work?
        return self.env[self.name]

    def __call__(self):
        return var_stream(self.env, self.name)

    def where(self, **kwargs):
        return bind_stream(self.env, self.name, kwargs)

    def __add__(self, other):
        return add(var_stream(self.env, self.name), other)
    def __next__(self):
        return next(self.env[self.name])

env = {}
p = where(env, 'fib',
        fib = fby(0, fby(1, Stream(lambda: env['fib'].vals[-2] + env['fib'].vals[-1]))))
print(next(p))
print(next(p))
print(next(p))
print(next(p))
print(next(p))
print(next(p))
print(next(p))

    def __mul__(self, other):
        return mul(var_stream(self.env, self.name), other)