This commit is contained in:
Natsu Kagami 2023-05-17 15:29:52 +02:00
commit 26f5bf3c3e
Signed by: nki
GPG key ID: 7306B3D3C3AD6E51
12 changed files with 263 additions and 0 deletions

1
.bsp/sbt.json Normal file
View file

@ -0,0 +1 @@
{"name":"sbt","version":"1.8.2","bspVersion":"2.1.0-M1","languages":["scala"],"argv":["/nix/store/grp5dj6bvnfcrd002mivmp36jldjzhph-openjdk-19.0.2+7/lib/openjdk/bin/java","-Xms100m","-Xmx100m","-classpath","/nix/store/g5hx4a8pqfhyn61iiillw0xn4y2a5zl4-sbt-1.8.2/share/sbt/bin/sbt-launch.jar","-Dsbt.script=/nix/store/g5hx4a8pqfhyn61iiillw0xn4y2a5zl4-sbt-1.8.2/bin/sbt","xsbt.boot.Boot","-bsp"]}

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
.metals
target
.bloop

2
.scalafmt.conf Normal file
View file

@ -0,0 +1,2 @@
version = "3.6.1"
runner.dialect = scala3

22
build.sbt Normal file
View file

@ -0,0 +1,22 @@
scalaVersion := "3.1.3"
enablePlugins(ScalaNativePlugin)
// set to Debug for compilation details (Info is default)
logLevel := Level.Info
// import to add Scala Native options
import scala.scalanative.build._
// defaults set with common options shown
nativeConfig ~= { c =>
c.withLTO(LTO.none) // thin
.withMode(Mode.releaseFast) // releaseFast
.withGC(GC.immix) // commix
.withMultithreadingSupport(true)
.withCompileOptions(c.compileOptions ++ Seq("-g"))
}
scalacOptions ++= Seq(
"-explain"
)

1
project/build.properties Normal file
View file

@ -0,0 +1 @@
sbt.version = 1.8.2

6
project/metals.sbt Normal file
View file

@ -0,0 +1,6 @@
// DO NOT EDIT! This file is auto-generated.
// This file enables sbt-bloop to create bloop config files.
addSbtPlugin("ch.epfl.scala" % "sbt-bloop" % "1.5.6")

1
project/plugins.sbt Normal file
View file

@ -0,0 +1 @@
addSbtPlugin("org.scala-native" % "sbt-scala-native" % "0.5.0-SNAPSHOT")

View file

@ -0,0 +1,6 @@
// DO NOT EDIT! This file is auto-generated.
// This file enables sbt-bloop to create bloop config files.
addSbtPlugin("ch.epfl.scala" % "sbt-bloop" % "1.5.6")

View file

@ -0,0 +1,6 @@
// DO NOT EDIT! This file is auto-generated.
// This file enables sbt-bloop to create bloop config files.
addSbtPlugin("ch.epfl.scala" % "sbt-bloop" % "1.5.6")

68
src/main/scala/Gen.scala Normal file
View file

@ -0,0 +1,68 @@
package gen
import scala.annotation.tailrec
object Gen:
import scala.scalanative.runtime.Continuations.*
enum Seqn[+T] {
case Empty
case Next(t: T, nx: () => Seqn[T])
}
type CanGen[-T] = BoundaryLabel[Seqn[T]]
def apply[T](f: CanGen[T] ?=> Unit): Iterator[T] =
new Iterator[T] {
var buf = boundary { f; Seqn.Empty }
def hasNext: Boolean = buf != Seqn.Empty
def next() = buf match
case Seqn.Empty => ???
case Seqn.Next(t, nx) =>
buf = nx()
t
}
def put[T](value: T)(using CanGen[T]): Unit =
suspend[Seqn[T]](f => Seqn.Next(value, f))
end Gen
import Gen.*
def allRightTriangles = Gen {
var c = 1
var a = 1
var b = 1
def nextState() =
if (a * a + b * b > c * c) then
a += 1
b = a
if (a >= c) then
c += 1
a = 1
b = 1
else b += 1
def toOk() =
while a * a + b * b != c * c do nextState()
while (true) do
toOk()
put((a, b, c))
nextState()
}
def fibonacci = Gen {
@tailrec def go(a: Int, b: Int): Unit =
put(a)
go(b, (a + b))
go(1, 1)
}
def rightTriangles(upTo: Int) = Gen {
allRightTriangles
.takeWhile((_, _, c) => c <= upTo)
.foreach(put)
}

52
src/main/scala/Main.scala Normal file
View file

@ -0,0 +1,52 @@
import gen.rightTriangles
import concurrent.simple.*
import gen.fibonacci
object Test {
def main(args: Array[String]): Unit =
testGen()
testGenCompare()
// testSimpleFutures()
def testGen(): Unit =
// println(rightTriangles(1500).toList)
println(fibonacci.take(1000).toList)
def testGenCompare(): Unit =
val iter = new Iterator[(Int, Int, Int)] {
var c = 1
var a = 1
var b = 1
def nextState() =
if (a * a + b * b > c * c) then
a += 1
b = a
if (a >= c) then
c += 1
a = 1
b = 1
else b += 1
def toOk() =
while a * a + b * b != c * c do nextState()
def hasNext =
toOk()
c <= 1500
def next() =
toOk()
val res = (a, b, c)
nextState()
res
}
println(iter.toList)
def testSimpleFutures(): Unit =
val futures = (1 to 10000)
.map(i => Future { i.toLong })
val futSq = futures.map(f => Future { f.await * f.await })
val sum = Future { futSq.map(_.await).sum }
println(Scheduler.blocking { sum.await })
}

View file

@ -0,0 +1,95 @@
package concurrent.simple
import scala.collection.mutable.ListBuffer
import scala.scalanative.runtime.Continuations.{boundary, suspend}
import scala.scalanative.unsafe.Tag
import scala.collection.mutable.ArrayDeque
import scala.annotation.tailrec
/* A single threaded scheduler */
object Scheduler:
private val taskQueue = ArrayDeque[Runnable]()
def schedule(task: Runnable): Unit =
synchronized {
taskQueue.addOne(task)
notify()
}
def nextTask(): Option[Runnable] = synchronized {
if taskQueue.isEmpty then None
else Some(taskQueue.removeLast())
}
def blocking[T](f: Async ?=> T): T =
var result: Option[T] = None
schedule(() => {
Future.async {
val v = f;
synchronized { result = Some(v); notifyAll() }
}
})
// spawn a bunch of threads
for (i <- 2 to 8) do
Thread
.ofPlatform()
.start(() =>
println(s"starting thread $i")
next(synchronized { result.isDefined })
)
next(synchronized { result.isDefined })
result.get
@tailrec private def next(condition: => Boolean): Unit =
if condition then ()
else
nextTask() match
case None => synchronized { if !condition then wait() }
case Some(value) => value.run()
next(condition)
trait Async:
def await[T](f: Future[T]): T
class Future[+T](body: Async ?=> T):
private var result: Option[T] = None
private var waiting: ListBuffer[T => Unit] = ListBuffer()
private def addWaiting(k: T => Unit): Unit = waiting += k
def await(using a: Async): T = a.await(this)
private def complete(): Unit =
Future.async {
val value = body
result = Some(value)
for k <- waiting do Scheduler.schedule(() => k(value))
waiting.clear()
}
Scheduler.schedule(() => complete())
object Future:
// a handler for Async
def async(body: Async ?=> Unit): Unit =
boundary[Unit] {
given Async with {
def await[T](f: Future[T]): T =
try {
f.result match
case Some(x) => x
case None => suspend[T, Unit](s => f.addWaiting(s))
} catch
case (e: Exception) => {
println(e)
throw e
}
}
body
}
end Future
// def Test(x: Future[Int], xs: List[Future[Int]]) =
// Future:
// x.await + xs.map(_.await).sum