From fe20b9064fca765a38345a09aa484bfb537aa3c0 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 14 Nov 2016 11:58:59 +0100 Subject: Pickle and unpickle type trees Lots of other changes to make positions work out everywhere. One important change is that now trees can be shared, just as types can. This change improves memory requirements (a bit) and also makes positions in shared trees more robust. --- src/dotty/tools/dotc/printing/RefinedPrinter.scala | 55 ++++++++++++++++++---- 1 file changed, 45 insertions(+), 10 deletions(-) (limited to 'src/dotty/tools/dotc/printing/RefinedPrinter.scala') diff --git a/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/src/dotty/tools/dotc/printing/RefinedPrinter.scala index 39a21b17b..4818c6eee 100644 --- a/src/dotty/tools/dotc/printing/RefinedPrinter.scala +++ b/src/dotty/tools/dotc/printing/RefinedPrinter.scala @@ -21,6 +21,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { /** A stack of enclosing DefDef, TypeDef, or ClassDef, or ModuleDefs nodes */ private var enclosingDef: untpd.Tree = untpd.EmptyTree private var myCtx: Context = _ctx + private var printPos = ctx.settings.Yprintpos.value override protected[this] implicit def ctx: Context = myCtx def withEnclosingDef(enclDef: Tree[_ >: Untyped])(op: => Text): Text = { @@ -35,6 +36,18 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { } } + def inPattern(op: => Text): Text = { + val savedCtx = myCtx + myCtx = ctx.addMode(Mode.Pattern) + try op finally myCtx = savedCtx + } + + def withoutPos(op: => Text): Text = { + val savedPrintPos = printPos + printPos = false + try op finally printPos = savedPrintPos + } + private def enclDefIsClass = enclosingDef match { case owner: TypeDef[_] => owner.isClassDef case owner: untpd.ModuleDef => true @@ -134,6 +147,8 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { return toTextParents(tp.parentsWithArgs) ~ "{...}" case JavaArrayType(elemtp) => return toText(elemtp) ~ "[]" + case tp: AnnotatedType if homogenizedView => + withoutPos(super.toText(tp)) case tp: SelectionProto => return "?{ " ~ toText(tp.name) ~ (" " provided !tp.name.decode.last.isLetterOrDigit) ~ ": " ~ toText(tp.memberProto) ~ " }" @@ -249,7 +264,8 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { } def nameIdText(tree: untpd.NameTree): Text = - toText(tree.name) ~ idText(tree) + if (tree.hasType && tree.symbol.exists) nameString(tree.symbol) + else toText(tree.name) ~ idText(tree) def toTextTemplate(impl: Template, ofNew: Boolean = false): Text = { val Template(constr @ DefDef(_, tparams, vparamss, _, _), parents, self, _) = impl @@ -284,7 +300,8 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { case tp: NamedType if name != nme.WILDCARD => val pre = if (tp.symbol is JavaStatic) tp.prefix.widen else tp.prefix toTextPrefix(pre) ~ selectionString(tp) - case _ => toText(name) + case _ => + toText(name) } case tree @ Select(qual, name) => if (qual.isType) toTextLocal(qual) ~ "#" ~ toText(name) @@ -337,7 +354,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { if (sel.isEmpty) blockText(cases) else changePrec(GlobalPrec) { toText(sel) ~ " match " ~ blockText(cases) } case CaseDef(pat, guard, body) => - "case " ~ toText(pat) ~ optText(guard)(" if " ~ _) ~ " => " ~ caseBlockText(body) + "case " ~ inPattern(toText(pat)) ~ optText(guard)(" if " ~ _) ~ " => " ~ caseBlockText(body) case Return(expr, from) => changePrec(GlobalPrec) { "return" ~ optText(expr)(" " ~ _) } case Try(expr, cases, finalizer) => @@ -519,22 +536,40 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { case _ => tree.fallbackToText(this) } + var txt = toTextCore(tree) + + def suppressTypes = + tree.isType || tree.isDef || // don't print types of types or defs + homogenizedView && ctx.mode.is(Mode.Pattern) + // When comparing pickled info, disregard types of patterns. + // The reason is that GADT matching can rewrite types of pattern trees + // without changing the trees themselves. (see Typer.typedCase.indexPatterns.transform). + // But then pickling and unpickling the original trees will yield trees + // with the original types before they are rewritten, which causes a discrepancy. + + def suppressPositions = tree match { + case _: WithoutTypeOrPos[_] | _: TypeTree => true // TypeTrees never have an interesting position + case _ => false + } + if (ctx.settings.printtypes.value && tree.hasType) { - val tp = tree.typeOpt match { + // add type to term nodes; replace type nodes with their types unless -Yprintpos is also set. + def tp = tree.typeOpt match { case tp: TermRef if tree.isInstanceOf[RefTree] && !tp.denot.isOverloaded => tp.underlying case tp => tp } - if (tree.isType) txt = toText(tp) - else if (!tree.isDef) txt = ("<" ~ txt ~ ":" ~ toText(tp) ~ ">").close + if (!suppressTypes) + txt = ("<" ~ txt ~ ":" ~ toText(tp) ~ ">").close + else if (tree.isType && !homogenizedView) + txt = toText(tp) } - else if (homogenizedView && tree.isType) - txt = toText(tree.typeOpt) - if (ctx.settings.Yprintpos.value && !tree.isInstanceOf[WithoutTypeOrPos[_]]) { + if (printPos && !suppressPositions) { + // add positions val pos = if (homogenizedView && !tree.isInstanceOf[MemberDef]) tree.pos.toSynthetic else tree.pos - val clsStr = "" // DEBUG: if (tree.isType) tree.getClass.toString else "" + val clsStr = ""//if (tree.isType) tree.getClass.toString else "" txt = (txt ~ "@" ~ pos.toString ~ clsStr).close } tree match { -- cgit v1.2.3