From 5c607cd402001b57721afef8153d9bec5e68c933 Mon Sep 17 00:00:00 2001 From: Felix Mulder Date: Wed, 30 Nov 2016 14:21:51 +0100 Subject: Add basic Show capability --- library/src/dotty/Show.scala | 88 ++++++++++++++++++++++++++++++++++++++ library/test/dotty/ShowTests.scala | 76 ++++++++++++++++++++++++++++++++ project/Build.scala | 3 +- 3 files changed, 166 insertions(+), 1 deletion(-) create mode 100644 library/src/dotty/Show.scala create mode 100644 library/test/dotty/ShowTests.scala diff --git a/library/src/dotty/Show.scala b/library/src/dotty/Show.scala new file mode 100644 index 000000000..123fffdc7 --- /dev/null +++ b/library/src/dotty/Show.scala @@ -0,0 +1,88 @@ +package dotty + +import scala.annotation.implicitNotFound + +@implicitNotFound("No member of type class Show could be found for ${T}") +trait Show[-T] { + def show(t: T): String +} + +object Show { + implicit class ShowValue[V](val v: V) extends AnyVal { + def show(implicit ev: Show[V] = null): String = + if (ev != null) ev.show(v) + else v.toString + } + + implicit val stringShow = new Show[String] { + //charEscapeSeq ::= ‘\‘ (‘b‘ | ‘t‘ | ‘n‘ | ‘f‘ | ‘r‘ | ‘"‘ | ‘'‘ | ‘\‘) + def show(str: String) = + "\"" + + str + .replaceAll("\b", "\\\\b") + .replaceAll("\t", "\\\\t") + .replaceAll("\n", "\\\\n") + .replaceAll("\f", "\\\\f") + .replaceAll("\r", "\\\\r") + .replaceAll("\'", "\\\\'") + .replaceAll("\"", "\\\\\"") + + "\"" + } + + implicit val intShow = new Show[Int] { + def show(i: Int) = i.toString + } + + implicit val floatShow = new Show[Float] { + def show(f: Float) = f + "f" + } + + implicit val doubleShow = new Show[Double] { + def show(d: Double) = d.toString + } + + implicit val charShow = new Show[Char] { + def show(c: Char) = "'" + (c match { + case '\b' => "\\b" + case '\t' => "\\t" + case '\n' => "\\n" + case '\f' => "\\f" + case '\r' => "\\r" + case '\'' => "\\'" + case '\"' => "\\\"" + case c => c + }) + "'" + } + + object List { + implicit def showList[T](implicit st: Show[T]) = new Show[List[T]] { + def show(xs: List[T]) = + if (xs.isEmpty) "Nil" + else "List(" + xs.map(_.show).mkString(", ") + ")" + } + + implicit val showNil = new Show[List[Nothing]] { + def show(xs: List[Nothing]) = "Nil" + } + } + + object Option { + implicit def showOption[T](implicit st: Show[T]) = new Show[Option[T]] { + def show(ot: Option[T]): String = ot match { + case Some(t) => "Some("+ st.show(t) + ")" + case none => "None" + } + } + + implicit val showNone = new Show[Option[Nothing]] { + def show(n: Option[Nothing]) = "None" + } + } + + object Map { + implicit def showMap[K, V](implicit sk: Show[K], sv: Show[V]) = new Show[Map[K, V]] { + def show(m: Map[K, V]) = + "Map(" + m.map { case (k, v) => sk.show(k) + " -> " + sv.show(v) } .mkString (", ") + ")" + } + } +} diff --git a/library/test/dotty/ShowTests.scala b/library/test/dotty/ShowTests.scala new file mode 100644 index 000000000..ef259e5d8 --- /dev/null +++ b/library/test/dotty/ShowTests.scala @@ -0,0 +1,76 @@ +package dotty + +import org.junit.Test +import org.junit.Assert._ + +class ShowTests { + import Show._ + + @Test def showString = { + assertEquals("\"\\thello world!\"", "\thello world!".show) + assertEquals("\"\\nhello world!\"", "\nhello world!".show) + assertEquals("\"\\rhello world!\"", "\rhello world!".show) + assertEquals("\"\\b\\t\\n\\f\\r\\\'\\\"\"", "\b\t\n\f\r\'\"".show) + } + + @Test def showFloat = { + assertEquals("1.0f", 1.0f.show) + assertEquals("1.0f", 1.0F.show) + } + + @Test def showDouble = { + assertEquals("1.0", 1.0d.show) + assertEquals("1.0", 1.0.show) + } + + @Test def showChar = { + assertEquals("'\\b'", '\b'.show) + assertEquals("'\\t'", '\t'.show) + assertEquals("'\\n'", '\n'.show) + assertEquals("'\\f'", '\f'.show) + assertEquals("'\\r'", '\r'.show) + assertEquals("'\\''", '\''.show) + assertEquals("'\\\"'", '\"'.show) + } + + @Test def showCar = { + import Show.List._ + case class Car(model: String, manufacturer: String, year: Int) + implicit val showCar = new Show[Car] { + def show(c: Car) = + "Car(" + c.model.show + ", " + c.manufacturer.show + ", " + c.year.show + ")" + } + + case class Shop(xs: List[Car], name: String) + implicit val showShop = new Show[Shop] { + def show(sh: Shop) = + "Shop(" + sh.xs.show + ", " + sh.name.show + ")" + } + + assertEquals("Car(\"Mustang\", \"Ford\", 1967)", Car("Mustang", "Ford", 1967).show) + } + + @Test def showOptions = { + import Show.Option._ + // TODO: first case is not possible since there's no Show[Nothing] - yet + //assertEquals("None", None.show) + assertEquals("None", (None: Option[String]).show) + assertEquals("Some(\"hello opt\")", Some("hello opt").show) + } + + @Test def showMaps = { + import Show.Map._ + val mp = scala.collection.immutable.Map("str1" -> "val1", "str2" -> "val2") + assertEquals("Map(\"str1\" -> \"val1\", \"str2\" -> \"val2\")", mp.show) + } + + @Test def withoutShow = { + case class Car(model: String, manufacturer: String, year: Int) + + assertEquals("Car(Mustang,Ford,1967)", Car("Mustang", "Ford", 1967).show) + assertEquals( + "Map(str1 -> val1, str2 -> val2)", + scala.collection.immutable.Map("str1" -> "val1", "str2" -> "val2").show + ) + } +} diff --git a/project/Build.scala b/project/Build.scala index 002bcfbab..ea7ce31af 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -375,7 +375,8 @@ object DottyBuild extends Build { settings( libraryDependencies ++= Seq( "org.scala-lang" % "scala-reflect" % scalaVersion.value, - "org.scala-lang" % "scala-library" % scalaVersion.value + "org.scala-lang" % "scala-library" % scalaVersion.value, + "com.novocode" % "junit-interface" % "0.11" % "test" ) ). settings(publishing) -- cgit v1.2.3 From c619f762b966bc0d2f4de30b001eb7df76c5a347 Mon Sep 17 00:00:00 2001 From: Felix Mulder Date: Wed, 30 Nov 2016 14:22:19 +0100 Subject: Fix `Option[Nothing]` show --- library/test/dotty/ShowTests.scala | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/library/test/dotty/ShowTests.scala b/library/test/dotty/ShowTests.scala index ef259e5d8..92539d0c4 100644 --- a/library/test/dotty/ShowTests.scala +++ b/library/test/dotty/ShowTests.scala @@ -52,8 +52,7 @@ class ShowTests { @Test def showOptions = { import Show.Option._ - // TODO: first case is not possible since there's no Show[Nothing] - yet - //assertEquals("None", None.show) + assertEquals("None", None.show) assertEquals("None", (None: Option[String]).show) assertEquals("Some(\"hello opt\")", Some("hello opt").show) } -- cgit v1.2.3 From 8bb9c849c6e918c31dea5910498319e96bcadd6b Mon Sep 17 00:00:00 2001 From: Felix Mulder Date: Wed, 30 Nov 2016 15:01:56 +0100 Subject: Make repl use show instances where possible --- .../dotty/tools/dotc/repl/CompilingInterpreter.scala | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/repl/CompilingInterpreter.scala b/compiler/src/dotty/tools/dotc/repl/CompilingInterpreter.scala index f269fef64..ad718100c 100644 --- a/compiler/src/dotty/tools/dotc/repl/CompilingInterpreter.scala +++ b/compiler/src/dotty/tools/dotc/repl/CompilingInterpreter.scala @@ -695,8 +695,21 @@ class CompilingInterpreter( s""" + "$varOrVal $prettyName: $varType = " + { | if ($fullPath.asInstanceOf[AnyRef] != null) { - | (if ($fullPath.toString().contains('\\n')) "\\n" else "") + - | $fullPath.toString() + "\\n" + | (if ($fullPath.toString().contains('\\n')) "\\n" else "") + { + | import dotty.Show._ + | if ("$varType".matches(".*Map\\\\[.*,.*\\\\]")) { + | import dotty.Show.Map._ + | $fullPath.show /*toString()*/ + "\\n" + | } else if ("$varType".matches(".*List\\\\[.*\\\\]")) { + | import dotty.Show.List._ + | $fullPath.show /*toString()*/ + "\\n" + | } else if ("$varType".matches(".*Option\\\\[.*\\\\]")) { + | import dotty.Show.Option._ + | $fullPath.show /*toString()*/ + "\\n" + | } else { + | $fullPath.show /*toString()*/ + "\\n" + | } + | } | } else { | "null\\n" | } -- cgit v1.2.3 From 8b7a7ea0cf25b55ea842fe1f299e1576b8bc3e5a Mon Sep 17 00:00:00 2001 From: Felix Mulder Date: Wed, 30 Nov 2016 15:02:14 +0100 Subject: Print List and Map abbreviated --- compiler/src/dotty/tools/dotc/repl/CompilingInterpreter.scala | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/repl/CompilingInterpreter.scala b/compiler/src/dotty/tools/dotc/repl/CompilingInterpreter.scala index ad718100c..d193148ef 100644 --- a/compiler/src/dotty/tools/dotc/repl/CompilingInterpreter.scala +++ b/compiler/src/dotty/tools/dotc/repl/CompilingInterpreter.scala @@ -683,9 +683,16 @@ class CompilingInterpreter( code.print(resultExtractors.mkString("")) } + private val ListReg = """^.*List\[(\w+)\]$""".r + private val MapReg = """^.*Map\[(\w+),[ ]*(\w+)\]$""".r + private def resultExtractor(req: Request, varName: Name): String = { val prettyName = varName.decode - val varType = string2code(req.typeOf(varName)) + val varType = string2code(req.typeOf(varName)) match { + case ListReg(param) => s"List[$param]" + case MapReg(k, v) => s"Map[$k, $v]" + case x => x + } val fullPath = req.fullPath(varName) val varOrVal = statement match { -- cgit v1.2.3 From a190cfe4f0ece8221d8d7e4b27e4bf73ca665a56 Mon Sep 17 00:00:00 2001 From: Felix Mulder Date: Wed, 30 Nov 2016 15:17:14 +0100 Subject: Get rid of nesting implicits --- .../tools/dotc/repl/CompilingInterpreter.scala | 13 +----- library/src/dotty/Show.scala | 48 +++++++++++----------- library/test/dotty/ShowTests.scala | 8 +--- 3 files changed, 26 insertions(+), 43 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/repl/CompilingInterpreter.scala b/compiler/src/dotty/tools/dotc/repl/CompilingInterpreter.scala index d193148ef..e0fda8258 100644 --- a/compiler/src/dotty/tools/dotc/repl/CompilingInterpreter.scala +++ b/compiler/src/dotty/tools/dotc/repl/CompilingInterpreter.scala @@ -704,18 +704,7 @@ class CompilingInterpreter( | if ($fullPath.asInstanceOf[AnyRef] != null) { | (if ($fullPath.toString().contains('\\n')) "\\n" else "") + { | import dotty.Show._ - | if ("$varType".matches(".*Map\\\\[.*,.*\\\\]")) { - | import dotty.Show.Map._ - | $fullPath.show /*toString()*/ + "\\n" - | } else if ("$varType".matches(".*List\\\\[.*\\\\]")) { - | import dotty.Show.List._ - | $fullPath.show /*toString()*/ + "\\n" - | } else if ("$varType".matches(".*Option\\\\[.*\\\\]")) { - | import dotty.Show.Option._ - | $fullPath.show /*toString()*/ + "\\n" - | } else { - | $fullPath.show /*toString()*/ + "\\n" - | } + | $fullPath.show /*toString()*/ + "\\n" | } | } else { | "null\\n" diff --git a/library/src/dotty/Show.scala b/library/src/dotty/Show.scala index 123fffdc7..103341d00 100644 --- a/library/src/dotty/Show.scala +++ b/library/src/dotty/Show.scala @@ -15,7 +15,9 @@ object Show { } implicit val stringShow = new Show[String] { - //charEscapeSeq ::= ‘\‘ (‘b‘ | ‘t‘ | ‘n‘ | ‘f‘ | ‘r‘ | ‘"‘ | ‘'‘ | ‘\‘) + // From 2.12 spec: + // + // charEscapeSeq ::= ‘\‘ (‘b‘ | ‘t‘ | ‘n‘ | ‘f‘ | ‘r‘ | ‘"‘ | ‘'‘ | ‘\‘) def show(str: String) = "\"" + str @@ -54,35 +56,33 @@ object Show { }) + "'" } - object List { - implicit def showList[T](implicit st: Show[T]) = new Show[List[T]] { - def show(xs: List[T]) = - if (xs.isEmpty) "Nil" - else "List(" + xs.map(_.show).mkString(", ") + ")" - } + implicit def showList[T](implicit st: Show[T]) = new Show[List[T]] { + def show(xs: List[T]) = + if (xs.isEmpty) "Nil" + else "List(" + xs.map(_.show).mkString(", ") + ")" + } - implicit val showNil = new Show[List[Nothing]] { - def show(xs: List[Nothing]) = "Nil" - } + implicit val showNil = new Show[List[Nothing]] { + def show(xs: List[Nothing]) = "Nil" } - object Option { - implicit def showOption[T](implicit st: Show[T]) = new Show[Option[T]] { - def show(ot: Option[T]): String = ot match { - case Some(t) => "Some("+ st.show(t) + ")" - case none => "None" - } + implicit def showOption[T](implicit st: Show[T]) = new Show[Option[T]] { + def show(ot: Option[T]): String = ot match { + case Some(t) => "Some("+ st.show(t) + ")" + case none => "None" } + } - implicit val showNone = new Show[Option[Nothing]] { - def show(n: Option[Nothing]) = "None" - } + implicit val showNone = new Show[Option[Nothing]] { + def show(n: Option[Nothing]) = "None" } - object Map { - implicit def showMap[K, V](implicit sk: Show[K], sv: Show[V]) = new Show[Map[K, V]] { - def show(m: Map[K, V]) = - "Map(" + m.map { case (k, v) => sk.show(k) + " -> " + sv.show(v) } .mkString (", ") + ")" - } + implicit def showMap[K, V](implicit sk: Show[K], sv: Show[V]) = new Show[Map[K, V]] { + def show(m: Map[K, V]) = + "Map(" + m.map { case (k, v) => sk.show(k) + " -> " + sv.show(v) } .mkString (", ") + ")" + } + + implicit def showMapOfNothing = new Show[Map[Nothing, Nothing]] { + def show(m: Map[Nothing, Nothing]) = m.toString } } diff --git a/library/test/dotty/ShowTests.scala b/library/test/dotty/ShowTests.scala index 92539d0c4..7230106d5 100644 --- a/library/test/dotty/ShowTests.scala +++ b/library/test/dotty/ShowTests.scala @@ -34,7 +34,6 @@ class ShowTests { } @Test def showCar = { - import Show.List._ case class Car(model: String, manufacturer: String, year: Int) implicit val showCar = new Show[Car] { def show(c: Car) = @@ -51,14 +50,12 @@ class ShowTests { } @Test def showOptions = { - import Show.Option._ assertEquals("None", None.show) assertEquals("None", (None: Option[String]).show) assertEquals("Some(\"hello opt\")", Some("hello opt").show) } @Test def showMaps = { - import Show.Map._ val mp = scala.collection.immutable.Map("str1" -> "val1", "str2" -> "val2") assertEquals("Map(\"str1\" -> \"val1\", \"str2\" -> \"val2\")", mp.show) } @@ -67,9 +64,6 @@ class ShowTests { case class Car(model: String, manufacturer: String, year: Int) assertEquals("Car(Mustang,Ford,1967)", Car("Mustang", "Ford", 1967).show) - assertEquals( - "Map(str1 -> val1, str2 -> val2)", - scala.collection.immutable.Map("str1" -> "val1", "str2" -> "val2").show - ) + assertEquals("Map()", Map().show) } } -- cgit v1.2.3 From e4f7b386d42352cea79b2a385668ce47e15cb13c Mon Sep 17 00:00:00 2001 From: Felix Mulder Date: Wed, 30 Nov 2016 15:51:36 +0100 Subject: Optimize `Show[String]` instance --- library/src/dotty/Show.scala | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/library/src/dotty/Show.scala b/library/src/dotty/Show.scala index 103341d00..36327b834 100644 --- a/library/src/dotty/Show.scala +++ b/library/src/dotty/Show.scala @@ -19,16 +19,20 @@ object Show { // // charEscapeSeq ::= ‘\‘ (‘b‘ | ‘t‘ | ‘n‘ | ‘f‘ | ‘r‘ | ‘"‘ | ‘'‘ | ‘\‘) def show(str: String) = - "\"" + - str - .replaceAll("\b", "\\\\b") - .replaceAll("\t", "\\\\t") - .replaceAll("\n", "\\\\n") - .replaceAll("\f", "\\\\f") - .replaceAll("\r", "\\\\r") - .replaceAll("\'", "\\\\'") - .replaceAll("\"", "\\\\\"") + - "\"" + "\"" + { + val sb = new StringBuilder + str.foreach { + case '\b' => sb.append("\\b") + case '\t' => sb.append("\\t") + case '\n' => sb.append("\\n") + case '\f' => sb.append("\\f") + case '\r' => sb.append("\\r") + case '\'' => sb.append("\\'") + case '\"' => sb.append("\\\"") + case c => sb.append(c) + } + sb.toString + } + "\"" } implicit val intShow = new Show[Int] { -- cgit v1.2.3 From 8a754cfdef89a57a9c0139c3cc767b1f5351f1db Mon Sep 17 00:00:00 2001 From: Felix Mulder Date: Wed, 30 Nov 2016 16:02:27 +0100 Subject: Get rid of null in evidence param --- library/src/dotty/Show.scala | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/library/src/dotty/Show.scala b/library/src/dotty/Show.scala index 36327b834..2febda0e7 100644 --- a/library/src/dotty/Show.scala +++ b/library/src/dotty/Show.scala @@ -8,10 +8,13 @@ trait Show[-T] { } object Show { + private[this] val defaultShow = new Show[Any] { + def show(x: Any) = x.toString + } + implicit class ShowValue[V](val v: V) extends AnyVal { - def show(implicit ev: Show[V] = null): String = - if (ev != null) ev.show(v) - else v.toString + def show(implicit ev: Show[V] = defaultShow): String = + ev.show(v) } implicit val stringShow = new Show[String] { -- cgit v1.2.3 From 214258f54ebc7f8d9118aa3f84902d3b186742f7 Mon Sep 17 00:00:00 2001 From: Felix Mulder Date: Wed, 30 Nov 2016 16:07:02 +0100 Subject: Add documentation to `Show` --- library/src/dotty/Show.scala | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/library/src/dotty/Show.scala b/library/src/dotty/Show.scala index 2febda0e7..21f80c7c5 100644 --- a/library/src/dotty/Show.scala +++ b/library/src/dotty/Show.scala @@ -7,20 +7,27 @@ trait Show[-T] { def show(t: T): String } +/** Ideally show would only contain `defaultShow` and the pimped generic class, + * but since we can't change the current stdlib, we're stuck with providing + * default instances in this object + */ object Show { private[this] val defaultShow = new Show[Any] { def show(x: Any) = x.toString } + /** This class implements pimping of all types to provide a show method. + * Currently it is quite permissive, if there's no instance of `Show[T]` for + * any `T`, we default to `T#toString`. + */ implicit class ShowValue[V](val v: V) extends AnyVal { def show(implicit ev: Show[V] = defaultShow): String = ev.show(v) } implicit val stringShow = new Show[String] { - // From 2.12 spec: - // - // charEscapeSeq ::= ‘\‘ (‘b‘ | ‘t‘ | ‘n‘ | ‘f‘ | ‘r‘ | ‘"‘ | ‘'‘ | ‘\‘) + // From 2.12 spec, `charEscapeSeq`: + // ‘\‘ (‘b‘ | ‘t‘ | ‘n‘ | ‘f‘ | ‘r‘ | ‘"‘ | ‘'‘ | ‘\‘) def show(str: String) = "\"" + { val sb = new StringBuilder -- cgit v1.2.3 From 1594bb008221ad26ea8cc1a5f4dacb6f61a4d79b Mon Sep 17 00:00:00 2001 From: Felix Mulder Date: Thu, 1 Dec 2016 13:27:27 +0100 Subject: Fix repl tests --- tests/repl/import.check | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/repl/import.check b/tests/repl/import.check index 3ed0fe46c..d53906ddc 100644 --- a/tests/repl/import.check +++ b/tests/repl/import.check @@ -7,5 +7,5 @@ val res0: scala.collection.mutable.ListBuffer[Int] = ListBuffer(22) scala> buf ++= List(1, 2, 3) val res1: scala.collection.mutable.ListBuffer[Int] = ListBuffer(22, 1, 2, 3) scala> buf.toList -val res2: scala.collection.immutable.List[Int] = List(22, 1, 2, 3) +val res2: List[Int] = List(22, 1, 2, 3) scala> :quit -- cgit v1.2.3 From d63e971e2cf5f134d1a0c8bab09e7deca4e9bc43 Mon Sep 17 00:00:00 2001 From: Felix Mulder Date: Thu, 1 Dec 2016 13:38:35 +0100 Subject: Fix tasty bootstrap --- library/src/dotty/Show.scala | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/library/src/dotty/Show.scala b/library/src/dotty/Show.scala index 21f80c7c5..5b75a6ea3 100644 --- a/library/src/dotty/Show.scala +++ b/library/src/dotty/Show.scala @@ -12,7 +12,7 @@ trait Show[-T] { * default instances in this object */ object Show { - private[this] val defaultShow = new Show[Any] { + private[this] val defaultShow: Show[Any] = new Show[Any] { def show(x: Any) = x.toString } @@ -25,7 +25,7 @@ object Show { ev.show(v) } - implicit val stringShow = new Show[String] { + implicit val stringShow: Show[String] = new Show[String] { // From 2.12 spec, `charEscapeSeq`: // ‘\‘ (‘b‘ | ‘t‘ | ‘n‘ | ‘f‘ | ‘r‘ | ‘"‘ | ‘'‘ | ‘\‘) def show(str: String) = @@ -45,19 +45,19 @@ object Show { } + "\"" } - implicit val intShow = new Show[Int] { + implicit val intShow: Show[Int] = new Show[Int] { def show(i: Int) = i.toString } - implicit val floatShow = new Show[Float] { + implicit val floatShow: Show[Float] = new Show[Float] { def show(f: Float) = f + "f" } - implicit val doubleShow = new Show[Double] { + implicit val doubleShow: Show[Double] = new Show[Double] { def show(d: Double) = d.toString } - implicit val charShow = new Show[Char] { + implicit val charShow: Show[Char] = new Show[Char] { def show(c: Char) = "'" + (c match { case '\b' => "\\b" case '\t' => "\\t" @@ -70,33 +70,33 @@ object Show { }) + "'" } - implicit def showList[T](implicit st: Show[T]) = new Show[List[T]] { + implicit def showList[T](implicit st: Show[T]): Show[List[T]] = new Show[List[T]] { def show(xs: List[T]) = if (xs.isEmpty) "Nil" else "List(" + xs.map(_.show).mkString(", ") + ")" } - implicit val showNil = new Show[List[Nothing]] { + implicit val showNil: Show[List[Nothing]] = new Show[List[Nothing]] { def show(xs: List[Nothing]) = "Nil" } - implicit def showOption[T](implicit st: Show[T]) = new Show[Option[T]] { + implicit def showOption[T](implicit st: Show[T]): Show[Option[T]] = new Show[Option[T]] { def show(ot: Option[T]): String = ot match { case Some(t) => "Some("+ st.show(t) + ")" case none => "None" } } - implicit val showNone = new Show[Option[Nothing]] { + implicit val showNone: Show[Option[Nothing]] = new Show[Option[Nothing]] { def show(n: Option[Nothing]) = "None" } - implicit def showMap[K, V](implicit sk: Show[K], sv: Show[V]) = new Show[Map[K, V]] { + implicit def showMap[K,V](implicit sk: Show[K], sv: Show[V]): Show[Map[K,V]] = new Show[Map[K,V]] { def show(m: Map[K, V]) = "Map(" + m.map { case (k, v) => sk.show(k) + " -> " + sv.show(v) } .mkString (", ") + ")" } - implicit def showMapOfNothing = new Show[Map[Nothing, Nothing]] { + implicit def showMapOfNothing: Show[Map[Nothing,Nothing]] = new Show[Map[Nothing,Nothing]] { def show(m: Map[Nothing, Nothing]) = m.toString } } -- cgit v1.2.3 From 454f09e5741c72f8edd6040585eb07588bf2763e Mon Sep 17 00:00:00 2001 From: Felix Mulder Date: Thu, 1 Dec 2016 14:02:46 +0100 Subject: Fix literal type printing --- compiler/src/dotty/tools/dotc/repl/CompilingInterpreter.scala | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler/src/dotty/tools/dotc/repl/CompilingInterpreter.scala b/compiler/src/dotty/tools/dotc/repl/CompilingInterpreter.scala index e0fda8258..7fe3d815d 100644 --- a/compiler/src/dotty/tools/dotc/repl/CompilingInterpreter.scala +++ b/compiler/src/dotty/tools/dotc/repl/CompilingInterpreter.scala @@ -685,12 +685,15 @@ class CompilingInterpreter( private val ListReg = """^.*List\[(\w+)\]$""".r private val MapReg = """^.*Map\[(\w+),[ ]*(\w+)\]$""".r + private val LitReg = """^.*\((.+)\)$""".r private def resultExtractor(req: Request, varName: Name): String = { val prettyName = varName.decode val varType = string2code(req.typeOf(varName)) match { case ListReg(param) => s"List[$param]" case MapReg(k, v) => s"Map[$k, $v]" + case LitReg(lit) => lit + case x if x.lastOption == Some('$') => x.init + ".type" case x => x } val fullPath = req.fullPath(varName) -- cgit v1.2.3 From 3a11ff78bf36a126edd90adb5d21b0280ab03533 Mon Sep 17 00:00:00 2001 From: Felix Mulder Date: Thu, 1 Dec 2016 15:13:28 +0100 Subject: Use Nil.type and None.type instead of superclasses --- library/src/dotty/Show.scala | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/src/dotty/Show.scala b/library/src/dotty/Show.scala index 5b75a6ea3..2feeb29ef 100644 --- a/library/src/dotty/Show.scala +++ b/library/src/dotty/Show.scala @@ -76,8 +76,8 @@ object Show { else "List(" + xs.map(_.show).mkString(", ") + ")" } - implicit val showNil: Show[List[Nothing]] = new Show[List[Nothing]] { - def show(xs: List[Nothing]) = "Nil" + implicit val showNil: Show[Nil.type] = new Show[Nil.type] { + def show(xs: Nil.type) = "Nil" } implicit def showOption[T](implicit st: Show[T]): Show[Option[T]] = new Show[Option[T]] { @@ -87,8 +87,8 @@ object Show { } } - implicit val showNone: Show[Option[Nothing]] = new Show[Option[Nothing]] { - def show(n: Option[Nothing]) = "None" + implicit val showNone: Show[None.type] = new Show[None.type] { + def show(n: None.type) = "None" } implicit def showMap[K,V](implicit sk: Show[K], sv: Show[V]): Show[Map[K,V]] = new Show[Map[K,V]] { -- cgit v1.2.3 From 35e8fcb805e7780555cf48160f90c9da71bb1811 Mon Sep 17 00:00:00 2001 From: Felix Mulder Date: Thu, 1 Dec 2016 15:34:37 +0100 Subject: Add comment regarding prettification --- .../dotty/tools/dotc/repl/CompilingInterpreter.scala | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/compiler/src/dotty/tools/dotc/repl/CompilingInterpreter.scala b/compiler/src/dotty/tools/dotc/repl/CompilingInterpreter.scala index 7fe3d815d..14a3b4ad0 100644 --- a/compiler/src/dotty/tools/dotc/repl/CompilingInterpreter.scala +++ b/compiler/src/dotty/tools/dotc/repl/CompilingInterpreter.scala @@ -689,10 +689,27 @@ class CompilingInterpreter( private def resultExtractor(req: Request, varName: Name): String = { val prettyName = varName.decode + // FIXME: `varType` is prettified to abbreviate common types where + // appropriate, and to also prettify literal types + // + // This should be rewritten to use the actual types once we have a + // semantic representation available to the REPL val varType = string2code(req.typeOf(varName)) match { + // Extract List's paremeter from full path case ListReg(param) => s"List[$param]" + // Extract Map's paremeters from full path case MapReg(k, v) => s"Map[$k, $v]" + // Extract literal type from literal type representation. Example: + // + // ``` + // scala> val x: 42 = 42 + // val x: Int(42) = 42 + // scala> val y: "hello" = "hello" + // val y: String("hello") = "hello" + // ``` case LitReg(lit) => lit + // When the type is a singleton value like None, don't show `None$` + // instead show `None.type`. case x if x.lastOption == Some('$') => x.init + ".type" case x => x } -- cgit v1.2.3