/
RTS.scala
84 lines (59 loc) · 2.37 KB
/
RTS.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
package matterhorn
import scala.language.higherKinds
import scala.concurrent.{Await, ExecutionContext, Future}
import scala.concurrent.duration.Duration
import rts.Interruptor
import rts.Interpreter._
case class RTS(ec: ExecutionContext, intr: Interruptor) {
import RTS._
def unsafePerformIO[A](io: IO[A]): Future[A] =
Val.reifyF[Future, A](unsafePerformEval(this)(io.thunk.reverse))
def unsafePerformIO_[A](io: IO[A]): A =
Await.result(unsafePerformIO(io), Duration.Inf)
}
object RTS {
val defaultRTS = RTS(ExecutionContext.Implicits.global, Interruptor.global)
case class ThreadId private[matterhorn](future: Future[Val], intr: Interruptor)
case object ThreadKilled extends Error
type Val = Any with ({ type Tag = Any })
private[matterhorn] object Val {
val unit: Val = cast(Unit)
def cast(x: Any): Val = x.asInstanceOf[Val]
def castF[F[_]](x: F[Any]): F[Val] = x.asInstanceOf[F[Val]]
def reify[A](x: Val): A = x.asInstanceOf[A]
def reifyF[F[_], A](x: Future[Val]): F[A] = x.asInstanceOf[F[A]]
}
type Thunk = List[Exp]
object Thunk {
import Exp._
import Val._
def point[A](f: Unit => A): Thunk =
Point(_ => cast(f(()))) :: Nil
def bind[A, B](xs: Thunk)(f: A => IO[B]): Thunk =
Bind(x => f(reify[A](x)).thunk) :: xs
def map[A, B](xs: Thunk)(f: A => B): Thunk =
Map(x => cast(f(reify[A](x)))) :: xs
def apply[A, B, C](f: (A, B) => C)(ioa: IO[A], iob: IO[B]): Thunk =
Apply((a, b) => cast(reify[A](a) -> reify[B](b)), ioa.thunk, iob.thunk) :: Nil
def fork[A](io: IO[A]): Thunk =
Fork(_ => io.thunk) :: Nil
def catching[A, E <: Throwable](io: IO[A])(f: E => IO[A])(implicit E: scala.reflect.ClassTag[E]): Thunk =
Catch({
case e: E => Some(f(e).thunk)
case _ => None
}, io.thunk) :: Nil
def fromFuture[A](future: Future[A]): Thunk =
Wait(ThreadId(castF[Future](future), Interruptor.unintr)) :: Nil
}
sealed trait Exp
object Exp {
import Val._
case class Point(f: Unit => Val) extends Exp
case class Map(f: Val => Val) extends Exp
case class Bind(f: Val => Thunk) extends Exp
case class Apply(f: (Val, Val) => Val, left: Thunk, right: Thunk) extends Exp
case class Fork(f: Unit => Thunk) extends Exp
case class Wait(t: ThreadId) extends Exp
case class Catch(f: Throwable => Option[Thunk], on: Thunk) extends Exp
}
}