aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/printing
diff options
context:
space:
mode:
authorodersky <odersky@gmail.com>2016-07-15 13:11:52 +0200
committerGitHub <noreply@github.com>2016-07-15 13:11:52 +0200
commit409c6c30c8496529aace68967acccf88850145da (patch)
tree56fd30bbb5d108b895982da72943e649a58fbd40 /src/dotty/tools/dotc/printing
parent1c02c56213cf22010c0aef1dc1446300fe8005fe (diff)
parent894c9fbf247765041fc32788c78b85f1b2b2a191 (diff)
downloaddotty-409c6c30c8496529aace68967acccf88850145da.tar.gz
dotty-409c6c30c8496529aace68967acccf88850145da.tar.bz2
dotty-409c6c30c8496529aace68967acccf88850145da.zip
Merge pull request #1343 from dotty-staging/change-hk-direct2
Direct representation of higher-kinded types
Diffstat (limited to 'src/dotty/tools/dotc/printing')
-rw-r--r--src/dotty/tools/dotc/printing/PlainPrinter.scala61
-rw-r--r--src/dotty/tools/dotc/printing/RefinedPrinter.scala74
2 files changed, 68 insertions, 67 deletions
diff --git a/src/dotty/tools/dotc/printing/PlainPrinter.scala b/src/dotty/tools/dotc/printing/PlainPrinter.scala
index 1e2ba0b4d..acf4514ea 100644
--- a/src/dotty/tools/dotc/printing/PlainPrinter.scala
+++ b/src/dotty/tools/dotc/printing/PlainPrinter.scala
@@ -6,6 +6,7 @@ import Texts._, Types._, Flags._, Names._, Symbols._, NameOps._, Constants._, De
import Contexts.Context, Scopes.Scope, Denotations.Denotation, Annotations.Annotation
import StdNames.{nme, tpnme}
import ast.Trees._, ast._
+import config.Config
import java.lang.Integer.toOctalString
import config.Config.summarizeDepth
import scala.annotation.switch
@@ -13,6 +14,8 @@ import scala.annotation.switch
class PlainPrinter(_ctx: Context) extends Printer {
protected[this] implicit def ctx: Context = _ctx.addMode(Mode.Printing)
+ private var openRecs: List[RecType] = Nil
+
protected def maxToTextRecursions = 100
protected final def controlled(op: => Text): Text =
@@ -48,9 +51,8 @@ class PlainPrinter(_ctx: Context) extends Printer {
homogenize(tp1) & homogenize(tp2)
case OrType(tp1, tp2) =>
homogenize(tp1) | homogenize(tp2)
- case tp @ TypeRef(_, tpnme.hkApply) =>
- val tp1 = tp.reduceProjection
- if (tp1 eq tp) tp else homogenize(tp1)
+ case tp: SkolemType =>
+ homogenize(tp.info)
case tp: LazyRef =>
homogenize(tp.ref)
case _ =>
@@ -58,6 +60,8 @@ class PlainPrinter(_ctx: Context) extends Printer {
}
else tp
+ private def selfRecName(n: Int) = s"z$n"
+
/** Render elements alternating with `sep` string */
protected def toText(elems: Traversable[Showable], sep: String) =
Text(elems map (_ toText this), sep)
@@ -105,12 +109,36 @@ class PlainPrinter(_ctx: Context) extends Printer {
protected def toTextRefinement(rt: RefinedType) =
(refinementNameString(rt) ~ toTextRHS(rt.refinedInfo)).close
+ protected def argText(arg: Type): Text = arg match {
+ case arg: TypeBounds => "_" ~ toTextGlobal(arg)
+ case _ => toTextGlobal(arg)
+ }
+
+ /** The text for a TypeLambda
+ *
+ * [v_1 p_1: B_1, ..., v_n p_n: B_n] -> T
+ *
+ * where
+ * @param paramNames = p_1, ..., p_n
+ * @param variances = v_1, ..., v_n
+ * @param argBoundss = B_1, ..., B_n
+ * @param body = T
+ */
+ protected def typeLambdaText(paramNames: List[String], variances: List[Int], argBoundss: List[TypeBounds], body: Type): Text = {
+ def lambdaParamText(variance: Int, name: String, bounds: TypeBounds): Text =
+ varianceString(variance) ~ name ~ toText(bounds)
+ changePrec(GlobalPrec) {
+ "[" ~ Text((variances, paramNames, argBoundss).zipped.map(lambdaParamText), ", ") ~
+ "] -> " ~ toTextGlobal(body)
+ }
+ }
+
/** The longest sequence of refinement types, starting at given type
* and following parents.
*/
private def refinementChain(tp: Type): List[Type] =
tp :: (tp match {
- case RefinedType(parent, _) => refinementChain(parent.stripTypeVar)
+ case tp: RefinedType => refinementChain(tp.parent.stripTypeVar)
case _ => Nil
})
@@ -130,6 +158,12 @@ class PlainPrinter(_ctx: Context) extends Printer {
val parent :: (refined: List[RefinedType @unchecked]) =
refinementChain(tp).reverse
toTextLocal(parent) ~ "{" ~ Text(refined map toTextRefinement, "; ").close ~ "}"
+ case tp: RecType =>
+ try {
+ openRecs = tp :: openRecs
+ "{" ~ selfRecName(openRecs.length) ~ " => " ~ toTextGlobal(tp.parent) ~ "}"
+ }
+ finally openRecs = openRecs.tail
case AndType(tp1, tp2) =>
changePrec(AndPrec) { toText(tp1) ~ " & " ~ toText(tp2) }
case OrType(tp1, tp2) =>
@@ -151,6 +185,8 @@ class PlainPrinter(_ctx: Context) extends Printer {
}
case tp: ExprType =>
changePrec(GlobalPrec) { "=> " ~ toText(tp.resultType) }
+ case tp: TypeLambda =>
+ typeLambdaText(tp.paramNames.map(_.toString), tp.variances, tp.paramBounds, tp.resultType)
case tp: PolyType =>
def paramText(name: TypeName, bounds: TypeBounds) =
toText(polyParamName(name)) ~ polyHash(tp) ~ toText(bounds)
@@ -163,6 +199,8 @@ class PlainPrinter(_ctx: Context) extends Printer {
toText(polyParamName(pt.paramNames(n))) ~ polyHash(pt)
case AnnotatedType(tpe, annot) =>
toTextLocal(tpe) ~ " " ~ toText(annot)
+ case HKApply(tycon, args) =>
+ toTextLocal(tycon) ~ "[" ~ Text(args.map(argText), ", ") ~ "]"
case tp: TypeVar =>
if (tp.isInstantiated)
toTextLocal(tp.instanceOpt) ~ "'" // debug for now, so that we can see where the TypeVars are.
@@ -175,7 +213,7 @@ class PlainPrinter(_ctx: Context) extends Printer {
else toText(tp.origin)
}
case tp: LazyRef =>
- "LazyRef(" ~ toTextGlobal(tp.ref) ~ ")"
+ "LazyRef(" ~ toTextGlobal(tp.ref) ~ ")" // TODO: only print this during debug mode?
case _ =>
tp.fallbackToText(this)
}
@@ -189,8 +227,8 @@ class PlainPrinter(_ctx: Context) extends Printer {
protected def simpleNameString(sym: Symbol): String = nameString(sym.name)
/** If -uniqid is set, the hashcode of the polytype, after a # */
- protected def polyHash(pt: PolyType): Text =
- "#" + pt.hashCode provided ctx.settings.uniqid.value
+ protected def polyHash(pt: GenericType): Text =
+ if (ctx.settings.uniqid.value) "#" + pt.hashCode else ""
/** If -uniqid is set, the unique id of symbol, after a # */
protected def idString(sym: Symbol): String =
@@ -232,11 +270,12 @@ class PlainPrinter(_ctx: Context) extends Printer {
toText(value)
case MethodParam(mt, idx) =>
nameString(mt.paramNames(idx))
- case tp: RefinedThis =>
- s"${nameString(tp.binder.typeSymbol)}{...}.this"
+ case tp: RecThis =>
+ val idx = openRecs.reverse.indexOf(tp.binder)
+ if (idx >= 0) selfRecName(idx + 1)
+ else "{...}.this" // TODO move underlying type to an addendum, e.g. ... z3 ... where z3: ...
case tp: SkolemType =>
- if (homogenizedView) toText(tp.info)
- else "<unknown instance of type " ~ toTextGlobal(tp.info) ~ ">"
+ if (homogenizedView) toText(tp.info) else tp.repr
}
}
diff --git a/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/src/dotty/tools/dotc/printing/RefinedPrinter.scala
index 614a274b4..ca62827af 100644
--- a/src/dotty/tools/dotc/printing/RefinedPrinter.scala
+++ b/src/dotty/tools/dotc/printing/RefinedPrinter.scala
@@ -12,6 +12,7 @@ import typer.ProtoTypes.{SelectionProto, ViewProto, FunProto, IgnoredProto, dumm
import Trees._
import TypeApplications._
import Decorators._
+import config.Config
import scala.annotation.switch
import language.implicitConversions
@@ -94,10 +95,6 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
}
override def toText(tp: Type): Text = controlled {
- def argText(arg: Type): Text = arg match {
- case arg: TypeBounds => "_" ~ toTextGlobal(arg)
- case _ => toTextGlobal(arg)
- }
def toTextTuple(args: List[Type]): Text =
"(" ~ toTextGlobal(args, ", ") ~ ")"
def toTextFunction(args: List[Type]): Text =
@@ -116,35 +113,6 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
if (defn.isFunctionClass(cls)) return toTextFunction(args)
if (defn.isTupleClass(cls)) return toTextTuple(args)
return (toTextLocal(tycon) ~ "[" ~ Text(args map argText, ", ") ~ "]").close
- case tp @ TypeLambda(variances, argBoundss, body) =>
- val prefix = ((('X' - 'A') + lambdaNestingLevel) % 26 + 'A').toChar
- val paramNames = variances.indices.toList.map(prefix.toString + _)
- val instantiate = new TypeMap {
- def contains(tp1: Type, tp2: Type): Boolean =
- tp1.eq(tp2) || {
- tp1.stripTypeVar match {
- case RefinedType(parent, _) => contains(parent, tp2)
- case _ => false
- }
- }
- def apply(t: Type): Type = t match {
- case TypeRef(RefinedThis(rt), name) if name.isHkArgName && contains(tp, rt) =>
- // Make up a name that prints as "Xi". Need to be careful we do not
- // accidentally unique-hash to something else. That's why we can't
- // use prefix = NoPrefix or a WithFixedSym instance.
- TypeRef.withSymAndName(
- defn.EmptyPackageClass.thisType, defn.AnyClass,
- paramNames(name.hkArgIndex).toTypeName)
- case _ =>
- mapOver(t)
- }
- }
- val instArgs = argBoundss.map(instantiate).asInstanceOf[List[TypeBounds]]
- val instBody = instantiate(body).dropAlias
- lambdaNestingLevel += 1
- try
- return typeLambdaText(paramNames, variances, instArgs, instBody)
- finally lambdaNestingLevel -=1
case tp: TypeRef =>
val hideType = tp.symbol is AliasPreferred
if (hideType && !ctx.phase.erasedTypes && !tp.symbol.isCompleting) {
@@ -184,30 +152,11 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
def blockText[T >: Untyped](trees: List[Tree[T]]): Text =
"{" ~ toText(trees, "\n") ~ "}"
- /** The text for a TypeLambda
- *
- * [v_1 p_1: B_1, ..., v_n p_n: B_n] -> T
- *
- * where
- * @param paramNames = p_1, ..., p_n
- * @param variances = v_1, ..., v_n
- * @param argBoundss = B_1, ..., B_n
- * @param body = T
- */
- def typeLambdaText(paramNames: List[String], variances: List[Int], argBoundss: List[TypeBounds], body: Type): Text = {
- def lambdaParamText(variance: Int, name: String, bounds: TypeBounds): Text =
- varianceString(variance) ~ name ~ toText(bounds)
- changePrec(GlobalPrec) {
- "[" ~ Text((variances, paramNames, argBoundss).zipped.map(lambdaParamText), ", ") ~
- "] -> " ~ toTextGlobal(body)
- }
- }
-
override def toText[T >: Untyped](tree: Tree[T]): Text = controlled {
import untpd.{modsDeco => _, _}
- /** Print modifiers form symbols if tree has type, overriding the untpd behavior. */
+ /** Print modifiers from symbols if tree has type, overriding the untpd behavior. */
implicit def modsDeco(mdef: untpd.MemberDef)(implicit ctx: Context): untpd.ModsDeco =
tpd.modsDeco(mdef.asInstanceOf[tpd.MemberDef]).asInstanceOf[untpd.ModsDeco]
@@ -264,6 +213,11 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
Text(mods.annotations.map(annotText), " ") ~~ flagsText ~~ (kw provided !suppressKw)
}
+ def varianceText(mods: untpd.Modifiers) =
+ if (mods is Covariant) "+"
+ else if (mods is Contravariant) "-"
+ else ""
+
def argText(arg: Tree): Text = arg match {
case arg: TypeBoundsTree => "_" ~ toTextGlobal(arg)
case arg: TypeTree =>
@@ -308,7 +262,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
}
def toTextPackageId(pid: Tree): Text =
- if (homogenizedView) toTextLocal(pid.tpe)
+ if (homogenizedView && pid.hasType) toTextLocal(pid.tpe)
else toTextLocal(pid)
var txt: Text = tree match {
@@ -345,7 +299,11 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
"new " ~ {
tpt match {
case tpt: Template => toTextTemplate(tpt, ofNew = true)
- case _ => toTextLocal(tpt.typeOpt.underlyingClassRef(refinementOK = false))
+ case _ =>
+ if (tpt.hasType)
+ toTextLocal(tpt.typeOpt.underlyingClassRef(refinementOK = false))
+ else
+ toTextLocal(tpt)
}
}
case Pair(l, r) =>
@@ -398,6 +356,10 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
toTextLocal(tpt) ~ " " ~ blockText(refines)
case AppliedTypeTree(tpt, args) =>
toTextLocal(tpt) ~ "[" ~ Text(args map argText, ", ") ~ "]"
+ case TypeLambdaTree(tparams, body) =>
+ changePrec(GlobalPrec) {
+ tparamsText(tparams) ~ " -> " ~ toText(body)
+ }
case ByNameTypeTree(tpt) =>
"=> " ~ toTextLocal(tpt)
case TypeBoundsTree(lo, hi) =>
@@ -431,7 +393,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
case tree @ TypeDef(name, rhs) =>
def typeDefText(rhsText: Text) =
dclTextOr {
- modText(tree.mods, "type") ~~ nameIdText(tree) ~
+ modText(tree.mods, "type") ~~ (varianceText(tree.mods) ~ nameIdText(tree)) ~
withEnclosingDef(tree) {
val rhsText1 = if (tree.hasType) toText(tree.symbol.info) else rhsText
tparamsText(tree.tparams) ~ rhsText1