Init
This commit is contained in:
commit
26f5bf3c3e
1
.bsp/sbt.json
Normal file
1
.bsp/sbt.json
Normal 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
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
.metals
|
||||||
|
target
|
||||||
|
.bloop
|
2
.scalafmt.conf
Normal file
2
.scalafmt.conf
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
version = "3.6.1"
|
||||||
|
runner.dialect = scala3
|
22
build.sbt
Normal file
22
build.sbt
Normal 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
1
project/build.properties
Normal file
|
@ -0,0 +1 @@
|
||||||
|
sbt.version = 1.8.2
|
6
project/metals.sbt
Normal file
6
project/metals.sbt
Normal 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
1
project/plugins.sbt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
addSbtPlugin("org.scala-native" % "sbt-scala-native" % "0.5.0-SNAPSHOT")
|
6
project/project/metals.sbt
Normal file
6
project/project/metals.sbt
Normal 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")
|
||||||
|
|
6
project/project/project/metals.sbt
Normal file
6
project/project/project/metals.sbt
Normal 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
68
src/main/scala/Gen.scala
Normal 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
52
src/main/scala/Main.scala
Normal 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 })
|
||||||
|
}
|
95
src/main/scala/concurrent/simple/simple-futures.scala
Normal file
95
src/main/scala/concurrent/simple/simple-futures.scala
Normal 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
|
Loading…
Reference in a new issue