2015-01-20 3 views
1

Я пытаюсь использовать scala.tools.nsc.interpreter для включения интерактивной отладки (например, в Python PDB/IPDB):Scala РЕПЛ сбой при запуске с помощью scala.tools.nsc.interpreter

val foo = 123 

import scala.tools.nsc.Settings 
import scala.tools.nsc.interpreter.{ ILoop, SimpleReader } 

val repl = new ILoop 
repl.settings = new Settings 
repl.settings.usejavacp.value = true 
repl.in = SimpleReader() 
repl.createInterpreter() 

repl.intp.bind("foo", "Int", foo) 

repl.loop() 
repl.closeInterpreter() 

При запуске, это то, что я получаю :

$ scala repl.scala 
foo: Int = 123 

scala> "hello" 
java.lang.NullPointerException 
    at scala.concurrent.Await$$anonfun$ready$1.apply(package.scala:95) 
    at scala.concurrent.Await$$anonfun$ready$1.apply(package.scala:95) 
    at scala.concurrent.BlockContext$DefaultBlockContext$.blockOn(BlockContext.scala:53) 
    at scala.concurrent.Await$.ready(package.scala:95) 
    at scala.tools.nsc.interpreter.ILoop.processLine(ILoop.scala:402) 
    at scala.tools.nsc.interpreter.ILoop.loop(ILoop.scala:430) 
    at Main$$anon$1.<init>(repl.scala:14) 
    at Main$.main(repl.scala:1) 
    at Main.main(repl.scala) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:606) 
    at scala.reflect.internal.util.ScalaClassLoader$$anonfun$run$1.apply(ScalaClassLoader.scala:70) 
    at scala.reflect.internal.util.ScalaClassLoader$class.asContext(ScalaClassLoader.scala:31) 
    at scala.reflect.internal.util.ScalaClassLoader$URLClassLoader.asContext(ScalaClassLoader.scala:101) 
    at scala.reflect.internal.util.ScalaClassLoader$class.run(ScalaClassLoader.scala:70) 
    at scala.reflect.internal.util.ScalaClassLoader$URLClassLoader.run(ScalaClassLoader.scala:101) 
    at scala.tools.nsc.CommonRunner$class.run(ObjectRunner.scala:22) 
    at scala.tools.nsc.ObjectRunner$.run(ObjectRunner.scala:39) 
    at scala.tools.nsc.CommonRunner$class.runAndCatch(ObjectRunner.scala:29) 
    at scala.tools.nsc.ObjectRunner$.runAndCatch(ObjectRunner.scala:39) 
    at scala.tools.nsc.ScriptRunner.scala$tools$nsc$ScriptRunner$$runCompiled(ScriptRunner.scala:175) 
    at scala.tools.nsc.ScriptRunner$$anonfun$runScript$1.apply(ScriptRunner.scala:192) 
    at scala.tools.nsc.ScriptRunner$$anonfun$runScript$1.apply(ScriptRunner.scala:192) 
    at scala.tools.nsc.ScriptRunner$$anonfun$withCompiledScript$1$$anonfun$apply$mcZ$sp$1.apply(ScriptRunner.scala:161) 
    at scala.tools.nsc.ScriptRunner$$anonfun$withCompiledScript$1.apply$mcZ$sp(ScriptRunner.scala:161) 
    at scala.tools.nsc.ScriptRunner$$anonfun$withCompiledScript$1.apply(ScriptRunner.scala:129) 
    at scala.tools.nsc.ScriptRunner$$anonfun$withCompiledScript$1.apply(ScriptRunner.scala:129) 
    at scala.tools.nsc.util.package$.trackingThreads(package.scala:43) 
    at scala.tools.nsc.util.package$.waitingForThreads(package.scala:27) 
    at scala.tools.nsc.ScriptRunner.withCompiledScript(ScriptRunner.scala:128) 
    at scala.tools.nsc.ScriptRunner.runScript(ScriptRunner.scala:192) 
    at scala.tools.nsc.ScriptRunner.runScriptAndCatch(ScriptRunner.scala:205) 
    at scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:67) 
    at scala.tools.nsc.MainGenericRunner.run$1(MainGenericRunner.scala:87) 
    at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:98) 
    at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:103) 
    at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala) 


Abandoning crashed session. 

scala> 

Если удалить repl.intp.bind("foo", "Int", foo) часть, это то, что я получаю:

$ scala repl.scala 

scala> 123 
null 

Abandoning crashed session. 

scala> 

Что я делаю неправильно? Есть ли более простой способ перейти в интерактивный REPL во время запуска программы для целей отладки? контрольные точки, переходы и проверка местных жителей просто не делают этого иногда.

Я нахожусь на Scala 2.11.5.

+1

Вы можете попробовать Скалистый: https://github.com/xitrum-framework/scalive –

+0

@ GáborBakos: большое спасибо; кажется потенциально очень полезным! –

ответ

1

Я не знаю, почему этот комментарий не имеет магические звездочки:

// start an interpreter with the given settings 
    def process(settings: Settings): Boolean 

Таким образом, вы можете:

scala> repl process s 
Welcome to Scala version 2.11.4 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_25). 
Type in expressions to have them evaluated. 
Type :help for more information. 

scala> :quit 
res0: Boolean = true 

Или вы можете:

package myrepl 

import scala.tools.nsc.Settings 
import scala.tools.nsc.interpreter.{ ILoop, SimpleReader } 

object Test extends App { 
    val foo = 42 
    val repl = new ILoop { 
    override def printWelcome() = { 
     intp.bind("foo", foo) 
     super.printWelcome() 
     echo("Customized...") 
    } 
    } 
    val s = new Settings 
    s.usejavacp.value = true 
    repl.in = SimpleReader() 
    repl process s 
    /* 
    repl.createInterpreter() 

    repl.intp.bind("foo", "Int", foo) 

    repl.loop() 
    repl.closeInterpreter() 
    */ 
} 

И

$ scalac myrepl.scala && scala myrepl.Test 
foo: Int = 42 
Welcome to Scala version 2.11.5 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_20). 
Type in expressions to have them evaluated. 
Type :help for more information. 
Customized... 

scala> foo 
res0: Int = 42 

scala> :quit 

Кроме того,

s.Xnojline.value = true 
    //repl.in = SimpleReader() 

Я собираюсь понизить до 2.11.4 из-за Repl грохот ошибка ...

Sbt делает это overriding createInterpreter and calling bind there.

Edit:

val repl = new ILoop { 
    override def printWelcome() = { 
     //import scala.concurrent.duration._ 
     //Await.ready(globalFuture, 10.minutes) // sorry, it's private! 
     super.printWelcome() 
     echo("Customizing...") 
     processLine("") // block for init to finish 
     intp.bind("foo", foo) 
    } 
    } 

Частный globalFuture является препятствием для подрыва запуска:

object Solid extends App { 
    val foo = 42 
    val repl = new ILoop { 
    override def printWelcome() = { 
     super.printWelcome() 
     echo("Customized...") 
    } 
    } 
    val s = new Settings 
    s.Xnojline.value = true 
    s.usejavacp.value = true 
    repl.settings = s 
    repl.createInterpreter() 
    repl.in = SimpleReader() 
    repl.intp.initializeSynchronous() 
    repl.loopPostInit() 
    repl.globalFuture = concurrent.Future.successful(true) 

    repl.intp.bind("foo", "Int", foo) 

    try repl.loop() 
    finally repl.closeInterpreter() 
} 

Опция -Yrepl-sync больше не почитается в 2.11.

+0

спасибо! если я заменю '.loop()' вызов на '.process (repl.settings)', он работает как рекламируемый, однако evaling 'foo' yields' error: not found: value foo' - возможно ли связывать имена к REPL? –

+0

@ErikAllik Запуск должен быть переделан, а также показать, как sbt выполняет свою консоль init. Там также есть -i для misc init. –

+0

Запуск вашего кода без изменений на 2.11.4 или 2.11.5 дает мне: 'scala.reflect.internal.Symbols $ CyclicReference: незаконная циклическая ссылка с участием объекта Predef', а затем, если я продолжаю повторять, он, недетерминистически, либо работает, или печатает ту же ошибку, но не сбой ... –

 Смежные вопросы

  • Нет связанных вопросов^_^