aboutsummaryrefslogtreecommitdiff
path: root/libraries/eval
diff options
context:
space:
mode:
authorRobey Pointer <robey@twitter.com>2011-03-31 18:49:34 -0700
committerChristopher Vogt <oss.nsp@cvogt.org>2016-11-07 02:08:38 -0500
commitbc1d0f0f32d32637d23046872d96492cb385d2dd (patch)
treeeb26cdb5c6644bb9a6ecdf1b05e252aa8adff496 /libraries/eval
parent03f6504352e732c680d234e1124479d8a9e3f0ec (diff)
downloadcbt-bc1d0f0f32d32637d23046872d96492cb385d2dd.tar.gz
cbt-bc1d0f0f32d32637d23046872d96492cb385d2dd.tar.bz2
cbt-bc1d0f0f32d32637d23046872d96492cb385d2dd.zip
allow in-place eval of the type scrooge would like to do.s
Diffstat (limited to 'libraries/eval')
-rw-r--r--libraries/eval/Eval.scala43
-rw-r--r--libraries/eval/test/EvalTest.scala6
2 files changed, 36 insertions, 13 deletions
diff --git a/libraries/eval/Eval.scala b/libraries/eval/Eval.scala
index cc9a3ff..278933c 100644
--- a/libraries/eval/Eval.scala
+++ b/libraries/eval/Eval.scala
@@ -55,10 +55,10 @@ object Eval {
/**
* Eval[Int]("1 + 1") // => 2
*/
- def apply[T](code: String): T = {
+ def apply[T](code: String, resetState: Boolean = true): T = {
val id = uniqueId(code)
val className = "Evaluator__" + id
- val cls = compiler(wrapCodeInClass(className, code), className, id)
+ val cls = compiler(wrapCodeInClass(className, code), className, id, resetState)
cls.getConstructor().newInstance().asInstanceOf[() => Any].apply().asInstanceOf[T]
}
@@ -76,6 +76,21 @@ object Eval {
apply(scala.io.Source.fromInputStream(stream).mkString)
}
+ /**
+ * Compile an entire source file into the virtual classloader.
+ */
+ def compile(code: String) {
+ Eval.compiler(code)
+ }
+
+ /**
+ * Like `Eval()`, but doesn't reset the virtual classloader before evaluating. So if you've
+ * loaded classes with `compile`, they can be referenced/imported in code run by `inPlace`.
+ */
+ def inPlace[T](code: String) = {
+ apply[T](code, false)
+ }
+
private def uniqueId(code: String): String = {
val digest = MessageDigest.getInstance("SHA-1").digest(code.getBytes())
val sha = new BigInteger(1, digest).toString(16)
@@ -204,18 +219,20 @@ object Eval {
}
/**
- * Reset the compiler, compile a new class, load it, and return it. Thread-safe.
+ * Compile a new class, load it, and return it. Thread-safe.
*/
- def apply(code: String, className: String, id: String): Class[_] = synchronized {
- cache.get(id) match {
- case Some(cls) =>
- cls
- case None =>
- reset()
- apply(code)
- val cls = classLoader.loadClass(className)
- cache(id) = cls
- cls
+ def apply(code: String, className: String, id: String, resetState: Boolean = true): Class[_] = {
+ synchronized {
+ cache.get(id) match {
+ case Some(cls) =>
+ cls
+ case None =>
+ if (resetState) reset()
+ apply(code)
+ val cls = classLoader.loadClass(className)
+ cache(id) = cls
+ cls
+ }
}
}
}
diff --git a/libraries/eval/test/EvalTest.scala b/libraries/eval/test/EvalTest.scala
index a77ed97..187d0d3 100644
--- a/libraries/eval/test/EvalTest.scala
+++ b/libraries/eval/test/EvalTest.scala
@@ -25,5 +25,11 @@ object EvaluatorSpec extends Specification {
"apply(InputStream)" in {
Eval[Int](getClass.getResourceAsStream("/OnePlusOne.scala")) mustEqual 2
}
+
+ "inPlace('expression')" in {
+ Eval.compile("object Doubler { def apply(n: Int) = n * 2 }")
+ Eval.inPlace[Int]("Doubler(2)") mustEqual 4
+ Eval.inPlace[Int]("Doubler(14)") mustEqual 28
+ }
}
}