Skip to content

Instantly share code, notes, and snippets.

@bryce-anderson
Last active December 30, 2015 04:09
Show Gist options
  • Save bryce-anderson/7774073 to your computer and use it in GitHub Desktop.
Save bryce-anderson/7774073 to your computer and use it in GitHub Desktop.
untested method for parsing a Process using a Process1 while keeping any remaining Process
def weave[O, B, F[_]](p: Process[F, O], p1: Process1[O, B])
(implicit M: Monad[F], C: Catchable[F]): F[(Seq[B], Process[F, O])] = {
// Nearly a direct copy of process1.feed, except it returns any unused inputs
def feed(i: Seq[O], p: Process1[O,B]): (Seq[O], Process1[O,B]) = {
@annotation.tailrec
def go(in: Seq[O], out: Vector[Seq[B]], cur: Process1[O,B]): (Seq[O], Process1[O,B]) =
if (in.nonEmpty) cur match {
case h@Halt(_) => (in, emitSeq(out.flatten, h))
case Emit(h, t) => go(in, out :+ h, t)
case Await1(recv, fb, c) =>
val next =
try recv(in.head)
catch {
case End => fb
case e: Throwable => c.causedBy(e)
}
go(in.tail, out, next)
}
else (in, if (out.isEmpty) cur else emitSeq(out.flatten, cur))
go(i, Vector(), p)
}
p match {
case Emit(seq, tail) =>
if (seq.isEmpty) weave(tail.asInstanceOf[Process[F,O]], p1)
else {
val _t = feed(seq.asInstanceOf[Seq[O]], p1)
if (_t._1.isEmpty) weave(tail.asInstanceOf[Process[F,O]], _t._2)
// We got some unused input. The P1 *MUST* be done
else _t._2 match {
case h@Halt(End) => // The Process1 has ended with no output
M.point((Nil, Emit(seq.asInstanceOf[Seq[O]], tail.asInstanceOf[Process[F,O]])))
case Halt(t) => C.fail(t)
case Emit(p1seq, Halt(End)) => // Got some output
M.point((p1seq, Emit(_t._1.asInstanceOf[Seq[O]], tail.asInstanceOf[Process[F,O]])))
case Emit(p1seq, Halt(t)) => C.fail(t)
case _ => sys.error("Shouldn't get here!")
}
}
case Await(f, recv, fb, c) =>
M.bind(C.attempt(f.asInstanceOf[F[AnyRef]]))(
_.fold(
{ case End => weave(fb.asInstanceOf[Process[F,O]], p1)
case e => weave(c.asInstanceOf[Process[F,O]].causedBy(e), p1)
},
o => weave(recv.asInstanceOf[AnyRef => Process[F,O]](o), p1)
))
case h@Halt(End) => M.point((p1.unemit._1, h))
case Halt(t) => C.fail(t)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment