|
| 1 | +import dotty.tools.dotc.quoted.Toolbox._ |
| 2 | +import scala.quoted._ |
| 3 | + |
| 4 | +trait StagedStreams { |
| 5 | + |
| 6 | + // TODO: remove as it exists in Quoted Lib |
| 7 | + sealed trait Var[T] { |
| 8 | + def get: Expr[T] |
| 9 | + def update(x: Expr[T]): Expr[Unit] |
| 10 | + } |
| 11 | + |
| 12 | + object Var { |
| 13 | + def apply[T: Type, U](init: Expr[T])(body: Var[T] => Expr[U]): Expr[U] = '{ |
| 14 | + var x = ~init |
| 15 | + ~body( |
| 16 | + new Var[T] { |
| 17 | + def get: Expr[T] = '(x) |
| 18 | + def update(e: Expr[T]): Expr[Unit] = '{ x = ~e } |
| 19 | + } |
| 20 | + ) |
| 21 | + } |
| 22 | + } |
| 23 | + |
| 24 | + type Id[A] = A |
| 25 | + |
| 26 | + trait Producer[A] { self => |
| 27 | + type St |
| 28 | + val card: Cardinality |
| 29 | + |
| 30 | + def init(k: St => Expr[Unit]): Expr[Unit] |
| 31 | + def step(st: St, k: (A => Expr[Unit])): Expr[Unit] |
| 32 | + def hasNext(st: St): Expr[Boolean] |
| 33 | + } |
| 34 | + |
| 35 | + trait Cardinality |
| 36 | + case object AtMost1 extends Cardinality |
| 37 | + case object Many extends Cardinality |
| 38 | + |
| 39 | + trait StagedStream[A] |
| 40 | + case class Linear[A](producer: Producer[A]) extends StagedStream[A] |
| 41 | + case class Nested[A, B](producer: Producer[A], nestedf: A => StagedStream[B]) extends StagedStream[B] |
| 42 | + |
| 43 | + case class Stream[A](stream: StagedStream[Expr[A]]) { |
| 44 | + // def fold[W](z: Expr[W], f: (Expr[W] => Expr[A] => Expr[W])): Expr[W] = ??? |
| 45 | + |
| 46 | + // def fold_raw[W](z: Expr[W], update_acc: Expr[W] => Expr[Unit], f: (Expr[W] => Expr[A] => Expr[W])): Expr[Unit] = { |
| 47 | + // def consume[A](consumer: A => Expr[Unit], stream: StagedStream[A]): Expr[Unit] = { |
| 48 | + // stream match { |
| 49 | + // case Linear(producer) => { |
| 50 | + // producer.card match { |
| 51 | + // case Many => |
| 52 | + // producer.init(sp => '{ |
| 53 | + // while(~producer.hasNext(sp)) { |
| 54 | + // ~producer.step(sp, consumer) |
| 55 | + // } |
| 56 | + // }) |
| 57 | + // case AtMost1 => |
| 58 | + // producer.init(sp => '{ |
| 59 | + // if (~producer.hasNext(sp)) { |
| 60 | + // ~producer.step(sp, consumer) |
| 61 | + // } |
| 62 | + // }) |
| 63 | + // } |
| 64 | + // } |
| 65 | + // case Nested(producer, nestedf) => { |
| 66 | + // ??? //consume(((a) => consume(consumer, nestedf(a))), Linear[A](producer)) |
| 67 | + // } |
| 68 | + // } |
| 69 | + // } |
| 70 | + |
| 71 | + // ??? // consume((a: Expr[A]) => '{ ~update_acc(f(z)(a)) }, stream) |
| 72 | + // } |
| 73 | + } |
| 74 | + |
| 75 | + object Stream { |
| 76 | + def of[A: Type](arr: Expr[Array[A]]): Stream[A] = { |
| 77 | + val prod = new Producer[Expr[A]] { |
| 78 | + type St = (Var[Int], Var[Int], Expr[Array[A]]) |
| 79 | + |
| 80 | + val card = Many |
| 81 | + |
| 82 | + def init(k: St => Expr[Unit]): Expr[Unit] = { |
| 83 | + Var('{(~arr).length}) { n => |
| 84 | + Var(0.toExpr){i => |
| 85 | + k((i, n, arr)) |
| 86 | + } |
| 87 | + } |
| 88 | + } |
| 89 | + |
| 90 | + def step(st: St, k: (Expr[A] => Expr[Unit])): Expr[Unit] = { |
| 91 | + val (i, _, arr) = st |
| 92 | + '{ |
| 93 | + val el = (~arr).apply(~i.get) |
| 94 | + ~i.update('{ ~i.get + 1 }) |
| 95 | + ~k('(el)) |
| 96 | + } |
| 97 | + } |
| 98 | + |
| 99 | + def hasNext(st: St): Expr[Boolean] = { |
| 100 | + val (i, n, _) = st |
| 101 | + '{ |
| 102 | + (~i.get < ~n.get) |
| 103 | + } |
| 104 | + } |
| 105 | + } |
| 106 | + |
| 107 | + Stream(Linear(prod)) |
| 108 | + } |
| 109 | + } |
| 110 | +} |
| 111 | + |
0 commit comments