Skip to content

Commit 9676010

Browse files
authored
Add 'stream::fix' fixpoint operator (#867)
Added together with a test. Not sure if the semantics are what we desire wrt stack, cc @b-studios.
1 parent 23d9ffc commit 9676010

File tree

4 files changed

+72
-0
lines changed

4 files changed

+72
-0
lines changed

effekt/jvm/src/test/scala/effekt/core/VMTests.scala

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -803,6 +803,22 @@ class VMTests extends munit.FunSuite {
803803
shifts = 0,
804804
resumes = 0
805805
)),
806+
807+
examplesDir / "stdlib" / "stream" / "fix.effekt" -> Some(Summary(
808+
staticDispatches = 38,
809+
dynamicDispatches = 52,
810+
patternMatches = 37,
811+
branches = 0,
812+
pushedFrames = 34,
813+
poppedFrames = 34,
814+
allocations = 37,
815+
closures = 37,
816+
variableReads = 10,
817+
variableWrites = 9,
818+
resets = 0,
819+
shifts = 0,
820+
resumes = 0
821+
)),
806822
)
807823

808824
val testFiles: Seq[(File, Option[Summary])] =

examples/stdlib/stream/fix.check

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
1
2+
2
3+
3
4+
4
5+
0
6+
100
7+
-60
8+
42
9+
-50
10+
sum: 42

examples/stdlib/stream/fix.effekt

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import stream
2+
3+
type Message {
4+
Primitive(n: Int)
5+
Complex(msgs: List[Message])
6+
}
7+
8+
def solveOne(m: Message): Unit / { emit[Int], emit[Message] } = m match {
9+
case Primitive(n) => do emit[Int](n)
10+
case Complex(msgs) => msgs.each
11+
}
12+
13+
def main() = {
14+
def solved() = fix[Message] { msg => solveOne(msg) } {
15+
do emit(
16+
Complex([
17+
Primitive(1),
18+
Complex([Primitive(2), Primitive(3), Primitive(4)]),
19+
Complex([]),
20+
Complex([Complex([Primitive(0)]), Primitive(100)])
21+
])
22+
)
23+
do emit(Primitive(-60))
24+
do emit(Complex([]))
25+
do emit(Complex([Complex([]), Primitive(42)]))
26+
do emit(Primitive(-50))
27+
}
28+
29+
var sum = 0
30+
for[Int] {solved} { n =>
31+
sum = n + sum
32+
println(n)
33+
}
34+
println("sum: " ++ show(sum))
35+
}

libraries/common/stream.effekt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,17 @@ effect stop(): Nothing
3030
def for[A] { stream: () => Unit / emit[A] } { action: A => Unit }: Unit =
3131
returning::for[A, Unit]{stream}{action}
3232

33+
/// Runs the stream as a message queue,
34+
/// handling each of its elements that can produce new elements ("messages"),
35+
/// until a fixed point is reached.
36+
def fix[T] { one: T => Unit / emit[T] } { stream: => Unit / emit[T] }: Unit =
37+
try {
38+
stream()
39+
} with emit[T] { value =>
40+
fix[T] {one} { one(value) }
41+
resume(())
42+
}
43+
3344
/// Turns a `list` into a producer of a push stream
3445
/// by emitting each contained value left-to-right.
3546
def each[A](list: List[A]): Unit / emit[A] =

0 commit comments

Comments
 (0)