Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor 'stream', add a few examples #705

Merged
merged 10 commits into from
Nov 25, 2024
6 changes: 5 additions & 1 deletion effekt/jvm/src/test/scala/effekt/StdlibTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ abstract class StdlibChezTests extends StdlibTests {
override def ignored: List[File] = List(
// Not implemented yet
examplesDir / "stdlib" / "bytearray",
examplesDir / "stdlib" / "io"
examplesDir / "stdlib" / "io",
examplesDir / "stdlib" / "stream" / "characters.effekt",
examplesDir / "stdlib" / "stream" / "fuse_newlines.effekt"
jiribenes marked this conversation as resolved.
Show resolved Hide resolved
)
}
class StdlibChezSchemeMonadicTests extends StdlibChezTests {
Expand All @@ -44,6 +46,8 @@ class StdlibLLVMTests extends StdlibTests {

// Valgrind leak/failure
examplesDir / "stdlib" / "bytearray" / "bytearray.effekt",
examplesDir / "stdlib" / "stream" / "characters.effekt",
examplesDir / "stdlib" / "stream" / "fuse_newlines.effekt",
examplesDir / "stdlib" / "io" / "filesystem" / "async_file_io.effekt",
examplesDir / "stdlib" / "io" / "filesystem" / "files.effekt",
examplesDir / "stdlib" / "io" / "filesystem" / "wordcount.effekt",
Expand Down
3 changes: 2 additions & 1 deletion examples/benchmarks/input_output/word_count_ascii.effekt
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ def countWords(): Output / read[Byte] = {
var lines = 0
var wasSpace = true

exhaustively { do read[Byte]() } { c =>
exhaustively {
val c = do read[Byte]()

chars = chars + 1

Expand Down
3 changes: 2 additions & 1 deletion examples/benchmarks/input_output/word_count_utf8.effekt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ def countWords(): Output / read[Char] = {
var lines = 0
var wasSpace = true

exhaustively[Char] { do read() } { c =>
exhaustively {
val c = do read[Char]()

chars = chars + 1

Expand Down
6 changes: 6 additions & 0 deletions examples/stdlib/stream/characters.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
H (72)
e (101)
l (108)
l (108)
o (111)
Cons(H, Cons(e, Cons(l, Cons(l, Cons(o, Nil())))))
11 changes: 11 additions & 0 deletions examples/stdlib/stream/characters.effekt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import stream

def main() = {
for[Char] { each("Hello") } { c =>
println(show(c) ++ " (" ++ show(c.toInt) ++ ")")
}

val list = collectList[Char] { each("Hello") }
println(list.map { c => c.show })
}

2 changes: 2 additions & 0 deletions examples/stdlib/stream/fibonacci.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
The first 10 Fibonacci numbers:
Cons(0, Cons(1, Cons(1, Cons(2, Cons(3, Cons(5, Cons(8, Cons(13, Cons(21, Cons(34, Nil()))))))))))
20 changes: 20 additions & 0 deletions examples/stdlib/stream/fibonacci.effekt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import stream

def main() = {
val max = 10

val fibs = collectList[Int] {
var a = 0
var b = 1

replicate(max) {
val current = a
val next = a + b
a = b
b = next
current
}
}
println("The first " ++ show(max) ++ " Fibonacci numbers:")
println(fibs)
}
3 changes: 3 additions & 0 deletions examples/stdlib/stream/fuse_newlines.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
ab
c
de
32 changes: 32 additions & 0 deletions examples/stdlib/stream/fuse_newlines.effekt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import stream

def fuseNewlines(): Nothing / {read[Char], emit[Char], stop} = {
val c = do read[Char]()
if (c == '\n') {
do emit(c)
skipNewlines()
} else {
do emit(c)
fuseNewlines()
}
}

def skipNewlines(): Nothing / {read[Char], emit[Char], stop} = {
val c = do read[Char]()
if (c == '\n') {
skipNewlines()
} else {
do emit(c)
fuseNewlines()
}
}

def main() = {
with feed("ab\n\nc\nde")
println(collectString {
with exhaustively
fuseNewlines()
})
}


35 changes: 35 additions & 0 deletions examples/stdlib/stream/neighbours.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
The immediate neighbours of [4, 3] are:
[3, 2]
[3, 3]
[3, 4]
[4, 2]
[4, 4]
[5, 2]
[5, 3]
[5, 4]

The neighbours and their neighbours of [4, 3] are:
[2, 1]
[2, 2]
[2, 3]
[2, 4]
[2, 5]
[3, 1]
[3, 2]
[3, 3]
[3, 4]
[3, 5]
[4, 1]
[4, 2]
[4, 4]
[4, 5]
[5, 1]
[5, 2]
[5, 3]
[5, 4]
[5, 5]
[6, 1]
[6, 2]
[6, 3]
[6, 4]
[6, 5]
38 changes: 38 additions & 0 deletions examples/stdlib/stream/neighbours.effekt
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import stream

record Pos(x: Int, y: Int)

def equals(left: Pos, right: Pos) = (left, right) match {
case (Pos(lx, ly), Pos(rx, ry)) => lx == rx && ly == ry
}

def show(p: Pos) = "[" ++ show(p.x) ++ ", " ++ show(p.y) ++ "]"

/// Gets the neighbours of a given position.
/// with radius=1, those are immediate neighbours (including the diagonal)
/// with radius=2, these are neighbours&their neighbours
/// ...
def neighboursOf(pos: Pos, radius: Int) = {
with val dx = for[Int] { range(neg(radius), radius + 1) }
with val dy = for[Int] { range(neg(radius), radius + 1) }
val newPosition = Pos(pos.x + dx, pos.y + dy)
do emit(newPosition)
}
jiribenes marked this conversation as resolved.
Show resolved Hide resolved

def main() = {
val start = Pos(4, 3)

println("The immediate neighbours of " ++ show(start) ++ " are:")
for[Pos] { start.neighboursOf(1) } {
case p and not(p.equals(start)) => println(show(p))
case _ => ()
}

println("")

println("The neighbours and their neighbours of " ++ show(start) ++ " are:")
for[Pos] { start.neighboursOf(2) } {
case p and not(p.equals(start)) => println(show(p))
case _ => ()
}
}
2 changes: 2 additions & 0 deletions examples/stdlib/stream/sum_of_squares.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
The sum of squares from 1 to 10 is:
385
16 changes: 16 additions & 0 deletions examples/stdlib/stream/sum_of_squares.effekt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import stream

def squares(): Unit / emit[Int] =
for[Int] { rangeFrom(1) } { n =>
do emit(n * n)
}


def main() = {
val max = 10
println("The sum of squares from 1 to " ++ show(max) ++ " is:")
println(sum {
with limit[Int](max + 1)
squares()
})
}
5 changes: 5 additions & 0 deletions examples/stdlib/stream/zip.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
1, H
2, e
3, l
4, l
5, o
11 changes: 11 additions & 0 deletions examples/stdlib/stream/zip.effekt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import stream
jiribenes marked this conversation as resolved.
Show resolved Hide resolved

def main() = {
def stream1() = rangeFrom(1)
// Ideally this would be an array to demonstrate the capabilities.
def stream2() = ['H', 'e', 'l', 'l', 'o'].each
jiribenes marked this conversation as resolved.
Show resolved Hide resolved

zip[Int, Char]{stream1}{stream2} { (a, b) =>
println(show(a) ++ ", " ++ show(b))
}
}
Loading