Alex Rivera | Logout

Getting type information inside scala repl via IMain

Asked 2013-03-28T09:48:14.353
8

Intent

I am trying to add support for :kind command to repl. Thanks to Eugene Burmako, I was able to get a working prototype. Though it only works with fully qualified names and fails to resolve imported names.

I am now trying to use IMain.exprTyper to do the job, as it is aware of types, imported into the repl. But there is a problem. Everything I've tried returns a ClassInfoType like the following (displayed with showRaw):

ClassInfoType(List(TypeRef(TypeRef(TypeRef(TypeRef(NoPrefix(), package <root>, List()), package java, List()), package lang, List()), class Object, List()), TypeRef(TypeRef(TypeRef(NoPrefix(), package <root>, List()), package scala, List()), trait Serializable, List())), Scope{
  def <init>(): Option.type;
  implicit def option2Iterable(xo: Option): Iterable;
  def apply(x: Object): Option;
  def empty(): Option;
  private def readResolve(): Object
}, object Option)

While the working implementation returns specific Type:

PolyType(List(TypeName("A")), ClassInfoType(List(TypeRef(ThisType(scala), TypeName("AnyRef"), List()), TypeRef(ThisType(scala), scala.Product, List()), TypeRef(ThisType(scala), scala.Serializable, List())), Scope(nme
Edit
Report

2 Answers

6

How about this? I'm using power mode which gives you access to the global from the currently running REPL, which is a shade more convenient than creating a new IMain.

scala> :power
Already in power mode.

scala> val g = global
g: $r.intp.global.type = <global>

scala> val context = g.analyzer.rootContext(NoCompilationUnit)
context: g.analyzer.Context = Context(<root>@EmptyTree unit=NoCompilationUnit scope=997093283 errors=false, reportErrors=true, throwErrors=false)

// aware imports of scala._, etc.
scala> val sym = context.lookupSymbol("Option": TypeName, _ => true).symbol
sym: g.analyzer.global.Symbol = class Option

scala> sym.tpeHK.typeParams
res21: List[g.analyzer.global.Symbol] = List(type A)

See also:

scala> intp.symbolOfType("Foo")
res26: $r.intp.global.Symbol = class Foo

But I'm not sure how to get at previously imported symbols:

scala> object Bar { class Bop }
defined object Bar

scala> import Bar.Bop
import Bar.Bop

scala> intp.symbolOfType("Bop")
res27: $r.intp.global.Symbol = <none>

Edit:

The reason OP's getting ClassInfoType instead of PolyType is due to phase. To get the same result as the power mode's global, one must set the phase to typer. To quote @retronym's explanation from REPL: intp.global vs "global" available in :power mode:

scala> :power
** Power User mode enabled - BEEP WHIR GYVE **
** :phase has been set to 'typer'.          **
    ^
    `----  this part is relevant

Symbols have an list of types (aka info-s), indexed by compiler phase. (aka TypeHistory). Many compiler phases install InfoTransformers to morph the type. See

answered 2013-03-28T23:34:39.133
2

You should use the mirror from the IMain's global:

scala> val imain = new IMain()
imain: scala.tools.nsc.interpreter.IMain = scala

scala> val mirror = imain.global.rootMirror
mirror: imain.global.Mirror = compiler mirror
answered 2013-03-28T13:02:35.767

Your Answer