diff options
author | Martin Odersky <odersky@gmail.com> | 2014-07-03 19:02:26 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2014-07-17 11:02:00 +0200 |
commit | db88bf06958e33ae415ca227808ab1f3e48fed7f (patch) | |
tree | def81047ef7f2bdf930e2a5561cfcd2403a61912 /src/dotty | |
parent | efe4f7e43652a303d16a5253f84316e547f45cca (diff) | |
download | dotty-db88bf06958e33ae415ca227808ab1f3e48fed7f.tar.gz dotty-db88bf06958e33ae415ca227808ab1f3e48fed7f.tar.bz2 dotty-db88bf06958e33ae415ca227808ab1f3e48fed7f.zip |
Various cleanups and utility additions
- Some new functionality in tpd and in Symbols.
- Added `sm` interpolator to print nicely.
- Make use of nestedMap where possible.
- Add IdentityDenotTransformer as a convencience class
Diffstat (limited to 'src/dotty')
-rw-r--r-- | src/dotty/tools/dotc/ast/tpd.scala | 14 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Decorators.scala | 36 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/DenotTransformers.scala | 8 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/SymDenotations.scala | 38 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/SymbolLoaders.scala | 6 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Symbols.scala | 6 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/pickling/ClassfileParser.scala | 16 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/pickling/UnPickler.scala | 12 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/SuperAccessors.scala | 17 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/ErrorReporting.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/ImportInfo.scala | 2 |
11 files changed, 116 insertions, 41 deletions
diff --git a/src/dotty/tools/dotc/ast/tpd.scala b/src/dotty/tools/dotc/ast/tpd.scala index 84e1118f9..f0151e1d3 100644 --- a/src/dotty/tools/dotc/ast/tpd.scala +++ b/src/dotty/tools/dotc/ast/tpd.scala @@ -204,11 +204,11 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { } val (vparamss, rtp) = valueParamss(mtp) val targs = tparams map (_.typeRef) - val argss = vparamss map (_ map (vparam => Ident(vparam.termRef))) + val argss = vparamss.nestedMap(vparam => Ident(vparam.termRef)) ta.assignType( untpd.DefDef( Modifiers(sym), sym.name, tparams map TypeDef, - vparamss map (_ map (ValDef(_))), TypeTree(rtp), rhsFn(targs)(argss)), sym) + vparamss.nestedMap(ValDef(_)), TypeTree(rtp), rhsFn(targs)(argss)), sym) } def TypeDef(sym: TypeSymbol)(implicit ctx: Context): TypeDef = @@ -384,6 +384,14 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { def changeOwner(from: Symbol, to: Symbol)(implicit ctx: Context): ThisTree = new TreeTypeMap(ownerMap = (sym => if (sym == from) to else sym)).apply(tree) + def appliedToArg(arg: Tree)(implicit ctx: Context): Tree = appliedToArgs(arg :: Nil) + + def appliedToArgs(args: List[Tree])(implicit ctx: Context): Tree = + if (args.isEmpty) tree else Apply(tree, args) + + def appliedToArgss(argss: List[List[Tree]])(implicit ctx: Context): Tree = + ((tree: Tree) /: argss)(Apply(_, _)) + def appliedToTypes(targs: List[Type])(implicit ctx: Context): Tree = appliedToTypeTrees(targs map (TypeTree(_))) @@ -395,7 +403,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { def tpes: List[Type] = xs map (_.tpe) } - class TreeTypeMap(val typeMap: TypeMap = IdentityTypeMap, val ownerMap: Symbol => Symbol = identity _)(implicit ctx: Context) extends TreeMap { + class TreeTypeMap(val typeMap: Type => Type = IdentityTypeMap, val ownerMap: Symbol => Symbol = identity _)(implicit ctx: Context) extends TreeMap { override def transform(tree: tpd.Tree)(implicit ctx: Context): tpd.Tree = super.transform { tree.withType(typeMap(tree.tpe)) match { case bind: tpd.Bind => diff --git a/src/dotty/tools/dotc/core/Decorators.scala b/src/dotty/tools/dotc/core/Decorators.scala index 155ea87e0..cd7b46896 100644 --- a/src/dotty/tools/dotc/core/Decorators.scala +++ b/src/dotty/tools/dotc/core/Decorators.scala @@ -143,7 +143,7 @@ object Decorators { * 2) Lists can be formatted using the desired separator between two `%` signs, * eg `i"myList = (${myList}%, %)"` */ - implicit class InfoString(val sc: StringContext) extends AnyVal { + implicit class StringInterpolators(val sc: StringContext) extends AnyVal { def i(args: Any*)(implicit ctx: Context): String = { @@ -166,7 +166,39 @@ object Decorators { val (args1, suffixes1) = (args, suffixes).zipped.map(treatArg(_, _)).unzip new StringContext(prefix :: suffixes1.toList: _*).s(args1: _*) } - } + /** Lifted from scala.reflect.internal.util + * A safe combination of [[scala.collection.immutable.StringLike#stripMargin]] + * and [[scala.StringContext#raw]]. + * + * The margin of each line is defined by whitespace leading up to a '|' character. + * This margin is stripped '''before''' the arguments are interpolated into to string. + * + * String escape sequences are '''not''' processed; this interpolater is designed to + * be used with triple quoted Strings. + * + * {{{ + * scala> val foo = "f|o|o" + * foo: String = f|o|o + * scala> sm"""|${foo} + * |""" + * res0: String = + * "f|o|o + * " + * }}} + */ + final def sm(args: Any*): String = { + def isLineBreak(c: Char) = c == '\n' || c == '\f' // compatible with StringLike#isLineBreak + def stripTrailingPart(s: String) = { + val (pre, post) = s.span(c => !isLineBreak(c)) + pre + post.stripMargin + } + val stripped: List[String] = sc.parts.toList match { + case head :: tail => head.stripMargin :: (tail map stripTrailingPart) + case Nil => Nil + } + new StringContext(stripped: _*).raw(args: _*) + } + } } diff --git a/src/dotty/tools/dotc/core/DenotTransformers.scala b/src/dotty/tools/dotc/core/DenotTransformers.scala index 6daa028fc..e052a07ea 100644 --- a/src/dotty/tools/dotc/core/DenotTransformers.scala +++ b/src/dotty/tools/dotc/core/DenotTransformers.scala @@ -46,4 +46,12 @@ object DenotTransformers { } } } + + /** A `DenotTransformer` trait that has the identity as its `transform` method. + * You might want to inherit from this trait so that new denotations can be + * installed using `installAfter` and `enteredAfter` at the end of the phase. + */ + trait IdentityDenotTransformer extends DenotTransformer { + def transform(ref: SingleDenotation)(implicit ctx: Context): SingleDenotation = ref + } } diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index 643237038..ba57909a0 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -212,6 +212,14 @@ object SymDenotations { final def addAnnotation(annot: Annotation): Unit = annotations = annot :: myAnnotations + /** Remove annotation with given class from this denotation */ + final def removeAnnotation(cls: Symbol)(implicit ctx: Context): Unit = + annotations = myAnnotations.filterNot(_ matches cls) + + /** Copy all annotations from given symbol by adding them to this symbol */ + final def addAnnotations(from: Symbol)(implicit ctx: Context): Unit = + from.annotations.foreach(addAnnotation) + @tailrec private def dropOtherAnnotations(anns: List[Annotation], cls: Symbol)(implicit ctx: Context): List[Annotation] = anns match { case ann :: rest => if (ann matches cls) anns else dropOtherAnnotations(rest, cls) @@ -861,6 +869,22 @@ object SymDenotations { /** Install this denotation as the result of the given denotation transformer. */ override def installAfter(phase: DenotTransformer)(implicit ctx: Context): Unit = super.installAfter(phase) + + /** Remove private modifier from symbol's definition. If this symbol + * is not a constructor nor a static module, rename it by expanding its name to avoid name clashes + * @param base the fully qualified name of this class will be appended if name expansion is needed + */ + final def makeNotPrivateAfter(base: Symbol, phase: DenotTransformer)(implicit ctx: Context): Unit = { + if (this.is(Private)) { + val newName = + if (this.is(Module) && isStatic || isClassConstructor) name + else { + if (this.is(Module)) moduleClass.makeNotPrivateAfter(base, phase) + name.expandedName(base) + } + copySymDenotation(name = newName, initFlags = flags &~ Private).installAfter(phase) + } + } } /** The contents of a class definition during a period @@ -1311,9 +1335,17 @@ object SymDenotations { decls.denotsNamed(cname).first.symbol } - def underlyingOfValueClass: Type = ??? - - def valueClassUnbox: Symbol = ??? + /** The member that of a derived value class that unboxes it. */ + def valueClassUnbox(implicit ctx: Context): Symbol = + // (info.decl(nme.unbox)).orElse(...) uncomment once we accept unbox methods + classInfo.decls + .find(d => d.isTerm && d.symbol.is(ParamAccessor)) + .map(_.symbol) + .getOrElse(NoSymbol) + + /** The unboxed type that underlies a derived value class */ + def underlyingOfValueClass(implicit ctx: Context): Type = + valueClassUnbox.info.resultType /** If this class has the same `decls` scope reference in `phase` and * `phase.next`, install a new denotation with a cloned scope in `phase.next`. diff --git a/src/dotty/tools/dotc/core/SymbolLoaders.scala b/src/dotty/tools/dotc/core/SymbolLoaders.scala index bebad60cc..886c728b7 100644 --- a/src/dotty/tools/dotc/core/SymbolLoaders.scala +++ b/src/dotty/tools/dotc/core/SymbolLoaders.scala @@ -12,7 +12,7 @@ import scala.compat.Platform.currentTime import dotty.tools.io.{ ClassPath, AbstractFile } import Contexts._, Symbols._, Flags._, SymDenotations._, Types._, Scopes._, util.Positions._, Names._ import StdNames._, NameOps._ -import Decorators.StringDecorator +import Decorators.{StringDecorator, StringInterpolators} import pickling.ClassfileParser object SymbolLoaders { @@ -69,8 +69,8 @@ class SymbolLoaders { // require yjp.jar at runtime. See SI-2089. if (ctx.settings.termConflict.isDefault) throw new TypeError( - s"""$owner contains object and package with same name: $pname - |one of them needs to be removed from classpath""".stripMargin) + sm"""$owner contains object and package with same name: $pname + |one of them needs to be removed from classpath""") else if (ctx.settings.termConflict.value == "package") { ctx.warning( s"Resolving package/object name conflict in favor of package ${preExisting.fullName}. The object will be inaccessible.") diff --git a/src/dotty/tools/dotc/core/Symbols.scala b/src/dotty/tools/dotc/core/Symbols.scala index cfd5bdf23..6421018e5 100644 --- a/src/dotty/tools/dotc/core/Symbols.scala +++ b/src/dotty/tools/dotc/core/Symbols.scala @@ -261,16 +261,14 @@ trait Symbols { this: Context => newSymbol(owner, name, SyntheticArtifact, if (name.isTypeName) TypeAlias(ErrorType) else ErrorType) - type OwnerMap = Symbol => Symbol - /** Map given symbols, subjecting all types to given type map and owner map. * Cross symbol references are brought over from originals to copies. * Do not copy any symbols if all attributes of all symbols stay the same. */ def mapSymbols( originals: List[Symbol], - typeMap: TypeMap = IdentityTypeMap, - ownerMap: OwnerMap = identity) + typeMap: Type => Type = IdentityTypeMap, + ownerMap: Symbol => Symbol = identity) = if (originals forall (sym => (typeMap(sym.info) eq sym.info) && (ownerMap(sym.owner) eq sym.owner))) diff --git a/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala b/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala index 0f0747597..f2b81072a 100644 --- a/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala +++ b/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala @@ -48,8 +48,8 @@ class ClassfileParser( case e: RuntimeException => if (ctx.debug) e.printStackTrace() throw new IOException( - s"""class file $classfile is broken, reading aborted with $e.getClass - |${Option(e.getMessage).getOrElse("")}""".stripMargin) + sm"""class file $classfile is broken, reading aborted with $e.getClass + |${Option(e.getMessage).getOrElse("")}""") } private def parseHeader(): Unit = { @@ -702,12 +702,12 @@ class ClassfileParser( getMember(owner, innerName.toTypeName) } assert(result ne NoSymbol, - s"""failure to resolve inner class: - |externalName = $externalName, - |outerName = $outerName, - |innerName = $innerName - |owner.fullName = owner.showFullName - |while parsing ${classfile}""".stripMargin) + sm"""failure to resolve inner class: + |externalName = $externalName, + |outerName = $outerName, + |innerName = $innerName + |owner.fullName = owner.showFullName + |while parsing ${classfile}""") result case None => diff --git a/src/dotty/tools/dotc/core/pickling/UnPickler.scala b/src/dotty/tools/dotc/core/pickling/UnPickler.scala index dd26b20df..462c10137 100644 --- a/src/dotty/tools/dotc/core/pickling/UnPickler.scala +++ b/src/dotty/tools/dotc/core/pickling/UnPickler.scala @@ -53,10 +53,10 @@ object UnPickler { val result = restpe.parameterizeWith(tparams) for ((msg, pos) <- err) ctx.warning( - s"""$msg - |originally parsed type : ${tp.show} - |will be approximated by: ${result.show}. - |Proceed at own risk.""".stripMargin) + sm"""$msg + |originally parsed type : ${tp.show} + |will be approximated by: ${result.show}. + |Proceed at own risk.""") result } else @@ -161,8 +161,8 @@ class UnPickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClassRoot: protected def errorBadSignature(msg: String, original: Option[RuntimeException] = None)(implicit ctx: Context) = { val ex = new BadSignature( - s"""error reading Scala signature of $classRoot from $source: - |error occured at position $readIndex: $msg""".stripMargin) + sm"""error reading Scala signature of $classRoot from $source: + |error occured at position $readIndex: $msg""") /*if (debug)*/ original.getOrElse(ex).printStackTrace() // !!! DEBUG throw ex } diff --git a/src/dotty/tools/dotc/transform/SuperAccessors.scala b/src/dotty/tools/dotc/transform/SuperAccessors.scala index 27378f533..d6af96301 100644 --- a/src/dotty/tools/dotc/transform/SuperAccessors.scala +++ b/src/dotty/tools/dotc/transform/SuperAccessors.scala @@ -48,7 +48,7 @@ import Symbols._ * * TODO: Rename phase to "Accessors" because it handles more than just super accessors */ -class SuperAccessors extends MacroTransform with DenotTransformer { thisTransformer => +class SuperAccessors extends MacroTransform with IdentityDenotTransformer { thisTransformer => import tpd._ @@ -58,9 +58,6 @@ class SuperAccessors extends MacroTransform with DenotTransformer { thisTransfor protected def newTransformer(implicit ctx: Context): Transformer = new SuperAccTransformer - /** No transformation here, but new denotations are installed by the tree traversal */ - def transform(ref: SingleDenotation)(implicit ctx: Context): SingleDenotation = ref - class SuperAccTransformer extends Transformer { /** validCurrentOwner arrives undocumented, but I reverse engineer it to be @@ -444,10 +441,10 @@ class SuperAccessors extends MacroTransform with DenotTransformer { thisTransfor val protectedAccessor = clazz.info.decl(accName).suchThat(_.signature == accType.signature).symbol orElse { val newAcc = ctx.newSymbol( clazz, accName, Artifact, accType, coord = tree.pos).enteredAfter(thisTransformer) - val code = polyDefDef(newAcc, targs => argss => { - val (receiver :: _) :: tail = argss - val base = Select(receiver, sym).appliedToTypes(targs) - (base /: argss)(Apply(_, _)) + val code = polyDefDef(newAcc, trefs => vrefss => { + val (receiver :: _) :: tail = vrefss + val base = Select(receiver, sym).appliedToTypes(trefs) + (base /: vrefss)(Apply(_, _)) }) ctx.debuglog("created protected accessor: " + code) storeAccessorDefinition(clazz, code) @@ -474,8 +471,8 @@ class SuperAccessors extends MacroTransform with DenotTransformer { thisTransfor val protectedAccessor = clazz.info.decl(accName).symbol orElse { val newAcc = ctx.newSymbol( clazz, accName, Artifact, accType, coord = tree.pos).enteredAfter(thisTransformer) - val code = DefDef(newAcc, argss => { - val (receiver :: value :: Nil) :: Nil = argss + val code = DefDef(newAcc, vrefss => { + val (receiver :: value :: Nil) :: Nil = vrefss Assign(Select(receiver, field), value).withPos(tree.pos) }) ctx.debuglog("created protected setter: " + code) diff --git a/src/dotty/tools/dotc/typer/ErrorReporting.scala b/src/dotty/tools/dotc/typer/ErrorReporting.scala index 0b016769b..89e73013f 100644 --- a/src/dotty/tools/dotc/typer/ErrorReporting.scala +++ b/src/dotty/tools/dotc/typer/ErrorReporting.scala @@ -127,7 +127,7 @@ object ErrorReporting { case _ => true } - val s = new InfoString(sc).i(args : _*) + val s = new StringInterpolators(sc).i(args : _*) if (args.forall(isSensical(_))) s else nonSensicalStartTag + s + nonSensicalEndTag } } diff --git a/src/dotty/tools/dotc/typer/ImportInfo.scala b/src/dotty/tools/dotc/typer/ImportInfo.scala index 9fbd07102..18e5db209 100644 --- a/src/dotty/tools/dotc/typer/ImportInfo.scala +++ b/src/dotty/tools/dotc/typer/ImportInfo.scala @@ -7,7 +7,7 @@ import ast.Trees._ import core._ import util.SimpleMap import Symbols._, Names._, Denotations._, Types._, Contexts._, StdNames._, Flags._ -import Decorators.InfoString +import Decorators.StringInterpolators object ImportInfo { /** The import info for a root import from given symbol `sym` */ |