diff options
author | Robey Pointer <robey@twitter.com> | 2011-03-31 18:49:34 -0700 |
---|---|---|
committer | Christopher Vogt <oss.nsp@cvogt.org> | 2016-11-07 02:08:38 -0500 |
commit | bc1d0f0f32d32637d23046872d96492cb385d2dd (patch) | |
tree | eb26cdb5c6644bb9a6ecdf1b05e252aa8adff496 /libraries | |
parent | 03f6504352e732c680d234e1124479d8a9e3f0ec (diff) | |
download | cbt-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')
-rw-r--r-- | libraries/eval/Eval.scala | 43 | ||||
-rw-r--r-- | libraries/eval/test/EvalTest.scala | 6 |
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 + } } } |