@@ -228,6 +228,65 @@ class CompilingInterpreter(out: PrintWriter, ictx: Context) extends Compiler wit
228
228
}
229
229
}
230
230
231
+ private def loadAndSetValue (objectName : String , value : AnyRef ) = {
232
+ /** This terrible string is the wrapped class's full name inside the
233
+ * classloader:
234
+ * lineX$object$$iw$$iw$list$object
235
+ */
236
+ val objName : String = List (
237
+ currentLineName + INTERPRETER_WRAPPER_SUFFIX ,
238
+ INTERPRETER_IMPORT_WRAPPER ,
239
+ INTERPRETER_IMPORT_WRAPPER ,
240
+ objectName
241
+ ).mkString(" $" )
242
+
243
+ try {
244
+ val resObj : Class [_] = Class .forName(objName, true , classLoader)
245
+ val setMethod = resObj.getDeclaredMethods.find(_.getName == " set" )
246
+
247
+ setMethod.fold(false ) { method =>
248
+ method.invoke(resObj, value) == null
249
+ }
250
+ } catch {
251
+ case NonFatal (_) =>
252
+ // Unable to set value on object due to exception during reflection
253
+ false
254
+ }
255
+ }
256
+
257
+ /** This bind is implemented by creating an object with a set method and a
258
+ * field `value`. The value is then set via Java reflection.
259
+ *
260
+ * Example: We want to bind a value `List(1,2,3)` to identifier `list` from
261
+ * sbt. The bind method accomplishes this by creating the following:
262
+ * {{{
263
+ * object ContainerObjectWithUniqueID {
264
+ * var value: List[Int] = _
265
+ * def set(x: Any) = value = x.asInstanceOf[List[Int]]
266
+ * }
267
+ * val list = ContainerObjectWithUniqueID.value
268
+ * }}}
269
+ *
270
+ * Between the object being created and the value being assigned, the value
271
+ * inside the object is set via reflection.
272
+ */
273
+ override def bind (id : String , boundType : String , value : AnyRef )(implicit ctx : Context ): Interpreter .Result =
274
+ interpret(
275
+ """
276
+ |object %s {
277
+ | var value: %s = _
278
+ | def set(x: Any) = value = x.asInstanceOf[%s]
279
+ |}
280
+ """ .stripMargin.format(id + INTERPRETER_WRAPPER_SUFFIX , boundType, boundType)
281
+ ) match {
282
+ case Interpreter .Success if loadAndSetValue(id + INTERPRETER_WRAPPER_SUFFIX , value) =>
283
+ val line = " val %s = %s.value" .format(id, id + INTERPRETER_WRAPPER_SUFFIX )
284
+ interpret(line)
285
+ case Interpreter .Error | Interpreter .Incomplete =>
286
+ out.println(" Set failed in bind(%s, %s, %s)" .format(id, boundType, value))
287
+ Interpreter .Error
288
+ }
289
+
231
290
/** Trait collecting info about one of the statements of an interpreter request */
232
291
private trait StatementInfo {
233
292
/** The statement */
@@ -738,6 +797,9 @@ class CompilingInterpreter(out: PrintWriter, ictx: Context) extends Compiler wit
738
797
INTERPRETER_LINE_PREFIX + num
739
798
}
740
799
800
+ private def currentLineName =
801
+ INTERPRETER_LINE_PREFIX + (nextLineNo - 1 )
802
+
741
803
/** next result variable number to use */
742
804
private var nextVarNameNo = 0
743
805
0 commit comments