diff options
author | Paul Phillips <paulp@improving.org> | 2011-05-29 21:30:29 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2011-05-29 21:30:29 +0000 |
commit | a8926ae0b28d606e240f409adca69f1d91f45990 (patch) | |
tree | d33af8c263ca170a4440d3f4005f69f0916b5b14 | |
parent | 4c7d23b470b71e730024d1f7797f742dc97207fa (diff) | |
download | scala-a8926ae0b28d606e240f409adca69f1d91f45990.tar.gz scala-a8926ae0b28d606e240f409adca69f1d91f45990.tar.bz2 scala-a8926ae0b28d606e240f409adca69f1d91f45990.zip |
Now :t types declarations as well as expression...
Now :t types declarations as well as expressions, and cleans up the
output the same way the repl does so stray unsolved type constraints
don't befuddle anyone. Closes #4391, no review.
-rw-r--r-- | src/compiler/scala/tools/nsc/interpreter/ILoop.scala | 10 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/interpreter/IMain.scala | 55 | ||||
-rw-r--r-- | test/files/run/bug4556.check | 17 | ||||
-rw-r--r-- | test/files/run/bug4556.scala | 9 | ||||
-rw-r--r-- | test/files/run/repl-colon-type.check | 57 | ||||
-rw-r--r-- | test/files/run/repl-colon-type.scala | 23 |
6 files changed, 122 insertions, 49 deletions
diff --git a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala index d83076f0be..dc2a653c83 100644 --- a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala +++ b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala @@ -419,13 +419,11 @@ class ILoop(in0: Option[BufferedReader], protected val out: PrintWriter) try newJavap() catch { case _: Exception => null } - // TODO: unsolved types shouldn't make it out of this alive. - // - // scala> :t Some(Set(1)) getOrElse Set("abc") - // scala.collection.immutable.Set[_ >: ? <: ?] + // Still todo: modules. private def typeCommand(line: String): Result = { - intp.typeOfExpression(line, false) match { - case Some(tp) => tp.toString + if (line.trim == "") ":type <expression>" + else intp.typeOfExpression(line, false) match { + case Some(tp) => intp.afterTyper(tp.toString) case _ => "" // the error message was already printed } } diff --git a/src/compiler/scala/tools/nsc/interpreter/IMain.scala b/src/compiler/scala/tools/nsc/interpreter/IMain.scala index 3f91f3c0d6..2594df90d1 100644 --- a/src/compiler/scala/tools/nsc/interpreter/IMain.scala +++ b/src/compiler/scala/tools/nsc/interpreter/IMain.scala @@ -510,6 +510,19 @@ class IMain(val settings: Settings, protected val out: PrintWriter) extends Impo Right(buildRequest(line, trees)) } + def typeCleanser(sym: Symbol, memberName: Name): Type = { + // the types are all =>T; remove the => + val tp1 = afterTyper(sym.info.nonPrivateDecl(memberName).tpe match { + case NullaryMethodType(tp) => tp + case tp => tp + }) + // normalize non-public types so we don't see protected aliases like Self + afterTyper(tp1 match { + case TypeRef(_, sym, _) if !sym.isPublic => tp1.normalize + case tp => tp + }) + } + /** * Interpret one line of input. All feedback, including parse errors * and evaluation results, are printed via the supplied compiler's @@ -817,25 +830,13 @@ class IMain(val settings: Settings, protected val out: PrintWriter) extends Impo def lookupTypeOf(name: Name) = typeOf.getOrElse(name, typeOf(global.encode(name.toString))) def simpleNameOfType(name: TypeName) = (compilerTypeOf get name) map (_.typeSymbol.simpleName) - private def typeMap[T](f: Type => T): Map[Name, T] = { - def toType(name: Name): T = { - // the types are all =>T; remove the => - val tp1 = lineAfterTyper(resultSymbol.info.nonPrivateDecl(name).tpe match { - case NullaryMethodType(tp) => tp - case tp => tp - }) - // normalize non-public types so we don't see protected aliases like Self - lineAfterTyper(tp1 match { - case TypeRef(_, sym, _) if !sym.isPublic => f(tp1.normalize) - case tp => f(tp) - }) - } - termNames ++ typeNames map (x => x -> toType(x)) toMap - } + private def typeMap[T](f: Type => T): Map[Name, T] = + termNames ++ typeNames map (x => x -> f(typeCleanser(resultSymbol, x))) toMap + /** Types of variables defined by this request. */ lazy val compilerTypeOf = typeMap[Type](x => x) /** String representations of same. */ - lazy val typeOf = typeMap[String](_.toString) + lazy val typeOf = typeMap[String](tp => afterTyper(tp.toString)) // lazy val definedTypes: Map[Name, Type] = { // typeNames map (x => x -> afterTyper(resultSymbol.info.nonPrivateDecl(x).tpe)) toMap @@ -973,6 +974,26 @@ class IMain(val settings: Settings, protected val out: PrintWriter) extends Impo } } + // Since people will be giving us ":t def foo = 5" even though that is not an + // expression, we have a means of typing declarations too. + private def typeOfDeclaration(code: String): Option[Type] = { + repldbg("typeOfDeclaration(" + code + ")") + val obname = freshInternalVarName() + + interpret("object " + obname + " {\n" + code + "\n}\n", true) match { + case IR.Success => + val sym = symbolOfTerm(obname) + if (sym == NoSymbol) None else { + // TODO: bitmap$n is not marked synthetic. + val decls = sym.tpe.decls.toList filterNot (x => x.isConstructor || x.isPrivate || (x.name.toString contains "$")) + repldbg("decls: " + decls) + decls.lastOption map (decl => typeCleanser(sym, decl.name)) + } + case _ => + None + } + } + // XXX literals. // 1) Identifiers defined in the repl. // 2) A path loadable via getModule. @@ -1011,7 +1032,7 @@ class IMain(val settings: Settings, protected val out: PrintWriter) extends Impo // while letting errors through, so it is first trying it silently: if there // is an error, and errors are desired, then it re-evaluates non-silently // to induce the error message. - beSilentDuring(evaluate()) orElse { + beSilentDuring(evaluate()) orElse beSilentDuring(typeOfDeclaration(expr)) orElse { if (!silent) evaluate() diff --git a/test/files/run/bug4556.check b/test/files/run/bug4556.check deleted file mode 100644 index 69d0b4fda1..0000000000 --- a/test/files/run/bug4556.check +++ /dev/null @@ -1,17 +0,0 @@ -Type in expressions to have them evaluated. -Type :help for more information. - -scala> - -scala> :type [List(1, 2, 3)] -<console>:2: error: illegal start of simple expression - [List(1, 2, 3)] - ^ - - -scala> :type List(1, 2, 3) -List[Int] - -scala> - -scala> diff --git a/test/files/run/bug4556.scala b/test/files/run/bug4556.scala deleted file mode 100644 index 8f682ce7df..0000000000 --- a/test/files/run/bug4556.scala +++ /dev/null @@ -1,9 +0,0 @@ -import scala.tools.partest.ReplTest - -object Test extends ReplTest { - def code = """ - |:type [List(1, 2, 3)] - |:type List(1, 2, 3) - """.stripMargin -} - diff --git a/test/files/run/repl-colon-type.check b/test/files/run/repl-colon-type.check new file mode 100644 index 0000000000..66c2fcc77f --- /dev/null +++ b/test/files/run/repl-colon-type.check @@ -0,0 +1,57 @@ +Type in expressions to have them evaluated. +Type :help for more information. + +scala> + +scala> :type List[1, 2, 3] +<console>:2: error: identifier expected but integer literal found. + List[1, 2, 3] + ^ + + +scala> :type List(1, 2, 3) +List[Int] + +scala> :type def foo[T](x: T) = List(x) +[T](x: T)List[T] + +scala> :type val bar = List(Set(1)) +List[scala.collection.immutable.Set[Int]] + +scala> :type lazy val bar = Set(Set(1)) +scala.collection.immutable.Set[scala.collection.immutable.Set[Int]] + +scala> :type def f[T >: Null, U <: String](x: T, y: U) = Set(x, y) +[T >: Null, U <: String](x: T, y: U)scala.collection.immutable.Set[Any] + +scala> :type def x = 1 ; def bar[T >: Null <: AnyRef](xyz: T) = 5 +[T >: Null <: AnyRef](xyz: T)Int + +scala> + +scala> :type 5 +Int + +scala> :type val f = 5 +Int + +scala> :type lazy val f = 5 +Int + +scala> :type protected lazy val f = 5 +Int + +scala> :type def f = 5 +Int + +scala> :type def f() = 5 +()Int + +scala> + +scala> :type def g[T](xs: Set[_ <: T]) = Some(xs.head) +[T](xs: Set[_ <: T])Some[T] + +scala> + +scala> diff --git a/test/files/run/repl-colon-type.scala b/test/files/run/repl-colon-type.scala new file mode 100644 index 0000000000..39ab580d2a --- /dev/null +++ b/test/files/run/repl-colon-type.scala @@ -0,0 +1,23 @@ +import scala.tools.partest.ReplTest + +object Test extends ReplTest { + def code = """ + |:type List[1, 2, 3] + |:type List(1, 2, 3) + |:type def foo[T](x: T) = List(x) + |:type val bar = List(Set(1)) + |:type lazy val bar = Set(Set(1)) + |:type def f[T >: Null, U <: String](x: T, y: U) = Set(x, y) + |:type def x = 1 ; def bar[T >: Null <: AnyRef](xyz: T) = 5 + | + |:type 5 + |:type val f = 5 + |:type lazy val f = 5 + |:type protected lazy val f = 5 + |:type def f = 5 + |:type def f() = 5 + | + |:type def g[T](xs: Set[_ <: T]) = Some(xs.head) + """.stripMargin +} + |