From 64c447070ea1be9d7d3ff392aa2355ae53b8a5e0 Mon Sep 17 00:00:00 2001 From: Matthew Lutze Date: Mon, 17 Oct 2022 10:33:13 +0200 Subject: [PATCH] experiment: peeker --- src/Utils/Peeker.flix | 46 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 src/Utils/Peeker.flix diff --git a/src/Utils/Peeker.flix b/src/Utils/Peeker.flix new file mode 100644 index 0000000..1f2e09c --- /dev/null +++ b/src/Utils/Peeker.flix @@ -0,0 +1,46 @@ +namespace Peeker { + + pub opaque enum Peeker[a: Type, r: Region](Ref[Option[Option[a]], r], Iterator[a, r]) + + instance Scoped[Peeker[a]] { + pub def regionOf(_: Peeker[a, r]): Region[r] = () as Region[r] + } + + + /// + /// Builds a Peeker from the given Iterator. + /// The given Iterator must not be reused. + /// + pub def fromIterator(iter: Iterator[a, r]): Peeker[a, r] \ {Read(r), Write(r)} = { + let r = Scoped.regionOf(iter); + Peeker(ref None @ r, iter) + } + + /// + /// Returns the first element in the iterator without consuming it. + /// + pub def peek(p: Peeker[a, r]): Option[a] \ {Read(r), Write(r)} = { + let Peeker(hd, tl) = p; + match deref hd { + case None => + let res = Iterator.next(tl); + hd := Some(res); + res + case Some(x) => x + } + } + + /// + /// Builds an Iterator from the given Peeker. + /// The given Peeker must not be reused. + /// + pub def toIterator(p: Peeker[a, r]): Iterator[a, r] \ {Read(r), Write(r)} = { + let r = Scoped.regionOf(p); + let Peeker(hd, tl) = p; + match deref hd { + case None => tl + case Some(None) => tl + case Some(Some(x)) => Iterator.append(Iterator.singleton(r, x), tl) + } + } +} \ No newline at end of file