@@ -22,9 +22,13 @@ import java.util.concurrent.{ TimeoutException, Callable, FutureTask, TimeUnit }
2222import scala .util .Try
2323import scala .util .control .NonFatal
2424import scala .concurrent .duration ._
25+ import scala .concurrent ._
2526import scala .language .reflectiveCalls
27+
2628import com .twitter .util .Eval
2729
30+ import monix .execution ._
31+
2832import scala .reflect .internal .util .{ BatchSourceFile , Position }
2933
3034sealed trait Severity
@@ -43,12 +47,14 @@ object EvalResult {
4347
4448 case object Timeout extends EvalResult [Nothing ]
4549 case class Success [T ](complilationInfos : CI , result : T , consoleOutput : String ) extends EvalResult [T ]
50+ case class Timeout [T ]() extends EvalResult [T ]
4651 case class EvalRuntimeError (complilationInfos : CI , runtimeError : Option [RuntimeError ]) extends EvalResult [Nothing ]
4752 case class CompilationError (complilationInfos : CI ) extends EvalResult [Nothing ]
4853 case class GeneralError (stack : Throwable ) extends EvalResult [Nothing ]
4954}
5055
51- class Evaluator (timeout : Duration = 20 .seconds) {
56+ class Evaluator (timeout : FiniteDuration = 20 .seconds) {
57+ implicit val scheduler : ExecutionContext = Scheduler .io(" evaluation-scheduler" )
5258
5359 def convert (errors : (Position , String , String )): (Severity , List [CompilationInfo ]) = {
5460 val (pos, msg, severity) = errors
@@ -60,11 +66,7 @@ class Evaluator(timeout: Duration = 20.seconds) {
6066 (sev, CompilationInfo (msg, Some (RangePosition (pos.start, pos.point, pos.end))) :: Nil )
6167 }
6268
63- def apply [T ](pre : String , code : String ): EvalResult [T ] = {
64- val allCode = s """
65- | $pre
66- | $code
67- """ .stripMargin
69+ def eval [T ](code : String ): EvalResult [T ] = {
6870 val eval = new Eval {
6971 @ volatile var errors : Map [Severity , List [CompilationInfo ]] = Map .empty
7072
@@ -82,26 +84,30 @@ class Evaluator(timeout: Duration = 20.seconds) {
8284 }
8385
8486 val result = for {
85- _ ← Try (eval.check(allCode ))
86- result ← Try (eval.apply[T ](allCode , resetState = true ))
87+ _ ← Try (eval.check(code ))
88+ result ← Try (eval.apply[T ](code , resetState = true ))
8789 } yield result
8890
8991 val errors : Map [Severity , List [CompilationInfo ]] = eval.errors.toMap
9092
91- println(allCode)
92-
93- println(result)
94-
95- println(errors)
96-
9793 result match {
9894 case scala.util.Success (r) ⇒ EvalResult .Success [T ](errors, r, " " )
9995 case scala.util.Failure (t) ⇒ t match {
10096 case e : Eval .CompilerException ⇒ EvalResult .CompilationError (errors)
101- case e ⇒ EvalResult .EvalRuntimeError (errors, None )
97+ case NonFatal (e) ⇒ EvalResult .EvalRuntimeError (errors, Option (RuntimeError (e, None )))
98+ case e ⇒ EvalResult .GeneralError (e)
10299 }
103100 }
104-
105101 }
106102
103+ def apply [T ](pre : String , code : String ): EvalResult [T ] = {
104+ val allCode = s """
105+ | $pre
106+ | $code
107+ """ .stripMargin
108+ val fut = Future ({ eval(allCode) })
109+ Try (
110+ Await .result(fut, timeout)
111+ ).getOrElse(EvalResult .Timeout ())
112+ }
107113}
0 commit comments