@@ -154,10 +154,10 @@ class IMain(val settings: Settings, protected val out: JPrintWriter) extends Imp
154154 @ deprecated(" Use `global` for access to the compiler instance." , " 2.9.0" )
155155 lazy val compiler : global.type = global
156156
157- import global ._
157+ import global .{ treeWrapper => _ , _ }
158158 import definitions .{ ScalaPackage , JavaLangPackage , PredefModule , RootClass }
159159
160- private def privateTreeOps (t : Tree ): List [Tree ] = {
160+ private implicit def privateTreeOps (t : Tree ): List [Tree ] = {
161161 (new Traversable [Tree ] {
162162 def foreach [U ](f : Tree => U ): Unit = t foreach { x => f(x) ; () }
163163 }).toList
@@ -267,7 +267,10 @@ class IMain(val settings: Settings, protected val out: JPrintWriter) extends Imp
267267 definitions.
268268 */
269269 private var _classLoader : AbstractFileClassLoader = null
270- def resetClassLoader () = _classLoader = makeClassLoader()
270+ def resetClassLoader () = {
271+ repldbg(" Setting new classloader: was " + _classLoader)
272+ _classLoader = makeClassLoader()
273+ }
271274 def classLoader : AbstractFileClassLoader = {
272275 if (_classLoader == null )
273276 resetClassLoader()
@@ -287,8 +290,10 @@ class IMain(val settings: Settings, protected val out: JPrintWriter) extends Imp
287290 override protected def findAbstractFile (name : String ): AbstractFile = {
288291 super .findAbstractFile(name) match {
289292 // deadlocks on startup if we try to translate names too early
290- case null if isInitializeComplete => generatedName(name) map (x => super .findAbstractFile(x)) orNull
291- case file => file
293+ case null if isInitializeComplete =>
294+ generatedName(name) map (x => super .findAbstractFile(x)) orNull
295+ case file =>
296+ file
292297 }
293298 }
294299 }
@@ -301,8 +306,9 @@ class IMain(val settings: Settings, protected val out: JPrintWriter) extends Imp
301306
302307 /** Given a simple repl-defined name, returns the real name of
303308 * the class representing it, e.g. for "Bippy" it may return
304- *
309+ * {{{
305310 * $line19.$read$$iw$$iw$$iw$$iw$$iw$$iw$$iw$$iw$Bippy
311+ * }}}
306312 */
307313 def generatedName (simpleName : String ): Option [String ] = {
308314 if (simpleName endsWith " $" ) optFlatName(simpleName.init) map (_ + " $" )
@@ -324,7 +330,7 @@ class IMain(val settings: Settings, protected val out: JPrintWriter) extends Imp
324330 private def mostRecentlyHandledTree : Option [Tree ] = {
325331 prevRequests.reverse foreach { req =>
326332 req.handlers.reverse foreach {
327- case x : MemberDefHandler if x.definesValue && ! isInternalVarName(x.name) => return Some (x.member)
333+ case x : MemberDefHandler if x.definesValue && ! isInternalVarName(x.name) => return Some (x.member)
328334 case _ => ()
329335 }
330336 }
@@ -347,6 +353,7 @@ class IMain(val settings: Settings, protected val out: JPrintWriter) extends Imp
347353 repldbg(" Redefining term '%s'\n %s -> %s" .format(name, t1, t2))
348354 }
349355 }
356+
350357 def recordRequest (req : Request ) {
351358 if (req == null || referencedNameMap == null )
352359 return
@@ -378,9 +385,10 @@ class IMain(val settings: Settings, protected val out: JPrintWriter) extends Imp
378385 }
379386 }
380387
381- private [nsc] def replwarn (msg : => String ): Unit =
388+ private [nsc] def replwarn (msg : => String ) {
382389 if (! settings.nowarnings.value)
383390 printMessage(msg)
391+ }
384392
385393 def isParseable (line : String ): Boolean = {
386394 beSilentDuring {
@@ -425,6 +433,7 @@ class IMain(val settings: Settings, protected val out: JPrintWriter) extends Imp
425433 case idx => s take idx
426434 }) mkString " \n "
427435 }
436+
428437 private def safePos (t : Tree , alt : Int ): Int =
429438 try t.pos.startOrPoint
430439 catch { case _ : UnsupportedOperationException => alt }
@@ -448,7 +457,7 @@ class IMain(val settings: Settings, protected val out: JPrintWriter) extends Imp
448457 }
449458 repltrace(
450459 trees map { t =>
451- privateTreeOps(t) map { t0 => t0.getClass + " at " + safePos(t0, - 1 ) + " \n " }
460+ t map { t0 => t0.getClass + " at " + safePos(t0, - 1 ) + " \n " }
452461 } mkString
453462 )
454463 // If the last tree is a bare expression, pinpoint where it begins using the
@@ -467,15 +476,20 @@ class IMain(val settings: Settings, protected val out: JPrintWriter) extends Imp
467476 else {
468477 // The position of the last tree
469478 val lastpos0 = earliestPosition(trees.last)
470- // Oh boy, the parser throws away parens so "(2+2)" is mispositioned.
471- // So until we can fix the parser we'll have to go trawling.
472- val adjustment = ((content take lastpos0).reverse takeWhile { ch =>
473- ch.isWhitespace || ch == '(' || ch == ')'
474- }).length
479+ // Oh boy, the parser throws away parens so "(2+2)" is mispositioned,
480+ // with increasingly hard to decipher positions as we move on to "() => 5",
481+ // (x: Int) => x + 1, and more. So I abandon attempts to finesse and just
482+ // look for semicolons and newlines, which I'm sure is also buggy.
483+ val (raw1, raw2) = content splitAt lastpos0
484+ repldbg(" [raw] " + raw1 + " <---> " + raw2)
485+
486+ val adjustment = (raw1.reverse takeWhile (ch => (ch != ';' ) && (ch != '\n ' ))).size
475487 val lastpos = lastpos0 - adjustment
476488
477489 // the source code split at the laboriously determined position.
478490 val (l1, l2) = content splitAt lastpos
491+ repldbg(" [adj] " + l1 + " <---> " + l2)
492+
479493 val prefix = if (l1.trim == " " ) " " else l1 + " ;\n "
480494 // Note to self: val source needs to have this precise structure so that
481495 // error messages print the user-submitted part without the "val res0 = " part.
@@ -528,18 +542,14 @@ class IMain(val settings: Settings, protected val out: JPrintWriter) extends Imp
528542 def interpret (line : String , synthetic : Boolean ): IR .Result = {
529543 def loadAndRunReq (req : Request ) = {
530544 val (result, succeeded) = req.loadAndRun
545+
531546 /** To our displeasure, ConsoleReporter offers only printMessage,
532547 * which tacks a newline on the end. Since that breaks all the
533548 * output checking, we have to take one off to balance.
534549 */
535- def show () = {
536- if (result == " " ) ()
537- else printMessage(result stripSuffix " \n " )
538- }
539-
540550 if (succeeded) {
541- if (printResults)
542- show( )
551+ if (printResults && result != " " )
552+ printMessage(result stripSuffix " \n " )
543553 else if (isReplDebug) // show quiet-mode activity
544554 printMessage(result.trim.lines map (" [quiet] " + _) mkString " \n " )
545555
@@ -550,7 +560,7 @@ class IMain(val settings: Settings, protected val out: JPrintWriter) extends Imp
550560 }
551561 else {
552562 // don't truncate stack traces
553- withoutTruncating(show( ))
563+ withoutTruncating(printMessage(result ))
554564 IR .Error
555565 }
556566 }
@@ -583,11 +593,19 @@ class IMain(val settings: Settings, protected val out: JPrintWriter) extends Imp
583593 |}
584594 """ .stripMargin.format(bindRep.evalName, boundType, boundType)
585595 )
586- bindRep.callOpt(" set" , value) match {
587- case Some (_) => interpret(" val %s = %s.value" .format(name, bindRep.evalPath))
588- case _ => repldbg(" Set failed in bind(%s, %s, %s)" .format(name, boundType, value)) ; IR .Error
596+ bindRep.callEither(" set" , value) match {
597+ case Left (ex) =>
598+ repldbg(" Set failed in bind(%s, %s, %s)" .format(name, boundType, value))
599+ repldbg(util.stackTraceString(ex))
600+ IR .Error
601+
602+ case Right (_) =>
603+ val line = " val %s = %s.value" .format(name, bindRep.evalPath)
604+ repldbg(" Interpreting: " + line)
605+ interpret(line)
589606 }
590607 }
608+
591609 def rebind (p : NamedParam ): IR .Result = {
592610 val name = p.name
593611 val oldType = typeOfTerm(name) getOrElse { return IR .Error }
@@ -683,15 +701,30 @@ class IMain(val settings: Settings, protected val out: JPrintWriter) extends Imp
683701 def call (name : String , args : Any * ): AnyRef =
684702 evalMethod(name).invoke(evalClass, args.map(_.asInstanceOf [AnyRef ]): _* )
685703
704+ def callEither (name : String , args : Any * ): Either [Throwable , AnyRef ] =
705+ try Right (call(name, args : _* ))
706+ catch { case ex : Throwable => Left (ex) }
707+
686708 def callOpt (name : String , args : Any * ): Option [AnyRef ] =
687709 try Some (call(name, args : _* ))
688- catch { case ex : Exception => bindError(ex) ; None }
710+ catch { case ex : Throwable => bindError(ex) ; None }
711+
712+ class EvalException (msg : String , cause : Throwable ) extends RuntimeException (msg, cause) { }
689713
690- private def load (s : String ): Class [_] =
691- (classLoader tryToInitializeClass s) getOrElse sys.error(" Failed to load expected class: '" + s + " '" )
714+ private def evalError (path : String , ex : Throwable ) =
715+ throw new EvalException (" Failed to load '" + path + " ': " + ex.getMessage, ex)
716+
717+ private def load (path : String ): Class [_] = {
718+ try Class .forName(path, true , classLoader)
719+ catch { case ex => evalError(path, unwrap(ex)) }
720+ }
692721
722+ var evalCaught : Option [Throwable ] = None
693723 lazy val evalClass = load(evalPath)
694- lazy val evalValue = callOpt(evalName)
724+ lazy val evalValue = callEither(evalName) match {
725+ case Left (ex) => evalCaught = Some (ex) ; None
726+ case Right (result) => Some (result)
727+ }
695728
696729 def compile (source : String ): Boolean = compileAndSaveRun(" <console>" , source)
697730 def lineAfterTyper [T ](op : => T ): T = {
@@ -726,7 +759,7 @@ class IMain(val settings: Settings, protected val out: JPrintWriter) extends Imp
726759 /** One line of code submitted by the user for interpretation */
727760 // private
728761 class Request (val line : String , val trees : List [Tree ]) {
729- val lineRep = new ReadEvalPrint ()
762+ val lineRep = new ReadEvalPrint ()
730763 import lineRep .lineAfterTyper
731764
732765 private var _originalLine : String = null
@@ -922,6 +955,7 @@ class IMain(val settings: Settings, protected val out: JPrintWriter) extends Imp
922955 try Some (definitions.getClass(newTypeName(name)))
923956 catch { case _ : MissingRequirementError => None }
924957 }
958+
925959 def safeModule (name : String ): Option [Symbol ] = {
926960 try Some (definitions.getModule(newTermName(name)))
927961 catch { case _ : MissingRequirementError => None }
@@ -942,6 +976,7 @@ class IMain(val settings: Settings, protected val out: JPrintWriter) extends Imp
942976 case nme.ROOTPKG => Some (definitions.RootClass .tpe)
943977 case name => requestForName(name) flatMap (_.compilerTypeOf get name)
944978 }
979+
945980 def symbolOfTerm (id : String ): Symbol =
946981 requestForIdent(id) flatMap (_.definedSymbols get newTermName(id)) getOrElse NoSymbol
947982
@@ -981,6 +1016,39 @@ class IMain(val settings: Settings, protected val out: JPrintWriter) extends Imp
9811016 def definedTypes = onlyTypes(allDefinedNames)
9821017 def definedSymbols = prevRequests.toSet flatMap ((x : Request ) => x.definedSymbols.values)
9831018
1019+ private def findName (name : Name ) = definedSymbols find (_.name == name)
1020+
1021+ private def missingOpt (op : => Symbol ): Option [Symbol ] =
1022+ try Some (op)
1023+ catch { case _ : MissingRequirementError => None }
1024+ private def missingWrap (op : => Symbol ): Symbol =
1025+ try op
1026+ catch { case _ : MissingRequirementError => NoSymbol }
1027+
1028+ def optCompilerClass (name : String ) = missingOpt(definitions.getClass(name))
1029+ def optCompilerModule (name : String ) = missingOpt(definitions.getModule(name))
1030+ def getCompilerClass (name : String ) = missingWrap(definitions.getClass(name))
1031+ def getCompilerModule (name : String ) = missingWrap(definitions.getModule(name))
1032+
1033+ /** Translate a repl-defined identifier into a Symbol.
1034+ */
1035+ def apply (name : String ): Symbol = {
1036+ val tpname = newTypeName(name)
1037+ (
1038+ findName(tpname)
1039+ orElse findName(tpname.companionName)
1040+ orElse optCompilerClass(name)
1041+ orElse optCompilerModule(name)
1042+ getOrElse NoSymbol
1043+ )
1044+ }
1045+ def types (name : String ): Symbol = {
1046+ findName(newTypeName(name)) getOrElse getCompilerClass(name)
1047+ }
1048+ def terms (name : String ): Symbol = {
1049+ findName(newTermName(name)) getOrElse getCompilerModule(name)
1050+ }
1051+
9841052 /** the previous requests this interpreter has processed */
9851053 private lazy val prevRequests = mutable.ListBuffer [Request ]()
9861054 private lazy val referencedNameMap = mutable.Map [Name , Request ]()
@@ -1023,6 +1091,7 @@ class IMain(val settings: Settings, protected val out: JPrintWriter) extends Imp
10231091 parse(code) foreach (ts => ts foreach (t => withoutUnwrapping(repldbg(asCompactString(t)))))
10241092 }
10251093 }
1094+
10261095 // debugging
10271096 def debugging [T ](msg : String )(res : T ) = {
10281097 repldbg(msg + " " + res)
0 commit comments