From ccc671bed8ee57542652e5c79ef556452784b2cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reto=20Habl=C3=BCtzel?= Date: Tue, 15 Nov 2016 07:06:17 +0100 Subject: [PATCH 1/4] Add colon after method type, prefix def/val/var in REPL --- .../src/dotty/tools/dotc/printing/PlainPrinter.scala | 6 +++++- .../src/dotty/tools/dotc/repl/CompilingInterpreter.scala | 9 +++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala index 15c382bb09ad..8745cb320a07 100644 --- a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala @@ -164,10 +164,14 @@ class PlainPrinter(_ctx: Context) extends Printer { "" case tp: MethodType => def paramText(name: TermName, tp: Type) = toText(name) ~ ": " ~ toText(tp) + def typeColon(resultType: Type): Text = resultType match { + case _: TypeRef => ": " + case _ => "" // eg. methods with implicit parameters go here in first pass + } changePrec(GlobalPrec) { (if (tp.isImplicit) "(implicit " else "(") ~ Text((tp.paramNames, tp.paramTypes).zipped map paramText, ", ") ~ - ")" ~ toText(tp.resultType) + ")" ~ typeColon(tp.resultType) ~ toText(tp.resultType) } case tp: ExprType => changePrec(GlobalPrec) { "=> " ~ toText(tp.resultType) } diff --git a/compiler/src/dotty/tools/dotc/repl/CompilingInterpreter.scala b/compiler/src/dotty/tools/dotc/repl/CompilingInterpreter.scala index 5b3669d5e472..84b7199f483b 100644 --- a/compiler/src/dotty/tools/dotc/repl/CompilingInterpreter.scala +++ b/compiler/src/dotty/tools/dotc/repl/CompilingInterpreter.scala @@ -685,7 +685,12 @@ class CompilingInterpreter( val varType = string2code(req.typeOf(varName)) val fullPath = req.fullPath(varName) - s""" + "$prettyName: $varType = " + { + val varOrVal = statement match { + case v: ValDef if v.mods is Flags.Mutable => "var" + case _ => "val" + } + + s""" + "$varOrVal $prettyName: $varType = " + { | if ($fullPath.asInstanceOf[AnyRef] != null) { | (if ($fullPath.toString().contains('\\n')) "\\n" else "") + | $fullPath.toString() + "\\n" @@ -736,7 +741,7 @@ class CompilingInterpreter( override def resultExtractionCode(req: Request, code: PrintWriter): Unit = { if (!defDef.mods.is(Flags.AccessFlags)) - code.print("+\"" + string2code(defDef.name.toString) + ": " + + code.print("+\"def " + string2code(defDef.name.toString) + string2code(req.typeOf(defDef.name)) + "\\n\"") } } From b33c962f23eb6abc2708184a6a344485c24c444d Mon Sep 17 00:00:00 2001 From: Felix Mulder Date: Thu, 24 Nov 2016 15:03:54 +0100 Subject: [PATCH 2/4] Update tests fixing contributor PR --- tests/repl/import.check | 8 ++++---- tests/repl/imports.check | 4 ++-- tests/repl/onePlusOne.check | 2 +- tests/repl/patdef.check | 14 +++++++------- tests/repl/toplevelTry.check | 2 +- tests/repl/vars.check | 4 ++-- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/tests/repl/import.check b/tests/repl/import.check index ccaa521903c0..3ed0fe46c325 100644 --- a/tests/repl/import.check +++ b/tests/repl/import.check @@ -1,11 +1,11 @@ scala> import collection.mutable._ import collection.mutable._ scala> val buf = new ListBuffer[Int] -buf: scala.collection.mutable.ListBuffer[Int] = ListBuffer() +val buf: scala.collection.mutable.ListBuffer[Int] = ListBuffer() scala> buf += 22 -res0: scala.collection.mutable.ListBuffer[Int] = ListBuffer(22) +val res0: scala.collection.mutable.ListBuffer[Int] = ListBuffer(22) scala> buf ++= List(1, 2, 3) -res1: scala.collection.mutable.ListBuffer[Int] = ListBuffer(22, 1, 2, 3) +val res1: scala.collection.mutable.ListBuffer[Int] = ListBuffer(22, 1, 2, 3) scala> buf.toList -res2: scala.collection.immutable.List[Int] = List(22, 1, 2, 3) +val res2: scala.collection.immutable.List[Int] = List(22, 1, 2, 3) scala> :quit diff --git a/tests/repl/imports.check b/tests/repl/imports.check index 7e078fe001b8..5260589a92ef 100644 --- a/tests/repl/imports.check +++ b/tests/repl/imports.check @@ -1,7 +1,7 @@ scala> import scala.collection.mutable import scala.collection.mutable scala> val buf = mutable.ListBuffer[Int]() -buf: scala.collection.mutable.ListBuffer[Int] = ListBuffer() +val buf: scala.collection.mutable.ListBuffer[Int] = ListBuffer() scala> object o { val xs = List(1, 2, 3) } defined module o scala> import o._ @@ -14,7 +14,7 @@ scala> buf += xs | required: String | scala> buf ++= xs -res1: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1, 2, 3) +val res1: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1, 2, 3) scala> import util.foo -- Error: ------------------------------------------------------------ 8 |import util.foo diff --git a/tests/repl/onePlusOne.check b/tests/repl/onePlusOne.check index 9db6e6817c99..1e906069354b 100644 --- a/tests/repl/onePlusOne.check +++ b/tests/repl/onePlusOne.check @@ -1,3 +1,3 @@ scala> 1+1 -res0: Int = 2 +val res0: Int = 2 scala> :quit diff --git a/tests/repl/patdef.check b/tests/repl/patdef.check index 0cb1c6d4f74f..c92b678e003c 100644 --- a/tests/repl/patdef.check +++ b/tests/repl/patdef.check @@ -1,10 +1,10 @@ -scala> val Const,x = 0 -Const: Int = 0 -x: Int = 0 +scala> val Const, x = 0 +val Const: Int = 0 +val x: Int = 0 scala> val (Const, List(`x`, _, a), b) = (0, List(0, 1337, 1), 2) -a: Int = 1 -b: Int = 2 +val a: Int = 1 +val b: Int = 2 scala> val a@b = 0 -a: Int @unchecked = 0 -b: Int @unchecked = 0 +val a: Int @unchecked = 0 +val b: Int @unchecked = 0 scala> :quit diff --git a/tests/repl/toplevelTry.check b/tests/repl/toplevelTry.check index 9d2c87b353fe..5b9be157f975 100644 --- a/tests/repl/toplevelTry.check +++ b/tests/repl/toplevelTry.check @@ -1,3 +1,3 @@ scala> try { 0 } catch { _: Throwable => 1 } -res0: Int = 0 +val res0: Int = 0 scala> :quit diff --git a/tests/repl/vars.check b/tests/repl/vars.check index 5cebbf61c954..2e21e1a9fbb4 100644 --- a/tests/repl/vars.check +++ b/tests/repl/vars.check @@ -1,8 +1,8 @@ scala> var x = 0 -x: Int = 0 +var x: Int = 0 scala> x = x + 1 x: Int = 1 scala> x *= 2 scala> x -res2: Int = 2 +val res2: Int = 2 scala> :quit From 08e17339a36a8dddb65c35a23fa045d4af1b67b1 Mon Sep 17 00:00:00 2001 From: Felix Mulder Date: Thu, 24 Nov 2016 15:04:18 +0100 Subject: [PATCH 3/4] Fix defs not being printed correctly --- .../dotc/repl/CompilingInterpreter.scala | 25 ++++++++++++++++--- tests/repl/def.check | 9 +++++++ 2 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 tests/repl/def.check diff --git a/compiler/src/dotty/tools/dotc/repl/CompilingInterpreter.scala b/compiler/src/dotty/tools/dotc/repl/CompilingInterpreter.scala index 84b7199f483b..00f24845e7ba 100644 --- a/compiler/src/dotty/tools/dotc/repl/CompilingInterpreter.scala +++ b/compiler/src/dotty/tools/dotc/repl/CompilingInterpreter.scala @@ -740,9 +740,28 @@ class CompilingInterpreter( override def defNames = boundNames override def resultExtractionCode(req: Request, code: PrintWriter): Unit = { - if (!defDef.mods.is(Flags.AccessFlags)) - code.print("+\"def " + string2code(defDef.name.toString) + - string2code(req.typeOf(defDef.name)) + "\\n\"") + /** TODO: This is the result of the state of the REPL - this would be + * entirely unnecessary with a better structure where we could just + * use the type printer + * + * @see `def findTypes` for an explanation of what should be done + */ + if (!defDef.mods.is(Flags.AccessFlags)) { + val tpt = defDef.tpt match { + // ascribed TypeExpr e.g: `def foo: Int = 5` + case Ident(tpt) if defDef.vparamss.isEmpty => + ": " + tpt.show + // inferred TypeExpr e.g: `def foo = 5` + case tpt if defDef.vparamss.isEmpty => + ": " + req.typeOf(defDef.name) + // Inferred or ascribed MethodType with parameter list + case _ => + req.typeOf(defDef.name) + } + code.print { + "+\"def " + string2code(defDef.name.toString) + tpt + "\\n\"" + } + } } } diff --git a/tests/repl/def.check b/tests/repl/def.check new file mode 100644 index 000000000000..498ecb282fad --- /dev/null +++ b/tests/repl/def.check @@ -0,0 +1,9 @@ +scala> def foo = 5 +def foo: Int +scala> def bar: String = "1" +def bar: String +scala> def baz() = 2 +def baz(): Int +scala> def qux(): Int = 2 +def qux(): Int +scala> :quit From c52ffd7c9cb189f168470b9004cfb2dd554e3cc8 Mon Sep 17 00:00:00 2001 From: Felix Mulder Date: Thu, 24 Nov 2016 15:36:20 +0100 Subject: [PATCH 4/4] Make `findTypes` take the `resultType` of `MethodType` This is done so that we can use show for the entire method except for the ascribed type added by the compiler on success. --- .../tools/dotc/printing/PlainPrinter.scala | 6 +----- .../dotc/repl/CompilingInterpreter.scala | 19 ++++++++++++------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala index 8745cb320a07..15c382bb09ad 100644 --- a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala @@ -164,14 +164,10 @@ class PlainPrinter(_ctx: Context) extends Printer { "" case tp: MethodType => def paramText(name: TermName, tp: Type) = toText(name) ~ ": " ~ toText(tp) - def typeColon(resultType: Type): Text = resultType match { - case _: TypeRef => ": " - case _ => "" // eg. methods with implicit parameters go here in first pass - } changePrec(GlobalPrec) { (if (tp.isImplicit) "(implicit " else "(") ~ Text((tp.paramNames, tp.paramTypes).zipped map paramText, ", ") ~ - ")" ~ typeColon(tp.resultType) ~ toText(tp.resultType) + ")" ~ toText(tp.resultType) } case tp: ExprType => changePrec(GlobalPrec) { "=> " ~ toText(tp.resultType) } diff --git a/compiler/src/dotty/tools/dotc/repl/CompilingInterpreter.scala b/compiler/src/dotty/tools/dotc/repl/CompilingInterpreter.scala index 00f24845e7ba..f269fef64211 100644 --- a/compiler/src/dotty/tools/dotc/repl/CompilingInterpreter.scala +++ b/compiler/src/dotty/tools/dotc/repl/CompilingInterpreter.scala @@ -443,7 +443,10 @@ class CompilingInterpreter( } // the types are all =>T; remove the => - val cleanedType = rawType.widenExpr + val cleanedType = rawType.widenExpr match { + case tp: MethodType => tp.resultType + case tp => tp + } map + (name -> ctx.atPhase(ctx.typerPhase.next) { implicit ctx => @@ -747,19 +750,21 @@ class CompilingInterpreter( * @see `def findTypes` for an explanation of what should be done */ if (!defDef.mods.is(Flags.AccessFlags)) { + // Take the DefDef and remove the `rhs` and ascribed type `tpt` + val copy = ast.untpd.cpy.DefDef(defDef)( + rhs = EmptyTree, + tpt = TypeTree + ) + val tpt = defDef.tpt match { // ascribed TypeExpr e.g: `def foo: Int = 5` case Ident(tpt) if defDef.vparamss.isEmpty => ": " + tpt.show - // inferred TypeExpr e.g: `def foo = 5` - case tpt if defDef.vparamss.isEmpty => + case tpt => ": " + req.typeOf(defDef.name) - // Inferred or ascribed MethodType with parameter list - case _ => - req.typeOf(defDef.name) } code.print { - "+\"def " + string2code(defDef.name.toString) + tpt + "\\n\"" + "+\"" + string2code(copy.show) + tpt + "\\n\"" } } }