diff options
author | Adriaan Moors <adriaan.moors@epfl.ch> | 2012-06-08 09:00:12 -0700 |
---|---|---|
committer | Adriaan Moors <adriaan.moors@epfl.ch> | 2012-06-08 09:00:12 -0700 |
commit | f42f76b4c6484521c70493207bf92732200e0411 (patch) | |
tree | 8e3123bb11d564e10c5e2837e43f828f1a9d13d6 /src | |
parent | 1fac5bcbbcb9bbfc5953c29574f3952b97945921 (diff) | |
parent | be3d06b33284b133e783ce6ed6e8206f4646319c (diff) | |
download | scala-f42f76b4c6484521c70493207bf92732200e0411.tar.gz scala-f42f76b4c6484521c70493207bf92732200e0411.tar.bz2 scala-f42f76b4c6484521c70493207bf92732200e0411.zip |
Merge pull request #684 from scalamacros/pullrequest/reflection
The new reflection
Diffstat (limited to 'src')
413 files changed, 12572 insertions, 8663 deletions
diff --git a/src/build/maven/maven-deploy.xml b/src/build/maven/maven-deploy.xml index 7ab54f81c3..131358f0f3 100644 --- a/src/build/maven/maven-deploy.xml +++ b/src/build/maven/maven-deploy.xml @@ -111,6 +111,7 @@ <deploy-local name="scala-library" version="@{version}" repository="@{repository}" /> <deploy-local name="scala-compiler" version="@{version}" repository="@{repository}" /> <deploy-local-plugin name="continuations" version="@{version}" repository="@{repository}"/> + <deploy-local name="scala-reflect" version="@{version}" repository="@{repository}" /> <deploy-local name="scala-actors" version="@{version}" repository="@{repository}" /> <deploy-local name="scala-actors-migration" version="@{version}" repository="@{repository}" /> <deploy-local name="scala-swing" version="@{version}" repository="@{repository}"/> @@ -170,6 +171,7 @@ </extra-attachments> </deploy-remote> <deploy-remote name="jline" version="@{version}" repository="@{repository}"/> + <deploy-remote name="scala-reflect" version="@{version}" repository="@{repository}"/> <deploy-remote name="scala-compiler" version="@{version}" repository="@{repository}" /> <deploy-remote name="scala-swing" version="@{version}" repository="@{repository}"/> <deploy-remote name="scala-actors" version="@{version}" repository="@{repository}"/> @@ -238,6 +240,7 @@ <deploy-remote-plugin-signed name="continuations" version="@{version}" repository="@{repository}"/> <deploy-remote-signed name="scala-library" version="@{version}" repository="@{repository}"/> <deploy-remote-signed name="jline" version="@{version}" repository="@{repository}"/> + <deploy-remote-signed name="scala-reflect" version="@{version}" repository="@{repository}"/> <deploy-remote-signed name="scala-compiler" version="@{version}" repository="@{repository}" /> <deploy-remote-signed name="scala-swing" version="@{version}" repository="@{repository}"/> <deploy-remote-signed name="scala-actors" version="@{version}" repository="@{repository}"/> diff --git a/src/build/maven/scala-compiler-pom.xml b/src/build/maven/scala-compiler-pom.xml index 82d0ed7c91..fedc34a5d5 100644 --- a/src/build/maven/scala-compiler-pom.xml +++ b/src/build/maven/scala-compiler-pom.xml @@ -37,6 +37,11 @@ <artifactId>scala-library</artifactId> <version>@VERSION@</version> </dependency> + <dependency> + <groupId>org.scala-lang</groupId> + <artifactId>scala-reflect</artifactId> + <version>@VERSION@</version> + </dependency> <dependency> <groupId>org.scala-lang</groupId> <artifactId>jline</artifactId> diff --git a/src/build/maven/scala-reflect-pom.xml b/src/build/maven/scala-reflect-pom.xml new file mode 100644 index 0000000000..7a1613f42c --- /dev/null +++ b/src/build/maven/scala-reflect-pom.xml @@ -0,0 +1,62 @@ +<project + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>org.scala-lang</groupId> + <artifactId>scala-reflect</artifactId> + <packaging>jar</packaging> + <version>@VERSION@</version> + <name>Scala Compiler</name> + <description>Compiler for the Scala Programming Language</description> + <url>http://www.scala-lang.org/</url> + <inceptionYear>2002</inceptionYear> + <organization> + <name>LAMP/EPFL</name> + <url>http://lamp.epfl.ch/</url> + </organization> + <licenses> + <license> + <name>BSD-like</name> + <url>http://www.scala-lang.org/downloads/license.html + </url> + <distribution>repo</distribution> + </license> + </licenses> + <scm> + <connection>scm:git:git://github.com/scala/scala.git</connection> + <url>https://github.com/scala/scala.git</url> + </scm> + <issueManagement> + <system>JIRA</system> + <url>https://issues.scala-lang.org/</url> + </issueManagement> + + <dependencies> + <dependency> + <groupId>org.scala-lang</groupId> + <artifactId>scala-library</artifactId> + <version>@VERSION@</version> + </dependency> + </dependencies> + <distributionManagement> + <repository> + <id>scala-tools.org</id> + <url>@RELEASE_REPOSITORY@</url> + </repository> + <snapshotRepository> + <id>scala-tools.org</id> + <url>@SNAPSHOT_REPOSITORY@</url> + <uniqueVersion>false</uniqueVersion> + </snapshotRepository> + </distributionManagement> + <developers> + <developer> + <id>lamp</id> + <name>EPFL LAMP</name> + </developer> + <developer> + <id>Typesafe</id> + <name>Typesafe, Inc.</name> + </developer> + </developers> +</project> diff --git a/src/build/pack.xml b/src/build/pack.xml index 956beaef88..564d290967 100644 --- a/src/build/pack.xml +++ b/src/build/pack.xml @@ -136,6 +136,7 @@ MAIN DISTRIBUTION PACKAGING </macrodef> <mvn-copy-lib mvn.artifact.name="jline"/> <mvn-copy-lib mvn.artifact.name="scala-library"/> + <mvn-copy-lib mvn.artifact.name="scala-reflect"/> <mvn-copy-lib mvn.artifact.name="scala-compiler"/> <mvn-copy-lib mvn.artifact.name="scala-swing"/> <mvn-copy-lib mvn.artifact.name="scala-actors"/> @@ -212,6 +213,8 @@ MAIN DISTRIBUTION PACKAGING file="${dists.dir}/maven/${version.number}/scala-library/scala-library-docs.jar"/> <copy tofile="${dists.dir}/maven/${version.number}/scala-actors/scala-actors-docs.jar" file="${dists.dir}/maven/${version.number}/scala-library/scala-library-docs.jar"/> + <copy tofile="${dists.dir}/maven/${version.number}/scala-reflect/scala-reflect-docs.jar" + file="${dists.dir}/maven/${version.number}/scala-library/scala-library-docs.jar"/> </target> <target name="pack-maven.latest.unix" depends="pack-maven.docs" unless="os.win"> diff --git a/src/compiler/scala/reflect/internal/FreeVars.scala b/src/compiler/scala/reflect/internal/FreeVars.scala deleted file mode 100644 index 8b6e8b61f3..0000000000 --- a/src/compiler/scala/reflect/internal/FreeVars.scala +++ /dev/null @@ -1,60 +0,0 @@ -package scala.reflect -package internal - -trait FreeVars extends api.FreeVars { - self: SymbolTable => - - object FreeTerm extends FreeTermExtractor { - def unapply(freeTerm: FreeTerm): Option[(TermName, Type, Any, String)] = - Some(freeTerm.name, freeTerm.info, freeTerm.value, freeTerm.origin) - } - - object FreeType extends FreeTypeExtractor { - def unapply(freeType: FreeType): Option[(TypeName, Type, String)] = - Some(freeType.name, freeType.info, freeType.origin) - } - - // [Eugene] am I doing this right? - def freeTerms(tree: Tree): List[FreeTerm] = { - def isFreeTermSym(sym: Symbol) = sym != null && sym.isFreeTerm - def isFreeTermTpe(t: Type) = t != null && isFreeTermSym(t.termSymbol) - - val buf = collection.mutable.Set[Symbol]() - tree foreach (sub => { - if (sub.tpe != null) buf ++= (sub.tpe collect { case tpe if isFreeTermTpe(tpe) => tpe.typeSymbol }) - if (sub.symbol != null && isFreeTermSym(sub.symbol)) buf += sub.symbol - }) - - buf.toList.collect{ case fty: FreeTerm => fty } - } - - // [Eugene] am I doing this right? - def freeTypes(tree: Tree): List[FreeType] = { - def isFreeTypeSym(sym: Symbol) = sym != null && sym.isFreeType - def isFreeTypeTpe(t: Type) = t != null && isFreeTypeSym(t.typeSymbol) - - val buf = collection.mutable.Set[Symbol]() - tree foreach (sub => { - if (sub.tpe != null) buf ++= (sub.tpe collect { case tpe if isFreeTypeTpe(tpe) => tpe.typeSymbol }) - if (sub.symbol != null && isFreeTypeSym(sub.symbol)) buf += sub.symbol - }) - - buf.toList.collect{ case fty: FreeType => fty } - } - - // todo. also update tpe's of dependent free vars - // e.g. if we substitute free$C, then free$C$this should have its info updated - // todo. should also transform typetags of types dependent on that free type? - // [Eugene] how do I check that the substitution is legal w.r.t fty.info? - def substituteFreeTypes(tree0: Tree, subs: Map[FreeType, Type]): Tree = { - val tree = tree0.duplicate - new TreeTypeSubstituter(subs.keys.toList, subs.values.toList).traverse(tree) - tree - } - - // [Eugene] how do I check that the substitution is legal w.r.t fty.info? - def substituteFreeTypes(tpe0: Type, subs: Map[FreeType, Type]): Type = { - val tpe = tpe0 // [Eugene] tpe0.duplicate? - tpe.subst(subs.keys.toList, subs.values.toList) - } -}
\ No newline at end of file diff --git a/src/compiler/scala/reflect/internal/StdAttachments.scala b/src/compiler/scala/reflect/internal/StdAttachments.scala deleted file mode 100644 index ae2ad87deb..0000000000 --- a/src/compiler/scala/reflect/internal/StdAttachments.scala +++ /dev/null @@ -1,10 +0,0 @@ -package scala.reflect -package internal - -import scala.reflect.makro.runtime.{Context => MacroContext} - -trait StdAttachments { - self: SymbolTable => - - case class ReifyAttachment(original: Symbol) -}
\ No newline at end of file diff --git a/src/compiler/scala/reflect/internal/TreeBuildUtil.scala b/src/compiler/scala/reflect/internal/TreeBuildUtil.scala deleted file mode 100644 index d4d4652e91..0000000000 --- a/src/compiler/scala/reflect/internal/TreeBuildUtil.scala +++ /dev/null @@ -1,66 +0,0 @@ -package scala.reflect -package internal - -import Flags._ - -trait TreeBuildUtil extends api.TreeBuildUtil { self: SymbolTable => - - // ``staticClass'' and ``staticModule'' rely on ClassLoaders - // which are implementation-specific for different Universes - - def staticClassIfDefined(fullName: String): Symbol = - try staticClass(fullName) - catch { case _: MissingRequirementError => NoSymbol } - - def staticModuleIfDefined(fullName: String): Symbol = - try staticModule(fullName) - catch { case _: MissingRequirementError => NoSymbol } - - def thisModuleType(fullname: String) = staticModule(fullname).moduleClass.thisType - - def selectType(owner: Symbol, name: String): Symbol = - owner.info.decl(newTypeName(name)) orElse { - MissingRequirementError.notFound("type %s in %s".format(name, owner.fullName)) - } - - def selectTypeIfDefined(owner: Symbol, name: String): Symbol = - try selectType(owner, name) - catch { case _: MissingRequirementError => NoSymbol } - -// try getModule(fullname.toTermName) -// catch { case _: MissingRequirementError => NoSymbol } - - def selectTerm(owner: Symbol, name: String): Symbol = { - val sym = owner.info.decl(newTermName(name)) - val result = - if (sym.isOverloaded) sym suchThat (!_.isMethod) - else sym - result orElse { - MissingRequirementError.notFound("term %s in %s".format(name, owner.fullName)) - } - } - - def selectTermIfDefined(owner: Symbol, name: String): Symbol = - try selectTerm(owner, name) - catch { case _: MissingRequirementError => NoSymbol } - - def selectOverloadedMethod(owner: Symbol, name: String, index: Int): Symbol = - owner.info.decl(newTermName(name)).alternatives(index) orElse { - MissingRequirementError.notFound("overloaded method %s #%d in %s".format(name, index, owner.fullName)) - } - - def selectOverloadedMethodIfDefined(owner: Symbol, name: String, index: Int): Symbol = - try selectOverloadedMethod(owner, name, index) - catch { case _: MissingRequirementError => NoSymbol } - - def newFreeTerm(name: String, info: Type, value: => Any, flags: Long = 0L, origin: String = null) = newFreeTermSymbol(newTermName(name), info, value, flags, origin) - - def newFreeType(name: String, info: Type, value: => Any, flags: Long = 0L, origin: String = null) = newFreeTypeSymbol(newTypeName(name), info, value, (if (flags == 0L) PARAM else flags) | DEFERRED, origin) - - def newFreeExistential(name: String, info: Type, value: => Any, flags: Long = 0L, origin: String = null) = newFreeTypeSymbol(newTypeName(name), info, value, (if (flags == 0L) EXISTENTIAL else flags) | DEFERRED, origin) - - def modifiersFromInternalFlags(flags: Long, privateWithin: Name, annotations: List[Tree]): Modifiers = - Modifiers(flags, privateWithin, annotations) - - val gen: TreeGen { val global: TreeBuildUtil.this.type } -}
\ No newline at end of file diff --git a/src/compiler/scala/reflect/internal/Trees.scala b/src/compiler/scala/reflect/internal/Trees.scala deleted file mode 100644 index 3e7f23800c..0000000000 --- a/src/compiler/scala/reflect/internal/Trees.scala +++ /dev/null @@ -1,435 +0,0 @@ -/* NSC -- new Scala compiler - * Copyright 2005-2011 LAMP/EPFL - * @author Martin Odersky - */ - -package scala.reflect -package internal - -import Flags._ -import api.Modifier - -trait Trees extends api.Trees { self: SymbolTable => - - // Belongs in TreeInfo but then I can't reach it from TreePrinters. - def isReferenceToScalaMember(t: Tree, Id: Name) = t match { - case Ident(Id) => true - case Select(Ident(nme.scala_), Id) => true - case Select(Select(Ident(nme.ROOTPKG), nme.scala_), Id) => true - case _ => false - } - /** Is the tree Predef, scala.Predef, or _root_.scala.Predef? - */ - def isReferenceToPredef(t: Tree) = isReferenceToScalaMember(t, nme.Predef) - def isReferenceToAnyVal(t: Tree) = isReferenceToScalaMember(t, tpnme.AnyVal) - - // --- modifiers implementation --------------------------------------- - - /** @param privateWithin the qualifier for a private (a type name) - * or tpnme.EMPTY, if none is given. - * @param annotations the annotations for the definition. - * '''Note:''' the typechecker drops these annotations, - * use the AnnotationInfo's (Symbol.annotations) in later phases. - */ - case class Modifiers(flags: Long, - privateWithin: Name, - annotations: List[Tree]) extends AbsModifiers with HasFlags { - - var positions: Map[Long, Position] = Map() - - def setPositions(poss: Map[Long, Position]): this.type = { - positions = poss; this - } - - /* Abstract types from HasFlags. */ - type AccessBoundaryType = Name - type AnnotationType = Tree - - def hasAnnotationNamed(name: TypeName) = { - annotations exists { - case Apply(Select(New(Ident(`name`)), _), _) => true - case Apply(Select(New(Select(_, `name`)), _), _) => true - case _ => false - } - } - - def hasAccessBoundary = privateWithin != tpnme.EMPTY - def hasAllFlags(mask: Long): Boolean = (flags & mask) == mask - def hasFlag(flag: Long) = (flag & flags) != 0L - - def & (flag: Long): Modifiers = { - val flags1 = flags & flag - if (flags1 == flags) this - else Modifiers(flags1, privateWithin, annotations) setPositions positions - } - def &~ (flag: Long): Modifiers = { - val flags1 = flags & (~flag) - if (flags1 == flags) this - else Modifiers(flags1, privateWithin, annotations) setPositions positions - } - def | (flag: Long): Modifiers = { - val flags1 = flags | flag - if (flags1 == flags) this - else Modifiers(flags1, privateWithin, annotations) setPositions positions - } - def withAnnotations(annots: List[Tree]) = - if (annots.isEmpty) this - else copy(annotations = annotations ::: annots) setPositions positions - - def withPosition(flag: Long, position: Position) = - copy() setPositions positions + (flag -> position) - - override def hasModifier(mod: Modifier) = - hasFlag(flagOfModifier(mod)) - override def modifiers: Set[Modifier] = - Modifier.values filter hasModifier - override def mapAnnotations(f: List[Tree] => List[Tree]): Modifiers = - Modifiers(flags, privateWithin, f(annotations)) setPositions positions - - override def toString = "Modifiers(%s, %s, %s)".format(flagString, annotations mkString ", ", positions) - } - - def Modifiers(flags: Long, privateWithin: Name): Modifiers = Modifiers(flags, privateWithin, List()) - def Modifiers(flags: Long): Modifiers = Modifiers(flags, tpnme.EMPTY) - - def Modifiers(mods: Set[Modifier], - privateWithin: Name, - annotations: List[Tree]): Modifiers = { - val flagSet = mods map flagOfModifier - Modifiers((0L /: flagSet)(_ | _), privateWithin, annotations) - } - - lazy val NoMods = Modifiers(0) - - // --- extension methods -------------------------------------------------------- - - implicit class TreeOps(tree: Tree) { - def isErroneous = (tree.tpe ne null) && tree.tpe.isErroneous - def isTyped = (tree.tpe ne null) && !tree.tpe.isErroneous - - /** Sets the tree's type to the result of the given function. - * If the type is null, it remains null - the function is not called. - */ - def modifyType(f: Type => Type): Tree = - if (tree.tpe eq null) tree - else tree setType f(tree.tpe) - - /** If `pf` is defined for a given subtree, call super.traverse(pf(tree)), - * otherwise super.traverse(tree). - */ - def foreachPartial(pf: PartialFunction[Tree, Tree]) { - new ForeachPartialTreeTraverser(pf).traverse(tree) - } - - def changeOwner(pairs: (Symbol, Symbol)*): Tree = { - pairs.foldLeft(tree) { case (t, (oldOwner, newOwner)) => - new ChangeOwnerTraverser(oldOwner, newOwner) apply t - } - } - - def substTreeSyms(pairs: (Symbol, Symbol)*): Tree = - substTreeSyms(pairs.map(_._1).toList, pairs.map(_._2).toList) - - def substTreeSyms(from: List[Symbol], to: List[Symbol]): Tree = - new TreeSymSubstituter(from, to)(tree) - - def substTreeThis(clazz: Symbol, to: Tree): Tree = new ThisSubstituter(clazz, to) transform tree - - def shallowDuplicate: Tree = new ShallowDuplicator(tree) transform tree - def shortClass: String = tree.getClass.getName split "[.$]" last - - def isErrorTyped = (tree.tpe ne null) && tree.tpe.isError - - /** When you want to know a little more than the class, but a lot - * less than the whole tree. - */ - def summaryString: String = tree match { - case Literal(const) => "Literal(" + const + ")" - case Ident(name) => "Ident(%s)".format(name.decode) - case Select(qual, name) => "Select(%s, %s)".format(qual.summaryString, name.decode) - case t: NameTree => t.name.longString - case t => - t.shortClass + ( - if (t.symbol != null && t.symbol != NoSymbol) "(" + t.symbol + ")" - else "" - ) - } - } - - // ---- values and creators --------------------------------------- - - /** @param sym the class symbol - * @return the implementation template - */ - def ClassDef(sym: Symbol, impl: Template): ClassDef = - atPos(sym.pos) { - ClassDef(Modifiers(sym.flags), - sym.name.toTypeName, - sym.typeParams map TypeDef, - impl) setSymbol sym - } - - /** - * @param sym the class symbol - * @param impl the implementation template - */ - def ModuleDef(sym: Symbol, impl: Template): ModuleDef = - atPos(sym.pos) { - ModuleDef(Modifiers(sym.flags), sym.name.toTermName, impl) setSymbol sym - } - - def ValDef(sym: Symbol, rhs: Tree): ValDef = - atPos(sym.pos) { - ValDef(Modifiers(sym.flags), sym.name.toTermName, - TypeTree(sym.tpe) setPos sym.pos.focus, - rhs) setSymbol sym - } - - def ValDef(sym: Symbol): ValDef = ValDef(sym, EmptyTree) - - object emptyValDef extends ValDef(Modifiers(PRIVATE), nme.WILDCARD, TypeTree(NoType), EmptyTree) { - override def isEmpty = true - super.setPos(NoPosition) - override def setPos(pos: Position) = { assert(false); this } - } - - def DefDef(sym: Symbol, mods: Modifiers, vparamss: List[List[ValDef]], rhs: Tree): DefDef = - atPos(sym.pos) { - assert(sym != NoSymbol) - DefDef(mods, - sym.name.toTermName, - sym.typeParams map TypeDef, - vparamss, - TypeTree(sym.tpe.finalResultType) setPos sym.pos.focus, - rhs) setSymbol sym - } - - def DefDef(sym: Symbol, vparamss: List[List[ValDef]], rhs: Tree): DefDef = - DefDef(sym, Modifiers(sym.flags), vparamss, rhs) - - def DefDef(sym: Symbol, mods: Modifiers, rhs: Tree): DefDef = - DefDef(sym, mods, mapParamss(sym)(ValDef), rhs) - - def DefDef(sym: Symbol, rhs: Tree): DefDef = - DefDef(sym, Modifiers(sym.flags), rhs) - - def DefDef(sym: Symbol, rhs: List[List[Symbol]] => Tree): DefDef = - DefDef(sym, rhs(sym.info.paramss)) - - /** A TypeDef node which defines given `sym` with given tight hand side `rhs`. */ - def TypeDef(sym: Symbol, rhs: Tree): TypeDef = - atPos(sym.pos) { - TypeDef(Modifiers(sym.flags), sym.name.toTypeName, sym.typeParams map TypeDef, rhs) setSymbol sym - } - - /** A TypeDef node which defines abstract type or type parameter for given `sym` */ - def TypeDef(sym: Symbol): TypeDef = - TypeDef(sym, TypeBoundsTree(TypeTree(sym.info.bounds.lo), TypeTree(sym.info.bounds.hi))) - - def LabelDef(sym: Symbol, params: List[Symbol], rhs: Tree): LabelDef = - atPos(sym.pos) { - LabelDef(sym.name.toTermName, params map Ident, rhs) setSymbol sym - } - - /** casedef shorthand */ - def CaseDef(pat: Tree, body: Tree): CaseDef = - CaseDef(pat, EmptyTree, body) - - def Bind(sym: Symbol, body: Tree): Bind = - Bind(sym.name, body) setSymbol sym - - def Try(body: Tree, cases: (Tree, Tree)*): Try = - Try(body, cases.toList map { case (pat, rhs) => CaseDef(pat, EmptyTree, rhs) }, EmptyTree) - - def Throw(tpe: Type, args: Tree*): Throw = - Throw(New(tpe, args: _*)) - - def Apply(sym: Symbol, args: Tree*): Tree = - Apply(Ident(sym), args.toList) - - /** Factory method for object creation `new tpt(args_1)...(args_n)` - * A `New(t, as)` is expanded to: `(new t).<init>(as)` - */ - def New(tpt: Tree, argss: List[List[Tree]]): Tree = argss match { - case Nil => new ApplyConstructor(tpt, Nil) - case xs :: rest => rest.foldLeft(new ApplyConstructor(tpt, xs): Tree)(Apply) - } - - /** 0-1 argument list new, based on a type. - */ - def New(tpe: Type, args: Tree*): Tree = - new ApplyConstructor(TypeTree(tpe), args.toList) - - def New(sym: Symbol, args: Tree*): Tree = - New(sym.tpe, args: _*) - - def Super(sym: Symbol, mix: TypeName): Tree = - Super(This(sym), mix) - - def This(sym: Symbol): Tree = - This(sym.name.toTypeName) setSymbol sym - - def Select(qualifier: Tree, name: String): Select = - Select(qualifier, newTermName(name)) - - def Select(qualifier: Tree, sym: Symbol): Select = - Select(qualifier, sym.name) setSymbol sym - - def Ident(name: String): Ident = - Ident(newTermName(name)) - - def Ident(sym: Symbol): Ident = - Ident(sym.name) setSymbol sym - - /** Block factory that flattens directly nested blocks. - */ - def Block(stats: Tree*): Block = { - if (stats.isEmpty) Block(Nil, Literal(Constant(()))) - else stats match { - case Seq(b @ Block(_, _)) => b - case Seq(stat) => Block(stats.toList, Literal(Constant(()))) - case Seq(_, rest @ _*) => Block(stats.init.toList, stats.last) - } - } - - // --- specific traversers and transformers - // todo. move these into scala.reflect.api - - protected[scala] def duplicateTree(tree: Tree): Tree = duplicator transform tree - - private lazy val duplicator = new Transformer { - override val treeCopy = newStrictTreeCopier - override def transform(t: Tree) = { - val t1 = super.transform(t) - if ((t1 ne t) && t1.pos.isRange) t1 setPos t.pos.focus - t1 - } - } - - class ForeachPartialTreeTraverser(pf: PartialFunction[Tree, Tree]) extends Traverser { - override def traverse(tree: Tree) { - val t = if (pf isDefinedAt tree) pf(tree) else tree - super.traverse(t) - } - } - - class ChangeOwnerTraverser(val oldowner: Symbol, val newowner: Symbol) extends Traverser { - def changeOwner(tree: Tree) = tree match { - case Return(expr) => - if (tree.symbol == oldowner) { - // SI-5612 - if (newowner hasTransOwner oldowner) - log("NOT changing owner of %s because %s is nested in %s".format(tree, newowner, oldowner)) - else { - log("changing owner of %s: %s => %s".format(tree, oldowner, newowner)) - tree.symbol = newowner - } - } - case _: DefTree | _: Function => - if (tree.symbol != NoSymbol && tree.symbol.owner == oldowner) { - tree.symbol.owner = newowner - } - case _ => - } - override def traverse(tree: Tree) { - changeOwner(tree) - super.traverse(tree) - } - } - - private class ShallowDuplicator(orig: Tree) extends Transformer { - override val treeCopy = newStrictTreeCopier - override def transform(tree: Tree) = - if (tree eq orig) super.transform(tree) - else tree - } - // Create a readable string describing a substitution. - private def substituterString(fromStr: String, toStr: String, from: List[Any], to: List[Any]): String = { - "subst[%s, %s](%s)".format(fromStr, toStr, (from, to).zipped map (_ + " -> " + _) mkString ", ") - } - - // NOTE: calls shallowDuplicate on trees in `to` to avoid problems when symbols in `from` - // occur multiple times in the `tree` passed to `transform`, - // otherwise, the resulting Tree would be a graph, not a tree... this breaks all sorts of stuff, - // notably concerning the mutable aspects of Trees (such as setting their .tpe) - class TreeSubstituter(from: List[Symbol], to: List[Tree]) extends Transformer { - override def transform(tree: Tree): Tree = tree match { - case Ident(_) => - def subst(from: List[Symbol], to: List[Tree]): Tree = - if (from.isEmpty) tree - else if (tree.symbol == from.head) to.head.shallowDuplicate // TODO: does it ever make sense *not* to perform a shallowDuplicate on `to.head`? - else subst(from.tail, to.tail); - subst(from, to) - case _ => - super.transform(tree) - } - override def toString = substituterString("Symbol", "Tree", from, to) - } - - /** Substitute clazz.this with `to`. `to` must be an attributed tree. - */ - class ThisSubstituter(clazz: Symbol, to: => Tree) extends Transformer { - val newtpe = to.tpe - override def transform(tree: Tree) = { - if (tree.tpe ne null) tree.tpe = tree.tpe.substThis(clazz, newtpe) - tree match { - case This(_) if tree.symbol == clazz => to - case _ => super.transform(tree) - } - } - } - - class TypeMapTreeSubstituter(val typeMap: TypeMap) extends Traverser { - override def traverse(tree: Tree) { - if (tree.tpe ne null) - tree.tpe = typeMap(tree.tpe) - if (tree.isDef) - tree.symbol modifyInfo typeMap - - super.traverse(tree) - } - override def apply[T <: Tree](tree: T): T = super.apply(tree.duplicate) - } - - class TreeTypeSubstituter(val from: List[Symbol], val to: List[Type]) extends TypeMapTreeSubstituter(new SubstTypeMap(from, to)) { - def isEmpty = from.isEmpty && to.isEmpty - override def toString() = "TreeTypeSubstituter("+from+","+to+")" - } - - lazy val EmptyTreeTypeSubstituter = new TreeTypeSubstituter(List(), List()) - - class TreeSymSubstTraverser(val from: List[Symbol], val to: List[Symbol]) extends TypeMapTreeSubstituter(new SubstSymMap(from, to)) { - override def toString() = "TreeSymSubstTraverser/" + substituterString("Symbol", "Symbol", from, to) - } - - /** Substitute symbols in `from` with symbols in `to`. Returns a new - * tree using the new symbols and whose Ident and Select nodes are - * name-consistent with the new symbols. - */ - class TreeSymSubstituter(from: List[Symbol], to: List[Symbol]) extends Transformer { - val symSubst = new SubstSymMap(from, to) - override def transform(tree: Tree): Tree = { - def subst(from: List[Symbol], to: List[Symbol]) { - if (!from.isEmpty) - if (tree.symbol == from.head) tree setSymbol to.head - else subst(from.tail, to.tail) - } - - if (tree.tpe ne null) tree.tpe = symSubst(tree.tpe) - if (tree.hasSymbol) { - subst(from, to) - tree match { - case Ident(name0) if tree.symbol != NoSymbol => - treeCopy.Ident(tree, tree.symbol.name) - case Select(qual, name0) if tree.symbol != NoSymbol => - treeCopy.Select(tree, transform(qual), tree.symbol.name) - case _ => - super.transform(tree) - } - } else - super.transform(tree) - } - def apply[T <: Tree](tree: T): T = transform(tree).asInstanceOf[T] - override def toString() = "TreeSymSubstituter/" + substituterString("Symbol", "Symbol", from, to) - } -} diff --git a/src/compiler/scala/reflect/makro/runtime/AbortMacroException.scala b/src/compiler/scala/reflect/makro/runtime/AbortMacroException.scala index d78eae9237..a68910859d 100644 --- a/src/compiler/scala/reflect/makro/runtime/AbortMacroException.scala +++ b/src/compiler/scala/reflect/makro/runtime/AbortMacroException.scala @@ -1,6 +1,6 @@ package scala.reflect.makro package runtime -import scala.reflect.api.Position +import scala.reflect.internal.util.Position class AbortMacroException(val pos: Position, val msg: String) extends Throwable(msg) diff --git a/src/compiler/scala/reflect/makro/runtime/Aliases.scala b/src/compiler/scala/reflect/makro/runtime/Aliases.scala index a4f208ca34..760f7fc54d 100644 --- a/src/compiler/scala/reflect/makro/runtime/Aliases.scala +++ b/src/compiler/scala/reflect/makro/runtime/Aliases.scala @@ -4,18 +4,23 @@ package runtime trait Aliases { self: Context => - /** Aliases of mirror types */ - override type Symbol = mirror.Symbol - override type Type = mirror.Type - override type Name = mirror.Name - override type Tree = mirror.Tree - override type Position = mirror.Position - override type Scope = mirror.Scope - override type Modifiers = mirror.Modifiers - override type Expr[+T] = mirror.Expr[T] - override type TypeTag[T] = mirror.TypeTag[T] + override type Symbol = universe.Symbol + override type Type = universe.Type + override type Name = universe.Name + override type TermName = universe.TermName + override type TypeName = universe.TypeName + override type Tree = universe.Tree + // override type Position = universe.Position + override type Scope = universe.Scope + override type Modifiers = universe.Modifiers - /** Creator/extractor objects for Expr and TypeTag values */ - override val TypeTag = mirror.TypeTag - override val Expr = mirror.Expr + override type Expr[+T] = universe.Expr[T] + override val Expr = universe.Expr + + override type AbsTypeTag[T] = universe.AbsTypeTag[T] + override type TypeTag[T] = universe.TypeTag[T] + override val AbsTypeTag = universe.AbsTypeTag + override val TypeTag = universe.TypeTag + override def typeTag[T](implicit ttag: TypeTag[T]) = ttag + override def typeOf[T](implicit ttag: TypeTag[T]): Type = ttag.tpe }
\ No newline at end of file diff --git a/src/compiler/scala/reflect/makro/runtime/CapturedVariables.scala b/src/compiler/scala/reflect/makro/runtime/CapturedVariables.scala index 4e93d4e06d..021b93ceee 100644 --- a/src/compiler/scala/reflect/makro/runtime/CapturedVariables.scala +++ b/src/compiler/scala/reflect/makro/runtime/CapturedVariables.scala @@ -5,10 +5,11 @@ trait CapturedVariables { self: Context => import mirror._ + import universe._ - def captureVariable(vble: Symbol): Unit = mirror.captureVariable(vble) + def captureVariable(vble: Symbol): Unit = universe.captureVariable(vble) - def referenceCapturedVariable(vble: Symbol): Tree = mirror.referenceCapturedVariable(vble) + def referenceCapturedVariable(vble: Symbol): Tree = universe.referenceCapturedVariable(vble) - def capturedVariableType(vble: Symbol): Type = mirror.capturedVariableType(vble) + def capturedVariableType(vble: Symbol): Type = universe.capturedVariableType(vble) }
\ No newline at end of file diff --git a/src/compiler/scala/reflect/makro/runtime/Context.scala b/src/compiler/scala/reflect/makro/runtime/Context.scala index ca02822788..c7563e7b67 100644 --- a/src/compiler/scala/reflect/makro/runtime/Context.scala +++ b/src/compiler/scala/reflect/makro/runtime/Context.scala @@ -8,20 +8,26 @@ abstract class Context extends scala.reflect.makro.Context with CapturedVariables with Infrastructure with Enclosures + with Mirrors with Names with Reifiers with FrontEnds with Settings - with Symbols with Typers - with Util + with Parsers + with Exprs + with TypeTags + with Evals + with ExprUtils with Traces { - val mirror: Global + val universe: Global - val callsiteTyper: mirror.analyzer.Typer + val mirror: MirrorOf[universe.type] = new ContextMirror + + val callsiteTyper: universe.analyzer.Typer val prefix: Expr[PrefixType] val expandee: Tree -}
\ No newline at end of file +} diff --git a/src/compiler/scala/reflect/makro/runtime/ContextReifiers.scala b/src/compiler/scala/reflect/makro/runtime/ContextReifiers.scala new file mode 100644 index 0000000000..564148fe6c --- /dev/null +++ b/src/compiler/scala/reflect/makro/runtime/ContextReifiers.scala @@ -0,0 +1,26 @@ +package scala.reflect.makro +package runtime + +abstract class ContextReifiers { self => + val c: Context + + import c.universe._ + import definitions._ + import treeBuild._ + + import scala.reflect.reify.Taggers + import language.implicitConversions + private implicit def context2taggers(c0: Context) : Taggers { val c: c0.type } = new { val c: c0.type = c0 } with Taggers + + private def forMacroContext[T](prefix: Tree)(op: (Tree, Tree) => T): T = { + val universe = gen.mkAttributedSelect(prefix.duplicate, MacroContextUniverse) setType SingleType(prefix.tpe, MacroContextUniverse) + val mirror = TypeApply(Select(Select(prefix.duplicate, nme.mirror), nme.asInstanceOf_), List(Select(Ident(nme.UNIVERSE_SHORT), tpnme.Mirror))) + op(universe, mirror) + } + + def materializeExprForMacroContext(prefix: Tree, expr: Tree): Tree = + forMacroContext(prefix)((universe, mirror) => c.materializeExpr(universe, mirror, expr)) + + def materializeTypeTagForMacroContext(prefix: Tree, tpe: Type, concrete: Boolean): Tree = + forMacroContext(prefix)((universe, mirror) => c.materializeTypeTag(universe, mirror, tpe, concrete)) +}
\ No newline at end of file diff --git a/src/compiler/scala/reflect/makro/runtime/Enclosures.scala b/src/compiler/scala/reflect/makro/runtime/Enclosures.scala index ab38fc024d..80c35d22ff 100644 --- a/src/compiler/scala/reflect/makro/runtime/Enclosures.scala +++ b/src/compiler/scala/reflect/makro/runtime/Enclosures.scala @@ -4,6 +4,7 @@ package runtime trait Enclosures { self: Context => + import universe._ import mirror._ private def site = callsiteTyper.context @@ -16,7 +17,7 @@ trait Enclosures { val enclosingApplication: Tree = enclTrees collectFirst { case t: Apply => t } getOrElse EmptyTree val enclosingClass: Tree = site.enclClass.tree val enclosingImplicits: List[(Type, Tree)] = site.openImplicits - val enclosingMacros: List[Context] = this :: mirror.analyzer.openMacros // include self + val enclosingMacros: List[Context] = this :: universe.analyzer.openMacros // include self val enclosingMethod: Tree = site.enclMethod.tree val enclosingPosition: Position = if (enclPoses.isEmpty) NoPosition else enclPoses.head.pos val enclosingUnit: CompilationUnit = currentRun.currentUnit diff --git a/src/compiler/scala/reflect/makro/runtime/Evals.scala b/src/compiler/scala/reflect/makro/runtime/Evals.scala new file mode 100644 index 0000000000..0574359a19 --- /dev/null +++ b/src/compiler/scala/reflect/makro/runtime/Evals.scala @@ -0,0 +1,18 @@ +package scala.reflect.makro +package runtime + +import scala.reflect.runtime.{universe => ru} +import scala.tools.reflect.ToolBox + +trait Evals { + self: Context => + + private lazy val evalMirror = ru.runtimeMirror(libraryClassLoader) + private lazy val evalToolBox = evalMirror.mkToolBox() + private lazy val evalImporter = ru.mkImporter(universe).asInstanceOf[ru.Importer { val from: universe.type }] + + def eval[T](expr: Expr[T]): T = { + val imported = evalImporter.importTree(expr.tree) + evalToolBox.runExpr(imported).asInstanceOf[T] + } +}
\ No newline at end of file diff --git a/src/compiler/scala/reflect/makro/runtime/Util.scala b/src/compiler/scala/reflect/makro/runtime/ExprUtils.scala index 2671155721..4775138e5a 100644 --- a/src/compiler/scala/reflect/makro/runtime/Util.scala +++ b/src/compiler/scala/reflect/makro/runtime/ExprUtils.scala @@ -1,9 +1,10 @@ package scala.reflect.makro package runtime -trait Util { +trait ExprUtils { self: Context => + import universe._ import mirror._ def literalNull = Expr[Null](Literal(Constant(null)))(TypeTag.Null) diff --git a/src/compiler/scala/reflect/makro/runtime/Exprs.scala b/src/compiler/scala/reflect/makro/runtime/Exprs.scala new file mode 100644 index 0000000000..b680b56bab --- /dev/null +++ b/src/compiler/scala/reflect/makro/runtime/Exprs.scala @@ -0,0 +1,8 @@ +package scala.reflect.makro +package runtime + +trait Exprs { + self: Context => + + def Expr[T: AbsTypeTag](tree: Tree): Expr[T] = universe.Expr[T](mirror, universe.FixedMirrorTreeCreator(mirror, tree)) +} diff --git a/src/compiler/scala/reflect/makro/runtime/FrontEnds.scala b/src/compiler/scala/reflect/makro/runtime/FrontEnds.scala index 7cfa8e80f3..6644c579ac 100644 --- a/src/compiler/scala/reflect/makro/runtime/FrontEnds.scala +++ b/src/compiler/scala/reflect/makro/runtime/FrontEnds.scala @@ -1,32 +1,35 @@ package scala.reflect.makro package runtime -trait FrontEnds { +trait FrontEnds extends scala.tools.reflect.FrontEnds { self: Context => + import universe._ import mirror._ - def frontEnd: FrontEnd = wrapReporter(mirror.reporter) + override type Position = universe.Position + + def frontEnd: FrontEnd = wrapReporter(universe.reporter) def setFrontEnd(frontEnd: FrontEnd): this.type = { - mirror.reporter = wrapFrontEnd(frontEnd) + universe.reporter = wrapFrontEnd(frontEnd) this } def withFrontEnd[T](frontEnd: FrontEnd)(op: => T): T = { - val old = mirror.reporter + val old = universe.reporter setFrontEnd(frontEnd) try op - finally mirror.reporter = old + finally universe.reporter = old } - def echo(pos: Position, msg: String): Unit = mirror.reporter.echo(pos, msg) + def echo(pos: Position, msg: String): Unit = universe.reporter.echo(pos, msg) - def info(pos: Position, msg: String, force: Boolean): Unit = mirror.reporter.info(pos, msg, force) + def info(pos: Position, msg: String, force: Boolean): Unit = universe.reporter.info(pos, msg, force) - def hasWarnings: Boolean = mirror.reporter.hasErrors + def hasWarnings: Boolean = universe.reporter.hasErrors - def hasErrors: Boolean = mirror.reporter.hasErrors + def hasErrors: Boolean = universe.reporter.hasErrors def warning(pos: Position, msg: String): Unit = callsiteTyper.context.warning(pos, msg) @@ -37,7 +40,7 @@ trait FrontEnds { throw new AbortMacroException(pos, msg) } - def interactive(): Unit = mirror.reporter match { + def interactive(): Unit = universe.reporter match { case reporter: tools.nsc.reporters.AbstractReporter => reporter.displayPrompt() case _ => () } diff --git a/src/compiler/scala/reflect/makro/runtime/Infrastructure.scala b/src/compiler/scala/reflect/makro/runtime/Infrastructure.scala index 6d8e55cc35..76c4b21731 100644 --- a/src/compiler/scala/reflect/makro/runtime/Infrastructure.scala +++ b/src/compiler/scala/reflect/makro/runtime/Infrastructure.scala @@ -1,26 +1,44 @@ package scala.reflect.makro package runtime +import scala.tools.nsc.util.ScalaClassLoader + trait Infrastructure { self: Context => - val forJVM: Boolean = mirror.forJVM + val forJVM: Boolean = universe.forJVM + + val forMSIL: Boolean = universe.forMSIL + + val forInteractive: Boolean = universe.forInteractive - val forMSIL: Boolean = mirror.forMSIL + val forScaladoc: Boolean = universe.forScaladoc - val forInteractive: Boolean = mirror.forInteractive + val currentRun: Run = universe.currentRun - val forScaladoc: Boolean = mirror.forScaladoc + val libraryClassPath: List[java.net.URL] = universe.classPath.asURLs - val currentRun: Run = mirror.currentRun + lazy val libraryClassLoader: ClassLoader = { + val classpath = libraryClassPath + var loader: ClassLoader = ScalaClassLoader.fromURLs(classpath, self.getClass.getClassLoader) + + // [Eugene] a heuristic to detect REPL + if (universe.settings.exposeEmptyPackage.value) { + import scala.tools.nsc.interpreter._ + val virtualDirectory = universe.settings.outputDirs.getSingleOutput.get + loader = new AbstractFileClassLoader(virtualDirectory, loader) {} + } + + loader + } - type Run = mirror.Run + type Run = universe.Run object Run extends RunExtractor { def unapply(run: Run): Option[(CompilationUnit, List[CompilationUnit])] = Some(run.currentUnit, run.units.toList) } - type CompilationUnit = mirror.CompilationUnit + type CompilationUnit = universe.CompilationUnit object CompilationUnit extends CompilationUnitExtractor { def unapply(compilationUnit: CompilationUnit): Option[(java.io.File, Array[Char], Tree)] = Some(compilationUnit.source.file.file, compilationUnit.source.content, compilationUnit.body) @@ -28,7 +46,7 @@ trait Infrastructure { val currentMacro: Symbol = expandee.symbol - val globalCache: collection.mutable.Map[Any, Any] = mirror.analyzer.globalMacroCache + val globalCache: collection.mutable.Map[Any, Any] = universe.analyzer.globalMacroCache - val cache: collection.mutable.Map[Any, Any] = mirror.analyzer.perRunMacroCache.getOrElseUpdate(currentMacro, collection.mutable.Map[Any, Any]()) + val cache: collection.mutable.Map[Any, Any] = universe.analyzer.perRunMacroCache.getOrElseUpdate(currentMacro, collection.mutable.Map[Any, Any]()) }
\ No newline at end of file diff --git a/src/compiler/scala/reflect/makro/runtime/Mirrors.scala b/src/compiler/scala/reflect/makro/runtime/Mirrors.scala new file mode 100644 index 0000000000..79fa07fdb4 --- /dev/null +++ b/src/compiler/scala/reflect/makro/runtime/Mirrors.scala @@ -0,0 +1,40 @@ +package scala.reflect.makro +package runtime + +import scala.tools.nsc.util.ScalaClassLoader + +trait Mirrors { + self: Context => + + import universe._ + import definitions._ + + class ContextMirror extends RootsBase(NoSymbol) { + val universe: self.universe.type = self.universe + def rootLoader: LazyType = rootMirror.rootLoader + + val RootPackage = rootMirror.RootPackage + val RootClass = rootMirror.RootClass + val EmptyPackage = rootMirror.EmptyPackage + val EmptyPackageClass = rootMirror.EmptyPackageClass + + // [Eugene++] this still doesn't solve the problem of invoking `c.typeCheck` on the code that refers to packageless symbols + override protected def mirrorMissingHook(owner: Symbol, name: Name): Symbol = { + if (owner.isRoot && isJavaClass(name.toString)) EmptyPackageClass.info decl name + else NoSymbol + } + + private def isJavaClass(path: String): Boolean = + try { + val classpath = platform.classPath.asURLs + var classLoader = ScalaClassLoader.fromURLs(classpath) + Class.forName(path, true, classLoader) + true + } catch { + case (_: ClassNotFoundException) | (_: NoClassDefFoundError) | (_: IncompatibleClassChangeError) => + false + } + + override def toString = "macro context mirror" + } +}
\ No newline at end of file diff --git a/src/compiler/scala/reflect/makro/runtime/Names.scala b/src/compiler/scala/reflect/makro/runtime/Names.scala index d8ecc2b89e..3f43b15d90 100644 --- a/src/compiler/scala/reflect/makro/runtime/Names.scala +++ b/src/compiler/scala/reflect/makro/runtime/Names.scala @@ -6,15 +6,12 @@ trait Names { lazy val freshNameCreator = callsiteTyper.context.unit.fresh - def fresh(): String = { + def fresh(): String = freshNameCreator.newName() - } - def fresh(name: String): String = { + def fresh(name: String): String = freshNameCreator.newName(name) - } - def fresh(name: Name): Name = { - name.mapName(freshNameCreator.newName(_)) - } + def fresh[NameType <: Name](name: NameType): NameType = + name.mapName(freshNameCreator.newName(_)).asInstanceOf[NameType] }
\ No newline at end of file diff --git a/src/compiler/scala/reflect/makro/runtime/Parsers.scala b/src/compiler/scala/reflect/makro/runtime/Parsers.scala new file mode 100644 index 0000000000..ac8d09f592 --- /dev/null +++ b/src/compiler/scala/reflect/makro/runtime/Parsers.scala @@ -0,0 +1,25 @@ +package scala.reflect.makro +package runtime + +import language.existentials +import scala.tools.reflect.ToolBox +import scala.tools.reflect.ToolBoxError + +trait Parsers { + self: Context => + + def parse(code: String): Tree = + // todo. provide decent implementation + try { + import scala.reflect.runtime.{universe => ru} + val parsed = ru.rootMirror.mkToolBox().parseExpr(code) + val importer = universe.mkImporter(ru) + importer.importTree(parsed) + } catch { + case ToolBoxError(msg, cause) => + throw new ParseError(universe.NoPosition, msg) + } + + case class ParseError(val pos: Position, val msg: String) extends Throwable(msg) + object ParseError extends ParseErrorExtractor +}
\ No newline at end of file diff --git a/src/compiler/scala/reflect/makro/runtime/Reifiers.scala b/src/compiler/scala/reflect/makro/runtime/Reifiers.scala index 1c5af4b752..10b5ae5f42 100644 --- a/src/compiler/scala/reflect/makro/runtime/Reifiers.scala +++ b/src/compiler/scala/reflect/makro/runtime/Reifiers.scala @@ -9,26 +9,71 @@ package runtime trait Reifiers { self: Context => - import mirror._ + val global: universe.type = universe + import universe._ import definitions._ - lazy val reflectMirrorPrefix: Tree = ReflectMirrorPrefix + lazy val basisUniverse: Tree = gen.mkBasisUniverseRef - def reifyTree(prefix: Tree, tree: Tree): Tree = { - val result = scala.reflect.reify.`package`.reifyTree(mirror)(callsiteTyper, prefix, tree) + lazy val runtimeUniverse: Tree = gen.mkRuntimeUniverseRef + + def reifyTree(universe: Tree, mirror: Tree, tree: Tree): Tree = { + val result = scala.reflect.reify.`package`.reifyTree(self.universe)(callsiteTyper, universe, mirror, tree) logFreeVars(enclosingPosition, result) result } - def reifyType(prefix: Tree, tpe: Type, dontSpliceAtTopLevel: Boolean = false, concrete: Boolean = false): Tree = { - val result = scala.reflect.reify.`package`.reifyType(mirror)(callsiteTyper, prefix, tpe, dontSpliceAtTopLevel, concrete) + def reifyType(universe: Tree, mirror: Tree, tpe: Type, concrete: Boolean = false): Tree = { + val result = scala.reflect.reify.`package`.reifyType(self.universe)(callsiteTyper, universe, mirror, tpe, concrete) logFreeVars(enclosingPosition, result) result } - def reifyErasure(tpe: Type, concrete: Boolean = true): Tree = - scala.reflect.reify.`package`.reifyErasure(mirror)(callsiteTyper, tpe, concrete) + def reifyRuntimeClass(tpe: Type, concrete: Boolean = true): Tree = + scala.reflect.reify.`package`.reifyRuntimeClass(universe)(callsiteTyper, tpe, concrete = concrete) + + def reifyEnclosingRuntimeClass: Tree = + scala.reflect.reify.`package`.reifyEnclosingRuntimeClass(universe)(callsiteTyper) + + def unreifyTree(tree: Tree): Tree = { + assert(ExprSplice != NoSymbol) + Select(tree, ExprSplice) + } + + // fixme: if I put utils here, then "global" from utils' early initialization syntax + // and "global" that comes from here conflict with each other when incrementally compiling + // the problem is that both are pickled with the same owner - trait Reifiers + // and this upsets the compiler, so that oftentimes it throws assertion failures + // Martin knows the details + // + // object utils extends { + // val global: self.global.type = self.global + // val typer: global.analyzer.Typer = self.callsiteTyper + // } with scala.reflect.reify.utils.Utils + // import utils._ + + private def logFreeVars(position: Position, reification: Tree): Unit = { + object utils extends { + val global: self.global.type = self.global + val typer: global.analyzer.Typer = self.callsiteTyper + } with scala.reflect.reify.utils.Utils + import utils._ - def unreifyTree(tree: Tree): Tree = - Select(tree, definitions.ExprEval) + def logFreeVars(symtab: SymbolTable): Unit = + // logging free vars only when they are untyped prevents avalanches of duplicate messages + symtab.syms map (sym => symtab.symDef(sym)) foreach { + case FreeTermDef(_, _, binding, _, origin) if universe.settings.logFreeTerms.value && binding.tpe == null => + reporter.echo(position, "free term: %s %s".format(showRaw(binding), origin)) + case FreeTypeDef(_, _, binding, _, origin) if universe.settings.logFreeTypes.value && binding.tpe == null => + reporter.echo(position, "free type: %s %s".format(showRaw(binding), origin)) + case _ => + // do nothing + } + + if (universe.settings.logFreeTerms.value || universe.settings.logFreeTypes.value) + reification match { + case ReifiedTree(_, _, symtab, _, _, _, _) => logFreeVars(symtab) + case ReifiedType(_, _, symtab, _, _, _) => logFreeVars(symtab) + } + } } diff --git a/src/compiler/scala/reflect/makro/runtime/Settings.scala b/src/compiler/scala/reflect/makro/runtime/Settings.scala index 32f7115db8..8288180b8d 100644 --- a/src/compiler/scala/reflect/makro/runtime/Settings.scala +++ b/src/compiler/scala/reflect/makro/runtime/Settings.scala @@ -5,12 +5,12 @@ trait Settings { self: Context => def settings: List[String] = { - val optionName = mirror.settings.XmacroSettings.name + val optionName = universe.settings.XmacroSettings.name val settings = compilerSettings.find(opt => opt.startsWith(optionName)).map(opt => opt.substring(optionName.length + 1)).getOrElse("") settings.split(",").toList } - def compilerSettings: List[String] = mirror.settings.recreateArgs + def compilerSettings: List[String] = universe.settings.recreateArgs def setCompilerSettings(options: String): this.type = // todo. is not going to work with quoted arguments with embedded whitespaces @@ -19,7 +19,7 @@ trait Settings { def setCompilerSettings(options: List[String]): this.type = { val settings = new tools.nsc.Settings(_ => ()) // [Eugene] what settings should we exclude? - settings.copyInto(mirror.settings) + settings.copyInto(universe.settings) this } diff --git a/src/compiler/scala/reflect/makro/runtime/Symbols.scala b/src/compiler/scala/reflect/makro/runtime/Symbols.scala deleted file mode 100644 index 6341523486..0000000000 --- a/src/compiler/scala/reflect/makro/runtime/Symbols.scala +++ /dev/null @@ -1,10 +0,0 @@ -package scala.reflect.makro -package runtime - -trait Symbols { - self: Context => - - def isLocatable(sym: Symbol) = sym.isLocatable - - def isStatic(sym: Symbol) = sym.isStatic -}
\ No newline at end of file diff --git a/src/compiler/scala/reflect/makro/runtime/Traces.scala b/src/compiler/scala/reflect/makro/runtime/Traces.scala index 6b61842316..225ee1f62b 100644 --- a/src/compiler/scala/reflect/makro/runtime/Traces.scala +++ b/src/compiler/scala/reflect/makro/runtime/Traces.scala @@ -4,5 +4,5 @@ package runtime trait Traces extends util.Traces { self: Context => - def globalSettings = mirror.settings + def globalSettings = universe.settings } diff --git a/src/compiler/scala/reflect/makro/runtime/TypeTags.scala b/src/compiler/scala/reflect/makro/runtime/TypeTags.scala new file mode 100644 index 0000000000..4f9b287674 --- /dev/null +++ b/src/compiler/scala/reflect/makro/runtime/TypeTags.scala @@ -0,0 +1,9 @@ +package scala.reflect.makro +package runtime + +trait TypeTags { + self: Context => + + def AbsTypeTag[T](tpe: Type): AbsTypeTag[T] = universe.AbsTypeTag[T](mirror, universe.FixedMirrorTypeCreator(mirror, tpe)) + def TypeTag[T](tpe: Type): TypeTag[T] = universe.TypeTag[T](mirror, universe.FixedMirrorTypeCreator(mirror, tpe)) +} diff --git a/src/compiler/scala/reflect/makro/runtime/Typers.scala b/src/compiler/scala/reflect/makro/runtime/Typers.scala index 704d3d7ac2..18c1714d15 100644 --- a/src/compiler/scala/reflect/makro/runtime/Typers.scala +++ b/src/compiler/scala/reflect/makro/runtime/Typers.scala @@ -4,11 +4,11 @@ package runtime trait Typers { self: Context => - def openMacros: List[Context] = this :: mirror.analyzer.openMacros + def openMacros: List[Context] = this :: universe.analyzer.openMacros def openImplicits: List[(Type, Tree)] = callsiteTyper.context.openImplicits - def typeCheck(tree: Tree, pt: Type = mirror.WildcardType, silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): Tree = { + def typeCheck(tree: Tree, pt: Type = universe.WildcardType, silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): Tree = { macroLogVerbose("typechecking %s with expected type %s, implicit views = %s, macros = %s".format(tree, pt, !withImplicitViewsDisabled, !withMacrosDisabled)) val wrapper1 = if (!withImplicitViewsDisabled) (callsiteTyper.context.withImplicitsEnabled[Tree] _) else (callsiteTyper.context.withImplicitsDisabled[Tree] _) val wrapper2 = if (!withMacrosDisabled) (callsiteTyper.context.withMacrosEnabled[Tree] _) else (callsiteTyper.context.withMacrosDisabled[Tree] _) @@ -18,28 +18,28 @@ trait Typers { // typechecking uses silent anyways (e.g. in typedSelect), so you'll only waste your time // I'd advise fixing the root cause: finding why the context is not set to report errors // (also see reflect.runtime.ToolBoxes.typeCheckExpr for a workaround that might work for you) - wrapper(callsiteTyper.silent(_.typed(tree, mirror.analyzer.EXPRmode, pt)) match { - case mirror.analyzer.SilentResultValue(result) => + wrapper(callsiteTyper.silent(_.typed(tree, universe.analyzer.EXPRmode, pt)) match { + case universe.analyzer.SilentResultValue(result) => macroLogVerbose(result) result - case error @ mirror.analyzer.SilentTypeError(_) => + case error @ universe.analyzer.SilentTypeError(_) => macroLogVerbose(error.err.errMsg) - if (!silent) throw new mirror.TypeError(error.err.errPos, error.err.errMsg) - mirror.EmptyTree + if (!silent) throw new universe.TypeError(error.err.errPos, error.err.errMsg) + universe.EmptyTree }) } def inferImplicitValue(pt: Type, silent: Boolean = true, withMacrosDisabled: Boolean = false, pos: Position = enclosingPosition): Tree = { macroLogVerbose("inferring implicit value of type %s, macros = %s".format(pt, !withMacrosDisabled)) - import mirror.analyzer.SearchResult + import universe.analyzer.SearchResult val context = callsiteTyper.context val wrapper1 = if (!withMacrosDisabled) (context.withMacrosEnabled[SearchResult] _) else (context.withMacrosDisabled[SearchResult] _) def wrapper (inference: => SearchResult) = wrapper1(inference) - wrapper(mirror.analyzer.inferImplicit(mirror.EmptyTree, pt, true, false, context, !silent, pos)) match { + wrapper(universe.analyzer.inferImplicit(universe.EmptyTree, pt, true, false, context, !silent, pos)) match { case failure if failure.tree.isEmpty => macroLogVerbose("implicit search has failed. to find out the reason, turn on -Xlog-implicits") - if (context.hasErrors) throw new mirror.TypeError(context.errBuffer.head.errPos, context.errBuffer.head.errMsg) - mirror.EmptyTree + if (context.hasErrors) throw new universe.TypeError(context.errBuffer.head.errPos, context.errBuffer.head.errMsg) + universe.EmptyTree case success => success.tree } @@ -47,29 +47,29 @@ trait Typers { def inferImplicitView(tree: Tree, from: Type, to: Type, silent: Boolean = true, withMacrosDisabled: Boolean = false, reportAmbiguous: Boolean = true, pos: Position = enclosingPosition): Tree = { macroLogVerbose("inferring implicit view from %s to %s for %s, macros = %s, reportAmbiguous = %s".format(from, to, tree, !withMacrosDisabled, reportAmbiguous)) - import mirror.analyzer.SearchResult + import universe.analyzer.SearchResult val context = callsiteTyper.context val wrapper1 = if (!withMacrosDisabled) (context.withMacrosEnabled[SearchResult] _) else (context.withMacrosDisabled[SearchResult] _) def wrapper (inference: => SearchResult) = wrapper1(inference) - val fun1 = mirror.definitions.FunctionClass(1) - val viewTpe = mirror.TypeRef(fun1.typeConstructor.prefix, fun1, List(from, to)) - wrapper(mirror.analyzer.inferImplicit(tree, viewTpe, reportAmbiguous, true, context, !silent, pos)) match { + val fun1 = universe.definitions.FunctionClass(1) + val viewTpe = universe.TypeRef(fun1.typeConstructor.prefix, fun1, List(from, to)) + wrapper(universe.analyzer.inferImplicit(tree, viewTpe, reportAmbiguous, true, context, !silent, pos)) match { case failure if failure.tree.isEmpty => macroLogVerbose("implicit search has failed. to find out the reason, turn on -Xlog-implicits") - if (context.hasErrors) throw new mirror.TypeError(context.errBuffer.head.errPos, context.errBuffer.head.errMsg) - mirror.EmptyTree + if (context.hasErrors) throw new universe.TypeError(context.errBuffer.head.errPos, context.errBuffer.head.errMsg) + universe.EmptyTree case success => success.tree } } - type TypeError = mirror.TypeError + type TypeError = universe.TypeError object TypeError extends TypeErrorExtractor { def unapply(error: TypeError): Option[(Position, String)] = Some((error.pos, error.msg)) } - def resetAllAttrs(tree: Tree): Tree = mirror.resetAllAttrs(tree) + def resetAllAttrs(tree: Tree): Tree = universe.resetAllAttrs(tree) - def resetLocalAttrs(tree: Tree): Tree = mirror.resetLocalAttrs(tree) + def resetLocalAttrs(tree: Tree): Tree = universe.resetLocalAttrs(tree) }
\ No newline at end of file diff --git a/src/compiler/scala/reflect/reify/Errors.scala b/src/compiler/scala/reflect/reify/Errors.scala index 4466f281b8..714795503b 100644 --- a/src/compiler/scala/reflect/reify/Errors.scala +++ b/src/compiler/scala/reflect/reify/Errors.scala @@ -1,5 +1,4 @@ -package scala.reflect -package reify +package scala.reflect.reify import scala.reflect.makro.ReificationError import scala.reflect.makro.UnexpectedReificationError @@ -7,10 +6,13 @@ import scala.reflect.makro.UnexpectedReificationError trait Errors { self: Reifier => - import mirror._ + import global._ import definitions._ - def defaultErrorPosition = analyzer.enclosingMacroPosition + def defaultErrorPosition = { + val stack = currents collect { case t: Tree if t.pos != NoPosition => t.pos } + stack.headOption getOrElse analyzer.enclosingMacroPosition + } // expected errors: these can happen if the user casually writes whatever.reify(...) // hence we don't crash here, but nicely report a typechecking error and bail out asap @@ -30,11 +32,28 @@ trait Errors { throw new ReificationError(defaultErrorPosition, msg) } - def CannotReifyConcreteTypeTagHavingUnresolvedTypeParameters(tpe: Type) = { - val msg = "cannot reify ConcreteTypeTag having unresolved type parameter %s".format(tpe) + def CannotReifyTypeTagHavingUnresolvedTypeParameters(tpe: Type) = { + val msg = "cannot reify TypeTag having unresolved type parameter %s".format(tpe) + throw new ReificationError(defaultErrorPosition, msg) + } + + def CannotConvertManifestToTagWithoutScalaReflect(tpe: Type, manifestInScope: Tree) = { + val msg = s""" + |to create a type tag here, it is necessary to interoperate with the manifest `$manifestInScope` in scope. + |however manifest -> typetag conversion requires Scala reflection, which is not present on the classpath. + |to proceed put scala-reflect.jar on your compilation classpath and recompile.""".trim.stripMargin throw new ReificationError(defaultErrorPosition, msg) } + def CannotReifyRuntimeSplice(tree: Tree) = { + val msg = """ + |the splice cannot be resolved statically, which means there is a cross-stage evaluation involved. + |cross-stage evaluations need to be invoked explicitly, so we're showing you this error. + |if you're sure this is not an oversight, add scala-compiler.jar to the classpath, + |import `scala.tools.reflect.Eval` and call `<your expr>.eval` instead.""".trim.stripMargin + throw new ReificationError(tree.pos, msg) + } + // unexpected errors: these can never happen under normal conditions unless there's a bug in the compiler (or in a compiler plugin or in a macro) // hence, we fail fast and loudly and don't care about being nice - in this situation noone will appreciate our quiet nicety diff --git a/src/compiler/scala/reflect/reify/NodePrinters.scala b/src/compiler/scala/reflect/reify/NodePrinters.scala deleted file mode 100644 index eaca9a4968..0000000000 --- a/src/compiler/scala/reflect/reify/NodePrinters.scala +++ /dev/null @@ -1,111 +0,0 @@ -/* NSC -- new Scala compiler - * Copyright 2005-2011 LAMP/EPFL - * @author Martin Odersky - */ - -package scala.reflect -package reify - -import scala.Array.canBuildFrom -import scala.compat.Platform.EOL -import scala.tools.nsc.symtab.Flags -import scala.tools.nsc.Global - -trait NodePrinters { self: scala.tools.nsc.ast.NodePrinters => - - val global: Global - import global._ - - object reifiedNodeToString extends Function2[Tree, Tree, String] { - def apply(prefix: Tree, tree: Tree): String = { - import scala.reflect.api.Modifier - var modifierIsUsed = false - var flagsAreUsed = false - - // @PP: I fervently hope this is a test case or something, not anything being - // depended upon. Of more fragile code I cannot conceive. - // @Eugene: This stuff is only needed to debug-print out reifications in human-readable format - // Rolling a full-fledged, robust TreePrinter would be several times more code. - val (List(mirror), reified) = (for (line <- (tree.toString.split(EOL).toList drop 1 dropRight 1)) yield { - var s = line.trim - s = s.replace("$mr.", "") - s = s.replace(".apply", "") - s = s.replace("scala.collection.immutable.", "") - s = "List\\[List\\[.*?\\].*?\\]".r.replaceAllIn(s, "List") - s = "List\\[.*?\\]".r.replaceAllIn(s, "List") - s = s.replace("immutable.this.Nil", "List()") - s = s.replace("modifiersFromInternalFlags", "Modifiers") - s = s.replace("Modifiers(0L, newTypeName(\"\"), List())", "Modifiers()") - s = """Modifiers\((\d+)[lL], newTypeName\("(.*?)"\), List\((.*?)\)\)""".r.replaceAllIn(s, m => { - val buf = new collection.mutable.ListBuffer[String] - - val annotations = m.group(3) - if (buf.nonEmpty || annotations.nonEmpty) - buf.append("List(" + annotations + ")") - - val privateWithin = "" + m.group(2) - if (buf.nonEmpty || privateWithin != "") - buf.append("newTypeName(\"" + privateWithin + "\")") - - val flags = m.group(1).toLong - val s_flags = Flags.modifiersOfFlags(flags) map (_.sourceString) mkString ", " - if (buf.nonEmpty || s_flags != "") { - modifierIsUsed = true - buf.append("Set(" + s_flags + ")") - } - - "Modifiers(" + buf.reverse.mkString(", ") + ")" - }) - s = """setInternalFlags\((\d+)L\)""".r.replaceAllIn(s, m => { - flagsAreUsed = true - val flags = m.group(1).toLong - val mods = Flags.modifiersOfFlags(flags) map (_.sourceString) - "setInternalFlags(flagsOfModifiers(List(" + mods.mkString(", ") + ")))" - }) - - s - }) splitAt 1 - - val printout = collection.mutable.ListBuffer(mirror); - printout += "import " + nme.MIRROR_SHORT + "._" - if (modifierIsUsed) printout += "import scala.reflect.api.Modifier._" - if (flagsAreUsed) printout += "import scala.reflect.internal.Flags._" - val body = reified dropWhile (_.startsWith("val")) - if (body.length > 0 && body(0).startsWith("Expr[")) { - if (reified(0) startsWith "val") { - printout += "val code = {" - printout ++= (reified map (" " + _)) - printout += "}" - printout += "mkToolBox().runExpr(code)" - } else { - printout += "val code = " + reified(0) - printout ++= reified drop 1 - printout += "mkToolBox().runExpr(code)" - } - try { - val prefix = Select(Select(Ident(definitions.ScalaPackage), newTermName("reflect")), newTermName("mirror")) - val tree1 = new global.Transformer { - override def transform(tree: Tree) = super.transform(tree match { - case Block(ValDef(_, mr, _, _) :: Nil, expr) if mr == nme.MIRROR_SHORT => transform(expr) - case Block(ValDef(_, mr, _, _) :: symbolTable, expr) if mr == nme.MIRROR_SHORT => transform(Block(symbolTable, expr)) - case Select(Ident(mr), name) if mr == nme.MIRROR_SHORT => Select(prefix, name) - case tree => tree - }) - }.transform(tree) - val stringified = mkToolBox().runExpr(tree1).toString - if (settings.Yreifydebug.value) printout += "*****************************" - printout += stringified - } catch { - case ex: Throwable => -// val realex = ReflectionUtils.unwrapThrowable(ex) -// val message = new java.io.StringWriter() -// realex.printStackTrace(new java.io.PrintWriter(message)) -// println(message) - } - } else { - printout ++= reified - } - printout mkString EOL - } - } -}
\ No newline at end of file diff --git a/src/compiler/scala/reflect/reify/Phases.scala b/src/compiler/scala/reflect/reify/Phases.scala index 49d5a45e8e..1710cae2a5 100644 --- a/src/compiler/scala/reflect/reify/Phases.scala +++ b/src/compiler/scala/reflect/reify/Phases.scala @@ -1,16 +1,15 @@ -package scala.reflect -package reify +package scala.reflect.reify -import scala.reflect.reify.phases._ +import phases._ -trait Phases extends Calculate - with Reshape +trait Phases extends Reshape + with Calculate with Metalevels with Reify { self: Reifier => - import mirror._ + import global._ import definitions._ private var alreadyRun = false @@ -26,16 +25,19 @@ trait Phases extends Calculate if (reifyDebug) println("[reshape phase]") tree = reshape.transform(tree) + if (reifyDebug) println("[interlude]") + if (reifyDebug) println("reifee = " + (if (opt.showTrees) "\n" + nodePrinters.nodeToString(tree).trim else tree.toString)) + + if (reifyDebug) println("[calculate phase]") + calculate.traverse(tree) if (reifyDebug) println("[metalevels phase]") tree = metalevels.transform(tree) - if (reifyDebug) println("[interlude]") - if (reifyDebug) println("symbol table = " + (if (symbolTable.length == 0) "<empty>" else "")) - if (reifyDebug) symbolTable foreach (println(_)) - if (reifyDebug) println("reifee = " + (if (opt.showTrees) "\n" + nodePrinters.nodeToString(tree).trim else tree.toString)) + if (reifyDebug) println(symtab.debugString) + if (reifyDebug) println("[reify phase]") - var result = reify(tree) + val result = reify(tree) result } diff --git a/src/compiler/scala/reflect/reify/Reifier.scala b/src/compiler/scala/reflect/reify/Reifier.scala index fea825358e..00f25f0d8b 100644 --- a/src/compiler/scala/reflect/reify/Reifier.scala +++ b/src/compiler/scala/reflect/reify/Reifier.scala @@ -1,9 +1,9 @@ -package scala.reflect -package reify +package scala.reflect.reify import scala.tools.nsc.Global import scala.reflect.makro.ReificationError import scala.reflect.makro.UnexpectedReificationError +import scala.reflect.reify.utils.Utils /** Given a tree or a type, generate a tree that when executed at runtime produces the original tree or type. * See more info in the comments to ``reify'' in scala.reflect.api.Universe. @@ -11,51 +11,59 @@ import scala.reflect.makro.UnexpectedReificationError * @author Martin Odersky * @version 2.10 */ -abstract class Reifier extends Phases - with Errors { +abstract class Reifier extends States + with Phases + with Errors + with Utils { - val mirror: Global - import mirror._ + val global: Global + import global._ import definitions._ - import treeInfo._ - val typer: mirror.analyzer.Typer - val prefix: Tree + val typer: global.analyzer.Typer + val universe: Tree + val mirror: Tree val reifee: Any - val dontSpliceAtTopLevel: Boolean val concrete: Boolean + // needed to seamlessly integrate with standalone utils + override def getReifier: Reifier { val global: Reifier.this.global.type } = + this.asInstanceOf[Reifier { val global: Reifier.this.global.type }] + override def hasReifier = true + /** * For ``reifee'' and other reification parameters, generate a tree of the form * * { - * val $mr = <[ prefix ]> - * $mr.Expr[T](rtree) // if data is a Tree - * $mr.TypeTag[T](rtree) // if data is a Type + * val $u: universe.type = <[ universe ]> + * val $m: $u.Mirror = <[ mirror ]> + * $u.Expr[T](rtree) // if data is a Tree + * $u.TypeTag[T](rtree) // if data is a Type * } * * where * - * - `prefix` is the tree that represents the universe - * the result will be bound to + * - `universe` is the tree that represents the universe the result will be bound to + * - `mirror` is the tree that represents the mirror the result will be initially bound to * - `rtree` is code that generates `reifee` at runtime. * - `T` is the type that corresponds to `data`. * * This is not a method, but a value to indicate the fact that Reifier instances are a one-off. */ - lazy val reified: Tree = { + lazy val reification: Tree = { try { // [Eugene] conventional way of doing this? - if (prefix exists (_.isErroneous)) CannotReifyErroneousPrefix(prefix) - if (prefix.tpe == null) CannotReifyUntypedPrefix(prefix) + if (universe exists (_.isErroneous)) CannotReifyErroneousPrefix(universe) + if (universe.tpe == null) CannotReifyUntypedPrefix(universe) - val rtree = reifee match { + val result = reifee match { case tree: Tree => reifyTrace("reifying = ")(if (opt.showTrees) "\n" + nodePrinters.nodeToString(tree).trim else tree.toString) reifyTrace("reifee is located at: ")(tree.pos) - reifyTrace("prefix = ")(prefix) + reifyTrace("universe = ")(universe) + reifyTrace("mirror = ")(mirror) // [Eugene] conventional way of doing this? - if (tree exists (_.isErroneous)) CannotReifyErroneousReifee(prefix) + if (tree exists (_.isErroneous)) CannotReifyErroneousReifee(tree) if (tree.tpe == null) CannotReifyUntypedReifee(tree) val pipeline = mkReificationPipeline val rtree = pipeline(tree) @@ -74,31 +82,23 @@ abstract class Reifier extends Phases if (tree.tpe exists (sub => sub.typeSymbol.isLocalToReifee)) CannotReifyReifeeThatHasTypeLocalToReifee(tree) - val taggedType = typer.packedType(tree, NoSymbol) - val tagModule = if (reificationIsConcrete) ConcreteTypeTagModule else TypeTagModule - val tagCtor = TypeApply(Select(Ident(nme.MIRROR_SHORT), tagModule.name), List(TypeTree(taggedType))) - val exprCtor = TypeApply(Select(Ident(nme.MIRROR_SHORT), ExprModule.name), List(TypeTree(taggedType))) - val tagArgs = List(reify(taggedType), reifyErasure(mirror)(typer, taggedType, concrete = false)) - Apply(Apply(exprCtor, List(rtree)), List(Apply(tagCtor, tagArgs))) + val tpe = typer.packedType(tree, NoSymbol) + val ReifiedType(_, _, tpeSymtab, _, rtpe, tpeReificationIsConcrete) = `package`.reifyType(global)(typer, universe, mirror, tpe, concrete = false) + state.reificationIsConcrete &= tpeReificationIsConcrete + state.symtab ++= tpeSymtab + ReifiedTree(universe, mirror, symtab, rtree, tpe, rtpe, reificationIsConcrete) case tpe: Type => reifyTrace("reifying = ")(tpe.toString) - reifyTrace("prefix = ")(prefix) + reifyTrace("universe = ")(universe) + reifyTrace("mirror = ")(mirror) val rtree = reify(tpe) - - val taggedType = tpe - val tagModule = if (reificationIsConcrete) ConcreteTypeTagModule else TypeTagModule - val ctor = TypeApply(Select(Ident(nme.MIRROR_SHORT), tagModule.name), List(TypeTree(taggedType))) - val args = List(rtree, reifyErasure(mirror)(typer, taggedType, concrete = false)) - Apply(ctor, args) + ReifiedType(universe, mirror, symtab, tpe, rtree, reificationIsConcrete) case _ => throw new Error("reifee %s of type %s is not supported".format(reifee, if (reifee == null) "null" else reifee.getClass.toString)) } - val mirrorAlias = ValDef(NoMods, nme.MIRROR_SHORT, SingletonTypeTree(prefix), prefix) - val wrapped = Block(mirrorAlias :: symbolTable, rtree) - // todo. why do we resetAllAttrs? // // typically we do some preprocessing before reification and @@ -107,14 +107,14 @@ abstract class Reifier extends Phases // // ===example 1=== // we move a freevar from a nested symbol table to a top-level symbol table, - // and then the reference to mr$ becomes screwed up, because nested symbol tables are already typechecked, - // so we have an mr$ symbol that points to the nested mr$ rather than to the top-level one. + // and then the reference to $u becomes screwed up, because nested symbol tables are already typechecked, + // so we have an $u symbol that points to the nested $u rather than to the top-level one. // // ===example 2=== - // we inline a freevar by replacing a reference to it, e.g. $mr.Apply($mr.Select($mr.Ident($mr.newTermName("$mr")), $mr.newTermName("Ident")), List($mr.Ident($mr.newTermName("free$x")))) - // with its original binding (e.g. $mr.Ident("x")) - // we'd love to typecheck the result, but we cannot do this easily, because $mr is external to this tree - // what's even worse, sometimes $mr can point to the top-level symbol table's $mr, which doesn't have any symbol/type yet - + // we inline a freevar by replacing a reference to it, e.g. $u.Apply($u.Select($u.Ident($u.newTermName("$u")), $u.newTermName("Ident")), List($u.Ident($u.newTermName("free$x")))) + // with its original binding (e.g. $u.Ident("x")) + // we'd love to typecheck the result, but we cannot do this easily, because $u is external to this tree + // what's even worse, sometimes $u can point to the top-level symbol table's $u, which doesn't have any symbol/type yet - // it's just a ValDef that will be emitted only after the reification is completed // // hence, the simplest solution is to erase all attrs so that invalid (as well as non-existent) bindings get rebound correctly @@ -124,31 +124,30 @@ abstract class Reifier extends Phases // needs to be solved some day // // list of non-hygienic transformations: - // 1) local freetype inlining in Nested - // 2) external freevar moving in Nested - // 3) local freeterm inlining in Metalevels - // 4) trivial tree splice inlining in Reify (Trees.scala) - // 5) trivial type splice inlining in Reify (Types.scala) - val freevarBindings = symbolTable collect { case entry @ FreeDef(_, _, binding, _, _) => binding.symbol } toSet - // [Eugene] yeah, ugly and extremely brittle, but we do need to do resetAttrs. will be fixed later - var importantSymbols = Set[Symbol](PredefModule, ScalaRunTimeModule) + // todo. to be updated + // [Eugene++] yeah, ugly and extremely brittle, but we do need to do resetAttrs. will be fixed later + // todo. maybe try `resetLocalAttrs` once the dust settles + var importantSymbols = Set[Symbol]( + NothingClass, AnyClass, SingletonClass, PredefModule, ScalaRunTimeModule, TypeCreatorClass, TreeCreatorClass, MirrorOfClass, + BaseUniverseClass, ApiUniverseClass, JavaUniverseClass, ReflectRuntimePackage, ReflectRuntimeCurrentMirror) importantSymbols ++= importantSymbols map (_.companionSymbol) importantSymbols ++= importantSymbols map (_.moduleClass) importantSymbols ++= importantSymbols map (_.linkedClassOfClass) - def importantSymbol(sym: Symbol): Boolean = sym != null && sym != NoSymbol && importantSymbols(sym) - val untyped = resetAllAttrs(wrapped, leaveAlone = { - case ValDef(_, mr, _, _) if mr == nme.MIRROR_SHORT => true - case tree if freevarBindings contains tree.symbol => true - case tree if importantSymbol(tree.symbol) => true + def isImportantSymbol(sym: Symbol): Boolean = sym != null && sym != NoSymbol && importantSymbols(sym) + val untyped = resetAllAttrs(result, leaveAlone = { + case ValDef(_, u, _, _) if u == nme.UNIVERSE_SHORT => true + case ValDef(_, m, _, _) if m == nme.MIRROR_SHORT => true + case tree if symtab.syms contains tree.symbol => true + case tree if isImportantSymbol(tree.symbol) => true case _ => false }) if (reifyCopypaste) { if (reifyDebug) println("=============================") - println(reifiedNodeToString(prefix, untyped)) + println(reifiedNodeToString(untyped)) if (reifyDebug) println("=============================") } else { - reifyTrace("reified = ")(untyped) + reifyTrace("reification = ")(untyped) } untyped diff --git a/src/compiler/scala/reflect/reify/States.scala b/src/compiler/scala/reflect/reify/States.scala new file mode 100644 index 0000000000..a01cfe5d74 --- /dev/null +++ b/src/compiler/scala/reflect/reify/States.scala @@ -0,0 +1,65 @@ +package scala.reflect.reify + +trait States { + self: Reifier => + + import global._ + import definitions._ + + /** Encapsulates reifier state + * + * When untangling reifier symbol tables from the reifier itself, + * I discovered that encoding of a symbol table (e.g. producing corresponding reificode) + * might cause subsequent reification (e.g. when filling in signatures and annotations for syms). + * + * This is a mess in the face of nested reifications, splices and inlining of thereof, + * so I made `SymbolTable` immutable, which brought a significant amount of sanity. + * + * However that wasn't enough. Sure, symbol table became immutable, but the reifier still needed + * to mutate its `symtab` field during reification. This caused nasty desyncs between the table being encoded + * and the table of the underlying reifier, so I decided to encapsulate the entire state here, + * so that encoding can backup the state before it starts and restore it after it completes. + */ + val state = new State + + // todo. rewrite the reifier so that we don't need mutable state anymore + // to aid you with that I've already removed all the setters from the reifier + // so all the places that involve mutations are forced to do that by explicitly mentioning `state` + class State { + var symtab = SymbolTable() + var reifyTreeSymbols = false + var reifyTreeTypes = false + private var _reificationIsConcrete = true + def reificationIsConcrete: Boolean = _reificationIsConcrete + def reificationIsConcrete_=(value: Boolean): Unit = { + _reificationIsConcrete = value + if (!value && concrete) { + assert(current.isInstanceOf[Type], current) + val offender = current.asInstanceOf[Type] + CannotReifyTypeTagHavingUnresolvedTypeParameters(offender) + } + } + var reifyStack = reifee :: Nil + var localSymbols = Map[Symbol, Int]() + + def backup: State = { + val backup = new State + backup.symtab = this.symtab + backup.reifyTreeSymbols = this.reifyTreeSymbols + backup.reifyTreeTypes = this.reifyTreeTypes + backup._reificationIsConcrete = this._reificationIsConcrete + backup.reifyStack = this.reifyStack + backup.localSymbols = this.localSymbols + backup + } + + def restore(backup: State): Unit = { + this.symtab = backup.symtab + this.reifyTreeSymbols = backup.reifyTreeSymbols + this.reifyTreeTypes = backup.reifyTreeTypes + this._reificationIsConcrete = backup._reificationIsConcrete + this.reifyStack = backup.reifyStack + this.localSymbols = backup.localSymbols + } + } +} diff --git a/src/compiler/scala/reflect/reify/Taggers.scala b/src/compiler/scala/reflect/reify/Taggers.scala new file mode 100644 index 0000000000..b70c3f44a3 --- /dev/null +++ b/src/compiler/scala/reflect/reify/Taggers.scala @@ -0,0 +1,103 @@ +package scala.reflect.reify + +import scala.reflect.makro.{ReificationError, UnexpectedReificationError} +import scala.reflect.makro.runtime.Context + +abstract class Taggers { + val c: Context + + import c.universe._ + import definitions._ + import treeBuild._ + + val coreTags = Map( + ByteClass.asType -> nme.Byte, + ShortClass.asType -> nme.Short, + CharClass.asType -> nme.Char, + IntClass.asType -> nme.Int, + LongClass.asType -> nme.Long, + FloatClass.asType -> nme.Float, + DoubleClass.asType -> nme.Double, + BooleanClass.asType -> nme.Boolean, + UnitClass.asType -> nme.Unit, + AnyClass.asType -> nme.Any, + ObjectClass.asType -> nme.Object, + NothingClass.asType -> nme.Nothing, + NullClass.asType -> nme.Null, + StringClass.asType -> nme.String) + + def materializeClassTag(prefix: Tree, tpe: Type): Tree = { + val tagModule = ClassTagModule + materializeTag(prefix, tpe, tagModule, { + val erasure = c.reifyRuntimeClass(tpe, concrete = true) + val factory = TypeApply(Select(Ident(tagModule), nme.apply), List(TypeTree(tpe))) + Apply(factory, List(erasure)) + }) + } + + def materializeTypeTag(universe: Tree, mirror: Tree, tpe: Type, concrete: Boolean): Tree = { + if (universe.symbol == MacroContextUniverse && mirror == EmptyTree) { + import scala.reflect.makro.runtime.ContextReifiers + import language.implicitConversions + implicit def context2contextreifiers(c0: Context) : ContextReifiers { val c: c0.type } = new { val c: c0.type = c0 } with ContextReifiers + val Select(prefix, _) = universe + c.materializeTypeTagForMacroContext(prefix, tpe, concrete) + } else { + val tagType = if (concrete) TypeTagClass else AbsTypeTagClass + val unaffiliatedTagTpe = TypeRef(BaseUniverseClass.asTypeConstructor, tagType, List(tpe)) + val unaffiliatedTag = c.inferImplicitValue(unaffiliatedTagTpe, silent = true, withMacrosDisabled = true) + unaffiliatedTag match { + case success if !success.isEmpty => + Apply(Select(success, nme.in), List(mirror orElse mkDefaultMirrorRef(c.universe)(universe, c.callsiteTyper))) + case _ => + val tagModule = if (concrete) TypeTagModule else AbsTypeTagModule + materializeTag(universe, tpe, tagModule, c.reifyType(universe, mirror, tpe, concrete = concrete)) + } + } + } + + private def materializeTag(prefix: Tree, tpe: Type, tagModule: Symbol, materializer: => Tree): Tree = { + val result = + tpe match { + case coreTpe if coreTags contains coreTpe => + val ref = if (tagModule.owner.isPackageClass) Ident(tagModule) else Select(prefix, tagModule.name) + Select(ref, coreTags(coreTpe)) + case _ => + translatingReificationErrors(materializer) + } + try c.typeCheck(result) + catch { case terr @ c.TypeError(pos, msg) => failTag(result, terr) } + } + + def materializeExpr(universe: Tree, mirror: Tree, expr: Tree): Tree = { + val result = translatingReificationErrors(c.reifyTree(universe, mirror, expr)) + try c.typeCheck(result) + catch { case terr @ c.TypeError(pos, msg) => failExpr(result, terr) } + } + + private def translatingReificationErrors(materializer: => Tree): Tree = { + try materializer + catch { + case ReificationError(pos, msg) => + c.error(pos.asInstanceOf[c.Position], msg) // this cast is a very small price for the sanity of exception handling + EmptyTree + case UnexpectedReificationError(pos, err, cause) if cause != null => + throw cause + } + } + + private def failTag(result: Tree, reason: Any): Nothing = { + val Apply(TypeApply(fun, List(tpeTree)), _) = c.macroApplication + val tpe = tpeTree.tpe + val PolyType(_, MethodType(_, tagTpe)) = fun.tpe + val tagModule = tagTpe.typeSymbol.companionSymbol + if (c.compilerSettings.contains("-Xlog-implicits")) + c.echo(c.enclosingPosition, s"cannot materialize ${tagModule.name}[$tpe] as $result because:\n$reason") + c.abort(c.enclosingPosition, "No %s available for %s".format(tagModule.name, tpe)) + } + + private def failExpr(result: Tree, reason: Any): Nothing = { + val Apply(_, expr :: Nil) = c.macroApplication + c.abort(c.enclosingPosition, s"Cannot materialize $expr as $result because:\n$reason") + } +} diff --git a/src/compiler/scala/reflect/reify/codegen/AnnotationInfos.scala b/src/compiler/scala/reflect/reify/codegen/GenAnnotationInfos.scala index 1d218317dc..5f4296f54f 100644 --- a/src/compiler/scala/reflect/reify/codegen/AnnotationInfos.scala +++ b/src/compiler/scala/reflect/reify/codegen/GenAnnotationInfos.scala @@ -1,12 +1,11 @@ package scala.reflect.reify package codegen -trait AnnotationInfos { +trait GenAnnotationInfos { self: Reifier => - import mirror._ + import global._ import definitions._ - import treeInfo._ // usually annotations are reified as their originals from Modifiers // however, when reifying free and tough types, we're forced to reify annotation infos as is @@ -26,8 +25,8 @@ trait AnnotationInfos { // reflective typechecker will fill in missing symbols and types, right? // A: actually, no. annotation ASTs live inside AnnotatedTypes, // and insides of the types is the place where typechecker doesn't look. - reifyTreeSymbols = true - reifyTreeTypes = true + state.reifyTreeSymbols = true + state.reifyTreeTypes = true // todo. every AnnotationInfo is an island, entire of itself // no regular Traverser or Transformer can reach it @@ -35,8 +34,8 @@ trait AnnotationInfos { // e.g. to apply reshaping or to check metalevels reify(arg) } finally { - reifyTreeSymbols = saved1 - reifyTreeTypes = saved2 + state.reifyTreeSymbols = saved1 + state.reifyTreeTypes = saved2 } } diff --git a/src/compiler/scala/reflect/reify/codegen/Names.scala b/src/compiler/scala/reflect/reify/codegen/GenNames.scala index 589f6355d0..4abf88f475 100644 --- a/src/compiler/scala/reflect/reify/codegen/Names.scala +++ b/src/compiler/scala/reflect/reify/codegen/GenNames.scala @@ -1,12 +1,11 @@ package scala.reflect.reify package codegen -trait Names { +trait GenNames { self: Reifier => - import mirror._ + import global._ import definitions._ - import treeInfo._ def reifyName(name: Name) = { val factory = if (name.isTypeName) nme.nmeNewTypeName else nme.nmeNewTermName diff --git a/src/compiler/scala/reflect/reify/codegen/Positions.scala b/src/compiler/scala/reflect/reify/codegen/GenPositions.scala index ac9195ef31..8c5db04454 100644 --- a/src/compiler/scala/reflect/reify/codegen/Positions.scala +++ b/src/compiler/scala/reflect/reify/codegen/GenPositions.scala @@ -1,12 +1,11 @@ package scala.reflect.reify package codegen -trait Positions { +trait GenPositions { self: Reifier => - import mirror._ + import global._ import definitions._ - import treeInfo._ // we do not reify positions because this inflates resulting trees, but doesn't buy as anything // where would one use positions? right, in error messages diff --git a/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala b/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala new file mode 100644 index 0000000000..3a98d308a7 --- /dev/null +++ b/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala @@ -0,0 +1,109 @@ +package scala.reflect.reify +package codegen + +trait GenSymbols { + self: Reifier => + + import global._ + import definitions._ + + /** Symbol table of the reifee. + * + * Keeps track of auxiliary symbols that are necessary for this reification session. + * These include: + * 1) Free vars (terms, types and existentials), + * 2) Non-locatable symbols (sometimes, e.g. for RefinedTypes, we need to reify these; to do that we create their local copies in the reificode) + * 3) Non-locatable symbols that are referred by #1, #2 and #3 + * + * Exposes three main methods: + * 1) `syms` that lists symbols belonging to the table, + * 2) `symXXX` family of methods that provide information about the symbols in the table, + * 3) `encode` that renders the table into a list of trees (recursively populating #3 and setting up initialization code for #1, #2 and #3) + */ + def symtab: SymbolTable = state.symtab + + /** Reify a reference to a symbol */ + def reifySymRef(sym0: Symbol): Tree = { + assert(sym0 != null, "sym is null") + val sym = sym0.dealias + + if (sym == NoSymbol) + mirrorSelect(nme.NoSymbol) + else if (sym.isRootPackage) + mirrorMirrorSelect(nme.RootPackage) + else if (sym.isRoot) + mirrorMirrorSelect(nme.RootClass) + else if (sym.isEmptyPackage) + mirrorMirrorSelect(nme.EmptyPackage) + else if (sym.isEmptyPackageClass) + mirrorMirrorSelect(nme.EmptyPackageClass) + else if (sym.isModuleClass) + Select(Select(reify(sym.sourceModule), nme.asModuleSymbol), nme.moduleClass) + else if (sym.isLocatable) { + // [Eugene] am I doing this right? +// if (sym.isStaticOwner) { // no good for us, because it returns false for packages + if (sym.isStatic && (sym.isClass || sym.isModule)) { + val resolver = if (sym.isType) nme.staticClass else nme.staticModule + mirrorMirrorCall(resolver, reify(sym.fullName)) + } else { + if (reifyDebug) println("Locatable: %s (%s) owned by %s (%s) at %s".format(sym, sym.accurateKindString, sym.owner, sym.owner.accurateKindString, sym.owner.fullNameString)) + val rowner = reify(sym.owner) + val rname = reify(sym.name.toString) + if (sym.isType) + mirrorBuildCall(nme.selectType, rowner, rname) + else if (sym.isMethod && sym.owner.isClass && sym.owner.info.decl(sym.name).isOverloaded) { + val index = sym.owner.info.decl(sym.name).alternatives indexOf sym + assert(index >= 0, sym) + mirrorBuildCall(nme.selectOverloadedMethod, rowner, rname, reify(index)) + } else + mirrorBuildCall(nme.selectTerm, rowner, rname) + } + } else { + // todo. make sure that free methods and free local defs work correctly + if (sym.isTerm) reifyFreeTerm(sym, Ident(sym)) + else reifyFreeType(sym, Ident(sym)) + } + } + + def reifyFreeTerm(sym: Symbol, value: Tree): Tree = + reifyIntoSymtab(sym) { + if (reifyDebug) println("Free term" + (if (sym.isCapturedVariable) " (captured)" else "") + ": " + sym + "(" + sym.accurateKindString + ")") + var name = newTermName(nme.REIFY_FREE_PREFIX + sym.name) + if (sym.isType) name = name.append(nme.REIFY_FREE_THIS_SUFFIX) + if (sym.isCapturedVariable) { + assert(value.isInstanceOf[Ident], showRaw(value)) + val capturedTpe = capturedVariableType(sym) + val capturedValue = referenceCapturedVariable(sym) + (name, mirrorBuildCall(nme.newFreeTerm, reify(sym.name.toString), reify(capturedTpe), capturedValue, mirrorBuildCall(nme.flagsFromBits, reify(sym.flags)), reify(origin(sym)))) + } else { + (name, mirrorBuildCall(nme.newFreeTerm, reify(sym.name.toString), reify(sym.tpe), value, mirrorBuildCall(nme.flagsFromBits, reify(sym.flags)), reify(origin(sym)))) + } + } + + def reifyFreeType(sym: Symbol, value: Tree): Tree = + reifyIntoSymtab(sym) { + if (reifyDebug) println("Free type: %s (%s)".format(sym, sym.accurateKindString)) + var name = newTermName(nme.REIFY_FREE_PREFIX + sym.name) + val phantomTypeTag = Apply(TypeApply(Select(Ident(nme.UNIVERSE_SHORT), nme.TypeTag), List(value)), List(Literal(Constant(null)), Literal(Constant(null)))) + val flavor = if (sym.isExistential) nme.newFreeExistential else nme.newFreeType + (name, mirrorBuildCall(flavor, reify(sym.name.toString), reify(sym.info), phantomTypeTag, mirrorBuildCall(nme.flagsFromBits, reify(sym.flags)), reify(origin(sym)))) + } + + def reifySymDef(sym: Symbol): Tree = + reifyIntoSymtab(sym) { + if (reifyDebug) println("Sym def: %s (%s)".format(sym, sym.accurateKindString)) + assert(!sym.isLocatable, sym) // if this assertion fires, then tough type reification needs to be rethought + sym.owner.ownersIterator find (!_.isLocatable) foreach reifySymDef + var name = newTermName(nme.REIFY_SYMDEF_PREFIX + sym.name) + (name, mirrorBuildCall(nme.newNestedSymbol, reify(sym.owner), reify(sym.name), reify(sym.pos), mirrorBuildCall(nme.flagsFromBits, reify(sym.flags)), reify(sym.isClass))) + } + + private def reifyIntoSymtab(sym: Symbol)(reificode: => (TermName, Tree)): Tree ={ + def fromSymtab = symtab symRef sym + if (fromSymtab == EmptyTree) { + val reification = reificode + state.symtab += (sym, reification._1, reification._2) + } + fromSymtab + } +} diff --git a/src/compiler/scala/reflect/reify/codegen/Trees.scala b/src/compiler/scala/reflect/reify/codegen/GenTrees.scala index c9f5fc5b8d..b97bf6b0cd 100644 --- a/src/compiler/scala/reflect/reify/codegen/Trees.scala +++ b/src/compiler/scala/reflect/reify/codegen/GenTrees.scala @@ -1,18 +1,17 @@ package scala.reflect.reify package codegen -trait Trees { +trait GenTrees { self: Reifier => - import mirror._ + import global._ import definitions._ - import treeInfo._ - import scala.reflect.api.Modifier // unfortunately, these are necessary to reify AnnotatedTypes - // I'd gladly got rid of them, but I don't fancy making a metaprogramming API that doesn't work with annotated types - var reifyTreeSymbols = false - var reifyTreeTypes = false + // I'd gladly get rid of them, but I don't fancy making a metaprogramming API that doesn't work with annotated types + // luckily for our sanity, these vars are mutated only within a very restricted code execution path + def reifyTreeSymbols: Boolean = state.reifyTreeSymbols + def reifyTreeTypes: Boolean = state.reifyTreeTypes /** * Reify a tree. @@ -43,10 +42,10 @@ trait Trees { // the second prototype reified external types, but avoided reifying local ones => this created an ugly irregularity // current approach is uniform and compact var rtree = tree match { - case mirror.EmptyTree => + case global.EmptyTree => reifyMirrorObject(EmptyTree) - case mirror.emptyValDef => - mirrorSelect(nme.emptyValDef) + case global.emptyValDef => + mirrorBuildSelect(nme.emptyValDef) case FreeDef(_, _, _, _, _) => reifyNestedFreeDef(tree) case FreeRef(_, _) => @@ -55,31 +54,7 @@ trait Trees { reifyBoundTerm(tree) case BoundType(tree) => reifyBoundType(tree) - case NestedExpr(_, _, _) => - reifyNestedExpr(tree) case Literal(const @ Constant(_)) => - // [Eugene] was necessary when we reified erasures as normalized tycons - // now, when we do existentialAbstraction on normalizations, everything works great - // todo. find an explanation -// if (const.tag == ClazzTag) { -//// def preprocess(tpe: Type): Type = tpe.typeSymbol match { -//// case ArrayClass => appliedType(ArrayClass, preprocess(tpe.typeArgs.head)) -//// case _ => tpe.typeConstructor -//// } -//// val tpe = preprocess(const.typeValue) -// val tpe = const.typeValue -// var reified = reify(tpe) -// reified = mirrorCall(nme.Literal, mirrorCall(nme.Constant, reified)) -//// val skolems = ClassClass.typeParams map (_ => newTypeName(typer.context.unit.fresh.newName("_$"))) -//// var existential = mirrorCall(nme.AppliedTypeTree, mirrorCall(nme.TypeTree, reify(ClassClass.typeConstructor)), mkList(skolems map (skolem => mirrorCall(nme.Ident, reify(skolem))))) -//// existential = mirrorCall(nme.ExistentialTypeTree, existential, reify(skolems map (skolem => TypeDef(Modifiers(Set(Modifier.deferred: Modifier)), skolem, Nil, TypeBoundsTree(Ident(NothingClass) setType NothingClass.tpe, Ident(AnyClass) setType AnyClass.tpe))))) -//// reified = mirrorCall(nme.TypeApply, mirrorCall(nme.Select, reified, reify(nme.asInstanceOf_)), mkList(List(existential))) -// // why is this required?? -//// reified = mirrorCall(nme.TypeApply, mirrorCall(nme.Select, reified, reify(nme.asInstanceOf_)), mkList(List(mirrorCall(nme.TypeTree, reify(appliedType(ClassClass.tpe, List(AnyClass.tpe))))))) -// reified -// } else { -// mirrorCall(nme.Literal, reifyProduct(const)) -// } mirrorCall(nme.Literal, reifyProduct(const)) case Import(expr, selectors) => mirrorCall(nme.Import, reify(expr), mkList(selectors map reifyProduct)) @@ -91,61 +66,57 @@ trait Trees { // however, reification of AnnotatedTypes is special. see ``reifyType'' to find out why. if (reifyTreeSymbols && tree.hasSymbol) { if (reifyDebug) println("reifying symbol %s for tree %s".format(tree.symbol, tree)) - rtree = Apply(Select(rtree, nme.setSymbol), List(reify(tree.symbol))) + rtree = mirrorBuildCall(nme.setSymbol, rtree, reify(tree.symbol)) } if (reifyTreeTypes && tree.tpe != null) { if (reifyDebug) println("reifying type %s for tree %s".format(tree.tpe, tree)) - rtree = Apply(Select(rtree, nme.setType), List(reify(tree.tpe))) + rtree = mirrorBuildCall(nme.setType, rtree, reify(tree.tpe)) } rtree } - def reifyModifiers(m: mirror.Modifiers) = - mirrorCall("modifiersFromInternalFlags", reify(m.flags), reify(m.privateWithin), reify(m.annotations)) + def reifyModifiers(m: global.Modifiers) = + mirrorFactoryCall(nme.Modifiers, mirrorBuildCall(nme.flagsFromBits, reify(m.flags)), reify(m.privateWithin), reify(m.annotations)) private def spliceTree(tree: Tree): Tree = { tree match { - case EvalSplice(splicee) => - if (reifyDebug) println("splicing eval " + tree) + case TreeSplice(splicee) => + if (reifyDebug) println("splicing " + tree) // see ``Metalevels'' for more info about metalevel breaches // and about how we deal with splices that contain them - if (splicee exists (sub => sub.hasSymbol && sub.symbol != NoSymbol && sub.symbol.metalevel > 0)) { - if (reifyDebug) println("splicing has failed: cannot splice when facing a metalevel breach") - EmptyTree + val isMetalevelBreach = splicee exists (sub => sub.hasSymbol && sub.symbol != NoSymbol && sub.symbol.metalevel > 0) + val isRuntimeEval = splicee exists (sub => sub.hasSymbol && sub.symbol == ExprSplice) + if (isMetalevelBreach || isRuntimeEval) { + // we used to convert dynamic splices into runtime evals transparently, but we no longer do that + // why? see comments in ``Metalevels'' + // if (reifyDebug) println("splicing has failed: cannot splice when facing a metalevel breach") + // EmptyTree + CannotReifyRuntimeSplice(tree) } else { if (reifyDebug) println("splicing has succeeded") - var splice = Select(splicee, nme.tree) - splice match { - case InlinedTreeSplice(_, inlinedSymbolTable, tree, _) => + splicee match { + // we intentionally don't care about the prefix (the first underscore in the `RefiedTree` pattern match) + case ReifiedTree(_, _, inlinedSymtab, rtree, _, _, _) => if (reifyDebug) println("inlining the splicee") // all free vars local to the enclosing reifee should've already been inlined by ``Metalevels'' - inlinedSymbolTable collect { case freedef @ FreeDef(_, _, binding, _, _) if binding.symbol.isLocalToReifee => assert(false, freedef) } - symbolTable ++= inlinedSymbolTable - tree + inlinedSymtab.syms foreach (sym => if (sym.isLocalToReifee) assert(false, inlinedSymtab.symDef(sym))) + state.symtab ++= inlinedSymtab + rtree case tree => - // we need to preserve types of exprs, because oftentimes they cannot be inferred later - // this circumvents regular reification scheme, therefore we go the extra mile here - new Transformer { - override def transform(tree: Tree) = super.transform(tree match { - case NestedExpr(factory, tree, typetag) => - val typedFactory = TypeApply(factory, List(TypeTree(typetag.tpe.typeArgs(0)))) - Apply(Apply(typedFactory, List(tree)), List(typetag)) - case _ => - tree - }) - }.transform(tree) + val migrated = Apply(Select(splicee, nme.in), List(Ident(nme.MIRROR_SHORT))) + Select(migrated, nme.tree) } } - case ValueSplice(splicee) => - // todo. implement this - ??? case _ => EmptyTree } } + // unlike in `reifyBoundType` we can skip checking for `tpe` being local or not local w.r.t the reifee + // a single check for a symbol of the bound term should be enough + // that's because only Idents and Thises can be bound terms, and they cannot host complex types private def reifyBoundTerm(tree: Tree): Tree = tree match { case tree @ This(_) if tree.symbol == NoSymbol => throw new Error("unexpected: bound term that doesn't have a symbol: " + showRaw(tree)) @@ -153,10 +124,10 @@ trait Trees { val sym = tree.symbol if (reifyDebug) println("This for %s, reified as freeVar".format(sym)) if (reifyDebug) println("Free: " + sym) - mirrorCall(nme.Ident, reifyFreeTerm(sym, This(sym))) + mirrorBuildCall(nme.Ident, reifyFreeTerm(sym, This(sym))) case tree @ This(_) if !tree.symbol.isLocalToReifee => if (reifyDebug) println("This for %s, reified as This".format(tree.symbol)) - mirrorCall(nme.This, reify(tree.symbol)) + mirrorBuildCall(nme.This, reify(tree.symbol)) case tree @ This(_) if tree.symbol.isLocalToReifee => mirrorCall(nme.This, reify(tree.qual)) case tree @ Ident(_) if tree.symbol == NoSymbol => @@ -167,9 +138,9 @@ trait Trees { case tree @ Ident(_) if !tree.symbol.isLocalToReifee => if (tree.symbol.isVariable && tree.symbol.owner.isTerm) { captureVariable(tree.symbol) // Note order dependency: captureVariable needs to come before reification here. - mirrorCall(nme.Select, mirrorCall(nme.Ident, reify(tree.symbol)), reify(nme.elem)) + mirrorCall(nme.Select, mirrorBuildCall(nme.Ident, reify(tree.symbol)), reify(nme.elem)) } else { - mirrorCall(nme.Ident, reify(tree.symbol)) + mirrorBuildCall(nme.Ident, reify(tree.symbol)) } case tree @ Ident(_) if tree.symbol.isLocalToReifee => mirrorCall(nme.Ident, reify(tree.name)) @@ -182,7 +153,12 @@ trait Trees { if (tree.tpe == null) throw new Error("unexpected: bound type that doesn't have a tpe: " + showRaw(tree)) - if (tree.symbol.isLocalToReifee) + // if a symbol or a type of the scrutinee are local to reifee + // (e.g. point to a locally declared class or to a path-dependent thingie that depends on a local variable) + // then we can reify the scrutinee as a symless AST and that will definitely be hygienic + // why? because then typechecking of a scrutinee doesn't depend on the environment external to the quasiquote + // otherwise we need to reify the corresponding type + if (tree.symbol.isLocalToReifee || tree.tpe.isLocalToReifee) reifyProduct(tree) else { val sym0 = tree.symbol @@ -195,7 +171,7 @@ trait Trees { val spliced = spliceType(tpe) if (spliced == EmptyTree) { if (reifyDebug) println("splicing failed: reify as is") - mirrorCall(nme.TypeTree, reify(tpe)) + mirrorBuildCall(nme.TypeTree, reify(tpe)) } else { spliced match { case TypeRefToFreeType(freeType) => @@ -203,16 +179,16 @@ trait Trees { Ident(freeType) case _ => if (reifyDebug) println("splicing succeeded: " + spliced) - mirrorCall(nme.TypeTree, spliced) + mirrorBuildCall(nme.TypeTree, spliced) } } } else { if (sym.isLocatable) { if (reifyDebug) println("tpe is locatable: reify as Ident(%s)".format(sym)) - mirrorCall(nme.Ident, reify(sym)) + mirrorBuildCall(nme.Ident, reify(sym)) } else { if (reifyDebug) println("tpe is an alias, but not a locatable: reify as TypeTree(%s)".format(tpe)) - mirrorCall(nme.TypeTree, reify(tpe)) + mirrorBuildCall(nme.TypeTree, reify(tpe)) } } } @@ -235,25 +211,8 @@ trait Trees { reifyProduct(tree) } - private def reifyNestedFreeRef(tree: Tree): Tree = tree match { - case Apply(Select(mrRef @ Ident(_), ident), List(Ident(name: TermName))) if ident == nme.Ident && name.startsWith(nme.MIRROR_FREE_PREFIX) => - if (reifyDebug) println("nested free ref: %s".format(showRaw(tree))) - reifyProduct(tree) - case _ => - throw new Error("internal error: %s (%s, %s) is not supported".format(tree, tree.productPrefix, tree.getClass)) - } - - private def reifyNestedExpr(tree: Tree): Tree = tree match { - case NestedExpr(factory, tree, typetag) => - // we need to preserve types of exprs, because oftentimes they cannot be inferred later - // this circumvents regular reification scheme, therefore we go through this crazy dance - if (reifyDebug) println("nested expr: %s".format(showRaw(tree))) - val rtype = mirrorCall(nme.TypeTree, reify(typetag.tpe.typeArgs(0))) - val rfactory = mirrorCall(nme.TypeApply, reify(factory), mkList(List(rtype))) - val rexpr = mirrorCall(nme.Apply, rfactory, reify(List(tree))) - val rwrapped = mirrorCall(nme.Apply, rexpr, reify(List(typetag))) - rwrapped - case _ => - throw new Error("internal error: %s (%s, %s) is not supported".format(tree, tree.productPrefix, tree.getClass)) + private def reifyNestedFreeRef(tree: Tree): Tree = { + if (reifyDebug) println("nested free ref: %s".format(showRaw(tree))) + reifyProduct(tree) } -}
\ No newline at end of file +} diff --git a/src/compiler/scala/reflect/reify/codegen/GenTypes.scala b/src/compiler/scala/reflect/reify/codegen/GenTypes.scala new file mode 100644 index 0000000000..f4e2200edc --- /dev/null +++ b/src/compiler/scala/reflect/reify/codegen/GenTypes.scala @@ -0,0 +1,203 @@ +package scala.reflect.reify +package codegen + +trait GenTypes { + self: Reifier => + + import global._ + import definitions._ + + /** + * Reify a type. + * For internal use only, use ``reified'' instead. + */ + def reifyType(tpe0: Type): Tree = { + assert(tpe0 != null, "tpe is null") + val tpe = tpe0.dealias + + if (tpe.isErroneous) + CannotReifyErroneousReifee(tpe) + if (tpe.isLocalToReifee) + CannotReifyType(tpe) + + // this is a very special case. see the comments below for more info. + if (isSemiConcreteTypeMember(tpe)) + return reifySemiConcreteTypeMember(tpe) + + // [Eugene] how do I check that the substitution is legal w.r.t tpe.info? + val spliced = spliceType(tpe) + if (spliced != EmptyTree) + return spliced + + val tsym = tpe.typeSymbol + if (tsym.isClass && tpe == tsym.typeConstructor && tsym.isStatic) + Select(Select(reify(tpe.typeSymbol), nme.asTypeSymbol), nme.asTypeConstructor) + else tpe match { + case tpe @ NoType => + reifyMirrorObject(tpe) + case tpe @ NoPrefix => + reifyMirrorObject(tpe) + case tpe @ ThisType(root) if root.isRoot => + mirrorBuildCall(nme.thisPrefix, mirrorMirrorSelect(nme.RootClass)) + case tpe @ ThisType(empty) if empty.isEmptyPackageClass => + mirrorBuildCall(nme.thisPrefix, mirrorMirrorSelect(nme.EmptyPackageClass)) + case tpe @ ThisType(clazz) if clazz.isModuleClass && clazz.isStatic => + // [Eugene++ to Martin] makes sense? + val module = mirrorMirrorCall(nme.staticModule, reify(clazz.fullName)) + val moduleClass = Select(Select(module, nme.asModuleSymbol), nme.moduleClass) + mirrorFactoryCall(nme.ThisType, moduleClass) + case tpe @ ThisType(_) => + reifyProduct(tpe) + case tpe @ SuperType(thistpe, supertpe) => + reifyProduct(tpe) + case tpe @ SingleType(pre, sym) => + reifyProduct(tpe) + case tpe @ ConstantType(value) => + mirrorFactoryCall(nme.ConstantType, reifyProduct(value)) + case tpe @ TypeRef(pre, sym, args) => + reifyProduct(tpe) + case tpe @ TypeBounds(lo, hi) => + reifyProduct(tpe) + case tpe @ NullaryMethodType(restpe) => + reifyProduct(tpe) + case tpe @ AnnotatedType(anns, underlying, selfsym) => + reifyAnnotatedType(tpe) + case _ => + reifyToughType(tpe) + } + } + + /** Keeps track of whether this reification contains abstract type parameters */ + def reificationIsConcrete: Boolean = state.reificationIsConcrete + + def spliceType(tpe: Type): Tree = { + // [Eugene] it seems that depending on the context the very same symbol can be either a spliceable tparam or a quantified existential. very weird! + val quantified = currentQuantified + if (tpe.isSpliceable && !(quantified contains tpe.typeSymbol)) { + if (reifyDebug) println("splicing " + tpe) + + val tagFlavor = if (concrete) tpnme.TypeTag.toString else tpnme.AbsTypeTag.toString + val key = (tagFlavor, tpe.typeSymbol) + // if this fails, it might produce the dreaded "erroneous or inaccessible type" error + // to find out the whereabouts of the error run scalac with -Ydebug + if (reifyDebug) println("launching implicit search for %s.%s[%s]".format(universe, tagFlavor, tpe)) + val result = + typer.resolveTypeTag(defaultErrorPosition, universe.tpe, tpe, concrete = concrete, allowMaterialization = false) match { + case failure if failure.isEmpty => + if (reifyDebug) println("implicit search was fruitless") + if (reifyDebug) println("trying to splice as manifest") + val splicedAsManifest = spliceAsManifest(tpe) + if (splicedAsManifest.isEmpty) { + if (reifyDebug) println("no manifest in scope") + EmptyTree + } else { + if (reifyDebug) println("successfully spliced as manifest: " + splicedAsManifest) + splicedAsManifest + } + case success => + if (reifyDebug) println("implicit search has produced a result: " + success) + state.reificationIsConcrete &= concrete || success.tpe <:< TypeTagClass.asTypeConstructor + Select(Apply(Select(success, nme.in), List(Ident(nme.MIRROR_SHORT))), nme.tpe) + } + if (result != EmptyTree) return result + state.reificationIsConcrete = false + } + + EmptyTree + } + + private def spliceAsManifest(tpe: Type): Tree = { + val ManifestClass = rootMirror.staticClass("scala.reflect.Manifest") + val ManifestModule = rootMirror.staticModule("scala.reflect.Manifest") + def isSynthetic(manifest: Tree) = manifest exists (sub => sub.symbol != null && (sub.symbol == ManifestModule || sub.symbol.owner == ManifestModule)) + def searchForManifest(typer: analyzer.Typer): Tree = + analyzer.inferImplicit( + EmptyTree, + appliedType(ManifestClass.asTypeConstructor, List(tpe)), + reportAmbiguous = false, + isView = false, + context = typer.context, + saveAmbiguousDivergent = false, + pos = defaultErrorPosition) match { + case success if !success.tree.isEmpty && !isSynthetic(success.tree) => + val manifestInScope = success.tree + // todo. write a test for this + if (ReflectRuntimeUniverse == NoSymbol) CannotConvertManifestToTagWithoutScalaReflect(tpe, manifestInScope) + val cm = typer.typed(Ident(ReflectRuntimeCurrentMirror)) + val tagTree = gen.mkMethodCall(ReflectRuntimeUniverse, nme.manifestToTypeTag, List(tpe), List(cm, manifestInScope)) + Select(Apply(Select(tagTree, nme.in), List(Ident(nme.MIRROR_SHORT))), nme.tpe) + case _ => + EmptyTree + } + val result = typer.silent(silentTyper => silentTyper.context.withMacrosDisabled(searchForManifest(silentTyper))) + result match { + case analyzer.SilentResultValue(result) => result + case analyzer.SilentTypeError(_) => EmptyTree + } + } + + /** Reify a semi-concrete type member. + * + * This is a VERY special case to deal with stuff like `typeOf[ru.Type]`. + * In that case `Type`, which is an abstract type member of scala.reflect.api.Universe, is not a free type. + * Why? Because we know its prefix, and it unambiguously determines the type. + * + * Here is a different view on this question that supports this suggestion. + * Say, you reify a tree. Iff it doesn't contain free types, it can be successfully compiled and run. + * For example, if you reify `tpe.asInstanceOf[T]` taken from `def foo[T]`, then you won't be able to compile the result. + * Fair enough, you don't know the `T`, so the compiler will choke. + * This fact is captured by reification result having a free type T (this can be inspected by calling `tree.freeTypes`). + * Now imagine you reify the following tree: `tpe.asInstanceOf[ru.Type]`. + * To the contrast with the previous example, that's totally not a problem. + * + * Okay, so we figured out that `ru.Type` is not a free type. + * However, in our reification framework, this type would be treated a free type. + * Why? Because `tpe.isSpliceable` will return true. + * Hence we intervene and handle this situation in a special way. + * + * By the way, we cannot change the definition of `isSpliceable`, because class tags also depend on it. + * And, you know, class tags don't care whether we select a type member from a concrete instance or get it from scope (as with type parameters). + * The type itself still remains not concrete, in the sense that we don't know its erasure. + * I.e. we can compile the code that involves `ru.Type`, but we cannot serialize an instance of `ru.Type`. + */ + private def reifySemiConcreteTypeMember(tpe: Type): Tree = tpe match { + case tpe @ TypeRef(pre @ SingleType(prepre, presym), sym, args) if sym.isAbstractType && !sym.isExistential => + return mirrorFactoryCall(nme.TypeRef, reify(pre), mirrorBuildCall(nme.selectType, reify(sym.owner), reify(sym.name.toString)), reify(args)) + } + + /** Reify an annotated type, i.e. the one that makes us deal with AnnotationInfos */ + private def reifyAnnotatedType(tpe: AnnotatedType): Tree = { + val AnnotatedType(anns, underlying, selfsym) = tpe + mirrorFactoryCall(nme.AnnotatedType, mkList(anns map reifyAnnotationInfo), reify(underlying), reify(selfsym)) + } + + /** Reify a tough type, i.e. the one that leads to creation of auxiliary symbols */ + private def reifyToughType(tpe: Type): Tree = { + if (reifyDebug) println("tough type: %s (%s)".format(tpe, tpe.kind)) + + def reifyScope(scope: Scope): Tree = { + scope foreach reifySymDef + mirrorCall(nme.newScopeWith, scope.toList map reify: _*) + } + + tpe match { + case tpe @ RefinedType(parents, decls) => + reifySymDef(tpe.typeSymbol) + mirrorFactoryCall(tpe, reify(parents), reifyScope(decls), reify(tpe.typeSymbol)) + case tpe @ ExistentialType(tparams, underlying) => + tparams foreach reifySymDef + mirrorFactoryCall(tpe, reify(tparams), reify(underlying)) + case tpe @ ClassInfoType(parents, decls, clazz) => + reifySymDef(clazz) + mirrorFactoryCall(tpe, reify(parents), reifyScope(decls), reify(tpe.typeSymbol)) + case tpe @ MethodType(params, restpe) => + params foreach reifySymDef + mirrorFactoryCall(tpe, reify(params), reify(restpe)) + case tpe @ PolyType(tparams, underlying) => + tparams foreach reifySymDef + mirrorFactoryCall(tpe, reify(tparams), reify(underlying)) + case _ => + throw new Error("internal error: %s (%s) is not supported".format(tpe, tpe.kind)) + } + } +} diff --git a/src/compiler/scala/reflect/reify/codegen/Util.scala b/src/compiler/scala/reflect/reify/codegen/GenUtils.scala index bb369a1adb..2b7733fb6c 100644 --- a/src/compiler/scala/reflect/reify/codegen/Util.scala +++ b/src/compiler/scala/reflect/reify/codegen/GenUtils.scala @@ -1,18 +1,11 @@ package scala.reflect.reify package codegen -trait Util { +trait GenUtils { self: Reifier => - import mirror._ + import global._ import definitions._ - import treeInfo._ - - val reifyDebug = settings.Yreifydebug.value - val reifyCopypaste = settings.Yreifycopypaste.value - val reifyTrace = scala.tools.nsc.util.trace when reifyDebug - object reifiedNodePrinters extends { val global: mirror.type = mirror } with tools.nsc.ast.NodePrinters with NodePrinters - val reifiedNodeToString = reifiedNodePrinters.reifiedNodeToString def reifyList(xs: List[Any]): Tree = mkList(xs map reify) @@ -39,12 +32,30 @@ trait Util { Apply(termPath(fname), args.toList) def mirrorSelect(name: String): Tree = + termPath(nme.UNIVERSE_PREFIX + name) + + def mirrorBuildSelect(name: String): Tree = + termPath(nme.UNIVERSE_BUILD_PREFIX + name) + + def mirrorMirrorSelect(name: String): Tree = termPath(nme.MIRROR_PREFIX + name) def mirrorCall(name: TermName, args: Tree*): Tree = - call("" + (nme.MIRROR_PREFIX append name), args: _*) + call("" + (nme.UNIVERSE_PREFIX append name), args: _*) def mirrorCall(name: String, args: Tree*): Tree = + call(nme.UNIVERSE_PREFIX + name, args: _*) + + def mirrorBuildCall(name: TermName, args: Tree*): Tree = + call("" + (nme.UNIVERSE_BUILD_PREFIX append name), args: _*) + + def mirrorBuildCall(name: String, args: Tree*): Tree = + call(nme.UNIVERSE_BUILD_PREFIX + name, args: _*) + + def mirrorMirrorCall(name: TermName, args: Tree*): Tree = + call("" + (nme.MIRROR_PREFIX append name), args: _*) + + def mirrorMirrorCall(name: String, args: Tree*): Tree = call(nme.MIRROR_PREFIX + name, args: _*) def mirrorFactoryCall(value: Product, args: Tree*): Tree = @@ -93,6 +104,17 @@ trait Util { tpe != null && (tpe exists isTough) } + object TypedOrAnnotated { + def unapply(tree: Tree): Option[Tree] = tree match { + case ty @ Typed(_, _) => + Some(ty) + case at @ Annotated(_, _) => + Some(at) + case _ => + None + } + } + def isAnnotated(tpe: Type) = { def isAnnotated(tpe: Type) = tpe match { case _: AnnotatedType => true @@ -102,6 +124,17 @@ trait Util { tpe != null && (tpe exists isAnnotated) } + def isSemiConcreteTypeMember(tpe: Type) = tpe match { + case TypeRef(SingleType(_, _), sym, _) if sym.isAbstractType && !sym.isExistential => true + case _ => false + } + + def isCrossStageTypeBearer(tree: Tree): Boolean = tree match { + case TypeApply(hk, _) => isCrossStageTypeBearer(hk) + case Select(sym @ Select(_, ctor), nme.apply) if ctor == nme.AbsTypeTag || ctor == nme.TypeTag || ctor == nme.Expr => true + case _ => false + } + def origin(sym: Symbol) = { var origin = "" if (sym.owner != NoSymbol) origin += "defined by %s".format(sym.owner.name) diff --git a/src/compiler/scala/reflect/reify/codegen/Symbols.scala b/src/compiler/scala/reflect/reify/codegen/Symbols.scala deleted file mode 100644 index 21a08b7efb..0000000000 --- a/src/compiler/scala/reflect/reify/codegen/Symbols.scala +++ /dev/null @@ -1,184 +0,0 @@ -package scala.reflect.reify -package codegen - -trait Symbols { - self: Reifier => - - import mirror._ - import definitions._ - import treeInfo._ - - /** Reify a reference to a symbol */ - def reifySymRef(sym0: Symbol): Tree = { - assert(sym0 != null, "sym is null") - val sym = sym0.dealias - - if (sym == NoSymbol) - mirrorSelect(nme.NoSymbol) - else if (sym == RootPackage) - Select(mirrorSelect(nme.definitions), nme.RootPackage) - else if (sym == RootClass) - Select(mirrorSelect(nme.definitions), nme.RootClass) - else if (sym == EmptyPackage) - Select(mirrorSelect(nme.definitions), nme.EmptyPackage) - else if (sym == EmptyPackageClass) - Select(mirrorSelect(nme.definitions), nme.EmptyPackageClass) - else if (sym.isModuleClass) - Select(reify(sym.sourceModule), nme.moduleClass) - else if (sym.isLocatable) { - // [Eugene] am I doing this right? -// if (sym.isStaticOwner) { // no good for us, because it returns false for packages - if (sym.isStatic && (sym.isClass || sym.isModule)) { - val resolver = if (sym.isType) nme.staticClass else nme.staticModule - mirrorCall(resolver, reify(sym.fullName)) - } else { - if (reifyDebug) println("Locatable: %s (%s) owned by %s (%s) at %s".format(sym, sym.accurateKindString, sym.owner, sym.owner.accurateKindString, sym.owner.fullNameString)) - val rowner = reify(sym.owner) - val rname = reify(sym.name.toString) - if (sym.isType) - mirrorCall(nme.selectType, rowner, rname) - else if (sym.isMethod && sym.owner.isClass && sym.owner.info.decl(sym.name).isOverloaded) { - val index = sym.owner.info.decl(sym.name).alternatives indexOf sym - assert(index >= 0, sym) - mirrorCall(nme.selectOverloadedMethod, rowner, rname, reify(index)) - } else - mirrorCall(nme.selectTerm, rowner, rname) - } - } else { - // todo. make sure that free methods and free local defs work correctly - if (sym.isTerm) reifyFreeTerm(sym, Ident(sym)) - else reifyFreeType(sym, Ident(sym)) - } - } - - def reifyFreeTerm(sym: Symbol, value: Tree): Tree = - locallyReified get sym match { - case Some(reified) => - reified - case None => - if (reifyDebug) println("Free term" + (if (sym.isCapturedVariable) " (captured)" else "") + ": " + sym + "(" + sym.accurateKindString + ")") - var name = newTermName(nme.MIRROR_FREE_PREFIX + sym.name) - if (sym.isType) name = name.append(nme.MIRROR_FREE_THIS_SUFFIX) - if (sym.isCapturedVariable) { - assert(value.isInstanceOf[Ident], showRaw(value)) - val capturedTpe = capturedVariableType(sym) - val capturedValue = referenceCapturedVariable(sym) - locallyReify(sym, name, mirrorCall(nme.newFreeTerm, reify(sym.name.toString), reify(capturedTpe), capturedValue, reify(sym.flags), reify(origin(sym)))) - } else { - locallyReify(sym, name, mirrorCall(nme.newFreeTerm, reify(sym.name.toString), reify(sym.tpe), value, reify(sym.flags), reify(origin(sym)))) - } - } - - def reifyFreeType(sym: Symbol, value: Tree): Tree = - locallyReified get sym match { - case Some(reified) => - reified - case None => - if (reifyDebug) println("Free type: %s (%s)".format(sym, sym.accurateKindString)) - var name = newTermName(nme.MIRROR_FREE_PREFIX + sym.name) - val phantomTypeTag = Apply(TypeApply(Select(Ident(nme.MIRROR_SHORT), nme.TypeTag), List(value)), List(Literal(Constant(null)), Literal(Constant(null)))) - val flavor = if (sym.isExistential) nme.newFreeExistential else nme.newFreeType - locallyReify(sym, name, mirrorCall(flavor, reify(sym.name.toString), reify(sym.info), phantomTypeTag, reify(sym.flags), reify(origin(sym)))) - } - - def reifySymDef(sym: Symbol): Tree = - locallyReified get sym match { - case Some(reified) => - reified - case None => - if (reifyDebug) println("Sym def: %s (%s)".format(sym, sym.accurateKindString)) - assert(!sym.isLocatable, sym) // if this assertion fires, then tough type reification needs to be rethought - sym.owner.ownersIterator find (!_.isLocatable) foreach reifySymDef - var name = newTermName(nme.MIRROR_SYMDEF_PREFIX + sym.name) - locallyReify(sym, name, Apply(Select(reify(sym.owner), nme.newNestedSymbol), List(reify(sym.name), reify(sym.pos), reify(sym.flags), reify(sym.isClass)))) - } - - // todo. very brittle abstraction, needs encapsulation - import scala.collection.mutable._ - private val localReifications = ArrayBuffer[Tree]() - private val locallyReified = Map[Symbol, Tree]() - private var filledIn = false - def symbolTable: List[Tree] = { fillInSymbolTable(); localReifications.toList } - def symbolTable_=(newSymbolTable: List[Tree]): Unit = { - localReifications.clear() - locallyReified.clear() - filledIn = false - newSymbolTable foreach { - case entry => - val att = entry.attachmentOpt[ReifyAttachment] - att match { - case Some(ReifyAttachment(sym)) => - // don't duplicate reified symbols when merging inlined reifee - if (!(locallyReified contains sym)) { - val ValDef(_, name, _, _) = entry - localReifications += entry - locallyReified(sym) = Ident(name) - } - case other => - // do nothing => symbol table fill-ins will be repopulated later - } - } - } - - private def localName(name0: TermName): TermName = { - var name = name0.toString - name = name.replace(".type", "$type") - name = name.replace(" ", "$") - val fresh = typer.context.unit.fresh - newTermName(fresh.newName(name)) - } - - private def locallyReify(sym: Symbol, name0: TermName, reificode: => Tree): Tree = { - val reified = reificode - val name = localName(name0) - // todo. tried to declare a private class here to carry an attachment, but it's path-dependent - // so got troubles with exchanging free variables between nested and enclosing quasiquotes - // attaching just Symbol isn't good either, so we need to think of a principled solution - val local = ValDef(NoMods, name, TypeTree(), reified) withAttachment ReifyAttachment(sym) - localReifications += local - filledIn = false - locallyReified(sym) = Ident(name) - locallyReified(sym) - } - - /** Sets type signatures and annotations for locally reified symbols */ - private def fillInSymbolTable() = { - if (!filledIn) { - val fillIns = new ArrayBuffer[Tree] - var i = 0 - while (i < localReifications.length) { - // fillInSymbol might create new locallyReified symbols, that's why this is done iteratively - val reified = localReifications(i) - val att = reified.attachmentOpt[ReifyAttachment] - att match { - case Some(ReifyAttachment(sym)) => fillIns += fillInSymbol(sym) - case other => // do nothing - } - i += 1 - } - - filledIn = true - localReifications ++= fillIns.toList - } - } - - /** Generate code to add type and annotation info to a reified symbol */ - private def fillInSymbol(sym: Symbol): Tree = { - if (reifyDebug) println("Filling in: %s (%s)".format(sym, sym.accurateKindString)) - val isFree = locallyReified(sym) match { case Ident(name) => name startsWith nme.MIRROR_FREE_PREFIX } - if (isFree) { - if (sym.annotations.isEmpty) EmptyTree - else Apply(Select(locallyReified(sym), nme.setAnnotations), List(reify(sym.annotations))) - } else { - import scala.reflect.internal.Flags._ - if (sym hasFlag LOCKED) { - // [Eugene] better to have a symbol without a type signature, than to crash with a CyclicReference - EmptyTree - } else { - val rset = Apply(Select(locallyReified(sym), nme.setTypeSignature), List(reify(sym.info))) - if (sym.annotations.isEmpty) rset - else Apply(Select(rset, nme.setAnnotations), List(reify(sym.annotations))) - } - } - } -}
\ No newline at end of file diff --git a/src/compiler/scala/reflect/reify/codegen/Types.scala b/src/compiler/scala/reflect/reify/codegen/Types.scala deleted file mode 100644 index a2b074c6b2..0000000000 --- a/src/compiler/scala/reflect/reify/codegen/Types.scala +++ /dev/null @@ -1,168 +0,0 @@ -package scala.reflect.reify -package codegen - -trait Types { - self: Reifier => - - import mirror._ - import definitions._ - import treeInfo._ - - /** - * Reify a type. - * For internal use only, use ``reified'' instead. - */ - def reifyType(tpe0: Type): Tree = { - assert(tpe0 != null, "tpe is null") - val tpe = tpe0.dealias - - if (tpe.isErroneous) - CannotReifyErroneousReifee(tpe) - if (tpe.isLocalToReifee) - CannotReifyType(tpe) - - // [Eugene] how do I check that the substitution is legal w.r.t tpe.info? - val spliced = spliceType(tpe) - if (spliced != EmptyTree) - return spliced - - val tsym = tpe.typeSymbol - if (tsym.isClass && tpe == tsym.typeConstructor && tsym.isStatic) - Select(reify(tpe.typeSymbol), nme.asTypeConstructor) - else tpe match { - case tpe @ NoType => - reifyMirrorObject(tpe) - case tpe @ NoPrefix => - reifyMirrorObject(tpe) - case tpe @ ThisType(root) if root == RootClass => - mirrorSelect("definitions.RootClass.thisPrefix") - case tpe @ ThisType(empty) if empty == EmptyPackageClass => - mirrorSelect("definitions.EmptyPackageClass.thisPrefix") - case tpe @ ThisType(clazz) if clazz.isModuleClass && clazz.isStatic => - mirrorCall(nme.thisModuleType, reify(clazz.fullName)) - case tpe @ ThisType(_) => - reifyProduct(tpe) - case tpe @ SuperType(thistpe, supertpe) => - reifyProduct(tpe) - case tpe @ SingleType(pre, sym) => - reifyProduct(tpe) - case tpe @ ConstantType(value) => - mirrorFactoryCall(nme.ConstantType, reifyProduct(value)) - case tpe @ TypeRef(pre, sym, args) => - reifyProduct(tpe) - case tpe @ TypeBounds(lo, hi) => - reifyProduct(tpe) - case tpe @ NullaryMethodType(restpe) => - reifyProduct(tpe) - case tpe @ AnnotatedType(anns, underlying, selfsym) => - reifyAnnotatedType(tpe) - case _ => - reifyToughType(tpe) - } - } - - /** An obscure flag necessary for implicit TypeTag generation */ - private var spliceTypesEnabled = !dontSpliceAtTopLevel - - /** Keeps track of whether this reification contains abstract type parameters */ - private var _reificationIsConcrete = true - def reificationIsConcrete = _reificationIsConcrete - def reificationIsConcrete_=(value: Boolean) { - _reificationIsConcrete = value - if (!value && concrete) { - assert(current.isInstanceOf[Type], current) - val offender = current.asInstanceOf[Type] - CannotReifyConcreteTypeTagHavingUnresolvedTypeParameters(offender) - } - } - - private type SpliceCacheKey = (Symbol, Symbol) - private lazy val spliceCache: collection.mutable.Map[SpliceCacheKey, Tree] = { - val cache = analyzer.perRunMacroCache.getOrElseUpdate(MacroContextReify, collection.mutable.Map[Any, Any]()) - cache.getOrElseUpdate("spliceCache", collection.mutable.Map[SpliceCacheKey, Tree]()).asInstanceOf[collection.mutable.Map[SpliceCacheKey, Tree]] - } - - def spliceType(tpe: Type): Tree = { - // [Eugene] it seems that depending on the context the very same symbol can be either a spliceable tparam or a quantified existential. very weird! - val quantified = currentQuantified - if (tpe.isSpliceable && !(quantified contains tpe.typeSymbol)) { - if (reifyDebug) println("splicing " + tpe) - - if (spliceTypesEnabled) { - var tagClass = if (concrete) ConcreteTypeTagClass else TypeTagClass - val tagTpe = singleType(prefix.tpe, prefix.tpe member tagClass.name) - - // [Eugene] this should be enough for an abstract type, right? - val key = (tagClass, tpe.typeSymbol) - if (reifyDebug && spliceCache.contains(key)) println("cache hit: " + spliceCache(key)) - val result = spliceCache.getOrElseUpdate(key, { - // if this fails, it might produce the dreaded "erroneous or inaccessible type" error - // to find out the whereabouts of the error run scalac with -Ydebug - if (reifyDebug) println("launching implicit search for %s.%s[%s]".format(prefix, tagClass.name, tpe)) - typer.resolveTypeTag(prefix.tpe, tpe, defaultErrorPosition, concrete) match { - case failure if failure.isEmpty => - if (reifyDebug) println("implicit search was fruitless") - EmptyTree - case success => - if (reifyDebug) println("implicit search has produced a result: " + success) - reificationIsConcrete &= concrete - var splice = Select(success, nme.tpe) - splice match { - case InlinedTypeSplice(_, inlinedSymbolTable, tpe) => - // all free vars local to the enclosing reifee should've already been inlined by ``Metalevels'' - inlinedSymbolTable collect { case freedef @ FreeDef(_, _, binding, _, _) if binding.symbol.isLocalToReifee => assert(false, freedef) } - symbolTable ++= inlinedSymbolTable - reifyTrace("inlined the splicee: ")(tpe) - case tpe => - tpe - } - } - }) - if (result != EmptyTree) return result.duplicate - } else { - if (reifyDebug) println("splicing has been cancelled: spliceTypesEnabled = false") - } - - reificationIsConcrete = false - } - - spliceTypesEnabled = true - EmptyTree - } - - /** Reify an annotated type, i.e. the one that makes us deal with AnnotationInfos */ - private def reifyAnnotatedType(tpe: AnnotatedType): Tree = { - val AnnotatedType(anns, underlying, selfsym) = tpe - mirrorFactoryCall(nme.AnnotatedType, mkList(anns map reifyAnnotationInfo), reify(underlying), reify(selfsym)) - } - - /** Reify a tough type, i.e. the one that leads to creation of auxiliary symbols */ - private def reifyToughType(tpe: Type): Tree = { - if (reifyDebug) println("tough type: %s (%s)".format(tpe, tpe.kind)) - - def reifyScope(scope: Scope): Tree = { - scope foreach reifySymDef - mirrorCall(nme.newScopeWith, scope.toList map reify: _*) - } - - tpe match { - case tpe @ RefinedType(parents, decls) => - reifySymDef(tpe.typeSymbol) - mirrorFactoryCall(tpe, reify(parents), reifyScope(decls), reify(tpe.typeSymbol)) - case tpe @ ExistentialType(tparams, underlying) => - tparams foreach reifySymDef - mirrorFactoryCall(tpe, reify(tparams), reify(underlying)) - case tpe @ ClassInfoType(parents, decls, clazz) => - reifySymDef(clazz) - mirrorFactoryCall(tpe, reify(parents), reifyScope(decls), reify(tpe.typeSymbol)) - case tpe @ MethodType(params, restpe) => - params foreach reifySymDef - mirrorFactoryCall(tpe, reify(params), reify(restpe)) - case tpe @ PolyType(tparams, underlying) => - tparams foreach reifySymDef - mirrorFactoryCall(tpe, reify(tparams), reify(underlying)) - case _ => - throw new Error("internal error: %s (%s) is not supported".format(tpe, tpe.kind)) - } - } -}
\ No newline at end of file diff --git a/src/compiler/scala/reflect/reify/package.scala b/src/compiler/scala/reflect/reify/package.scala index a096e2e93b..80011368a8 100644 --- a/src/compiler/scala/reflect/reify/package.scala +++ b/src/compiler/scala/reflect/reify/package.scala @@ -1,59 +1,76 @@ package scala.reflect +import language.implicitConversions +import language.experimental.macros +import scala.reflect.base.{Universe => BaseUniverse} +import scala.reflect.makro.{Context, ReificationError, UnexpectedReificationError} import scala.tools.nsc.Global -import scala.reflect.makro.ReificationError -import scala.reflect.makro.UnexpectedReificationError package object reify { - private def mkReifier(global: Global)(typer: global.analyzer.Typer, prefix: global.Tree, reifee: Any, dontSpliceAtTopLevel: Boolean = false, concrete: Boolean = false): Reifier { val mirror: global.type } = { + private def mkReifier(global1: Global)(typer: global1.analyzer.Typer, universe: global1.Tree, mirror: global1.Tree, reifee: Any, concrete: Boolean = false): Reifier { val global: global1.type } = { val typer1: typer.type = typer - val prefix1: prefix.type = prefix + val universe1: universe.type = universe + val mirror1: mirror.type = mirror val reifee1 = reifee - val dontSpliceAtTopLevel1 = dontSpliceAtTopLevel val concrete1 = concrete new { - val mirror: global.type = global + val global: global1.type = global1 val typer = typer1 - val prefix = prefix1 + val universe = universe1 + val mirror = mirror1 val reifee = reifee1 - val dontSpliceAtTopLevel = dontSpliceAtTopLevel1 val concrete = concrete1 } with Reifier } - def reifyTree(global: Global)(typer: global.analyzer.Typer, prefix: global.Tree, tree: global.Tree): global.Tree = - mkReifier(global)(typer, prefix, tree, false, false).reified.asInstanceOf[global.Tree] + private[reify] def mkDefaultMirrorRef(global: Global)(universe: global.Tree, typer0: global.analyzer.Typer): global.Tree = { + import global._ + import definitions._ + val enclosingErasure = reifyEnclosingRuntimeClass(global)(typer0) + // JavaUniverse is defined in scala-reflect.jar, so we must be very careful in case someone reifies stuff having only scala-library.jar on the classpath + val isJavaUniverse = JavaUniverseClass != NoSymbol && universe.tpe <:< JavaUniverseClass.asTypeConstructor + if (isJavaUniverse && !enclosingErasure.isEmpty) Apply(Select(universe, nme.runtimeMirror), List(Select(enclosingErasure, sn.GetClassLoader))) + else Select(universe, nme.rootMirror) + } - def reifyType(global: Global)(typer: global.analyzer.Typer, prefix: global.Tree, tpe: global.Type, dontSpliceAtTopLevel: Boolean = false, concrete: Boolean = false): global.Tree = - mkReifier(global)(typer, prefix, tpe, dontSpliceAtTopLevel, concrete).reified.asInstanceOf[global.Tree] + def reifyTree(global: Global)(typer: global.analyzer.Typer, universe: global.Tree, mirror: global.Tree, tree: global.Tree): global.Tree = + mkReifier(global)(typer, universe, mirror, tree, concrete = false).reification.asInstanceOf[global.Tree] - def reifyErasure(global: Global)(typer0: global.analyzer.Typer, tpe: global.Type, concrete: Boolean = true): global.Tree = { + def reifyType(global: Global)(typer: global.analyzer.Typer,universe: global.Tree, mirror: global.Tree, tpe: global.Type, concrete: Boolean = false): global.Tree = + mkReifier(global)(typer, universe, mirror, tpe, concrete = concrete).reification.asInstanceOf[global.Tree] + + def reifyRuntimeClass(global: Global)(typer0: global.analyzer.Typer, tpe: global.Type, concrete: Boolean = true): global.Tree = { import global._ import definitions._ import analyzer.enclosingMacroPosition - def erasureTagInScope = typer0.context.withMacrosDisabled(typer0.resolveErasureTag(tpe, enclosingMacroPosition, concrete = concrete)) - def arrayTagInScope = typer0.context.withMacrosDisabled(typer0.resolveArrayTag(tpe, enclosingMacroPosition)) - val inScope = (erasureTagInScope, arrayTagInScope) + if (tpe.isSpliceable) { + val classTagInScope = typer0.resolveClassTag(enclosingMacroPosition, tpe, allowMaterialization = false) + if (!classTagInScope.isEmpty) return Select(classTagInScope, nme.runtimeClass) + if (concrete) throw new ReificationError(enclosingMacroPosition, "tpe %s is an unresolved spliceable type".format(tpe)) + } - inScope match { - case (success, _) if !success.isEmpty => - Select(success, nme.erasure) - case (_, success) if !success.isEmpty => - gen.mkMethodCall(arrayElementClassMethod, List(success)) + tpe.normalize match { + case TypeRef(_, ArrayClass, componentTpe :: Nil) => + val componentErasure = reifyRuntimeClass(global)(typer0, componentTpe, concrete) + gen.mkMethodCall(arrayClassMethod, List(componentErasure)) case _ => - tpe.normalize match { - case TypeRef(_, ArrayClass, componentTpe :: Nil) => - val componentErasure = reifyErasure(global)(typer0, componentTpe, concrete) - gen.mkMethodCall(arrayClassMethod, List(componentErasure)) - case _ => - if (tpe.isSpliceable && concrete) - throw new ReificationError(enclosingMacroPosition, "tpe %s is an unresolved spliceable type".format(tpe)) - var erasure = tpe.erasure - if (tpe.typeSymbol.isDerivedValueClass && global.phase.id < global.currentRun.erasurePhase.id) erasure = tpe - gen.mkNullaryCall(Predef_classOf, List(erasure)) - } + var erasure = tpe.erasure + if (tpe.typeSymbol.isDerivedValueClass && global.phase.id < global.currentRun.erasurePhase.id) erasure = tpe + gen.mkNullaryCall(Predef_classOf, List(erasure)) } } + + def reifyEnclosingRuntimeClass(global: Global)(typer0: global.analyzer.Typer): global.Tree = { + import global._ + import definitions._ + def isThisInScope = typer0.context.enclosingContextChain exists (_.tree.isInstanceOf[Template]) + if (isThisInScope) { + val enclosingClasses = typer0.context.enclosingContextChain map (_.tree) collect { case classDef: ClassDef => classDef } + val classInScope = enclosingClasses.headOption getOrElse EmptyTree + if (!classInScope.isEmpty) reifyRuntimeClass(global)(typer0, classInScope.symbol.asTypeConstructor, concrete = true) + else Select(This(tpnme.EMPTY), sn.GetClass) + } else EmptyTree + } } diff --git a/src/compiler/scala/reflect/reify/phases/Calculate.scala b/src/compiler/scala/reflect/reify/phases/Calculate.scala index 93ef46472e..41cf6c066a 100644 --- a/src/compiler/scala/reflect/reify/phases/Calculate.scala +++ b/src/compiler/scala/reflect/reify/phases/Calculate.scala @@ -4,25 +4,26 @@ package phases trait Calculate { self: Reifier => - import mirror._ + import global._ import definitions._ - import treeInfo._ - implicit class RichSymbol(sym: Symbol) { - def metalevel: Int = { assert(sym != NoSymbol); localSymbols.getOrElse(sym, 0) } + implicit class RichCalculateSymbol(sym: Symbol) { + def metalevel: Int = { assert(sym != null && sym != NoSymbol); localSymbols.getOrElse(sym, 0) } def isLocalToReifee = (localSymbols contains sym) // [Eugene] how do I account for local skolems? } - implicit class RichType(tpe: Type) { + implicit class RichCalculateType(tpe: Type) { def isLocalToReifee = tpe != null && (tpe exists (tp => (localSymbols contains tp.typeSymbol) || (localSymbols contains tp.termSymbol))) } - private var localSymbols = collection.mutable.Map[Symbol, Int]() // set of all symbols that are local to the tree to be reified + private def localSymbols: Map[Symbol, Int] = state.localSymbols // set of all symbols that are local to the tree to be reified + private def localSymbols_=(value: Map[Symbol, Int]): Unit = state.localSymbols = value private def registerLocalSymbol(sym: Symbol, metalevel: Int): Unit = if (sym != null && sym != NoSymbol) { if (localSymbols contains sym) assert(localSymbols(sym) == metalevel, "metalevel mismatch: expected %s, actual %s".format(localSymbols(sym), metalevel)) - localSymbols(sym) = metalevel + else + localSymbols += (sym -> metalevel) } /** @@ -38,7 +39,7 @@ trait Calculate { try super.traverse(tree) finally currMetalevel += 1 case tree if tree.isDef => - if (reifyDebug) println("boundSym: %s of type %s".format(tree.symbol, (tree.productIterator.toList collect { case tt: TypeTree => tt } headOption).getOrElse(TypeTree(tree.tpe)))) + if (reifyDebug) println("boundSym: %s of type %s".format(tree.symbol, (tree.productIterator.toList collect { case tt: TypeTree => tt }).headOption.getOrElse(TypeTree(tree.tpe)))) registerLocalSymbol(tree.symbol, currMetalevel) bindRelatedSymbol(tree.symbol.sourceModule, "sourceModule") diff --git a/src/compiler/scala/reflect/reify/phases/Metalevels.scala b/src/compiler/scala/reflect/reify/phases/Metalevels.scala index 206f3b1118..1624bbe951 100644 --- a/src/compiler/scala/reflect/reify/phases/Metalevels.scala +++ b/src/compiler/scala/reflect/reify/phases/Metalevels.scala @@ -4,9 +4,8 @@ package phases trait Metalevels { self: Reifier => - import mirror._ + import global._ import definitions._ - import treeInfo._ /** * Makes sense of cross-stage bindings. @@ -23,7 +22,7 @@ trait Metalevels { * val x = 2 // metalevel of symbol x is 1, because it's declared inside reify * val y = reify{x} // metalevel of symbol y is 1, because it's declared inside reify * // metalevel of Ident(x) is 2, because it's inside two reifies - * y.eval // metalevel of Ident(y) is 0, because it's inside a designator of a splice + * y.splice // metalevel of Ident(y) is 0, because it's inside a designator of a splice * } * * Cross-stage bindings are introduced when symbol.metalevel != curr_metalevel. @@ -37,21 +36,26 @@ trait Metalevels { * * 2) symbol.metalevel > curr_metalevel. This leads to a metalevel breach that violates intuitive perception of splicing. * As defined in macro spec, splicing takes a tree and inserts it into another tree - as simple as that. - * However, how exactly do we do that in the case of y.eval? In this very scenario we can use dataflow analysis and inline it, + * However, how exactly do we do that in the case of y.splice? In this very scenario we can use dataflow analysis and inline it, * but what if y were a var, and what if it were calculated randomly at runtime? * * This question has a genuinely simple answer. Sure, we cannot resolve such splices statically (i.e. during macro expansion of ``reify''), * but now we have runtime toolboxes, so noone stops us from picking up that reified tree and evaluating it at runtime - * (in fact, this is something that ``Expr.eval'' and ``Expr.value'' do transparently). + * (in fact, this is something that ``Expr.splice'' does transparently). * * This is akin to early vs late binding dilemma. * The prior is faster, plus, the latter (implemented with reflection) might not work because of visibility issues or might be not available on all platforms. * But the latter still has its uses, so I'm allowing metalevel breaches, but introducing the -Xlog-runtime-evals to log them. * + * upd. We no longer do that. In case of a runaway ``splice'' inside a `reify`, one will get a static error. + * Why? Unfortunately, the cute idea of transparently converting between static and dynamic splices has failed. + * 1) Runtime eval that services dynamic splices requires scala-compiler.jar, which might not be on library classpath + * 2) Runtime eval incurs a severe performance penalty, so it'd better to be explicit about it + * * ================ * - * As we can see, the only problem is the fact that lhs'es of eval can be code blocks that can capture variables from the outside. - * Code inside the lhs of an eval is not reified, while the code from the enclosing reify is. + * As we can see, the only problem is the fact that lhs'es of `splice` can be code blocks that can capture variables from the outside. + * Code inside the lhs of an `splice` is not reified, while the code from the enclosing reify is. * * Hence some bindings become cross-stage, which is not bad per se (in fact, some cross-stage bindings have sane semantics, as in the example above). * However this affects freevars, since they are delicate inter-dimensional beings that refer to both current and next planes of existence. @@ -61,10 +65,10 @@ trait Metalevels { * * reify { * val x = 2 - * reify{x}.eval + * reify{x}.splice * } * - * Since the result of the inner reify is wrapped in an eval, it won't be reified + * Since the result of the inner reify is wrapped in a splice, it won't be reified * together with the other parts of the outer reify, but will be inserted into that result verbatim. * * The inner reify produces an Expr[Int] that wraps Ident(freeVar("x", IntClass.tpe, x)). @@ -76,10 +80,10 @@ trait Metalevels { * reify { * val x = 2 * val y = reify{x} - * y.eval + * y.splice * } * - * In this case the inner reify doesn't appear next to eval, so it will be reified together with x. + * In this case the inner reify doesn't appear next to splice, so it will be reified together with x. * This means that no special processing is needed here. * * Example 4. Consider the following fragment: @@ -89,16 +93,16 @@ trait Metalevels { * { * val y = 2 * val z = reify{reify{x + y}} - * z.eval - * }.eval + * z.splice + * }.splice * } * * The reasoning from Example 2 still holds here - we do need to inline the freevar that refers to x. - * However, we must not touch anything inside the eval'd block, because it's not getting reified. + * However, we must not touch anything inside the splice'd block, because it's not getting reified. */ - var metalevels = new Transformer { + val metalevels = new Transformer { var insideSplice = false - var freedefsToInline = collection.mutable.Map[String, ValDef]() + var inlineableBindings = collection.mutable.Map[TermName, Tree]() def withinSplice[T](op: => T) = { val old = insideSplice @@ -107,40 +111,36 @@ trait Metalevels { finally insideSplice = old } - // Q: here we deal with all sorts of reified trees. what about ReifiedType(_, _, _, _)? + // Q: here we deal with all sorts of reified trees. what about ReifiedType(_, _, _, _, _, _)? // A: nothing. reified trees give us problems because they sometimes create dimensional rifts as described above // to the contrast, reified types (i.e. synthetic typetags materialized by Implicits.scala) always stay on the same metalevel as their enclosing code override def transform(tree: Tree): Tree = tree match { - case InlineableTreeSplice(splicee, inlinedSymbolTable, _, _, flavor) => - if (reifyDebug) println("entering inlineable splice: " + splicee) - val Block(mrDef :: symbolTable, expr) = splicee - // [Eugene] how to express the fact that a scrutinee is both of some type and matches an extractor? - val freedefsToInline = symbolTable collect { case freedef @ FreeTermDef(_, _, binding, _, _) if binding.symbol.isLocalToReifee => freedef.asInstanceOf[ValDef] } - freedefsToInline foreach (vdef => this.freedefsToInline(vdef.name) = vdef) - val symbolTable1 = symbolTable diff freedefsToInline - val tree1 = Select(Block(mrDef :: symbolTable1, expr), flavor) - if (reifyDebug) println("trimmed %s inlineable free defs from its symbol table: %s".format(freedefsToInline.length, freedefsToInline map (_.name) mkString(", "))) - withinSplice { super.transform(tree1) } + case TreeSplice(ReifiedTree(universe, mirror, symtab, rtree, tpe, rtpe, concrete)) => + if (reifyDebug) println("entering inlineable splice: " + tree) + val inlinees = symtab.syms filter (_.isLocalToReifee) + inlinees foreach (inlinee => symtab.symAliases(inlinee) foreach (alias => inlineableBindings(alias) = symtab.symBinding(inlinee))) + val symtab1 = symtab -- inlinees + if (reifyDebug) println("trimmed %s inlineable free defs from its symbol table: %s".format(inlinees.length, inlinees map (inlinee => symtab.symName(inlinee)) mkString(", "))) + withinSplice { super.transform(TreeSplice(ReifiedTree(universe, mirror, symtab1, rtree, tpe, rtpe, concrete))) } case TreeSplice(splicee) => if (reifyDebug) println("entering splice: " + splicee) - val hasBreaches = splicee exists (_.symbol.metalevel > 0) - if (!insideSplice && hasBreaches) { - if (settings.logRuntimeSplices.value) reporter.echo(tree.pos, "this splice cannot be resolved statically") - if (reifyDebug) println("metalevel breach in %s: %s".format(tree, (splicee filter (_.symbol.metalevel > 0) map (_.symbol) distinct) mkString ", ")) + val breaches = splicee filter (sub => sub.hasSymbol && sub.symbol != NoSymbol && sub.symbol.metalevel > 0) + if (!insideSplice && breaches.nonEmpty) { + // we used to convert dynamic splices into runtime evals transparently, but we no longer do that + // why? see comments above + // if (settings.logRuntimeSplices.value) reporter.echo(tree.pos, "this splice cannot be resolved statically") + // withinSplice { super.transform(tree) } + if (reifyDebug) println("metalevel breach in %s: %s".format(tree, (breaches map (_.symbol)).distinct mkString ", ")) + CannotReifyRuntimeSplice(tree) + } else { + withinSplice { super.transform(tree) } } - withinSplice { super.transform(tree) } - // todo. also inline usages of ``freedefsToInline'' in the symbolTable itself + // todo. also inline usages of ``inlineableBindings'' in the symtab itself // e.g. a free$Foo can well use free$x, if Foo is path-dependent w.r.t x // FreeRef(_, _) check won't work, because metalevels of symbol table and body are different, hence, freerefs in symbol table look different from freerefs in body - // todo. also perform garbage collection on local symbols - // so that local symbols used only in type signatures of free vars get removed - // todo. same goes for auxiliary symbol defs reified to support tough types - // some of them need to be rebuilt, some of them need to be removed, because they're no longer necessary - case FreeRef(mr, name) if freedefsToInline contains name => + case FreeRef(_, name) if inlineableBindings contains name => if (reifyDebug) println("inlineable free ref: %s in %s".format(name, showRaw(tree))) - val freedef @ FreeDef(_, _, binding, _, _) = freedefsToInline(name) - if (reifyDebug) println("related definition: %s".format(showRaw(freedef))) - val inlined = reify(binding) + val inlined = reify(inlineableBindings(name)) if (reifyDebug) println("verdict: inlined as %s".format(showRaw(inlined))) inlined case _ => diff --git a/src/compiler/scala/reflect/reify/phases/Reify.scala b/src/compiler/scala/reflect/reify/phases/Reify.scala index e03ff5832c..dc0028be38 100644 --- a/src/compiler/scala/reflect/reify/phases/Reify.scala +++ b/src/compiler/scala/reflect/reify/phases/Reify.scala @@ -5,29 +5,22 @@ import scala.runtime.ScalaRunTime.isAnyVal import scala.runtime.ScalaRunTime.isTuple import scala.reflect.reify.codegen._ -trait Reify extends Symbols - with Types - with Names - with Trees - with AnnotationInfos - with Positions - with Util { +trait Reify extends GenSymbols + with GenTypes + with GenNames + with GenTrees + with GenAnnotationInfos + with GenPositions + with GenUtils { self: Reifier => - import mirror._ + import global._ import definitions._ - import treeInfo._ - // `reify` looked so nice, I wanted to push the last bit of orthogonal - // logic out of it so you can see the improvement. There is no cost to - // wrapper methods of this form because the inliner will eliminate them, - // but they are very good at separating concerns like pushing/popping - // a stack, and they are great for composition and reuse. - // - // Also, please avoid public vars whenever possible. private object reifyStack { - var currents: List[Any] = reifee :: Nil + def currents: List[Any] = state.reifyStack + def currents_=(value: List[Any]): Unit = state.reifyStack = value @inline final def push[T](reifee: Any)(body: => T): T = { currents ::= reifee @@ -37,6 +30,7 @@ trait Reify extends Symbols } def currentQuantified = flatCollect(reifyStack.currents)({ case ExistentialType(quantified, _) => quantified }) def current = reifyStack.currents.head + def currents = reifyStack.currents /** * Reifies any supported value. @@ -52,9 +46,9 @@ trait Reify extends Symbols case tree: Tree => reifyTree(tree) // disabled because this is a very special case that I plan to remove later // why do I dislike annotations? see comments to `reifyAnnotationInfo` -// case ann: AnnotationInfo => reifyAnnotationInfo(ann) + // case ann: AnnotationInfo => reifyAnnotationInfo(ann) case pos: Position => reifyPosition(pos) - case mods: mirror.Modifiers => reifyModifiers(mods) + case mods: global.Modifiers => reifyModifiers(mods) case xs: List[_] => reifyList(xs) case s: String => Literal(Constant(s)) case v if isAnyVal(v) => Literal(Constant(v)) diff --git a/src/compiler/scala/reflect/reify/phases/Reshape.scala b/src/compiler/scala/reflect/reify/phases/Reshape.scala index 4ab306a13f..e26dd7e227 100644 --- a/src/compiler/scala/reflect/reify/phases/Reshape.scala +++ b/src/compiler/scala/reflect/reify/phases/Reshape.scala @@ -6,15 +6,16 @@ import scala.tools.nsc.symtab.Flags._ trait Reshape { self: Reifier => - import mirror._ + import global._ import definitions._ - import treeInfo._ /** * Rolls back certain changes that were introduced during typechecking of the reifee. * * These include: + * * Undoing macro expansions * * Replacing type trees with TypeTree(tpe) + * * Reassembling CompoundTypeTrees into reifiable form * * Transforming Modifiers.annotations into Symbol.annotations * * Transforming Annotated annotations into AnnotatedType annotations * * Transforming Annotated(annot, expr) into Typed(expr, TypeTree(Annotated(annot, _)) @@ -23,7 +24,8 @@ trait Reshape { val reshape = new Transformer { var currentSymbol: Symbol = NoSymbol - override def transform(tree: Tree) = { + override def transform(tree0: Tree) = { + val tree = undoMacroExpansion(tree0) currentSymbol = tree.symbol val preTyper = tree match { @@ -31,8 +33,13 @@ trait Reshape { tree case tt @ TypeTree() => toPreTyperTypeTree(tt) + case ctt @ CompoundTypeTree(_) => + toPreTyperCompoundTypeTree(ctt) case toa @ TypedOrAnnotated(_) => toPreTyperTypedOrAnnotated(toa) + case ta @ TypeApply(_, _) if isCrossStageTypeBearer(ta) => + if (reifyDebug) println("cross-stage type bearer, retaining: " + tree) + ta case ta @ TypeApply(hk, ts) => val discard = ts collect { case tt: TypeTree => tt } exists isDiscarded if (reifyDebug && discard) println("discarding TypeApply: " + tree) @@ -85,6 +92,27 @@ trait Reshape { super.transform(preTyper) } + private def undoMacroExpansion(tree: Tree): Tree = + tree.attachments.get[MacroExpansionAttachment] match { + case Some(MacroExpansionAttachment(original)) => + original match { + // this hack is necessary until I fix implicit macros + // so far tag materialization is implemented by sneaky macros hidden in scala-compiler.jar + // hence we cannot reify references to them, because noone will be able to see them later + // when implicit macros are fixed, these sneaky macros will move to corresponding companion objects + // of, say, ClassTag or TypeTag + case Apply(TypeApply(_, List(tt)), _) if original.symbol == MacroInternal_materializeClassTag => + gen.mkNullaryCall(Predef_implicitly, List(appliedType(ClassTagClass, tt.tpe))) + case Apply(TypeApply(_, List(tt)), List(pre)) if original.symbol == MacroInternal_materializeAbsTypeTag => + gen.mkNullaryCall(Predef_implicitly, List(typeRef(pre.tpe, AbsTypeTagClass, List(tt.tpe)))) + case Apply(TypeApply(_, List(tt)), List(pre)) if original.symbol == MacroInternal_materializeTypeTag => + gen.mkNullaryCall(Predef_implicitly, List(typeRef(pre.tpe, TypeTagClass, List(tt.tpe)))) + case _ => + original + } + case _ => tree + } + override def transformModifiers(mods: Modifiers) = { val mods1 = toPreTyperModifiers(mods, currentSymbol) super.transformModifiers(mods1) @@ -130,6 +158,7 @@ trait Reshape { * Suddenly I found out that in certain contexts original trees do not contain symbols, but are just parser trees. * To the moment I know only one such situation: typedAnnotations does not typecheck the annotation in-place, but rather creates new trees and typechecks them, so the original remains symless. * Thus we apply a workaround for that in typedAnnotated. I hope this will be the only workaround in this department. + * upd. There are also problems with CompoundTypeTrees. I had to use attachments to retain necessary information. * * upd. Recently I went ahead and started using original for all TypeTrees, regardless of whether they refer to local symbols or not. * As a result, ``reifyType'' is never called directly by tree reification (and, wow, it seems to work great!). @@ -137,7 +166,7 @@ trait Reshape { */ private def isDiscarded(tt: TypeTree) = tt.original == null private def toPreTyperTypeTree(tt: TypeTree): Tree = { - if (tt.original != null) { + if (!isDiscarded(tt)) { // here we rely on the fact that the originals that reach this point // have all necessary symbols attached to them (i.e. that they can be recompiled in any lexical context) // if this assumption fails, please, don't be quick to add postprocessing here (like I did before) @@ -154,6 +183,14 @@ trait Reshape { } } + private def toPreTyperCompoundTypeTree(ctt: CompoundTypeTree): Tree = { + val CompoundTypeTree(tmpl @ Template(parents, self, stats)) = ctt + assert(self eq emptyValDef, self) + val att = tmpl.attachments.get[CompoundTypeTreeOriginalAttachment] + val CompoundTypeTreeOriginalAttachment(parents1, stats1) = att.getOrElse(CompoundTypeTreeOriginalAttachment(parents, stats)) + CompoundTypeTree(Template(parents1, self, stats1)) + } + private def toPreTyperTypedOrAnnotated(tree: Tree): Tree = tree match { case ty @ Typed(expr1, tt @ TypeTree()) => if (reifyDebug) println("reify typed: " + tree) @@ -213,7 +250,7 @@ trait Reshape { // [Eugene] is this implemented correctly? private def trimAccessors(deff: Tree, stats: List[Tree]): List[Tree] = { - val symdefs = stats collect { case vodef: ValOrDefDef => vodef } map (vodeff => vodeff.symbol -> vodeff) toMap + val symdefs = (stats collect { case vodef: ValOrDefDef => vodef } map (vodeff => vodeff.symbol -> vodeff)).toMap val accessors = collection.mutable.Map[ValDef, List[DefDef]]() stats collect { case ddef: DefDef => ddef } foreach (defdef => { val valdef = symdefs get defdef.symbol.accessedOrSelf collect { case vdef: ValDef => vdef } getOrElse null @@ -223,8 +260,8 @@ trait Reshape { if (defdef.name.startsWith(prefix)) { var name = defdef.name.toString.substring(prefix.length) def uncapitalize(s: String) = if (s.length == 0) "" else { val chars = s.toCharArray; chars(0) = chars(0).toLower; new String(chars) } - def findValDef(name: String) = symdefs.values collect { case vdef: ValDef if nme.dropLocalSuffix(vdef.name).toString == name => vdef } headOption; - val valdef = findValDef(name) orElse findValDef(uncapitalize(name)) orNull; + def findValDef(name: String) = (symdefs.values collect { case vdef: ValDef if nme.dropLocalSuffix(vdef.name).toString == name => vdef }).headOption + val valdef = findValDef(name).orElse(findValDef(uncapitalize(name))).orNull if (valdef != null) accessors(valdef) = accessors.getOrElse(valdef, Nil) :+ defdef } } diff --git a/src/compiler/scala/reflect/reify/utils/Extractors.scala b/src/compiler/scala/reflect/reify/utils/Extractors.scala new file mode 100644 index 0000000000..52e4ff08c1 --- /dev/null +++ b/src/compiler/scala/reflect/reify/utils/Extractors.scala @@ -0,0 +1,302 @@ +package scala.reflect.reify +package utils + +trait Extractors { + self: Utils => + + import global._ + import definitions._ + import Flag._ + + // Example of a reified tree for `reify(List(1, 2))`: + // (also contains an example of a reified type as a third argument to the constructor of Expr) + // { + // val $u: reflect.runtime.universe.type = scala.reflect.runtime.`package`.universe; + // val $m: $u.Mirror = $u.runtimeMirror(Test.this.getClass().getClassLoader()); + // $u.Expr[List[Int]]($m, { + // final class $treecreator1 extends scala.reflect.base.TreeCreator { + // def <init>(): $treecreator1 = { + // $treecreator1.super.<init>(); + // () + // }; + // def apply[U >: Nothing <: scala.reflect.base.Universe with Singleton]($m$untyped: scala.reflect.base.MirrorOf[U]): U#Tree = { + // val $u: scala.reflect.api.Universe = $m$untyped.universe.asInstanceOf[scala.reflect.api.Universe]; + // val $m: $u.Mirror = $m$untyped.asInstanceOf[$u.Mirror]; + // applyImpl($m).asInstanceOf[U#Tree]; + // } + // def applyImpl[U >: Nothing <: scala.reflect.api.Universe with Singleton]($m$untyped: scala.reflect.base.MirrorOf[U]): U#Tree = { + // val $u: U = $m$untyped.universe; + // val $m: $u.Mirror = $m$untyped.asInstanceOf[$u.Mirror]; + // $u.Apply($u.Select($u.Select($u.build.This($m.staticModule("scala.collection.immutable").moduleClass), $u.newTermName("List")), $u.newTermName("apply")), List($u.Literal($u.Constant(1)), $u.Literal($u.Constant(2)))) + // } + // }; + // new $treecreator1() + // })($u.TypeTag[List[Int]]($m, { + // final class $typecreator1 extends scala.reflect.base.TypeCreator { + // def <init>(): $typecreator1 = { + // $typecreator1.super.<init>(); + // () + // }; + // def apply[U >: Nothing <: scala.reflect.base.Universe with Singleton]($m$untyped: scala.reflect.base.MirrorOf[U]): U#Type = { + // val $u: U = $m$untyped.universe; + // val $m: $u.Mirror = $m$untyped.asInstanceOf[$u.Mirror]; + // $u.TypeRef($u.ThisType($m.staticModule("scala.collection.immutable").moduleClass), $m.staticClass("scala.collection.immutable.List"), List($m.staticClass("scala.Int").asTypeConstructor)) + // } + // }; + // new $typecreator1() + // })) + // } + + private def mkCreator(flavor: TypeName, symtab: SymbolTable, rtree: Tree): Tree = { + val tparamu = newTypeName("U") + val (reifierBase, reifierName, reifierTpt, reifierUniverse) = flavor match { + case tpnme.REIFY_TYPECREATOR_PREFIX => (TypeCreatorClass, nme.apply, SelectFromTypeTree(Ident(tparamu), tpnme.Type), BaseUniverseClass) + case tpnme.REIFY_TREECREATOR_PREFIX => (TreeCreatorClass, nme.applyImpl, SelectFromTypeTree(Ident(BaseUniverseClass), tpnme.Tree), ApiUniverseClass) + case _ => throw new Error(s"unexpected flavor $flavor") + } + val reifierPreamble = flavor match { + case tpnme.REIFY_TYPECREATOR_PREFIX => Nil + case tpnme.REIFY_TREECREATOR_PREFIX => List[Tree]( + DefDef(NoMods, + nme.apply, + List(TypeDef(Modifiers(PARAM), tparamu, List(), TypeBoundsTree(Ident(NothingClass), CompoundTypeTree(Template(List(Ident(BaseUniverseClass), Ident(SingletonClass)), emptyValDef, List()))))), + List(List(ValDef(Modifiers(PARAM), nme.MIRROR_UNTYPED, AppliedTypeTree(Ident(MirrorOfClass), List(Ident(tparamu))), EmptyTree))), + SelectFromTypeTree(Ident(tparamu), tpnme.Tree), + Block( + ValDef(NoMods, nme.UNIVERSE_SHORT, Ident(ApiUniverseClass), TypeApply(Select(Select(Ident(nme.MIRROR_UNTYPED), nme.universe), nme.asInstanceOf_), List(Ident(ApiUniverseClass)))), + ValDef(NoMods, nme.MIRROR_SHORT, Select(Ident(nme.UNIVERSE_SHORT), tpnme.Mirror), TypeApply(Select(Ident(nme.MIRROR_UNTYPED), nme.asInstanceOf_), List(Select(Ident(nme.UNIVERSE_SHORT), tpnme.Mirror)))), + TypeApply(Select(Apply(TypeApply(Ident(reifierName), List(SingletonTypeTree(Ident(nme.UNIVERSE_SHORT)))), List(Ident(nme.MIRROR_SHORT))), nme.asInstanceOf_), List(SelectFromTypeTree(Ident(tparamu), tpnme.Tree))) + )) + ) + case _ => throw new Error(s"unexpected flavor $flavor") + } + val reifierBody = { + def gc(symtab: SymbolTable): SymbolTable = { + def loop(symtab: SymbolTable): SymbolTable = { + def extractNames(tree: Tree) = tree.collect{ case ref: RefTree => ref.name }.toSet + val usedNames = extractNames(rtree) ++ symtab.syms.flatMap(sym => extractNames(symtab.symDef(sym))) + symtab filterAliases { case (_, name) => usedNames(name) } + } + var prev = symtab + var next = loop(symtab) + while (next.syms.length < prev.syms.length) { + prev = next + next = loop(prev) + } + next + } + + val universeAlias = ValDef(NoMods, nme.UNIVERSE_SHORT, Ident(tparamu), Select(Ident(nme.MIRROR_UNTYPED), nme.universe)) + val mirrorAlias = ValDef(NoMods, nme.MIRROR_SHORT, Select(Ident(nme.UNIVERSE_SHORT), tpnme.Mirror), TypeApply(Select(Ident(nme.MIRROR_UNTYPED), nme.asInstanceOf_), List(Select(Ident(nme.UNIVERSE_SHORT), tpnme.Mirror)))) + val trimmedSymtab = if (hasReifier) gc(symtab) else symtab + Block(universeAlias :: mirrorAlias :: trimmedSymtab.encode, rtree) + } + val tpec = ClassDef( + Modifiers(FINAL), + newTypeName(global.currentUnit.fresh.newName(flavor.toString)), + List(), + Template(List(Ident(reifierBase)), + emptyValDef, + List( + DefDef(NoMods, nme.CONSTRUCTOR, List(), List(List()), TypeTree(), Block(List(Apply(Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR), List())), Literal(Constant(())))) + ) ++ reifierPreamble ++ List( + DefDef(NoMods, + reifierName, + List(TypeDef(Modifiers(PARAM), tparamu, List(), TypeBoundsTree(Ident(NothingClass), CompoundTypeTree(Template(List(Ident(reifierUniverse), Ident(SingletonClass)), emptyValDef, List()))))), + List(List(ValDef(Modifiers(PARAM), nme.MIRROR_UNTYPED, AppliedTypeTree(Ident(MirrorOfClass), List(Ident(tparamu))), EmptyTree))), + reifierTpt, reifierBody)))) + Block(tpec, ApplyConstructor(Ident(tpec.name), List())) + } + + private def mkWrapper(universe: Tree, mirror: Tree, wrappee: Tree): Tree = { + val universeAlias = ValDef(NoMods, nme.UNIVERSE_SHORT, SingletonTypeTree(universe), universe) + val mirrorAlias = ValDef(NoMods, nme.MIRROR_SHORT, Select(Ident(nme.UNIVERSE_SHORT), tpnme.Mirror), mirror orElse mkDefaultMirrorRef(global)(universe, typer)) + Block(List(universeAlias, mirrorAlias), wrappee) + } + + object ReifiedTree { + def apply(universe: Tree, mirror: Tree, symtab: SymbolTable, rtree: Tree, tpe: Type, rtpe: Tree, concrete: Boolean): Tree = { + val tagFactory = if (concrete) nme.TypeTag else nme.AbsTypeTag + val tagCtor = TypeApply(Select(Select(Ident(nme.UNIVERSE_SHORT), tagFactory), nme.apply), List(TypeTree(tpe))) + val exprCtor = TypeApply(Select(Select(Ident(nme.UNIVERSE_SHORT), nme.Expr), nme.apply), List(TypeTree(tpe))) + val tagArgs = List(Ident(nme.MIRROR_SHORT), mkCreator(tpnme.REIFY_TYPECREATOR_PREFIX, symtab, rtpe)) + val unwrapped = Apply(Apply(exprCtor, List(Ident(nme.MIRROR_SHORT), mkCreator(tpnme.REIFY_TREECREATOR_PREFIX, symtab, rtree))), List(Apply(tagCtor, tagArgs))) + mkWrapper(universe, mirror, unwrapped) + } + + def unapply(tree: Tree): Option[(Tree, Tree, SymbolTable, Tree, Type, Tree, Boolean)] = tree match { + case Block( + List(udef @ ValDef(_, _, _, universe), mdef @ ValDef(_, _, _, mirror)), + Apply( + Apply(TypeApply(_, List(ttpe @ TypeTree())), List(_, Block(List(ClassDef(_, _, _, Template(_, _, List(_, _, DefDef(_, _, _, _, _, Block(_ :: _ :: symbolTable1, rtree)))))), _))), + // todo. doesn't take into account optimizations such as $u.TypeTag.Int or the upcoming closure optimization + List(Apply(TypeApply(tagFactory @ Select(_, _), _), List(_, Block(List(ClassDef(_, _, _, Template(_, _, List(_, DefDef(_, _, _, _, _, Block(_ :: _ :: symbolTable2, rtpe)))))), _)))))) + if udef.name == nme.UNIVERSE_SHORT && mdef.name == nme.MIRROR_SHORT => + val tagFlavor = tagFactory match { + case Select(Select(_, tagFlavor), _) => tagFlavor + case Select(_, tagFlavor) => tagFlavor + } + Some(universe, mirror, SymbolTable(symbolTable1 ++ symbolTable2), rtree, ttpe.tpe, rtpe, tagFlavor == nme.TypeTag) + case _ => + None + } + } + + object ReifiedType { + def apply(universe: Tree, mirror: Tree, symtab: SymbolTable, tpe: Type, rtpe: Tree, concrete: Boolean) = { + val tagFactory = if (concrete) nme.TypeTag else nme.AbsTypeTag + val ctor = TypeApply(Select(Select(Ident(nme.UNIVERSE_SHORT), tagFactory), nme.apply), List(TypeTree(tpe))) + val args = List(Ident(nme.MIRROR_SHORT), mkCreator(tpnme.REIFY_TYPECREATOR_PREFIX, symtab, rtpe)) + val unwrapped = Apply(ctor, args) + mkWrapper(universe, mirror, unwrapped) + } + + def unapply(tree: Tree): Option[(Tree, Tree, SymbolTable, Type, Tree, Boolean)] = tree match { + case Block( + List(udef @ ValDef(_, _, _, universe), mdef @ ValDef(_, _, _, mirror)), + // todo. doesn't take into account optimizations such as $u.TypeTag.Int or the upcoming closure optimization + Apply(TypeApply(tagFactory @ Select(_, _), List(ttpe @ TypeTree())), List(_, Block(List(ClassDef(_, _, _, Template(_, _, List(_, DefDef(_, _, _, _, _, Block(_ :: _ :: symtab, rtpe)))))), _)))) + if udef.name == nme.UNIVERSE_SHORT && mdef.name == nme.MIRROR_SHORT => + val tagFlavor = tagFactory match { + case Select(Select(_, tagFlavor), _) => tagFlavor + case Select(_, tagFlavor) => tagFlavor + } + Some(universe, mirror, SymbolTable(symtab), ttpe.tpe, rtpe, tagFlavor == nme.TypeTag) + case _ => + None + } + } + + object TreeSplice { + def apply(splicee: Tree): Tree = + Select(splicee, ExprSplice) + + def unapply(tree: Tree): Option[Tree] = tree match { + case Select(splicee, _) if tree.symbol != NoSymbol && tree.symbol == ExprSplice => + Some(splicee) + case _ => + None + } + } + + object FreeDef { + def unapply(tree: Tree): Option[(Tree, TermName, Tree, Long, String)] = tree match { + case FreeTermDef(uref, name, binding, flags, origin) => + Some(uref, name, binding, flags, origin) + case FreeTypeDef(uref, name, binding, flags, origin) => + Some(uref, name, binding, flags, origin) + case _ => + None + } + } + + object FreeTermDef { + def unapply(tree: Tree): Option[(Tree, TermName, Tree, Long, String)] = tree match { + case + ValDef(_, name, _, Apply( + Select(Select(uref1 @ Ident(_), build1), newFreeTerm), + List( + _, + _, + binding, + Apply(Select(Select(uref2 @ Ident(_), build2), flagsFromBits), List(Literal(Constant(flags: Long)))), + Literal(Constant(origin: String))))) + if uref1.name == nme.UNIVERSE_SHORT && build1 == nme.build && newFreeTerm == nme.newFreeTerm && + uref2.name == nme.UNIVERSE_SHORT && build2 == nme.build && flagsFromBits == nme.flagsFromBits => + Some(uref1, name, binding, flags, origin) + case _ => + None + } + } + + object FreeTypeDef { + def unapply(tree: Tree): Option[(Tree, TermName, Tree, Long, String)] = tree match { + case + ValDef(_, name, _, Apply( + Select(Select(uref1 @ Ident(_), build1), newFreeType), + List( + _, + _, + value, + Apply(Select(Select(uref2 @ Ident(_), build2), flagsFromBits), List(Literal(Constant(flags: Long)))), + Literal(Constant(origin: String))))) + if uref1.name == nme.UNIVERSE_SHORT && build1 == nme.build && (newFreeType == nme.newFreeType || newFreeType == nme.newFreeExistential) && + uref2.name == nme.UNIVERSE_SHORT && build2 == nme.build && flagsFromBits == nme.flagsFromBits => + value match { + case Apply(TypeApply(Select(Select(uref3 @ Ident(_), typeTag), apply), List(binding)), List(Literal(Constant(null)), _)) + if uref3.name == nme.UNIVERSE_SHORT && typeTag == nme.TypeTag && apply == nme.apply => + Some(uref1, name, binding, flags, origin) + case Apply(TypeApply(Select(uref3 @ Ident(_), typeTag), List(binding)), List(Literal(Constant(null)), _)) + if uref3.name == nme.UNIVERSE_SHORT && typeTag == nme.TypeTag => + Some(uref1, name, binding, flags, origin) + case _ => + throw new Error("unsupported free type def: %s%n%s".format(value, showRaw(value))) + } + case _ => + None + } + } + + object FreeRef { + def unapply(tree: Tree): Option[(Tree, TermName)] = tree match { + case Apply(Select(Select(uref @ Ident(_), build), ident), List(Ident(name: TermName))) + if build == nme.build && ident == nme.Ident && name.startsWith(nme.REIFY_FREE_PREFIX) => + Some(uref, name) + case _ => + None + } + } + + object SymDef { + def unapply(tree: Tree): Option[(Tree, TermName, Long, Boolean)] = tree match { + case + ValDef(_, name, _, Apply( + Select(Select(uref1 @ Ident(_), build1), newNestedSymbol), + List( + _, + _, + _, + Apply(Select(Select(uref2 @ Ident(_), build2), flagsFromBits), List(Literal(Constant(flags: Long)))), + Literal(Constant(isClass: Boolean))))) + if uref1.name == nme.UNIVERSE_SHORT && build1 == nme.build && newNestedSymbol == nme.newNestedSymbol && + uref2.name == nme.UNIVERSE_SHORT && build2 == nme.build && flagsFromBits == nme.flagsFromBits => + Some(uref1, name, flags, isClass) + case _ => + None + } + } + + object TypeRefToFreeType { + def unapply(tree: Tree): Option[TermName] = tree match { + case Apply(Select(Select(uref @ Ident(_), typeRef), apply), List(Select(_, noSymbol), Ident(freeType: TermName), nil)) + if (uref.name == nme.UNIVERSE_SHORT && typeRef == nme.TypeRef && noSymbol == nme.NoSymbol && freeType.startsWith(nme.REIFY_FREE_PREFIX)) => + Some(freeType) + case _ => + None + } + } + + object BoundTerm { + def unapply(tree: Tree): Option[Tree] = tree match { + case Ident(name) if name.isTermName => + Some(tree) + case This(_) => + Some(tree) + case _ => + None + } + } + + object BoundType { + def unapply(tree: Tree): Option[Tree] = tree match { + case Select(_, name) if name.isTypeName => + Some(tree) + case SelectFromTypeTree(_, name) if name.isTypeName => + Some(tree) + case Ident(name) if name.isTypeName => + Some(tree) + case _ => + None + } + } +} diff --git a/src/compiler/scala/reflect/reify/utils/NodePrinters.scala b/src/compiler/scala/reflect/reify/utils/NodePrinters.scala new file mode 100644 index 0000000000..ce0ab2196a --- /dev/null +++ b/src/compiler/scala/reflect/reify/utils/NodePrinters.scala @@ -0,0 +1,144 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2011 LAMP/EPFL + * @author Martin Odersky + */ +package scala.reflect.reify +package utils + +import scala.compat.Platform.EOL + +trait NodePrinters { + self: Utils => + + import global._ + import definitions._ + import Flag._ + + object reifiedNodeToString extends (Tree => String) { + // [Eugene++ to Martin] can we do better? + // didn't want to invent anything myself in order not to interfere with your line of thought + def bitsToFlags(bits: String): String = { + val flags = bits.toLong + if (flags == NoFlags) nme.NoFlags.toString + else { + val s_flags = new collection.mutable.ListBuffer[String] + if (flags containsAll TRAIT) s_flags += "TRAIT" + if (flags containsAll MODULE) s_flags += "MODULE" + if (flags containsAll MUTABLE) s_flags += "MUTABLE" + if (flags containsAll PACKAGE) s_flags += "PACKAGE" + if (flags containsAll METHOD) s_flags += "METHOD" + if (flags containsAll DEFERRED) s_flags += "DEFERRED" + if (flags containsAll ABSTRACT) s_flags += "ABSTRACT" + if (flags containsAll FINAL) s_flags += "FINAL" + if (flags containsAll SEALED) s_flags += "SEALED" + if (flags containsAll IMPLICIT) s_flags += "IMPLICIT" + if (flags containsAll LAZY) s_flags += "LAZY" + if (flags containsAll OVERRIDE) s_flags += "OVERRIDE" + if (flags containsAll PRIVATE) s_flags += "PRIVATE" + if (flags containsAll PROTECTED) s_flags += "PROTECTED" + if (flags containsAll CASE) s_flags += "CASE" + if (flags containsAll ABSOVERRIDE) s_flags += "ABSOVERRIDE" + if (flags containsAll BYNAMEPARAM) s_flags += "BYNAMEPARAM" + if (flags containsAll PARAM) s_flags += "PARAM" + if (flags containsAll PARAMACCESSOR) s_flags += "PARAMACCESSOR" + if (flags containsAll CASEACCESSOR) s_flags += "CASEACCESSOR" + if (flags containsAll COVARIANT) s_flags += "COVARIANT" + if (flags containsAll CONTRAVARIANT) s_flags += "CONTRAVARIANT" + if (flags containsAll DEFAULTPARAM) s_flags += "DEFAULTPARAM" + if (flags containsAll INTERFACE) s_flags += "INTERFACE" + s_flags mkString " | " + } + } + + def apply(tree: Tree): String = { + var mirrorIsUsed = false + var flagsAreUsed = false + + // @PP: I fervently hope this is a test case or something, not anything being + // depended upon. Of more fragile code I cannot conceive. + // @Eugene: This stuff is only needed to debug-print out reifications in human-readable format + // Rolling a full-fledged, robust TreePrinter would be several times more code. + val lines = (tree.toString.split(EOL) drop 1 dropRight 1).toList splitAt 2 + var (List(universe, mirror), reification) = lines + reification = (for (line <- reification) yield { + var s = line substring 2 + s = s.replace(nme.UNIVERSE_PREFIX.toString, "") + s = s.replace(".apply", "") + s = "([^\"])scala\\.collection\\.immutable\\.".r.replaceAllIn(s, "$1") + s = "List\\[List\\[.*?\\].*?\\]".r.replaceAllIn(s, "List") + s = "List\\[.*?\\]".r.replaceAllIn(s, "List") + s = s.replace("immutable.this.Nil", "List()") + s = """build\.flagsFromBits\((\d+)[lL]\)""".r.replaceAllIn(s, m => { + flagsAreUsed = true + bitsToFlags(m.group(1)) + }) + s = s.replace("Modifiers(0L, newTypeName(\"\"), List())", "Modifiers()") + s = """Modifiers\((\d+)[lL], newTypeName\("(.*?)"\), List\((.*?)\)\)""".r.replaceAllIn(s, m => { + val buf = new collection.mutable.ListBuffer[String] + + val annotations = m.group(3) + if (buf.nonEmpty || annotations.nonEmpty) + buf.append("List(" + annotations + ")") + + val privateWithin = "" + m.group(2) + if (buf.nonEmpty || privateWithin != "") + buf.append("newTypeName(\"" + privateWithin + "\")") + + val bits = m.group(1) + if (buf.nonEmpty || bits != "0L") { + flagsAreUsed = true + buf.append(bitsToFlags(bits)) + } + + val replacement = "Modifiers(" + buf.reverse.mkString(", ") + ")" + java.util.regex.Matcher.quoteReplacement(replacement) + }) + s + }) + + val isExpr = reification.length > 0 && reification(0).trim.startsWith("Expr[") + var rtree = reification dropWhile (!_.trim.startsWith(s"val ${nme.UNIVERSE_SHORT}: U = ${nme.MIRROR_UNTYPED}.universe;")) + rtree = rtree drop 2 + rtree = rtree takeWhile (_ != " }") + rtree = rtree map (s0 => { + var s = s0 + mirrorIsUsed |= s contains nme.MIRROR_PREFIX.toString + s = s.replace(nme.MIRROR_PREFIX.toString, "") + s.trim + }) + + val printout = collection.mutable.ListBuffer[String](); + printout += universe.trim + if (mirrorIsUsed) printout += mirror.replace("MirrorOf[", "scala.reflect.base.MirrorOf[").trim + val imports = collection.mutable.ListBuffer[String](); + imports += nme.UNIVERSE_SHORT + // if (buildIsUsed) imports += nme.build + if (mirrorIsUsed) imports += nme.MIRROR_SHORT + if (flagsAreUsed) imports += nme.Flag + printout += s"""import ${imports map (_ + "._") mkString ", "}""" + + val name = if (isExpr) "tree" else "tpe" + if (rtree(0) startsWith "val") { + printout += s"val $name = {" + printout ++= (rtree map (" " + _)) + printout += "}" + } else { + printout += s"val $name = " + rtree(0) + } + if (isExpr) { + if (mirror contains ".getClassLoader") { + printout += "import scala.tools.reflect.ToolBox" + printout += s"println(${nme.MIRROR_SHORT}.mkToolBox().runExpr(tree))" + } else { + printout += "println(tree)" + } + } else { + printout += "println(tpe)" + } + + // printout mkString EOL + val prefix = "// produced from " + reifier.defaultErrorPosition + (prefix +: "object Test extends App {" +: (printout map (" " + _)) :+ "}") mkString EOL + } + } +} diff --git a/src/compiler/scala/reflect/reify/utils/StdAttachments.scala b/src/compiler/scala/reflect/reify/utils/StdAttachments.scala new file mode 100644 index 0000000000..abbed814e0 --- /dev/null +++ b/src/compiler/scala/reflect/reify/utils/StdAttachments.scala @@ -0,0 +1,12 @@ +package scala.reflect.reify +package utils + +trait StdAttachments { + self: Utils => + + import global._ + + case class ReifyBindingAttachment(binding: Symbol) + + case class ReifyAliasAttachment(binding: Symbol, alias: TermName) +}
\ No newline at end of file diff --git a/src/compiler/scala/reflect/reify/utils/SymbolTables.scala b/src/compiler/scala/reflect/reify/utils/SymbolTables.scala new file mode 100644 index 0000000000..a7ac299317 --- /dev/null +++ b/src/compiler/scala/reflect/reify/utils/SymbolTables.scala @@ -0,0 +1,223 @@ +package scala.reflect.reify +package utils + +import scala.collection._ +import scala.compat.Platform.EOL + +trait SymbolTables { + self: Utils => + + import global._ + import definitions._ + import Flag._ + + class SymbolTable private[SymbolTable] ( + private[SymbolTable] val symtab: immutable.ListMap[Symbol, Tree] = immutable.ListMap[Symbol, Tree](), + private[SymbolTable] val aliases: List[(Symbol, TermName)] = List[(Symbol, TermName)](), + private[SymbolTable] val original: Option[List[Tree]] = None) { + + def syms: List[Symbol] = symtab.keys.toList + +// def aliases: Map[Symbol, List[TermName]] = aliases.distinct groupBy (_._1) mapValues (_ map (_._2)) + + def symDef(sym: Symbol): Tree = + symtab.getOrElse(sym, EmptyTree) + + def symName(sym: Symbol): TermName = + symtab.get(sym) match { + case Some(FreeDef(_, name, _, _, _)) => name + case Some(SymDef(_, name, _, _)) => name + case None => EmptyTermName + } + + def symAliases(sym: Symbol): List[TermName] = + symName(sym) match { + case name if name.isEmpty => Nil + case _ => (aliases.distinct groupBy (_._1) mapValues (_ map (_._2)))(sym) + } + + def symBinding(sym: Symbol): Tree = + symtab.get(sym) match { + case Some(FreeDef(_, _, binding, _, _)) => binding + case Some(SymDef(_, _, _, _)) => throw new UnsupportedOperationException(s"${symtab(sym)} is a symdef, hence it doesn't have a binding") + case None => EmptyTree + } + + def symRef(sym: Symbol): Tree = + symtab.get(sym) match { + case Some(FreeDef(_, name, _, _, _)) => Ident(name) addAttachment ReifyBindingAttachment(sym) + case Some(SymDef(_, name, _, _)) => Ident(name) addAttachment ReifyBindingAttachment(sym) + case None => EmptyTree + } + + def +(sym: Symbol, name: TermName, reification: Tree): SymbolTable = add(sym, name, reification) + def +(sym: Symbol, name: TermName): SymbolTable = add(sym, name) + def +(symDef: Tree): SymbolTable = add(symDef) + def ++(symDefs: TraversableOnce[Tree]): SymbolTable = (this /: symDefs)((symtab, symDef) => symtab.add(symDef)) + def ++(symtab: SymbolTable): SymbolTable = { val updated = this ++ symtab.symtab.values; new SymbolTable(updated.symtab, updated.aliases ++ symtab.aliases) } + def -(sym: Symbol): SymbolTable = remove(sym) + def -(name: TermName): SymbolTable = remove(name) + def -(symDef: Tree): SymbolTable = remove(binding(symDef)) + def --(syms: GenTraversableOnce[Symbol]): SymbolTable = (this /: syms)((symtab, sym) => symtab.remove(sym)) + def --(names: Iterable[TermName]): SymbolTable = (this /: names)((symtab, name) => symtab.remove(name)) + def --(symDefs: TraversableOnce[Tree]): SymbolTable = this -- (symDefs map (binding(_))) + def --(symtab: SymbolTable): SymbolTable = { val updated = this -- symtab.symtab.values; new SymbolTable(updated.symtab, updated.aliases diff symtab.aliases) } + def filterSyms(p: Symbol => Boolean): SymbolTable = this -- (syms filterNot p) + def filterAliases(p: (Symbol, TermName) => Boolean): SymbolTable = this -- (aliases filterNot (tuple => p(tuple._1, tuple._2)) map (_._2)) + + private def add(symDef: Tree): SymbolTable = { + val sym = binding(symDef) + assert(sym != NoSymbol, showRaw(symDef)) + val name = symDef match { + case FreeDef(_, name, _, _, _) => name + case SymDef(_, name, _, _) => name + } + val newSymtab = if (!(symtab contains sym)) symtab + (sym -> symDef) else symtab + val newAliases = aliases :+ (sym -> name) + new SymbolTable(newSymtab, newAliases) + } + + private def add(sym: Symbol, name0: TermName, reification: Tree): SymbolTable = { + def freshName(name0: TermName): TermName = { + var name = name0.toString + name = name.replace(".type", "$type") + name = name.replace(" ", "$") + val fresh = typer.context.unit.fresh + newTermName(fresh.newName(name)) + } + add(ValDef(NoMods, freshName(name0), TypeTree(), reification) addAttachment ReifyBindingAttachment(sym)) + } + + private def add(sym: Symbol, name: TermName): SymbolTable = { + if (!(syms contains sym)) error("cannot add an alias to a symbol not in the symbol table") + add(sym, name, EmptyTree) + } + + private def remove(sym: Symbol): SymbolTable = { + val newSymtab = symtab - sym + val newAliases = aliases filter (_._1 != sym) + new SymbolTable(newSymtab, newAliases) + } + + private def remove(name: TermName): SymbolTable = { + var newSymtab = symtab + val newAliases = aliases filter (_._2 != name) + newSymtab = newSymtab filter { case ((sym, _)) => newAliases exists (_._1 == sym) } + newSymtab = newSymtab map { case ((sym, tree)) => + val ValDef(mods, primaryName, tpt, rhs) = tree + val tree1 = + if (!(newAliases contains (sym, primaryName))) { + val primaryName1 = newAliases.find(_._1 == sym).get._2 + ValDef(mods, primaryName1, tpt, rhs).copyAttrs(tree) + } else tree + (sym, tree1) + } + new SymbolTable(newSymtab, newAliases) + } + + private def binding(tree: Tree): Symbol = + tree.attachments.get[ReifyBindingAttachment] match { + case Some(ReifyBindingAttachment(binding)) => binding + case other => NoSymbol + } + + private val cache = mutable.Map[SymbolTable, List[Tree]]() + def encode: List[Tree] = cache.getOrElseUpdate(this, SymbolTable.encode(this)) map (_.duplicate) + + override def toString = { + val symtabString = symtab.keys.map(symName(_)).mkString(", ") + val trueAliases = aliases.distinct.filter(entry => symName(entry._1) != entry._2) + val aliasesString = trueAliases.map(entry => s"${symName(entry._1)} -> ${entry._2}").mkString(", ") + s"""symtab = [$symtabString], aliases = [$aliasesString]${if (original.isDefined) ", has original" else ""}""" + } + + def debugString: String = { + val buf = new StringBuilder + buf.append("symbol table = " + (if (syms.length == 0) "<empty>" else "")).append(EOL) + syms foreach (sym => buf.append(symDef(sym)).append(EOL)) + buf.delete(buf.length - EOL.length, buf.length) + buf.toString + } + } + + object SymbolTable { + def apply(): SymbolTable = + new SymbolTable() + + def apply(encoded: List[Tree]): SymbolTable = { + var result = new SymbolTable(original = Some(encoded)) + encoded foreach (entry => (entry.attachments.get[ReifyBindingAttachment], entry.attachments.get[ReifyAliasAttachment]) match { + case (Some(ReifyBindingAttachment(sym)), _) => result += entry + case (_, Some(ReifyAliasAttachment(sym, alias))) => result = new SymbolTable(result.symtab, result.aliases :+ (sym, alias)) + case _ => // do nothing, this is boilerplate that can easily be recreated by subsequent `result.encode` + }) + result + } + + private[SymbolTable] def encode(symtab0: SymbolTable): List[Tree] = { + if (symtab0.original.isDefined) return symtab0.original.get.map(_.duplicate) + else assert(hasReifier, "encoding a symbol table requires a reifier") + // during `encode` we might need to do some reifications + // these reifications might lead to changes in `reifier.symtab` + // reifier is mutable, symtab is immutable. this is a tough friendship + val backup = reifier.state.backup + reifier.state.symtab = symtab0.asInstanceOf[reifier.SymbolTable] + def currtab = reifier.symtab.asInstanceOf[SymbolTable] + try { + val cumulativeSymtab = mutable.ArrayBuffer[Tree](symtab0.symtab.values.toList: _*) + val cumulativeAliases = mutable.ArrayBuffer[(Symbol, TermName)](symtab0.aliases: _*) + + def fillInSymbol(sym: Symbol): Tree = { + if (reifyDebug) println("Filling in: %s (%s)".format(sym, sym.accurateKindString)) + val isFree = currtab.symName(sym) startsWith nme.REIFY_FREE_PREFIX + if (isFree) { + if (sym.annotations.isEmpty) EmptyTree + else Apply(Select(currtab.symRef(sym), nme.setAnnotations), List(reifier.reify(sym.annotations))) + } else { + import scala.reflect.internal.Flags._ + if (sym hasFlag LOCKED) { + // [Eugene] better to have a symbol without a type signature, than to crash with a CyclicReference + EmptyTree + } else { + val rset = reifier.mirrorBuildCall(nme.setTypeSignature, currtab.symRef(sym), reifier.reify(sym.info)) + if (sym.annotations.isEmpty) rset + else reifier.mirrorBuildCall(nme.setAnnotations, rset, reifier.mkList(sym.annotations map reifier.reifyAnnotationInfo)) + } + } + } + + // `fillInSymbol` might add symbols to `symtab`, that's why this is done iteratively + var progress = 0 + while (progress < cumulativeSymtab.length) { + val sym = currtab.binding(cumulativeSymtab(progress)) + if (sym != NoSymbol) { + val symtabProgress = currtab.symtab.size + val aliasesProgress = currtab.aliases.length + val fillIn = fillInSymbol(sym) + cumulativeSymtab ++= currtab.symtab.values drop symtabProgress + cumulativeAliases ++= currtab.aliases drop aliasesProgress + cumulativeSymtab += fillIn + } + progress += 1 + } + + val withAliases = cumulativeSymtab flatMap (entry => { + val result = mutable.ListBuffer[Tree]() + result += entry + val sym = currtab.binding(entry) + if (sym != NoSymbol) + result ++= cumulativeAliases.distinct filter (alias => alias._1 == sym && alias._2 != currtab.symName(sym)) map (alias => { + val canonicalName = currtab.symName(sym) + val aliasName = alias._2 + ValDef(NoMods, aliasName, TypeTree(), Ident(canonicalName)) addAttachment ReifyAliasAttachment(sym, aliasName) + }) + result.toList + }) + + withAliases.toList + } finally { + reifier.state.restore(backup) + } + } + } +}
\ No newline at end of file diff --git a/src/compiler/scala/reflect/reify/utils/Utils.scala b/src/compiler/scala/reflect/reify/utils/Utils.scala new file mode 100644 index 0000000000..e1213f932c --- /dev/null +++ b/src/compiler/scala/reflect/reify/utils/Utils.scala @@ -0,0 +1,21 @@ +package scala.reflect.reify +package utils + +import scala.tools.nsc.Global + +trait Utils extends NodePrinters + with Extractors + with SymbolTables + with StdAttachments { + + val global: Global + val typer: global.analyzer.Typer + + lazy val reifier: Reifier { val global: Utils.this.global.type } = getReifier + def getReifier: Reifier { val global: Utils.this.global.type } = ??? + def hasReifier = false + + val reifyDebug = global.settings.Yreifydebug.value + val reifyCopypaste = global.settings.Yreifycopypaste.value + val reifyTrace = scala.tools.nsc.util.trace when reifyDebug +}
\ No newline at end of file diff --git a/src/compiler/scala/reflect/runtime/ClassLoaders.scala b/src/compiler/scala/reflect/runtime/ClassLoaders.scala deleted file mode 100644 index b73d57c04d..0000000000 --- a/src/compiler/scala/reflect/runtime/ClassLoaders.scala +++ /dev/null @@ -1,25 +0,0 @@ -package scala.reflect -package runtime - -trait ClassLoaders extends internal.SymbolTable { self: SymbolTable => - - def staticClass(fullname: String) = - definitions.getRequiredClass(fullname) - - def staticModule(fullname: String) = - definitions.getRequiredModule(fullname) - - /** If `owner` is a package class (but not the empty package) and `name` is a term name, make a new package - * <owner>.<name>, otherwise return NoSymbol. - * Exception: If owner is root and a java class with given name exists, create symbol in empty package instead. - */ - override def missingHook(owner: Symbol, name: Name): Symbol = - if (owner.isRoot && isJavaClass(name.toString)) - definitions.EmptyPackageClass.info decl name - else if (name.isTermName && owner.hasPackageFlag && !owner.isEmptyPackageClass) - makeScalaPackage(if (owner.isRoot) name.toString else owner.fullName+"."+name).sourceModule - else { - info("*** missing: "+name+"/"+name.isTermName+"/"+owner+"/"+owner.hasPackageFlag+"/"+owner.info.decls.getClass) - super.missingHook(owner, name) - } -} diff --git a/src/compiler/scala/reflect/runtime/ConversionUtil.scala b/src/compiler/scala/reflect/runtime/ConversionUtil.scala deleted file mode 100644 index e45fc243c6..0000000000 --- a/src/compiler/scala/reflect/runtime/ConversionUtil.scala +++ /dev/null @@ -1,92 +0,0 @@ -package scala.reflect -package runtime - -import java.lang.{Class => jClass, Package => jPackage} -import java.lang.reflect.{ - Method => jMethod, Constructor => jConstructor, Modifier => jModifier, Field => jField, - Member => jMember, Type => jType, TypeVariable => jTypeVariable, GenericDeclaration} -import collection.mutable.HashMap - -trait ConversionUtil { self: SymbolTable => - - /** A cache that maintains a bijection between Java reflection type `J` - * and Scala reflection type `S`. - */ - // todo. should be weak - protected class TwoWayCache[J, S] { - - private val toScalaMap = new HashMap[J, S] - private val toJavaMap = new HashMap[S, J] - - def enter(j: J, s: S) = synchronized { - debugInfo("cached: "+j+"/"+s) - toScalaMap(j) = s - toJavaMap(s) = j - } - - def toScala(key: J)(body: => S): S = synchronized { - toScalaMap get key match { - case Some(v) => - v - case none => - val result = body - enter(key, result) - result - } - } - - def toJava(key: S)(body: => J): J = synchronized { - toJavaMap get key match { - case Some(v) => - v - case none => - val result = body - enter(result, key) - result - } - } - - def toJavaOption(key: S)(body: => Option[J]): Option[J] = synchronized { - toJavaMap get key match { - case None => - val result = body - for (value <- result) enter(value, key) - result - case some => some - } - } - } - - protected val classCache = new TwoWayCache[jClass[_], Symbol] - protected val packageCache = new TwoWayCache[Package, Symbol] - protected val methodCache = new TwoWayCache[jMethod, Symbol] - protected val constructorCache = new TwoWayCache[jConstructor[_], Symbol] - protected val fieldCache = new TwoWayCache[jField, Symbol] - protected val tparamCache = new TwoWayCache[jTypeVariable[_], Symbol] - - /** the type of this symbol after Scala -> Java transformsi in refChecks, uncurry, erasure - */ - def transformedType(sym: Symbol): Type - - /** The Java class thaty given type compiles to */ - def typeToJavaClass(tpe: Type): jClass[_] - - /** Does method `meth` erase to Java method `jmeth`? - * This is true if the Java method type is the same as the Scala method type after performing - * all Scala-specific transformations in InfoTransformers. (to be done) - */ - protected def erasesTo(meth: Symbol, jmeth: jMethod): Boolean = { - val mtpe = transformedType(meth) - (mtpe.paramTypes map typeToJavaClass) == jmeth.getParameterTypes.toList && - typeToJavaClass(mtpe.resultType) == jmeth.getReturnType - } - - /** Does constructor `meth` erase to Java method `jconstr`? - * This is true if the Java constructor type is the same as the Scala constructor type after performing - * all Scala-specific transformations in InfoTransformers. (to be done) - */ - protected def erasesTo(meth: Symbol, jconstr: jConstructor[_]): Boolean = { - val mtpe = transformedType(meth) - (mtpe.paramTypes map typeToJavaClass) == jconstr.getParameterTypes.toList - } -}
\ No newline at end of file diff --git a/src/compiler/scala/reflect/runtime/JavaToScala.scala b/src/compiler/scala/reflect/runtime/JavaToScala.scala deleted file mode 100644 index e11f6140c9..0000000000 --- a/src/compiler/scala/reflect/runtime/JavaToScala.scala +++ /dev/null @@ -1,697 +0,0 @@ -package scala.reflect -package runtime - -import java.lang.{ Class => jClass, Package => jPackage, ClassLoader => JClassLoader } -import java.io.IOException -import java.lang.reflect.{ - Method => jMethod, - Constructor => jConstructor, - Modifier => jModifier, - Field => jField, - Member => jMember, - Type => jType, - TypeVariable => jTypeVariable, - GenericDeclaration, - GenericArrayType, - ParameterizedType, - WildcardType, - AnnotatedElement -} -import internal.MissingRequirementError -import internal.pickling.ByteCodecs -import internal.ClassfileConstants._ -import internal.pickling.UnPickler -import collection.mutable.{ HashMap, ListBuffer } -import internal.Flags._ -import scala.tools.nsc.util.ScalaClassLoader -import scala.tools.nsc.util.ScalaClassLoader._ - -trait JavaToScala extends ConversionUtil { self: SymbolTable => - - import definitions._ - - private object unpickler extends UnPickler { - val global: JavaToScala.this.type = self - } - - /** Defines the classloader that will be used for all class resolution activities in this mirror. - * Is mutable, since sometimes we need to change it in flight (e.g. to make the default mirror work with REPL). - * - * If you want to have a mirror with non-standard class resolution, override this var - * (or, even simpler, use the `mkMirror` function from `scala.reflect` package) - * - * Be careful, though, since fancy stuff might happen. - * Here's one example: - * - * partest uses a URLClassLoader(urls, null) with custom classpath to run workers (in separate threads) - * however it doesn't set the context classloader for them, so they inherit the system classloader - * http://www.javaworld.com/javaworld/javaqa/2003-06/01-qa-0606-load.html - * - * Once upon a time, scala.reflect.mirror was loaded using getClass.getClassLoader, - * which also means that classOf[...] constructs such as: - * - * classOf[scala.reflect.ScalaSignature] - * - * in unpickleClass were also loaded by the URLClassLoader - * - * But mirror's classLoader used Thread.currentThread.getContextClassLoader, - * which introduced a subtle bug that made the following snippet incorrectly: - * - * jclazz.getAnnotation(classOf[scala.reflect.ScalaSignature]) - * - * Indeed, jclazz was loaded by context classloader, which defaulted to system classloader, - * while ScalaSignature class was loaded by getClass.getClassLoader, which was incompatible with system classloader. - * As a result, unpickler couldn't see the signature and that blew up the mirror. - */ - var classLoader: ClassLoader - - /** Paul: It seems the default class loader does not pick up root classes, whereas the system classloader does. - * Can you check with your newly acquired classloader fu whether this implementation makes sense? - */ - def javaClass(path: String): jClass[_] = - javaClass(path, classLoader) - def javaClass(path: String, classLoader: JClassLoader): jClass[_] = - Class.forName(path, true, classLoader) - - /** Does `path` correspond to a Java class with that fully qualified name? */ - def isJavaClass(path: String): Boolean = - try { - javaClass(path) - true - } catch { - case (_: ClassNotFoundException) | (_: NoClassDefFoundError) | (_: IncompatibleClassChangeError) => - false - } - - /** - * Generate types for top-level Scala root class and root companion object - * from the pickled information stored in a corresponding Java class - * @param clazz The top-level Scala class for which info is unpickled - * @param module The top-level Scala companion object for which info is unpickled - * @param jclazz The Java class which contains the unpickled information in a - * ScalaSignature or ScalaLongSignature annotation. - */ - def unpickleClass(clazz: Symbol, module: Symbol, jclazz: jClass[_]): Unit = { - def markAbsent(tpe: Type) = setAllInfos(clazz, module, tpe) - def handleError(ex: Exception) = { - markAbsent(ErrorType) - if (settings.debug.value) ex.printStackTrace() - val msg = ex.getMessage() - MissingRequirementError.signal( - (if (msg eq null) "reflection error while loading " + clazz.name - else "error while loading " + clazz.name) + ", " + msg) - } - // don't use classOf[scala.reflect.ScalaSignature] here, because it will use getClass.getClassLoader, not mirror's classLoader - // don't use asInstanceOf either because of the same reason (lol, I cannot believe I fell for it) - // don't use structural types to simplify reflective invocations because of the same reason - // todo. test for this - def loadAnnotation(name: String): java.lang.annotation.Annotation = { - def inferClasspath(cl: ClassLoader) = cl match { - case cl: java.net.URLClassLoader => "[" + (cl.getURLs mkString ",") + "]" - case _ => "<unknown>" - } - def show(cl: ClassLoader) = cl match { - case cl if cl != null => - "%s of type %s with classpath %s".format(cl, cl.getClass, inferClasspath(cl)) - case null => - import scala.tools.util.PathResolver.Environment._ - "primordial classloader with boot classpath [%s]".format(javaBootClassPath) - } - - try { - val cls_ann = Class.forName(name, true, classLoader) - val anns = jclazz.getAnnotations - val ann = anns find (_.annotationType == cls_ann) orNull; - if (ann == null && anns.find(_.annotationType.getName == name).isDefined) { - val msg = "Mirror classloader mismatch: %s (loaded by %s)%nis unrelated to the mirror's classloader (%s)" - throw new Error(msg.format(jclazz, show(jclazz.getClassLoader), show(classLoader))) - } - ann - } catch { - case ex: ClassNotFoundException => - val msg = "Dysfunctional mirror classloader, cannot load %s: %s." - throw new Error(msg.format(name, show(classLoader)), ex) - } - } - def loadScalaSignature: Option[String] = { - val ssig = loadAnnotation("scala.reflect.ScalaSignature") - if (ssig != null) { - val bytesMethod = ssig.annotationType.getMethod("bytes") - val result = bytesMethod.invoke(ssig) - Some(result.asInstanceOf[String]) - } else { - None - } - } - def loadScalaLongSignature: Option[Array[String]] = { - val slsig = loadAnnotation("scala.reflect.ScalaLongSignature") - if (slsig != null) { - val bytesMethod = slsig.annotationType.getMethod("bytes") - val result = bytesMethod.invoke(slsig) - Some(result.asInstanceOf[Array[String]]) - } else { - None - } - } - try { - markAbsent(NoType) - val sigs = (loadScalaSignature, loadScalaLongSignature) - sigs match { - case (Some(ssig), _) => - info("unpickling Scala "+clazz + " and " + module+ ", owner = " + clazz.owner) - val bytes = ssig.getBytes - val len = ByteCodecs.decode(bytes) - unpickler.unpickle(bytes take len, 0, clazz, module, jclazz.getName) - case (_, Some(slsig)) => - info("unpickling Scala "+clazz + " and " + module + " with long Scala signature") - val byteSegments = slsig map (_.getBytes) - val lens = byteSegments map ByteCodecs.decode - val bytes = Array.ofDim[Byte](lens.sum) - var len = 0 - for ((bs, l) <- byteSegments zip lens) { - bs.copyToArray(bytes, len, l) - len += l - } - unpickler.unpickle(bytes, 0, clazz, module, jclazz.getName) - case (None, None) => - // class does not have a Scala signature; it's a Java class - info("translating reflection info for Java " + jclazz) //debug - initClassModule(clazz, module, new FromJavaClassCompleter(clazz, module, jclazz)) - } - } catch { - case ex: MissingRequirementError => - handleError(ex) - case ex: IOException => - handleError(ex) - } - } - - /** - * A fresh Scala type parameter that corresponds to a Java type variable. - * The association between Scala type parameter and Java type variable is entered in the cache. - * @param jtvar The Java type variable - */ - private def createTypeParameter(jtvar: jTypeVariable[_ <: GenericDeclaration]): Symbol = { - val tparam = sOwner(jtvar).newTypeParameter(newTypeName(jtvar.getName)) - .setInfo(new TypeParamCompleter(jtvar)) - tparamCache enter (jtvar, tparam) - tparam - } - - /** - * A completer that fills in the type of a Scala type parameter from the bounds of a Java type variable. - * @param jtvar The Java type variable - */ - private class TypeParamCompleter(jtvar: jTypeVariable[_ <: GenericDeclaration]) extends LazyType { - override def load(sym: Symbol) = complete(sym) - override def complete(sym: Symbol) = { - sym setInfo TypeBounds.upper(glb(jtvar.getBounds.toList map typeToScala map objToAny)) - } - } - - /** - * Copy all annotations of Java annotated element `jann` over to Scala symbol `sym`. - * Pre: `sym` is already initialized with a concrete type. - * Note: If `sym` is a method or constructor, its parameter annotations are copied as well. - */ - private def copyAnnotations(sym: Symbol, jann: AnnotatedElement) { - // to do: implement - } - - /** - * A completer that fills in the types of a Scala class and its companion object - * by copying corresponding type info from a Java class. This completer is used - * to reflect classes in Scala that do not have a Scala pickle info, be it - * because they are local classes or have been compiled from Java sources. - * @param clazz The Scala class for which info is copied - * @param module The Scala companion object for which info is copied - * @param jclazz The Java class - */ - private class FromJavaClassCompleter(clazz: Symbol, module: Symbol, jclazz: jClass[_]) extends LazyType { - override def load(sym: Symbol) = { - debugInfo("completing from Java " + sym + "/" + clazz.fullName)//debug - assert(sym == clazz || (module != NoSymbol && (sym == module || sym == module.moduleClass)), sym) - val flags = toScalaClassFlags(jclazz.getModifiers) - clazz setFlag (flags | JAVA) - if (module != NoSymbol) { - module setFlag (flags & PRIVATE | JAVA) - module.moduleClass setFlag (flags & PRIVATE | JAVA) - } - - copyAnnotations(clazz, jclazz) - // to do: annotations to set also for module? - - clazz setInfo new LazyPolyType(jclazz.getTypeParameters.toList map createTypeParameter) - if (module != NoSymbol) { - module setInfo module.moduleClass.tpe - module.moduleClass setInfo new LazyPolyType(List()) - } - } - - override def complete(sym: Symbol): Unit = { - load(sym) - completeRest() - } - def completeRest(): Unit = self.synchronized { - val tparams = clazz.rawInfo.typeParams - - val parents = try { - parentsLevel += 1 - val jsuperclazz = jclazz.getGenericSuperclass - val superclazz = if (jsuperclazz == null) AnyClass.tpe else typeToScala(jsuperclazz) - superclazz :: (jclazz.getGenericInterfaces.toList map typeToScala) - } finally { - parentsLevel -= 1 - } - clazz setInfo GenPolyType(tparams, new ClassInfoType(parents, newScope, clazz)) - if (module != NoSymbol) { - module.moduleClass setInfo new ClassInfoType(List(), newScope, module.moduleClass) - } - - def enter(sym: Symbol, mods: Int) = - (if (jModifier.isStatic(mods)) module.moduleClass else clazz).info.decls enter sym - - for (jinner <- jclazz.getDeclaredClasses) { - enter(jclassAsScala(jinner, clazz), jinner.getModifiers) - } - - pendingLoadActions = { () => - - for (jfield <- jclazz.getDeclaredFields) - enter(jfieldAsScala(jfield), jfield.getModifiers) - - for (jmeth <- jclazz.getDeclaredMethods) - enter(jmethodAsScala(jmeth), jmeth.getModifiers) - - for (jconstr <- jclazz.getConstructors) - enter(jconstrAsScala(jconstr), jconstr.getModifiers) - - } :: pendingLoadActions - - if (parentsLevel == 0) { - while (!pendingLoadActions.isEmpty) { - val item = pendingLoadActions.head - pendingLoadActions = pendingLoadActions.tail - item() - } - } - } - class LazyPolyType(override val typeParams: List[Symbol]) extends LazyType { - override def complete(sym: Symbol) { - completeRest() - } - } - } - - /** used to avoid cyclies */ - var parentsLevel = 0 - var pendingLoadActions: List[() => Unit] = Nil - - /** - * If Java modifiers `mods` contain STATIC, return the module class - * of the companion module of `clazz`, otherwise the class `clazz` itself. - */ - private def followStatic(clazz: Symbol, mods: Int) = - if (jModifier.isStatic(mods)) clazz.companionModule.moduleClass else clazz - - /** Methods which need to be wrapped because they either are getSimpleName - * or call getSimpleName: - * - * public String getSimpleName() - * public boolean isAnonymousClass() - * public boolean isLocalClass() - * public boolean isMemberClass() - * public String getCanonicalName() - * - * TODO - find all such calls and wrap them. - * TODO - create mechanism to avoid the recurrence of unwrapped calls. - */ - private def wrapClassCheck[T](alt: T)(body: => T): T = - try body catch { case x: InternalError if x.getMessage == "Malformed class name" => alt } - - private def wrapIsLocalClass(clazz: jClass[_]): Boolean = - wrapClassCheck(false)(clazz.isLocalClass) - - private def wrapGetSimpleName(clazz: jClass[_]): String = - wrapClassCheck("")(clazz.getSimpleName) - - /** - * The Scala owner of the Scala class corresponding to the Java class `jclazz` - */ - private def sOwner(jclazz: jClass[_]): Symbol = { - if (jclazz.isMemberClass) { - val jEnclosingClass = jclazz.getEnclosingClass - val sEnclosingClass = classToScala(jEnclosingClass) - followStatic(sEnclosingClass, jclazz.getModifiers) - } else if (wrapIsLocalClass(jclazz)) { - val jEnclosingMethod = jclazz.getEnclosingMethod - if (jEnclosingMethod != null) { - methodToScala(jEnclosingMethod) - } else { - val jEnclosingConstructor = jclazz.getEnclosingConstructor - constrToScala(jEnclosingConstructor) - } - } else if (jclazz.isPrimitive || jclazz.isArray) { - ScalaPackageClass - } else if (jclazz.getPackage != null) { - val jPackage = jclazz.getPackage - packageToScala(jPackage) - } else { - // @eb: a weird classloader might return a null package for something with a non-empty package name - // for example, http://groups.google.com/group/scala-internals/browse_thread/thread/7be09ff8f67a1e5c - // in that case we could invoke packageNameToScala(jPackageName) and, probably, be okay - // however, I think, it's better to blow up, since weirdness of the class loader might bite us elsewhere - val jPackageName = jclazz.getName.substring(0, Math.max(jclazz.getName.lastIndexOf("."), 0)) - assert(jPackageName == "") - EmptyPackageClass - } - } - - /** - * The Scala owner of the Scala symbol corresponding to the Java member `jmember` - */ - private def sOwner(jmember: jMember): Symbol = { - followStatic(classToScala(jmember.getDeclaringClass), jmember.getModifiers) - } - - /** - * The Scala owner of the Scala type parameter corresponding to the Java type variable `jtvar` - */ - private def sOwner(jtvar: jTypeVariable[_ <: GenericDeclaration]): Symbol = - genericDeclarationToScala(jtvar.getGenericDeclaration) - - /** - * Returns `true` if Scala name `name` equals Java name `jstr`, possibly after - * make-not-private expansion. - */ - private def approximateMatch(sym: Symbol, jstr: String): Boolean = - (sym.name.toString == jstr) || - sym.isPrivate && nme.expandedName(sym.name.toTermName, sym.owner).toString == jstr - - /** - * Find declarations or definition in class `clazz` that maps to a Java - * entity with name `jname`. Because of name-mangling, this is more difficult - * than a simple name-based lookup via `decl`. If `decl` fails, members - * that start with the given name are searched instead. - */ - private def lookup(clazz: Symbol, jname: String): Symbol = - clazz.info.decl(newTermName(jname)) orElse { - (clazz.info.decls.iterator filter (approximateMatch(_, jname))).toList match { - case List() => NoSymbol - case List(sym) => sym - case alts => clazz.newOverloaded(alts.head.tpe.prefix, alts) - } - } - - /** - * The Scala method corresponding to given Java method. - * @param jmeth The Java method - * @return A Scala method object that corresponds to `jmeth`. - */ - def methodToScala(jmeth: jMethod): Symbol = methodCache.toScala(jmeth) { - val jOwner = jmeth.getDeclaringClass - var sOwner = classToScala(jOwner) - sOwner = followStatic(sOwner, jmeth.getModifiers) - lookup(sOwner, jmeth.getName) suchThat (erasesTo(_, jmeth)) orElse jmethodAsScala(jmeth) - } - - /** - * The Scala constructor corresponding to given Java constructor. - * @param jconstr The Java constructor - * @return A Scala method object that corresponds to `jconstr`. - */ - def constrToScala(jconstr: jConstructor[_]): Symbol = constructorCache.toScala(jconstr) { - val owner = followStatic(classToScala(jconstr.getDeclaringClass), jconstr.getModifiers) - lookup(owner, "<init>") suchThat (erasesTo(_, jconstr)) orElse jconstrAsScala(jconstr) - } - - /** - * The Scala package corresponding to given Java package - */ - def packageToScala(jpkg: jPackage): Symbol = packageCache.toScala(jpkg) { - makeScalaPackage(jpkg.getName) - } - - /** - * The Scala package with given fully qualified name. - */ - def packageNameToScala(fullname: String): Symbol = { - val jpkg = jPackage.getPackage(fullname) - if (jpkg != null) packageToScala(jpkg) else makeScalaPackage(fullname) - } - - /** - * The Scala package with given fully qualified name. Unlike `packageNameToScala`, - * this one bypasses the cache. - */ - def makeScalaPackage(fullname: String): Symbol = { - val split = fullname lastIndexOf '.' - val owner = if (split > 0) packageNameToScala(fullname take split) else RootClass - assert(owner.isModuleClass, owner+" when making "+fullname) - val name = newTermName(fullname drop (split + 1)) - var pkg = owner.info decl name - if (pkg == NoSymbol) { - pkg = owner.newPackage(name) - pkg.moduleClass setInfo new LazyPackageType - pkg setInfoAndEnter pkg.moduleClass.tpe - info("made Scala "+pkg) - } else if (!pkg.isPackage) - throw new ReflectError(pkg+" is not a package") - pkg.moduleClass - } - - private def scalaSimpleName(jclazz: jClass[_]): TypeName = { - val owner = sOwner(jclazz) - val enclosingClass = jclazz.getEnclosingClass - var prefix = if (enclosingClass != null) enclosingClass.getName else "" - val isObject = owner.isModuleClass && !owner.isPackageClass - if (isObject && !prefix.endsWith(nme.MODULE_SUFFIX_STRING)) prefix += nme.MODULE_SUFFIX_STRING - assert(jclazz.getName.startsWith(prefix)) - var name = jclazz.getName.substring(prefix.length) - name = name.substring(name.lastIndexOf(".") + 1) - newTypeName(name) - } - - /** - * The Scala class that corresponds to a given Java class. - * @param jclazz The Java class - * @return A Scala class symbol that reflects all elements of the Java class, - * in the form they appear in the Scala pickling info, or, if that is - * not available, wrapped from the Java reflection info. - */ - def classToScala(jclazz: jClass[_]): Symbol = classCache.toScala(jclazz) { - val jname = javaTypeName(jclazz) - - val sym = - if (jname == fulltpnme.RuntimeNothing) - NothingClass - else if (jname == fulltpnme.RuntimeNull) - NullClass - else - { - val owner = sOwner(jclazz) - val simpleName = scalaSimpleName(jclazz) - - def lookup = { - def coreLookup(name: Name): Symbol = { - val sym = owner.info.decl(name) - sym orElse { - if (name.startsWith(nme.NAME_JOIN_STRING)) - coreLookup(name.subName(1, name.length)) - else - NoSymbol - } - } - - if (nme.isModuleName(simpleName)) { - val moduleName = nme.stripModuleSuffix(simpleName).toTermName - val sym = coreLookup(moduleName) - if (sym == NoSymbol) sym else sym.moduleClass - } else { - coreLookup(simpleName) - } - } - - val sym = { - if (jclazz.isMemberClass && !nme.isImplClassName(jname)) { - lookup - } else if (wrapIsLocalClass(jclazz) || invalidClassName(jname)) { - // local classes and implementation classes not preserved by unpickling - treat as Java - jclassAsScala(jclazz) - } else if (jclazz.isArray) { - ArrayClass - } else javaTypeToValueClass(jclazz) orElse { - // jclazz is top-level - get signature - lookup - // val (clazz, module) = createClassModule( - // sOwner(jclazz), newTypeName(jclazz.getSimpleName), new TopClassCompleter(_, _)) - // classCache enter (jclazz, clazz) - // clazz - } - } - - if (!sym.isType) { - val classloader = jclazz.getClassLoader - println("classloader is: %s of type %s".format(classloader, classloader.getClass)) - def inferClasspath(cl: ClassLoader) = cl match { - case cl: java.net.URLClassLoader => "[" + (cl.getURLs mkString ",") + "]" - case _ => "<unknown>" - } - println("classpath is: %s".format(inferClasspath(classloader))) - def msgNoSym = "no symbol could be loaded from %s (scala equivalent is %s) by name %s".format(owner, jclazz, simpleName) - def msgIsNotType = "not a type: symbol %s loaded from %s (scala equivalent is %s) by name %s".format(sym, owner, jclazz, simpleName) - assert(false, if (sym == NoSymbol) msgNoSym else msgIsNotType) - } - - sym - } - - sym.asInstanceOf[ClassSymbol] - } - - /** - * The Scala type parameter that corresponds to a given Java type parameter. - * @param jparam The Java type parameter - * @return A Scala type parameter symbol that has the same owner and name as the Java type parameter - */ - def tparamToScala(jparam: jTypeVariable[_ <: GenericDeclaration]): Symbol = tparamCache.toScala(jparam) { - val owner = genericDeclarationToScala(jparam.getGenericDeclaration) - owner.info match { - case PolyType(tparams, _) => tparams.find(_.name.toString == jparam.getName).get - } - } - - /** - * The Scala symbol that corresponds to a given Java generic declaration (class, method, or constructor) - */ - def genericDeclarationToScala(jdecl: GenericDeclaration) = jdecl match { - case jclazz: jClass[_] => classToScala(jclazz) - case jmeth: jMethod => methodToScala(jmeth) - case jconstr: jConstructor[_] => constrToScala(jconstr) - } - - /** - * Given some Java type arguments, a corresponding list of Scala types, plus potentially - * some existentially bound type variables that represent wildcard arguments. - */ - private def targsToScala(owner: Symbol, args: List[jType]): (List[Type], List[Symbol]) = { - val tparams = new ListBuffer[Symbol] - def targToScala(arg: jType): Type = arg match { - case jwild: WildcardType => - val tparam = owner.newExistential(newTypeName("T$" + tparams.length)) - .setInfo(TypeBounds( - lub(jwild.getLowerBounds.toList map typeToScala), - glb(jwild.getUpperBounds.toList map typeToScala map objToAny))) - tparams += tparam - typeRef(NoPrefix, tparam, List()) - case _ => - typeToScala(arg) - } - (args map targToScala, tparams.toList) - } - - /** - * The Scala type that corresponds to given Java type - */ - def typeToScala(jtpe: jType): Type = jtpe match { - case jclazz: jClass[_] => - if (jclazz.isArray) - arrayType(typeToScala(jclazz.getComponentType)) - else { - val clazz = classToScala(jclazz) - rawToExistential(typeRef(clazz.owner.thisType, clazz, List())) - } - case japplied: ParameterizedType => - val (pre, sym) = typeToScala(japplied.getRawType) match { - case ExistentialType(tparams, TypeRef(pre, sym, _)) => (pre, sym) - case TypeRef(pre, sym, _) => (pre, sym) - } - val args0 = japplied.getActualTypeArguments - val (args, bounds) = targsToScala(pre.typeSymbol, args0.toList) - ExistentialType(bounds, typeRef(pre, sym, args)) - case jarr: GenericArrayType => - arrayType(typeToScala(jarr.getGenericComponentType)) - case jtvar: jTypeVariable[_] => - val tparam = tparamToScala(jtvar) - typeRef(NoPrefix, tparam, List()) - } - - /** - * The Scala class that corresponds to given Java class without taking - * Scala pickling info into account. - * @param jclazz The Java class - * @return A Scala class symbol that wraps all reflection info of `jclazz` - */ - private def jclassAsScala(jclazz: jClass[_]): Symbol = jclassAsScala(jclazz, sOwner(jclazz)) - - private def jclassAsScala(jclazz: jClass[_], owner: Symbol): Symbol = { - val name = scalaSimpleName(jclazz) - val completer = (clazz: Symbol, module: Symbol) => new FromJavaClassCompleter(clazz, module, jclazz) - val (clazz, module) = createClassModule(owner, name, completer) - classCache enter (jclazz, clazz) - clazz - } - - /** - * The Scala field that corresponds to given Java field without taking - * Scala pickling info into account. - * @param jfield The Java field - * @return A Scala value symbol that wraps all reflection info of `jfield` - */ - private def jfieldAsScala(jfield: jField): Symbol = fieldCache.toScala(jfield) { - val field = ( - sOwner(jfield) - newValue(newTermName(jfield.getName), NoPosition, toScalaFieldFlags(jfield.getModifiers)) - setInfo typeToScala(jfield.getGenericType) - ) - fieldCache enter (jfield, field) - copyAnnotations(field, jfield) - field - } - - private def setMethType(meth: Symbol, tparams: List[Symbol], paramtpes: List[Type], restpe: Type) = { - meth setInfo GenPolyType(tparams, MethodType(meth.owner.newSyntheticValueParams(paramtpes map objToAny), restpe)) - } - - /** - * The Scala method that corresponds to given Java method without taking - * Scala pickling info into account. - * @param jmeth The Java method - * @return A Scala method symbol that wraps all reflection info of `jmethod` - */ - private def jmethodAsScala(jmeth: jMethod): Symbol = methodCache.toScala(jmeth) { - val clazz = sOwner(jmeth) - val meth = clazz.newMethod(newTermName(jmeth.getName), NoPosition, toScalaMethodFlags(jmeth.getModifiers)) - methodCache enter (jmeth, meth) - val tparams = jmeth.getTypeParameters.toList map createTypeParameter - val paramtpes = jmeth.getGenericParameterTypes.toList map typeToScala - val resulttpe = typeToScala(jmeth.getGenericReturnType) - setMethType(meth, tparams, paramtpes, resulttpe) - copyAnnotations(meth, jmeth) - if ((jmeth.getModifiers & JAVA_ACC_VARARGS) != 0) { - meth.setInfo(arrayToRepeated(meth.info)) - } - meth - } - - /** - * The Scala constructor that corresponds to given Java constructor without taking - * Scala pickling info into account. - * @param jconstr The Java constructor - * @return A Scala constructor symbol that wraps all reflection info of `jconstr` - */ - private def jconstrAsScala(jconstr: jConstructor[_]): Symbol = { - // [Martin] Note: I know there's a lot of duplication wrt jmethodAsScala, but don't think it's worth it to factor this out. - val clazz = sOwner(jconstr) - val constr = clazz.newConstructor(NoPosition, toScalaMethodFlags(jconstr.getModifiers)) - constructorCache enter (jconstr, constr) - val tparams = jconstr.getTypeParameters.toList map createTypeParameter - val paramtpes = jconstr.getGenericParameterTypes.toList map typeToScala - setMethType(constr, tparams, paramtpes, clazz.tpe) - constr setInfo GenPolyType(tparams, MethodType(clazz.newSyntheticValueParams(paramtpes), clazz.tpe)) - copyAnnotations(constr, jconstr) - constr - } -} - -class ReflectError(msg: String) extends java.lang.Error(msg) diff --git a/src/compiler/scala/reflect/runtime/Mirror.scala b/src/compiler/scala/reflect/runtime/Mirror.scala deleted file mode 100644 index bf4bc83bea..0000000000 --- a/src/compiler/scala/reflect/runtime/Mirror.scala +++ /dev/null @@ -1,85 +0,0 @@ -package scala.reflect -package runtime - -import java.lang.reflect.Array -import ReflectionUtils._ -import scala.tools.nsc.util.ScalaClassLoader._ - -/** The mirror for standard runtime reflection from Java. - */ -class Mirror(var classLoader: ClassLoader) extends Universe with api.Mirror { - - definitions.init() - import definitions._ - - def symbolForName(name: String): Symbol = { - val clazz = javaClass(name, classLoader) - classToScala(clazz) - } - - def companionInstance(clazz: Symbol): AnyRef = { - val singleton = singletonInstance(classLoader, clazz.fullName) - singleton - } - - def symbolOfInstance(obj: Any): Symbol = classToScala(obj.getClass) - def typeOfInstance(obj: Any): Type = typeToScala(obj.getClass) - // to do add getClass/getType for instances of primitive types, probably like this: - // def getClass[T <: AnyVal : ClassTag](x: T): Symbol = classTag[T].sym - - def getValueOfField(receiver: AnyRef, field: Symbol): Any = { - fieldToJava(field).get(receiver) - } - def setValueOfField(receiver: AnyRef, field: Symbol, value: Any): Unit = { - fieldToJava(field).set(receiver, value) - } - def invoke(receiver: AnyRef, meth: Symbol)(args: Any*): Any = { - if (meth.owner == ArrayClass) { - meth.name match { - case nme.length => return Array.getLength(receiver) - case nme.apply => return Array.get(receiver, args(0).asInstanceOf[Int]) - case nme.update => return Array.set(receiver, args(0).asInstanceOf[Int], args(1)) - } - } - - val jmeth = methodToJava(meth) - jmeth.invoke(receiver, args.asInstanceOf[Seq[AnyRef]]: _*) - } - - private def validateIncomingClassLoader(wannabeCl: ClassLoader) = { - val ourCls = loaderChain(classLoader) - if (wannabeCl != null && !(ourCls contains wannabeCl)) - throw new Error("class doesn't belong to the classloader chain of the mirror") - } - - def classToType(jclazz: java.lang.Class[_]): Type = { - validateIncomingClassLoader(jclazz.getClassLoader) - typeToScala(jclazz) - } - - def classToSymbol(jclazz: java.lang.Class[_]): Symbol = { - validateIncomingClassLoader(jclazz.getClassLoader) - classToScala(jclazz) - } - - def typeToClass(tpe: Type): java.lang.Class[_] = - typeToJavaClass(tpe) - - def symbolToClass(sym: Symbol): java.lang.Class[_] = - classToJava(sym) - - override def inReflexiveMirror = true -} - -/** test code; should go to tests once things settle down a bit - * - -object Test extends Mirror with App { - val sym = classToScala(classOf[scala.collection.Iterable[_]]) - println(sym) - println("parents = "+sym.info.parents) - println("decls = "+(sym.info.decls.toList map (_.defString))) - val ms = sym.info.members.toList map (_.initialize) - println("members = "+(ms map (_.defString) mkString ("\n "))) -} -*/
\ No newline at end of file diff --git a/src/compiler/scala/reflect/runtime/ScalaToJava.scala b/src/compiler/scala/reflect/runtime/ScalaToJava.scala deleted file mode 100644 index 87cdd11652..0000000000 --- a/src/compiler/scala/reflect/runtime/ScalaToJava.scala +++ /dev/null @@ -1,87 +0,0 @@ -package scala.reflect -package runtime - -import java.lang.{Class => jClass, Package => jPackage} -import java.lang.reflect.{ - Method => jMethod, Constructor => jConstructor, Modifier => jModifier, Field => jField, - Member => jMember, Type => jType, Array => jArray, GenericDeclaration} - -trait ScalaToJava extends ConversionUtil { self: SymbolTable => - - import definitions._ - - /** Optionally, the Java package corresponding to a given Scala package, or None if no such Java package exists. - * @param pkg The Scala package - */ - def packageToJava(pkg: Symbol): Option[jPackage] = packageCache.toJavaOption(pkg) { - Option(jPackage.getPackage(pkg.fullName.toString)) - } - - /** The Java class corresponding to given Scala class. - * Note: This only works for - * - top-level classes - * - Scala classes that were generated via jclassToScala - * - classes that have a class owner that has a corresponding Java class - * @throws A `ClassNotFoundException` for all Scala classes not in one of these categories. - */ - @throws(classOf[ClassNotFoundException]) - def classToJava(clazz: Symbol): jClass[_] = classCache.toJava(clazz) { - def noClass = throw new ClassNotFoundException("no Java class corresponding to "+clazz+" found") - //println("classToJava "+clazz+" "+clazz.owner+" "+clazz.owner.isPackageClass)//debug - if (clazz.isPrimitiveValueClass) - valueClassToJavaType(clazz) - else if (clazz == ArrayClass) - noClass - else if (clazz.owner.isPackageClass) - javaClass(clazz.javaClassName) - else if (clazz.owner.isClass) - classToJava(clazz.owner) - .getDeclaredClasses - .find(_.getSimpleName == clazz.name.toString) - .getOrElse(noClass) - else - noClass - } - - private def expandedName(sym: Symbol): String = - if (sym.isPrivate) nme.expandedName(sym.name.toTermName, sym.owner).toString - else sym.name.toString - - def fieldToJava(fld: Symbol): jField = fieldCache.toJava(fld) { - val jclazz = classToJava(fld.owner) - try jclazz getDeclaredField fld.name.toString - catch { - case ex: NoSuchFieldException => jclazz getDeclaredField expandedName(fld) - } - } - - def methodToJava(meth: Symbol): jMethod = methodCache.toJava(meth) { - val jclazz = classToJava(meth.owner) - val paramClasses = transformedType(meth).paramTypes map typeToJavaClass - try jclazz getDeclaredMethod (meth.name.toString, paramClasses: _*) - catch { - case ex: NoSuchMethodException => - jclazz getDeclaredMethod (expandedName(meth), paramClasses: _*) - } - } - - def constrToJava(constr: Symbol): jConstructor[_] = constructorCache.toJava(constr) { - val jclazz = classToJava(constr.owner) - val paramClasses = transformedType(constr).paramTypes map typeToJavaClass - jclazz getConstructor (paramClasses: _*) - } - - private def jArrayClass(elemClazz: jClass[_]): jClass[_] = { - jArray.newInstance(elemClazz, 0).getClass - } - - /** The Java class that corresponds to given Scala type. - * Pre: Scala type is already transformed to Java level. - */ - def typeToJavaClass(tpe: Type): jClass[_] = tpe match { - case ExistentialType(_, rtpe) => typeToJavaClass(rtpe) - case TypeRef(_, ArrayClass, List(elemtpe)) => jArrayClass(typeToJavaClass(elemtpe)) - case TypeRef(_, sym, _) => classToJava(sym) - case _ => throw new NoClassDefFoundError("no Java class corresponding to "+tpe+" found") - } -}
\ No newline at end of file diff --git a/src/compiler/scala/reflect/runtime/Universe.scala b/src/compiler/scala/reflect/runtime/Universe.scala deleted file mode 100644 index fd53308d0a..0000000000 --- a/src/compiler/scala/reflect/runtime/Universe.scala +++ /dev/null @@ -1,43 +0,0 @@ -package scala.reflect -package runtime - -import internal.{SomePhase, NoPhase, Phase, TreeGen} - -/** The universe for standard runtime reflection from Java. - * This type implements all abstract term members in internal.SymbolTable. - * It also provides methods to go from Java members to Scala members, - * using the code in JavaConversions. - */ -abstract class Universe extends SymbolTable with ToolBoxes { - - type AbstractFileType = AbstractFile - - def picklerPhase = SomePhase - - type TreeGen = internal.TreeGen - - val gen = new TreeGen { val global: Universe.this.type = Universe.this } - - lazy val settings = new Settings - def forInteractive = false - def forScaladoc = false - - val phaseWithId: Array[Phase] = Array(NoPhase, SomePhase) - val currentRunId = 1 // fake a run id so that it is different from NoRunId - phase = SomePhase // set to a phase different from NoPhase - - def log(msg: => AnyRef): Unit = println(" [] "+msg) - - type TreeCopier = TreeCopierOps - def newStrictTreeCopier: TreeCopier = new StrictTreeCopier - def newLazyTreeCopier: TreeCopier = new LazyTreeCopier - - definitions.AnyValClass // force it. - - // establish root association to avoid cyclic dependency errors later - // don't use classOf[...] here, because it gets serviced by getClass.getClassLoader! - classToScala(Class.forName("java.lang.Object", true, classLoader)).initialize - -// println("initializing definitions") - definitions.init() -} diff --git a/src/compiler/scala/reflect/runtime/package.scala b/src/compiler/scala/reflect/runtime/package.scala deleted file mode 100644 index 52ab2c5deb..0000000000 --- a/src/compiler/scala/reflect/runtime/package.scala +++ /dev/null @@ -1,5 +0,0 @@ -package scala.reflect - -package object runtime { - def mkMirror(classLoader: ClassLoader): api.Mirror = new Mirror(classLoader) -}
\ No newline at end of file diff --git a/src/compiler/scala/tools/ant/FastScalac.scala b/src/compiler/scala/tools/ant/FastScalac.scala index 19a1526e67..c0d7441ad5 100644 --- a/src/compiler/scala/tools/ant/FastScalac.scala +++ b/src/compiler/scala/tools/ant/FastScalac.scala @@ -157,7 +157,7 @@ class FastScalac extends Scalac { val scalaHome: String = try { val url = ScalaClassLoader.originOfClass(classOf[FastScalac]).get - File(url.getFile).jfile.getParentFile.getParentFile getAbsolutePath + File(url.getFile).jfile.getParentFile.getParentFile.getAbsolutePath } catch { case _ => buildError("Compilation failed because of an internal compiler error;"+ diff --git a/src/compiler/scala/tools/ant/Scalac.scala b/src/compiler/scala/tools/ant/Scalac.scala index 3c79fcd3fb..a34692f5e0 100644 --- a/src/compiler/scala/tools/ant/Scalac.scala +++ b/src/compiler/scala/tools/ant/Scalac.scala @@ -632,7 +632,7 @@ class Scalac extends ScalaMatchingTask with ScalacShared { case "none" => case x => val depFilePath = SPath(x) - command.settings.dependenciesFile.value = SPath(getProject.getBaseDir).normalize resolve depFilePath path + command.settings.dependenciesFile.value = SPath(getProject.getBaseDir).normalize.resolve(depFilePath).path } (command.settings, sourceFiles, javaOnly) diff --git a/src/compiler/scala/tools/cmd/CommandLine.scala b/src/compiler/scala/tools/cmd/CommandLine.scala index ced3a97380..d9a74a698c 100644 --- a/src/compiler/scala/tools/cmd/CommandLine.scala +++ b/src/compiler/scala/tools/cmd/CommandLine.scala @@ -7,6 +7,7 @@ package scala.tools package cmd import scala.collection.mutable.ListBuffer +import language.postfixOps trait CommandLineConfig { def enforceArity: Boolean = true diff --git a/src/compiler/scala/tools/cmd/FromString.scala b/src/compiler/scala/tools/cmd/FromString.scala index 91356b3c19..29f1baaa0c 100644 --- a/src/compiler/scala/tools/cmd/FromString.scala +++ b/src/compiler/scala/tools/cmd/FromString.scala @@ -7,14 +7,15 @@ package scala.tools package cmd import nsc.io.{ Path, File, Directory } -import scala.reflect.TypeTag +import scala.reflect.runtime.{universe => ru} +import scala.tools.reflect.StdTags._ /** A general mechanism for defining how a command line argument * (always a String) is transformed into an arbitrary type. A few * example instances are in the companion object, but in general * either IntFromString will suffice or you'll want custom transformers. */ -abstract class FromString[+T](implicit t: TypeTag[T]) extends PartialFunction[String, T] { +abstract class FromString[+T](implicit t: ru.TypeTag[T]) extends PartialFunction[String, T] { def apply(s: String): T def isDefinedAt(s: String): Boolean = true def zero: T = apply("") @@ -29,19 +30,19 @@ object FromString { /** Path related stringifiers. */ - val ExistingFile: FromString[File] = new FromString[File] { + val ExistingFile: FromString[File] = new FromString[File]()(tagOfFile) { override def isDefinedAt(s: String) = toFile(s).isFile def apply(s: String): File = if (isDefinedAt(s)) toFile(s) else cmd.runAndExit(println("'%s' is not an existing file." format s)) } - val ExistingDir: FromString[Directory] = new FromString[Directory] { + val ExistingDir: FromString[Directory] = new FromString[Directory]()(tagOfDirectory) { override def isDefinedAt(s: String) = toDir(s).isDirectory def apply(s: String): Directory = if (isDefinedAt(s)) toDir(s) else cmd.runAndExit(println("'%s' is not an existing directory." format s)) } - def ExistingDirRelativeTo(root: Directory) = new FromString[Directory] { + def ExistingDirRelativeTo(root: Directory) = new FromString[Directory]()(tagOfDirectory) { private def resolve(s: String) = toDir(s) toAbsoluteWithRoot root toDirectory override def isDefinedAt(s: String) = resolve(s).isDirectory def apply(s: String): Directory = @@ -52,19 +53,19 @@ object FromString { /** Argument expander, i.e. turns single argument "foo bar baz" into argument * list "foo", "bar", "baz". */ - val ArgumentsFromString: FromString[List[String]] = new FromString[List[String]] { + val ArgumentsFromString: FromString[List[String]] = new FromString[List[String]]()(tagOfListOfString) { def apply(s: String) = toArgs(s) } /** Identity. */ - implicit val StringFromString: FromString[String] = new FromString[String] { + implicit val StringFromString: FromString[String] = new FromString[String]()(tagOfString) { def apply(s: String): String = s } /** Implicit as the most likely to be useful as-is. */ - implicit val IntFromString: FromString[Int] = new FromString[Int] { + implicit val IntFromString: FromString[Int] = new FromString[Int]()(tagOfInt) { override def isDefinedAt(s: String) = safeToInt(s).isDefined def apply(s: String) = safeToInt(s).get def safeToInt(s: String): Option[Int] = try Some(java.lang.Integer.parseInt(s)) catch { case _: NumberFormatException => None } diff --git a/src/compiler/scala/tools/cmd/gen/Codegen.scala b/src/compiler/scala/tools/cmd/gen/Codegen.scala index 1bb820455a..59b58563d1 100644 --- a/src/compiler/scala/tools/cmd/gen/Codegen.scala +++ b/src/compiler/scala/tools/cmd/gen/Codegen.scala @@ -6,6 +6,8 @@ package scala.tools.cmd package gen +import language.postfixOps + class Codegen(args: List[String]) extends { val parsed = CodegenSpec(args: _*) } with CodegenSpec with Instance { } diff --git a/src/compiler/scala/tools/nsc/ClassLoaders.scala b/src/compiler/scala/tools/nsc/ClassLoaders.scala deleted file mode 100644 index 4058ee9324..0000000000 --- a/src/compiler/scala/tools/nsc/ClassLoaders.scala +++ /dev/null @@ -1,64 +0,0 @@ -package scala.tools.nsc - -import util.ScalaClassLoader - -trait ClassLoaders { self: Global => - - def staticClass(fullname: String) = { - if (self.forMSIL) - throw new UnsupportedOperationException("Scala reflection not available on this platform") - - getClass(newTypeName(fullname)) - } - - def staticModule(fullname: String) = { - if (self.forMSIL) - throw new UnsupportedOperationException("Scala reflection not available on this platform") - - getModule(newTermName(fullname)) - } - - private def getClass(fullname: Name): Symbol = { - var result = getModuleOrClass(fullname.toTypeName) - while (result.isAliasType) result = result.info.typeSymbol - result - } - - private def getModule(fullname: Name): Symbol = - getModuleOrClass(fullname.toTermName) - - private def getModuleOrClass(path: Name): Symbol = - getModuleOrClass(path, path.length) - - private def getModuleOrClass(path: Name, len: Int): Symbol = { - val point = path lastPos('.', len - 1) - val owner = - if (point > 0) getModuleOrClass(path.toTermName, point) - else definitions.RootClass - val name = path subName (point + 1, len) - val sym = owner.info member name - val result = if (path.isTermName) sym.suchThat(_ hasFlag symtab.Flags.MODULE) else sym - if (result != NoSymbol) result - else { - if (settings.debug.value) { log(sym.info); log(sym.info.members) }//debug - if (owner.isRoot && isJavaClass(name.toString)) - definitions.EmptyPackageClass.info decl name - else { - def info(msg: => String) = if (settings.verbose.value) println(msg) - info("*** missing: "+name+"/"+name.isTermName+"/"+owner+"/"+owner.hasPackageFlag+"/"+owner.info.decls.getClass) - MissingRequirementError.notFound((if (path.isTermName) "object " else "class ")+path) - } - } - } - - private def isJavaClass(path: String): Boolean = - try { - val classpath = platform.classPath.asURLs - var classLoader = ScalaClassLoader.fromURLs(classpath) - Class.forName(path, true, classLoader) - true - } catch { - case (_: ClassNotFoundException) | (_: NoClassDefFoundError) | (_: IncompatibleClassChangeError) => - false - } -} diff --git a/src/compiler/scala/tools/nsc/CompilationUnits.scala b/src/compiler/scala/tools/nsc/CompilationUnits.scala index 2f1e15168a..54b114bf82 100644 --- a/src/compiler/scala/tools/nsc/CompilationUnits.scala +++ b/src/compiler/scala/tools/nsc/CompilationUnits.scala @@ -5,7 +5,8 @@ package scala.tools.nsc -import util.{ FreshNameCreator, Position, NoPosition, BatchSourceFile, SourceFile, NoSourceFile } +import util.FreshNameCreator +import scala.reflect.internal.util.{ Position, NoPosition, BatchSourceFile, SourceFile, NoSourceFile } import scala.collection.mutable import scala.collection.mutable.{ LinkedHashSet, ListBuffer } diff --git a/src/compiler/scala/tools/nsc/CompileServer.scala b/src/compiler/scala/tools/nsc/CompileServer.scala index 6393ade146..fd59319c14 100644 --- a/src/compiler/scala/tools/nsc/CompileServer.scala +++ b/src/compiler/scala/tools/nsc/CompileServer.scala @@ -7,7 +7,7 @@ package scala.tools.nsc import java.io.{ BufferedOutputStream, FileOutputStream, PrintStream } import scala.tools.nsc.reporters.{Reporter, ConsoleReporter} -import scala.tools.nsc.util.FakePos //Position +import scala.reflect.internal.util.FakePos //Position import scala.tools.util.SocketServer import settings.FscSettings diff --git a/src/compiler/scala/tools/nsc/CompileSocket.scala b/src/compiler/scala/tools/nsc/CompileSocket.scala index a4a8e1fd11..7d2abd42fd 100644 --- a/src/compiler/scala/tools/nsc/CompileSocket.scala +++ b/src/compiler/scala/tools/nsc/CompileSocket.scala @@ -13,7 +13,7 @@ import java.security.SecureRandom import io.{ File, Path, Directory, Socket } import scala.util.control.Exception.catching import scala.tools.util.CompileOutputCommon -import scala.tools.util.StringOps.splitWhere +import scala.reflect.internal.util.StringOps.splitWhere import scala.sys.process._ trait HasCompileSocket { diff --git a/src/compiler/scala/tools/nsc/Driver.scala b/src/compiler/scala/tools/nsc/Driver.scala index 0c52954a0b..0051c3bdec 100644 --- a/src/compiler/scala/tools/nsc/Driver.scala +++ b/src/compiler/scala/tools/nsc/Driver.scala @@ -2,7 +2,7 @@ package scala.tools.nsc import scala.tools.nsc.reporters.{Reporter, ConsoleReporter} import Properties.{ versionString, copyrightString } -import scala.tools.nsc.util.{ BatchSourceFile, FakePos } +import scala.reflect.internal.util.{ BatchSourceFile, FakePos } abstract class Driver { diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 271dca3157..787c9c7f57 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -12,7 +12,8 @@ import scala.tools.util.PathResolver import scala.collection.{ mutable, immutable } import io.{ SourceReader, AbstractFile, Path } import reporters.{ Reporter, ConsoleReporter } -import util.{ NoPosition, Exceptional, ClassPath, MergedClassPath, SourceFile, NoSourceFile, Statistics, StatisticsInfo, BatchSourceFile, ScriptSourceFile, ScalaClassLoader, returning } +import util.{ Exceptional, ClassPath, MergedClassPath, Statistics, StatisticsInfo, ScalaClassLoader, returning } +import scala.reflect.internal.util.{ NoPosition, SourceFile, NoSourceFile, BatchSourceFile, ScriptSourceFile } import scala.reflect.internal.pickling.{ PickleBuffer, PickleFormat } import settings.{ AestheticSettings } import symtab.{ Flags, SymbolTable, SymbolLoaders, SymbolTrackers } @@ -30,22 +31,44 @@ import backend.opt.{ Inliners, InlineExceptionHandlers, ClosureElimination, Dead import backend.icode.analysis._ import language.postfixOps import reflect.internal.StdAttachments +import scala.reflect.ClassTag -class Global(var currentSettings: Settings, var reporter: Reporter) extends SymbolTable - with ClassLoaders - with ToolBoxes - with CompilationUnits - with Plugins - with PhaseAssembly - with Trees - with FreeVars - with TreePrinters - with DocComments - with Positions { +class Global(var currentSettings: Settings, var reporter: Reporter) + extends SymbolTable + with CompilationUnits + with Plugins + with PhaseAssembly + with Trees + with TreePrinters + with DocComments + with Positions { self => + + // [Eugene++] would love to find better homes for the new things dumped into Global + + // the mirror -------------------------------------------------- + + override def isCompilerUniverse = true + + class GlobalMirror extends Roots(NoSymbol) { + val universe: self.type = self + def rootLoader: LazyType = platform.rootLoader + override def toString = "compiler mirror" + } + + lazy val rootMirror: Mirror = { + val rm = new GlobalMirror + rm.init() + rm.asInstanceOf[Mirror] + } + def RootClass: ClassSymbol = rootMirror.RootClass + def EmptyPackageClass: ClassSymbol = rootMirror.EmptyPackageClass + // [Eugene++] this little inconvenience gives us precise types for Expr.mirror and TypeTag.mirror + // by the way, is it possible to define variant type members? override def settings = currentSettings - import definitions.{ findNamedMember, findMemberFromRoot } + import definitions.findNamedMember + def findMemberFromRoot(fullName: Name): Symbol = rootMirror.findMemberFromRoot(fullName) // alternate constructors ------------------------------------------ @@ -77,14 +100,12 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb def classPath: PlatformClassPath = platform.classPath - def rootLoader: LazyType = platform.rootLoader - // sub-components -------------------------------------------------- /** Generate ASTs */ type TreeGen = scala.tools.nsc.ast.TreeGen - object gen extends { + override object gen extends { val global: Global.this.type = Global.this } with TreeGen { def mkAttributedCast(tree: Tree, pt: Type): Tree = @@ -386,6 +407,9 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb val global: Global.this.type = Global.this } + /** Returns the mirror that loaded given symbol */ + def mirrorThatLoaded(sym: Symbol): Mirror = rootMirror + // ------------ Phases -------------------------------------------} var globalPhase: Phase = NoPhase @@ -686,7 +710,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb object icodeChecker extends icodeCheckers.ICodeChecker() object typer extends analyzer.Typer( - analyzer.NoContext.make(EmptyTree, Global.this.definitions.RootClass, newScope) + analyzer.NoContext.make(EmptyTree, RootClass, newScope) ) /** Add the internal compiler phases to the phases set. @@ -849,7 +873,9 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb /** Is given package class a system package class that cannot be invalidated? */ private def isSystemPackageClass(pkg: Symbol) = - pkg == definitions.RootClass || + // [Eugene++ to Martin] please, verify +// was: pkg == definitions.RootClass || + pkg == RootClass || pkg == definitions.ScalaPackageClass || { val pkgname = pkg.fullName (pkgname startsWith "scala.") && !(pkgname startsWith "scala.tools") @@ -911,7 +937,9 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb else new MergedClassPath(elems, classPath.context) val oldEntries = mkClassPath(subst.keys) val newEntries = mkClassPath(subst.values) - reSync(definitions.RootClass, Some(classPath), Some(oldEntries), Some(newEntries), invalidated, failed) + // [Eugene++ to Martin] please, verify +// was: reSync(definitions.RootClass, Some(classPath), Some(oldEntries), Some(newEntries), invalidated, failed) + reSync(RootClass, Some(classPath), Some(oldEntries), Some(newEntries), invalidated, failed) } } def show(msg: String, syms: collection.Traversable[Symbol]) = @@ -970,7 +998,9 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb invalidateOrRemove(root) } else { if (classesFound) { - if (root.isRoot) invalidateOrRemove(definitions.EmptyPackageClass) + // [Eugene++ to Martin] please, verify +// was: if (root.isRoot) invalidateOrRemove(definitions.EmptyPackageClass) + if (root.isRoot) invalidateOrRemove(EmptyPackageClass) else failed += root } (oldEntries, newEntries) match { @@ -1514,13 +1544,16 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb compileUnits(sources map (new CompilationUnit(_)), firstPhase) } - /** Compile list of units, starting with phase `fromPhase` - */ def compileUnits(units: List[CompilationUnit], fromPhase: Phase) { try compileUnitsInternal(units, fromPhase) catch { case ex => + val shown = if (settings.verbose.value) { + val pw = new java.io.PrintWriter(new java.io.StringWriter) + ex.printStackTrace(pw) + pw.toString + } else ex.getClass.getName // ex.printStackTrace(Console.out) // DEBUG for fsc, note that error stacktraces do not print in fsc - globalError(supplementErrorMessage("uncaught exception during compilation: " + ex.getClass.getName)) + globalError(supplementErrorMessage("uncaught exception during compilation: " + shown)) throw ex } } @@ -1600,7 +1633,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb // Reset project if (!stopPhase("namer")) { atPhase(namerPhase) { - resetProjectClasses(definitions.RootClass) + resetProjectClasses(RootClass) } } } diff --git a/src/compiler/scala/tools/nsc/Main.scala b/src/compiler/scala/tools/nsc/Main.scala index 4763fab45c..19c872b6d3 100644 --- a/src/compiler/scala/tools/nsc/Main.scala +++ b/src/compiler/scala/tools/nsc/Main.scala @@ -11,7 +11,7 @@ import File.pathSeparator import scala.tools.nsc.interactive.{ RefinedBuildManager, SimpleBuildManager } import scala.tools.nsc.io.AbstractFile import scala.tools.nsc.reporters.{Reporter, ConsoleReporter} -import scala.tools.nsc.util.{ BatchSourceFile, FakePos } //{Position} +import scala.reflect.internal.util.{ BatchSourceFile, FakePos } //{Position} import Properties.{ versionString, copyrightString, residentPromptString, msilLibPath } /** The main class for NSC, a compiler for the programming diff --git a/src/compiler/scala/tools/nsc/Phases.scala b/src/compiler/scala/tools/nsc/Phases.scala index aa0ea1bdd8..896fcb3ca1 100644 --- a/src/compiler/scala/tools/nsc/Phases.scala +++ b/src/compiler/scala/tools/nsc/Phases.scala @@ -6,7 +6,7 @@ package scala.tools.nsc import symtab.Flags -import util.TableDef +import reflect.internal.util.TableDef import language.postfixOps object Phases { diff --git a/src/compiler/scala/tools/nsc/ReflectGlobal.scala b/src/compiler/scala/tools/nsc/ReflectGlobal.scala index 68a6a4d336..4f4db83339 100644 --- a/src/compiler/scala/tools/nsc/ReflectGlobal.scala +++ b/src/compiler/scala/tools/nsc/ReflectGlobal.scala @@ -5,17 +5,33 @@ import reporters.Reporter /** A version of Global that uses reflection to get class * infos, instead of reading class or source files. */ -class ReflectGlobal(currentSettings: Settings, reporter: Reporter, var classLoader: ClassLoader) - extends Global(currentSettings, reporter) with reflect.runtime.SymbolTable { +class ReflectGlobal(currentSettings: Settings, reporter: Reporter, override val rootClassLoader: ClassLoader) + extends Global(currentSettings, reporter) with scala.tools.nsc.ReflectSetup with scala.reflect.runtime.SymbolTable { override def transformedType(sym: Symbol) = erasure.transformInfo(sym, uncurry.transformInfo(sym, refChecks.transformInfo(sym, sym.info))) - override def staticClass(fullname: String) = - super[SymbolTable].staticClass(fullname) + override def isCompilerUniverse = true - override def staticModule(fullname: String) = - super[SymbolTable].staticModule(fullname) + // Typically `runtimeMirror` creates a new mirror for every new classloader + // and shares symbols between the created mirrors. + // + // However we can't do that for the compiler. + // The problem is that symbol sharing violates owner chain assumptions that the compiler has. + // + // For example, we can easily end up with a situation when: + // + // Predef defined in package scala loaded by the classloader that has scala-library.jar + // + // cannot be accessed in: + // + // package scala for the rootMirror of ReflectGlobal that might correspond to a different classloader + // + // This happens because, despite the fact that `Predef` is shared between multiple `scala` packages (i.e. multiple scopes) + // (each mirror has its own set package symbols, because of the peculiarities of symbol loading in scala), + // that `Predef` symbol only has a single owner, and this messes up visibility, which is calculated based on owners, not scopes. + override def runtimeMirror(cl: ClassLoader): Mirror = rootMirror } + diff --git a/src/compiler/scala/tools/nsc/ReflectMain.scala b/src/compiler/scala/tools/nsc/ReflectMain.scala index f9a18abc25..161391fc2c 100644 --- a/src/compiler/scala/tools/nsc/ReflectMain.scala +++ b/src/compiler/scala/tools/nsc/ReflectMain.scala @@ -1,16 +1,15 @@ package scala.tools.nsc -import util.ScalaClassLoader import tools.util.PathResolver import util.ClassPath.DefaultJavaContext +import util.ScalaClassLoader object ReflectMain extends Driver { - private def reflectionClassloaderFromSettings(settings: Settings) = { + private def classloaderFromSettings(settings: Settings) = { val classpath = new PathResolver(settings).result ScalaClassLoader.fromURLs(classpath.asURLs, getClass.getClassLoader) } - override def newCompiler(): Global = new ReflectGlobal(settings, reporter, reflectionClassloaderFromSettings(settings)) - + override def newCompiler(): Global = new ReflectGlobal(settings, reporter, classloaderFromSettings(settings)) }
\ No newline at end of file diff --git a/src/compiler/scala/tools/nsc/ReflectSetup.scala b/src/compiler/scala/tools/nsc/ReflectSetup.scala new file mode 100644 index 0000000000..26c720a10f --- /dev/null +++ b/src/compiler/scala/tools/nsc/ReflectSetup.scala @@ -0,0 +1,7 @@ +package scala.tools.nsc + +/** A helper trait to initialize things that need to be set before JavaMirrors and other + * reflect specific traits are initialized */ +private[nsc] trait ReflectSetup { this: Global => + phase = new Run().typerPhase +}
\ No newline at end of file diff --git a/src/compiler/scala/tools/nsc/ScalaDoc.scala b/src/compiler/scala/tools/nsc/ScalaDoc.scala index 4fa2cc71e5..5a4b4172c6 100644 --- a/src/compiler/scala/tools/nsc/ScalaDoc.scala +++ b/src/compiler/scala/tools/nsc/ScalaDoc.scala @@ -9,7 +9,7 @@ package scala.tools.nsc import java.io.File.pathSeparator import scala.tools.nsc.doc.DocFactory import scala.tools.nsc.reporters.ConsoleReporter -import scala.tools.nsc.util.FakePos +import scala.reflect.internal.util.FakePos import Properties.msilLibPath /** The main class for scaladoc, a front-end for the Scala compiler diff --git a/src/compiler/scala/tools/nsc/ToolBoxes.scala b/src/compiler/scala/tools/nsc/ToolBoxes.scala deleted file mode 100644 index f5eefa4e62..0000000000 --- a/src/compiler/scala/tools/nsc/ToolBoxes.scala +++ /dev/null @@ -1,84 +0,0 @@ -package scala.tools.nsc - -import util.ScalaClassLoader - -trait ToolBoxes { self: Global => - - def mkToolBox(frontEnd: FrontEnd = mkSilentFrontEnd(), options: String = "") = new ToolBox(frontEnd, options) - - class ToolBox(val frontEnd: FrontEnd, val options: String) extends AbsToolBox { - def typeCheck(tree0: Tree, pt: Type = WildcardType, freeTypes: Map[FreeType, Type] = Map[FreeType, Type](), silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): Tree = { - val tree = substituteFreeTypes(tree0, freeTypes) - val currentTyper = typer - val wrapper1 = if (!withImplicitViewsDisabled) (currentTyper.context.withImplicitsEnabled[Tree] _) else (currentTyper.context.withImplicitsDisabled[Tree] _) - val wrapper2 = if (!withMacrosDisabled) (currentTyper.context.withMacrosEnabled[Tree] _) else (currentTyper.context.withMacrosDisabled[Tree] _) - def wrapper (tree: => Tree) = wrapper1(wrapper2(tree)) - wrapper(currentTyper.silent(_.typed(tree, analyzer.EXPRmode, pt)) match { - case analyzer.SilentResultValue(result) => - result - case error @ analyzer.SilentTypeError(_) => - if (!silent) throw new ToolBoxError(this, "reflective typecheck has failed: %s".format(error.err.errMsg)) - EmptyTree - }) - } - - def inferImplicitValue(pt: Type, silent: Boolean = true, withMacrosDisabled: Boolean = false): Tree = - // todo. implement this - ??? - - def inferImplicitView(tree: Tree, from: Type, to: Type, silent: Boolean = true, withMacrosDisabled: Boolean = false, reportAmbiguous: Boolean = true): Tree = - // todo. implement this - ??? - - def resetAllAttrs(tree: Tree): Tree = - self.resetAllAttrs(tree) - - def resetLocalAttrs(tree: Tree): Tree = - self.resetLocalAttrs(tree) - - def runExpr(tree0: Tree, freeTypes: Map[FreeType, Type] = Map[FreeType, Type]()): Any = { - var tree = substituteFreeTypes(tree0, freeTypes) - // need to reset the tree, otherwise toolbox will refuse to work with it - // upd. this has to be done by the user himself, otherwise we run into troubles. see SI-5713 -// tree = resetAllAttrs(tree0.duplicate) - val imported = importer.importTree(tree) - val toolBox = libraryClasspathMirror.mkToolBox(frontEnd.asInstanceOf[libraryClasspathMirror.FrontEnd], options) - try toolBox.runExpr(imported) - catch { - case ex: toolBox.ToolBoxError => - throw new ToolBoxError(this, ex.message, ex.cause) - } - } - - // [Eugene] how do I make this work without casts? - // private lazy val importer = libraryClasspathMirror.mkImporter(self) - private lazy val importer = libraryClasspathMirror.mkImporter(self).asInstanceOf[libraryClasspathMirror.Importer { val from: self.type }] - - private lazy val libraryClasspathMirror = { - if (self.forMSIL) - throw new UnsupportedOperationException("Scala reflection not available on this platform") - - val libraryClassLoader = { - val classpath = self.classPath.asURLs - var loader: ClassLoader = ScalaClassLoader.fromURLs(classpath, self.getClass.getClassLoader) - - // [Eugene] a heuristic to detect REPL - if (self.settings.exposeEmptyPackage.value) { - import scala.tools.nsc.interpreter._ - val virtualDirectory = self.settings.outputDirs.getSingleOutput.get - loader = new AbstractFileClassLoader(virtualDirectory, loader) {} - } - - loader - } - - new scala.reflect.runtime.Mirror(libraryClassLoader) - } - - class ToolBoxError(val toolBox: ToolBox, val message: String, val cause: Throwable = null) extends Throwable(message, cause) - - object ToolBoxError extends ToolBoxErrorExtractor { - def unapply(error: ToolBoxError): Option[(ToolBox, String)] = Some((error.toolBox, error.message)) - } - } -}
\ No newline at end of file diff --git a/src/compiler/scala/tools/nsc/ast/DocComments.scala b/src/compiler/scala/tools/nsc/ast/DocComments.scala index 028c5741c9..316faba6e2 100755 --- a/src/compiler/scala/tools/nsc/ast/DocComments.scala +++ b/src/compiler/scala/tools/nsc/ast/DocComments.scala @@ -8,7 +8,7 @@ package ast import symtab._ import reporters._ -import util.{Position, NoPosition} +import scala.reflect.internal.util.{Position, NoPosition} import util.DocStrings._ import scala.reflect.internal.Chars._ import scala.collection.mutable @@ -458,7 +458,7 @@ trait DocComments { self: Global => case site :: sites1 => select(site.thisType, name, findIn(sites1)) } val (classes, pkgs) = site.ownerChain.span(!_.isPackageClass) - findIn(classes ::: List(pkgs.head, definitions.RootClass)) + findIn(classes ::: List(pkgs.head, rootMirror.RootClass)) } def getType(_str: String, variable: String): Type = { @@ -508,7 +508,7 @@ trait DocComments { self: Global => val tpe = getType(repl.trim, alias.name.toString) if (tpe != NoType) tpe else { - val alias1 = alias.cloneSymbol(definitions.RootClass, alias.rawflags, newTypeName(repl)) + val alias1 = alias.cloneSymbol(rootMirror.RootClass, alias.rawflags, newTypeName(repl)) typeRef(NoPrefix, alias1, Nil) } case None => diff --git a/src/compiler/scala/tools/nsc/ast/FreeVars.scala b/src/compiler/scala/tools/nsc/ast/FreeVars.scala deleted file mode 100644 index a1983d1834..0000000000 --- a/src/compiler/scala/tools/nsc/ast/FreeVars.scala +++ /dev/null @@ -1,26 +0,0 @@ -package scala.tools.nsc -package ast - -trait FreeVars extends reflect.internal.FreeVars { self: Global => - - import self._ - import definitions._ - import treeInfo._ - - def logFreeVars(position: Position, reified: Tree): Unit = { - if (settings.logFreeTerms.value || settings.logFreeTypes.value) { - reified match { - case Reified(_, symbolTable, _) => - // logging free vars only when they are untyped prevents avalanches of duplicate messages - symbolTable foreach { - case FreeTermDef(_, _, binding, _, origin) if settings.logFreeTerms.value && binding.tpe == null => - reporter.echo(position, "free term: %s %s".format(showRaw(binding), origin)) - case FreeTypeDef(_, _, binding, _, origin) if settings.logFreeTypes.value && binding.tpe == null => - reporter.echo(position, "free type: %s %s".format(showRaw(binding), origin)) - case _ => - // do nothing - } - } - } - } -}
\ No newline at end of file diff --git a/src/compiler/scala/tools/nsc/ast/NodePrinters.scala b/src/compiler/scala/tools/nsc/ast/NodePrinters.scala index ce3106ab29..ba1f3b2e3c 100644 --- a/src/compiler/scala/tools/nsc/ast/NodePrinters.scala +++ b/src/compiler/scala/tools/nsc/ast/NodePrinters.scala @@ -145,6 +145,8 @@ abstract class NodePrinters { str.toString } def printModifiers(tree: MemberDef) { + // [Eugene++] there's most likely a bug here (?) + // see `TreePrinters.printAnnotations` for more information val annots0 = tree.symbol.annotations match { case Nil => tree.mods.annotations case xs => xs map annotationInfoToString @@ -167,7 +169,7 @@ abstract class NodePrinters { } } - def treePrefix(tree: Tree) = showPosition(tree) + tree.printingPrefix + def treePrefix(tree: Tree) = showPosition(tree) + tree.productPrefix def printMultiline(tree: Tree)(body: => Unit) { printMultiline(treePrefix(tree), showAttributes(tree))(body) } diff --git a/src/compiler/scala/tools/nsc/ast/Positions.scala b/src/compiler/scala/tools/nsc/ast/Positions.scala index 83a67cfbe3..74d1f8ab4b 100644 --- a/src/compiler/scala/tools/nsc/ast/Positions.scala +++ b/src/compiler/scala/tools/nsc/ast/Positions.scala @@ -1,7 +1,7 @@ package scala.tools.nsc package ast -import scala.tools.nsc.util.{ SourceFile, Position, OffsetPosition, NoPosition } +import scala.reflect.internal.util.{ SourceFile, Position, OffsetPosition, NoPosition } trait Positions extends scala.reflect.internal.Positions { self: Global => @@ -14,7 +14,7 @@ trait Positions extends scala.reflect.internal.Positions { // [Eugene] disabling this for now. imo it doesn't justify pollution of the public API // override def _checkSetAnnotation(tree: Tree, annot: TreeAnnotation): Unit = { // if (tree.pos != NoPosition && tree.pos != annot.pos) debugwarn("Overwriting annotation "+ tree.annotation +" of tree "+ tree +" with annotation "+ annot) - // // if ((tree.annotation.isInstanceOf[scala.tools.nsc.util.Position] || !annot.isInstanceOf[scala.tools.nsc.util.Position]) && tree.isInstanceOf[Block]) + // // if ((tree.annotation.isInstanceOf[scala.reflect.internal.util.Position] || !annot.isInstanceOf[scala.reflect.internal.util.Position]) && tree.isInstanceOf[Block]) // // println("Updating block from "+ tree.annotation +" to "+ annot) // } diff --git a/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala b/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala index b4beb231ab..f88e41375d 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala @@ -354,7 +354,7 @@ abstract class TreeBrowsers { */ object TreeInfo { /** Return the case class name and the Name, if the node defines one */ - def treeName(t: Tree): (String, Name) = ((t.printingPrefix, t match { + def treeName(t: Tree): (String, Name) = ((t.productPrefix, t match { case UnitTree(unit) => newTermName("" + unit) case Super(_, mix) => newTermName("mix: " + mix) case This(qual) => qual diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala index 6f1a8f488f..1d29e33c50 100644 --- a/src/compiler/scala/tools/nsc/ast/Trees.scala +++ b/src/compiler/scala/tools/nsc/ast/Trees.scala @@ -116,7 +116,10 @@ trait Trees extends reflect.internal.Trees { self: Global => if (vparamss1.isEmpty || !vparamss1.head.isEmpty && vparamss1.head.head.mods.isImplicit) vparamss1 = List() :: vparamss1; val superRef: Tree = atPos(superPos)(gen.mkSuperSelect) - val superCall = (superRef /: argss) (Apply) + def mkApply(fun: Tree, args: List[Tree]) = Apply(fun, args) + val superCall = (superRef /: argss) (mkApply) + // [Eugene++] no longer compiles after I moved the `Apply` case class into scala.reflect.internal + // val superCall = (superRef /: argss) (Apply) List( atPos(wrappingPos(superPos, lvdefs ::: argss.flatten)) ( DefDef(constrMods, nme.CONSTRUCTOR, List(), vparamss1, TypeTree(), Block(lvdefs ::: List(superCall), Literal(Constant()))))) diff --git a/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala b/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala index f702f44338..12b39d9e9c 100755 --- a/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala @@ -9,7 +9,8 @@ package ast.parser import scala.collection.mutable import mutable.{ Buffer, ArrayBuffer, ListBuffer } import scala.util.control.ControlThrowable -import scala.tools.nsc.util.{SourceFile,CharArrayReader} +import scala.tools.nsc.util.CharArrayReader +import scala.reflect.internal.util.SourceFile import scala.xml.{ Text, TextBuffer } import scala.xml.parsing.MarkupParserCommon import scala.xml.Utility.{ isNameStart, isNameChar, isSpace } diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index 43560f9d8d..fd154fe796 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -10,10 +10,11 @@ package scala.tools.nsc package ast.parser import scala.collection.mutable.{ListBuffer, StringBuilder} -import util.{ SourceFile, OffsetPosition, FreshNameCreator } import scala.reflect.internal.{ ModifierFlags => Flags } -import Tokens._ import scala.reflect.internal.Chars.{ isScalaLetter } +import scala.reflect.internal.util.{ SourceFile, OffsetPosition } +import Tokens._ +import util.FreshNameCreator /** Historical note: JavaParsers started life as a direct copy of Parsers * but at a time when that Parsers had been replaced by a different one. @@ -1026,7 +1027,7 @@ self => val tok = in.token val name = ident() t = atPos(start) { - if (tok == BACKQUOTED_IDENT) Ident(name) withAttachment BackquotedIdentifier + if (tok == BACKQUOTED_IDENT) Ident(name) addAttachment BackquotedIdentifierAttachment else Ident(name) } if (in.token == DOT) { @@ -2534,8 +2535,7 @@ self => } else { if (in.token == EQUALS) { in.nextTokenAllow(nme.MACROkw) - if (settings.Xmacros.value && in.token == MACRO || // [Martin] Xmacros can be retired now - in.token == IDENTIFIER && in.name == nme.MACROkw) { + if (in.token == IDENTIFIER && in.name == nme.MACROkw) { in.nextToken() newmods |= Flags.MACRO } diff --git a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala index 87072f3172..6ba273b8ea 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala @@ -5,7 +5,8 @@ package scala.tools.nsc package ast.parser -import scala.tools.nsc.util._ +import scala.tools.nsc.util.CharArrayReader +import scala.reflect.internal.util._ import scala.reflect.internal.Chars._ import Tokens._ import scala.annotation.switch @@ -185,7 +186,7 @@ trait Scanners extends ScannersCommon { sepRegions.nonEmpty && sepRegions.head == STRINGLIT /** Are we directly in a multiline string interpolation expression? - * @pre: inStringInterpolation + * @pre inStringInterpolation */ @inline private def inMultiLineInterpolation = inStringInterpolation && sepRegions.tail.nonEmpty && sepRegions.tail.head == STRINGPART diff --git a/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala index b0204c5971..a4b45482de 100755 --- a/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala @@ -10,7 +10,7 @@ import scala.collection.{ mutable, immutable } import xml.{ EntityRef, Text } import xml.XML.{ xmlns } import symtab.Flags.MUTABLE -import scala.tools.util.StringOps.splitWhere +import scala.reflect.internal.util.StringOps.splitWhere import language.implicitConversions /** This class builds instance of `Tree` that represent XML. diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala index de7e6f9c7a..90f9d538c1 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala @@ -546,7 +546,10 @@ abstract class TreeBuilder { rhs1, List( atPos(pat1.pos) { - CaseDef(pat1, EmptyTree, makeTupleTerm(vars map (_._1) map Ident, true)) + def mkIdent(name: Name) = Ident(name) + CaseDef(pat1, EmptyTree, makeTupleTerm(vars map (_._1) map mkIdent, true)) + // [Eugene++] no longer compiles after I moved the `Ident` case class into scala.reflect.internal + // CaseDef(pat1, EmptyTree, makeTupleTerm(vars map (_._1) map Ident, true)) } )) } diff --git a/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala b/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala index b8ecaf1b43..86533c713e 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala @@ -9,7 +9,7 @@ package icode import scala.collection.{ mutable, immutable } import mutable.{ ListBuffer, ArrayBuffer } -import util.{ Position, NoPosition } +import scala.reflect.internal.util.{ Position, NoPosition } import backend.icode.analysis.ProgramPoint import language.postfixOps diff --git a/src/compiler/scala/tools/nsc/backend/icode/Members.scala b/src/compiler/scala/tools/nsc/backend/icode/Members.scala index efb4e7a199..00f4a9d262 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/Members.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/Members.scala @@ -9,7 +9,7 @@ package icode import java.io.PrintWriter import scala.collection.{ mutable, immutable } -import util.{ SourceFile, NoSourceFile } +import scala.reflect.internal.util.{ SourceFile, NoSourceFile } import symtab.Flags.{ DEFERRED } trait ReferenceEquality { diff --git a/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala b/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala index 3179fc5c56..5f495c8456 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala @@ -10,7 +10,7 @@ package backend package icode import scala.tools.nsc.ast._ -import scala.tools.nsc.util.{Position,NoPosition} +import scala.reflect.internal.util.{Position,NoPosition} /* A pattern match diff --git a/src/compiler/scala/tools/nsc/backend/icode/Printers.scala b/src/compiler/scala/tools/nsc/backend/icode/Printers.scala index 4ea253d29d..d34d93f147 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/Printers.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/Printers.scala @@ -9,7 +9,7 @@ package icode import java.io.PrintWriter import scala.tools.nsc.symtab.Flags -import scala.tools.nsc.util.Position +import scala.reflect.internal.util.Position trait Printers { self: ICodes => import global._ diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala index 3f193672ec..0c527fbaf4 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala @@ -53,7 +53,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters { override def erasedTypes = true
def apply(cls: IClass) = sys.error("no implementation")
- val BeanInfoAttr = definitions.getRequiredClass("scala.beans.BeanInfo")
+ val BeanInfoAttr = rootMirror.getRequiredClass("scala.beans.BeanInfo")
def isJavaEntryPoint(icls: IClass) = {
val sym = icls.symbol
@@ -345,8 +345,8 @@ abstract class GenASM extends SubComponent with BytecodeWriters { def inameToSymbol(iname: String): Symbol = {
val name = global.newTypeName(iname)
val res0 =
- if (nme.isModuleName(name)) definitions.getModule(nme.stripModuleSuffix(name))
- else definitions.getClassByName(name.replace('/', '.')) // TODO fails for inner classes (but this hasn't been tested).
+ if (nme.isModuleName(name)) rootMirror.getModule(nme.stripModuleSuffix(name))
+ else rootMirror.getClassByName(name.replace('/', '.')) // TODO fails for inner classes (but this hasn't been tested).
assert(res0 != NoSymbol)
val res = jsymbol(res0)
res
@@ -1180,8 +1180,8 @@ abstract class GenASM extends SubComponent with BytecodeWriters { */
private val androidFieldName = newTermName("CREATOR")
- private lazy val AndroidParcelableInterface = definitions.getClassIfDefined("android.os.Parcelable")
- private lazy val AndroidCreatorClass = definitions.getClassIfDefined("android.os.Parcelable$Creator")
+ private lazy val AndroidParcelableInterface = rootMirror.getClassIfDefined("android.os.Parcelable")
+ private lazy val AndroidCreatorClass = rootMirror.getClassIfDefined("android.os.Parcelable$Creator")
def isAndroidParcelableClass(sym: Symbol) =
(AndroidParcelableInterface != NoSymbol) &&
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenAndroid.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenAndroid.scala index 1ba5b155fc..e3da5c486b 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenAndroid.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenAndroid.scala @@ -25,8 +25,8 @@ trait GenAndroid { */ private val fieldName = newTermName("CREATOR") - private lazy val AndroidParcelableInterface = definitions.getClassIfDefined("android.os.Parcelable") - private lazy val AndroidCreatorClass = definitions.getClassIfDefined("android.os.Parcelable$Creator") + private lazy val AndroidParcelableInterface = rootMirror.getClassIfDefined("android.os.Parcelable") + private lazy val AndroidCreatorClass = rootMirror.getClassIfDefined("android.os.Parcelable$Creator") def isAndroidParcelableClass(sym: Symbol) = (AndroidParcelableInterface != NoSymbol) && diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala index 73bcd08f4b..21260d399c 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala @@ -11,7 +11,7 @@ import java.nio.ByteBuffer import scala.collection.{ mutable, immutable } import scala.reflect.internal.pickling.{ PickleFormat, PickleBuffer } import scala.tools.nsc.symtab._ -import scala.tools.nsc.util.{ SourceFile, NoSourceFile } +import scala.reflect.internal.util.{ SourceFile, NoSourceFile } import scala.reflect.internal.ClassfileConstants._ import ch.epfl.lamp.fjbg._ import JAccessFlags._ @@ -203,10 +203,10 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with val MethodHandleType = new JObjectType("java.dyn.MethodHandle") // Scala attributes - val BeanInfoAttr = definitions.getRequiredClass("scala.beans.BeanInfo") - val BeanInfoSkipAttr = definitions.getRequiredClass("scala.beans.BeanInfoSkip") - val BeanDisplayNameAttr = definitions.getRequiredClass("scala.beans.BeanDisplayName") - val BeanDescriptionAttr = definitions.getRequiredClass("scala.beans.BeanDescription") + val BeanInfoAttr = rootMirror.getRequiredClass("scala.beans.BeanInfo") + val BeanInfoSkipAttr = rootMirror.getRequiredClass("scala.beans.BeanInfoSkip") + val BeanDisplayNameAttr = rootMirror.getRequiredClass("scala.beans.BeanDisplayName") + val BeanDescriptionAttr = rootMirror.getRequiredClass("scala.beans.BeanDescription") final val ExcludedForwarderFlags = { import Flags._ @@ -1711,7 +1711,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with abort("Unknown arithmetic primitive " + primitive) } - case Logical(op, kind) => (op, kind) match { + case Logical(op, kind) => ((op, kind): @unchecked) match { case (AND, LONG) => jcode.emitLAND() case (AND, INT) => jcode.emitIAND() case (AND, _) => @@ -1734,7 +1734,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with jcode.emitT2T(javaType(INT), javaType(kind)); } - case Shift(op, kind) => (op, kind) match { + case Shift(op, kind) => ((op, kind): @unchecked) match { case (LSL, LONG) => jcode.emitLSHL() case (LSL, INT) => jcode.emitISHL() case (LSL, _) => diff --git a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala index 08e059419a..f332e8cfdd 100644 --- a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala +++ b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala @@ -9,7 +9,7 @@ package backend.opt import scala.collection.mutable import scala.tools.nsc.symtab._ -import scala.tools.nsc.util.NoSourceFile +import scala.reflect.internal.util.NoSourceFile /** * @author Iulian Dragos @@ -100,7 +100,7 @@ abstract class Inliners extends SubComponent { } def isBottomType(sym: Symbol) = sym == NullClass || sym == NothingClass - def posToStr(pos: util.Position) = if (pos.isDefined) pos.point.toString else "<nopos>" + def posToStr(pos: scala.reflect.internal.util.Position) = if (pos.isDefined) pos.point.toString else "<nopos>" /** Is the given class a closure? */ def isClosureClass(cls: Symbol): Boolean = diff --git a/src/compiler/scala/tools/nsc/dependencies/DependencyAnalysis.scala b/src/compiler/scala/tools/nsc/dependencies/DependencyAnalysis.scala index 02be916f59..317cc28298 100644 --- a/src/compiler/scala/tools/nsc/dependencies/DependencyAnalysis.scala +++ b/src/compiler/scala/tools/nsc/dependencies/DependencyAnalysis.scala @@ -1,11 +1,11 @@ package scala.tools.nsc package dependencies -import util.SourceFile import io.Path import collection._ import symtab.Flags import scala.tools.nsc.io.AbstractFile +import scala.reflect.internal.util.SourceFile trait DependencyAnalysis extends SubComponent with Files { import global._ diff --git a/src/compiler/scala/tools/nsc/doc/DocFactory.scala b/src/compiler/scala/tools/nsc/doc/DocFactory.scala index 76a8b87ba7..e2e1ddf065 100644 --- a/src/compiler/scala/tools/nsc/doc/DocFactory.scala +++ b/src/compiler/scala/tools/nsc/doc/DocFactory.scala @@ -8,7 +8,7 @@ package doc import scala.util.control.ControlThrowable import reporters.Reporter -import util.{ NoPosition, BatchSourceFile} +import scala.reflect.internal.util.{ NoPosition, BatchSourceFile} import io.{ File, Directory } import DocParser.Parsed diff --git a/src/compiler/scala/tools/nsc/doc/DocParser.scala b/src/compiler/scala/tools/nsc/doc/DocParser.scala index 2bd80f31da..119a2c06e9 100644 --- a/src/compiler/scala/tools/nsc/doc/DocParser.scala +++ b/src/compiler/scala/tools/nsc/doc/DocParser.scala @@ -8,7 +8,7 @@ package nsc package doc import reporters._ -import util._ +import scala.reflect.internal.util._ import interactive.RangePositions import DocParser.Parsed diff --git a/src/compiler/scala/tools/nsc/doc/Settings.scala b/src/compiler/scala/tools/nsc/doc/Settings.scala index d3a1d47de8..4458889d55 100644 --- a/src/compiler/scala/tools/nsc/doc/Settings.scala +++ b/src/compiler/scala/tools/nsc/doc/Settings.scala @@ -150,15 +150,15 @@ class Settings(error: String => Unit) extends scala.tools.nsc.Settings(error) { * the function result should be a humanly-understandable description of the type class */ val knownTypeClasses: Map[String, String => String] = Map() + - ("<root>.scala.package.Numeric" -> ((tparam: String) => tparam + " is a numeric class, such as Int, Long, Float or Double")) + - ("<root>.scala.package.Integral" -> ((tparam: String) => tparam + " is an integral numeric class, such as Int or Long")) + - ("<root>.scala.package.Fractional" -> ((tparam: String) => tparam + " is a fractional numeric class, such as Float or Double")) + - ("<root>.scala.reflect.Manifest" -> ((tparam: String) => tparam + " is accompanied by a Manifest, which is a runtime representation of its type that survives erasure")) + - ("<root>.scala.reflect.ClassManifest" -> ((tparam: String) => tparam + " is accompanied by a ClassManifest, which is a runtime representation of its type that survives erasure")) + - ("<root>.scala.reflect.OptManifest" -> ((tparam: String) => tparam + " is accompanied by an OptManifest, which can be either a runtime representation of its type or the NoManifest, which means the runtime type is not available")) + - ("<root>.scala.reflect.ClassTag" -> ((tparam: String) => tparam + " is accompanied by a ClassTag, which is a runtime representation of its type that survives erasure")) + - ("<root>.scala.reflect.TypeTag" -> ((tparam: String) => tparam + " is accompanied by a TypeTag, which is a runtime representation of its type that survives erasure")) + - ("<root>.scala.reflect.ConcreteTypeTag" -> ((tparam: String) => tparam + " is accompanied by an ConcreteTypeTag, which is a runtime representation of a concrete type that survives erasure")) + ("<root>.scala.package.Numeric" -> ((tparam: String) => tparam + " is a numeric class, such as Int, Long, Float or Double")) + + ("<root>.scala.package.Integral" -> ((tparam: String) => tparam + " is an integral numeric class, such as Int or Long")) + + ("<root>.scala.package.Fractional" -> ((tparam: String) => tparam + " is a fractional numeric class, such as Float or Double")) + + ("<root>.scala.reflect.Manifest" -> ((tparam: String) => tparam + " is accompanied by a Manifest, which is a runtime representation of its type that survives erasure")) + + ("<root>.scala.reflect.ClassManifest" -> ((tparam: String) => tparam + " is accompanied by a ClassManifest, which is a runtime representation of its type that survives erasure")) + + ("<root>.scala.reflect.OptManifest" -> ((tparam: String) => tparam + " is accompanied by an OptManifest, which can be either a runtime representation of its type or the NoManifest, which means the runtime type is not available")) + + ("<root>.scala.reflect.ClassTag" -> ((tparam: String) => tparam + " is accompanied by a ClassTag, which is a runtime representation of its type that survives erasure")) + + ("<root>.scala.reflect.AbsTypeTag" -> ((tparam: String) => tparam + " is accompanied by an AbsTypeTag, which is a runtime representation of its type that survives erasure")) + + ("<root>.scala.reflect.TypeTag" -> ((tparam: String) => tparam + " is accompanied by a TypeTag, which is a runtime representation of its type that survives erasure")) /** * Set of classes to exclude from index and diagrams diff --git a/src/compiler/scala/tools/nsc/doc/Uncompilable.scala b/src/compiler/scala/tools/nsc/doc/Uncompilable.scala index 8f426a443d..fef753b12c 100644 --- a/src/compiler/scala/tools/nsc/doc/Uncompilable.scala +++ b/src/compiler/scala/tools/nsc/doc/Uncompilable.scala @@ -16,7 +16,8 @@ trait Uncompilable { val settings: Settings import global.{ reporter, inform, warning, newTypeName, newTermName, Symbol, Name, DocComment, NoSymbol } - import global.definitions.{ RootClass, AnyRefClass } + import global.definitions.AnyRefClass + import global.rootMirror.RootClass private implicit def translateName(name: Global#Name) = if (name.isTypeName) newTypeName("" + name) else newTermName("" + name) diff --git a/src/compiler/scala/tools/nsc/doc/html/SyntaxHigh.scala b/src/compiler/scala/tools/nsc/doc/html/SyntaxHigh.scala index 3ff973ec66..629ac84b34 100644 --- a/src/compiler/scala/tools/nsc/doc/html/SyntaxHigh.scala +++ b/src/compiler/scala/tools/nsc/doc/html/SyntaxHigh.scala @@ -40,8 +40,8 @@ private[html] object SyntaxHigh { /** Standard library classes/objects, sorted alphabetically */ val standards = Array ( - "Any", "AnyRef", "AnyVal", "App", "Application", "Array", - "Boolean", "Byte", "Char", "Class", "ClassTag", "ClassManifest", "ConcreteTypeTag", + "AbsTypeTag", "Any", "AnyRef", "AnyVal", "App", "Application", "Array", + "Boolean", "Byte", "Char", "Class", "ClassTag", "ClassManifest", "Console", "Double", "Enumeration", "Float", "Function", "Int", "List", "Long", "Manifest", "Map", "NoManifest", "None", "Nothing", "Null", "Object", "Option", "OptManifest", diff --git a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala index 9062203dcd..3dd77d47da 100644 --- a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala +++ b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala @@ -20,7 +20,8 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { thisFactory: ModelFactory with ModelFactoryImplicitSupport with CommentFactory with TreeFactory => import global._ - import definitions.{ ObjectClass, RootPackage, EmptyPackage, NothingClass, AnyClass, AnyValClass, AnyRefClass } + import definitions.{ ObjectClass, NothingClass, AnyClass, AnyValClass, AnyRefClass } + import rootMirror.{ RootPackage, EmptyPackage } private var droppedPackages = 0 def templatesCount = templatesCache.size - droppedPackages @@ -339,7 +340,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { /** */ def normalizeTemplate(aSym: Symbol): Symbol = aSym match { - case null | EmptyPackage | NoSymbol => + case null | rootMirror.EmptyPackage | NoSymbol => normalizeTemplate(RootPackage) case ObjectClass => normalizeTemplate(AnyRefClass) diff --git a/src/compiler/scala/tools/nsc/doc/model/TreeFactory.scala b/src/compiler/scala/tools/nsc/doc/model/TreeFactory.scala index f948d53c8b..fe586c4996 100755 --- a/src/compiler/scala/tools/nsc/doc/model/TreeFactory.scala +++ b/src/compiler/scala/tools/nsc/doc/model/TreeFactory.scala @@ -3,7 +3,7 @@ package doc package model import scala.collection._ -import util.{RangePosition, OffsetPosition, SourceFile} +import scala.reflect.internal.util.{RangePosition, OffsetPosition, SourceFile} /** The goal of this trait is , using makeTree, * to browse a tree to diff --git a/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala b/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala index e6bc76f676..996223b9f9 100644 --- a/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala +++ b/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala @@ -12,7 +12,7 @@ import reporters.Reporter import scala.collection._ import scala.util.matching.Regex import scala.annotation.switch -import util.{NoPosition, Position} +import scala.reflect.internal.util.{NoPosition, Position} import language.postfixOps /** The comment parser transforms raw comment strings into `Comment` objects. diff --git a/src/compiler/scala/tools/nsc/interactive/BuildManager.scala b/src/compiler/scala/tools/nsc/interactive/BuildManager.scala index 0f89236861..7d36d17a18 100644 --- a/src/compiler/scala/tools/nsc/interactive/BuildManager.scala +++ b/src/compiler/scala/tools/nsc/interactive/BuildManager.scala @@ -9,7 +9,7 @@ package interactive import scala.collection._ import scala.tools.nsc.reporters.{Reporter, ConsoleReporter} -import util.FakePos +import scala.reflect.internal.util.FakePos import dependencies._ import io.AbstractFile diff --git a/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala b/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala index 1b91b06942..801b4ad22b 100644 --- a/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala +++ b/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala @@ -7,11 +7,12 @@ package interactive import scala.util.control.ControlThrowable import scala.tools.nsc.io.AbstractFile -import scala.tools.nsc.util.{SourceFile, Position, WorkScheduler} import scala.tools.nsc.symtab._ import scala.tools.nsc.ast._ import scala.tools.nsc.util.FailedInterrupt import scala.tools.nsc.util.EmptyAction +import scala.tools.nsc.util.WorkScheduler +import scala.reflect.internal.util.{SourceFile, Position} /** Interface of interactive compiler to a client such as an IDE * The model the presentation compiler consists of the following parts: diff --git a/src/compiler/scala/tools/nsc/interactive/ContextTrees.scala b/src/compiler/scala/tools/nsc/interactive/ContextTrees.scala index fc48d4819c..80d2796801 100644 --- a/src/compiler/scala/tools/nsc/interactive/ContextTrees.scala +++ b/src/compiler/scala/tools/nsc/interactive/ContextTrees.scala @@ -6,7 +6,7 @@ package scala.tools.nsc package interactive import collection.mutable.ArrayBuffer -import util.Position +import scala.reflect.internal.util.Position trait ContextTrees { self: Global => diff --git a/src/compiler/scala/tools/nsc/interactive/Global.scala b/src/compiler/scala/tools/nsc/interactive/Global.scala index edf0108e58..82ce59d075 100644 --- a/src/compiler/scala/tools/nsc/interactive/Global.scala +++ b/src/compiler/scala/tools/nsc/interactive/Global.scala @@ -11,7 +11,8 @@ import mutable.{LinkedHashMap, SynchronizedMap, HashSet, SynchronizedSet} import scala.concurrent.SyncVar import scala.util.control.ControlThrowable import scala.tools.nsc.io.{ AbstractFile, LogReplay, Logger, NullLogger, Replayer } -import scala.tools.nsc.util.{ SourceFile, BatchSourceFile, Position, RangePosition, NoPosition, WorkScheduler, MultiHashMap } +import scala.tools.nsc.util.{ WorkScheduler, MultiHashMap } +import scala.reflect.internal.util.{ SourceFile, BatchSourceFile, Position, RangePosition, NoPosition } import scala.tools.nsc.reporters._ import scala.tools.nsc.symtab._ import scala.tools.nsc.ast._ diff --git a/src/compiler/scala/tools/nsc/interactive/InteractiveReporter.scala b/src/compiler/scala/tools/nsc/interactive/InteractiveReporter.scala index 397e83a362..df8fc3b21e 100644 --- a/src/compiler/scala/tools/nsc/interactive/InteractiveReporter.scala +++ b/src/compiler/scala/tools/nsc/interactive/InteractiveReporter.scala @@ -6,7 +6,7 @@ package scala.tools.nsc package interactive import collection.mutable.ArrayBuffer -import util.Position +import scala.reflect.internal.util.Position import reporters.Reporter case class Problem(pos: Position, msg: String, severityLevel: Int) diff --git a/src/compiler/scala/tools/nsc/interactive/Picklers.scala b/src/compiler/scala/tools/nsc/interactive/Picklers.scala index b7a9c7329c..bf920191c8 100644 --- a/src/compiler/scala/tools/nsc/interactive/Picklers.scala +++ b/src/compiler/scala/tools/nsc/interactive/Picklers.scala @@ -5,10 +5,12 @@ package scala.tools.nsc package interactive -import util.{SourceFile, BatchSourceFile, InterruptReq} +import util.InterruptReq +import scala.reflect.internal.util.{SourceFile, BatchSourceFile} import io.{AbstractFile, PlainFile} -import util.{Position, RangePosition, NoPosition, OffsetPosition, TransparentPosition, EmptyAction} +import util.EmptyAction +import scala.reflect.internal.util.{Position, RangePosition, NoPosition, OffsetPosition, TransparentPosition} import io.{Pickler, CondPickler} import io.Pickler._ import collection.mutable @@ -115,7 +117,7 @@ trait Picklers { self: Global => if (sym.isOverloaded) makeSymbol(sym.alternatives(rest.head.toString.toInt), rest.tail) else makeSymbol(sym, rest) } - pkl[List[Name]] .wrapped { makeSymbol(definitions.RootClass, _) } { ownerNames(_, new ListBuffer).toList } + pkl[List[Name]] .wrapped { makeSymbol(rootMirror.RootClass, _) } { ownerNames(_, new ListBuffer).toList } } implicit def workEvent: Pickler[WorkEvent] = { diff --git a/src/compiler/scala/tools/nsc/interactive/REPL.scala b/src/compiler/scala/tools/nsc/interactive/REPL.scala index 1d78cc6e1c..1dcc979255 100644 --- a/src/compiler/scala/tools/nsc/interactive/REPL.scala +++ b/src/compiler/scala/tools/nsc/interactive/REPL.scala @@ -6,7 +6,7 @@ package scala.tools.nsc package interactive import scala.concurrent.SyncVar -import scala.tools.nsc.util._ +import scala.reflect.internal.util._ import scala.tools.nsc.symtab._ import scala.tools.nsc.ast._ import scala.tools.nsc.reporters._ @@ -141,7 +141,7 @@ object REPL { */ def compileInstrumented(iSourceName: String, arguments: List[String]): Option[AbstractFile] = { println("compiling "+iSourceName) - val command = new CompilerCommand(iSourceName :: arguments, reporter.error(scala.tools.nsc.util.NoPosition, _)) + val command = new CompilerCommand(iSourceName :: arguments, reporter.error(scala.reflect.internal.util.NoPosition, _)) val virtualDirectoryOpt = if (arguments contains "-d") None diff --git a/src/compiler/scala/tools/nsc/interactive/RangePositions.scala b/src/compiler/scala/tools/nsc/interactive/RangePositions.scala index 49ba9d0aeb..06828f3a3a 100644 --- a/src/compiler/scala/tools/nsc/interactive/RangePositions.scala +++ b/src/compiler/scala/tools/nsc/interactive/RangePositions.scala @@ -7,7 +7,8 @@ package interactive import ast.Trees import ast.Positions -import scala.tools.nsc.util.{SourceFile, Position, RangePosition, NoPosition, WorkScheduler} +import scala.reflect.internal.util.{SourceFile, Position, RangePosition, NoPosition} +import scala.tools.nsc.util.WorkScheduler import scala.collection.mutable.ListBuffer /** Handling range positions @@ -189,7 +190,7 @@ self: scala.tools.nsc.Global => override def validatePositions(tree: Tree) { def reportTree(prefix : String, tree : Tree) { val source = if (tree.pos.isDefined) tree.pos.source else "" - inform("== "+prefix+" tree ["+tree.id+"] of type "+tree.printingPrefix+" at "+tree.pos.show+source) + inform("== "+prefix+" tree ["+tree.id+"] of type "+tree.productPrefix+" at "+tree.pos.show+source) inform("") inform(treeStatus(tree)) inform("") diff --git a/src/compiler/scala/tools/nsc/interactive/RefinedBuildManager.scala b/src/compiler/scala/tools/nsc/interactive/RefinedBuildManager.scala index bad181eb76..57f0835edd 100644 --- a/src/compiler/scala/tools/nsc/interactive/RefinedBuildManager.scala +++ b/src/compiler/scala/tools/nsc/interactive/RefinedBuildManager.scala @@ -12,7 +12,8 @@ import scala.util.control.Breaks._ import scala.tools.nsc.symtab.Flags import dependencies._ -import util.{FakePos, ClassPath} +import scala.reflect.internal.util.FakePos +import util.ClassPath import io.AbstractFile import scala.tools.util.PathResolver diff --git a/src/compiler/scala/tools/nsc/interactive/RichCompilationUnits.scala b/src/compiler/scala/tools/nsc/interactive/RichCompilationUnits.scala index 9ef7d33549..9b2fee5f1f 100644 --- a/src/compiler/scala/tools/nsc/interactive/RichCompilationUnits.scala +++ b/src/compiler/scala/tools/nsc/interactive/RichCompilationUnits.scala @@ -5,7 +5,7 @@ package scala.tools.nsc package interactive -import scala.tools.nsc.util.{SourceFile, Position, NoPosition} +import scala.reflect.internal.util.{SourceFile, Position, NoPosition} import collection.mutable.ArrayBuffer trait RichCompilationUnits { self: Global => diff --git a/src/compiler/scala/tools/nsc/interactive/ScratchPadMaker.scala b/src/compiler/scala/tools/nsc/interactive/ScratchPadMaker.scala index e2dcc48709..a3f6726b44 100644 --- a/src/compiler/scala/tools/nsc/interactive/ScratchPadMaker.scala +++ b/src/compiler/scala/tools/nsc/interactive/ScratchPadMaker.scala @@ -1,7 +1,7 @@ package scala.tools.nsc package interactive -import util.{SourceFile, BatchSourceFile, RangePosition} +import scala.reflect.internal.util.{SourceFile, BatchSourceFile, RangePosition} import collection.mutable.ArrayBuffer import reflect.internal.Chars.isLineBreakChar diff --git a/src/compiler/scala/tools/nsc/interactive/SimpleBuildManager.scala b/src/compiler/scala/tools/nsc/interactive/SimpleBuildManager.scala index dd06e7dafa..6c9c7249e8 100644 --- a/src/compiler/scala/tools/nsc/interactive/SimpleBuildManager.scala +++ b/src/compiler/scala/tools/nsc/interactive/SimpleBuildManager.scala @@ -10,7 +10,7 @@ import scala.collection._ import scala.tools.nsc.reporters.{Reporter, ConsoleReporter} import dependencies._ -import util.FakePos +import scala.reflect.internal.util.FakePos import io.AbstractFile /** A simple build manager, using the default scalac dependency tracker. diff --git a/src/compiler/scala/tools/nsc/interactive/tests/InteractiveTest.scala b/src/compiler/scala/tools/nsc/interactive/tests/InteractiveTest.scala index 9dc2a8de10..f622f11ffd 100644 --- a/src/compiler/scala/tools/nsc/interactive/tests/InteractiveTest.scala +++ b/src/compiler/scala/tools/nsc/interactive/tests/InteractiveTest.scala @@ -12,8 +12,8 @@ import java.io.File.pathSeparatorChar import java.io.File.separatorChar import scala.annotation.migration -import scala.tools.nsc.util.Position -import scala.tools.nsc.util.SourceFile +import scala.reflect.internal.util.Position +import scala.reflect.internal.util.SourceFile import collection.mutable.ListBuffer diff --git a/src/compiler/scala/tools/nsc/interactive/tests/Tester.scala b/src/compiler/scala/tools/nsc/interactive/tests/Tester.scala index 034db218ae..55198e3617 100644 --- a/src/compiler/scala/tools/nsc/interactive/tests/Tester.scala +++ b/src/compiler/scala/tools/nsc/interactive/tests/Tester.scala @@ -6,7 +6,7 @@ package scala.tools.nsc package interactive package tests -import util._ +import scala.reflect.internal.util._ import reporters._ import io.AbstractFile import collection.mutable.ArrayBuffer diff --git a/src/compiler/scala/tools/nsc/interactive/tests/core/AskCommand.scala b/src/compiler/scala/tools/nsc/interactive/tests/core/AskCommand.scala index 657ef23eed..0cf32a8d8a 100644 --- a/src/compiler/scala/tools/nsc/interactive/tests/core/AskCommand.scala +++ b/src/compiler/scala/tools/nsc/interactive/tests/core/AskCommand.scala @@ -7,8 +7,8 @@ package interactive package tests.core import scala.tools.nsc.interactive.Response -import scala.tools.nsc.util.Position -import scala.tools.nsc.util.SourceFile +import scala.reflect.internal.util.Position +import scala.reflect.internal.util.SourceFile /** * A trait for defining commands that can be queried to the diff --git a/src/compiler/scala/tools/nsc/interactive/tests/core/CoreTestDefs.scala b/src/compiler/scala/tools/nsc/interactive/tests/core/CoreTestDefs.scala index d6102734ab..c8e6b6ccce 100644 --- a/src/compiler/scala/tools/nsc/interactive/tests/core/CoreTestDefs.scala +++ b/src/compiler/scala/tools/nsc/interactive/tests/core/CoreTestDefs.scala @@ -2,7 +2,7 @@ package scala.tools.nsc package interactive package tests.core -import scala.tools.nsc.util.Position +import scala.reflect.internal.util.Position import scala.tools.nsc.interactive.tests.core._ /** Set of core test definitions that are executed for each test run. */ diff --git a/src/compiler/scala/tools/nsc/interactive/tests/core/PresentationCompilerRequestsWorkingMode.scala b/src/compiler/scala/tools/nsc/interactive/tests/core/PresentationCompilerRequestsWorkingMode.scala index d2baaf32c6..18a8eb5fc3 100644 --- a/src/compiler/scala/tools/nsc/interactive/tests/core/PresentationCompilerRequestsWorkingMode.scala +++ b/src/compiler/scala/tools/nsc/interactive/tests/core/PresentationCompilerRequestsWorkingMode.scala @@ -2,8 +2,8 @@ package scala.tools.nsc package interactive package tests.core -import scala.tools.nsc.util.Position -import scala.tools.nsc.util.SourceFile +import scala.reflect.internal.util.Position +import scala.reflect.internal.util.SourceFile trait PresentationCompilerRequestsWorkingMode extends TestResources { diff --git a/src/compiler/scala/tools/nsc/interactive/tests/core/PresentationCompilerTestDef.scala b/src/compiler/scala/tools/nsc/interactive/tests/core/PresentationCompilerTestDef.scala index 8b8be697cc..9cf2aa4fe4 100644 --- a/src/compiler/scala/tools/nsc/interactive/tests/core/PresentationCompilerTestDef.scala +++ b/src/compiler/scala/tools/nsc/interactive/tests/core/PresentationCompilerTestDef.scala @@ -1,7 +1,7 @@ package scala.tools.nsc.interactive.tests.core import scala.tools.nsc.interactive.Global -import scala.tools.nsc.util.Position +import scala.reflect.internal.util.Position trait PresentationCompilerTestDef { diff --git a/src/compiler/scala/tools/nsc/interactive/tests/core/SourcesCollector.scala b/src/compiler/scala/tools/nsc/interactive/tests/core/SourcesCollector.scala index 21e90fe57f..e80b741a8d 100644 --- a/src/compiler/scala/tools/nsc/interactive/tests/core/SourcesCollector.scala +++ b/src/compiler/scala/tools/nsc/interactive/tests/core/SourcesCollector.scala @@ -1,6 +1,6 @@ package scala.tools.nsc.interactive.tests.core -import scala.tools.nsc.util.{SourceFile,BatchSourceFile} +import scala.reflect.internal.util.{SourceFile,BatchSourceFile} import scala.tools.nsc.io.{AbstractFile,Path} private[tests] object SourcesCollector { diff --git a/src/compiler/scala/tools/nsc/interactive/tests/core/TestResources.scala b/src/compiler/scala/tools/nsc/interactive/tests/core/TestResources.scala index 106d1dacb3..887c3cf29b 100644 --- a/src/compiler/scala/tools/nsc/interactive/tests/core/TestResources.scala +++ b/src/compiler/scala/tools/nsc/interactive/tests/core/TestResources.scala @@ -1,7 +1,7 @@ package scala.tools.nsc.interactive.tests.core import scala.tools.nsc.io.Path -import scala.tools.nsc.util.SourceFile +import scala.reflect.internal.util.SourceFile /** Resources used by the test. */ private[tests] trait TestResources extends TestSettings { diff --git a/src/compiler/scala/tools/nsc/interpreter/AbstractFileClassLoader.scala b/src/compiler/scala/tools/nsc/interpreter/AbstractFileClassLoader.scala index 605ecee6c7..7289a947f4 100644 --- a/src/compiler/scala/tools/nsc/interpreter/AbstractFileClassLoader.scala +++ b/src/compiler/scala/tools/nsc/interpreter/AbstractFileClassLoader.scala @@ -15,7 +15,7 @@ import scala.collection.{ mutable, immutable } * * @author Lex Spoon */ -class AbstractFileClassLoader(root: AbstractFile, parent: ClassLoader) +class AbstractFileClassLoader(val root: AbstractFile, parent: ClassLoader) extends ClassLoader(parent) with ScalaClassLoader { diff --git a/src/compiler/scala/tools/nsc/interpreter/ExprTyper.scala b/src/compiler/scala/tools/nsc/interpreter/ExprTyper.scala index 79b429e26a..f2438dcc20 100644 --- a/src/compiler/scala/tools/nsc/interpreter/ExprTyper.scala +++ b/src/compiler/scala/tools/nsc/interpreter/ExprTyper.scala @@ -6,7 +6,7 @@ package scala.tools.nsc package interpreter -import util.BatchSourceFile +import scala.reflect.internal.util.BatchSourceFile import scala.tools.nsc.ast.parser.Tokens.EOF trait ExprTyper { diff --git a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala index de778e7469..e5e7d7081d 100644 --- a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala +++ b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala @@ -24,6 +24,8 @@ import util.ScalaClassLoader import ScalaClassLoader._ import scala.tools.util._ import language.{implicitConversions, existentials} +import scala.reflect.{ClassTag, classTag} +import scala.tools.reflect.StdTags._ /** The Scala interactive shell. It provides a read-eval-print loop * around the Interpreter class. @@ -105,7 +107,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) } def isAsync = !settings.Yreplsync.value - lazy val power = new Power(intp, new StdReplVals(this)) + lazy val power = new Power(intp, new StdReplVals(this))(tagOfStdReplVals, classTag[StdReplVals]) def history = in.history /** The context class loader at the time this object was created */ @@ -554,7 +556,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) // return false if repl should exit def processLine(line: String): Boolean = { if (isAsync) { - awaitInitialized() + if (!awaitInitialized()) return false runThunks() } if (line eq null) false // assume null means EOF @@ -830,7 +832,14 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) } // Bind intp somewhere out of the regular namespace where // we can get at it in generated code. - addThunk(intp.quietBind("$intp" -> intp)) + addThunk(intp.quietBind(NamedParam[IMain]("$intp", intp)(tagOfIMain, classTag[IMain]))) + addThunk({ + import scala.tools.nsc.io._ + import Properties.userHome + import compat.Platform.EOL + val autorun = replProps.replAutorunCode.option flatMap (f => io.File(f).safeSlurp()) + if (autorun.isDefined) intp.quietRun(autorun.get) + }) loadFiles(settings) // it is broken on startup; go ahead and exit diff --git a/src/compiler/scala/tools/nsc/interpreter/ILoopInit.scala b/src/compiler/scala/tools/nsc/interpreter/ILoopInit.scala index 9072eaae46..37e4dfaea4 100644 --- a/src/compiler/scala/tools/nsc/interpreter/ILoopInit.scala +++ b/src/compiler/scala/tools/nsc/interpreter/ILoopInit.scala @@ -6,7 +6,7 @@ package scala.tools.nsc package interpreter -import util.Position +import scala.reflect.internal.util.Position import scala.util.control.Exception.ignoring /** @@ -44,6 +44,7 @@ trait ILoopInit { } // a condition used to ensure serial access to the compiler. @volatile private var initIsComplete = false + @volatile private var initError: String = null private def elapsed() = "%.3f".format((System.nanoTime - initStart).toDouble / 1000000000L) // the method to be called when the interpreter is initialized. @@ -63,9 +64,17 @@ trait ILoopInit { } // called from main repl loop - protected def awaitInitialized() { + protected def awaitInitialized(): Boolean = { if (!initIsComplete) withLock { while (!initIsComplete) initLoopCondition.await() } + if (initError != null) { + println(""" + |Failed to initialize the REPL due to an unexpected error. + |This is a bug, please, report it along with the error diagnostics printed below. + |%s.""".stripMargin.format(initError) + ) + false + } else true } // private def warningsThunks = List( // () => intp.bind("lastWarnings", "" + typeTag[List[(Position, String)]], intp.lastWarnings _), @@ -80,13 +89,22 @@ trait ILoopInit { // ) // called once after init condition is signalled protected def postInitialization() { - postInitThunks foreach (f => addThunk(f())) - runThunks() - initIsComplete = true + try { + postInitThunks foreach (f => addThunk(f())) + runThunks() + } catch { + case ex => + val message = new java.io.StringWriter() + ex.printStackTrace(new java.io.PrintWriter(message)) + initError = message.toString + throw ex + } finally { + initIsComplete = true - if (isAsync) { - asyncMessage("[info] total init time: " + elapsed() + " s.") - withLock(initLoopCondition.signal()) + if (isAsync) { + asyncMessage("[info] total init time: " + elapsed() + " s.") + withLock(initLoopCondition.signal()) + } } } // code to be executed only after the interpreter is initialized diff --git a/src/compiler/scala/tools/nsc/interpreter/IMain.scala b/src/compiler/scala/tools/nsc/interpreter/IMain.scala index 956e282b26..2a7adbe781 100644 --- a/src/compiler/scala/tools/nsc/interpreter/IMain.scala +++ b/src/compiler/scala/tools/nsc/interpreter/IMain.scala @@ -7,7 +7,8 @@ package scala.tools.nsc package interpreter import Predef.{ println => _, _ } -import util.{ Set => _, _ } +import util.stringFromWriter +import scala.reflect.internal.util._ import java.net.URL import scala.sys.BooleanProp import io.VirtualDirectory @@ -25,6 +26,9 @@ import IMain._ import java.util.concurrent.Future import typechecker.Analyzer import language.implicitConversions +import scala.reflect.runtime.{ universe => ru } +import scala.reflect.{ ClassTag, classTag } +import scala.tools.reflect.StdTags._ /** directory to save .class files to */ private class ReplVirtualDirectory(out: JPrintWriter) extends VirtualDirectory("(memory)", None) { @@ -149,6 +153,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends private def _initSources = List(new BatchSourceFile("<init>", "class $repl_$init { }")) private def _initialize() = { try { + // [Eugene] todo. if this crashes, REPL will hang new _compiler.Run() compileSources _initSources _initializeComplete = true true @@ -194,17 +199,8 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends lazy val compiler: global.type = global import global._ - import definitions.{ - ScalaPackage, JavaLangPackage, RootClass, - getClassIfDefined, getModuleIfDefined, getRequiredModule, getRequiredClass, - termMember, typeMember - } - - private implicit def privateTreeOps(t: Tree): List[Tree] = { - (new Traversable[Tree] { - def foreach[U](f: Tree => U): Unit = t foreach { x => f(x) ; () } - }).toList - } + import definitions.{ScalaPackage, JavaLangPackage, termMember, typeMember} + import rootMirror.{RootClass, getClassIfDefined, getModuleIfDefined, getRequiredModule, getRequiredClass} implicit class ReplTypeOps(tp: Type) { def orElse(other: => Type): Type = if (tp ne NoType) tp else other @@ -331,14 +327,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends def getInterpreterClassLoader() = classLoader // Set the current Java "context" class loader to this interpreter's class loader - def setContextClassLoader() = { - classLoader.setAsContext() - - // this is risky, but it's our only possibility to make default reflexive mirror to work with REPL - // so far we have only used the default mirror to create a few tags for the compiler - // so it shouldn't be in conflict with our classloader, especially since it respects its parent - scala.reflect.mirror.classLoader = classLoader - } + def setContextClassLoader() = classLoader.setAsContext() /** Given a simple repl-defined name, returns the real name of * the class representing it, e.g. for "Bippy" it may return @@ -499,11 +488,17 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends case Some(trees) => trees } repltrace( - trees map (t => - t map (t0 => + trees map (t => { + // [Eugene to Paul] previously it just said `t map ...` + // because there was an implicit conversion from Tree to a list of Trees + // however Martin and I have removed the conversion + // (it was conflicting with the new reflection API), + // so I had to rewrite this a bit + val subs = t collect { case sub => sub } + subs map (t0 => " " + safePos(t0, -1) + ": " + t0.shortClass + "\n" ) mkString "" - ) mkString "\n" + }) mkString "\n" ) // If the last tree is a bare expression, pinpoint where it begins using the // AST node position and snap the line off there. Rewrite the code embodied @@ -651,8 +646,8 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends directlyBoundNames += newTermName(name) result } - def directBind(p: NamedParam): IR.Result = directBind(p.name, p.tpe, p.value) - def directBind[T: ClassTag](name: String, value: T): IR.Result = directBind((name, value)) + def directBind(p: NamedParam): IR.Result = directBind(p.name, p.tpe, p.value) + def directBind[T: ru.TypeTag : ClassTag](name: String, value: T): IR.Result = directBind((name, value)) def rebind(p: NamedParam): IR.Result = { val name = p.name @@ -668,12 +663,12 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends if (ids.isEmpty) IR.Success else interpret("import " + ids.mkString(", ")) - def quietBind(p: NamedParam): IR.Result = beQuietDuring(bind(p)) - def bind(p: NamedParam): IR.Result = bind(p.name, p.tpe, p.value) - def bind[T: TypeTag](name: String, value: T): IR.Result = bind((name, value)) - def bindSyntheticValue(x: Any): IR.Result = bindValue(freshInternalVarName(), x) - def bindValue(x: Any): IR.Result = bindValue(freshUserVarName(), x) - def bindValue(name: String, x: Any): IR.Result = bind(name, TypeStrings.fromValue(x), x) + def quietBind(p: NamedParam): IR.Result = beQuietDuring(bind(p)) + def bind(p: NamedParam): IR.Result = bind(p.name, p.tpe, p.value) + def bind[T: ru.TypeTag : ClassTag](name: String, value: T): IR.Result = bind((name, value)) + def bindSyntheticValue(x: Any): IR.Result = bindValue(freshInternalVarName(), x) + def bindValue(x: Any): IR.Result = bindValue(freshUserVarName(), x) + def bindValue(name: String, x: Any): IR.Result = bind(name, TypeStrings.fromValue(x), x) /** Reset this interpreter, forgetting all user-specified requests. */ def reset() { @@ -716,7 +711,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends val unwrapped = unwrap(t) withLastExceptionLock[String]({ - directBind[Throwable]("lastException", unwrapped) + directBind[Throwable]("lastException", unwrapped)(tagOfThrowable, classTag[Throwable]) util.stackTraceString(unwrapped) }, util.stackTraceString(unwrapped)) } @@ -1050,7 +1045,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends valueOfTerm(id) map (_.getClass) def typeOfTerm(id: String): Type = newTermName(id) match { - case nme.ROOTPKG => definitions.RootClass.tpe + case nme.ROOTPKG => RootClass.tpe case name => requestForName(name).fold(NoType: Type)(_ compilerTypeOf name) } @@ -1127,9 +1122,9 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends findName(termname) orElse getModuleIfDefined(termname) } // [Eugene to Paul] possibly you could make use of TypeTags here - def types[T: ClassTag] : Symbol = types(classTag[T].erasure.getName) - def terms[T: ClassTag] : Symbol = terms(classTag[T].erasure.getName) - def apply[T: ClassTag] : Symbol = apply(classTag[T].erasure.getName) + def types[T: ClassTag] : Symbol = types(classTag[T].runtimeClass.getName) + def terms[T: ClassTag] : Symbol = terms(classTag[T].runtimeClass.getName) + def apply[T: ClassTag] : Symbol = apply(classTag[T].runtimeClass.getName) def classSymbols = allDefSymbols collect { case x: ClassSymbol => x } def methodSymbols = allDefSymbols collect { case x: MethodSymbol => x } @@ -1227,7 +1222,7 @@ object IMain { def maxStringLength: Int def isTruncating: Boolean def truncate(str: String): String = { - if (isTruncating && str.length > maxStringLength) + if (isTruncating && (maxStringLength != 0 && str.length > maxStringLength)) (str take maxStringLength - 3) + "..." else str } diff --git a/src/compiler/scala/tools/nsc/interpreter/ISettings.scala b/src/compiler/scala/tools/nsc/interpreter/ISettings.scala index 59c933632b..d68a2becfb 100644 --- a/src/compiler/scala/tools/nsc/interpreter/ISettings.scala +++ b/src/compiler/scala/tools/nsc/interpreter/ISettings.scala @@ -24,7 +24,7 @@ class ISettings(intp: IMain) { * more than this number of characters, then the printout is * truncated. */ - var maxPrintString = 800 + var maxPrintString = replProps.maxPrintString.option.getOrElse(800) /** The maximum number of completion candidates to print for tab * completion without requiring confirmation. diff --git a/src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala b/src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala index b1e6a9d7d9..c429e3b196 100644 --- a/src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala +++ b/src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala @@ -16,7 +16,8 @@ import collection.mutable.ListBuffer class JLineCompletion(val intp: IMain) extends Completion with CompletionOutput { val global: intp.global.type = intp.global import global._ - import definitions.{ PredefModule, RootClass, AnyClass, AnyRefClass, ScalaPackage, JavaLangPackage, getModuleIfDefined } + import definitions.{ PredefModule, AnyClass, AnyRefClass, ScalaPackage, JavaLangPackage } + import rootMirror.{ RootClass, getModuleIfDefined } type ExecResult = Any import intp.{ debugging } diff --git a/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala b/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala index a29eb3ac6d..236f3f23c5 100644 --- a/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala +++ b/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala @@ -115,7 +115,11 @@ trait MemberHandlers { if (mods.isLazy) codegenln(false, "<lazy>") else any2stringOf(req fullPath name, maxStringElements) - """ + "%s: %s = " + %s""".format(prettyName, string2code(req typeOf name), resultString) + val vidString = + if (replProps.vids) """" + " @ " + "%%8x".format(System.identityHashCode(%s)) + " """.trim.format(req fullPath name) + else "" + + """ + "%s%s: %s = " + %s""".format(prettyName, vidString, string2code(req typeOf name), resultString) } } } diff --git a/src/compiler/scala/tools/nsc/interpreter/NamedParam.scala b/src/compiler/scala/tools/nsc/interpreter/NamedParam.scala index a3cbfffc3b..3a69ea86b5 100644 --- a/src/compiler/scala/tools/nsc/interpreter/NamedParam.scala +++ b/src/compiler/scala/tools/nsc/interpreter/NamedParam.scala @@ -8,23 +8,25 @@ package interpreter import NamedParam._ import language.implicitConversions +import scala.reflect.runtime.{universe => ru} +import scala.reflect.{ClassTag, classTag} trait NamedParamCreator { protected def freshName: () => String def apply(name: String, tpe: String, value: Any): NamedParam = NamedParamClass(name, tpe, value) - def apply[T: TypeTag](name: String, x: T): NamedParam = new Typed[T](name, x) - def apply[T: TypeTag](x: T): NamedParam = apply(freshName(), x) + def apply[T: ru.TypeTag : ClassTag](name: String, x: T): NamedParam = new Typed[T](name, x) + def apply[T: ru.TypeTag : ClassTag](x: T): NamedParam = apply(freshName(), x) def clazz(name: String, x: Any): NamedParam = new Untyped(name, x) def clazz(x: Any): NamedParam = clazz(freshName(), x) - implicit def namedValue[T: TypeTag](name: String, x: T): NamedParam = apply(name, x) - implicit def tuple[T: TypeTag](pair: (String, T)): NamedParam = apply(pair._1, pair._2) + implicit def namedValue[T: ru.TypeTag : ClassTag](name: String, x: T): NamedParam = apply(name, x) + implicit def tuple[T: ru.TypeTag : ClassTag](pair: (String, T)): NamedParam = apply(pair._1, pair._2) } object NamedParam extends NamedParamCreator { - class Typed[T: TypeTag](val name: String, val value: T) extends NamedParam { + class Typed[T: ru.TypeTag : ClassTag](val name: String, val value: T) extends NamedParam { val tpe = TypeStrings.fromTag[T] } class Untyped(val name: String, val value: Any) extends NamedParam { diff --git a/src/compiler/scala/tools/nsc/interpreter/Power.scala b/src/compiler/scala/tools/nsc/interpreter/Power.scala index 9c4c05f1ee..57d7cef726 100644 --- a/src/compiler/scala/tools/nsc/interpreter/Power.scala +++ b/src/compiler/scala/tools/nsc/interpreter/Power.scala @@ -8,12 +8,14 @@ package interpreter import scala.collection.{ mutable, immutable } import scala.util.matching.Regex -import scala.tools.nsc.util.{ BatchSourceFile } +import scala.reflect.internal.util.{ BatchSourceFile } import session.{ History } import scala.io.Codec import java.net.{ URL, MalformedURLException } import io.{ Path } import language.implicitConversions +import scala.reflect.runtime.{universe => ru} +import scala.reflect.{ClassTag, classTag} /** Collecting some power mode examples. @@ -42,10 +44,11 @@ Lost after 18/flatten { /** A class for methods to be injected into the intp in power mode. */ -class Power[ReplValsImpl <: ReplVals : TypeTag](val intp: IMain, replVals: ReplValsImpl) { +class Power[ReplValsImpl <: ReplVals : ru.TypeTag: ClassTag](val intp: IMain, replVals: ReplValsImpl) { import intp.{ beQuietDuring, typeOfExpression, interpret, parse } import intp.global._ - import definitions.{ compilerTypeFromTag, compilerSymbolFromTag, getClassIfDefined, getModuleIfDefined } + import definitions.{ compilerTypeFromTag, compilerSymbolFromTag} + import rootMirror.{ getClassIfDefined, getModuleIfDefined } abstract class SymSlurper { def isKeep(sym: Symbol): Boolean @@ -162,7 +165,7 @@ class Power[ReplValsImpl <: ReplVals : TypeTag](val intp: IMain, replVals: ReplV } trait LowPriorityInternalInfo { - implicit def apply[T: TypeTag] : InternalInfo[T] = new InternalInfo[T](None) + implicit def apply[T: ru.TypeTag : ClassTag] : InternalInfo[T] = new InternalInfo[T](None) } object InternalInfo extends LowPriorityInternalInfo { } @@ -173,12 +176,12 @@ class Power[ReplValsImpl <: ReplVals : TypeTag](val intp: IMain, replVals: ReplV * of the conveniences exist on that wrapper. */ trait LowPriorityInternalInfoWrapper { - implicit def apply[T: TypeTag] : InternalInfoWrapper[T] = new InternalInfoWrapper[T](None) + implicit def apply[T: ru.TypeTag : ClassTag] : InternalInfoWrapper[T] = new InternalInfoWrapper[T](None) } object InternalInfoWrapper extends LowPriorityInternalInfoWrapper { } - class InternalInfoWrapper[T: TypeTag](value: Option[T] = None) { + class InternalInfoWrapper[T: ru.TypeTag : ClassTag](value: Option[T] = None) { def ? : InternalInfo[T] = new InternalInfo[T](value) } @@ -186,8 +189,8 @@ class Power[ReplValsImpl <: ReplVals : TypeTag](val intp: IMain, replVals: ReplV * translate tag type arguments into applied types * customizable symbol filter (had to hardcode no-spec to reduce noise) */ - class InternalInfo[T: TypeTag](value: Option[T] = None) { - private def newInfo[U: TypeTag](value: U): InternalInfo[U] = new InternalInfo[U](Some(value)) + class InternalInfo[T](value: Option[T] = None)(implicit typeEvidence: ru.TypeTag[T], runtimeClassEvidence: ClassTag[T]) { + private def newInfo[U: ru.TypeTag : ClassTag](value: U): InternalInfo[U] = new InternalInfo[U](Some(value)) private def isSpecialized(s: Symbol) = s.name.toString contains "$mc" private def isImplClass(s: Symbol) = s.name.toString endsWith "$class" @@ -226,9 +229,9 @@ class Power[ReplValsImpl <: ReplVals : TypeTag](val intp: IMain, replVals: ReplV def pkgClasses = pkgMembers filter (s => s.isClass && s.isDefinedInPackage) def pkgSymbols = new PackageSlurper(pkgClass).slurp() filterNot excludeMember - def tag = typeTag[T] - def erasure = tag.erasure - def shortClass = erasure.getName split "[$.]" last + def tag = typeEvidence + def runtimeClass = runtimeClassEvidence.runtimeClass + def shortClass = runtimeClass.getName split "[$.]" last def baseClasses = tpe.baseClasses def baseClassDecls = mapFrom(baseClasses)(_.info.decls.toList.sortBy(_.name)) @@ -236,13 +239,13 @@ class Power[ReplValsImpl <: ReplVals : TypeTag](val intp: IMain, replVals: ReplV def ancestorDeclares(name: String) = ancestors filter (_.info member newTermName(name) ne NoSymbol) def baseTypes = tpe.baseTypeSeq.toList - def <:<[U: TypeTag](other: U) = tpe <:< newInfo(other).tpe - def lub[U: TypeTag](other: U) = intp.global.lub(List(tpe, newInfo(other).tpe)) - def glb[U: TypeTag](other: U) = intp.global.glb(List(tpe, newInfo(other).tpe)) + def <:<[U: ru.TypeTag : ClassTag](other: U) = tpe <:< newInfo(other).tpe + def lub[U: ru.TypeTag : ClassTag](other: U) = intp.global.lub(List(tpe, newInfo(other).tpe)) + def glb[U: ru.TypeTag : ClassTag](other: U) = intp.global.glb(List(tpe, newInfo(other).tpe)) override def toString = value match { case Some(x) => "%s (%s)".format(x, shortClass) - case _ => erasure.getName + case _ => runtimeClass.getName } } @@ -362,7 +365,7 @@ class Power[ReplValsImpl <: ReplVals : TypeTag](val intp: IMain, replVals: ReplV implicit lazy val powerSymbolOrdering: Ordering[Symbol] = Ordering[Name] on (_.name) implicit lazy val powerTypeOrdering: Ordering[Type] = Ordering[Symbol] on (_.typeSymbol) - implicit def replInternalInfo[T: TypeTag](x: T): InternalInfoWrapper[T] = new InternalInfoWrapper[T](Some(x)) + implicit def replInternalInfo[T: ru.TypeTag : ClassTag](x: T): InternalInfoWrapper[T] = new InternalInfoWrapper[T](Some(x)) implicit def replEnhancedStrings(s: String): RichReplString = new RichReplString(s) implicit def replMultiPrinting[T: Prettifier](xs: TraversableOnce[T]): MultiPrettifierClass[T] = new MultiPrettifierClass[T](xs.toSeq) @@ -378,12 +381,12 @@ class Power[ReplValsImpl <: ReplVals : TypeTag](val intp: IMain, replVals: ReplV trait ReplUtilities { // [Eugene to Paul] needs review! - // def module[T: TypeTag] = getModuleIfDefined(typeTag[T].erasure.getName stripSuffix nme.MODULE_SUFFIX_STRING) - // def clazz[T: TypeTag] = getClassIfDefined(typeTag[T].erasure.getName) - def module[T: TypeTag] = typeTag[T].sym.suchThat(_.isPackage) - def clazz[T: TypeTag] = typeTag[T].sym.suchThat(_.isClass) - def info[T: TypeTag] = InternalInfo[T] - def ?[T: TypeTag] = InternalInfo[T] + // def module[T: Manifest] = getModuleIfDefined(manifest[T].erasure.getName stripSuffix nme.MODULE_SUFFIX_STRING) + // def clazz[T: Manifest] = getClassIfDefined(manifest[T].erasure.getName) + def module[T: ru.TypeTag] = ru.typeOf[T].typeSymbol.suchThat(_.isPackage) + def clazz[T: ru.TypeTag] = ru.typeOf[T].typeSymbol.suchThat(_.isClass) + def info[T: ru.TypeTag : ClassTag] = InternalInfo[T] + def ?[T: ru.TypeTag : ClassTag] = InternalInfo[T] def url(s: String) = { try new URL(s) catch { case _: MalformedURLException => diff --git a/src/compiler/scala/tools/nsc/interpreter/ReplProps.scala b/src/compiler/scala/tools/nsc/interpreter/ReplProps.scala index 5eb1e0ae18..218e02193a 100644 --- a/src/compiler/scala/tools/nsc/interpreter/ReplProps.scala +++ b/src/compiler/scala/tools/nsc/interpreter/ReplProps.scala @@ -7,9 +7,11 @@ package scala.tools.nsc package interpreter import scala.sys._ +import Prop._ class ReplProps { private def bool(name: String) = BooleanProp.keyExists(name) + private def int(name: String) = IntProp(name) val jlineDebug = bool("scala.tools.jline.internal.Log.debug") val jlineTrace = bool("scala.tools.jline.internal.Log.trace") @@ -19,7 +21,11 @@ class ReplProps { val trace = bool("scala.repl.trace") val power = bool("scala.repl.power") - val replInitCode = Prop[JFile]("scala.repl.initcode") - val powerInitCode = Prop[JFile]("scala.repl.power.initcode") - val powerBanner = Prop[JFile]("scala.repl.power.banner") + val replInitCode = Prop[JFile]("scala.repl.initcode") + val replAutorunCode = Prop[JFile]("scala.repl.autoruncode") + val powerInitCode = Prop[JFile]("scala.repl.power.initcode") + val powerBanner = Prop[JFile]("scala.repl.power.banner") + + val vids = bool("scala.repl.vids") + val maxPrintString = int("scala.repl.maxprintstring") } diff --git a/src/compiler/scala/tools/nsc/interpreter/ReplVals.scala b/src/compiler/scala/tools/nsc/interpreter/ReplVals.scala index 280247f20c..588d0647d2 100644 --- a/src/compiler/scala/tools/nsc/interpreter/ReplVals.scala +++ b/src/compiler/scala/tools/nsc/interpreter/ReplVals.scala @@ -6,8 +6,9 @@ package scala.tools.nsc package interpreter -import scala.reflect.{mirror => rm} import language.implicitConversions +import scala.reflect.base.{Universe => BaseUniverse} +import scala.reflect.runtime.{universe => ru} /** A class which the repl utilizes to expose predefined objects. * The base implementation is empty; the standard repl implementation @@ -64,15 +65,15 @@ object ReplVals { * I have this forwarder which widens the type and then cast the result back * to the dependent type. */ - def compilerTypeFromTag(t: rm.TypeTag[_]): Global#Type = + def compilerTypeFromTag(t: BaseUniverse # AbsTypeTag[_]): Global#Type = definitions.compilerTypeFromTag(t) class AppliedTypeFromTags(sym: Symbol) { - def apply[M](implicit m1: rm.TypeTag[M]): Type = + def apply[M](implicit m1: ru.TypeTag[M]): Type = if (sym eq NoSymbol) NoType else appliedType(sym, compilerTypeFromTag(m1).asInstanceOf[Type]) - def apply[M1, M2](implicit m1: rm.TypeTag[M1], m2: rm.TypeTag[M2]): Type = + def apply[M1, M2](implicit m1: ru.TypeTag[M1], m2: ru.TypeTag[M2]): Type = if (sym eq NoSymbol) NoType else appliedType(sym, compilerTypeFromTag(m1).asInstanceOf[Type], compilerTypeFromTag(m2).asInstanceOf[Type]) } diff --git a/src/compiler/scala/tools/nsc/interpreter/RichClass.scala b/src/compiler/scala/tools/nsc/interpreter/RichClass.scala index 2e735e3b9b..32eb1e95c1 100644 --- a/src/compiler/scala/tools/nsc/interpreter/RichClass.scala +++ b/src/compiler/scala/tools/nsc/interpreter/RichClass.scala @@ -6,6 +6,8 @@ package scala.tools.nsc package interpreter +import scala.reflect.{ ClassTag, classTag } + class RichClass[T](val clazz: Class[T]) { def toTag: ClassTag[T] = ClassTag[T](clazz) def toTypeString: String = TypeStrings.fromClazz(clazz) diff --git a/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala b/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala index 5d5123811e..56b9c7011c 100644 --- a/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala +++ b/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala @@ -10,9 +10,11 @@ import java.lang.{ reflect => r } import r.TypeVariable import scala.reflect.NameTransformer import NameTransformer._ -import scala.reflect.{mirror => rm} +import scala.reflect.runtime.{universe => ru} +import scala.reflect.{ClassTag, classTag} import typechecker.DestructureTypes -import scala.tools.util.StringOps.ojoin +import scala.reflect.internal.util.StringOps.ojoin +import language.implicitConversions /** A more principled system for turning types into strings. */ @@ -192,7 +194,7 @@ trait TypeStrings { else enclClass.getName + "." + (name stripPrefix enclPre) ) } - def scalaName(m: ClassTag[_]): String = scalaName(m.erasure) + def scalaName(ct: ClassTag[_]): String = scalaName(ct.runtimeClass) def anyClass(x: Any): JClass = if (x == null) null else x.getClass private def brackets(tps: String*): String = @@ -209,10 +211,12 @@ trait TypeStrings { brackets(clazz.getTypeParameters map tvarString: _*) } - private def tparamString[T: TypeTag] : String = { - // [Eugene to Paul] needs review!! - def typeArguments: List[rm.Type] = typeTag[T].tpe.typeArguments - def typeVariables: List[java.lang.Class[_]] = typeArguments map (targ => rm.typeToClass(targ)) + private def tparamString[T: ru.TypeTag] : String = { + // [Eugene++ to Paul] needs review!! + def typeArguments: List[ru.Type] = ru.typeOf[T].typeArguments + // [Eugene++] todo. need to use not the `rootMirror`, but a mirror with the REPL's classloader + // how do I get to it? acquiring context classloader seems unreliable because of multithreading + def typeVariables: List[java.lang.Class[_]] = typeArguments map (targ => ru.rootMirror.runtimeClass(targ)) brackets(typeArguments map (jc => tvarString(List(jc))): _*) } @@ -224,10 +228,10 @@ trait TypeStrings { * practice to rely on toString for correctness) generated the VALID string * representation of the type. */ - def fromTypedValue[T: TypeTag](x: T): String = fromTag[T] - def fromValue(value: Any): String = if (value == null) "Null" else fromClazz(anyClass(value)) - def fromClazz(clazz: JClass): String = scalaName(clazz) + tparamString(clazz) - def fromTag[T: TypeTag] : String = scalaName(typeTag[T].erasure) + tparamString[T] + def fromTypedValue[T: ru.TypeTag : ClassTag](x: T): String = fromTag[T] + def fromValue(value: Any): String = if (value == null) "Null" else fromClazz(anyClass(value)) + def fromClazz(clazz: JClass): String = scalaName(clazz) + tparamString(clazz) + def fromTag[T: ru.TypeTag : ClassTag] : String = scalaName(classTag[T].runtimeClass) + tparamString[T] /** Reducing fully qualified noise for some common packages. */ diff --git a/src/compiler/scala/tools/nsc/io/Pickler.scala b/src/compiler/scala/tools/nsc/io/Pickler.scala index 416b84eec6..48361cd157 100644 --- a/src/compiler/scala/tools/nsc/io/Pickler.scala +++ b/src/compiler/scala/tools/nsc/io/Pickler.scala @@ -4,6 +4,7 @@ import annotation.unchecked import Lexer._ import java.io.Writer import language.implicitConversions +import reflect.ClassTag /** An abstract class for writing and reading Scala objects to and * from a legible representation. The presesentation follows the following grammar: diff --git a/src/compiler/scala/tools/nsc/io/SourceReader.scala b/src/compiler/scala/tools/nsc/io/SourceReader.scala index 324c5e4111..2e146becdf 100644 --- a/src/compiler/scala/tools/nsc/io/SourceReader.scala +++ b/src/compiler/scala/tools/nsc/io/SourceReader.scala @@ -28,7 +28,7 @@ class SourceReader(decoder: CharsetDecoder, reporter: Reporter) { private var chars: CharBuffer = CharBuffer.allocate(0x4000) private def reportEncodingError(filename:String) = { - reporter.error(util.NoPosition, + reporter.error(scala.reflect.internal.util.NoPosition, "IO error while decoding "+filename+" with "+decoder.charset()+"\n"+ "Please try specifying another one using the -encoding option") } diff --git a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala index f71e067366..e2203e07b3 100644 --- a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala +++ b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala @@ -8,7 +8,7 @@ package scala.tools.nsc package javac -import scala.tools.nsc.util.OffsetPosition +import scala.reflect.internal.util.OffsetPosition import scala.collection.mutable.ListBuffer import symtab.Flags import JavaTokens._ diff --git a/src/compiler/scala/tools/nsc/javac/JavaScanners.scala b/src/compiler/scala/tools/nsc/javac/JavaScanners.scala index d47756e757..73b5a752b4 100644 --- a/src/compiler/scala/tools/nsc/javac/JavaScanners.scala +++ b/src/compiler/scala/tools/nsc/javac/JavaScanners.scala @@ -6,7 +6,8 @@ package scala.tools.nsc package javac -import scala.tools.nsc.util._ +import scala.tools.nsc.util.JavaCharArrayReader +import scala.reflect.internal.util._ import scala.reflect.internal.Chars._ import JavaTokens._ import scala.annotation.switch diff --git a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala index 7346d9c59f..0d1356a6b0 100644 --- a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala +++ b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala @@ -9,7 +9,7 @@ package matching import PartialFunction._ import scala.collection.{ mutable } -import util.Position +import scala.reflect.internal.util.Position import transform.ExplicitOuter import symtab.Flags import mutable.ListBuffer diff --git a/src/compiler/scala/tools/nsc/plugins/Plugin.scala b/src/compiler/scala/tools/nsc/plugins/Plugin.scala index 48c4a9b5b3..7f9df2235a 100644 --- a/src/compiler/scala/tools/nsc/plugins/Plugin.scala +++ b/src/compiler/scala/tools/nsc/plugins/Plugin.scala @@ -6,7 +6,7 @@ package scala.tools.nsc package plugins -import io.{ File, Path } +import io.{ File, Path, Jar } import java.net.URLClassLoader import java.util.jar.JarFile import java.util.zip.ZipException @@ -132,7 +132,8 @@ object Plugin { val alljars = (jars ::: (for { dir <- dirs if dir.isDirectory entry <- dir.toDirectory.files.toList sortBy (_.name) - if Path.isJarOrZip(entry) +// was: if Path.isJarOrZip(entry) + if Jar.isJarOrZip(entry) pdesc <- loadDescription(entry) if !(ignoring contains pdesc.name) } yield entry)).distinct diff --git a/src/compiler/scala/tools/nsc/reporters/AbstractReporter.scala b/src/compiler/scala/tools/nsc/reporters/AbstractReporter.scala index ab8fe23909..cb85e49d55 100644 --- a/src/compiler/scala/tools/nsc/reporters/AbstractReporter.scala +++ b/src/compiler/scala/tools/nsc/reporters/AbstractReporter.scala @@ -8,7 +8,7 @@ package reporters import scala.collection.mutable import scala.tools.nsc.Settings -import scala.tools.nsc.util.Position +import scala.reflect.internal.util.Position /** * This reporter implements filtering. diff --git a/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala b/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala index 956c43c35a..dff900383e 100644 --- a/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala +++ b/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala @@ -7,8 +7,7 @@ package scala.tools.nsc package reporters import java.io.{ BufferedReader, IOException, PrintWriter } -import util._ -import scala.tools.util.StringOps +import scala.reflect.internal.util._ /** * This class implements a Reporter that displays messages on a text diff --git a/src/compiler/scala/tools/nsc/reporters/Reporter.scala b/src/compiler/scala/tools/nsc/reporters/Reporter.scala index 309fc5733f..303a477491 100644 --- a/src/compiler/scala/tools/nsc/reporters/Reporter.scala +++ b/src/compiler/scala/tools/nsc/reporters/Reporter.scala @@ -6,9 +6,8 @@ package scala.tools.nsc package reporters -import scala.tools.nsc.util._ -import scala.tools.util.StringOps -import StringOps._ +import scala.reflect.internal.util._ +import scala.reflect.internal.util.StringOps._ /** * This interface provides methods to issue information, warning and @@ -78,8 +77,8 @@ abstract class Reporter { } // sbt compat - @deprecated("Moved to scala.tools.util.StringOps", "2.10.0") + @deprecated("Moved to scala.reflect.internal.util.StringOps", "2.10.0") def countElementsAsString(n: Int, elements: String): String = StringOps.countElementsAsString(n, elements) - @deprecated("Moved to scala.tools.util.StringOps", "2.10.0") + @deprecated("Moved to scala.reflect.internal.util.StringOps", "2.10.0") def countAsString(n: Int): String = StringOps.countAsString(n) } diff --git a/src/compiler/scala/tools/nsc/reporters/StoreReporter.scala b/src/compiler/scala/tools/nsc/reporters/StoreReporter.scala index 12edd9bf31..5c3f7b8965 100644 --- a/src/compiler/scala/tools/nsc/reporters/StoreReporter.scala +++ b/src/compiler/scala/tools/nsc/reporters/StoreReporter.scala @@ -7,7 +7,7 @@ package scala.tools.nsc package reporters import scala.collection.mutable -import scala.tools.nsc.util.Position +import scala.reflect.internal.util.Position /** * This class implements a Reporter that displays messages on a text diff --git a/src/compiler/scala/tools/nsc/scratchpad/Executor.scala b/src/compiler/scala/tools/nsc/scratchpad/Executor.scala index 8a918a829c..89523df71e 100644 --- a/src/compiler/scala/tools/nsc/scratchpad/Executor.scala +++ b/src/compiler/scala/tools/nsc/scratchpad/Executor.scala @@ -4,7 +4,7 @@ import java.io.{PrintStream, OutputStreamWriter, Writer} import scala.runtime.ScalaRunTime.stringOf import java.lang.reflect.InvocationTargetException -import scala.reflect.ReflectionUtils._ +import scala.reflect.runtime.ReflectionUtils._ object Executor { diff --git a/src/compiler/scala/tools/nsc/scratchpad/SourceInserter.scala b/src/compiler/scala/tools/nsc/scratchpad/SourceInserter.scala index 311aa6e324..42a35dc642 100644 --- a/src/compiler/scala/tools/nsc/scratchpad/SourceInserter.scala +++ b/src/compiler/scala/tools/nsc/scratchpad/SourceInserter.scala @@ -2,7 +2,7 @@ package scala.tools.nsc package scratchpad import java.io.Writer -import util.SourceFile +import scala.reflect.internal.util.SourceFile import reflect.internal.Chars._ diff --git a/src/compiler/scala/tools/nsc/settings/MutableSettings.scala b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala index c4dd9a2a36..fc833e2c26 100644 --- a/src/compiler/scala/tools/nsc/settings/MutableSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala @@ -8,10 +8,11 @@ package scala.tools package nsc package settings -import io.{ AbstractFile, Path, PlainFile, VirtualDirectory } -import scala.tools.util.StringOps +import io.{ AbstractFile, Jar, Path, PlainFile, VirtualDirectory } +import scala.reflect.internal.util.StringOps import scala.collection.mutable.ListBuffer import scala.io.Source +import scala.reflect.{ ClassTag, classTag } /** A mutable Settings object. */ @@ -184,7 +185,7 @@ class MutableSettings(val errorFn: String => Unit) * and `boot.class.path`. These resources should contain the application * and boot classpaths in the same form as would be passed on the command line.*/ def embeddedDefaults[T: ClassTag]: Unit = - embeddedDefaults(classTag[T].erasure.getClassLoader) + embeddedDefaults(classTag[T].runtimeClass.getClassLoader) /** Initializes these settings for embedded use by a class from the given class loader. * The class loader for `T` should provide resources `app.class.path` @@ -254,7 +255,8 @@ class MutableSettings(val errorFn: String => Unit) private def checkDir(dir: AbstractFile, name: String, allowJar: Boolean = false): AbstractFile = ( if (dir != null && dir.isDirectory) dir - else if (allowJar && dir == null && Path.isJarOrZip(name, false)) +// was: else if (allowJar && dir == null && Path.isJarOrZip(name, false)) + else if (allowJar && dir == null && Jar.isJarOrZip(name, false)) new PlainFile(Path(name)) else throw new FatalError(name + " does not exist or is not a directory") diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index 88a89d54eb..04acba06e8 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -82,7 +82,6 @@ trait ScalaSettings extends AbsScalaSettings val XlogImplicits = BooleanSetting ("-Xlog-implicits", "Show more detail on why some implicits are not applicable.") val logImplicitConv = BooleanSetting ("-Xlog-implicit-conversions", "Print a message whenever an implicit conversion is inserted.") val logReflectiveCalls = BooleanSetting("-Xlog-reflective-calls", "Print a message when a reflective method call is generated") - val logRuntimeSplices = BooleanSetting("-Xlog-runtime-splices", "Print a message when Expr.eval or Expr.value cannot be resolved statically.") val logFreeTerms = BooleanSetting ("-Xlog-free-terms", "Print a message when reification creates a free term.") val logFreeTypes = BooleanSetting ("-Xlog-free-types", "Print a message when reification resorts to generating a free type.") val maxClassfileName = IntSetting ("-Xmax-classfile-name", "Maximum filename length for generated classes", 255, Some((72, 255)), _ => None) @@ -110,6 +109,7 @@ trait ScalaSettings extends AbsScalaSettings val XoldPatmat = BooleanSetting ("-Xoldpatmat", "Use the pre-2.10 pattern matcher. Otherwise, the 'virtualizing' pattern matcher is used in 2.10.") val XnoPatmatAnalysis = BooleanSetting ("-Xno-patmat-analysis", "Don't perform exhaustivity/unreachability analysis. Also, ignore @switch annotation.") + val XfullLubs = BooleanSetting ("-Xfull-lubs", "Retains pre 2.10 behavior of less aggressive truncation of least upper bounds.") /** Compatibility stubs for options whose value name did * not previously match the option name. @@ -203,7 +203,6 @@ trait ScalaSettings extends AbsScalaSettings val Xexperimental = BooleanSetting("-Xexperimental", "Enable experimental extensions.") enabling experimentalSettings // Feature extensions - val Xmacros = BooleanSetting("-Xmacros", "Enable macros.") // [Martin] Can be retired now. val XmacroSettings = MultiStringSetting("-Xmacro-settings", "option", "Custom settings for macros.") val XmacroPrimaryClasspath = PathSetting("-Xmacro-primary-classpath", "Classpath to load macros implementations from, defaults to compilation classpath (aka \"library classpath\".", "") val XmacroFallbackClasspath = PathSetting("-Xmacro-fallback-classpath", "Classpath to load macros implementations from if they cannot be loaded from library classpath.", "") diff --git a/src/compiler/scala/tools/nsc/symtab/BrowsingLoaders.scala b/src/compiler/scala/tools/nsc/symtab/BrowsingLoaders.scala index 5f7deb87bd..25d835790e 100644 --- a/src/compiler/scala/tools/nsc/symtab/BrowsingLoaders.scala +++ b/src/compiler/scala/tools/nsc/symtab/BrowsingLoaders.scala @@ -6,7 +6,7 @@ package scala.tools.nsc package symtab -import scala.tools.nsc.util.BatchSourceFile +import scala.reflect.internal.util.BatchSourceFile import scala.tools.nsc.io.AbstractFile /** A subclass of SymbolLoaders that implements browsing behavior. diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index 7373a610d7..d8bf23f4fe 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -183,7 +183,7 @@ abstract class ClassfileParser { if (in.buf(start).toInt != CONSTANT_CLASS) errorBadTag(start) val name = getExternalName(in.getChar(start + 1)) if (nme.isModuleName(name)) - c = definitions.getModule(nme.stripModuleSuffix(name)) + c = rootMirror.getModule(nme.stripModuleSuffix(name)) else c = classNameToSymbol(name) @@ -234,7 +234,7 @@ abstract class ClassfileParser { //assert(name.endsWith("$"), "Not a module class: " + name) f = forceMangledName(name dropRight 1, true) if (f == NoSymbol) - f = definitions.getModule(name dropRight 1) + f = rootMirror.getModule(name dropRight 1) } else { val origName = nme.originalName(name) val owner = if (static) ownerTpe.typeSymbol.linkedClassOfClass else ownerTpe.typeSymbol @@ -417,7 +417,7 @@ abstract class ClassfileParser { */ def forceMangledName(name: Name, module: Boolean): Symbol = { val parts = name.decode.toString.split(Array('.', '$')) - var sym: Symbol = definitions.RootClass + var sym: Symbol = rootMirror.RootClass // was "at flatten.prev" beforeFlatten { @@ -445,7 +445,7 @@ abstract class ClassfileParser { return NoSymbol.newClass(name.toTypeName) } val completer = new global.loaders.ClassfileLoader(file) - var owner: Symbol = definitions.RootClass + var owner: Symbol = rootMirror.RootClass var sym: Symbol = NoSymbol var ss: Name = null var start = 0 @@ -473,9 +473,9 @@ abstract class ClassfileParser { def lookupClass(name: Name) = try { if (name.pos('.') == name.length) - definitions.getMember(definitions.EmptyPackageClass, name.toTypeName) + definitions.getMember(rootMirror.EmptyPackageClass, name.toTypeName) else - definitions.getClass(name) // see tickets #2464, #3756 + rootMirror.getClass(name) // see tickets #2464, #3756 } catch { case _: FatalError => loadClassSymbol(name) } @@ -919,7 +919,7 @@ abstract class ClassfileParser { val srcfileLeaf = pool.getName(in.nextChar).toString.trim val srcpath = sym.enclosingPackage match { case NoSymbol => srcfileLeaf - case definitions.EmptyPackage => srcfileLeaf + case rootMirror.EmptyPackage => srcfileLeaf case pkg => pkg.fullName(File.separatorChar)+File.separator+srcfileLeaf } srcfile0 = settings.outputDirs.srcFilesFor(in.file, srcpath).find(_.exists) diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala index 862a3ffdc7..bb9f9bde98 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala @@ -165,21 +165,21 @@ abstract class ICodeReader extends ClassfileParser { else if (name == fulltpnme.RuntimeNull) definitions.NullClass else if (nme.isImplClassName(name)) { - val iface = definitions.getClass(tpnme.interfaceName(name)) + val iface = rootMirror.getClassByName(tpnme.interfaceName(name)) log("forcing " + iface.owner + " at phase: " + phase + " impl: " + iface.implClass) iface.owner.info // force the mixin type-transformer - definitions.getClass(name) + rootMirror.getClassByName(name) } else if (nme.isModuleName(name)) { val strippedName = nme.stripModuleSuffix(name) val sym = forceMangledName(newTermName(strippedName.decode), true) - if (sym == NoSymbol) definitions.getModule(strippedName) + if (sym == NoSymbol) rootMirror.getModule(strippedName) else sym } else { forceMangledName(name, false) - afterFlatten(definitions.getClass(name.toTypeName)) + afterFlatten(rootMirror.getClassByName(name.toTypeName)) } if (sym.isModule) sym.moduleClass diff --git a/src/compiler/scala/tools/nsc/symtab/clr/CLRTypes.scala b/src/compiler/scala/tools/nsc/symtab/clr/CLRTypes.scala index 7be0fcb146..d3b6c9238d 100644 --- a/src/compiler/scala/tools/nsc/symtab/clr/CLRTypes.scala +++ b/src/compiler/scala/tools/nsc/symtab/clr/CLRTypes.scala @@ -12,7 +12,7 @@ import java.util.{Comparator, StringTokenizer} import scala.util.Sorting import ch.epfl.lamp.compiler.msil._ import scala.collection.{ mutable, immutable } -import scala.tools.nsc.util.{Position, NoPosition} +import scala.reflect.internal.util.{Position, NoPosition} /** * Collects all types from all reference assemblies. diff --git a/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala b/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala index 028d6f2484..e54ecdd590 100644 --- a/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala @@ -653,7 +653,7 @@ abstract class TypeParser { private def getClassType(typ: MSILType): Type = { assert(typ != null); - val res = definitions.getClass(typ.FullName.replace('+', '.')).tpe; + val res = rootMirror.getClassByName(typ.FullName.replace('+', '.')).tpe; //if (res.isError()) // global.reporter.error("unknown class reference " + type.FullName); res diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index ea66dbedd6..ce16facf77 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -638,7 +638,6 @@ abstract class Erasure extends AddInterfaces */ private def adaptMember(tree: Tree): Tree = { //Console.println("adaptMember: " + tree); - val x = 2 + 2 tree match { case Apply(TypeApply(sel @ Select(qual, name), List(targ)), List()) if tree.symbol == Any_asInstanceOf => @@ -967,7 +966,7 @@ abstract class Erasure extends AddInterfaces } // Rewrite 5.getClass to ScalaRunTime.anyValClass(5) else if (isPrimitiveValueClass(qual.tpe.typeSymbol)) - global.typer.typed(gen.mkRuntimeCall(nme.anyValClass, List(qual, typer.resolveErasureTag(qual.tpe.widen, tree.pos, true)))) + global.typer.typed(gen.mkRuntimeCall(nme.anyValClass, List(qual, typer.resolveClassTag(tree.pos, qual.tpe.widen)))) else tree diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala index 9cffb6a1e1..1b8513373d 100644 --- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala +++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala @@ -385,7 +385,7 @@ abstract class ExplicitOuter extends InfoTransform method setInfo new MethodType(params, BooleanClass.tpe) localTyper typed { - DEF(method) === guard.changeOwner(currentOwner -> method).substTreeSyms(vs zip params: _*) + DEF(method) === guard.changeOwner(currentOwner -> method).substituteSymbols(vs, params) } } @@ -410,18 +410,15 @@ abstract class ExplicitOuter extends InfoTransform (CASE(transform(strippedPat)) IF gdcall) ==> transform(body) } - def isUncheckedAnnotation(tpe: Type) = tpe hasAnnotation UncheckedClass - def isSwitchAnnotation(tpe: Type) = tpe hasAnnotation SwitchClass - val (checkExhaustive, requireSwitch) = nselector match { case Typed(nselector1, tpt) => - val unchecked = isUncheckedAnnotation(tpt.tpe) + val unchecked = treeInfo.isUncheckedAnnotation(tpt.tpe) if (unchecked) nselector = nselector1 // Don't require a tableswitch if there are 1-2 casedefs // since the matcher intentionally emits an if-then-else. - (!unchecked, isSwitchAnnotation(tpt.tpe) && ncases.size > 2) + (!unchecked, treeInfo.isSwitchAnnotation(tpt.tpe) && ncases.size > 2) case _ => (true, false) } diff --git a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala index 8556cc9ddc..31d804b4b5 100644 --- a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala +++ b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala @@ -138,9 +138,9 @@ abstract class ExtensionMethods extends Transform with TypingTransformers { val GenPolyType(extensionTpeParams, extensionMono) = extensionMeth.info val origTpeParams = (tparams map (_.symbol)) ::: currentOwner.typeParams val extensionBody = rhs - .substTreeSyms(origTpeParams, extensionTpeParams) - .substTreeSyms(vparamss.flatten map (_.symbol), allParams(extensionMono).tail) - .substTreeThis(currentOwner, thisParamRef) + .substituteSymbols(origTpeParams, extensionTpeParams) + .substituteSymbols(vparamss.flatten map (_.symbol), allParams(extensionMono).tail) + .substituteThis(currentOwner, thisParamRef) .changeOwner((origMeth, extensionMeth)) extensionDefs(companion) += atPos(tree.pos) { DefDef(extensionMeth, extensionBody) } val extensionCallPrefix = Apply( diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala index 79b9317f20..fe5bef5009 100644 --- a/src/compiler/scala/tools/nsc/transform/Mixin.scala +++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala @@ -477,7 +477,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { /** The rootContext used for typing */ private val rootContext = - erasure.NoContext.make(EmptyTree, RootClass, newScope) + erasure.NoContext.make(EmptyTree, rootMirror.RootClass, newScope) /** The typer */ private var localTyper: erasure.Typer = _ diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala index f2e109a5ad..ae6ec8511c 100644 --- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala +++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala @@ -9,6 +9,7 @@ package transform import scala.tools.nsc.symtab.Flags import scala.collection.{ mutable, immutable } import language.postfixOps +import language.existentials /** Specialize code on types. * @@ -66,11 +67,12 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { private implicit val typeOrdering: Ordering[Type] = Ordering[String] on ("" + _.typeSymbol.name) import definitions.{ - RootClass, BooleanClass, UnitClass, ArrayClass, + BooleanClass, UnitClass, ArrayClass, ScalaValueClasses, isPrimitiveValueClass, isPrimitiveValueType, SpecializedClass, UnspecializedClass, AnyRefClass, ObjectClass, AnyRefModule, GroupOfSpecializable, uncheckedVarianceClass, ScalaInlineClass } + import rootMirror.RootClass /** TODO - this is a lot of maps. */ @@ -434,7 +436,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { val sClassMap = anyrefSpecCache.getOrElseUpdate(sClass, mutable.Map[Symbol, Symbol]()) sClassMap.getOrElseUpdate(tparam, - tparam.cloneSymbol(sClass, tparam.flags, tparam.name append tpnme.SPECIALIZED_SUFFIX) + tparam.cloneSymbol(sClass, tparam.flags, (tparam.name append tpnme.SPECIALIZED_SUFFIX).asInstanceOf[Name]) // [Eugene++] why do we need this cast? modifyInfo (info => TypeBounds(info.bounds.lo, AnyRefClass.tpe)) ).tpe } @@ -1693,9 +1695,12 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { } } - private def forwardCall(pos: util.Position, receiver: Tree, paramss: List[List[ValDef]]): Tree = { + private def forwardCall(pos: scala.reflect.internal.util.Position, receiver: Tree, paramss: List[List[ValDef]]): Tree = { val argss = mmap(paramss)(x => Ident(x.symbol)) - atPos(pos) { (receiver /: argss) (Apply) } + def mkApply(fun: Tree, args: List[Tree]) = Apply(fun, args) + atPos(pos) { (receiver /: argss) (mkApply) } + // [Eugene++] no longer compiles after I moved the `Apply` case class into scala.reflect.internal + // atPos(pos) { (receiver /: argss) (Apply) } } /** Forward to the generic class constructor. If the current class initializes @@ -1717,7 +1722,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { * } * }} */ - private def forwardCtorCall(pos: util.Position, receiver: Tree, paramss: List[List[ValDef]], clazz: Symbol): Tree = { + private def forwardCtorCall(pos: scala.reflect.internal.util.Position, receiver: Tree, paramss: List[List[ValDef]], clazz: Symbol): Tree = { /** A constructor parameter `f` initializes a specialized field * iff: @@ -1737,7 +1742,10 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { else Ident(x.symbol) ) - atPos(pos) { (receiver /: argss) (Apply) } + def mkApply(fun: Tree, args: List[Tree]) = Apply(fun, args) + atPos(pos) { (receiver /: argss) (mkApply) } + // [Eugene++] no longer compiles after I moved the `Apply` case class into scala.reflect.internal + // atPos(pos) { (receiver /: argss) (Apply) } } /** Add method m to the set of symbols for which we need an implementation tree diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala index 8af12f3f10..663b3dd2e9 100644 --- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala +++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala @@ -418,23 +418,23 @@ abstract class UnCurry extends InfoTransform def sequenceToArray(tree: Tree) = { val toArraySym = tree.tpe member nme.toArray assert(toArraySym != NoSymbol) - def getArrayTag(tp: Type): Tree = { - val tag = localTyper.resolveArrayTag(tp, tree.pos) + def getClassTag(tp: Type): Tree = { + val tag = localTyper.resolveClassTag(tree.pos, tp) // Don't want bottom types getting any further than this (SI-4024) - if (tp.typeSymbol.isBottomClass) getArrayTag(AnyClass.tpe) + if (tp.typeSymbol.isBottomClass) getClassTag(AnyClass.tpe) else if (!tag.isEmpty) tag - else if (tp.bounds.hi ne tp) getArrayTag(tp.bounds.hi) - else localTyper.TyperErrorGen.MissingArrayTagError(tree, tp) + else if (tp.bounds.hi ne tp) getClassTag(tp.bounds.hi) + else localTyper.TyperErrorGen.MissingClassTagError(tree, tp) } - def traversableArrayTag(tpe: Type): Tree = { + def traversableClassTag(tpe: Type): Tree = { (tpe baseType TraversableClass).typeArgs match { - case targ :: _ => getArrayTag(targ) + case targ :: _ => getClassTag(targ) case _ => EmptyTree } } afterUncurry { localTyper.typedPos(pos) { - gen.mkMethodCall(tree, toArraySym, Nil, List(traversableArrayTag(tree.tpe))) + gen.mkMethodCall(tree, toArraySym, Nil, List(traversableClassTag(tree.tpe))) } } } @@ -688,7 +688,7 @@ abstract class UnCurry extends InfoTransform tree match { /* Some uncurry post transformations add members to templates. - * + * * Members registered by `addMembers` for the current template are added * once the template transformation has finished. * diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala index affa9cd63b..a2f0e053a8 100644 --- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala @@ -7,7 +7,7 @@ package scala.tools.nsc package typechecker import scala.collection.{ mutable, immutable } -import scala.tools.util.StringOps.{ countElementsAsString, countAsString } +import scala.reflect.internal.util.StringOps.{ countElementsAsString, countAsString } import symtab.Flags.{ PRIVATE, PROTECTED } trait ContextErrors { @@ -562,9 +562,9 @@ trait ContextErrors { def AbstractExistentiallyOverParamerizedTpeError(tree: Tree, tp: Type) = issueNormalTypeError(tree, "can't existentially abstract over parameterized type " + tp) - // resolveArrayTag - def MissingArrayTagError(tree: Tree, tp: Type) = { - issueNormalTypeError(tree, "cannot find array tag for element type "+tp) + // resolveClassTag + def MissingClassTagError(tree: Tree, tp: Type) = { + issueNormalTypeError(tree, "cannot find class tag for element type "+tp) setError(tree) } diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index f4f081252f..ac3c94c47a 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -30,9 +30,9 @@ trait Contexts { self: Analyzer => private val startContext = { NoContext.make( - global.Template(List(), emptyValDef, List()) setSymbol global.NoSymbol setType global.NoType, - global.definitions.RootClass, - global.definitions.RootClass.info.decls) + Template(List(), emptyValDef, List()) setSymbol global.NoSymbol setType global.NoType, + rootMirror.RootClass, + rootMirror.RootClass.info.decls) } var lastAccessCheckDetails: String = "" @@ -543,7 +543,7 @@ trait Contexts { self: Analyzer => (pre == NoPrefix) || { val ab = sym.accessBoundary(sym.owner) - ( (ab.isTerm || ab == definitions.RootClass) + ( (ab.isTerm || ab == rootMirror.RootClass) || (accessWithin(ab) || accessWithinLinked(ab)) && ( !sym.hasLocalFlag || sym.owner.isImplClass // allow private local accesses to impl classes diff --git a/src/compiler/scala/tools/nsc/typechecker/DestructureTypes.scala b/src/compiler/scala/tools/nsc/typechecker/DestructureTypes.scala index 0b414801d6..5802d36878 100644 --- a/src/compiler/scala/tools/nsc/typechecker/DestructureTypes.scala +++ b/src/compiler/scala/tools/nsc/typechecker/DestructureTypes.scala @@ -6,6 +6,8 @@ package scala.tools.nsc package typechecker +import language.implicitConversions + /** A generic means of breaking down types into their subcomponents. * Types are decomposed top down, and recognizable substructure is * dispatched via self-apparently named methods. Those methods can @@ -64,7 +66,7 @@ trait DestructureTypes { case x: NameTree => atom(x.name.toString, x) case _ => wrapAtom(tree) }, - tree.printingPrefix + tree.productPrefix ) def wrapSymbol(label: String, sym: Symbol): Node = { if (sym eq NoSymbol) wrapEmpty diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index 217cadaab8..aa63f3ec31 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -17,6 +17,7 @@ import mutable.{ LinkedHashMap, ListBuffer } import scala.util.matching.Regex import symtab.Flags._ import util.Statistics._ +import language.implicitConversions /** This trait provides methods to find various kinds of implicits. * @@ -335,7 +336,7 @@ trait Implicits { * The _complexity_ of a stripped core type corresponds roughly to the number of * nodes in its ast, except that singleton types are widened before taking the complexity. * Two types overlap if they have the same type symbol, or - * if one or both are intersection types with a pair of overlapiing parent types. + * if one or both are intersection types with a pair of overlapping parent types. */ private def dominates(dtor: Type, dted: Type): Boolean = { def core(tp: Type): Type = tp.normalize match { @@ -1132,11 +1133,9 @@ trait Implicits { private def TagSymbols = TagMaterializers.keySet private val TagMaterializers = Map[Symbol, Symbol]( - ArrayTagClass -> MacroInternal_materializeArrayTag, - ErasureTagClass -> MacroInternal_materializeErasureTag, - ClassTagClass -> MacroInternal_materializeClassTag, - TypeTagClass -> MacroInternal_materializeTypeTag, - ConcreteTypeTagClass -> MacroInternal_materializeConcreteTypeTag + ClassTagClass -> MacroInternal_materializeClassTag, + AbsTypeTagClass -> MacroInternal_materializeAbsTypeTag, + TypeTagClass -> MacroInternal_materializeTypeTag ) /** Creates a tree will produce a tag of the requested flavor. @@ -1166,9 +1165,8 @@ trait Implicits { } val prefix = ( - // ClassTags only exist for scala.reflect.mirror, so their materializer - // doesn't care about prefixes - if ((tagClass eq ArrayTagClass) || (tagClass eq ErasureTagClass) || (tagClass eq ClassTagClass)) ReflectMirrorPrefix + // ClassTags are not path-dependent, so their materializer doesn't care about prefixes + if (tagClass eq ClassTagClass) gen.mkBasisUniverseRef else pre match { // [Eugene to Martin] this is the crux of the interaction between // implicits and reifiers here we need to turn a (supposedly @@ -1183,16 +1181,24 @@ trait Implicits { // if ``pre'' is not a PDT, e.g. if someone wrote // implicitly[scala.reflect.makro.Context#TypeTag[Int]] // then we need to fail, because we don't know the prefix to use during type reification - return failure(tp, "tag error: unsupported prefix type %s (%s)".format(pre, pre.kind)) + // upd. we also need to fail silently, because this is a very common situation + // e.g. quite often we're searching for BaseUniverse#TypeTag, e.g. for a type tag in any universe + // so that if we find one, we could convert it to whatever universe we need by the means of the `in` method + // if no tag is found in scope, we end up here, where we ask someone to materialize the tag for us + // however, since the original search was about a tag with no particular prefix, we cannot proceed + // this situation happens very often, so emitting an error message here (even if only for -Xlog-implicits) would be too much + //return failure(tp, "tag error: unsupported prefix type %s (%s)".format(pre, pre.kind)) + return SearchFailure } ) // todo. migrate hardcoded materialization in Implicits to corresponding implicit macros - var materializer = atPos(pos.focus)( - gen.mkMethodCall(TagMaterializers(tagClass), List(tp), List(prefix)) - ) + var materializer = atPos(pos.focus)(gen.mkMethodCall(TagMaterializers(tagClass), List(tp), List(prefix))) if (settings.XlogImplicits.value) println("materializing requested %s.%s[%s] using %s".format(pre, tagClass.name, tp, materializer)) if (context.macrosEnabled) success(materializer) - else failure(materializer, "macros are disabled") + // don't call `failure` here. if macros are disabled, we just fail silently + // otherwise -Xlog-implicits will spam the long with zillions of "macros are disabled" + // this is ugly but temporary, since all this code will be removed once I fix implicit macros + else SearchFailure } private val ManifestSymbols = Set[Symbol](PartialManifestClass, FullManifestClass, OptManifestClass) @@ -1287,13 +1293,33 @@ trait Implicits { } val tagInScope = - if (full) context.withMacrosDisabled(resolveTypeTag(ReflectMirrorPrefix.tpe, tp, pos, true)) - else context.withMacrosDisabled(resolveArrayTag(tp, pos)) + if (full) resolveTypeTag(pos, NoType, tp, concrete = true, allowMaterialization = false) + else resolveClassTag(pos, tp, allowMaterialization = false) if (tagInScope.isEmpty) mot(tp, Nil, Nil) else { + if (full) { + if (ReflectRuntimeUniverse == NoSymbol) { + // todo. write a test for this + context.error(pos, s""" + |to create a manifest here, it is necessary to interoperate with the type tag `$tagInScope` in scope. + |however typetag -> manifest conversion requires Scala reflection, which is not present on the classpath. + |to proceed put scala-reflect.jar on your compilation classpath and recompile.""".trim.stripMargin) + return SearchFailure + } + if (resolveClassTag(pos, tp, allowMaterialization = true) == EmptyTree) { + context.error(pos, s""" + |to create a manifest here, it is necessary to interoperate with the type tag `$tagInScope` in scope. + |however typetag -> manifest conversion requires a class tag for the corresponding type to be present. + |to proceed add a class tag to the type `$tp` (e.g. by introducing a context bound) and recompile.""".trim.stripMargin) + return SearchFailure + } + } + val interop = - if (full) gen.mkMethodCall(ReflectPackage, nme.concreteTypeTagToManifest, List(tp), List(tagInScope)) - else gen.mkMethodCall(ReflectPackage, nme.arrayTagToClassManifest, List(tp), List(tagInScope)) + if (full) { + val cm = typed(Ident(ReflectRuntimeCurrentMirror)) + gen.mkMethodCall(ReflectRuntimeUniverse, nme.typeTagToManifest, List(tp), List(cm, tagInScope)) + } else gen.mkMethodCall(ReflectRuntimeUniverse, nme.classTagToClassManifest, List(tp), List(tagInScope)) wrapResult(interop) } } diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala index 85c2aebfab..9e371dd2dd 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala @@ -187,7 +187,7 @@ trait Infer { tp1 // @MAT aliases already handled by subtyping } - private val stdErrorClass = RootClass.newErrorClass(tpnme.ERROR) + private val stdErrorClass = rootMirror.RootClass.newErrorClass(tpnme.ERROR) private val stdErrorValue = stdErrorClass.newErrorValue(nme.ERROR) /** The context-dependent inferencer part */ @@ -1247,7 +1247,10 @@ trait Infer { check(tp, Nil) } - def checkCheckable(tree: Tree, tp: Type, kind: String) { + // if top-level abstract types can be checked using a classtag extractor, don't warn about them + def checkCheckable(tree: Tree, tp: Type, inPattern: Boolean, canRemedy: Boolean = false) = { + val kind = if (inPattern) "pattern " else "" + def patternWarning(tp0: Type, prefix: String) = { context.unit.uncheckedWarning(tree.pos, prefix+tp0+" in type "+kind+tp+" is unchecked since it is eliminated by erasure") } @@ -1264,7 +1267,8 @@ trait Infer { check(pre, bound) case TypeRef(pre, sym, args) => if (sym.isAbstractType) { - if (!isLocalBinding(sym)) patternWarning(tp, "abstract type ") + // we only use the extractor for top-level type tests, type arguments (see below) remain unchecked + if (!isLocalBinding(sym) && !canRemedy) patternWarning(tp, "abstract type ") } else if (sym.isAliasType) { check(tp.normalize, bound) } else if (sym == NothingClass || sym == NullClass || sym == AnyValClass) { @@ -1320,7 +1324,7 @@ trait Infer { } } - def inferTypedPattern(tree0: Tree, pattp: Type, pt0: Type): Type = { + def inferTypedPattern(tree0: Tree, pattp: Type, pt0: Type, canRemedy: Boolean): Type = { val pt = widen(pt0) val ptparams = freeTypeParamsOfTerms(pt) val tpparams = freeTypeParamsOfTerms(pattp) @@ -1337,7 +1341,7 @@ trait Infer { return ErrorType } - checkCheckable(tree0, pattp, "pattern ") + checkCheckable(tree0, pattp, inPattern = true, canRemedy) if (pattp <:< pt) () else { debuglog("free type params (1) = " + tpparams) diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala index c10901cdce..ec14476d1a 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala @@ -4,13 +4,13 @@ package typechecker import symtab.Flags._ import scala.tools.nsc.util._ import scala.tools.nsc.util.ClassPath._ -import scala.reflect.ReflectionUtils +import scala.reflect.runtime.ReflectionUtils import scala.collection.mutable.ListBuffer import scala.compat.Platform.EOL -import scala.reflect.makro.runtime.{Context => MacroContext} -import scala.reflect.runtime.Mirror import util.Statistics._ import scala.reflect.makro.util._ +import java.lang.{Class => jClass} +import java.lang.reflect.{Array => jArray, Method => jMethod} /** * Code to deal with macros, namely with: @@ -26,7 +26,7 @@ import scala.reflect.makro.util._ * def fooBar[T: c.TypeTag] * (c: scala.reflect.makro.Context) * (xs: c.Expr[List[T]]) - * : c.mirror.Tree = { + * : c.Tree = { * ... * } * @@ -37,7 +37,7 @@ import scala.reflect.makro.util._ * (Expr(elems)) * (TypeTag(Int)) */ -trait Macros extends Traces { +trait Macros extends scala.tools.reflect.FastTrack with Traces { self: Analyzer => import global._ @@ -104,7 +104,7 @@ trait Macros extends Traces { RepeatedParamClass.typeConstructor, List(implType(isType, sigma(origTpe.typeArgs.head)))) else { - val tsym = getMember(MacroContextClass, if (isType) tpnme.TypeTag else tpnme.Expr) + val tsym = getMember(MacroContextClass, if (isType) tpnme.AbsTypeTag else tpnme.Expr) typeRef(singleType(NoPrefix, ctxParam), tsym, List(sigma(origTpe))) } val paramCache = collection.mutable.Map[Symbol, Symbol]() @@ -155,7 +155,7 @@ trait Macros extends Traces { case TypeRef(SingleType(NoPrefix, contextParam), sym, List(tparam)) => var wannabe = sym while (wannabe.isAliasType) wannabe = wannabe.info.typeSymbol - if (wannabe != definitions.TypeTagClass && wannabe != definitions.ConcreteTypeTagClass) + if (wannabe != definitions.AbsTypeTagClass && wannabe != definitions.TypeTagClass) List(param) else transform(param, tparam.typeSymbol) map (_ :: Nil) getOrElse Nil @@ -185,7 +185,14 @@ trait Macros extends Traces { import typer.context macroLogVerbose("typechecking macro def %s at %s".format(ddef.symbol, ddef.pos)) + if (fastTrack contains ddef.symbol) { + macroLogVerbose("typecheck terminated unexpectedly: macro is hardwired") + assert(!ddef.tpt.isEmpty, "hardwired macros must provide result type") + return EmptyTree + } + if (!typer.checkFeature(ddef.pos, MacrosFeature, immediate = true)) { + macroLogVerbose("typecheck terminated unexpectedly: language.experimental.macros feature is not enabled") ddef.symbol setFlag IS_ERROR return EmptyTree } @@ -193,8 +200,9 @@ trait Macros extends Traces { implicit class AugmentedString(s: String) { def abbreviateCoreAliases: String = { // hack! var result = s - result = result.replace("c.mirror.TypeTag", "c.TypeTag") - result = result.replace("c.mirror.Expr", "c.Expr") + result = result.replace("c.universe.AbsTypeTag", "c.AbsTypeTag") + result = result.replace("c.universe.TypeTag", "c.TypeTag") + result = result.replace("c.universe.Expr", "c.Expr") result } } @@ -582,126 +590,81 @@ trait Macros extends Traces { runtimeType } - /** Primary mirror that is used to resolve and run macro implementations. + /** Primary classloader that is used to resolve and run macro implementations. * Loads classes from -Xmacro-primary-classpath, or from -cp if the option is not specified. + * Is also capable of detecting REPL and reusing its classloader. */ - private lazy val primaryMirror: Mirror = { + private lazy val primaryClassloader: ClassLoader = { if (global.forMSIL) throw new UnsupportedOperationException("Scala reflection not available on this platform") - val libraryClassLoader = { - if (settings.XmacroPrimaryClasspath.value != "") { - macroLogVerbose("primary macro mirror: initializing from -Xmacro-primary-classpath: %s".format(settings.XmacroPrimaryClasspath.value)) - val classpath = toURLs(settings.XmacroFallbackClasspath.value) - ScalaClassLoader.fromURLs(classpath, self.getClass.getClassLoader) - } else { - macroLogVerbose("primary macro mirror: initializing from -cp: %s".format(global.classPath.asURLs)) - val classpath = global.classPath.asURLs - var loader: ClassLoader = ScalaClassLoader.fromURLs(classpath, self.getClass.getClassLoader) - - // [Eugene] a heuristic to detect REPL - if (global.settings.exposeEmptyPackage.value) { - import scala.tools.nsc.interpreter._ - val virtualDirectory = global.settings.outputDirs.getSingleOutput.get - loader = new AbstractFileClassLoader(virtualDirectory, loader) {} - } - - loader + if (settings.XmacroPrimaryClasspath.value != "") { + macroLogVerbose("primary macro classloader: initializing from -Xmacro-primary-classpath: %s".format(settings.XmacroPrimaryClasspath.value)) + val classpath = toURLs(settings.XmacroFallbackClasspath.value) + ScalaClassLoader.fromURLs(classpath, self.getClass.getClassLoader) + } else { + macroLogVerbose("primary macro classloader: initializing from -cp: %s".format(global.classPath.asURLs)) + val classpath = global.classPath.asURLs + var loader: ClassLoader = ScalaClassLoader.fromURLs(classpath, self.getClass.getClassLoader) + + // [Eugene] a heuristic to detect the REPL + if (global.settings.exposeEmptyPackage.value) { + macroLogVerbose("primary macro classloader: initializing from a REPL classloader".format(global.classPath.asURLs)) + import scala.tools.nsc.interpreter._ + val virtualDirectory = global.settings.outputDirs.getSingleOutput.get + loader = new AbstractFileClassLoader(virtualDirectory, loader) {} } - } - new Mirror(libraryClassLoader) { override def toString = "<primary macro mirror>" } + loader + } } - /** Fallback mirror that is used to resolve and run macro implementations. - * Loads classes from -Xmacro-fallback-classpath aka "macro fallback classpath". + /** Fallback classloader that is used to resolve and run macro implementations when `primaryClassloader` fails. + * Loads classes from -Xmacro-fallback-classpath. */ - private lazy val fallbackMirror: Mirror = { + private lazy val fallbackClassloader: ClassLoader = { if (global.forMSIL) throw new UnsupportedOperationException("Scala reflection not available on this platform") - val fallbackClassLoader = { - macroLogVerbose("fallback macro mirror: initializing from -Xmacro-fallback-classpath: %s".format(settings.XmacroFallbackClasspath.value)) - val classpath = toURLs(settings.XmacroFallbackClasspath.value) - ScalaClassLoader.fromURLs(classpath, self.getClass.getClassLoader) - } - - new Mirror(fallbackClassLoader) { override def toString = "<fallback macro mirror>" } + macroLogVerbose("fallback macro classloader: initializing from -Xmacro-fallback-classpath: %s".format(settings.XmacroFallbackClasspath.value)) + val classpath = toURLs(settings.XmacroFallbackClasspath.value) + ScalaClassLoader.fromURLs(classpath, self.getClass.getClassLoader) } /** Produces a function that can be used to invoke macro implementation for a given macro definition: * 1) Looks up macro implementation symbol in this universe. - * 2) Loads its enclosing class from the primary mirror. - * 3) Loads the companion of that enclosing class from the primary mirror. + * 2) Loads its enclosing class from the primary classloader. + * 3) Loads the companion of that enclosing class from the primary classloader. * 4) Resolves macro implementation within the loaded companion. - * 5) If 2-4 fails, repeats them for the fallback mirror. + * 5) If 2-4 fails, repeats them for the fallback classloader. * * @return Some(runtime) if macro implementation can be loaded successfully from either of the mirrors, * None otherwise. */ - private type MacroRuntime = List[Any] => Any + type MacroRuntime = List[Any] => Any private val macroRuntimesCache = perRunCaches.newWeakMap[Symbol, Option[MacroRuntime]] - private lazy val fastTrack: Map[Symbol, MacroRuntime] = { - import scala.reflect.api.Universe - import scala.reflect.makro.internal._ - Map( // challenge: how can we factor out the common code? Does not seem to be easy. - MacroInternal_materializeArrayTag -> (args => { - assert(args.length == 3, args) - val c = args(0).asInstanceOf[MacroContext] - materializeArrayTag_impl(c)(args(1).asInstanceOf[c.Expr[Universe]])(args(2).asInstanceOf[c.TypeTag[_]]) - }), - MacroInternal_materializeErasureTag -> (args => { - assert(args.length == 3, args) - val c = args(0).asInstanceOf[MacroContext] - materializeErasureTag_impl(c)(args(1).asInstanceOf[c.Expr[Universe]])(args(2).asInstanceOf[c.TypeTag[_]]) - }), - MacroInternal_materializeClassTag -> (args => { - assert(args.length == 3, args) - val c = args(0).asInstanceOf[MacroContext] - materializeClassTag_impl(c)(args(1).asInstanceOf[c.Expr[Universe]])(args(2).asInstanceOf[c.TypeTag[_]]) - }), - MacroInternal_materializeTypeTag -> (args => { - assert(args.length == 3, args) - val c = args(0).asInstanceOf[MacroContext] - materializeTypeTag_impl(c)(args(1).asInstanceOf[c.Expr[Universe]])(args(2).asInstanceOf[c.TypeTag[_]]) - }), - MacroInternal_materializeConcreteTypeTag -> (args => { - assert(args.length == 3, args) - val c = args(0).asInstanceOf[MacroContext] - materializeConcreteTypeTag_impl(c)(args(1).asInstanceOf[c.Expr[Universe]])(args(2).asInstanceOf[c.TypeTag[_]]) - }) - ) - } private def macroRuntime(macroDef: Symbol): Option[MacroRuntime] = { macroTraceVerbose("looking for macro implementation: ")(macroDef) if (fastTrack contains macroDef) { - macroLogVerbose("macro expansion serviced by a fast track") + macroLogVerbose("macro expansion is serviced by a fast track") Some(fastTrack(macroDef)) } else { macroRuntimesCache.getOrElseUpdate(macroDef, { val runtime = { - macroTraceVerbose("looking for macro implementation: ")(macroDef) macroTraceVerbose("macroDef is annotated with: ")(macroDef.annotations) val ann = macroDef.getAnnotation(MacroImplAnnotation) - if (ann == None) { - macroTraceVerbose("@macroImpl annotation is missing (this means that macro definition failed to typecheck)")(macroDef) - return None - } + if (ann == None) { macroTraceVerbose("@macroImpl annotation is missing (this means that macro definition failed to typecheck)")(macroDef); return None } val macroImpl = ann.get.args(0).symbol - if (macroImpl == NoSymbol) { - macroTraceVerbose("@macroImpl annotation is malformed (this means that macro definition failed to typecheck)")(macroDef) - return None - } - + if (macroImpl == NoSymbol) { macroTraceVerbose("@macroImpl annotation is malformed (this means that macro definition failed to typecheck)")(macroDef); return None } macroLogVerbose("resolved implementation %s at %s".format(macroImpl, macroImpl.pos)) - if (macroImpl.isErroneous) { - macroTraceVerbose("macro implementation is erroneous (this means that either macro body or macro implementation signature failed to typecheck)")(macroDef) - return None - } + if (macroImpl.isErroneous) { macroTraceVerbose("macro implementation is erroneous (this means that either macro body or macro implementation signature failed to typecheck)")(macroDef); return None } - def loadMacroImpl(macroMirror: Mirror): Option[(Object, macroMirror.Symbol)] = { + // [Eugene++] I don't use Scala reflection here, because it seems to interfere with JIT magic + // whenever you instantiate a mirror (and not do anything with in, just instantiate), performance drops by 15-20% + // I'm not sure what's the reason - for me it's pure voodoo + def loadMacroImpl(cl: ClassLoader): Option[(Object, jMethod)] = { try { // this logic relies on the assumptions that were valid for the old macro prototype // namely that macro implementations can only be defined in top-level classes and modules @@ -711,17 +674,11 @@ trait Macros extends Traces { // however, the code below doesn't account for these guys, because it'd take a look of time to get it right // for now I leave it as a todo and move along to more the important stuff - macroTraceVerbose("loading implementation class from %s: ".format(macroMirror))(macroImpl.owner.fullName) - macroTraceVerbose("classloader is: ")("%s of type %s".format(macroMirror.classLoader, if (macroMirror.classLoader != null) macroMirror.classLoader.getClass.toString else "primordial classloader")) - def inferClasspath(cl: ClassLoader) = cl match { - case cl: java.net.URLClassLoader => "[" + (cl.getURLs mkString ",") + "]" - case null => "[" + scala.tools.util.PathResolver.Environment.javaBootClassPath + "]" - case _ => "<unknown>" - } - macroTraceVerbose("classpath is: ")(inferClasspath(macroMirror.classLoader)) + macroTraceVerbose("loading implementation class: ")(macroImpl.owner.fullName) + macroTraceVerbose("classloader is: ")(ReflectionUtils.show(cl)) // [Eugene] relies on the fact that macro implementations can only be defined in static classes - // [Martin to Eugene] There's similar logic buried in Symbol#flatname. Maybe we can refactor? + // [Martin to Eugene++] There's similar logic buried in Symbol#flatname. Maybe we can refactor? def classfile(sym: Symbol): String = { def recur(sym: Symbol): String = sym match { case sym if sym.owner.isPackageClass => @@ -736,71 +693,66 @@ trait Macros extends Traces { else recur(sym.enclClass) } - // [Eugene] this doesn't work for inner classes + // [Eugene++] this doesn't work for inner classes // neither does macroImpl.owner.javaClassName, so I had to roll my own implementation //val receiverName = macroImpl.owner.fullName val implClassName = classfile(macroImpl.owner) - val implClassSymbol: macroMirror.Symbol = macroMirror.symbolForName(implClassName) - - if (macroDebugVerbose) { - println("implClassSymbol is: " + implClassSymbol.fullNameString) - - if (implClassSymbol != macroMirror.NoSymbol) { - val implClass = macroMirror.classToJava(implClassSymbol) - val implSource = implClass.getProtectionDomain.getCodeSource - println("implClass is %s from %s".format(implClass, implSource)) - println("implClassLoader is %s with classpath %s".format(implClass.getClassLoader, inferClasspath(implClass.getClassLoader))) - } + val implObj = try { + val implObjClass = jClass.forName(implClassName, true, cl) + implObjClass getField "MODULE$" get null + } catch { + case ex: NoSuchFieldException => macroTraceVerbose("exception when loading implObj: ")(ex); null + case ex: NoClassDefFoundError => macroTraceVerbose("exception when loading implObj: ")(ex); null + case ex: ClassNotFoundException => macroTraceVerbose("exception when loading implObj: ")(ex); null } - val implObjSymbol = implClassSymbol.companionModule - macroTraceVerbose("implObjSymbol is: ")(implObjSymbol.fullNameString) - - if (implObjSymbol == macroMirror.NoSymbol) None + if (implObj == null) None else { - // yet another reflection method that doesn't work for inner classes - //val receiver = macroMirror.companionInstance(receiverClass) - val implObj = try { - val implObjClass = java.lang.Class.forName(implClassName, true, macroMirror.classLoader) - implObjClass getField "MODULE$" get null - } catch { - case ex: NoSuchFieldException => macroTraceVerbose("exception when loading implObj: ")(ex); null - case ex: NoClassDefFoundError => macroTraceVerbose("exception when loading implObj: ")(ex); null - case ex: ClassNotFoundException => macroTraceVerbose("exception when loading implObj: ")(ex); null - } - - if (implObj == null) None - else { - val implMethSymbol = implObjSymbol.info.member(macroMirror.newTermName(macroImpl.name.toString)) - macroLogVerbose("implMethSymbol is: " + implMethSymbol.fullNameString) - macroLogVerbose("jimplMethSymbol is: " + macroMirror.methodToJava(implMethSymbol)) + // [Eugene++] doh, it seems that I need to copy/paste Scala reflection logic + // see `JavaMirrors.methodToJava` or whatever it's called now + val implMeth = { + def typeToJavaClass(tpe: Type): jClass[_] = tpe match { + case ExistentialType(_, rtpe) => typeToJavaClass(rtpe) + case TypeRef(_, ArrayClass, List(elemtpe)) => jArray.newInstance(typeToJavaClass(elemtpe), 0).getClass + case TypeRef(_, sym: ClassSymbol, _) => jClass.forName(classfile(sym), true, cl) + case _ => throw new NoClassDefFoundError("no Java class corresponding to "+tpe+" found") + } - if (implMethSymbol == macroMirror.NoSymbol) None - else { - macroLogVerbose("successfully loaded macro impl as (%s, %s)".format(implObj, implMethSymbol)) - Some((implObj, implMethSymbol)) + val paramClasses = transformedType(macroImpl).paramTypes map typeToJavaClass + try implObj.getClass getDeclaredMethod (macroImpl.name.toString, paramClasses: _*) + catch { + case ex: NoSuchMethodException => + val expandedName = + if (macroImpl.isPrivate) nme.expandedName(macroImpl.name.toTermName, macroImpl.owner).toString + else macroImpl.name.toString + implObj.getClass getDeclaredMethod (expandedName, paramClasses: _*) } } + macroLogVerbose("successfully loaded macro impl as (%s, %s)".format(implObj, implMeth)) + Some((implObj, implMeth)) } } catch { case ex: ClassNotFoundException => macroTraceVerbose("implementation class failed to load: ")(ex.toString) None + case ex: NoSuchMethodException => + macroTraceVerbose("implementation method failed to load: ")(ex.toString) + None } } - val primary = loadMacroImpl(primaryMirror) + val primary = loadMacroImpl(primaryClassloader) primary match { - case Some((implObj, implMethSymbol)) => - def runtime(args: List[Any]) = primaryMirror.invoke(implObj, implMethSymbol)(args: _*).asInstanceOf[Any] + case Some((implObj, implMeth)) => + def runtime(args: List[Any]) = implMeth.invoke(implObj, (args map (_.asInstanceOf[AnyRef])): _*).asInstanceOf[Any] Some(runtime _) case None => if (settings.XmacroFallbackClasspath.value != "") { macroLogVerbose("trying to load macro implementation from the fallback mirror: %s".format(settings.XmacroFallbackClasspath.value)) - val fallback = loadMacroImpl(fallbackMirror) + val fallback = loadMacroImpl(fallbackClassloader) fallback match { - case Some((implObj, implMethSymbol)) => - def runtime(args: List[Any]) = fallbackMirror.invoke(implObj, implMethSymbol)(args: _*).asInstanceOf[Any] + case Some((implObj, implMeth)) => + def runtime(args: List[Any]) = implMeth.invoke(implObj, (args map (_.asInstanceOf[AnyRef])): _*).asInstanceOf[Any] Some(runtime _) case None => None @@ -817,15 +769,14 @@ trait Macros extends Traces { } } - /** Should become private again once we're done with migrating typetag generation from implicits */ - def macroContext(typer: Typer, prefixTree: Tree, expandeeTree: Tree): MacroContext { val mirror: global.type } = + private def macroContext(typer: Typer, prefixTree: Tree, expandeeTree: Tree): MacroContext = new { - val mirror: global.type = global - val callsiteTyper: mirror.analyzer.Typer = typer.asInstanceOf[global.analyzer.Typer] - // todo. infer precise typetag for this Expr, namely the PrefixType member of the Context refinement - val prefix = Expr(prefixTree)(TypeTag.Nothing) + val universe: self.global.type = self.global + val callsiteTyper: universe.analyzer.Typer = typer.asInstanceOf[global.analyzer.Typer] val expandee = expandeeTree - } with MacroContext { + } with UnaffiliatedMacroContext { + // todo. infer precise typetag for this Expr, namely the PrefixType member of the Context refinement + val prefix = Expr[Nothing](prefixTree)(TypeTag.Nothing) override def toString = "MacroContext(%s@%s +%d)".format(expandee.symbol.name, expandee.pos, enclosingMacros.length - 1 /* exclude myself */) } @@ -837,118 +788,124 @@ trait Macros extends Traces { * @return list of runtime objects to pass to the implementation obtained by ``macroRuntime'' */ private def macroArgs(typer: Typer, expandee: Tree): Option[List[Any]] = { - val macroDef = expandee.symbol - val runtime = macroRuntime(macroDef) orElse { return None } - var prefixTree: Tree = EmptyTree - var typeArgs = List[Tree]() - val exprArgs = ListBuffer[List[Expr[_]]]() - + val macroDef = expandee.symbol + val runtime = macroRuntime(macroDef) orElse { return None } + val prefixTree = expandee.collect{ case Select(qual, name) => qual }.headOption.getOrElse(EmptyTree) + val context = expandee.attachments.get[MacroRuntimeAttachment].flatMap(_.macroContext).getOrElse(macroContext(typer, prefixTree, expandee)) + var typeArgs = List[Tree]() + val exprArgs = ListBuffer[List[Expr[_]]]() def collectMacroArgs(tree: Tree): Unit = tree match { case Apply(fn, args) => // todo. infer precise typetag for this Expr, namely the declared type of the corresponding macro impl argument - exprArgs.prepend(args map (Expr(_)(TypeTag.Nothing))) + exprArgs.prepend(args map (arg => context.Expr[Nothing](arg)(TypeTag.Nothing))) collectMacroArgs(fn) case TypeApply(fn, args) => typeArgs = args collectMacroArgs(fn) - case Select(qual, name) => - prefixTree = qual case _ => } collectMacroArgs(expandee) - val context = expandee.attachmentOpt[MacroAttachment].flatMap(_.macroContext).getOrElse(macroContext(typer, prefixTree, expandee)) var argss: List[List[Any]] = List(context) :: exprArgs.toList macroTraceVerbose("argss: ")(argss) + val rawArgss = + if (fastTrack contains macroDef) { + if (fastTrack(macroDef) validate argss) argss + else { + // if you're getting here, it's not necessarily partial application that is at fault + // for example, if a signature of a hardwired macro has been changed without updated FastTrack + // then the corresponding partial function in FastTrack will refuse to process the expandee + // validation will return false, and control flow will end up here + // however, for simplicity sake, I didn't introduce the notion of error handling to FastTrack + // so all kinds of validation errors produce `MacroPartialApplicationError` + typer.TyperErrorGen.MacroPartialApplicationError(expandee) + return None + } + } else { + val ann = macroDef.getAnnotation(MacroImplAnnotation).getOrElse(throw new Error("assertion failed. %s: %s".format(macroDef, macroDef.annotations))) + val macroImpl = ann.args(0).symbol + var paramss = macroImpl.paramss + val tparams = macroImpl.typeParams + macroTraceVerbose("paramss: ")(paramss) + + // we need to take care of all possible combos of nullary/empty-paramlist macro defs vs nullary/empty-arglist invocations + // nullary def + nullary invocation => paramss and argss match, everything is okay + // nullary def + empty-arglist invocation => illegal Scala code, impossible, everything is okay + // empty-paramlist def + nullary invocation => uh-oh, we need to append a List() to argss + // empty-paramlist def + empty-arglist invocation => paramss and argss match, everything is okay + // that's almost it, but we need to account for the fact that paramss might have context bounds that mask the empty last paramlist + val paramss_without_evidences = transformTypeTagEvidenceParams(paramss, (param, tparam) => None) + val isEmptyParamlistDef = paramss_without_evidences.nonEmpty && paramss_without_evidences.last.isEmpty + val isEmptyArglistInvocation = argss.nonEmpty && argss.last.isEmpty + if (isEmptyParamlistDef && !isEmptyArglistInvocation) { + macroLogVerbose("isEmptyParamlistDef && !isEmptyArglistInvocation: appending a List() to argss") + argss = argss :+ Nil + } - val ann = macroDef.getAnnotation(MacroImplAnnotation).getOrElse(throw new Error("assertion failed. %s: %s".format(macroDef, macroDef.annotations))) - val macroImpl = ann.args(0).symbol - var paramss = macroImpl.paramss - val tparams = macroImpl.typeParams - macroTraceVerbose("paramss: ")(paramss) - - // we need to take care of all possible combos of nullary/empty-paramlist macro defs vs nullary/empty-arglist invocations - // nullary def + nullary invocation => paramss and argss match, everything is okay - // nullary def + empty-arglist invocation => illegal Scala code, impossible, everything is okay - // empty-paramlist def + nullary invocation => uh-oh, we need to append a List() to argss - // empty-paramlist def + empty-arglist invocation => paramss and argss match, everything is okay - // that's almost it, but we need to account for the fact that paramss might have context bounds that mask the empty last paramlist - val paramss_without_evidences = transformTypeTagEvidenceParams(paramss, (param, tparam) => None) - val isEmptyParamlistDef = paramss_without_evidences.nonEmpty && paramss_without_evidences.last.isEmpty - val isEmptyArglistInvocation = argss.nonEmpty && argss.last.isEmpty - if (isEmptyParamlistDef && !isEmptyArglistInvocation) { - macroLogVerbose("isEmptyParamlistDef && !isEmptyArglistInvocation: appending a List() to argss") - argss = argss :+ Nil - } - - // nb! check partial application against paramss without evidences - val numParamLists = paramss_without_evidences.length - val numArgLists = argss.length - if (numParamLists != numArgLists) { - typer.TyperErrorGen.MacroPartialApplicationError(expandee) - return None - } + // nb! check partial application against paramss without evidences + val numParamLists = paramss_without_evidences.length + val numArgLists = argss.length + if (numParamLists != numArgLists) { + typer.TyperErrorGen.MacroPartialApplicationError(expandee) + return None + } - // if paramss have typetag context bounds, add an arglist to argss if necessary and instantiate the corresponding evidences - // consider the following example: - // - // class D[T] { - // class C[U] { - // def foo[V] = macro Impls.foo[T, U, V] - // } - // } - // - // val outer1 = new D[Int] - // val outer2 = new outer1.C[String] - // outer2.foo[Boolean] - // - // then T and U need to be inferred from the lexical scope of the call using ``asSeenFrom'' - // whereas V won't be resolved by asSeenFrom and need to be loaded directly from ``expandee'' which needs to contain a TypeApply node - // also, macro implementation reference may contain a regular type as a type argument, then we pass it verbatim - val resolved = collection.mutable.Map[Symbol, Type]() - paramss = transformTypeTagEvidenceParams(paramss, (param, tparam) => { - val TypeApply(_, implRefTargs) = ann.args(0) - var implRefTarg = implRefTargs(tparam.paramPos).tpe.typeSymbol - val tpe = if (implRefTarg.isTypeParameterOrSkolem) { - if (implRefTarg.owner == macroDef) { - // [Eugene] doesn't work when macro def is compiled separately from its usages - // then implRefTarg is not a skolem and isn't equal to any of macroDef.typeParams -// val paramPos = implRefTarg.deSkolemize.paramPos - val paramPos = macroDef.typeParams.indexWhere(_.name == implRefTarg.name) - typeArgs(paramPos).tpe - } else - implRefTarg.tpe.asSeenFrom( - if (prefixTree == EmptyTree) macroDef.owner.tpe else prefixTree.tpe, - macroDef.owner) - } else - implRefTarg.tpe - macroLogVerbose("resolved tparam %s as %s".format(tparam, tpe)) - resolved(tparam) = tpe - param.tpe.typeSymbol match { - case definitions.TypeTagClass => - // do nothing - case definitions.ConcreteTypeTagClass => - if (!tpe.isConcrete) context.abort(context.enclosingPosition, "cannot create ConcreteTypeTag from a type %s having unresolved type parameters".format(tpe)) - // otherwise do nothing - case _ => - throw new Error("unsupported tpe: " + tpe) + // if paramss have typetag context bounds, add an arglist to argss if necessary and instantiate the corresponding evidences + // consider the following example: + // + // class D[T] { + // class C[U] { + // def foo[V] = macro Impls.foo[T, U, V] + // } + // } + // + // val outer1 = new D[Int] + // val outer2 = new outer1.C[String] + // outer2.foo[Boolean] + // + // then T and U need to be inferred from the lexical scope of the call using ``asSeenFrom'' + // whereas V won't be resolved by asSeenFrom and need to be loaded directly from ``expandee'' which needs to contain a TypeApply node + // also, macro implementation reference may contain a regular type as a type argument, then we pass it verbatim + val resolved = collection.mutable.Map[Symbol, Type]() + paramss = transformTypeTagEvidenceParams(paramss, (param, tparam) => { + val TypeApply(_, implRefTargs) = ann.args(0) + var implRefTarg = implRefTargs(tparam.paramPos).tpe.typeSymbol + val tpe = if (implRefTarg.isTypeParameterOrSkolem) { + if (implRefTarg.owner == macroDef) { + // [Eugene] doesn't work when macro def is compiled separately from its usages + // then implRefTarg is not a skolem and isn't equal to any of macroDef.typeParams + // val paramPos = implRefTarg.deSkolemize.paramPos + val paramPos = macroDef.typeParams.indexWhere(_.name == implRefTarg.name) + typeArgs(paramPos).tpe + } else + implRefTarg.tpe.asSeenFrom( + if (prefixTree == EmptyTree) macroDef.owner.tpe else prefixTree.tpe, + macroDef.owner) + } else + implRefTarg.tpe + macroLogVerbose("resolved tparam %s as %s".format(tparam, tpe)) + resolved(tparam) = tpe + param.tpe.typeSymbol match { + case definitions.AbsTypeTagClass => + // do nothing + case definitions.TypeTagClass => + if (!tpe.isConcrete) context.abort(context.enclosingPosition, "cannot create TypeTag from a type %s having unresolved type parameters".format(tpe)) + // otherwise do nothing + case _ => + throw new Error("unsupported tpe: " + tpe) + } + Some(tparam) + }) + val tags = paramss.last takeWhile (_.isType) map (resolved(_)) map (tpe => if (tpe.isConcrete) context.TypeTag(tpe) else context.AbsTypeTag(tpe)) + if (paramss.lastOption map (params => !params.isEmpty && params.forall(_.isType)) getOrElse false) argss = argss :+ Nil + argss = argss.dropRight(1) :+ (tags ++ argss.last) // todo. add support for context bounds in argss + + assert(argss.length == paramss.length, "argss: %s, paramss: %s".format(argss, paramss)) + val rawArgss = for ((as, ps) <- argss zip paramss) yield { + if (isVarArgsList(ps)) as.take(ps.length - 1) :+ as.drop(ps.length - 1) + else as + } + rawArgss } - Some(tparam) - }) - val tags = paramss.last takeWhile (_.isType) map (resolved(_)) map (tpe => { - // generally speaking, it's impossible to calculate erasure from a tpe here - // the tpe might be compiled by this run, so its jClass might not exist yet - // hence I just pass `null` instead and leave this puzzle to macro programmers - val ttag = TypeTag(tpe, null) - if (ttag.isConcrete) ttag.toConcrete else ttag - }) - if (paramss.lastOption map (params => !params.isEmpty && params.forall(_.isType)) getOrElse false) argss = argss :+ Nil - argss = argss.dropRight(1) :+ (tags ++ argss.last) // todo. add support for context bounds in argss - - assert(argss.length == paramss.length, "argss: %s, paramss: %s".format(argss, paramss)) - val rawArgss = for ((as, ps) <- argss zip paramss) yield { - if (isVarArgsList(ps)) as.take(ps.length - 1) :+ as.drop(ps.length - 1) - else as - } val rawArgs = rawArgss.flatten macroTraceVerbose("rawArgs: ")(rawArgs) Some(rawArgs) @@ -985,15 +942,17 @@ trait Macros extends Traces { def macroExpand(typer: Typer, expandee: Tree, mode: Int = EXPRmode, pt: Type = WildcardType): Tree = { def fail(what: String, tree: Tree): Tree = { val err = typer.context.errBuffer.head - this.fail(typer, tree, "failed to %s: %s at %s".format(what, err.errMsg, err.errPos)) + this.fail(typer, tree, err.errPos, "failed to %s: %s".format(what, err.errMsg)) return expandee } val start = startTimer(macroExpandNanos) incCounter(macroExpandCount) try { macroExpand1(typer, expandee) match { - case Success(expanded) => + case Success(expanded0) => try { + val expanded = expanded0 // virtpatmat swallows the local for expandee from the match + // so I added this dummy local for the ease of debugging var expectedTpe = expandee.tpe // [Eugene] weird situation. what's the conventional way to deal with it? @@ -1024,7 +983,7 @@ trait Macros extends Traces { if (typer.context.hasErrors) fail("typecheck against expected type", expanded) macroLogVerbose("typechecked2:%n%s%n%s".format(typechecked, showRaw(typechecked))) - typechecked + typechecked addAttachment MacroExpansionAttachment(expandee) } finally { openMacros = openMacros.tail } @@ -1046,11 +1005,11 @@ trait Macros extends Traces { private def Skip(expanded: Tree) = Other(expanded) private def Cancel(expandee: Tree) = Other(expandee) private def Failure(expandee: Tree) = Other(expandee) - private def fail(typer: Typer, expandee: Tree, msg: String = null) = { + private def fail(typer: Typer, expandee: Tree, pos: Position = NoPosition, msg: String = null) = { def msgForLog = if (msg != null && (msg contains "exception during macro expansion")) msg.split(EOL).drop(1).headOption.getOrElse("?") else msg macroLogLite("macro expansion has failed: %s".format(msgForLog)) - val pos = if (expandee.pos != NoPosition) expandee.pos else enclosingMacroPosition - if (msg != null) typer.context.error(pos, msg) + val errorPos = if (pos != NoPosition) pos else (if (expandee.pos != NoPosition) expandee.pos else enclosingMacroPosition) + if (msg != null) typer.context.error(errorPos, msg) typer.infer.setError(expandee) Failure(expandee) } @@ -1069,7 +1028,7 @@ trait Macros extends Traces { // if a macro implementation is incompatible or any of the arguments are erroneous // there is no sense to expand the macro itself => it will only make matters worse if (expandee.symbol.isErroneous || (expandee exists (_.isErroneous))) { - val reason = if (expandee.symbol.isErroneous) "incompatible macro implementation" else "erroneous arguments" + val reason = if (expandee.symbol.isErroneous) "not found or incompatible macro implementation" else "erroneous arguments" macroTraceVerbose("cancelled macro expansion because of %s: ".format(reason))(expandee) return Cancel(typer.infer.setError(expandee)) } @@ -1092,7 +1051,7 @@ trait Macros extends Traces { + "If you have troubles tracking free @kind@ variables, consider using -Xlog-free-@kind@s" ) val forgotten = ( - if (sym.isTerm) "eval when splicing this variable into a reifee" + if (sym.isTerm) "splice when splicing this variable into a reifee" else "c.TypeTag annotation for this type parameter" ) typer.context.error(expandee.pos, @@ -1105,7 +1064,7 @@ trait Macros extends Traces { val undetparams = calculateUndetparams(expandee) val nowDelayed = !typer.context.macrosEnabled || undetparams.nonEmpty - def failExpansion(msg: String = null) = fail(typer, expandee, msg) + def failExpansion(msg: String = null) = fail(typer, expandee, msg = msg) def performExpansion(args: List[Any]): MacroExpansionResult = { val numErrors = reporter.ERROR.count def hasNewErrors = reporter.ERROR.count > numErrors @@ -1119,8 +1078,8 @@ trait Macros extends Traces { macroLogVerbose("original:") macroLogLite("" + expanded.tree + "\n" + showRaw(expanded.tree)) - freeTerms(expanded.tree) foreach issueFreeError - freeTypes(expanded.tree) foreach issueFreeError + expanded.tree.freeTerms foreach issueFreeError + expanded.tree.freeTypes foreach issueFreeError if (hasNewErrors) failExpansion() // inherit the position from the first position-ful expandee in macro callstack @@ -1145,31 +1104,36 @@ trait Macros extends Traces { else { macroLogLite("typechecking macro expansion %s at %s".format(expandee, expandee.pos)) macroArgs(typer, expandee).fold(failExpansion(): MacroExpansionResult) { - case args @ ((context: MacroContext) :: _) => - if (nowDelayed) { - macroLogLite("macro expansion is delayed: %s".format(expandee)) - delayed += expandee -> undetparams - // need to save typer context for `macroExpandAll` - // need to save macro context to preserve enclosures - expandee attach MacroAttachment(delayed = true, typerContext = typer.context, macroContext = Some(context)) - Delay(expandee) - } - else { - // adding stuff to openMacros is easy, but removing it is a nightmare - // it needs to be sprinkled over several different code locations - // why? https://github.com/scala/scala/commit/bd3eacbae21f39b1ac7fe8ade4ed71fa98e1a28d#L2R1137 - // todo. will be improved - openMacros ::= context - var isSuccess = false - try performExpansion(args) match { - case x: Success => isSuccess = true ; x - case x => x + args => (args: @unchecked) match { + // [Eugene++] crashes virtpatmat: + // case args @ ((context: MacroContext) :: _) => + case args @ (context0 :: _) => + val context = context0.asInstanceOf[MacroContext] + if (nowDelayed) { + macroLogLite("macro expansion is delayed: %s".format(expandee)) + delayed += expandee -> undetparams + // need to save typer context for `macroExpandAll` + // need to save macro context to preserve enclosures + expandee addAttachment MacroRuntimeAttachment(delayed = true, typerContext = typer.context, macroContext = Some(context.asInstanceOf[MacroContext])) + Delay(expandee) } - finally { - expandee.detach(classOf[MacroAttachment]) - if (!isSuccess) openMacros = openMacros.tail + else { + // adding stuff to openMacros is easy, but removing it is a nightmare + // it needs to be sprinkled over several different code locations + // why? https://github.com/scala/scala/commit/bd3eacbae21f39b1ac7fe8ade4ed71fa98e1a28d#L2R1137 + // todo. will be improved + openMacros ::= context + var isSuccess = false + try performExpansion(args) match { + case x: Success => isSuccess = true ; x + case x => x + } + finally { + expandee.removeAttachment[MacroRuntimeAttachment] + if (!isSuccess) openMacros = openMacros.tail + } } - } + } } } } @@ -1257,7 +1221,7 @@ trait Macros extends Traces { None } } getOrElse realex.getMessage - fail(typer, expandee, "exception during macro expansion: " + message) + fail(typer, expandee, msg = "exception during macro expansion: " + message) } } @@ -1317,7 +1281,7 @@ trait Macros extends Traces { override def transform(tree: Tree) = super.transform(tree match { // todo. expansion should work from the inside out case wannabe if (delayed contains wannabe) && calculateUndetparams(wannabe).isEmpty => - val context = wannabe.attachment[MacroAttachment].typerContext + val context = wannabe.attachments.get[MacroRuntimeAttachment].get.typerContext delayed -= wannabe context.implicitsEnabled = typer.context.implicitsEnabled context.enrichmentEnabled = typer.context.enrichmentEnabled diff --git a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala index cf94f7d4d6..95d0369707 100644 --- a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala +++ b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala @@ -7,8 +7,9 @@ package typechecker import symtab.Flags._ import scala.collection.{ mutable, immutable } -import scala.tools.util.StringOps.{ ojoin } -import scala.reflect.{ mirror => rm } +import scala.reflect.internal.util.StringOps.{ ojoin } +import scala.reflect.ClassTag +import scala.reflect.runtime.{ universe => ru } import language.higherKinds /** Logic related to method synthesis which involves cooperation between @@ -22,15 +23,15 @@ trait MethodSynthesis { import CODE._ object synthesisUtil { - type CTT[T] = rm.ConcreteTypeTag[T] + type TT[T] = ru.TypeTag[T] type CT[T] = ClassTag[T] def ValOrDefDef(sym: Symbol, body: Tree) = if (sym.isLazy) ValDef(sym, body) else DefDef(sym, body) - def applyTypeInternal(tags: List[CTT[_]]): Type = { - // [Eugene to Paul] needs review!! + def applyTypeInternal(tags: List[TT[_]]): Type = { + // [Eugene++ to Paul] needs review!! val symbols = tags map compilerSymbolFromTag val container :: args = symbols val tparams = container.typeConstructor.typeParams @@ -44,26 +45,33 @@ trait MethodSynthesis { appliedType(container, args map (_.tpe): _*) } - def companionType[T](implicit m: CTT[T]) = - getRequiredModule(m.erasure.getName).tpe + def companionType[T](implicit ct: CT[T]) = + rootMirror.getRequiredModule(ct.runtimeClass.getName).tpe // Use these like `applyType[List, Int]` or `applyType[Map, Int, String]` - def applyType[CC](implicit m1: CTT[CC]): Type = - applyTypeInternal(List(m1)) - - def applyType[CC[X1], X1](implicit m1: CTT[CC[_]], m2: CTT[X1]): Type = - applyTypeInternal(List(m1, m2)) - - def applyType[CC[X1, X2], X1, X2](implicit m1: CTT[CC[_,_]], m2: CTT[X1], m3: CTT[X2]): Type = - applyTypeInternal(List(m1, m2, m3)) - - def applyType[CC[X1, X2, X3], X1, X2, X3](implicit m1: CTT[CC[_,_,_]], m2: CTT[X1], m3: CTT[X2], m4: CTT[X3]): Type = - applyTypeInternal(List(m1, m2, m3, m4)) - - def newMethodType[F](owner: Symbol)(implicit t: CTT[F]): Type = { + def applyType[CC](implicit t1: TT[CC]): Type = + applyTypeInternal(List(t1)) + + def applyType[CC[X1], X1](implicit t1: TT[CC[_]], t2: TT[X1]): Type = + applyTypeInternal(List[TT[_]](t1, t2)) + + def applyType[CC[X1, X2], X1, X2](implicit t1: TT[CC[_,_]], t2: TT[X1], t3: TT[X2]): Type = + // [Eugene++] without an explicit type annotation for List, we get this: + // [scalacfork] C:\Projects\KeplerUnderRefactoring\src\compiler\scala\tools\nsc\typechecker\MethodSynthesis.scala:59: error: no type parameters for method apply: (xs: A*)List[A] in object List exist so that it can be applied to arguments (scala.tools.nsc.typechecker.MethodSynthesis.synthesisUtil.TT[CC[_, _]], scala.tools.nsc.typechecker.MethodSynthesis.synthesisUtil.TT[X1], scala.tools.nsc.typechecker.MethodSynthesis.synthesisUtil.TT[X2]) + // [scalacfork] --- because --- + // [scalacfork] undetermined type + // [scalacfork] applyTypeInternal(List(t1, t2, t3)) + applyTypeInternal(List[TT[_]](t1, t2, t3)) + + def applyType[CC[X1, X2, X3], X1, X2, X3](implicit t1: TT[CC[_,_,_]], t2: TT[X1], t3: TT[X2], t4: TT[X3]): Type = + applyTypeInternal(List[TT[_]](t1, t2, t3, t4)) + + // [Martin->Eugene] !!! reinstantiate when typeables are in. + // [Eugene++->Martin] now this compiles, will soon check it out + def newMethodType[F](owner: Symbol)(implicit t: TT[F]): Type = { val fnSymbol = compilerSymbolFromTag(t) assert(fnSymbol isSubClass FunctionClass(t.tpe.typeArguments.size - 1), (owner, t)) - // [Eugene to Paul] needs review!! + // [Eugene++ to Paul] needs review!! // val symbols = m.typeArguments map (m => manifestToSymbol(m)) // val formals = symbols.init map (_.typeConstructor) val formals = compilerTypeFromTag(t).typeArguments diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 4eba665b93..decd18b599 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -313,7 +313,7 @@ trait Namers extends MethodSynthesis { /** All PackageClassInfoTypes come from here. */ private def createPackageSymbol(pos: Position, pid: RefTree): Symbol = { val pkgOwner = pid match { - case Ident(_) => if (owner == EmptyPackageClass) RootClass else owner + case Ident(_) => if (owner.isEmptyPackageClass) rootMirror.RootClass else owner case Select(qual: RefTree, _) => createPackageSymbol(pos, qual).moduleClass } val existing = pkgOwner.info.decls.lookup(pid.name) diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala index 932e4548ef..61443faba0 100644 --- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala +++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala @@ -9,6 +9,7 @@ package typechecker import symtab.Flags._ import scala.collection.mutable import scala.ref.WeakReference +import scala.reflect.ClassTag /** * @author Lukas Rytz @@ -39,14 +40,14 @@ trait NamesDefaults { self: Analyzer => def isNamed(arg: Tree) = nameOf(arg).isDefined /** @param pos maps indices from old to new */ - def reorderArgs[T: ArrayTag](args: List[T], pos: Int => Int): List[T] = { + def reorderArgs[T: ClassTag](args: List[T], pos: Int => Int): List[T] = { val res = new Array[T](args.length) foreachWithIndex(args)((arg, index) => res(pos(index)) = arg) res.toList } /** @param pos maps indices from new to old (!) */ - def reorderArgsInv[T: ArrayTag](args: List[T], pos: Int => Int): List[T] = { + def reorderArgsInv[T: ClassTag](args: List[T], pos: Int => Int): List[T] = { val argsArray = args.toArray (argsArray.indices map (i => argsArray(pos(i)))).toList } @@ -376,7 +377,7 @@ trait NamesDefaults { self: Analyzer => */ def addDefaults(givenArgs: List[Tree], qual: Option[Tree], targs: List[Tree], previousArgss: List[List[Tree]], params: List[Symbol], - pos: util.Position, context: Context): (List[Tree], List[Symbol]) = { + pos: scala.reflect.internal.util.Position, context: Context): (List[Tree], List[Symbol]) = { if (givenArgs.length < params.length) { val (missing, positional) = missingParams(givenArgs, params) if (missing forall (_.hasDefault)) { diff --git a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala index 48985213d1..68522c727f 100644 --- a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala +++ b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala @@ -53,11 +53,11 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL else noopTransformer // duplicated from CPSUtils (avoid dependency from compiler -> cps plugin...) - private lazy val MarkerCPSAdaptPlus = definitions.getClassIfDefined("scala.util.continuations.cpsPlus") - private lazy val MarkerCPSAdaptMinus = definitions.getClassIfDefined("scala.util.continuations.cpsMinus") - private lazy val MarkerCPSSynth = definitions.getClassIfDefined("scala.util.continuations.cpsSynth") + private lazy val MarkerCPSAdaptPlus = rootMirror.getClassIfDefined("scala.util.continuations.cpsPlus") + private lazy val MarkerCPSAdaptMinus = rootMirror.getClassIfDefined("scala.util.continuations.cpsMinus") + private lazy val MarkerCPSSynth = rootMirror.getClassIfDefined("scala.util.continuations.cpsSynth") private lazy val stripTriggerCPSAnns = List(MarkerCPSSynth, MarkerCPSAdaptMinus, MarkerCPSAdaptPlus) - private lazy val MarkerCPSTypes = definitions.getClassIfDefined("scala.util.continuations.cpsParam") + private lazy val MarkerCPSTypes = rootMirror.getClassIfDefined("scala.util.continuations.cpsParam") private lazy val strippedCPSAnns = MarkerCPSTypes :: stripTriggerCPSAnns private def removeCPSAdaptAnnotations(tp: Type) = tp filterAnnotations (ann => !(strippedCPSAnns exists (ann matches _))) @@ -204,7 +204,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL // the alternative to attaching the default case override would be to simply // append the default to the list of cases and suppress the unreachable case error that may arise (once we detect that...) - val matchFailGenOverride = match_ firstAttachment {case DefaultOverrideMatchAttachment(default) => ((scrut: Tree) => default)} + val matchFailGenOverride = match_.attachments.get[DefaultOverrideMatchAttachment].map{case DefaultOverrideMatchAttachment(default) => ((scrut: Tree) => default)} val selectorSym = freshSym(selector.pos, pureType(selectorTp)) setFlag SYNTH_CASE // pt = Any* occurs when compiling test/files/pos/annotDepMethType.scala with -Xexperimental @@ -1110,16 +1110,13 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL def matchFailGen = (matchFailGenOverride orElse Some(CODE.MATCHERROR(_: Tree))) // patmatDebug("combining cases: "+ (casesNoSubstOnly.map(_.mkString(" >> ")).mkString("{", "\n", "}"))) - def isSwitchAnnotation(tpe: Type) = tpe hasAnnotation SwitchClass - def isUncheckedAnnotation(tpe: Type) = tpe hasAnnotation UncheckedClass - val (unchecked, requireSwitch) = if (settings.XnoPatmatAnalysis.value) (true, false) else scrut match { case Typed(_, tpt) => - (isUncheckedAnnotation(tpt.tpe), + (treeInfo.isUncheckedAnnotation(tpt.tpe), // matches with two or fewer cases need not apply for switchiness (if-then-else will do) - isSwitchAnnotation(tpt.tpe) && casesNoSubstOnly.lengthCompare(2) > 0) + treeInfo.isSwitchAnnotation(tpt.tpe) && casesNoSubstOnly.lengthCompare(2) > 0) case _ => (false, false) } @@ -1488,7 +1485,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL // hashconsing trees (modulo value-equality) def unique(t: Tree, tpOverride: Type = NoType): Tree = - trees find (a => a.equalsStructure0(t)(sameValue)) match { + trees find (a => a.correspondsStructure(t)(sameValue)) match { case Some(orig) => orig // patmatDebug("unique: "+ (t eq orig, orig)); case _ => trees += t diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 6d9c9c4ce8..26cf246ed7 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -285,7 +285,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R def memberTp = self.memberType(member) def otherTp = self.memberType(other) def noErrorType = other.tpe != ErrorType && member.tpe != ErrorType - def isRootOrNone(sym: Symbol) = sym == RootClass || sym == NoSymbol + def isRootOrNone(sym: Symbol) = sym != null && sym.isRoot || sym == NoSymbol def isNeitherInClass = (member.owner != clazz) && (other.owner != clazz) def objectOverrideErrorMsg = ( "overriding " + other.fullLocationString + " with " + member.fullLocationString + ":\n" + @@ -1309,9 +1309,9 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R } List(tree1) } - case Import(_, _) => Nil - case DefDef(mods, _, _, _, _, _) if (mods hasFlag MACRO) => Nil - case _ => List(transform(tree)) + case Import(_, _) => Nil + case DefDef(mods, _, _, _, _, _) if (mods hasFlag MACRO) || (tree.symbol hasFlag MACRO) => Nil + case _ => List(transform(tree)) } /* Check whether argument types conform to bounds of type parameters */ @@ -1496,7 +1496,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R private def transformCaseApply(tree: Tree, ifNot: => Unit) = { val sym = tree.symbol - + def isClassTypeAccessible(tree: Tree): Boolean = tree match { case TypeApply(fun, targs) => isClassTypeAccessible(fun) @@ -1505,7 +1505,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R // the companion class is actually not a ClassSymbol, but a reference to an abstract type. module.symbol.companionClass.isClass } - + val doTransform = sym.isSourceMethod && sym.isCase && diff --git a/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala b/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala index 329a247106..190b18711c 100644 --- a/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala +++ b/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala @@ -1,10 +1,10 @@ package scala.tools.nsc package typechecker -import scala.reflect.makro.runtime.{Context => MacroContext} - trait StdAttachments { self: Analyzer => - case class MacroAttachment(delayed: Boolean, typerContext: Context, macroContext: Option[MacroContext]) + type UnaffiliatedMacroContext = scala.reflect.makro.runtime.Context + type MacroContext = UnaffiliatedMacroContext { val universe: self.global.type } + case class MacroRuntimeAttachment(delayed: Boolean, typerContext: Context, macroContext: Option[MacroContext]) }
\ No newline at end of file diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala index d327d9c397..daae69590f 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala @@ -246,7 +246,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT && sym.isProtected && sym.enclClass != currentClass && !sym.owner.isTrait - && (sym.owner.enclosingPackageClass != currentPackage) + && (sym.owner.enclosingPackageClass != currentClass.enclosingPackageClass) && (qual.symbol.info.member(sym.name) ne NoSymbol) ) if (shouldEnsureAccessor) { @@ -451,7 +451,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT && sym.isJavaDefined && !sym.isDefinedInPackage && !accessibleThroughSubclassing - && (sym.enclosingPackageClass != currentPackage) + && (sym.enclosingPackageClass != currentClass.enclosingPackageClass) && (sym.enclosingPackageClass == sym.accessBoundary(sym.enclosingPackageClass)) ) val host = hostForAccessorOf(sym, clazz) diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala index 6faa9a3cb7..f01e095856 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala @@ -63,7 +63,7 @@ trait SyntheticMethods extends ast.TreeDSL { // in the original order. def accessors = clazz.caseFieldAccessors sortBy { acc => originalAccessors indexWhere { orig => - (acc.name == orig.name) || (acc.name startsWith (orig.name append "$")) + (acc.name == orig.name) || (acc.name startsWith (orig.name append "$").asInstanceOf[Name]) // [Eugene++] why do we need this cast? } } val arity = accessors.size @@ -87,7 +87,7 @@ trait SyntheticMethods extends ast.TreeDSL { ) def forwardToRuntime(method: Symbol): Tree = - forwardMethod(method, getMember(ScalaRunTimeModule, method.name prepend "_"))(mkThis :: _) + forwardMethod(method, getMember(ScalaRunTimeModule, (method.name prepend "_").asInstanceOf[Name]))(mkThis :: _) // [Eugene++] why do we need this cast? def callStaticsMethod(name: String)(args: Tree*): Tree = { val method = termMember(RuntimeStaticsModule, name) diff --git a/src/compiler/scala/tools/nsc/typechecker/Taggings.scala b/src/compiler/scala/tools/nsc/typechecker/Taggings.scala deleted file mode 100644 index fb0d6fb3c5..0000000000 --- a/src/compiler/scala/tools/nsc/typechecker/Taggings.scala +++ /dev/null @@ -1,71 +0,0 @@ -package scala.tools.nsc -package typechecker - -trait Taggings { - self: Analyzer => - - import global._ - import definitions._ - - trait Tagging { - self: Typer => - - private def resolveTag(taggedTp: Type, pos: Position) = beforeTyper { - inferImplicit( - EmptyTree, - taggedTp, - /*reportAmbiguous =*/ true, - /*isView =*/ false, - /*context =*/ context, - /*saveAmbiguousDivergent =*/ true, - /*pos =*/ pos - ).tree - } - - /** Finds in scope or materializes an ArrayTag. - * Should be used instead of ClassTag or ClassManifest every time compiler needs to create an array. - * - * @param tp Type we're looking an ArrayTag for, e.g. resolveArrayTag(IntClass.tpe, pos) will look for ArrayTag[Int]. - * @param pos Position for error reporting. Please, provide meaningful value. - * - * @returns Tree that represents an `scala.reflect.ArrayTag` for `tp` if everything is okay. - * EmptyTree if the result contains unresolved (i.e. not spliced) type parameters and abstract type members. - */ - def resolveArrayTag(tp: Type, pos: Position): Tree = { - val taggedTp = appliedType(ArrayTagClass.typeConstructor, List(tp)) - resolveTag(taggedTp, pos) - } - - /** Finds in scope or materializes an ErasureTag (if `concrete` is false) or a ClassTag (if `concrete` is true). - * Should be used instead of ClassTag or ClassManifest every time compiler needs to persist an erasure. - * - * @param tp Type we're looking an ErasureTag for, e.g. resolveErasureTag(IntClass.tpe, pos, true) will look for ClassTag[Int]. - * @param pos Position for error reporting. Please, provide meaningful value. - * @param concrete If true then the result must not contain unresolved (i.e. not spliced) type parameters and abstract type members. - * If false then the function will always succeed (abstract types will be erased to their upper bounds). - * - * @returns Tree that represents an `scala.reflect.ErasureTag` for `tp` if everything is okay. - * EmptyTree if `concrete` is true and the result contains unresolved (i.e. not spliced) type parameters and abstract type members. - */ - def resolveErasureTag(tp: Type, pos: Position, concrete: Boolean): Tree = { - val taggedTp = appliedType(if (concrete) ClassTagClass.typeConstructor else ErasureTagClass.typeConstructor, List(tp)) - resolveTag(taggedTp, pos) - } - - /** Finds in scope or materializes a TypeTag (if `concrete` is false) or a ConcreteTypeTag (if `concrete` is true). - * - * @param pre Prefix that represents a universe this type tag will be bound to. - * @param tp Type we're looking a TypeTag for, e.g. resolveTypeTag(reflectMirrorPrefix, IntClass.tpe, pos, false) will look for scala.reflect.mirror.TypeTag[Int]. - * @param pos Position for error reporting. Please, provide meaningful value. - * @param concrete If true then the result must not contain unresolved (i.e. not spliced) type parameters and abstract type members. - * If false then the function will always succeed (abstract types will be reified as free types). - * - * @returns Tree that represents a `scala.reflect.TypeTag` for `tp` if everything is okay. - * EmptyTree if `concrete` is true and the result contains unresolved (i.e. not spliced) type parameters and abstract type members. - */ - def resolveTypeTag(pre: Type, tp: Type, pos: Position, concrete: Boolean): Tree = { - val taggedTp = appliedType(singleType(pre, pre member (if (concrete) ConcreteTypeTagClass else TypeTagClass).name), List(tp)) - resolveTag(taggedTp, pos) - } - } -}
\ No newline at end of file diff --git a/src/compiler/scala/tools/nsc/typechecker/Tags.scala b/src/compiler/scala/tools/nsc/typechecker/Tags.scala new file mode 100644 index 0000000000..052484e8e1 --- /dev/null +++ b/src/compiler/scala/tools/nsc/typechecker/Tags.scala @@ -0,0 +1,69 @@ +package scala.tools.nsc +package typechecker + +trait Tags { + self: Analyzer => + + import global._ + import definitions._ + + trait Tag { + self: Typer => + + private def resolveTag(pos: Position, taggedTp: Type, allowMaterialization: Boolean) = beforeTyper { + def wrapper (tree: => Tree): Tree = if (allowMaterialization) (context.withMacrosEnabled[Tree](tree)) else (context.withMacrosDisabled[Tree](tree)) + wrapper(inferImplicit( + EmptyTree, + taggedTp, + /*reportAmbiguous =*/ true, + /*isView =*/ false, + /*context =*/ context, + /*saveAmbiguousDivergent =*/ true, + /*pos =*/ pos + ).tree) + } + + /** Finds in scope or materializes a ClassTag. + * Should be used instead of ClassManifest every time compiler needs to persist an erasure. + * + * Once upon a time, we had an `ErasureTag` which was to `ClassTag` the same that `AbsTypeTag` is for `TypeTag`. + * However we found out that we don't really need this concept, so it got removed. + * + * @param pos Position for error reporting. Please, provide meaningful value. + * @param tp Type we're looking a ClassTag for, e.g. resolveClassTag(pos, IntClass.tpe) will look for ClassTag[Int]. + * @param allowMaterialization If true (default) then the resolver is allowed to launch materialization macros when there's no class tag in scope. + * If false then materialization macros are prohibited from running. + * + * @returns Tree that represents an `scala.reflect.ClassTag` for `tp` if everything is okay. + * EmptyTree if the result contains unresolved (i.e. not spliced) type parameters and abstract type members. + * EmptyTree if `allowMaterialization` is false, and there is no class tag in scope. + */ + def resolveClassTag(pos: Position, tp: Type, allowMaterialization: Boolean = true): Tree = { + val taggedTp = appliedType(ClassTagClass.typeConstructor, List(tp)) + resolveTag(pos, taggedTp, allowMaterialization) + } + + /** Finds in scope or materializes an AbsTypeTag (if `concrete` is false) or a TypeTag (if `concrete` is true). + * + * @param pos Position for error reporting. Please, provide meaningful value. + * @param pre Prefix that represents a universe this type tag will be bound to. + * If `pre` is set to `NoType`, then any type tag in scope will do, regardless of its affiliation. + * If `pre` is set to `NoType`, and tag resolution involves materialization, then `mkBasisPrefix` will be used. + * @param tp Type we're looking a TypeTag for, e.g. resolveTypeTag(pos, reflectBasisPrefix, IntClass.tpe, false) will look for scala.reflect.basis.TypeTag[Int]. + * @param concrete If true then the result must not contain unresolved (i.e. not spliced) type parameters and abstract type members. + * If false then the function will always succeed (abstract types will be reified as free types). + * @param allowMaterialization If true (default) then the resolver is allowed to launch materialization macros when there's no type tag in scope. + * If false then materialization macros are prohibited from running. + * + * @returns Tree that represents a `scala.reflect.TypeTag` for `tp` if everything is okay. + * EmptyTree if `concrete` is true and the result contains unresolved (i.e. not spliced) type parameters and abstract type members. + * EmptyTree if `allowMaterialization` is false, and there is no array tag in scope. + */ + def resolveTypeTag(pos: Position, pre: Type, tp: Type, concrete: Boolean, allowMaterialization: Boolean = true): Tree = { + val tagSym = if (concrete) TypeTagClass else AbsTypeTagClass + val tagTp = if (pre == NoType) TypeRef(BaseUniverseClass.asTypeConstructor, tagSym, List(tp)) else singleType(pre, pre member tagSym.name) + val taggedTp = appliedType(tagTp, List(tp)) + resolveTag(pos, taggedTp, allowMaterialization) + } + } +}
\ No newline at end of file diff --git a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala index fde760c752..b0956446a7 100644 --- a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala @@ -272,7 +272,7 @@ abstract class TreeCheckers extends Analyzer { tree match { case x: PackageDef => - if ((sym.ownerChain contains currentOwner) || currentOwner == definitions.EmptyPackageClass) () + if ((sym.ownerChain contains currentOwner) || currentOwner.isEmptyPackageClass) () else fail(sym + " owner chain does not contain currentOwner " + currentOwner + sym.ownerChain) case _ => def cond(s: Symbol) = !s.isTerm || s.isMethod || s == sym.owner diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index b0f6e44e88..2a1af2755f 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -13,7 +13,7 @@ package scala.tools.nsc package typechecker import scala.collection.mutable -import scala.tools.nsc.util.BatchSourceFile +import scala.reflect.internal.util.BatchSourceFile import mutable.ListBuffer import symtab.Flags._ import util.Statistics @@ -26,7 +26,7 @@ import util.Statistics._ * @author Martin Odersky * @version 1.0 */ -trait Typers extends Modes with Adaptations with Taggings { +trait Typers extends Modes with Adaptations with Tags { self: Analyzer => import global._ @@ -96,7 +96,7 @@ trait Typers extends Modes with Adaptations with Taggings { // this is disabled by: -Xoldpatmat, scaladoc or interactive compilation @inline private def newPatternMatching = opt.virtPatmat && !forScaladoc && !forInteractive // && (phase.id < currentRun.uncurryPhase.id) - abstract class Typer(context0: Context) extends TyperDiagnostics with Adaptation with Tagging with TyperContextErrors { + abstract class Typer(context0: Context) extends TyperDiagnostics with Adaptation with Tag with TyperContextErrors { import context0.unit import typeDebug.{ ptTree, ptBlock, ptLine } import TyperErrorGen._ @@ -237,7 +237,9 @@ trait Typers extends Modes with Adaptations with Taggings { * @return ... */ def checkStable(tree: Tree): Tree = - if (treeInfo.isExprSafeToInline(tree)) tree else UnstableTreeError(tree) + if (treeInfo.isExprSafeToInline(tree)) tree + else if (tree.isErrorTyped) tree + else UnstableTreeError(tree) /** Would tree be a stable (i.e. a pure expression) if the type * of its symbol was not volatile? @@ -903,6 +905,10 @@ trait Typers extends Modes with Adaptations with Taggings { def adaptType(): Tree = { if (inFunMode(mode)) { + // [Eugene++] the commented line below makes sense for typechecking, say, TypeApply(Ident(`some abstract type symbol`), List(...)) + // because otherwise Ident will have its tpe set to a TypeRef, not to a PolyType, and `typedTypeApply` will fail + // but this needs additional investigation, because it crashes t5228, gadts1 and maybe something else + // tree setType tree.tpe.normalize tree } else if (tree.hasSymbol && !tree.symbol.typeParams.isEmpty && !inHKMode(mode) && !(tree.symbol.isJavaDefined && context.unit.isJava)) { // (7) @@ -960,12 +966,21 @@ trait Typers extends Modes with Adaptations with Taggings { * see test/files/../t5189*.scala */ def adaptConstrPattern(): Tree = { // (5) - def isExtractor(sym: Symbol) = reallyExists(unapplyMember(sym.tpe)) - val extractor = tree.symbol filter isExtractor + def hasUnapplyMember(tp: Type) = reallyExists(unapplyMember(tp)) + val overloadedExtractorOfObject = tree.symbol filter (sym => hasUnapplyMember(sym.tpe)) + // if the tree's symbol's type does not define an extractor, maybe the tree's type does + // this is the case when we encounter an arbitrary tree as the target of an unapply call (rather than something that looks like a constructor call) + // (for now, this only happens due to wrapClassTagUnapply, but when we support parameterized extractors, it will become more common place) + val extractor = overloadedExtractorOfObject orElse unapplyMember(tree.tpe) if (extractor != NoSymbol) { - tree setSymbol extractor + // if we did some ad-hoc overloading resolution, update the tree's symbol + // do not update the symbol if the tree's symbol's type does not define an unapply member + // (e.g. since it's some method that returns an object with an unapply member) + if (overloadedExtractorOfObject != NoSymbol) + tree setSymbol overloadedExtractorOfObject + tree.tpe match { - case OverloadedType(pre, alts) => tree.tpe = overloadedType(pre, alts filter isExtractor) + case OverloadedType(pre, alts) => tree.tpe = overloadedType(pre, alts filter (alt => hasUnapplyMember(alt.tpe))) case _ => } val unapply = unapplyMember(extractor.tpe) @@ -1350,20 +1365,21 @@ trait Typers extends Modes with Adaptations with Taggings { if (!clazz.isStatic) unit.error(clazz.pos, "value class may not be a "+ (if (clazz.owner.isTerm) "local class" else "member of another class")) - val constr = clazz.primaryConstructor - clazz.info.decls.toList.filter(acc => acc.isMethod && (acc hasFlag PARAMACCESSOR)) match { - case List(acc) => - def isUnderlyingAcc(sym: Symbol) = - sym == acc || acc.hasAccessorFlag && sym == acc.accessed - if (acc.accessBoundary(clazz) != RootClass) - unit.error(acc.pos, "value class needs to have a publicly accessible val parameter") - for (stat <- body) - if (!treeInfo.isAllowedInUniversalTrait(stat) && !isUnderlyingAcc(stat.symbol)) - unit.error(stat.pos, - if (stat.symbol hasFlag PARAMACCESSOR) "illegal parameter for value class" - else "this statement is not allowed in value class: "+stat) - case x => - unit.error(clazz.pos, "value class needs to have exactly one public val parameter") + if (!clazz.isPrimitiveValueClass) { + clazz.info.decls.toList.filter(acc => acc.isMethod && (acc hasFlag PARAMACCESSOR)) match { + case List(acc) => + def isUnderlyingAcc(sym: Symbol) = + sym == acc || acc.hasAccessorFlag && sym == acc.accessed + if (acc.accessBoundary(clazz) != rootMirror.RootClass) + unit.error(acc.pos, "value class needs to have a publicly accessible val parameter") + for (stat <- body) + if (!treeInfo.isAllowedInUniversalTrait(stat) && !isUnderlyingAcc(stat.symbol)) + unit.error(stat.pos, + if (stat.symbol hasFlag PARAMACCESSOR) "illegal parameter for value class" + else "this statement is not allowed in value class: " + stat) + case x => + unit.error(clazz.pos, "value class needs to have exactly one public val parameter") + } } for (tparam <- clazz.typeParams) if (tparam hasAnnotation definitions.SpecializedClass) @@ -1729,7 +1745,7 @@ trait Typers extends Modes with Adaptations with Taggings { val body1 = typedStats(body, templ.symbol) - if (clazz.isDerivedValueClass) + if (clazz.info.firstParent.typeSymbol == AnyValClass) validateDerivedValueClass(clazz, body1) treeCopy.Template(templ, parents1, self1, body1) setType clazz.tpe @@ -2309,7 +2325,7 @@ trait Typers extends Modes with Adaptations with Taggings { import CODE._ // need to duplicate the cases before typing them to generate the apply method, or the symbols will be all messed up - val casesTrue = if (isPartial) cases map (c => deriveCaseDef(c)(x => atPos(x.pos.focus)(TRUE_typed)).duplicate) else Nil + val casesTrue = if (isPartial) cases map (c => deriveCaseDef(c)(x => atPos(x.pos.focus)(TRUE_typed)).duplicate.asInstanceOf[CaseDef]) else Nil // println("casesTrue "+ casesTrue) def parentsPartial(targs: List[Type]) = addSerializable(appliedType(AbstractPartialFunctionClass.typeConstructor, targs)) @@ -2377,7 +2393,7 @@ trait Typers extends Modes with Adaptations with Taggings { match_ setType B1.tpe // the default uses applyOrElse's first parameter since the scrut's type has been widened - val body = methodBodyTyper.virtualizedMatch(match_ withAttachment DefaultOverrideMatchAttachment(REF(default) APPLY (REF(x))), mode, B1.tpe) + val body = methodBodyTyper.virtualizedMatch(match_ addAttachment DefaultOverrideMatchAttachment(REF(default) APPLY (REF(x))), mode, B1.tpe) DefDef(methodSym, body) } @@ -2395,7 +2411,7 @@ trait Typers extends Modes with Adaptations with Taggings { methodSym setInfoAndEnter MethodType(paramSyms, BooleanClass.tpe) val match_ = methodBodyTyper.typedMatch(gen.mkUnchecked(selector), casesTrue, mode, BooleanClass.tpe) - val body = methodBodyTyper.virtualizedMatch(match_ withAttachment DefaultOverrideMatchAttachment(FALSE_typed), mode, BooleanClass.tpe) + val body = methodBodyTyper.virtualizedMatch(match_ addAttachment DefaultOverrideMatchAttachment(FALSE_typed), mode, BooleanClass.tpe) DefDef(methodSym, body) } @@ -2506,11 +2522,18 @@ trait Typers extends Modes with Adaptations with Taggings { } } - def typedRefinement(stats: List[Tree]) { + def typedRefinement(templ: Template) { + val stats = templ.body namer.enterSyms(stats) // need to delay rest of typedRefinement to avoid cyclic reference errors unit.toCheck += { () => val stats1 = typedStats(stats, NoSymbol) + // this code kicks in only after typer, so `stats` will never be filled in time + // as a result, most of compound type trees with non-empty stats will fail to reify + // [Eugene++] todo. investigate whether something can be done about this + val att = templ.attachments.get[CompoundTypeTreeOriginalAttachment].getOrElse(CompoundTypeTreeOriginalAttachment(Nil, Nil)) + templ.removeAttachment[CompoundTypeTreeOriginalAttachment] + templ addAttachment att.copy(stats = stats1) for (stat <- stats1 if stat.isDef) { val member = stat.symbol if (!(context.owner.ancestors forall @@ -3028,9 +3051,21 @@ trait Typers extends Modes with Adaptations with Taggings { case ErrorType => if (!tree.isErrorTyped) setError(tree) else tree // @H change to setError(treeCopy.Apply(tree, fun, args)) - /* --- begin unapply --- */ case otpe if inPatternMode(mode) && unapplyMember(otpe).exists => + doTypedUnapply(tree, fun0, fun, args, mode, pt) + + case _ => + duplErrorTree(ApplyWithoutArgsError(tree, fun)) + } + } + + def doTypedUnapply(tree: Tree, fun0: Tree, fun: Tree, args: List[Tree], mode: Int, pt: Type): Tree = { + def duplErrTree = setError(treeCopy.Apply(tree, fun0, args)) + def duplErrorTree(err: AbsTypeError) = { issue(err); duplErrTree } + + val otpe = fun.tpe + if (args.length > MaxTupleArity) return duplErrorTree(TooManyArgsPatternError(fun)) @@ -3054,6 +3089,11 @@ trait Typers extends Modes with Adaptations with Taggings { val argDummy = context.owner.newValue(nme.SELECTOR_DUMMY, fun.pos, SYNTHETIC) setInfo pt val arg = Ident(argDummy) setType pt + val uncheckedTypeExtractor = + if (unappType.paramTypes.nonEmpty) + extractorForUncheckedType(tree.pos, unappType.paramTypes.head) + else None + if (!isApplicableSafe(Nil, unappType, List(pt), WildcardType)) { //Console.println("UNAPP: need to typetest, arg.tpe = "+arg.tpe+", unappType = "+unappType) val (freeVars, unappFormal) = freshArgType(unappType.skolemizeExistential(context.owner, tree)) @@ -3061,7 +3101,7 @@ trait Typers extends Modes with Adaptations with Taggings { freeVars foreach unapplyContext.scope.enter val typer1 = newTyper(unapplyContext) - val pattp = typer1.infer.inferTypedPattern(tree, unappFormal, arg.tpe) + val pattp = typer1.infer.inferTypedPattern(tree, unappFormal, arg.tpe, canRemedy = uncheckedTypeExtractor.nonEmpty) // turn any unresolved type variables in freevars into existential skolems val skolems = freeVars map (fv => unapplyContext.owner.newExistentialSkolem(fv, fv)) @@ -3086,15 +3126,58 @@ trait Typers extends Modes with Adaptations with Taggings { val itype = glb(List(pt1, arg.tpe)) arg.tpe = pt1 // restore type (arg is a dummy tree, just needs to pass typechecking) - UnApply(fun1, args1) setPos tree.pos setType itype + val unapply = UnApply(fun1, args1) setPos tree.pos setType itype + + // if the type that the unapply method expects for its argument is uncheckable, wrap in classtag extractor + // skip if the unapply's type is not a method type with (at least, but really it should be exactly) one argument + // also skip if we already wrapped a classtag extractor (so we don't keep doing that forever) + if (uncheckedTypeExtractor.isEmpty || fun1.symbol.owner.isNonBottomSubClass(ClassTagClass)) unapply + else wrapClassTagUnapply(unapply, uncheckedTypeExtractor.get, unappType.paramTypes.head) } else duplErrorTree(WrongNumberArgsPatternError(tree, fun)) } + } -/* --- end unapply --- */ - case _ => - duplErrorTree(ApplyWithoutArgsError(tree, fun)) + def wrapClassTagUnapply(uncheckedPattern: Tree, classTagExtractor: Tree, pt: Type): Tree = { + // TODO: disable when in unchecked match + // we don't create a new Context for a Match, so find the CaseDef, then go out one level and navigate back to the match that has this case + // val thisCase = context.nextEnclosing(_.tree.isInstanceOf[CaseDef]) + // val unchecked = thisCase.outer.tree.collect{case Match(selector, cases) if cases contains thisCase => selector} match { + // case List(Typed(_, tpt)) if treeInfo.isUncheckedAnnotation(tpt.tpe) => true + // case t => println("outer tree: "+ (t, thisCase, thisCase.outer.tree)); false + // } + // println("wrapClassTagUnapply"+ (!isPastTyper && infer.containsUnchecked(pt), pt, uncheckedPattern)) + // println("wrapClassTagUnapply: "+ extractor) + // println(util.Position.formatMessage(uncheckedPattern.pos, "made unchecked type test into a checked one", true)) + + val args = List(uncheckedPattern) + // must call doTypedUnapply directly, as otherwise we get undesirable rewrites + // and re-typechecks of the target of the unapply call in PATTERNmode, + // this breaks down when the classTagExtractor (which defineds the unapply member) is not a simple reference to an object, + // but an arbitrary tree as is the case here + doTypedUnapply(Apply(classTagExtractor, args), classTagExtractor, classTagExtractor, args, PATTERNmode, pt) } + + // if there's a ClassTag that allows us to turn the unchecked type test for `pt` into a checked type test + // return the corresponding extractor (an instance of ClassTag[`pt`]) + def extractorForUncheckedType(pos: Position, pt: Type): Option[Tree] = if (!opt.virtPatmat || isPastTyper) None else { + // only look at top-level type, can't (reliably) do anything about unchecked type args (in general) + pt.normalize.typeConstructor match { + // if at least one of the types in an intersection is checkable, use the checkable ones + // this avoids problems as in run/matchonseq.scala, where the expected type is `Coll with scala.collection.SeqLike` + // Coll is an abstract type, but SeqLike of course is not + case RefinedType(parents, _) if (parents.length >= 2) && (parents.exists(tp => !infer.containsUnchecked(tp))) => + None + + case ptCheckable if infer.containsUnchecked(ptCheckable) => + val classTagExtractor = resolveClassTag(pos, ptCheckable) + + if (classTagExtractor != EmptyTree && unapplyMember(classTagExtractor.tpe) != NoSymbol) + Some(classTagExtractor) + else None + + case _ => None + } } /** @@ -3145,7 +3228,7 @@ trait Typers extends Modes with Adaptations with Taggings { if (annInfo.atp.isErroneous) { hasError = true; None } else Some(NestedAnnotArg(annInfo)) - // use of Array.apply[T: ArrayTag](xs: T*): Array[T] + // use of Array.apply[T: ClassTag](xs: T*): Array[T] // and Array.apply(x: Int, xs: Int*): Array[Int] (and similar) case Apply(fun, args) => val typedFun = typed(fun, forFunMode(mode), WildcardType) @@ -3537,7 +3620,7 @@ trait Typers extends Modes with Adaptations with Taggings { typedClassOf(tree, args.head, true) else { if (!isPastTyper && fun.symbol == Any_isInstanceOf && !targs.isEmpty) - checkCheckable(tree, targs.head, "") + checkCheckable(tree, targs.head, inPattern = false) val resultpe = restpe.instantiateTypeParams(tparams, targs) //@M substitution in instantiateParams needs to be careful! //@M example: class Foo[a] { def foo[m[x]]: m[a] = error("") } (new Foo[Int]).foo[List] : List[Int] @@ -3631,7 +3714,7 @@ trait Typers extends Modes with Adaptations with Taggings { case t => (t, Nil) } - @inline def hasNamedArg(as: List[Tree]) = as collectFirst {case AssignOrNamedArg(lhs, rhs) =>} nonEmpty + @inline def hasNamedArg(as: List[Tree]) = as.collectFirst{case AssignOrNamedArg(lhs, rhs) =>}.nonEmpty // note: context.tree includes at most one Apply node // thus, we can't use it to detect we're going to receive named args in expressions such as: @@ -3651,7 +3734,7 @@ trait Typers extends Modes with Adaptations with Taggings { } val dynSel = Select(qual, oper) - val tappSel = if (explicitTargs nonEmpty) TypeApply(dynSel, explicitTargs) else dynSel + val tappSel = if (explicitTargs.nonEmpty) TypeApply(dynSel, explicitTargs) else dynSel atPos(qual.pos)(Apply(tappSel, List(Literal(Constant(name.decode))))) } @@ -3688,11 +3771,10 @@ trait Typers extends Modes with Adaptations with Taggings { // hence we go the extra mile to hand-craft tis guy val original = if (arg1.isType) - (tree, arg1) match { - case (Annotated(annot, arg), tt @ TypeTree()) => Annotated(annot, tt.original) + arg1 match { + case tt @ TypeTree() => Annotated(ann, tt.original) // this clause is needed to correctly compile stuff like "new C @D" or "@(inline @getter)" - case (Annotated(annot, arg), _) => Annotated(annot, arg1) - case _ => throw new Error("unexpected trees in typedAnnotated: tree = %s, arg1 = %s".format(showRaw(tree), showRaw(arg1))) + case _ => Annotated(ann, arg1) } else tree @@ -4397,7 +4479,7 @@ trait Typers extends Modes with Adaptations with Taggings { // last ditch effort before failing. This method sets defSym and returns // true if a member of the given name exists. def checkEmptyPackage(): Boolean = { - defSym = EmptyPackageClass.tpe.nonPrivateMember(name) + defSym = rootMirror.EmptyPackageClass.tpe.nonPrivateMember(name) defSym != NoSymbol } def startingIdentContext = ( @@ -4525,7 +4607,7 @@ trait Typers extends Modes with Adaptations with Taggings { log("Allowing empty package member " + name + " due to settings.") else { if ((mode & QUALmode) != 0) { - val lastTry = missingHook(RootClass, name) + val lastTry = missingHook(rootMirror.RootClass, name) if (lastTry != NoSymbol) return typed1(tree setSymbol lastTry, mode, pt) } if (settings.debug.value) { @@ -4579,7 +4661,8 @@ trait Typers extends Modes with Adaptations with Taggings { val decls = newScope //Console.println("Owner: " + context.enclClass.owner + " " + context.enclClass.owner.id) val self = refinedType(parents1 map (_.tpe), context.enclClass.owner, decls, templ.pos) - newTyper(context.make(templ, self.typeSymbol, decls)).typedRefinement(templ.body) + newTyper(context.make(templ, self.typeSymbol, decls)).typedRefinement(templ) + templ addAttachment CompoundTypeTreeOriginalAttachment(parents1, Nil) // stats are set elsewhere tree setType self } } @@ -4794,10 +4877,21 @@ trait Typers extends Modes with Adaptations with Taggings { } case Typed(expr, tpt) => - val tpt1 = typedType(tpt, mode) - val expr1 = typed(expr, onlyStickyModes(mode), tpt1.tpe.deconst) - val ownType = if (isPatternMode) inferTypedPattern(tpt1, tpt1.tpe, pt) else tpt1.tpe - treeCopy.Typed(tree, expr1, tpt1) setType ownType + val tptTyped = typedType(tpt, mode) + val exprTyped = typed(expr, onlyStickyModes(mode), tptTyped.tpe.deconst) + val treeTyped = treeCopy.Typed(tree, exprTyped, tptTyped) + + if (isPatternMode) { + val uncheckedTypeExtractor = extractorForUncheckedType(tpt.pos, tptTyped.tpe) + val ownType = inferTypedPattern(tptTyped, tptTyped.tpe, pt, canRemedy = uncheckedTypeExtractor.nonEmpty) + treeTyped setType ownType + + uncheckedTypeExtractor match { + case None => treeTyped + case Some(extractor) => wrapClassTagUnapply(treeTyped, extractor, tptTyped.tpe) + } + } else + treeTyped setType tptTyped.tpe case TypeApply(fun, args) => // @M: kind-arity checking is done here and in adapt, full kind-checking is in checkKindBounds (in Infer) @@ -4851,8 +4945,8 @@ trait Typers extends Modes with Adaptations with Taggings { val Some((level, componentType)) = erasure.GenericArray.unapply(tpt.tpe) val tagType = List.iterate(componentType, level)(tpe => appliedType(ArrayClass.asType, List(tpe))).last val newArrayApp = atPos(tree.pos) { - val tag = resolveArrayTag(tagType, tree.pos) - if (tag.isEmpty) MissingArrayTagError(tree, tagType) + val tag = resolveClassTag(tree.pos, tagType) + if (tag.isEmpty) MissingClassTagError(tree, tagType) else new ApplyToImplicitArgs(Select(tag, nme.newArray), args) } typed(newArrayApp, mode, pt) @@ -4861,6 +4955,7 @@ trait Typers extends Modes with Adaptations with Taggings { } case ApplyDynamic(qual, args) => + assert(phase.erasedTypes) val reflectiveCalls = !(settings.refinementMethodDispatch.value == "invoke-dynamic") val qual1 = typed(qual, AnyRefClass.tpe) val args1 = args mapConserve (arg => if (reflectiveCalls) typed(arg, AnyRefClass.tpe) else typed(arg)) @@ -4907,7 +5002,7 @@ trait Typers extends Modes with Adaptations with Taggings { if (tree1.symbol != null && tree1.symbol.isOnlyRefinementMember) checkFeature(tree1.pos, ReflectiveCallsFeature, tree1.symbol.toString) - if (qual1.symbol == RootPackage) treeCopy.Ident(tree1, name) + if (qual1.hasSymbolWhich(_.isRootPackage)) treeCopy.Ident(tree1, name) else tree1 case Ident(name) => @@ -5208,7 +5303,8 @@ trait Typers extends Modes with Adaptations with Taggings { } val isMacroBodyOkay = !tree.symbol.isErroneous && !(tree1 exists (_.isErroneous)) - if (isMacroBodyOkay) computeMacroDefTypeFromMacroImpl(ddef, tree.symbol, tree1.symbol) else AnyClass.tpe + val shouldInheritMacroImplReturnType = ddef.tpt.isEmpty + if (isMacroBodyOkay && shouldInheritMacroImplReturnType) computeMacroDefTypeFromMacroImpl(ddef, tree.symbol, tree1.symbol) else AnyClass.tpe } def transformedOr(tree: Tree, op: => Tree): Tree = transformed.get(tree) match { diff --git a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala index d75e2705c3..4c20d14406 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala @@ -224,7 +224,10 @@ trait Unapplies extends ast.TreeDSL case Nil => Nil case ps :: _ => mmap(ps :: funParamss)(toIdent) } - val body = funParamss.foldRight(New(classTpe, argss): Tree)(Function) + def mkFunction(vparams: List[ValDef], body: Tree) = Function(vparams, body) + val body = funParamss.foldRight(New(classTpe, argss): Tree)(mkFunction) + // [Eugene++] no longer compiles after I moved the `Function` case class into scala.reflect.internal + // val body = funParamss.foldRight(New(classTpe, argss): Tree)(Function) Some(atPos(cdef.pos.focus)( DefDef(Modifiers(SYNTHETIC), nme.copy, tparams, copyParamss, bodyTpe, diff --git a/src/compiler/scala/tools/nsc/util/ClassPath.scala b/src/compiler/scala/tools/nsc/util/ClassPath.scala index 472b5180b4..9755fb6c60 100644 --- a/src/compiler/scala/tools/nsc/util/ClassPath.scala +++ b/src/compiler/scala/tools/nsc/util/ClassPath.scala @@ -10,7 +10,8 @@ package util import java.net.URL import scala.collection.{ mutable, immutable } import io.{ File, Directory, Path, Jar, AbstractFile } -import scala.tools.util.StringOps.splitWhere +import scala.reflect.internal.util.StringOps.splitWhere +import scala.reflect.ClassTag import Jar.isJarOrZip import File.pathSeparator import java.net.MalformedURLException diff --git a/src/compiler/scala/tools/nsc/util/Exceptional.scala b/src/compiler/scala/tools/nsc/util/Exceptional.scala index 7c093b7866..90d032518a 100644 --- a/src/compiler/scala/tools/nsc/util/Exceptional.scala +++ b/src/compiler/scala/tools/nsc/util/Exceptional.scala @@ -3,7 +3,7 @@ package util import java.util.concurrent.ExecutionException import java.lang.reflect.{ InvocationTargetException, UndeclaredThrowableException } -import scala.tools.util.StringOps._ +import scala.reflect.internal.util.StringOps._ import language.implicitConversions object Exceptional { diff --git a/src/compiler/scala/tools/nsc/util/FreshNameCreator.scala b/src/compiler/scala/tools/nsc/util/FreshNameCreator.scala index 88fc6718a2..16bf748414 100644 --- a/src/compiler/scala/tools/nsc/util/FreshNameCreator.scala +++ b/src/compiler/scala/tools/nsc/util/FreshNameCreator.scala @@ -16,9 +16,9 @@ trait FreshNameCreator { def newName(prefix: String): String @deprecated("use newName(prefix)", "2.9.0") - def newName(pos: util.Position, prefix: String): String = newName(prefix) + def newName(pos: scala.reflect.internal.util.Position, prefix: String): String = newName(prefix) @deprecated("use newName()", "2.9.0") - def newName(pos: util.Position): String = newName() + def newName(pos: scala.reflect.internal.util.Position): String = newName() } object FreshNameCreator { diff --git a/src/compiler/scala/tools/nsc/util/ScalaClassLoader.scala b/src/compiler/scala/tools/nsc/util/ScalaClassLoader.scala index 4c7920d6b3..5b30d9aacd 100644 --- a/src/compiler/scala/tools/nsc/util/ScalaClassLoader.scala +++ b/src/compiler/scala/tools/nsc/util/ScalaClassLoader.scala @@ -11,10 +11,11 @@ import java.lang.reflect.{ Constructor, Modifier, Method } import java.io.{ File => JFile } import java.net.{ URLClassLoader => JURLClassLoader } import java.net.URL -import scala.reflect.ReflectionUtils.unwrapHandler +import scala.reflect.runtime.ReflectionUtils.unwrapHandler import ScalaClassLoader._ import scala.util.control.Exception.{ catching } import language.implicitConversions +import scala.reflect.{ ClassTag, classTag } trait HasClassPath { def classPathURLs: Seq[URL] @@ -46,7 +47,7 @@ trait ScalaClassLoader extends JClassLoader { tryToInitializeClass[AnyRef](path) map (_.newInstance()) orNull def constructorsOf[T <: AnyRef : ClassTag]: List[Constructor[T]] = - classTag[T].erasure.getConstructors.toList map (_.asInstanceOf[Constructor[T]]) + classTag[T].runtimeClass.getConstructors.toList map (_.asInstanceOf[Constructor[T]]) /** The actual bytes for a class file, or an empty array if it can't be found. */ def classBytes(className: String): Array[Byte] = classAsStream(className) match { @@ -102,7 +103,7 @@ object ScalaClassLoader { def bootLoader = apply(null) def contextChain = loaderChain(contextLoader) - def pathToErasure[T: ClassTag] = pathToClass(classTag[T].erasure) + def pathToErasure[T: ClassTag] = pathToClass(classTag[T].runtimeClass) def pathToClass(clazz: Class[_]) = clazz.getName.replace('.', JFile.separatorChar) + ".class" def locate[T: ClassTag] = contextLoader getResource pathToErasure[T] diff --git a/src/compiler/scala/tools/nsc/util/Statistics.scala b/src/compiler/scala/tools/nsc/util/Statistics.scala index 53ab6654ee..087111a7ba 100644 --- a/src/compiler/scala/tools/nsc/util/Statistics.scala +++ b/src/compiler/scala/tools/nsc/util/Statistics.scala @@ -138,6 +138,8 @@ abstract class StatisticsInfo { inform(" of which in app impl : " + subtypeAppInfos) inform(" of which in improv : " + subtypeImprovCount) inform("#sametype : " + sametypeCount) + inform("#toplevel lub : " + lubCount) + inform("#all lub : " + nestedLubCount) inform("ms type-flow-analysis: " + analysis.timer.millis) if (phase.name == "typer") { @@ -155,6 +157,7 @@ abstract class StatisticsInfo { inform(" failed apply : " + showRelTyper(failedApplyNanos)) inform(" failed op= : " + showRelTyper(failedOpEqNanos)) inform("time spent ref scanning : " + showRelTyper(isReferencedNanos)) + inform("time spent in lubs : " + showRelTyper(lubNanos)) inform("micros by tree node : " + showCounts(microsByType)) inform("#visits by tree node : " + showCounts(visitsByType)) val average = new ClassCounts diff --git a/src/compiler/scala/tools/nsc/util/package.scala b/src/compiler/scala/tools/nsc/util/package.scala index 1336cca3c5..2229b8d997 100644 --- a/src/compiler/scala/tools/nsc/util/package.scala +++ b/src/compiler/scala/tools/nsc/util/package.scala @@ -86,4 +86,57 @@ package object util { lazy val trace = new SimpleTracer(System.out) lazy val errtrace = new SimpleTracer(System.err) + @deprecated("Moved to scala.reflect.internal.util.StringOps", "2.10.0") + val StringOps = scala.reflect.internal.util.StringOps + + @deprecated("Moved to scala.reflect.internal.util.StringOps", "2.10.0") + type StringOps = scala.reflect.internal.util.StringOps + + @deprecated("Moved to scala.reflect.internal.util.TableDef", "2.10.0") + val TableDef = scala.reflect.internal.util.TableDef + + @deprecated("Moved to scala.reflect.internal.util.TableDef", "2.10.0") + type TableDef[T] = scala.reflect.internal.util.TableDef[T] + + @deprecated("scala.reflect.internal.util.WeakHashSet", "2.10.0") + type WeakHashSet[T <: AnyRef] = scala.reflect.internal.util.WeakHashSet[T] + + @deprecated("Moved to scala.reflect.internal.util.Position", "2.10.0") + val Position = scala.reflect.internal.util.Position + + @deprecated("Moved to scala.reflect.internal.util.Position", "2.10.0") + type Position = scala.reflect.internal.util.Position + + @deprecated("Moved to scala.reflect.internal.util.NoPosition", "2.10.0") + val NoPosition = scala.reflect.internal.util.NoPosition + + @deprecated("Moved to scala.reflect.internal.util.FakePos", "2.10.0") + val FakePos = scala.reflect.internal.util.FakePos + + @deprecated("Moved to scala.reflect.internal.util.FakePos", "2.10.0") + type FakePos = scala.reflect.internal.util.FakePos + + @deprecated("Moved to scala.reflect.internal.util.OffsetPosition", "2.10.0") + type OffsetPosition = scala.reflect.internal.util.OffsetPosition + + @deprecated("Moved to scala.reflect.internal.util.RangePosition", "2.10.0") + type RangePosition = scala.reflect.internal.util.RangePosition + + @deprecated("Moved to scala.reflect.internal.util.SourceFile", "2.10.0") + type SourceFile = scala.reflect.internal.util.SourceFile + + @deprecated("Moved to scala.reflect.internal.util.NoSourceFile", "2.10.0") + val NoSourceFile = scala.reflect.internal.util.NoSourceFile + + @deprecated("Moved to scala.reflect.internal.util.NoFile", "2.10.0") + val NoFile = scala.reflect.internal.util.NoFile + + @deprecated("Moved to scala.reflect.internal.util.ScriptSourceFile", "2.10.0") + val ScriptSourceFile = scala.reflect.internal.util.ScriptSourceFile + + @deprecated("Moved to scala.reflect.internal.util.ScriptSourceFile", "2.10.0") + type ScriptSourceFile = scala.reflect.internal.util.ScriptSourceFile + + @deprecated("Moved to scala.reflect.internal.util.BatchSourceFile", "2.10.0") + type BatchSourceFile = scala.reflect.internal.util.BatchSourceFile } diff --git a/src/compiler/scala/tools/reflect/FastTrack.scala b/src/compiler/scala/tools/reflect/FastTrack.scala new file mode 100644 index 0000000000..59160f87d0 --- /dev/null +++ b/src/compiler/scala/tools/reflect/FastTrack.scala @@ -0,0 +1,47 @@ +package scala.tools +package reflect + +import scala.reflect.makro.runtime.ContextReifiers +import scala.reflect.reify.Taggers +import scala.tools.nsc.typechecker.{Analyzer, Macros} + +/** Optimizes system macro expansions by hardwiring them directly to their implementations + * bypassing standard reflective load and invoke to avoid the overhead of Java/Scala reflection. + */ +trait FastTrack { + self: Macros with Analyzer => + + import global._ + import definitions._ + + import language.implicitConversions + private implicit def context2taggers(c0: MacroContext) : Taggers { val c: c0.type } = new { val c: c0.type = c0 } with Taggers + private implicit def context2contextreifiers(c0: MacroContext) : ContextReifiers { val c: c0.type } = new { val c: c0.type = c0 } with ContextReifiers + + implicit def fastTrackEntry2MacroRuntime(entry: FastTrackEntry): MacroRuntime = args => entry.run(args) + type FastTrackExpander = PartialFunction[(MacroContext, Tree), Tree] + case class FastTrackEntry(sym: Symbol, expander: FastTrackExpander) { + def validate(argss: List[List[Any]]): Boolean = { + val c = argss.flatten.apply(0).asInstanceOf[MacroContext] + val isValid = expander isDefinedAt (c, c.expandee) + isValid + } + def run(args: List[Any]): Any = { + val c = args(0).asInstanceOf[MacroContext] + val result = expander((c, c.expandee)) + c.Expr[Nothing](result)(c.TypeTag.Nothing) + } + } + + lazy val fastTrack: Map[Symbol, FastTrackEntry] = { + var registry = Map[Symbol, FastTrackEntry]() + implicit class BindTo(sym: Symbol) { def bindTo(expander: FastTrackExpander): Unit = if (sym != NoSymbol) registry += sym -> FastTrackEntry(sym, expander) } + MacroInternal_materializeClassTag bindTo { case (c, Apply(TypeApply(_, List(tt)), List(u))) => c.materializeClassTag(u, tt.tpe) } + MacroInternal_materializeAbsTypeTag bindTo { case (c, Apply(TypeApply(_, List(tt)), List(u))) => c.materializeTypeTag(u, EmptyTree, tt.tpe, concrete = false) } + MacroInternal_materializeTypeTag bindTo { case (c, Apply(TypeApply(_, List(tt)), List(u))) => c.materializeTypeTag(u, EmptyTree, tt.tpe, concrete = true) } + ApiUniverseReify bindTo { case (c, Apply(TypeApply(_, List(tt)), List(expr))) => c.materializeExpr(c.prefix.tree, EmptyTree, expr) } + MacroContextReify bindTo { case (c, Apply(TypeApply(_, List(tt)), List(expr))) => c.materializeExprForMacroContext(c.prefix.tree, expr) } + ReflectRuntimeCurrentMirror bindTo { case (c, _) => scala.reflect.runtime.Macros.currentMirror(c).tree } + registry + } +}
\ No newline at end of file diff --git a/src/compiler/scala/reflect/internal/FrontEnds.scala b/src/compiler/scala/tools/reflect/FrontEnds.scala index 74501c7686..d8f07fb2e5 100644 --- a/src/compiler/scala/reflect/internal/FrontEnds.scala +++ b/src/compiler/scala/tools/reflect/FrontEnds.scala @@ -1,10 +1,13 @@ -package scala.reflect -package internal +package scala.tools +package reflect -trait FrontEnds { self: SymbolTable => +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import scala.reflect.ClassTag - import scala.tools.nsc.reporters._ - import scala.tools.nsc.Settings +trait FrontEnds extends scala.reflect.api.FrontEnds { + + type Position = scala.reflect.internal.util.Position def mkConsoleFrontEnd(minSeverity: Int = 1): FrontEnd = { val settings = new Settings() diff --git a/src/compiler/scala/tools/reflect/StdTags.scala b/src/compiler/scala/tools/reflect/StdTags.scala new file mode 100644 index 0000000000..c782181f21 --- /dev/null +++ b/src/compiler/scala/tools/reflect/StdTags.scala @@ -0,0 +1,42 @@ +package scala.tools +package reflect + +import java.lang.{Class => jClass} +import scala.reflect.{ClassTag, classTag} +import scala.reflect.base.{MirrorOf, TypeCreator, Universe => BaseUniverse} +import scala.reflect.runtime.{universe => ru} + +// [Eugene++] Before 2.10 is released, I suggest we don't rely on automated type tag generation +// sure, it's convenient, but then refactoring reflection / reification becomes a pain +// `ClassTag` tags are fine, because they don't need a reifier to be generated + +object StdTags { + // root mirror is fine for these guys, since scala-library.jar is guaranteed to be reachable from the root mirror + lazy val tagOfString = ru.TypeTag.String + lazy val tagOfListOfString = ru.TypeTag[List[String]]( + ru.rootMirror, + new TypeCreator { + def apply[U <: BaseUniverse with Singleton](m: MirrorOf[U]): U # Type = { + val u = m.universe + val pre = u.ThisType(m.staticModule("scala.collection.immutable").moduleClass.asInstanceOf[u.Symbol]) + u.TypeRef(pre, u.definitions.ListClass, List(u.definitions.StringClass.asTypeConstructor)) + } + }) + + // root mirror is NOT fine for these guys, hence we use the `currentMirror` trick + private val ourClassloader = getClass.getClassLoader + private def tagOfStaticClass[T: ClassTag] = + ru.TypeTag[T]( + ru.runtimeMirror(ourClassloader), + new TypeCreator { + def apply[U <: BaseUniverse with Singleton](m: MirrorOf[U]): U # Type = + m.staticClass(classTag[T].runtimeClass.getName).asTypeConstructor.asInstanceOf[U # Type] + }) + lazy val tagOfInt = ru.TypeTag.Int + lazy val tagOfFile = tagOfStaticClass[scala.tools.nsc.io.File] + lazy val tagOfDirectory = tagOfStaticClass[scala.tools.nsc.io.Directory] + lazy val tagOfStdReplVals = tagOfStaticClass[scala.tools.nsc.interpreter.StdReplVals] + lazy val tagOfIMain = tagOfStaticClass[scala.tools.nsc.interpreter.IMain] + lazy val tagOfThrowable = tagOfStaticClass[java.lang.Throwable] + lazy val tagOfClassLoader = tagOfStaticClass[java.lang.ClassLoader] +} diff --git a/src/compiler/scala/tools/reflect/ToolBox.scala b/src/compiler/scala/tools/reflect/ToolBox.scala new file mode 100644 index 0000000000..edd22c60f4 --- /dev/null +++ b/src/compiler/scala/tools/reflect/ToolBox.scala @@ -0,0 +1,93 @@ +package scala.tools +package reflect + +import scala.reflect.api.Universe +import scala.reflect.base.MirrorOf + +trait ToolBox[U <: Universe] { + + /** Underlying universe of a ToolBox + */ + val u: U + + /** Underlying mirror of a ToolBox + */ + val mirror: MirrorOf[u.type] + + /** Front end of the toolbox. + * + * Accumulates and displays warnings and errors, can drop to interactive mode (if supported). + * The latter can be useful to study the typechecker or to debug complex macros. + */ + def frontEnd: FrontEnd + + /** Typechecks a tree using this ToolBox. + * This populates symbols and types of the tree and possibly transforms it to reflect certain desugarings. + * + * If the tree has unresolved type variables (represented as instances of ``FreeTypeSymbol'' symbols), + * then they might, might be partially or might not be specified in the ``freeTypes'' parameter. + * + * If ``silent'' is false, ``TypeError'' will be thrown in case of a typecheck error. + * If ``silent'' is true, the typecheck is silent and will return ``EmptyTree'' if an error occurs. + * Such errors don't vanish and can be inspected by turning on -Ydebug. + * + * Typechecking can be steered with the following optional parameters: + * ``withImplicitViewsDisabled'' recursively prohibits implicit views (though, implicit vals will still be looked up and filled in), default value is false + * ``withMacrosDisabled'' recursively prohibits macro expansions and macro-based implicits, default value is false + */ + def typeCheck(tree: u.Tree, pt: u.Type = u.WildcardType, freeTypes: Map[u.FreeTypeSymbol, u.Type] = Map[u.FreeTypeSymbol, u.Type](), silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): u.Tree + + + /** Infers an implicit value of the expected type ``pt'' in the macro callsite context. + * + * If ``silent'' is false, ``TypeError'' will be thrown in case of an inference error. + * If ``silent'' is true, the typecheck is silent and will return ``EmptyTree'' if an error occurs. + * Such errors don't vanish and can be inspected by turning on -Xlog-implicits. + * Unlike in ``typeCheck'', ``silent'' is true by default. + */ + def inferImplicitValue(pt: u.Type, silent: Boolean = true, withMacrosDisabled: Boolean = false): u.Tree + + /** Infers an implicit view from the provided tree ``tree'' from the type ``from'' to the type ``to'' in the macro callsite context. + * + * Otional parameter, ``reportAmbiguous`` controls whether ambiguous implicit errors should be reported. + * If we search for a view simply to find out whether one type is coercible to another, it might be desirable to set this flag to ``false''. + * + * If ``silent'' is false, ``TypeError'' will be thrown in case of an inference error. + * If ``silent'' is true, the typecheck is silent and will return ``EmptyTree'' if an error occurs. + * Such errors don't vanish and can be inspected by turning on -Xlog-implicits. + * Unlike in ``typeCheck'', ``silent'' is true by default. + */ + def inferImplicitView(tree: u.Tree, from: u.Type, to: u.Type, silent: Boolean = true, withMacrosDisabled: Boolean = false, reportAmbiguous: Boolean = true): u.Tree + + /** Recursively resets symbols and types in a given tree. + * + * Note that this does not revert the tree to its pre-typer shape. + * For more info, read up https://issues.scala-lang.org/browse/SI-5464. + */ + def resetAllAttrs(tree: u.Tree): u.Tree + + /** Recursively resets locally defined symbols and types in a given tree. + * + * Note that this does not revert the tree to its pre-typer shape. + * For more info, read up https://issues.scala-lang.org/browse/SI-5464. + */ + def resetLocalAttrs(tree: u.Tree): u.Tree + + /** .. */ + def parseExpr(code: String): u.Tree + + /** Compiles and runs a tree using this ToolBox. + * + * If the tree has unresolved type variables (represented as instances of ``FreeTypeSymbol'' symbols), + * then they all have to be specified in the ``freeTypes'' parameter or an error occurs. + * + * This spawns the compiler at the Namer phase, and pipelines the tree through that compiler. + * Currently ``runExpr'' does not accept trees that already typechecked, because typechecking isn't idempotent. + * For more info, take a look at https://issues.scala-lang.org/browse/SI-5464. + */ + def runExpr(tree: u.Tree, freeTypes: Map[u.FreeTypeSymbol, u.Type] = Map[u.FreeTypeSymbol, u.Type]()): Any +} + +/** Represents an error during toolboxing + */ +case class ToolBoxError(val message: String, val cause: Throwable = null) extends Throwable(message, cause) diff --git a/src/compiler/scala/reflect/runtime/ToolBoxes.scala b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala index 895c645c83..7cf515425d 100644 --- a/src/compiler/scala/reflect/runtime/ToolBoxes.scala +++ b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala @@ -1,5 +1,5 @@ -package scala.reflect -package runtime +package scala.tools +package reflect import scala.tools.nsc.reporters._ import scala.tools.nsc.ReflectGlobal @@ -10,29 +10,43 @@ import scala.tools.nsc.io.VirtualDirectory import scala.tools.nsc.interpreter.AbstractFileClassLoader import scala.tools.nsc.util.FreshNameCreator import scala.reflect.internal.Flags -import scala.tools.nsc.util.{NoSourceFile, NoFile} +import scala.reflect.internal.util.{BatchSourceFile, NoSourceFile, NoFile} import java.lang.{Class => jClass} import scala.compat.Platform.EOL +import scala.reflect.NameTransformer +import scala.reflect.api.JavaUniverse +import scala.reflect.base.MirrorOf -trait ToolBoxes extends { self: Universe => +// [Eugene++ to Martin] by the way, toolboxes are unable to compile anything that involves packages +// is this intentional? - def mkToolBox(frontEnd: FrontEnd = mkSilentFrontEnd(), options: String = "") = new ToolBox(frontEnd, options) +abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => - class ToolBox(val frontEnd: FrontEnd, val options: String) extends AbsToolBox { + val mirror: u.Mirror + + def mkToolBox(frontEnd: FrontEnd = mkSilentFrontEnd(), options: String = ""): ToolBox[U] = + new ToolBoxImpl(frontEnd, options) + + private class ToolBoxImpl(val frontEnd: FrontEnd, val options: String) extends ToolBox[U] { toolBoxSelf => + + val u: factorySelf.u.type = factorySelf.u + val mirror: u.Mirror = factorySelf.mirror class ToolBoxGlobal(settings: scala.tools.nsc.Settings, reporter: Reporter) - extends ReflectGlobal(settings, reporter, ToolBox.this.classLoader) { + extends ReflectGlobal(settings, reporter, toolBoxSelf.classLoader) { import definitions._ private val trace = scala.tools.nsc.util.trace when settings.debug.value - private final val wrapperMethodName = "wrapper" - private var wrapCount = 0 + private final val wrapperMethodName = "wrapper" + private def nextWrapperModuleName() = { wrapCount += 1 - newTermName("__wrapper$" + wrapCount) + // we need to use UUIDs here, because our toolbox might be spawned by another toolbox + // that already has, say, __wrapper$1 in its virtual directory, which will shadow our codegen + newTermName("__wrapper$" + wrapCount + "$" + java.util.UUID.randomUUID.toString.replace("-", "")) } def verifyExpr(expr: Tree): Unit = { @@ -46,37 +60,34 @@ trait ToolBoxes extends { self: Universe => // That's why we cannot allow inputs of toolboxes to be typechecked, // at least not until the aforementioned issue is closed. val typed = expr filter (t => t.tpe != null && t.tpe != NoType && !t.isInstanceOf[TypeTree]) - if (!typed.isEmpty) throw new ToolBoxError(ToolBox.this, "reflective toolbox has failed: cannot operate on trees that are already typed") + if (!typed.isEmpty) throw ToolBoxError("reflective toolbox has failed: cannot operate on trees that are already typed") - val freeTypes = this.freeTypes(expr) + val freeTypes = expr.freeTypes if (freeTypes.length > 0) { var msg = "reflective toolbox has failed:" + EOL msg += "unresolved free type variables (namely: " + (freeTypes map (ft => "%s %s".format(ft.name, ft.origin)) mkString ", ") + "). " msg += "have you forgot to use TypeTag annotations for type parameters external to a reifee? " msg += "if you have troubles tracking free type variables, consider using -Xlog-free-types" - throw new ToolBoxError(ToolBox.this, msg) + throw ToolBoxError(msg) } } - def typeCheckExpr(expr0: Tree, pt: Type, silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): Tree = { - verifyExpr(expr0) - - // need to wrap the expr, because otherwise you won't be able to typecheck macros against something that contains free vars - // [Eugene] get rid of the copy/paste w.r.t compileExpr - val freeTerms = this.freeTerms(expr0) - val freeTermNames = collection.mutable.Map[Symbol, TermName]() + def extractFreeTerms(expr0: Tree, wrapFreeTermRefs: Boolean): (Tree, collection.mutable.LinkedHashMap[FreeTermSymbol, TermName]) = { + val freeTerms = expr0.freeTerms + val freeTermNames = collection.mutable.LinkedHashMap[FreeTermSymbol, TermName]() freeTerms foreach (ft => { var name = ft.name.toString val namesakes = freeTerms takeWhile (_ != ft) filter (ft2 => ft != ft2 && ft.name == ft2.name) if (namesakes.length > 0) name += ("$" + (namesakes.length + 1)) - freeTermNames += (ft -> newTermName(name + nme.MIRROR_FREE_VALUE_SUFFIX)) + freeTermNames += (ft -> newTermName(name + nme.REIFY_FREE_VALUE_SUFFIX)) }) var expr = new Transformer { override def transform(tree: Tree): Tree = if (tree.hasSymbol && tree.symbol.isFreeTerm) { tree match { case Ident(_) => - Ident(freeTermNames(tree.symbol)) + val freeTermRef = Ident(freeTermNames(tree.symbol.asFreeTermSymbol)) + if (wrapFreeTermRefs) Apply(freeTermRef, List()) else freeTermRef case _ => throw new Error("internal error: %s (%s, %s) is not supported".format(tree, tree.productPrefix, tree.getClass)) } @@ -84,14 +95,23 @@ trait ToolBoxes extends { self: Universe => super.transform(tree) } }.transform(expr0) - val dummies = freeTerms map (freeTerm => ValDef(NoMods, freeTermNames(freeTerm), TypeTree(freeTerm.info), Select(Ident(PredefModule), newTermName("$qmark$qmark$qmark")))) + (expr, freeTermNames) + } + + def typeCheckExpr(expr0: Tree, pt: Type, silent: Boolean = false, withImplicitViewsDisabled: Boolean, withMacrosDisabled: Boolean): Tree = { + verifyExpr(expr0) + + // need to wrap the expr, because otherwise you won't be able to typecheck macros against something that contains free vars + var (expr, freeTerms) = extractFreeTerms(expr0, wrapFreeTermRefs = false) + val dummies = freeTerms.map{ case (freeTerm, name) => ValDef(NoMods, name, TypeTree(freeTerm.info), Select(Ident(PredefModule), newTermName("$qmark$qmark$qmark"))) }.toList expr = Block(dummies, expr) // [Eugene] how can we implement that? // !!! Why is this is in the empty package? If it's only to make // it inaccessible then please put it somewhere designed for that // rather than polluting the empty package with synthetics. - val ownerClass = EmptyPackageClass.newClassWithInfo(newTypeName("<expression-owner>"), List(ObjectClass.tpe), newScope) + val ownerClass = rootMirror.EmptyPackageClass.newClassSymbol(newTypeName("<expression-owner>")) + build.setTypeSignature(ownerClass, ClassInfoType(List(ObjectClass.tpe), newScope, ownerClass)) val owner = ownerClass.newLocalDummy(expr.pos) var currentTyper = typer.atOwner(expr, owner) val wrapper1 = if (!withImplicitViewsDisabled) (currentTyper.context.withImplicitsEnabled[Tree] _) else (currentTyper.context.withImplicitsDisabled[Tree] _) @@ -107,22 +127,22 @@ trait ToolBoxes extends { self: Universe => case analyzer.SilentResultValue(result) => trace("success: ")(showAttributed(result, true, true, settings.Yshowsymkinds.value)) var Block(dummies, unwrapped) = result - var reversedFreeTermNames = freeTermNames map (_.swap) + var invertedIndex = freeTerms map (_.swap) // todo. also fixup singleton types unwrapped = new Transformer { override def transform(tree: Tree): Tree = tree match { - case Ident(name) if reversedFreeTermNames contains name => - Ident(reversedFreeTermNames(name)) setType tree.tpe + case Ident(name) if invertedIndex contains name => + Ident(invertedIndex(name)) setType tree.tpe case _ => super.transform(tree) } }.transform(unwrapped) - new TreeTypeSubstituter(dummies map (_.symbol), dummies map (dummy => SingleType(NoPrefix, reversedFreeTermNames(dummy.symbol.name)))).traverse(unwrapped) + new TreeTypeSubstituter(dummies map (_.symbol), dummies map (dummy => SingleType(NoPrefix, invertedIndex(dummy.symbol.name)))).traverse(unwrapped) unwrapped case error @ analyzer.SilentTypeError(_) => trace("failed: ")(error.err.errMsg) - if (!silent) throw new ToolBoxError(ToolBox.this, "reflective typecheck has failed: %s".format(error.err.errMsg)) + if (!silent) throw ToolBoxError("reflective typecheck has failed: %s".format(error.err.errMsg)) EmptyTree }) } @@ -131,48 +151,32 @@ trait ToolBoxes extends { self: Universe => verifyExpr(expr) def wrapExpr(expr0: Tree): Tree = { - def defOwner(tree: Tree): Symbol = tree find (_.isDef) map (_.symbol) match { - case Some(sym) if sym != null && sym != NoSymbol => sym.owner - case _ => NoSymbol - } + val (expr, freeTerms) = extractFreeTerms(expr0, wrapFreeTermRefs = true) - val freeTerms = this.freeTerms(expr0) - val freeTermNames = collection.mutable.Map[Symbol, TermName]() - freeTerms foreach (ft => { - var name = ft.name.toString - val namesakes = freeTerms takeWhile (_ != ft) filter (ft2 => ft != ft2 && ft.name == ft2.name) - if (namesakes.length > 0) name += ("$" + (namesakes.length + 1)) - freeTermNames += (ft -> newTermName(name + nme.MIRROR_FREE_VALUE_SUFFIX)) - }) - val expr = new Transformer { - override def transform(tree: Tree): Tree = - if (tree.hasSymbol && tree.symbol.isFreeTerm) { - tree match { - case Ident(_) => - Apply(Ident(freeTermNames(tree.symbol)), List()) - case _ => - throw new Error("internal error: %s (%s, %s) is not supported".format(tree, tree.productPrefix, tree.getClass)) - } - } else { - super.transform(tree) - } - }.transform(expr0) + val (obj, mclazz) = rootMirror.EmptyPackageClass.newModuleAndClassSymbol( + nextWrapperModuleName()) - val obj = EmptyPackageClass.newModule(nextWrapperModuleName()) val minfo = ClassInfoType(List(ObjectClass.tpe), newScope, obj.moduleClass) obj.moduleClass setInfo minfo obj setInfo obj.moduleClass.tpe + val meth = obj.moduleClass.newMethod(newTermName(wrapperMethodName)) - def makeParam(fv: Symbol) = { + def makeParam(schema: (FreeTermSymbol, TermName)) = { + val (fv, name) = schema // [Eugene] conventional way of doing this? val underlying = fv.tpe.resultType val tpe = appliedType(definitions.FunctionClass(0).tpe, List(underlying)) - meth.newValueParameter(freeTermNames(fv)) setInfo tpe + meth.newValueParameter(name) setInfo tpe } - meth setInfo MethodType(freeTerms map makeParam, AnyClass.tpe) + meth setInfo MethodType(freeTerms.map(makeParam).toList, AnyClass.tpe) minfo.decls enter meth + def defOwner(tree: Tree): Symbol = tree find (_.isDef) map (_.symbol) match { + case Some(sym) if sym != null && sym != NoSymbol => sym.owner + case _ => NoSymbol + } trace("wrapping ")(defOwner(expr) -> meth) val methdef = DefDef(meth, expr changeOwner (defOwner(expr) -> meth)) + val moduledef = ModuleDef( obj, Template( @@ -184,6 +188,7 @@ trait ToolBoxes extends { self: Universe => List(methdef), NoPosition)) trace("wrapped: ")(showAttributed(moduledef, true, true, settings.Yshowsymkinds.value)) + var cleanedUp = resetLocalAttrs(moduledef) trace("cleaned up: ")(showAttributed(cleanedUp, true, true, settings.Yshowsymkinds.value)) cleanedUp @@ -210,7 +215,7 @@ trait ToolBoxes extends { self: Universe => } def runExpr(expr: Tree, freeTypes: Map[TypeName, Type] = Map[TypeName, Type]()): Any = { - val freeTerms = this.freeTerms(expr) // need to calculate them here, because later on they will be erased + val freeTerms = expr.freeTerms // need to calculate them here, because later on they will be erased val thunks = freeTerms map (fte => () => fte.value) // need to be lazy in order not to distort evaluation order // @odersky writes: Not sure we will be able to drop this. I forgot the reason why we dereference () functions, @@ -218,14 +223,33 @@ trait ToolBoxes extends { self: Universe => // @Eugene writes: this dates back to the days when one could only reify functions // hence, blocks were translated into nullary functions, so // presumably, it was useful to immediately evaluate them to get the result of a block -// val result = jmeth.invoke(singleton, freeTerms map (sym => sym.asInstanceOf[FreeTermVar].value.asInstanceOf[AnyRef]): _*) -// if (etpe.typeSymbol != FunctionClass(0)) result -// else { -// val applyMeth = result.getClass.getMethod("apply") -// applyMeth.invoke(result) -// } + // @Eugene writes: anyways, I'll stash the old sources here in comments in case anyone wants to revive them + // val result = jmeth.invoke(singleton, freeTerms map (sym => sym.asInstanceOf[FreeTermVar].value.asInstanceOf[AnyRef]): _*) + // if (etpe.typeSymbol != FunctionClass(0)) result + // else { + // val applyMeth = result.getClass.getMethod("apply") + // applyMeth.invoke(result) + // } val (singleton, jmeth) = compileExpr(expr) - jmeth.invoke(singleton, thunks map (_.asInstanceOf[AnyRef]): _*) + val result = jmeth.invoke(singleton, thunks map (_.asInstanceOf[AnyRef]): _*) + result + } + + def parseExpr(code: String): Tree = { + val run = new Run + reporter.reset() + val wrappedCode = "object wrapper {" + EOL + code + EOL + "}" + val file = new BatchSourceFile("<toolbox>", wrappedCode) + val unit = new CompilationUnit(file) + phase = run.parserPhase + val parser = new syntaxAnalyzer.UnitParser(unit) + val wrappedTree = parser.parse() + throwIfErrors() + val PackageDef(_, List(ModuleDef(_, _, Template(_, _, _ :: parsed)))) = wrappedTree + parsed match { + case expr :: Nil => expr + case stats :+ expr => Block(stats, expr) + } } def showAttributed(tree: Tree, printTypes: Boolean = true, printIds: Boolean = true, printKinds: Boolean = false): String = { @@ -249,7 +273,7 @@ trait ToolBoxes extends { self: Universe => if (frontEnd.hasErrors) { var msg = "reflective compilation has failed: " + EOL + EOL msg += frontEnd.infos map (_.msg) mkString EOL - throw new ToolBoxError(ToolBox.this, msg) + throw ToolBoxError(msg) } } } @@ -258,94 +282,93 @@ trait ToolBoxes extends { self: Universe => lazy val arguments = options.split(" ") lazy val virtualDirectory = - (arguments zip arguments.tail) collect { case ("-d", dir) => dir } lastOption match { + (arguments zip arguments.tail).collect{ case ("-d", dir) => dir }.lastOption match { case Some(outDir) => scala.tools.nsc.io.AbstractFile.getDirectory(outDir) case None => new VirtualDirectory("(memory)", None) } lazy val compiler: ToolBoxGlobal = { try { - val errorFn: String => Unit = msg => frontEnd.log(NoPosition, msg, frontEnd.ERROR) + val errorFn: String => Unit = msg => frontEnd.log(scala.reflect.internal.util.NoPosition, msg, frontEnd.ERROR) val command = new CompilerCommand(arguments.toList, errorFn) command.settings.outputDirs setSingleOutput virtualDirectory val instance = new ToolBoxGlobal(command.settings, new FrontEndToReporterProxy(frontEnd) { val settings = command.settings }) if (frontEnd.hasErrors) { var msg = "reflective compilation has failed: cannot initialize the compiler: " + EOL + EOL msg += frontEnd.infos map (_.msg) mkString EOL - throw new ToolBoxError(this, msg) + throw ToolBoxError(msg) } - instance.phase = (new instance.Run).typerPhase // need to manually set a phase, because otherwise TypeHistory will crash instance } catch { case ex: Throwable => var msg = "reflective compilation has failed: cannot initialize the compiler due to %s".format(ex.toString) - throw new ToolBoxError(this, msg, ex) + throw ToolBoxError(msg, ex) } } - // @Eugene: how do I make this work without casts? - // lazy val importer = compiler.mkImporter(self) - lazy val importer = compiler.mkImporter(self).asInstanceOf[compiler.Importer { val from: self.type }] - + lazy val importer = compiler.mkImporter(u) lazy val exporter = importer.reverse + lazy val classLoader = new AbstractFileClassLoader(virtualDirectory, mirror.classLoader) - lazy val classLoader = new AbstractFileClassLoader(virtualDirectory, self.classLoader) - - def typeCheck(tree: Tree, expectedType: Type = WildcardType, freeTypes: Map[FreeType, Type] = Map[FreeType, Type](), silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): Tree = { + def typeCheck(tree: u.Tree, expectedType: u.Type, freeTypes: Map[u.FreeTypeSymbol, u.Type], silent: Boolean, withImplicitViewsDisabled: Boolean, withMacrosDisabled: Boolean): u.Tree = { if (compiler.settings.verbose.value) println("typing "+tree+", expectedType = "+expectedType+", freeTypes = "+freeTypes) var ctree: compiler.Tree = importer.importTree(tree) var cexpectedType: compiler.Type = importer.importType(expectedType) if (compiler.settings.verbose.value) println("substituting "+ctree+", expectedType = "+expectedType) - val cfreeTypes: Map[compiler.FreeType, compiler.Type] = freeTypes map { case (k, v) => (importer.importSymbol(k).asInstanceOf[compiler.FreeType], importer.importType(v)) } - ctree = compiler.substituteFreeTypes(ctree, cfreeTypes) - cexpectedType = compiler.substituteFreeTypes(cexpectedType, cfreeTypes) + val cfreeTypes: Map[compiler.FreeTypeSymbol, compiler.Type] = freeTypes map { case (k, v) => (importer.importSymbol(k).asInstanceOf[compiler.FreeTypeSymbol], importer.importType(v)) } + ctree = ctree.substituteTypes(cfreeTypes.keys.toList, cfreeTypes.values.toList) + cexpectedType = cexpectedType.substituteTypes(cfreeTypes.keys.toList, cfreeTypes.values.toList) if (compiler.settings.verbose.value) println("typing "+ctree+", expectedType = "+expectedType) val ttree: compiler.Tree = compiler.typeCheckExpr(ctree, cexpectedType, silent = silent, withImplicitViewsDisabled = withImplicitViewsDisabled, withMacrosDisabled = withMacrosDisabled) - val rmttree = exporter.importTree(ttree) - rmttree + val uttree = exporter.importTree(ttree) + uttree } - def inferImplicitValue(pt: Type, silent: Boolean = true, withMacrosDisabled: Boolean = false): Tree = + def inferImplicitValue(pt: u.Type, silent: Boolean, withMacrosDisabled: Boolean): u.Tree = // todo. implement this ??? - def inferImplicitView(tree: Tree, from: Type, to: Type, silent: Boolean = true, withMacrosDisabled: Boolean = false, reportAmbiguous: Boolean = true): Tree = + def inferImplicitView(tree: u.Tree, from: u.Type, to: u.Type, silent: Boolean, withMacrosDisabled: Boolean, reportAmbiguous: Boolean): u.Tree = // todo. implement this ??? - def resetAllAttrs(tree: Tree): Tree = { + def resetAllAttrs(tree: u.Tree): u.Tree = { val ctree: compiler.Tree = importer.importTree(tree) val ttree: compiler.Tree = compiler.resetAllAttrs(ctree) - exporter.importTree(ttree) + val uttree = exporter.importTree(ttree) + uttree } - def resetLocalAttrs(tree: Tree): Tree = { + def resetLocalAttrs(tree: u.Tree): u.Tree = { val ctree: compiler.Tree = importer.importTree(tree) val ttree: compiler.Tree = compiler.resetLocalAttrs(ctree) - exporter.importTree(ttree) + val uttree = exporter.importTree(ttree) + uttree } - def showAttributed(tree: Tree, printTypes: Boolean = true, printIds: Boolean = true, printKinds: Boolean = false): String = + def showAttributed(tree: u.Tree, printTypes: Boolean = true, printIds: Boolean = true, printKinds: Boolean = false): String = compiler.showAttributed(importer.importTree(tree), printTypes, printIds, printKinds) - def runExpr(tree: Tree, freeTypes: Map[FreeType, Type] = Map[FreeType, Type]()): Any = { + def parseExpr(code: String): u.Tree = { + if (compiler.settings.verbose.value) println("parsing "+code) + val ctree: compiler.Tree = compiler.parseExpr(code) + val utree = exporter.importTree(ctree) + utree + } + + def runExpr(tree: u.Tree, freeTypes: Map[u.FreeTypeSymbol, u.Type]): Any = { if (compiler.settings.verbose.value) println("running "+tree+", freeTypes = "+freeTypes) var ctree: compiler.Tree = importer.importTree(tree) if (compiler.settings.verbose.value) println("substituting "+ctree) - val cfreeTypes: Map[compiler.FreeType, compiler.Type] = freeTypes map { case (k, v) => (importer.importSymbol(k).asInstanceOf[compiler.FreeType], importer.importType(v)) } - ctree = compiler.substituteFreeTypes(ctree, cfreeTypes) + val cfreeTypes: Map[compiler.FreeTypeSymbol, compiler.Type] = freeTypes map { case (k, v) => (importer.importSymbol(k).asInstanceOf[compiler.FreeTypeSymbol], importer.importType(v)) } + ctree = ctree.substituteTypes(cfreeTypes.keys.toList, cfreeTypes.values.toList) if (compiler.settings.verbose.value) println("running "+ctree) compiler.runExpr(ctree) } - - class ToolBoxError(val toolBox: ToolBox, val message: String, val cause: Throwable = null) extends Throwable(message, cause) - - object ToolBoxError extends ToolBoxErrorExtractor { - def unapply(error: ToolBoxError): Option[(ToolBox, String)] = Some((error.toolBox, error.message)) - } } } + diff --git a/src/compiler/scala/tools/reflect/WrappedProperties.scala b/src/compiler/scala/tools/reflect/WrappedProperties.scala index 2ca374cf01..45c1b57d71 100644 --- a/src/compiler/scala/tools/reflect/WrappedProperties.scala +++ b/src/compiler/scala/tools/reflect/WrappedProperties.scala @@ -21,8 +21,8 @@ trait WrappedProperties extends PropertiesTrait { override def propIsSet(name: String) = wrap(super.propIsSet(name)) exists (x => x) override def propOrElse(name: String, alt: String) = wrap(super.propOrElse(name, alt)) getOrElse alt - override def setProp(name: String, value: String) = wrap(super.setProp(name, value)) orNull - override def clearProp(name: String) = wrap(super.clearProp(name)) orNull + override def setProp(name: String, value: String) = wrap(super.setProp(name, value)).orNull + override def clearProp(name: String) = wrap(super.clearProp(name)).orNull override def envOrElse(name: String, alt: String) = wrap(super.envOrElse(name, alt)) getOrElse alt override def envOrNone(name: String) = wrap(super.envOrNone(name)).flatten diff --git a/src/compiler/scala/tools/reflect/package.scala b/src/compiler/scala/tools/reflect/package.scala new file mode 100644 index 0000000000..a3778a3b69 --- /dev/null +++ b/src/compiler/scala/tools/reflect/package.scala @@ -0,0 +1,33 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2011 LAMP/EPFL + * @author Paul Phillips + */ + +package scala.tools + +import scala.reflect.api.JavaUniverse +import language.implicitConversions + +package object reflect extends FrontEnds { + // [todo: can we generalize this? + import scala.reflect.runtime.{universe => ru} + implicit def ToolBox(mirror0: ru.Mirror): ToolBoxFactory[ru.type] = + new ToolBoxFactory[ru.type](mirror0.universe) { + lazy val mirror = mirror0 + } + + // todo. replace this with an implicit class, once the pesky warning is gone + implicit def Eval[T](expr: JavaUniverse # Expr[T]): Eval[T] = new Eval[T](expr) + + // we don't provide `Eval` for trees, because it's unclear where to get an evaluation mirror from +} + +package reflect { + class Eval[T](expr: JavaUniverse # Expr[T]) { + def eval: T = { + val factory = new ToolBoxFactory[JavaUniverse](expr.mirror.universe) { val mirror = expr.mirror.asInstanceOf[this.u.Mirror] } + val toolBox = factory.mkToolBox() + toolBox.runExpr(expr.tree.asInstanceOf[toolBox.u.Tree]).asInstanceOf[T] + } + } +} diff --git a/src/compiler/scala/tools/util/Javap.scala b/src/compiler/scala/tools/util/Javap.scala index 42d8a910f0..f4f218350a 100644 --- a/src/compiler/scala/tools/util/Javap.scala +++ b/src/compiler/scala/tools/util/Javap.scala @@ -12,6 +12,7 @@ import scala.tools.nsc.util.ScalaClassLoader import java.io.{ InputStream, PrintWriter, ByteArrayInputStream, FileNotFoundException } import scala.tools.nsc.io.File import Javap._ +import language.reflectiveCalls trait Javap { def loader: ScalaClassLoader diff --git a/src/compiler/scala/tools/util/PathResolver.scala b/src/compiler/scala/tools/util/PathResolver.scala index 788891a062..5f4e6d58c3 100644 --- a/src/compiler/scala/tools/util/PathResolver.scala +++ b/src/compiler/scala/tools/util/PathResolver.scala @@ -13,6 +13,7 @@ import nsc.util.{ ClassPath, JavaClassPath, ScalaClassLoader } import nsc.io.{ File, Directory, Path, AbstractFile } import ClassPath.{ JavaContext, DefaultJavaContext, join, split } import PartialFunction.condOpt +import language.postfixOps // Loosely based on the draft specification at: // https://wiki.scala-lang.org/display/SW/Classpath @@ -192,7 +193,15 @@ class PathResolver(settings: Settings, context: JavaContext) { def javaUserClassPath = if (useJavaClassPath) Defaults.javaUserClassPath else "" def scalaBootClassPath = cmdLineOrElse("bootclasspath", Defaults.scalaBootClassPath) def scalaExtDirs = cmdLineOrElse("extdirs", Defaults.scalaExtDirs) - def sourcePath = cmdLineOrElse("sourcepath", Defaults.scalaSourcePath) + /** Scaladoc doesn't need any bootstrapping, otherwise will create errors such as: + * [scaladoc] ../scala-trunk/src/reflect/scala/reflect/makro/Reifiers.scala:89: error: object api is not a member of package reflect + * [scaladoc] case class ReificationError(val pos: reflect.api.PositionApi, val msg: String) extends Throwable(msg) + * [scaladoc] ^ + * because the bootstrapping will look at the sourcepath and create package "reflect" in "<root>" + * and then when typing relative names, instead of picking <root>.scala.relect, typedIdentifier will pick up the + * <root>.reflect package created by the bootstrapping. Thus, no bootstrapping for scaladoc! + * TODO: we should refactor this as a separate -bootstrap option to have a clean implementation, no? */ + def sourcePath = if (!settings.isScaladoc) cmdLineOrElse("sourcepath", Defaults.scalaSourcePath) else "" /** Against my better judgment, giving in to martin here and allowing * CLASSPATH to be used automatically. So for the user-specified part diff --git a/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala b/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala index 6f5284f75f..3a1dc87a6a 100644 --- a/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala +++ b/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala @@ -29,14 +29,14 @@ trait CPSUtils { val shiftUnitR = newTermName("shiftUnitR") } - lazy val MarkerCPSSym = definitions.getRequiredClass("scala.util.continuations.cpsSym") - lazy val MarkerCPSTypes = definitions.getRequiredClass("scala.util.continuations.cpsParam") - lazy val MarkerCPSSynth = definitions.getRequiredClass("scala.util.continuations.cpsSynth") - lazy val MarkerCPSAdaptPlus = definitions.getRequiredClass("scala.util.continuations.cpsPlus") - lazy val MarkerCPSAdaptMinus = definitions.getRequiredClass("scala.util.continuations.cpsMinus") - - lazy val Context = definitions.getRequiredClass("scala.util.continuations.ControlContext") - lazy val ModCPS = definitions.getRequiredModule("scala.util.continuations") + lazy val MarkerCPSSym = rootMirror.getRequiredClass("scala.util.continuations.cpsSym") + lazy val MarkerCPSTypes = rootMirror.getRequiredClass("scala.util.continuations.cpsParam") + lazy val MarkerCPSSynth = rootMirror.getRequiredClass("scala.util.continuations.cpsSynth") + lazy val MarkerCPSAdaptPlus = rootMirror.getRequiredClass("scala.util.continuations.cpsPlus") + lazy val MarkerCPSAdaptMinus = rootMirror.getRequiredClass("scala.util.continuations.cpsMinus") + + lazy val Context = rootMirror.getRequiredClass("scala.util.continuations.ControlContext") + lazy val ModCPS = rootMirror.getRequiredModule("scala.util.continuations") lazy val MethShiftUnit = definitions.getMember(ModCPS, cpsNames.shiftUnit) lazy val MethShiftUnit0 = definitions.getMember(ModCPS, cpsNames.shiftUnit0) diff --git a/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala b/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala index dcb7cd601f..54a0079f40 100644 --- a/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala +++ b/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala @@ -347,7 +347,7 @@ abstract class SelectiveCPSTransform extends PluginComponent with // val <lhs> = ctx.getTrivialValue; ... <--- TODO: try/catch ??? don't bother for the moment... // else // ctx.flatMap { <lhs> => ... } - val ctxSym = currentOwner.newValue(vd.symbol.name append cpsNames.shiftSuffix).setInfo(rhs1.tpe) + val ctxSym = currentOwner.newValue(newTermName("" + vd.symbol.name + cpsNames.shiftSuffix)).setInfo(rhs1.tpe) val ctxDef = localTyper.typed(ValDef(ctxSym, rhs1)) def ctxRef = localTyper.typed(Ident(ctxSym)) val argSym = currentOwner.newValue(vd.symbol.name).setInfo(tpe) diff --git a/src/library/scala/Array.scala b/src/library/scala/Array.scala index e7cf399fa4..6784b630c7 100644 --- a/src/library/scala/Array.scala +++ b/src/library/scala/Array.scala @@ -12,7 +12,7 @@ import scala.collection.generic._ import scala.collection.{ mutable, immutable } import mutable.{ ArrayBuilder, ArraySeq } import compat.Platform.arraycopy -import scala.reflect.ArrayTag +import scala.reflect.ClassTag import scala.runtime.ScalaRunTime.{ array_apply, array_update } /** Contains a fallback builder for arrays when the element type @@ -48,7 +48,7 @@ class FallbackArrayBuilding { * @version 1.0 */ object Array extends FallbackArrayBuilding { - implicit def canBuildFrom[T](implicit t: ArrayTag[T]): CanBuildFrom[Array[_], T, Array[T]] = + implicit def canBuildFrom[T](implicit t: ClassTag[T]): CanBuildFrom[Array[_], T, Array[T]] = new CanBuildFrom[Array[_], T, Array[T]] { def apply(from: Array[_]) = ArrayBuilder.make[T]()(t) def apply() = ArrayBuilder.make[T]()(t) @@ -57,7 +57,7 @@ object Array extends FallbackArrayBuilding { /** * Returns a new [[scala.collection.mutable.ArrayBuilder]]. */ - def newBuilder[T](implicit t: ArrayTag[T]): ArrayBuilder[T] = ArrayBuilder.make[T]()(t) + def newBuilder[T](implicit t: ClassTag[T]): ArrayBuilder[T] = ArrayBuilder.make[T]()(t) private def slowcopy(src : AnyRef, srcPos : Int, @@ -98,14 +98,14 @@ object Array extends FallbackArrayBuilding { } /** Returns an array of length 0 */ - def empty[T: ArrayTag]: Array[T] = new Array[T](0) + def empty[T: ClassTag]: Array[T] = new Array[T](0) /** Creates an array with given elements. * * @param xs the elements to put in the array * @return an array containing all elements from xs. */ - def apply[T: ArrayTag](xs: T*): Array[T] = { + def apply[T: ClassTag](xs: T*): Array[T] = { val array = new Array[T](xs.length) var i = 0 for (x <- xs.iterator) { array(i) = x; i += 1 } @@ -194,23 +194,23 @@ object Array extends FallbackArrayBuilding { } /** Creates array with given dimensions */ - def ofDim[T: ArrayTag](n1: Int): Array[T] = + def ofDim[T: ClassTag](n1: Int): Array[T] = new Array[T](n1) /** Creates a 2-dimensional array */ - def ofDim[T: ArrayTag](n1: Int, n2: Int): Array[Array[T]] = { + def ofDim[T: ClassTag](n1: Int, n2: Int): Array[Array[T]] = { val arr: Array[Array[T]] = (new Array[Array[T]](n1): Array[Array[T]]) for (i <- 0 until n1) arr(i) = new Array[T](n2) arr // tabulate(n1)(_ => ofDim[T](n2)) } /** Creates a 3-dimensional array */ - def ofDim[T: ArrayTag](n1: Int, n2: Int, n3: Int): Array[Array[Array[T]]] = + def ofDim[T: ClassTag](n1: Int, n2: Int, n3: Int): Array[Array[Array[T]]] = tabulate(n1)(_ => ofDim[T](n2, n3)) /** Creates a 4-dimensional array */ - def ofDim[T: ArrayTag](n1: Int, n2: Int, n3: Int, n4: Int): Array[Array[Array[Array[T]]]] = + def ofDim[T: ClassTag](n1: Int, n2: Int, n3: Int, n4: Int): Array[Array[Array[Array[T]]]] = tabulate(n1)(_ => ofDim[T](n2, n3, n4)) /** Creates a 5-dimensional array */ - def ofDim[T: ArrayTag](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int): Array[Array[Array[Array[Array[T]]]]] = + def ofDim[T: ClassTag](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int): Array[Array[Array[Array[Array[T]]]]] = tabulate(n1)(_ => ofDim[T](n2, n3, n4, n5)) /** Concatenates all arrays into a single array. @@ -218,7 +218,7 @@ object Array extends FallbackArrayBuilding { * @param xss the given arrays * @return the array created from concatenating `xss` */ - def concat[T: ArrayTag](xss: Array[T]*): Array[T] = { + def concat[T: ClassTag](xss: Array[T]*): Array[T] = { val b = newBuilder[T] b.sizeHint(xss.map(_.size).sum) for (xs <- xss) b ++= xs @@ -239,7 +239,7 @@ object Array extends FallbackArrayBuilding { * @return an Array of size n, where each element contains the result of computing * `elem`. */ - def fill[T: ArrayTag](n: Int)(elem: => T): Array[T] = { + def fill[T: ClassTag](n: Int)(elem: => T): Array[T] = { val b = newBuilder[T] b.sizeHint(n) var i = 0 @@ -257,7 +257,7 @@ object Array extends FallbackArrayBuilding { * @param n2 the number of elements in the 2nd dimension * @param elem the element computation */ - def fill[T: ArrayTag](n1: Int, n2: Int)(elem: => T): Array[Array[T]] = + def fill[T: ClassTag](n1: Int, n2: Int)(elem: => T): Array[Array[T]] = tabulate(n1)(_ => fill(n2)(elem)) /** Returns a three-dimensional array that contains the results of some element @@ -268,7 +268,7 @@ object Array extends FallbackArrayBuilding { * @param n3 the number of elements in the 3nd dimension * @param elem the element computation */ - def fill[T: ArrayTag](n1: Int, n2: Int, n3: Int)(elem: => T): Array[Array[Array[T]]] = + def fill[T: ClassTag](n1: Int, n2: Int, n3: Int)(elem: => T): Array[Array[Array[T]]] = tabulate(n1)(_ => fill(n2, n3)(elem)) /** Returns a four-dimensional array that contains the results of some element @@ -280,7 +280,7 @@ object Array extends FallbackArrayBuilding { * @param n4 the number of elements in the 4th dimension * @param elem the element computation */ - def fill[T: ArrayTag](n1: Int, n2: Int, n3: Int, n4: Int)(elem: => T): Array[Array[Array[Array[T]]]] = + def fill[T: ClassTag](n1: Int, n2: Int, n3: Int, n4: Int)(elem: => T): Array[Array[Array[Array[T]]]] = tabulate(n1)(_ => fill(n2, n3, n4)(elem)) /** Returns a five-dimensional array that contains the results of some element @@ -293,7 +293,7 @@ object Array extends FallbackArrayBuilding { * @param n5 the number of elements in the 5th dimension * @param elem the element computation */ - def fill[T: ArrayTag](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int)(elem: => T): Array[Array[Array[Array[Array[T]]]]] = + def fill[T: ClassTag](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int)(elem: => T): Array[Array[Array[Array[Array[T]]]]] = tabulate(n1)(_ => fill(n2, n3, n4, n5)(elem)) /** Returns an array containing values of a given function over a range of integer @@ -303,7 +303,7 @@ object Array extends FallbackArrayBuilding { * @param f The function computing element values * @return A traversable consisting of elements `f(0),f(1), ..., f(n - 1)` */ - def tabulate[T: ArrayTag](n: Int)(f: Int => T): Array[T] = { + def tabulate[T: ClassTag](n: Int)(f: Int => T): Array[T] = { val b = newBuilder[T] b.sizeHint(n) var i = 0 @@ -321,7 +321,7 @@ object Array extends FallbackArrayBuilding { * @param n2 the number of elements in the 2nd dimension * @param f The function computing element values */ - def tabulate[T: ArrayTag](n1: Int, n2: Int)(f: (Int, Int) => T): Array[Array[T]] = + def tabulate[T: ClassTag](n1: Int, n2: Int)(f: (Int, Int) => T): Array[Array[T]] = tabulate(n1)(i1 => tabulate(n2)(f(i1, _))) /** Returns a three-dimensional array containing values of a given function @@ -332,7 +332,7 @@ object Array extends FallbackArrayBuilding { * @param n3 the number of elements in the 3rd dimension * @param f The function computing element values */ - def tabulate[T: ArrayTag](n1: Int, n2: Int, n3: Int)(f: (Int, Int, Int) => T): Array[Array[Array[T]]] = + def tabulate[T: ClassTag](n1: Int, n2: Int, n3: Int)(f: (Int, Int, Int) => T): Array[Array[Array[T]]] = tabulate(n1)(i1 => tabulate(n2, n3)(f(i1, _, _))) /** Returns a four-dimensional array containing values of a given function @@ -344,7 +344,7 @@ object Array extends FallbackArrayBuilding { * @param n4 the number of elements in the 4th dimension * @param f The function computing element values */ - def tabulate[T: ArrayTag](n1: Int, n2: Int, n3: Int, n4: Int)(f: (Int, Int, Int, Int) => T): Array[Array[Array[Array[T]]]] = + def tabulate[T: ClassTag](n1: Int, n2: Int, n3: Int, n4: Int)(f: (Int, Int, Int, Int) => T): Array[Array[Array[Array[T]]]] = tabulate(n1)(i1 => tabulate(n2, n3, n4)(f(i1, _, _, _))) /** Returns a five-dimensional array containing values of a given function @@ -357,7 +357,7 @@ object Array extends FallbackArrayBuilding { * @param n5 the number of elements in the 5th dimension * @param f The function computing element values */ - def tabulate[T: ArrayTag](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int)(f: (Int, Int, Int, Int, Int) => T): Array[Array[Array[Array[Array[T]]]]] = + def tabulate[T: ClassTag](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int)(f: (Int, Int, Int, Int, Int) => T): Array[Array[Array[Array[Array[T]]]]] = tabulate(n1)(i1 => tabulate(n2, n3, n4, n5)(f(i1, _, _, _, _))) /** Returns an array containing a sequence of increasing integers in a range. @@ -396,7 +396,7 @@ object Array extends FallbackArrayBuilding { * @param f the function that is repeatedly applied * @return the array returning `len` values in the sequence `start, f(start), f(f(start)), ...` */ - def iterate[T: ArrayTag](start: T, len: Int)(f: T => T): Array[T] = { + def iterate[T: ClassTag](start: T, len: Int)(f: T => T): Array[T] = { val b = newBuilder[T] if (len > 0) { @@ -475,7 +475,7 @@ object Array extends FallbackArrayBuilding { * @define collectExample * @define undefinedorder * @define thatinfo the class of the returned collection. In the standard library configuration, - * `That` is either `Array[B]` if an ArrayTag is available for B or `ArraySeq[B]` otherwise. + * `That` is either `Array[B]` if an ClassTag is available for B or `ArraySeq[B]` otherwise. * @define zipthatinfo $thatinfo * @define bfinfo an implicit value of class `CanBuildFrom` which determines the result class `That` from the current * representation type `Repr` and the new element type `B`. diff --git a/src/library/scala/Predef.scala b/src/library/scala/Predef.scala index c08462ac1b..65e8549ae1 100644 --- a/src/library/scala/Predef.scala +++ b/src/library/scala/Predef.scala @@ -111,26 +111,6 @@ object Predef extends LowPriorityImplicits { def classManifest[T](implicit m: ClassManifest[T]) = m def optManifest[T](implicit m: OptManifest[T]) = m - // Tag types and companions, and incantations for summoning - type ArrayTag[T] = scala.reflect.ArrayTag[T] - type ErasureTag[T] = scala.reflect.ErasureTag[T] - type ClassTag[T] = scala.reflect.ClassTag[T] - type TypeTag[T] = scala.reflect.TypeTag[T] - type ConcreteTypeTag[T] = scala.reflect.ConcreteTypeTag[T] - val ClassTag = scala.reflect.ClassTag // doesn't need to be lazy, because it's not a path-dependent type - // [Paul to Eugene] No lazy vals in Predef. Too expensive. Have to work harder on breaking initialization dependencies. - lazy val TypeTag = scala.reflect.TypeTag // needs to be lazy, because requires scala.reflect.mirror instance - lazy val ConcreteTypeTag = scala.reflect.ConcreteTypeTag - - // [Eugene to Martin] it's really tedious to type "implicitly[...]" all the time, so I'm reintroducing these shortcuts - def arrayTag[T](implicit atag: ArrayTag[T]) = atag - def erasureTag[T](implicit etag: ErasureTag[T]) = etag - def classTag[T](implicit ctag: ClassTag[T]) = ctag - def tag[T](implicit ttag: TypeTag[T]) = ttag - def typeTag[T](implicit ttag: TypeTag[T]) = ttag - def concreteTag[T](implicit cttag: ConcreteTypeTag[T]) = cttag - def concreteTypeTag[T](implicit cttag: ConcreteTypeTag[T]) = cttag - // Minor variations on identity functions def identity[A](x: A): A = x // @see `conforms` for the implicit version @inline def implicitly[T](implicit e: T) = e // for summoning implicit values from the nether world -- TODO: when dependent method types are on by default, give this result type `e.type`, so that inliner has better chance of knowing which method to inline in calls like `implicitly[MatchingStrategy[Option]].zero` diff --git a/src/library/scala/collection/GenTraversableOnce.scala b/src/library/scala/collection/GenTraversableOnce.scala index eab6b84ea8..eadacd9209 100644 --- a/src/library/scala/collection/GenTraversableOnce.scala +++ b/src/library/scala/collection/GenTraversableOnce.scala @@ -8,6 +8,8 @@ package scala.collection +import scala.reflect.ClassTag + /** A template trait for all traversable-once objects which may be * traversed in parallel. * @@ -459,7 +461,7 @@ trait GenTraversableOnce[+A] extends Any { /** Converts this $coll to an array. * - * @tparam A1 the type of the elements of the array. An `ArrayTag` for + * @tparam A1 the type of the elements of the array. An `ClassTag` for * this type must be available. * @return an array containing all elements of this $coll. * @@ -469,9 +471,9 @@ trait GenTraversableOnce[+A] extends Any { * $willNotTerminateInf * * @return an array containing all elements of this $coll. - * An `ArrayTag` must be available for the element type of this $coll. + * An `ClassTag` must be available for the element type of this $coll. */ - def toArray[A1 >: A: ArrayTag]: Array[A1] + def toArray[A1 >: A: ClassTag]: Array[A1] /** Converts this $coll to a list. * $willNotTerminateInf diff --git a/src/library/scala/collection/Traversable.scala b/src/library/scala/collection/Traversable.scala index cd85ea4d2d..56a73ae62f 100644 --- a/src/library/scala/collection/Traversable.scala +++ b/src/library/scala/collection/Traversable.scala @@ -68,7 +68,7 @@ trait Traversable[+A] extends TraversableLike[A, Traversable[A]] override def copyToBuffer[B >: A](dest: Buffer[B]) override def copyToArray[B >: A](xs: Array[B], start: Int, len: Int) override def copyToArray[B >: A](xs: Array[B], start: Int) - override def toArray[B >: A : ArrayTag]: Array[B] + override def toArray[B >: A : ClassTag]: Array[B] override def toList: List[A] override def toIterable: Iterable[A] override def toSeq: Seq[A] diff --git a/src/library/scala/collection/TraversableOnce.scala b/src/library/scala/collection/TraversableOnce.scala index d42c037dee..386ce2d95a 100644 --- a/src/library/scala/collection/TraversableOnce.scala +++ b/src/library/scala/collection/TraversableOnce.scala @@ -11,6 +11,7 @@ package scala.collection import mutable.{ Buffer, Builder, ListBuffer, ArrayBuffer } import annotation.unchecked.{ uncheckedVariance => uV } import language.{implicitConversions, higherKinds} +import reflect.ClassTag /** A template trait for collections which can be traversed either once only * or one or more times. @@ -227,7 +228,7 @@ trait TraversableOnce[+A] extends Any with GenTraversableOnce[A] { def copyToArray[B >: A](xs: Array[B]): Unit = copyToArray(xs, 0, xs.length) - def toArray[B >: A : ArrayTag]: Array[B] = { + def toArray[B >: A : ClassTag]: Array[B] = { if (isTraversableAgain) { val result = new Array[B](size) copyToArray(result, 0) diff --git a/src/library/scala/collection/TraversableProxyLike.scala b/src/library/scala/collection/TraversableProxyLike.scala index 20880e369d..74b30e0faf 100644 --- a/src/library/scala/collection/TraversableProxyLike.scala +++ b/src/library/scala/collection/TraversableProxyLike.scala @@ -12,6 +12,7 @@ package scala.collection import generic._ import mutable.{Buffer, StringBuilder} +import reflect.ClassTag // Methods could be printed by cat TraversableLike.scala | egrep '^ (override )?def' @@ -73,7 +74,7 @@ trait TraversableProxyLike[+A, +Repr <: TraversableLike[A, Repr] with Traversabl override def copyToArray[B >: A](xs: Array[B], start: Int, len: Int) = self.copyToArray(xs, start, len) override def copyToArray[B >: A](xs: Array[B], start: Int) = self.copyToArray(xs, start) override def copyToArray[B >: A](xs: Array[B]) = self.copyToArray(xs) - override def toArray[B >: A: ArrayTag]: Array[B] = self.toArray + override def toArray[B >: A: ClassTag]: Array[B] = self.toArray override def toList: List[A] = self.toList override def toIterable: Iterable[A] = self.toIterable override def toSeq: Seq[A] = self.toSeq diff --git a/src/library/scala/collection/generic/ArrayTagTraversableFactory.scala b/src/library/scala/collection/generic/ClassTagTraversableFactory.scala index ddae0a4d64..95835d3e90 100644 --- a/src/library/scala/collection/generic/ArrayTagTraversableFactory.scala +++ b/src/library/scala/collection/generic/ClassTagTraversableFactory.scala @@ -10,6 +10,7 @@ package scala.collection package generic import language.higherKinds +import reflect.ClassTag /** A template for companion objects of `ClassTagTraversable` and * subclasses thereof. @@ -21,11 +22,11 @@ import language.higherKinds * @author Aleksandar Prokopec * @since 2.8 */ -abstract class ArrayTagTraversableFactory[CC[X] <: Traversable[X] with GenericArrayTagTraversableTemplate[X, CC]] - extends GenericArrayTagCompanion[CC] { +abstract class ClassTagTraversableFactory[CC[X] <: Traversable[X] with GenericClassTagTraversableTemplate[X, CC]] + extends GenericClassTagCompanion[CC] { - class GenericCanBuildFrom[A](implicit tag: ArrayTag[A]) extends CanBuildFrom[CC[_], A, CC[A]] { - def apply(from: CC[_]) = from.genericArrayTagBuilder[A] + class GenericCanBuildFrom[A](implicit tag: ClassTag[A]) extends CanBuildFrom[CC[_], A, CC[A]] { + def apply(from: CC[_]) = from.genericClassTagBuilder[A] def apply = newBuilder[A] } } diff --git a/src/library/scala/collection/generic/GenericArrayTagCompanion.scala b/src/library/scala/collection/generic/GenericClassTagCompanion.scala index 959adbce6d..8cce592627 100644 --- a/src/library/scala/collection/generic/GenericArrayTagCompanion.scala +++ b/src/library/scala/collection/generic/GenericClassTagCompanion.scala @@ -11,20 +11,21 @@ package generic import mutable.Builder import language.higherKinds +import reflect.ClassTag -/** This class represents companions of classes which require ArrayTags +/** This class represents companions of classes which require ClassTags * for their element types. * * @author Aleksandar Prokopec */ -abstract class GenericArrayTagCompanion[+CC[X] <: Traversable[X]] { +abstract class GenericClassTagCompanion[+CC[X] <: Traversable[X]] { type Coll = CC[_] - def newBuilder[A](implicit ord: ArrayTag[A]): Builder[A, CC[A]] + def newBuilder[A](implicit ord: ClassTag[A]): Builder[A, CC[A]] - def empty[A: ArrayTag]: CC[A] = newBuilder[A].result + def empty[A: ClassTag]: CC[A] = newBuilder[A].result - def apply[A](elems: A*)(implicit ord: ArrayTag[A]): CC[A] = { + def apply[A](elems: A*)(implicit ord: ClassTag[A]): CC[A] = { val b = newBuilder[A] b ++= elems b.result diff --git a/src/library/scala/collection/generic/GenericArrayTagTraversableTemplate.scala b/src/library/scala/collection/generic/GenericClassTagTraversableTemplate.scala index ac84683c59..d368d0007b 100644 --- a/src/library/scala/collection/generic/GenericArrayTagTraversableTemplate.scala +++ b/src/library/scala/collection/generic/GenericClassTagTraversableTemplate.scala @@ -12,19 +12,20 @@ package generic import mutable.Builder import annotation.unchecked.uncheckedVariance import language.higherKinds +import reflect.ClassTag -/** This trait represents collections classes which require array +/** This trait represents collections classes which require class * tags for their element types. * * @author Aleksandar Prokopec * @since 2.8 */ -trait GenericArrayTagTraversableTemplate[+A, +CC[X] <: Traversable[X]] extends HasNewBuilder[A, CC[A] @uncheckedVariance] { - implicit protected[this] val tag: ArrayTag[A] - def arrayTagCompanion: GenericArrayTagCompanion[CC] - def genericArrayTagBuilder[B](implicit tag: ArrayTag[B]): Builder[B, CC[B]] = arrayTagCompanion.newBuilder[B] - @deprecated("use arrayTagCompanion instead", "2.10.0") - def classManifestCompanion: GenericClassManifestCompanion[CC] = arrayTagCompanion - @deprecated("use genericArrayTagBuilder instead", "2.10.0") - def genericClassManifestBuilder[B](implicit manifest: ClassManifest[B]): Builder[B, CC[B]] = genericArrayTagBuilder[B](manifest) +trait GenericClassTagTraversableTemplate[+A, +CC[X] <: Traversable[X]] extends HasNewBuilder[A, CC[A] @uncheckedVariance] { + implicit protected[this] val tag: ClassTag[A] + def classTagCompanion: GenericClassTagCompanion[CC] + def genericClassTagBuilder[B](implicit tag: ClassTag[B]): Builder[B, CC[B]] = classTagCompanion.newBuilder[B] + @deprecated("use classTagCompanion instead", "2.10.0") + def classManifestCompanion: GenericClassManifestCompanion[CC] = classTagCompanion + @deprecated("use genericClassTagBuilder instead", "2.10.0") + def genericClassManifestBuilder[B](implicit manifest: ClassManifest[B]): Builder[B, CC[B]] = genericClassTagBuilder[B](manifest) } diff --git a/src/library/scala/collection/generic/TraversableForwarder.scala b/src/library/scala/collection/generic/TraversableForwarder.scala index 3d5bc2704f..5c55c27983 100644 --- a/src/library/scala/collection/generic/TraversableForwarder.scala +++ b/src/library/scala/collection/generic/TraversableForwarder.scala @@ -11,6 +11,7 @@ package scala.collection.generic import scala.collection._ import mutable.{ Buffer, StringBuilder } import immutable.{ List, Stream } +import reflect.ClassTag /** This trait implements a forwarder for traversable objects. It forwards * all calls to a different traversable, except for: @@ -57,7 +58,7 @@ trait TraversableForwarder[+A] extends Traversable[A] { override def copyToArray[B >: A](xs: Array[B], start: Int, len: Int) = underlying.copyToArray(xs, start, len) override def copyToArray[B >: A](xs: Array[B], start: Int) = underlying.copyToArray(xs, start) override def copyToArray[B >: A](xs: Array[B]) = underlying.copyToArray(xs) - override def toArray[B >: A: ArrayTag]: Array[B] = underlying.toArray + override def toArray[B >: A: ClassTag]: Array[B] = underlying.toArray override def toList: List[A] = underlying.toList override def toIterable: Iterable[A] = underlying.toIterable override def toSeq: Seq[A] = underlying.toSeq diff --git a/src/library/scala/collection/generic/package.scala b/src/library/scala/collection/generic/package.scala index e0351ebae6..85b9995f2e 100644 --- a/src/library/scala/collection/generic/package.scala +++ b/src/library/scala/collection/generic/package.scala @@ -1,6 +1,8 @@ package scala.collection import generic.CanBuildFrom +import language.higherKinds + package object generic { type CanBuild[-Elem, +To] = CanBuildFrom[Nothing, Elem, To] @@ -10,12 +12,12 @@ package object generic { */ type HasElem[Repr, A] = Repr => GenTraversableLike[A, Repr] - @deprecated("use ArrayTagTraversableFactory instead", "2.10.0") - type ClassManifestTraversableFactory[CC[X] <: Traversable[X] with GenericClassManifestTraversableTemplate[X, CC]] = ArrayTagTraversableFactory[CC] + @deprecated("use ClassTagTraversableFactory instead", "2.10.0") + type ClassManifestTraversableFactory[CC[X] <: Traversable[X] with GenericClassManifestTraversableTemplate[X, CC]] = ClassTagTraversableFactory[CC] - @deprecated("use GenericArrayTagCompanion instead", "2.10.0") - type GenericClassManifestCompanion[+CC[X] <: Traversable[X]] = GenericArrayTagCompanion[CC] + @deprecated("use GenericClassTagCompanion instead", "2.10.0") + type GenericClassManifestCompanion[+CC[X] <: Traversable[X]] = GenericClassTagCompanion[CC] - @deprecated("use GenericArrayTagTraversableTemplate instead", "2.10.0") - type GenericClassManifestTraversableTemplate[+A, +CC[X] <: Traversable[X]] = GenericArrayTagTraversableTemplate[A, CC] + @deprecated("use GenericClassTagTraversableTemplate instead", "2.10.0") + type GenericClassManifestTraversableTemplate[+A, +CC[X] <: Traversable[X]] = GenericClassTagTraversableTemplate[A, CC] }
\ No newline at end of file diff --git a/src/library/scala/collection/immutable/PagedSeq.scala b/src/library/scala/collection/immutable/PagedSeq.scala index 94953ce38b..7d373b7b39 100644 --- a/src/library/scala/collection/immutable/PagedSeq.scala +++ b/src/library/scala/collection/immutable/PagedSeq.scala @@ -13,6 +13,7 @@ package immutable import java.io._ import scala.util.matching.Regex +import reflect.ClassTag /** The `PagedSeq` object defines a lazy implementations of * a random access sequence. @@ -25,7 +26,7 @@ object PagedSeq { final val UndeterminedEnd = Int.MaxValue /** Constructs a paged sequence from an iterator */ - def fromIterator[T: ArrayTag](source: Iterator[T]): PagedSeq[T] = + def fromIterator[T: ClassTag](source: Iterator[T]): PagedSeq[T] = new PagedSeq[T]((data: Array[T], start: Int, len: Int) => { var i = 0 while (i < len && source.hasNext) { @@ -36,7 +37,7 @@ object PagedSeq { }) /** Constructs a paged sequence from an iterable */ - def fromIterable[T: ArrayTag](source: Iterable[T]): PagedSeq[T] = + def fromIterable[T: ClassTag](source: Iterable[T]): PagedSeq[T] = fromIterator(source.iterator) /** Constructs a paged character sequence from a string iterator */ @@ -115,7 +116,7 @@ import PagedSeq._ * It returns the number of elements produced, or -1 if end of logical input stream was reached * before reading any element. * - * @tparam T the type of the elements contained in this paged sequence, with an `ArrayTag` context bound. + * @tparam T the type of the elements contained in this paged sequence, with an `ClassTag` context bound. * * @author Martin Odersky * @since 2.7 @@ -124,7 +125,7 @@ import PagedSeq._ * @define mayNotTerminateInf * @define willNotTerminateInf */ -class PagedSeq[T: ArrayTag] protected( +class PagedSeq[T: ClassTag] protected( more: (Array[T], Int, Int) => Int, first1: Page[T], start: Int, @@ -205,7 +206,7 @@ extends scala.collection.AbstractSeq[T] /** Page containing up to PageSize characters of the input sequence. */ -private class Page[T: ArrayTag](val num: Int) { +private class Page[T: ClassTag](val num: Int) { private final val PageSize = 4096 diff --git a/src/library/scala/collection/immutable/StringLike.scala b/src/library/scala/collection/immutable/StringLike.scala index e41b17a5e8..af7662d2e0 100644 --- a/src/library/scala/collection/immutable/StringLike.scala +++ b/src/library/scala/collection/immutable/StringLike.scala @@ -13,6 +13,7 @@ import generic._ import mutable.Builder import scala.util.matching.Regex import scala.math.ScalaNumber +import reflect.ClassTag /** A companion object for the `StringLike` containing some constants. * @since 2.8 @@ -239,7 +240,7 @@ self => else throw new IllegalArgumentException("For input string: \"null\"") - override def toArray[B >: Char : ArrayTag]: Array[B] = + override def toArray[B >: Char : ClassTag]: Array[B] = toString.toCharArray.asInstanceOf[Array[B]] private def unwrapArg(arg: Any): AnyRef = arg match { diff --git a/src/library/scala/collection/mutable/ArrayBuilder.scala b/src/library/scala/collection/mutable/ArrayBuilder.scala index 293e85a97e..0eb96de6d7 100644 --- a/src/library/scala/collection/mutable/ArrayBuilder.scala +++ b/src/library/scala/collection/mutable/ArrayBuilder.scala @@ -12,7 +12,7 @@ package scala.collection package mutable import generic._ -import scala.reflect.ArrayTag +import scala.reflect.ClassTag import scala.runtime.ScalaRunTime /** A builder class for arrays. @@ -31,13 +31,12 @@ object ArrayBuilder { /** Creates a new arraybuilder of type `T`. * - * @tparam T type of the elements for the array builder, with a `ArrayTag` context bound. + * @tparam T type of the elements for the array builder, with a `ClassTag` context bound. * @return a new empty array builder. */ - def make[T: ArrayTag](): ArrayBuilder[T] = { - val tag = implicitly[ArrayTag[T]] - val erasure = ScalaRunTime.arrayElementClass(tag) - erasure match { + def make[T: ClassTag](): ArrayBuilder[T] = { + val tag = implicitly[ClassTag[T]] + tag.runtimeClass match { case java.lang.Byte.TYPE => new ArrayBuilder.ofByte().asInstanceOf[ArrayBuilder[T]] case java.lang.Short.TYPE => new ArrayBuilder.ofShort().asInstanceOf[ArrayBuilder[T]] case java.lang.Character.TYPE => new ArrayBuilder.ofChar().asInstanceOf[ArrayBuilder[T]] @@ -47,15 +46,15 @@ object ArrayBuilder { case java.lang.Double.TYPE => new ArrayBuilder.ofDouble().asInstanceOf[ArrayBuilder[T]] case java.lang.Boolean.TYPE => new ArrayBuilder.ofBoolean().asInstanceOf[ArrayBuilder[T]] case java.lang.Void.TYPE => new ArrayBuilder.ofUnit().asInstanceOf[ArrayBuilder[T]] - case _ => new ArrayBuilder.ofRef[T with AnyRef]()(tag.asInstanceOf[ArrayTag[T with AnyRef]]).asInstanceOf[ArrayBuilder[T]] + case _ => new ArrayBuilder.ofRef[T with AnyRef]()(tag.asInstanceOf[ClassTag[T with AnyRef]]).asInstanceOf[ArrayBuilder[T]] } } /** A class for array builders for arrays of reference types. * - * @tparam T type of elements for the array builder, subtype of `AnyRef` with a `ArrayTag` context bound. + * @tparam T type of elements for the array builder, subtype of `AnyRef` with a `ClassTag` context bound. */ - class ofRef[T <: AnyRef : ArrayTag] extends ArrayBuilder[T] { + class ofRef[T <: AnyRef : ClassTag] extends ArrayBuilder[T] { private var elems: Array[T] = _ private var capacity: Int = 0 diff --git a/src/library/scala/collection/mutable/ArrayOps.scala b/src/library/scala/collection/mutable/ArrayOps.scala index 0807721f7d..01636eb54e 100644 --- a/src/library/scala/collection/mutable/ArrayOps.scala +++ b/src/library/scala/collection/mutable/ArrayOps.scala @@ -12,7 +12,7 @@ package scala.collection package mutable import compat.Platform.arraycopy -import scala.reflect.ArrayTag +import scala.reflect.ClassTag import scala.runtime.ScalaRunTime._ import parallel.mutable.ParArray @@ -47,8 +47,8 @@ abstract class ArrayOps[T] extends ArrayLike[T, Array[T]] with CustomParalleliza Array.copy(repr, 0, xs, start, l) } - override def toArray[U >: T : ArrayTag]: Array[U] = { - val thatElementClass = arrayElementClass(implicitly[ArrayTag[U]]) + override def toArray[U >: T : ClassTag]: Array[U] = { + val thatElementClass = arrayElementClass(implicitly[ClassTag[U]]) if (elementClass eq thatElementClass) repr.asInstanceOf[Array[U]] else @@ -64,7 +64,7 @@ abstract class ArrayOps[T] extends ArrayLike[T, Array[T]] with CustomParalleliza * @param asTrav A function that converts elements of this array to rows - arrays of type `U`. * @return An array obtained by concatenating rows of this array. */ - def flatten[U, To](implicit asTrav: T => collection.Traversable[U], m: ArrayTag[U]): Array[U] = { + def flatten[U, To](implicit asTrav: T => collection.Traversable[U], m: ClassTag[U]): Array[U] = { val b = Array.newBuilder[U] b.sizeHint(map{case is: collection.IndexedSeq[_] => is.size case _ => 0}.sum) for (xs <- this) diff --git a/src/library/scala/collection/mutable/ArrayStack.scala b/src/library/scala/collection/mutable/ArrayStack.scala index ed5f39f21b..040a0e2aa7 100644 --- a/src/library/scala/collection/mutable/ArrayStack.scala +++ b/src/library/scala/collection/mutable/ArrayStack.scala @@ -10,6 +10,7 @@ package scala.collection package mutable import generic._ +import reflect.ClassTag /** Factory object for the `ArrayStack` class. * @@ -21,7 +22,7 @@ object ArrayStack extends SeqFactory[ArrayStack] { implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, ArrayStack[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]] def newBuilder[A]: Builder[A, ArrayStack[A]] = new ArrayStack[A] def empty: ArrayStack[Nothing] = new ArrayStack() - def apply[A: ArrayTag](elems: A*): ArrayStack[A] = { + def apply[A: ClassTag](elems: A*): ArrayStack[A] = { val els: Array[AnyRef] = elems.reverseMap(_.asInstanceOf[AnyRef])(breakOut) if (els.length == 0) new ArrayStack() else new ArrayStack[A](els, els.length) diff --git a/src/library/scala/collection/mutable/UnrolledBuffer.scala b/src/library/scala/collection/mutable/UnrolledBuffer.scala index 0c2e6e1cae..6785aba10d 100644 --- a/src/library/scala/collection/mutable/UnrolledBuffer.scala +++ b/src/library/scala/collection/mutable/UnrolledBuffer.scala @@ -12,6 +12,7 @@ import collection.AbstractIterator import collection.Iterator import collection.generic._ import annotation.tailrec +import reflect.ClassTag /** A buffer that stores elements in an unrolled linked list. * @@ -41,11 +42,11 @@ import annotation.tailrec * */ @SerialVersionUID(1L) -class UnrolledBuffer[T](implicit val tag: ArrayTag[T]) +class UnrolledBuffer[T](implicit val tag: ClassTag[T]) extends collection.mutable.AbstractBuffer[T] with collection.mutable.Buffer[T] with collection.mutable.BufferLike[T, UnrolledBuffer[T]] - with GenericArrayTagTraversableTemplate[T, UnrolledBuffer] + with GenericClassTagTraversableTemplate[T, UnrolledBuffer] with collection.mutable.Builder[T, UnrolledBuffer[T]] with Serializable { @@ -67,7 +68,7 @@ extends collection.mutable.AbstractBuffer[T] private[collection] def calcNextLength(sz: Int) = sz - def arrayTagCompanion = UnrolledBuffer + def classTagCompanion = UnrolledBuffer /** Concatenates the targer unrolled buffer to this unrolled buffer. * @@ -185,11 +186,11 @@ extends collection.mutable.AbstractBuffer[T] } -object UnrolledBuffer extends ArrayTagTraversableFactory[UnrolledBuffer] { +object UnrolledBuffer extends ClassTagTraversableFactory[UnrolledBuffer] { /** $genericCanBuildFromInfo */ - implicit def canBuildFrom[T](implicit t: ArrayTag[T]): CanBuildFrom[Coll, T, UnrolledBuffer[T]] = + implicit def canBuildFrom[T](implicit t: ClassTag[T]): CanBuildFrom[Coll, T, UnrolledBuffer[T]] = new GenericCanBuildFrom[T] - def newBuilder[T](implicit t: ArrayTag[T]): Builder[T, UnrolledBuffer[T]] = new UnrolledBuffer[T] + def newBuilder[T](implicit t: ClassTag[T]): Builder[T, UnrolledBuffer[T]] = new UnrolledBuffer[T] val waterline = 50 val waterlineDelim = 100 @@ -197,7 +198,7 @@ object UnrolledBuffer extends ArrayTagTraversableFactory[UnrolledBuffer] { /** Unrolled buffer node. */ - class Unrolled[T: ArrayTag] private[collection] (var size: Int, var array: Array[T], var next: Unrolled[T], val buff: UnrolledBuffer[T] = null) { + class Unrolled[T: ClassTag] private[collection] (var size: Int, var array: Array[T], var next: Unrolled[T], val buff: UnrolledBuffer[T] = null) { private[collection] def this() = this(0, new Array[T](unrolledlength), null, null) private[collection] def this(b: UnrolledBuffer[T]) = this(0, new Array[T](unrolledlength), null, b) diff --git a/src/library/scala/collection/mutable/WrappedArray.scala b/src/library/scala/collection/mutable/WrappedArray.scala index 86317819a1..fec0fbaa3c 100644 --- a/src/library/scala/collection/mutable/WrappedArray.scala +++ b/src/library/scala/collection/mutable/WrappedArray.scala @@ -11,7 +11,7 @@ package scala.collection package mutable -import scala.reflect.ArrayTag +import scala.reflect.ClassTag import scala.runtime.ScalaRunTime._ import scala.collection.generic._ import scala.collection.parallel.mutable.ParArray @@ -42,7 +42,7 @@ extends AbstractSeq[T] override protected[this] def toCollection(repr: WrappedArray[T]): WrappedArray[T] = repr /** The tag of the element type */ - def elemTag: ArrayTag[T] + def elemTag: ClassTag[T] @deprecated("use elemTag instead", "2.10.0") def elemManifest: ClassManifest[T] = ClassManifest.fromClass[T](arrayElementClass(elemTag).asInstanceOf[Class[T]]) @@ -64,8 +64,8 @@ extends AbstractSeq[T] private def elementClass: Class[_] = arrayElementClass(repr.getClass) - override def toArray[U >: T : ArrayTag]: Array[U] = { - val thatElementClass = arrayElementClass(implicitly[ArrayTag[U]]) + override def toArray[U >: T : ClassTag]: Array[U] = { + val thatElementClass = arrayElementClass(implicitly[ClassTag[U]]) if (elementClass eq thatElementClass) array.asInstanceOf[Array[U]] else @@ -110,7 +110,7 @@ object WrappedArray { case x: Array[Unit] => new ofUnit(x) }).asInstanceOf[WrappedArray[T]] - implicit def canBuildFrom[T](implicit m: ArrayTag[T]): CanBuildFrom[WrappedArray[_], T, WrappedArray[T]] = + implicit def canBuildFrom[T](implicit m: ClassTag[T]): CanBuildFrom[WrappedArray[_], T, WrappedArray[T]] = new CanBuildFrom[WrappedArray[_], T, WrappedArray[T]] { def apply(from: WrappedArray[_]): Builder[T, WrappedArray[T]] = ArrayBuilder.make[T]()(m) mapResult WrappedArray.make[T] diff --git a/src/library/scala/collection/mutable/WrappedArrayBuilder.scala b/src/library/scala/collection/mutable/WrappedArrayBuilder.scala index 99a0b0ede3..b7db8d1245 100644 --- a/src/library/scala/collection/mutable/WrappedArrayBuilder.scala +++ b/src/library/scala/collection/mutable/WrappedArrayBuilder.scala @@ -12,7 +12,7 @@ package scala.collection package mutable import generic._ -import scala.reflect.ArrayTag +import scala.reflect.ClassTag import scala.runtime.ScalaRunTime._ /** A builder class for arrays. @@ -22,18 +22,18 @@ import scala.runtime.ScalaRunTime._ * * @since 2.8 */ -class WrappedArrayBuilder[A](tag: ArrayTag[A]) extends Builder[A, WrappedArray[A]] { +class WrappedArrayBuilder[A](tag: ClassTag[A]) extends Builder[A, WrappedArray[A]] { @deprecated("use tag instead", "2.10.0") - val manifest: ArrayTag[A] = tag + val manifest: ClassTag[A] = tag private var elems: WrappedArray[A] = _ private var capacity: Int = 0 private var size: Int = 0 private def mkArray(size: Int): WrappedArray[A] = { - val erasure = arrayElementClass(tag) - val newelems = erasure match { + val runtimeClass = arrayElementClass(tag) + val newelems = runtimeClass match { case java.lang.Byte.TYPE => new WrappedArray.ofByte(new Array[Byte](size)).asInstanceOf[WrappedArray[A]] case java.lang.Short.TYPE => new WrappedArray.ofShort(new Array[Short](size)).asInstanceOf[WrappedArray[A]] case java.lang.Character.TYPE => new WrappedArray.ofChar(new Array[Char](size)).asInstanceOf[WrappedArray[A]] diff --git a/src/library/scala/collection/parallel/ParIterableLike.scala b/src/library/scala/collection/parallel/ParIterableLike.scala index 321f259f5d..a447f1b5e4 100644 --- a/src/library/scala/collection/parallel/ParIterableLike.scala +++ b/src/library/scala/collection/parallel/ParIterableLike.scala @@ -24,6 +24,7 @@ import scala.collection.GenIterable import scala.collection.GenTraversableOnce import scala.collection.GenTraversable import immutable.HashMapCombiner +import reflect.{ClassTag, classTag} import java.util.concurrent.atomic.AtomicBoolean @@ -183,25 +184,25 @@ self: ParIterableLike[T, Repr, Sequential] => def hasDefiniteSize = true def isEmpty = size == 0 - + def nonEmpty = size != 0 - + def head = iterator.next - + def headOption = if (nonEmpty) Some(head) else None - + def tail = drop(1) - + def last = { var lst = head for (x <- this.seq) lst = x lst } - + def lastOption = if (nonEmpty) Some(last) else None - + def init = take(size - 1) - + /** Creates a new parallel iterator used to traverse the elements of this parallel collection. * This iterator is more specific than the iterator of the returned by `iterator`, and augmented * with additional accessor and transformer methods. @@ -303,7 +304,7 @@ self: ParIterableLike[T, Repr, Sequential] => protected implicit def builder2ops[Elem, To](cb: Builder[Elem, To]) = new BuilderOps[Elem, To] { def ifIs[Cmb](isbody: Cmb => Unit) = new Otherwise[Cmb] { def otherwise(notbody: => Unit)(implicit t: ClassTag[Cmb]) { - if (cb.getClass == t.erasure) isbody(cb.asInstanceOf[Cmb]) else notbody + if (cb.getClass == t.runtimeClass) isbody(cb.asInstanceOf[Cmb]) else notbody } } def isCombiner = cb.isInstanceOf[Combiner[_, _]] @@ -822,7 +823,7 @@ self: ParIterableLike[T, Repr, Sequential] => def size = splitter.remaining } - override def toArray[U >: T: ArrayTag]: Array[U] = { + override def toArray[U >: T: ClassTag]: Array[U] = { val arr = new Array[U](size) copyToArray(arr) arr diff --git a/src/library/scala/collection/parallel/mutable/ParArray.scala b/src/library/scala/collection/parallel/mutable/ParArray.scala index 29d84408db..6889d8b472 100644 --- a/src/library/scala/collection/parallel/mutable/ParArray.scala +++ b/src/library/scala/collection/parallel/mutable/ParArray.scala @@ -26,7 +26,7 @@ import scala.collection.parallel.CHECK_RATE import scala.collection.mutable.ArraySeq import scala.collection.mutable.Builder import scala.collection.GenTraversableOnce - +import scala.reflect.ClassTag @@ -706,7 +706,7 @@ object ParArray extends ParFactory[ParArray] { case _ => new ParArray[T](new ExposedArraySeq[T](runtime.ScalaRunTime.toObjectArray(arr), sz)) } - def createFromCopy[T <: AnyRef : ArrayTag](arr: Array[T]): ParArray[T] = { + def createFromCopy[T <: AnyRef : ClassTag](arr: Array[T]): ParArray[T] = { val newarr = new Array[T](arr.length) Array.copy(arr, 0, newarr, 0, arr.length) handoff(newarr) diff --git a/src/library/scala/collection/parallel/mutable/UnrolledParArrayCombiner.scala b/src/library/scala/collection/parallel/mutable/UnrolledParArrayCombiner.scala index 43d40776bf..9648791502 100644 --- a/src/library/scala/collection/parallel/mutable/UnrolledParArrayCombiner.scala +++ b/src/library/scala/collection/parallel/mutable/UnrolledParArrayCombiner.scala @@ -21,12 +21,12 @@ import scala.collection.parallel.TaskSupport import scala.collection.parallel.unsupportedop import scala.collection.parallel.Combiner import scala.collection.parallel.Task +import scala.reflect.ClassTag - -private[mutable] class DoublingUnrolledBuffer[T](implicit t: ArrayTag[T]) extends UnrolledBuffer[T]()(t) { +private[mutable] class DoublingUnrolledBuffer[T](implicit t: ClassTag[T]) extends UnrolledBuffer[T]()(t) { override def calcNextLength(sz: Int) = if (sz < 10000) sz * 2 else sz protected override def newUnrolled = new Unrolled[T](0, new Array[T](4), null, this) } diff --git a/src/library/scala/concurrent/Future.scala b/src/library/scala/concurrent/Future.scala index c42393eee2..2a52d0ac0b 100644 --- a/src/library/scala/concurrent/Future.scala +++ b/src/library/scala/concurrent/Future.scala @@ -25,6 +25,7 @@ import scala.annotation.tailrec import scala.collection.mutable.Stack import scala.collection.mutable.Builder import scala.collection.generic.CanBuildFrom +import scala.reflect.ClassTag import language.higherKinds @@ -489,7 +490,7 @@ trait Future[+T] extends Awaitable[T] { case l: Left[_, _] => p complete l.asInstanceOf[Left[Throwable, S]] case Right(t) => p complete (try { - Right(boxedType(tag.erasure).cast(t).asInstanceOf[S]) + Right(boxedType(tag.runtimeClass).cast(t).asInstanceOf[S]) } catch { case e: ClassCastException => Left(e) }) diff --git a/src/library/scala/languageFeature.scala b/src/library/scala/languageFeature.scala index c990f714c1..c32f1eb724 100644 --- a/src/library/scala/languageFeature.scala +++ b/src/library/scala/languageFeature.scala @@ -4,26 +4,26 @@ import annotation.meta object languageFeature { - @meta.languageFeature("extension of type scala.Dynamic", true) + @meta.languageFeature("extension of type scala.Dynamic", enableRequired = true) sealed trait dynamics - @meta.languageFeature("postfix operator #", false) + @meta.languageFeature("postfix operator #", enableRequired = false) sealed trait postfixOps - @meta.languageFeature("reflective access of structural type member #", false) + @meta.languageFeature("reflective access of structural type member #", enableRequired = false) sealed trait reflectiveCalls - @meta.languageFeature("implicit conversion #", false) + @meta.languageFeature("implicit conversion #", enableRequired = false) sealed trait implicitConversions - @meta.languageFeature("higher-kinded type", false) + @meta.languageFeature("higher-kinded type", enableRequired = false) sealed trait higherKinds - @meta.languageFeature("#, which cannot be expressed by wildcards, ", false) + @meta.languageFeature("#, which cannot be expressed by wildcards, ", enableRequired = false) sealed trait existentials object experimental { - @meta.languageFeature("macro definition", true) + @meta.languageFeature("macro definition", enableRequired = true) sealed trait macros } } diff --git a/src/library/scala/ref/WeakReference.scala b/src/library/scala/ref/WeakReference.scala index 98cfb2c84b..322eab0be4 100644 --- a/src/library/scala/ref/WeakReference.scala +++ b/src/library/scala/ref/WeakReference.scala @@ -10,6 +10,9 @@ package scala.ref /** + * A wrapper class for java.lag.ref.WeakReference + * The new functionality is (1) results are Option values, instead of using null. + * (2) There is an extractor that maps the weak reference itself into an option. * @author Sean McDirmid */ class WeakReference[+T <: AnyRef](value: T, queue: ReferenceQueue[T]) extends ReferenceWrapper[T] { @@ -18,6 +21,19 @@ class WeakReference[+T <: AnyRef](value: T, queue: ReferenceQueue[T]) extends Re new WeakReferenceWithWrapper[T](value, queue, this) } +/** An extractor for weak reference values */ +object WeakReference { + + /** Creates a weak reference pointing to `value` */ + def apply[T <: AnyRef](value: T) = new WeakReference(value) + + /** Optionally returns the referenced value, or `None` if that value no longer exists */ + def unapply[T <: AnyRef](wr: WeakReference[T]): Option[T] = { + val x = wr.underlying.get + if (x != null) Some(x) else None + } +} + /** * @author Philipp Haller */ diff --git a/src/library/scala/reflect/ArrayTag.scala b/src/library/scala/reflect/ArrayTag.scala deleted file mode 100644 index ba0c075723..0000000000 --- a/src/library/scala/reflect/ArrayTag.scala +++ /dev/null @@ -1,25 +0,0 @@ -package scala.reflect - -/** An `ArrayTag[T]` is a descriptor that is requested by the compiler every time - * when an array is instantiated, but the element type is unknown at compile time. - * - * Implicit in the contract of `ArrayTag[T]` is the fact that `T` - * cannot contain unresolved references to type parameters or abstract types. - * - * Scala library provides a standard implementation of this trait, - * `ClassTag[T]` that explicitly carries the `java.lang.Class` erasure of type T - * and uses Java reflection to instantiate arrays. - * - * However other platforms (e.g. a Scala -> JS crosscompiler) may reimplement this trait as they see fit - * and then expose the implementation via an implicit macro. - * - * @see [[scala.reflect.api.TypeTags]] - */ -@annotation.implicitNotFound(msg = "No ArrayTag available for ${T}") -trait ArrayTag[T] { - /** Produces an `ArrayTag` that knows how to build `Array[Array[T]]` */ - def wrap: ArrayTag[Array[T]] - - /** Produces a new array with element type `T` and length `len` */ - def newArray(len: Int): Array[T] -}
\ No newline at end of file diff --git a/src/library/scala/reflect/ClassManifest.scala b/src/library/scala/reflect/ClassManifest.scala index 43e043fd40..d89d31f689 100644 --- a/src/library/scala/reflect/ClassManifest.scala +++ b/src/library/scala/reflect/ClassManifest.scala @@ -27,6 +27,7 @@ trait ClassManifest[T] extends OptManifest[T] with ClassTag[T] with Equals with /** A class representing the type `U` to which `T` would be erased. Note * that there is no subtyping relationship between `T` and `U`. */ def erasure: jClass[_] + override def runtimeClass: jClass[_] = erasure private def subtype(sub: jClass[_], sup: jClass[_]): Boolean = { def loop(left: Set[jClass[_]], seen: Set[jClass[_]]): Boolean = { diff --git a/src/library/scala/reflect/ClassTag.scala b/src/library/scala/reflect/ClassTag.scala index e485691747..f753dfbcbb 100644 --- a/src/library/scala/reflect/ClassTag.scala +++ b/src/library/scala/reflect/ClassTag.scala @@ -1,39 +1,37 @@ package scala.reflect import java.lang.{ Class => jClass } -import scala.reflect.{ mirror => rm } import language.{implicitConversions, existentials} import scala.runtime.ScalaRunTime.arrayClass -/** A `ClassTag[T]` wraps a Java class, which can be accessed via the `erasure` method. +/** A `ClassTag[T]` wraps a runtime class, which can be accessed via the `runtimeClass` method. * * This is useful in itself, but also enables very important use case. * Having this knowledge ClassTag can instantiate `Arrays` * in those cases where the element type is unknown at compile time. - * Hence, ClassTag[T] conforms to the ArrayTag[T] trait. * * If an implicit value of type u.ClassTag[T] is required, the compiler will make one up on demand. - * The implicitly created value contains in its erasure field the Java class that is the result of erasing type T. + * The implicitly created value contains in its `runtimeClass` field the runtime class that is the result of erasing type T. * In that value, any occurrences of type parameters or abstract types U which come themselves with a ClassTag - * or a reflect.mirror.ConcreteTypeTag are represented by the type referenced by that tag. + * are represented by the type referenced by that tag. * If the type T contains unresolved references to type parameters or abstract types, a static error results. * - * A ConcreteTypeTag member of the reflect.mirror object is convertible to a ClassTag via an implicit conversion - * (this is not possible to do in all reflection universes because an operation that converts a type to a Java class might not be available). - * - * @see [[scala.reflect.api.TypeTags]] + * @see [[scala.reflect.base.TypeTags]] */ @annotation.implicitNotFound(msg = "No ClassTag available for ${T}") -trait ClassTag[T] extends ArrayTag[T] with ErasureTag[T] with Equals with Serializable { +trait ClassTag[T] extends Equals with Serializable { // please, don't add any APIs here, like it was with `newWrappedArray` and `newArrayBuilder` // class tags, and all tags in general, should be as minimalistic as possible + /** Returns a runtime class of type `T` */ + def runtimeClass: jClass[_] + /** Produces a `ClassTag` that knows how to build `Array[Array[T]]` */ - def wrap: ClassTag[Array[T]] = ClassTag[Array[T]](arrayClass(erasure)) + def wrap: ClassTag[Array[T]] = ClassTag[Array[T]](arrayClass(runtimeClass)) /** Produces a new array with element type `T` and length `len` */ def newArray(len: Int): Array[T] = - erasure match { + runtimeClass match { case java.lang.Byte.TYPE => new Array[Byte](len).asInstanceOf[Array[T]] case java.lang.Short.TYPE => new Array[Short](len).asInstanceOf[Array[T]] case java.lang.Character.TYPE => new Array[Char](len).asInstanceOf[Array[T]] @@ -43,14 +41,24 @@ trait ClassTag[T] extends ArrayTag[T] with ErasureTag[T] with Equals with Serial case java.lang.Double.TYPE => new Array[Double](len).asInstanceOf[Array[T]] case java.lang.Boolean.TYPE => new Array[Boolean](len).asInstanceOf[Array[T]] case java.lang.Void.TYPE => new Array[Unit](len).asInstanceOf[Array[T]] - case _ => java.lang.reflect.Array.newInstance(erasure, len).asInstanceOf[Array[T]] + case _ => java.lang.reflect.Array.newInstance(runtimeClass, len).asInstanceOf[Array[T]] } + /** A ClassTag[T] can serve as an extractor that matches only objects of type T. + * + * The compiler tries to turn unchecked type tests in pattern matches into checked ones + * by wrapping a `(_: T)` type pattern as `ct(_: T)`, where `ct` is the `ClassTag[T]` instance. + * Type tests necessary before calling other extractors are treated similarly. + * `SomeExtractor(...)` is turned into `ct(SomeExtractor(...))` if `T` in `SomeExtractor.unapply(x: T)` + * is uncheckable, but we have an instance of `ClassTag[T]`. + */ + def unapply(x: Any): Option[T] = if (runtimeClass.isAssignableFrom(x.getClass)) Some(x.asInstanceOf[T]) else None + /** case class accessories */ override def canEqual(x: Any) = x.isInstanceOf[ClassTag[_]] - override def equals(x: Any) = x.isInstanceOf[ClassTag[_]] && this.erasure == x.asInstanceOf[ClassTag[_]].erasure - override def hashCode = scala.runtime.ScalaRunTime.hash(erasure) - override def toString = "ClassTag[" + erasure + "]" + override def equals(x: Any) = x.isInstanceOf[ClassTag[_]] && this.runtimeClass == x.asInstanceOf[ClassTag[_]].runtimeClass + override def hashCode = scala.runtime.ScalaRunTime.hash(runtimeClass) + override def toString = "ClassTag[" + runtimeClass + "]" } object ClassTag { @@ -59,25 +67,25 @@ object ClassTag { private val ObjectTYPE = classOf[java.lang.Object] private val StringTYPE = classOf[java.lang.String] - val Byte : ClassTag[scala.Byte] = new ClassTag[scala.Byte]{ def erasure = java.lang.Byte.TYPE; private def readResolve() = ClassTag.Byte } - val Short : ClassTag[scala.Short] = new ClassTag[scala.Short]{ def erasure = java.lang.Short.TYPE; private def readResolve() = ClassTag.Short } - val Char : ClassTag[scala.Char] = new ClassTag[scala.Char]{ def erasure = java.lang.Character.TYPE; private def readResolve() = ClassTag.Char } - val Int : ClassTag[scala.Int] = new ClassTag[scala.Int]{ def erasure = java.lang.Integer.TYPE; private def readResolve() = ClassTag.Int } - val Long : ClassTag[scala.Long] = new ClassTag[scala.Long]{ def erasure = java.lang.Long.TYPE; private def readResolve() = ClassTag.Long } - val Float : ClassTag[scala.Float] = new ClassTag[scala.Float]{ def erasure = java.lang.Float.TYPE; private def readResolve() = ClassTag.Float } - val Double : ClassTag[scala.Double] = new ClassTag[scala.Double]{ def erasure = java.lang.Double.TYPE; private def readResolve() = ClassTag.Double } - val Boolean : ClassTag[scala.Boolean] = new ClassTag[scala.Boolean]{ def erasure = java.lang.Boolean.TYPE; private def readResolve() = ClassTag.Boolean } - val Unit : ClassTag[scala.Unit] = new ClassTag[scala.Unit]{ def erasure = java.lang.Void.TYPE; private def readResolve() = ClassTag.Unit } - val Any : ClassTag[scala.Any] = new ClassTag[scala.Any]{ def erasure = ObjectTYPE; private def readResolve() = ClassTag.Any } - val Object : ClassTag[java.lang.Object] = new ClassTag[java.lang.Object]{ def erasure = ObjectTYPE; private def readResolve() = ClassTag.Object } - val AnyVal : ClassTag[scala.AnyVal] = new ClassTag[scala.AnyVal]{ def erasure = ObjectTYPE; private def readResolve() = ClassTag.AnyVal } - val AnyRef : ClassTag[scala.AnyRef] = new ClassTag[scala.AnyRef]{ def erasure = ObjectTYPE; private def readResolve() = ClassTag.AnyRef } - val Nothing : ClassTag[scala.Nothing] = new ClassTag[scala.Nothing]{ def erasure = NothingTYPE; private def readResolve() = ClassTag.Nothing } - val Null : ClassTag[scala.Null] = new ClassTag[scala.Null]{ def erasure = NullTYPE; private def readResolve() = ClassTag.Null } - val String : ClassTag[java.lang.String] = new ClassTag[java.lang.String]{ def erasure = StringTYPE; private def readResolve() = ClassTag.String } + val Byte : ClassTag[scala.Byte] = new ClassTag[scala.Byte]{ def runtimeClass = java.lang.Byte.TYPE; private def readResolve() = ClassTag.Byte } + val Short : ClassTag[scala.Short] = new ClassTag[scala.Short]{ def runtimeClass = java.lang.Short.TYPE; private def readResolve() = ClassTag.Short } + val Char : ClassTag[scala.Char] = new ClassTag[scala.Char]{ def runtimeClass = java.lang.Character.TYPE; private def readResolve() = ClassTag.Char } + val Int : ClassTag[scala.Int] = new ClassTag[scala.Int]{ def runtimeClass = java.lang.Integer.TYPE; private def readResolve() = ClassTag.Int } + val Long : ClassTag[scala.Long] = new ClassTag[scala.Long]{ def runtimeClass = java.lang.Long.TYPE; private def readResolve() = ClassTag.Long } + val Float : ClassTag[scala.Float] = new ClassTag[scala.Float]{ def runtimeClass = java.lang.Float.TYPE; private def readResolve() = ClassTag.Float } + val Double : ClassTag[scala.Double] = new ClassTag[scala.Double]{ def runtimeClass = java.lang.Double.TYPE; private def readResolve() = ClassTag.Double } + val Boolean : ClassTag[scala.Boolean] = new ClassTag[scala.Boolean]{ def runtimeClass = java.lang.Boolean.TYPE; private def readResolve() = ClassTag.Boolean } + val Unit : ClassTag[scala.Unit] = new ClassTag[scala.Unit]{ def runtimeClass = java.lang.Void.TYPE; private def readResolve() = ClassTag.Unit } + val Any : ClassTag[scala.Any] = new ClassTag[scala.Any]{ def runtimeClass = ObjectTYPE; private def readResolve() = ClassTag.Any } + val Object : ClassTag[java.lang.Object] = new ClassTag[java.lang.Object]{ def runtimeClass = ObjectTYPE; private def readResolve() = ClassTag.Object } + val AnyVal : ClassTag[scala.AnyVal] = new ClassTag[scala.AnyVal]{ def runtimeClass = ObjectTYPE; private def readResolve() = ClassTag.AnyVal } + val AnyRef : ClassTag[scala.AnyRef] = new ClassTag[scala.AnyRef]{ def runtimeClass = ObjectTYPE; private def readResolve() = ClassTag.AnyRef } + val Nothing : ClassTag[scala.Nothing] = new ClassTag[scala.Nothing]{ def runtimeClass = NothingTYPE; private def readResolve() = ClassTag.Nothing } + val Null : ClassTag[scala.Null] = new ClassTag[scala.Null]{ def runtimeClass = NullTYPE; private def readResolve() = ClassTag.Null } + val String : ClassTag[java.lang.String] = new ClassTag[java.lang.String]{ def runtimeClass = StringTYPE; private def readResolve() = ClassTag.String } - def apply[T](erasure1: jClass[_]): ClassTag[T] = - erasure1 match { + def apply[T](runtimeClass1: jClass[_]): ClassTag[T] = + runtimeClass1 match { case java.lang.Byte.TYPE => ClassTag.Byte.asInstanceOf[ClassTag[T]] case java.lang.Short.TYPE => ClassTag.Short.asInstanceOf[ClassTag[T]] case java.lang.Character.TYPE => ClassTag.Char.asInstanceOf[ClassTag[T]] @@ -89,8 +97,8 @@ object ClassTag { case java.lang.Void.TYPE => ClassTag.Unit.asInstanceOf[ClassTag[T]] case ObjectTYPE => ClassTag.Object.asInstanceOf[ClassTag[T]] case StringTYPE => ClassTag.String.asInstanceOf[ClassTag[T]] - case _ => new ClassTag[T]{ def erasure = erasure1 } + case _ => new ClassTag[T]{ def runtimeClass = runtimeClass1 } } - def unapply[T](ctag: ClassTag[T]): Option[Class[_]] = Some(ctag.erasure) + def unapply[T](ctag: ClassTag[T]): Option[Class[_]] = Some(ctag.runtimeClass) }
\ No newline at end of file diff --git a/src/library/scala/reflect/DummyMirror.scala b/src/library/scala/reflect/DummyMirror.scala deleted file mode 100644 index aa731f62db..0000000000 --- a/src/library/scala/reflect/DummyMirror.scala +++ /dev/null @@ -1,783 +0,0 @@ -package scala.reflect - -import scala.reflect.api.AbsTreeGen -import scala.reflect.api.Attachment -import scala.reflect.api.Modifier -import scala.reflect.api.Universe - -// todo. make Dummy objects not equal to themselves -class DummyMirror(cl: ClassLoader) extends api.Mirror { - // Members declared in scala.reflect.api.AnnotationInfos - implicit def classfileAnnotArgTag: scala.reflect.ClassTag[ClassfileAnnotArg] = notSupported() - type AnnotationInfo = DummyAnnotationInfo.type - object DummyAnnotationInfo - val AnnotationInfo: AnnotationInfoExtractor = DummyAnnotationInfoExtractor - object DummyAnnotationInfoExtractor extends AnnotationInfoExtractor { - def apply(atp: Type, args: List[Tree], assocs: List[(Name, ClassfileAnnotArg)]): AnnotationInfo = DummyAnnotationInfo - def unapply(info: AnnotationInfo): Option[(Type, List[Tree], List[(Name, ClassfileAnnotArg)])] = notSupported() - } - type ClassfileAnnotArg = AnyRef - type LiteralAnnotArg = DummyLiteralAnnotArg.type - object DummyLiteralAnnotArg - val LiteralAnnotArg: LiteralAnnotArgExtractor = DummyLiteralAnnotArgExtractor - type ArrayAnnotArg = DummyArrayAnnotArg.type - object DummyArrayAnnotArg - val ArrayAnnotArg: ArrayAnnotArgExtractor = DummyArrayAnnotArgExtractor - type NestedAnnotArg = DummyNestedAnnotArg.type - object DummyNestedAnnotArg - val NestedAnnotArg: NestedAnnotArgExtractor = DummyNestedAnnotArgExtractor - object DummyLiteralAnnotArgExtractor extends LiteralAnnotArgExtractor { - def apply(const: Constant): LiteralAnnotArg = DummyLiteralAnnotArg - def unapply(arg: LiteralAnnotArg): Option[Constant] = notSupported() - } - object DummyArrayAnnotArgExtractor extends ArrayAnnotArgExtractor { - def apply(const: Array[ClassfileAnnotArg]): ArrayAnnotArg = DummyArrayAnnotArg - def unapply(arg: ArrayAnnotArg): Option[Array[ClassfileAnnotArg]] = notSupported() - } - object DummyNestedAnnotArgExtractor extends NestedAnnotArgExtractor { - def apply(anninfo: AnnotationInfo): NestedAnnotArg = DummyNestedAnnotArg - def unapply(arg: NestedAnnotArg): Option[AnnotationInfo] = notSupported() - } - - // Members declared in scala.reflect.api.Constants - type Constant = DummyConstant.type - object DummyConstant extends AbsConstant { - val value: Any = notSupported() - def tpe: Type = notSupported() - def isNaN: Boolean = notSupported() - def booleanValue: Boolean = notSupported() - def byteValue: Byte = notSupported() - def shortValue: Short = notSupported() - def charValue: Char = notSupported() - def intValue: Int = notSupported() - def longValue: Long = notSupported() - def floatValue: Float = notSupported() - def doubleValue: Double = notSupported() - def stringValue: String = notSupported() - def typeValue: Type = notSupported() - def symbolValue: Symbol = notSupported() - def convertTo(pt: Type): Constant = notSupported() - } - val Constant: ConstantExtractor = DummyConstantExtractor - object DummyConstantExtractor extends ConstantExtractor { - def apply(const: Any): Constant = DummyConstant - def unapply(arg: Constant): Option[Any] = notSupported() - } - - // Members declared in scala.reflect.api.FreeVars - type FreeTerm = DummyFreeTerm.type - val DummyFreeTerm = DummySymbol - val FreeTerm: FreeTermExtractor = DummyFreeTermExtractor - object DummyFreeTermExtractor extends FreeTermExtractor { - def unapply(freeTerm: FreeTerm): Option[(TermName, Type, Any, String)] = notSupported() - } - type FreeType = DummyFreeType.type - val DummyFreeType = DummySymbol - val FreeType: FreeTypeExtractor = DummyFreeTypeExtractor - object DummyFreeTypeExtractor extends FreeTypeExtractor { - def unapply(freeType: FreeType): Option[(TypeName, Type, String)] = notSupported() - } - def freeTerms(tree: Tree): List[FreeTerm] = notSupported() - def freeTypes(tree: Tree): List[FreeType] = notSupported() - def substituteFreeTypes(tpe: Type,subs: Map[FreeType,Type]): Type = notSupported() - def substituteFreeTypes(tree: Tree,subs: Map[FreeType,Type]): Tree = notSupported() - - // Members declared in scala.reflect.api.Importers - def mkImporter(from0: scala.reflect.api.Universe): Importer{val from: from0.type} = notSupported() - - // Members declared in scala.reflect.api.Mirror - def classLoader: ClassLoader = cl - def classLoader_=(x$1: ClassLoader): Unit = notSupported() - def classToSymbol(clazz: Class[_]): Symbol = notSupported() - def classToType(clazz: Class[_]): Type = notSupported() - def companionInstance(clazz: Symbol): AnyRef = notSupported() - def getValueOfField(receiver: AnyRef,field: Symbol): Any = notSupported() - def invoke(receiver: AnyRef,meth: Symbol)(args: Any*): Any = notSupported() - def setValueOfField(receiver: AnyRef,field: Symbol,value: Any): Unit = notSupported() - def symbolForName(name: String): Symbol = notSupported() - def symbolOfInstance(instance: Any): Symbol = notSupported() - def symbolToClass(sym: Symbol): Class[_] = notSupported() - def typeOfInstance(instance: Any): Type = notSupported() - def typeToClass(tpe: Type): Class[_] = notSupported() - - // Members declared in scala.reflect.api.Names - type Name = DummyName.type - type TypeName = DummyName.type - type TermName = DummyName.type - object DummyName extends AbsName { - def isTermName: Boolean = notSupported() - def isTypeName: Boolean = notSupported() - def toTermName: TermName = notSupported() - def toTypeName: TypeName = notSupported() - def decoded: String = notSupported() - def encoded: String = notSupported() - def decodedName: Name = notSupported() - def encodedName: Name = notSupported() - } - def newTermName(s: String): TermName = notSupported() - def newTypeName(s: String): TypeName = notSupported() - - // Members declared in scala.reflect.api.Positions - type Position = DummyPosition.type - object DummyPosition extends api.Position { - def pos: Position = notSupported() - def withPos(newPos: scala.reflect.api.Position): Attachment = notSupported() - def payload: Any = notSupported() - def withPayload(newPayload: Any): Attachment = notSupported() - def fileInfo: java.io.File = notSupported() - def fileContent: Array[Char] = notSupported() - def isDefined: Boolean = notSupported() - def isTransparent: Boolean = notSupported() - def isRange: Boolean = notSupported() - def isOpaqueRange: Boolean = notSupported() - def makeTransparent: Position = notSupported() - def start: Int = notSupported() - def startOrPoint: Int = notSupported() - def point: Int = notSupported() - def pointOrElse(default: Int): Int = notSupported() - def end: Int = notSupported() - def endOrPoint: Int = notSupported() - def withStart(off: Int): Position = notSupported() - def withEnd(off: Int): Position = notSupported() - def withPoint(off: Int): Position = notSupported() - def union(pos: scala.reflect.api.Position): Position = notSupported() - def focusStart: Position = notSupported() - def focus: Position = notSupported() - def focusEnd: Position = notSupported() - def includes(pos: scala.reflect.api.Position): Boolean = notSupported() - def properlyIncludes(pos: scala.reflect.api.Position): Boolean = notSupported() - def precedes(pos: scala.reflect.api.Position): Boolean = notSupported() - def properlyPrecedes(pos: scala.reflect.api.Position): Boolean = notSupported() - def overlaps(pos: scala.reflect.api.Position): Boolean = notSupported() - def sameRange(pos: scala.reflect.api.Position): Boolean = notSupported() - def line: Int = notSupported() - def column: Int = notSupported() - def toSingleLine: Position = notSupported() - def lineContent: String = notSupported() - def show: String = notSupported() - } - val NoPosition: Position = DummyPosition - def atPos[T <: Tree](pos: Position)(tree: T): T = tree - def ensureNonOverlapping(tree: Tree,others: List[Tree]): Unit = notSupported() - def wrappingPos(trees: List[Tree]): Position = notSupported() - def wrappingPos(default: Position,trees: List[Tree]): Position = notSupported() - - // Members declared in scala.reflect.api.FrontEnds - def mkConsoleFrontEnd(minSeverity: Int): FrontEnd = notSupported() - - // Members declared in scala.reflect.api.Scopes - type Scope = DummyScope.type - object DummyScope extends Iterable[Symbol] { - def iterator: Iterator[Symbol] = notSupported() - } - def newScope: Scope = DummyScope - def newScopeWith(elems: Symbol*): Scope = DummyScope - def newNestedScope(outer: Scope): Scope = DummyScope - - // Members declared in scala.reflect.api.StandardDefinitions - val AnyRefTpe: Type = DummyType - val AnyTpe: Type = DummyType - val AnyValTpe: Type = DummyType - val BooleanTpe: Type = DummyType - val ByteTpe: Type = DummyType - val CharTpe: Type = DummyType - val DoubleTpe: Type = DummyType - val FloatTpe: Type = DummyType - val IntTpe: Type = DummyType - val LongTpe: Type = DummyType - val NothingTpe: Type = DummyType - val NullTpe: Type = DummyType - val ObjectTpe: Type = DummyType - val ShortTpe: Type = DummyType - val StringTpe: Type = DummyType - val UnitTpe: Type = DummyType - val definitions: AbsDefinitions = DummyDefinitions - object DummyDefinitions extends AbsDefinitions { - def ByNameParamClass = DummySymbol - def JavaRepeatedParamClass = DummySymbol - def RepeatedParamClass = DummySymbol - def AnyClass = DummyClassSymbol - def AnyRefClass = DummyTypeSymbol - def AnyValClass = DummyClassSymbol - def ArrayClass = DummyClassSymbol - def ArrayModule = DummySymbol - def ArrayModule_overloadedApply = DummySymbol - def Array_apply = DummySymbol - def Array_clone = DummySymbol - def Array_length = DummySymbol - def Array_update = DummySymbol - def BooleanClass = DummyClassSymbol - def ByteClass = DummyClassSymbol - def CharClass = DummyClassSymbol - def ClassClass = DummyClassSymbol - def ClassTagClass = DummyClassSymbol - def ClassTagModule = DummySymbol - def ConcreteTypeTagClass = DummyClassSymbol - def ConcreteTypeTagModule = DummySymbol - def ConsClass = DummySymbol - def DoubleClass = DummyClassSymbol - def EmptyPackage = DummyPackageSymbol - def EmptyPackageClass = DummySymbol - def FloatClass = DummyClassSymbol - def FunctionClass: Array[Symbol] = Array() - def IntClass = DummyClassSymbol - def IterableClass = DummySymbol - def IteratorClass = DummySymbol - def IteratorModule = DummySymbol - def Iterator_apply = DummySymbol - def JavaLangPackage = DummyPackageSymbol - def JavaLangPackageClass = DummySymbol - def ListClass = DummyClassSymbol - def ListModule = DummyModuleSymbol - def List_apply = DummySymbol - def LongClass = DummyClassSymbol - def NilModule = DummySymbol - def NoneModule = DummySymbol - def NothingClass = DummyClassSymbol - def NullClass = DummyClassSymbol - def ObjectClass = DummyClassSymbol - def OptionClass = DummySymbol - def PredefModule = DummyModuleSymbol - def ProductClass: Array[Symbol] = Array() - def RootClass = DummyClassSymbol - def RootPackage = DummyPackageSymbol - def ScalaPackage = DummyPackageSymbol - def ScalaPackageClass = DummySymbol - def ScalaPrimitiveValueClasses = Nil - def SeqClass = DummySymbol - def SeqModule = DummySymbol - def ShortClass = DummyClassSymbol - def SomeClass = DummySymbol - def SomeModule = DummySymbol - def StringBuilderClass = DummySymbol - def StringClass = DummyClassSymbol - def SymbolClass = DummySymbol - def TraversableClass = DummySymbol - def TupleClass: Array[Symbol] = Array() - def TypeTagClass = DummyClassSymbol - def TypeTagModule = DummySymbol - def UnitClass = DummyClassSymbol - def isNumericValueClass(sym: Symbol): Boolean = notSupported() - def isPrimitiveValueClass(sym: Symbol): Boolean = notSupported() - def vmClassType(arg: Type): Type = DummyType - def vmSignature(sym: Symbol,info: Type): String = notSupported() - } - - // Members declared in scala.reflect.api.StandardNames - val nme: AbsTermNames = DummyAbsTermNames - val tpnme: AbsTypeNames = DummyAbsTypeNames - object DummyAbsTermNames extends AbsTermNames { - type NameType = TermName - val EMPTY: NameType = DummyName - val ANON_FUN_NAME: NameType = DummyName - val ANON_CLASS_NAME: NameType = DummyName - val EMPTY_PACKAGE_NAME: NameType = DummyName - val IMPORT: NameType = DummyName - val MODULE_VAR_SUFFIX: NameType = DummyName - val ROOT: NameType = DummyName - val PACKAGE: NameType = DummyName - val SPECIALIZED_SUFFIX: NameType = DummyName - val ERROR: NameType = DummyName - val NO_NAME: NameType = DummyName - val WILDCARD: NameType = DummyName - def flattenedName(segments: Name*): NameType = notSupported() - val EXPAND_SEPARATOR_STRING: String = "" - val ANYNAME: TermName = DummyName - val CONSTRUCTOR: TermName = DummyName - val FAKE_LOCAL_THIS: TermName = DummyName - val INITIALIZER: TermName = DummyName - val LAZY_LOCAL: TermName = DummyName - val LOCAL_SUFFIX_STRING: String = "" - val MIRROR_PREFIX: TermName = DummyName - val MIRROR_SHORT: TermName = DummyName - val MIRROR_FREE_PREFIX: TermName = DummyName - val MIRROR_FREE_THIS_SUFFIX: TermName = DummyName - val MIRROR_FREE_VALUE_SUFFIX: TermName = DummyName - val MIRROR_SYMDEF_PREFIX: TermName = DummyName - val MIXIN_CONSTRUCTOR: TermName = DummyName - val MODULE_INSTANCE_FIELD: TermName = DummyName - val OUTER: TermName = DummyName - val OUTER_LOCAL: TermName = DummyName - val OUTER_SYNTH: TermName = DummyName - val SELECTOR_DUMMY: TermName = DummyName - val SELF: TermName = DummyName - val SPECIALIZED_INSTANCE: TermName = DummyName - val STAR: TermName = DummyName - val THIS: TermName = DummyName - val BITMAP_NORMAL: TermName = DummyName - val BITMAP_TRANSIENT: TermName = DummyName - val BITMAP_CHECKINIT: TermName = DummyName - val BITMAP_CHECKINIT_TRANSIENT: TermName = DummyName - val INTERPRETER_IMPORT_WRAPPER: String = "" - val INTERPRETER_LINE_PREFIX: String = "" - val INTERPRETER_VAR_PREFIX: String = "" - val INTERPRETER_WRAPPER_SUFFIX: String = "" - val ROOTPKG: TermName = DummyName - val ADD: TermName = DummyName - val AND: TermName = DummyName - val ASR: TermName = DummyName - val DIV: TermName = DummyName - val EQ: TermName = DummyName - val EQL: TermName = DummyName - val GE: TermName = DummyName - val GT: TermName = DummyName - val HASHHASH: TermName = DummyName - val LE: TermName = DummyName - val LSL: TermName = DummyName - val LSR: TermName = DummyName - val LT: TermName = DummyName - val MINUS: TermName = DummyName - val MOD: TermName = DummyName - val MUL: TermName = DummyName - val NE: TermName = DummyName - val OR: TermName = DummyName - val PLUS : TermName = DummyName - val SUB: TermName = DummyName - val XOR: TermName = DummyName - val ZAND: TermName = DummyName - val ZOR: TermName = DummyName - val UNARY_~ : TermName = DummyName - val UNARY_+ : TermName = DummyName - val UNARY_- : TermName = DummyName - val UNARY_! : TermName = DummyName - val ??? : TermName = DummyName - val MODULE_SUFFIX_NAME: TermName = DummyName - val NAME_JOIN_NAME: TermName = DummyName - val IMPL_CLASS_SUFFIX: String = "" - val LOCALDUMMY_PREFIX: String = "" - val PROTECTED_PREFIX: String = "" - val PROTECTED_SET_PREFIX: String = "" - val SINGLETON_SUFFIX: String = "" - val SUPER_PREFIX_STRING: String = "" - val TRAIT_SETTER_SEPARATOR_STRING: String = "" - val SETTER_SUFFIX: TermName = DummyName - def isConstructorName(name: Name): Boolean = notSupported() - def isExceptionResultName(name: Name): Boolean = notSupported() - def isImplClassName(name: Name): Boolean = notSupported() - def isLocalDummyName(name: Name): Boolean = notSupported() - def isLocalName(name: Name): Boolean = notSupported() - def isLoopHeaderLabel(name: Name): Boolean = notSupported() - def isProtectedAccessorName(name: Name): Boolean = notSupported() - def isSuperAccessorName(name: Name): Boolean = notSupported() - def isReplWrapperName(name: Name): Boolean = notSupported() - def isSetterName(name: Name): Boolean = notSupported() - def isTraitSetterName(name: Name): Boolean = notSupported() - def isSingletonName(name: Name): Boolean = notSupported() - def isModuleName(name: Name): Boolean = notSupported() - def isOpAssignmentName(name: Name): Boolean = notSupported() - def segments(name: String, assumeTerm: Boolean): List[Name] = notSupported() - def originalName(name: Name): Name = notSupported() - def stripModuleSuffix(name: Name): Name = notSupported() - def unspecializedName(name: Name): Name = notSupported() - def splitSpecializedName(name: Name): (Name, String, String) = notSupported() - def dropLocalSuffix(name: Name): Name = notSupported() - def expandedName(name: TermName, base: Symbol, separator: String = EXPAND_SEPARATOR_STRING): TermName = notSupported() - def expandedSetterName(name: TermName, base: Symbol): TermName = notSupported() - def protName(name: Name): TermName = notSupported() - def protSetterName(name: Name): TermName = notSupported() - def getterName(name: TermName): TermName = notSupported() - def getterToLocal(name: TermName): TermName = notSupported() - def getterToSetter(name: TermName): TermName = notSupported() - def localToGetter(name: TermName): TermName = notSupported() - def setterToGetter(name: TermName): TermName = notSupported() - def defaultGetterName(name: Name, pos: Int): TermName = notSupported() - def defaultGetterToMethod(name: Name): TermName = notSupported() - def localDummyName(clazz: Symbol): TermName = notSupported() - def superName(name: Name): TermName = notSupported() - } - object DummyAbsTypeNames extends AbsTypeNames { - type NameType = TypeName - val EMPTY: NameType = DummyName - val ANON_FUN_NAME: NameType = DummyName - val ANON_CLASS_NAME: NameType = DummyName - val EMPTY_PACKAGE_NAME: NameType = DummyName - val IMPORT: NameType = DummyName - val MODULE_VAR_SUFFIX: NameType = DummyName - val ROOT: NameType = DummyName - val PACKAGE: NameType = DummyName - val SPECIALIZED_SUFFIX: NameType = DummyName - val ERROR: NameType = DummyName - val NO_NAME: NameType = DummyName - val WILDCARD: NameType = DummyName - def flattenedName(segments: Name*): NameType = notSupported() - val REFINE_CLASS_NAME: TypeName = DummyName - val BYNAME_PARAM_CLASS_NAME: TypeName = DummyName - val EQUALS_PATTERN_NAME: TypeName = DummyName - val JAVA_REPEATED_PARAM_CLASS_NAME: TypeName = DummyName - val LOCAL_CHILD: TypeName = DummyName - val REPEATED_PARAM_CLASS_NAME: TypeName = DummyName - val WILDCARD_STAR: TypeName = DummyName - - def dropSingletonName(name: Name): TypeName = notSupported() - def singletonName(name: Name): TypeName = notSupported() - def implClassName(name: Name): TypeName = notSupported() - def interfaceName(implname: Name): TypeName = notSupported() - } - - // Members declared in scala.reflect.api.Symbols - val NoSymbol = DummySymbol - type Symbol = DummySymbolApi - object DummySymbol extends DummySymbolApi - type TypeSymbol = DummyTypeSymbolApi - object DummyTypeSymbol extends DummyTypeSymbolApi - type TermSymbol = DummyTermSymbolApi - object DummyTermSymbol extends DummyTermSymbolApi - type MethodSymbol = DummyMethodSymbolApi - object DummyMethodSymbol extends DummyMethodSymbolApi - type ModuleSymbol = DummyModuleSymbolApi - object DummyModuleSymbol extends DummyModuleSymbolApi - type PackageSymbol = DummyPackageSymbolApi - object DummyPackageSymbol extends DummyPackageSymbolApi - type ClassSymbol = DummyClassSymbolApi - object DummyClassSymbol extends DummyClassSymbolApi - trait DummySymbolApi extends AbsSymbol { - this: Symbol => - - def pos: Position = notSupported() - def modifiers: Set[Modifier] = notSupported() - def hasModifier(mod: Modifier): Boolean = notSupported() - def annotations: List[AnnotationInfo] = notSupported() - def hasAnnotation(sym: Symbol): Boolean = notSupported() - def owner: Symbol = notSupported() - def name: Name = notSupported() - def fullName: String = notSupported() - def id: Int = notSupported() - def orElse(alt: => Symbol): Symbol = notSupported() - def filter(cond: Symbol => Boolean): Symbol = notSupported() - def suchThat(cond: Symbol => Boolean): Symbol = notSupported() - def privateWithin: Symbol = notSupported() - def companionSymbol: Symbol = notSupported() - def moduleClass: Symbol = notSupported() - def enclosingTopLevelClass: Symbol = notSupported() - def enclosingClass: Symbol = notSupported() - def enclosingMethod: Symbol = notSupported() - def enclosingPackageClass: Symbol = notSupported() - def isTerm : Boolean = notSupported() - def isPackage : Boolean = notSupported() - def isMethod : Boolean = notSupported() - def isOverloaded : Boolean = notSupported() - def isFreeTerm : Boolean = notSupported() - def isType : Boolean = notSupported() - def isClass : Boolean = notSupported() - def isPackageClass : Boolean = notSupported() - def isPrimitiveValueClass: Boolean = notSupported() - def isDerivedValueClass: Boolean = notSupported() - def isAliasType : Boolean = notSupported() - def isAbstractType : Boolean = notSupported() - def isSkolem : Boolean = notSupported() - def isExistential : Boolean = notSupported() - def isFreeType : Boolean = notSupported() - def isContravariant : Boolean = notSupported() - def isCovariant : Boolean = notSupported() - def isErroneous : Boolean = notSupported() - def typeSignature: Type = notSupported() - def typeSignatureIn(site: Type): Type = notSupported() - def asType: Type = notSupported() - def asTypeIn(site: Type): Type = notSupported() - def asTypeConstructor: Type = notSupported() - def thisPrefix: Type = notSupported() - def selfType: Type = notSupported() - def alternatives: List[Symbol] = notSupported() - def resolveOverloaded(pre: Type = NoPrefix, targs: Seq[Type] = List(), actuals: Seq[Type]): Symbol = notSupported() - def newNestedSymbol(name: Name, pos: Position, flags: Long, isClass: Boolean): Symbol = notSupported() - def setInternalFlags(flags: Long): this.type = notSupported() - def setTypeSignature(tpe: Type): this.type = notSupported() - def setAnnotations(annots: AnnotationInfo*): this.type = notSupported() - def kind: String = notSupported() - } - trait DummyTypeSymbolApi extends DummySymbolApi with TypeSymbolApi { - this: TypeSymbol => - } - trait DummyTermSymbolApi extends DummySymbolApi with TermSymbolApi { - this: TermSymbol => - } - trait DummyMethodSymbolApi extends DummyTermSymbolApi with MethodSymbolApi { - this: MethodSymbol => - } - trait DummyModuleSymbolApi extends DummyTermSymbolApi with ModuleSymbolApi { - this: ModuleSymbol => - } - trait DummyPackageSymbolApi extends DummyModuleSymbolApi with PackageSymbolApi { - this: PackageSymbol => - } - trait DummyClassSymbolApi extends DummyTypeSymbolApi with ClassSymbolApi { - this: ClassSymbol => - } - - // Members declared in scala.reflect.api.ToolBoxes - def mkToolBox(frontEnd: FrontEnd, options: String): AbsToolBox = notSupported() - - // Members declared in scala.reflect.api.TreeBuildUtil - // type TreeGen = DummyTreeGen.type // [Eugene] cannot compile if uncomment this - val gen: TreeGen{val global: DummyMirror.this.type} = DummyTreeGen.asInstanceOf[TreeGen{val global: DummyMirror.this.type}] - def modifiersFromInternalFlags(flags: Long,privateWithin: Name,annotations: List[Tree]): Modifiers = DummyModifiers - def newFreeExistential(name: String,info: Type,value: => Any,flags: Long,origin: String) = DummySymbol - def newFreeTerm(name: String,info: Type,value: => Any,flags: Long,origin: String) = DummySymbol - def newFreeType(name: String,info: Type,value: => Any,flags: Long,origin: String) = DummySymbol - def selectOverloadedMethod(owner: Symbol,name: String,index: Int) = DummySymbol - def selectOverloadedMethodIfDefined(owner: Symbol,name: String,index: Int) = DummySymbol - def selectTerm(owner: Symbol,name: String) = DummySymbol - def selectTermIfDefined(owner: Symbol,name: String) = DummySymbol - def selectType(owner: Symbol,name: String) = DummySymbol - def selectTypeIfDefined(owner: Symbol,name: String) = DummySymbol - def staticClass(fullName: String) = DummySymbol - def staticClassIfDefined(fullName: String) = DummySymbol - def staticModule(fullName: String) = DummySymbol - def staticModuleIfDefined(fullName: String) = DummySymbol - def thisModuleType(fullName: String): Type = DummyType - object DummyTreeGen extends AbsTreeGen { - val global: Universe = DummyMirror.this - type TreeGenTree = global.Tree - type TreeGenType = global.Type - type TreeGenSymbol = global.Symbol - type TreeGenName = global.Name - def mkAttributedQualifier(tpe: TreeGenType): TreeGenTree = notSupported() - def mkAttributedQualifier(tpe: TreeGenType, termSym: TreeGenSymbol): TreeGenTree = notSupported() - def mkAttributedRef(pre: TreeGenType, sym: TreeGenSymbol): TreeGenTree = notSupported() - def mkAttributedRef(sym: TreeGenSymbol): TreeGenTree = notSupported() - def mkAttributedThis(sym: TreeGenSymbol): TreeGenTree = notSupported() - def mkAttributedIdent(sym: TreeGenSymbol): TreeGenTree = notSupported() - def mkAttributedSelect(qual: TreeGenTree, sym: TreeGenSymbol): TreeGenTree = notSupported() - def mkMethodCall(target: TreeGenTree,targs: List[TreeGenType],args: List[TreeGenTree]): TreeGenTree = notSupported() - def mkMethodCall(receiver: TreeGenTree,method: TreeGenSymbol,targs: List[TreeGenType],args: List[TreeGenTree]): TreeGenTree = notSupported() - def mkMethodCall(receiver: TreeGenSymbol,methodName: TreeGenName,args: List[TreeGenTree]): TreeGenTree = notSupported() - def mkMethodCall(target: TreeGenTree,args: List[TreeGenTree]): TreeGenTree = notSupported() - def mkMethodCall(method: TreeGenSymbol,args: List[TreeGenTree]): TreeGenTree = notSupported() - def mkMethodCall(method: TreeGenSymbol,targs: List[TreeGenType],args: List[TreeGenTree]): TreeGenTree = notSupported() - def mkMethodCall(receiver: TreeGenSymbol,methodName: TreeGenName,targs: List[TreeGenType],args: List[TreeGenTree]): TreeGenTree = notSupported() - def mkNullaryCall(method: TreeGenSymbol,targs: List[TreeGenType]): TreeGenTree = notSupported() - } - - // Members declared in scala.reflect.api.TreePrinters - def newTreePrinter(out: java.io.PrintWriter): TreePrinter = notSupported() - - // Members declared in scala.reflect.api.Trees - def Apply(sym: Symbol,args: Tree*): Tree = Apply(EmptyTree, Nil) - def Bind(sym: Symbol,body: Tree): Bind = Bind(DummyName, EmptyTree) - def Block(stats: Tree*): Block = Block() - def CaseDef(pat: Tree,body: Tree): CaseDef = CaseDef(EmptyTree, EmptyTree, EmptyTree) - def ClassDef(sym: Symbol,impl: Template): ClassDef = ClassDef(DummyModifiers, DummyName, Nil, Template(Nil, emptyValDef, Nil)) - def DefDef(sym: Symbol,rhs: List[List[Symbol]] => Tree): DefDef = DefDef(DummyModifiers, DummyName, Nil, Nil, EmptyTree, EmptyTree) - def DefDef(sym: Symbol,rhs: Tree): DefDef = DefDef(DummyModifiers, DummyName, Nil, Nil, EmptyTree, EmptyTree) - def DefDef(sym: Symbol,mods: Modifiers,rhs: Tree): DefDef = DefDef(DummyModifiers, DummyName, Nil, Nil, EmptyTree, EmptyTree) - def DefDef(sym: Symbol,vparamss: List[List[ValDef]],rhs: Tree): DefDef = DefDef(DummyModifiers, DummyName, Nil, Nil, EmptyTree, EmptyTree) - def DefDef(sym: Symbol,mods: Modifiers,vparamss: List[List[ValDef]],rhs: Tree): DefDef = DefDef(DummyModifiers, DummyName, Nil, Nil, EmptyTree, EmptyTree) - def Ident(sym: Symbol): Ident = Ident(DummyName) - def Ident(name: String): Ident = Ident(DummyName) - def LabelDef(sym: Symbol,params: List[Symbol],rhs: Tree): LabelDef = LabelDef(DummyName, Nil, EmptyTree) - type Modifiers = DummyModifiers.type - val NoMods: Modifiers = DummyModifiers - object DummyModifiers extends AbsModifiers { - def modifiers: Set[Modifier] = notSupported() - def hasModifier(mod: Modifier): Boolean = notSupported() - def privateWithin: Name = notSupported() - def annotations: List[Tree] = notSupported() - def mapAnnotations(f: List[Tree] => List[Tree]): Modifiers = notSupported() - } - def Modifiers(mods: Set[scala.reflect.api.Modifier],privateWithin: Name,annotations: List[Tree]): Modifiers = DummyModifiers - def ModuleDef(sym: Symbol,impl: Template): ModuleDef = ModuleDef(DummyModifiers, DummyName, Template(Nil, emptyValDef, Nil)) - def New(sym: Symbol,args: Tree*): Tree = New(EmptyTree) - def New(tpe: Type,args: Tree*): Tree = New(EmptyTree) - def New(tpt: Tree,argss: List[List[Tree]]): Tree = New(EmptyTree) - def Select(qualifier: Tree,sym: Symbol): Select = Select(EmptyTree, DummyName) - def Select(qualifier: Tree,name: String): Select = Select(EmptyTree, DummyName) - def Super(sym: Symbol,mix: TypeName): Tree = Super(EmptyTree, DummyName) - def This(sym: Symbol): Tree = This(DummyName) - def Throw(tpe: Type,args: Tree*): Throw = Throw(EmptyTree) - def Try(body: Tree,cases: (Tree, Tree)*): Try = Try(EmptyTree) - def TypeDef(sym: Symbol): TypeDef = TypeDef(DummyModifiers, DummyName, Nil, EmptyTree) - def TypeDef(sym: Symbol,rhs: Tree): TypeDef = TypeDef(DummyModifiers, DummyName, Nil, EmptyTree) - def ValDef(sym: Symbol): ValDef = ValDef(DummyModifiers, DummyName, EmptyTree, EmptyTree) - def ValDef(sym: Symbol,rhs: Tree): ValDef = ValDef(DummyModifiers, DummyName, EmptyTree, EmptyTree) - protected def duplicateTree(tree: Tree): Tree = notSupported() - object emptyValDef extends ValDef(DummyModifiers, DummyName, EmptyTree, EmptyTree) { override def isEmpty = true } - type TreeCopier = DummyTreeCopier.type - def newStrictTreeCopier: TreeCopier = DummyTreeCopier - def newLazyTreeCopier: TreeCopier = DummyTreeCopier - object DummyTreeCopier extends TreeCopierOps { - def ClassDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], impl: Template): ClassDef = notSupported() - def PackageDef(tree: Tree, pid: RefTree, stats: List[Tree]): PackageDef = notSupported() - def ModuleDef(tree: Tree, mods: Modifiers, name: Name, impl: Template): ModuleDef = notSupported() - def ValDef(tree: Tree, mods: Modifiers, name: Name, tpt: Tree, rhs: Tree): ValDef = notSupported() - def DefDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree): DefDef = notSupported() - def TypeDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], rhs: Tree): TypeDef = notSupported() - def LabelDef(tree: Tree, name: Name, params: List[Ident], rhs: Tree): LabelDef = notSupported() - def Import(tree: Tree, expr: Tree, selectors: List[ImportSelector]): Import = notSupported() - def Template(tree: Tree, parents: List[Tree], self: ValDef, body: List[Tree]): Template = notSupported() - def Block(tree: Tree, stats: List[Tree], expr: Tree): Block = notSupported() - def CaseDef(tree: Tree, pat: Tree, guard: Tree, body: Tree): CaseDef = notSupported() - def Alternative(tree: Tree, trees: List[Tree]): Alternative = notSupported() - def Star(tree: Tree, elem: Tree): Star = notSupported() - def Bind(tree: Tree, name: Name, body: Tree): Bind = notSupported() - def UnApply(tree: Tree, fun: Tree, args: List[Tree]): UnApply = notSupported() - def ArrayValue(tree: Tree, elemtpt: Tree, trees: List[Tree]): ArrayValue = notSupported() - def Function(tree: Tree, vparams: List[ValDef], body: Tree): Function = notSupported() - def Assign(tree: Tree, lhs: Tree, rhs: Tree): Assign = notSupported() - def AssignOrNamedArg(tree: Tree, lhs: Tree, rhs: Tree): AssignOrNamedArg = notSupported() - def If(tree: Tree, cond: Tree, thenp: Tree, elsep: Tree): If = notSupported() - def Match(tree: Tree, selector: Tree, cases: List[CaseDef]): Match = notSupported() - def Return(tree: Tree, expr: Tree): Return = notSupported() - def Try(tree: Tree, block: Tree, catches: List[CaseDef], finalizer: Tree): Try = notSupported() - def Throw(tree: Tree, expr: Tree): Throw = notSupported() - def New(tree: Tree, tpt: Tree): New = notSupported() - def Typed(tree: Tree, expr: Tree, tpt: Tree): Typed = notSupported() - def TypeApply(tree: Tree, fun: Tree, args: List[Tree]): TypeApply = notSupported() - def Apply(tree: Tree, fun: Tree, args: List[Tree]): Apply = notSupported() - def ApplyDynamic(tree: Tree, qual: Tree, args: List[Tree]): ApplyDynamic = notSupported() - def Super(tree: Tree, qual: Tree, mix: TypeName): Super = notSupported() - def This(tree: Tree, qual: Name): This = notSupported() - def Select(tree: Tree, qualifier: Tree, selector: Name): Select = notSupported() - def Ident(tree: Tree, name: Name): Ident = notSupported() - def ReferenceToBoxed(tree: Tree, idt: Ident): ReferenceToBoxed = notSupported() - def Literal(tree: Tree, value: Constant): Literal = notSupported() - def TypeTree(tree: Tree): TypeTree = notSupported() - def Annotated(tree: Tree, annot: Tree, arg: Tree): Annotated = notSupported() - def SingletonTypeTree(tree: Tree, ref: Tree): SingletonTypeTree = notSupported() - def SelectFromTypeTree(tree: Tree, qualifier: Tree, selector: Name): SelectFromTypeTree = notSupported() - def CompoundTypeTree(tree: Tree, templ: Template): CompoundTypeTree = notSupported() - def AppliedTypeTree(tree: Tree, tpt: Tree, args: List[Tree]): AppliedTypeTree = notSupported() - def TypeBoundsTree(tree: Tree, lo: Tree, hi: Tree): TypeBoundsTree = notSupported() - def ExistentialTypeTree(tree: Tree, tpt: Tree, whereClauses: List[Tree]): ExistentialTypeTree = notSupported() - } - - // Members declared in scala.reflect.api.Types - type Type = DummyType.type - type SingletonType = DummyType.type - type CompoundType = DummyType.type - type AnnotatedType = DummyType.type - val AnnotatedType: AnnotatedTypeExtractor = DummyAnnotatedTypeExtractor - type BoundedWildcardType = DummyType.type - val BoundedWildcardType: BoundedWildcardTypeExtractor = DummyBoundedWildcardTypeExtractor - type ClassInfoType = DummyType.type - val ClassInfoType: ClassInfoTypeExtractor = DummyClassInfoTypeExtractor - type ConstantType = DummyType.type - val ConstantType: ConstantTypeExtractor = DummyConstantTypeExtractor - type ExistentialType = DummyType.type - val ExistentialType: ExistentialTypeExtractor = DummyExistentialTypeExtractor - type MethodType = DummyType.type - val MethodType: MethodTypeExtractor = DummyMethodTypeExtractor - val NoPrefix: Type = DummyType - val NoType: Type = DummyType - type NullaryMethodType = DummyType.type - val NullaryMethodType: NullaryMethodTypeExtractor = DummyNullaryMethodTypeExtractor - type PolyType = DummyType.type - val PolyType: PolyTypeExtractor = DummyPolyTypeExtractor - type RefinedType = DummyType.type - val RefinedType: RefinedTypeExtractor = DummyRefinedTypeExtractor - type SingleType = DummyType.type - val SingleType: SingleTypeExtractor = DummySingleTypeExtractor - type SuperType = DummyType.type - val SuperType: SuperTypeExtractor = DummySuperTypeExtractor - type ThisType = DummyType.type - val ThisType: ThisTypeExtractor = DummyThisTypeExtractor - type TypeBounds = DummyType.type - val TypeBounds: TypeBoundsExtractor = DummyTypeBoundsExtractor - type TypeRef = DummyType.type - val TypeRef: TypeRefExtractor = DummyTypeRefExtractor - val WildcardType: Type = DummyType - def appliedType(tycon: Type,args: List[Type]): Type = DummyType - def existentialAbstraction(tparams: List[Symbol],tpe0: Type): Type = DummyType - def glb(ts: List[Type]): Type = DummyType - def intersectionType(tps: List[Type],owner: Symbol): Type = DummyType - def intersectionType(tps: List[Type]): Type = DummyType - def lub(xs: List[Type]): Type = DummyType - def polyType(tparams: List[Symbol],tpe: Type): Type = DummyType - def refinedType(parents: List[Type],owner: Symbol): Type = DummyType - def refinedType(parents: List[Type],owner: Symbol,decls: Scope,pos: Position): Type = DummyType - def singleType(pre: Type,sym: Symbol): Type = DummyType - def typeRef(pre: Type,sym: Symbol,args: List[Type]): Type = DummyType - object DummyType extends AbsType { - def =:=(that: Type): Boolean = notSupported() - def <:<(that: Type): Boolean = notSupported() - def asSeenFrom(pre: Type,clazz: Symbol): Type = notSupported() - def baseClasses: List[Symbol] = notSupported() - def baseType(clazz: Symbol): Type = notSupported() - def contains(sym: Symbol): Boolean = notSupported() - def declaration(name: Name): Symbol = notSupported() - def declarations: Iterable[Symbol] = notSupported() - def erasure: Type = notSupported() - def exists(p: Type => Boolean): Boolean = notSupported() - def find(p: Type => Boolean): Option[Type] = notSupported() - def foreach(f: Type => Unit): Unit = notSupported() - def isConcrete: Boolean = notSupported() - def isHigherKinded: Boolean = notSupported() - def isSpliceable: Boolean = notSupported() - def kind: String = notSupported() - def map(f: Type => Type): Type = notSupported() - def member(name: Name): Symbol = notSupported() - def members: Iterable[Symbol] = notSupported() - def nonPrivateMember(name: Name): Symbol = notSupported() - def nonPrivateMembers: Iterable[Symbol] = notSupported() - def normalize: Type = notSupported() - def parents: List[Type] = notSupported() - def substituteTypes(from: List[Symbol],to: List[Type]): Type = notSupported() - def typeArguments: List[Type] = notSupported() - def typeConstructor: Type = notSupported() - def typeParams: List[Symbol] = notSupported() - def typeSymbol: Symbol = notSupported() - def underlying: Type = notSupported() - def widen: Type = notSupported() - } - object DummyAnnotatedTypeExtractor extends AnnotatedTypeExtractor { - def apply(annotations: List[AnnotationInfo], underlying: Type, selfsym: Symbol): AnnotatedType = DummyType - def unapply(tpe: AnnotatedType): Option[(List[AnnotationInfo], Type, Symbol)] = notSupported() - } - object DummyBoundedWildcardTypeExtractor extends BoundedWildcardTypeExtractor { - def apply(bounds: TypeBounds): BoundedWildcardType = DummyType - def unapply(tpe: BoundedWildcardType): Option[TypeBounds] = notSupported() - } - object DummyClassInfoTypeExtractor extends ClassInfoTypeExtractor { - def apply(parents: List[Type], decls: Scope, clazz: Symbol): ClassInfoType = DummyType - def unapply(tpe: ClassInfoType): Option[(List[Type], Scope, Symbol)] = notSupported() - } - object DummyConstantTypeExtractor extends ConstantTypeExtractor { - def apply(value: Constant): ConstantType = DummyType - def unapply(tpe: ConstantType): Option[Constant] = notSupported() - } - object DummyExistentialTypeExtractor extends ExistentialTypeExtractor { - def apply(quantified: List[Symbol], underlying: Type): ExistentialType = DummyType - def unapply(tpe: ExistentialType): Option[(List[Symbol], Type)] = notSupported() - } - object DummyMethodTypeExtractor extends MethodTypeExtractor { - def apply(params: List[Symbol], resultType: Type): MethodType = DummyType - def unapply(tpe: MethodType): Option[(List[Symbol], Type)] = notSupported() - } - object DummyNullaryMethodTypeExtractor extends NullaryMethodTypeExtractor { - def apply(resultType: Type): NullaryMethodType = DummyType - def unapply(tpe: NullaryMethodType): Option[(Type)] = notSupported() - } - object DummyPolyTypeExtractor extends PolyTypeExtractor { - def apply(typeParams: List[Symbol], resultType: Type): PolyType = DummyType - def unapply(tpe: PolyType): Option[(List[Symbol], Type)] = notSupported() - } - object DummyRefinedTypeExtractor extends RefinedTypeExtractor { - def apply(parents: List[Type], decls: Scope): RefinedType = DummyType - def apply(parents: List[Type], decls: Scope, clazz: Symbol): RefinedType = DummyType - def unapply(tpe: RefinedType): Option[(List[Type], Scope)] = notSupported() - } - object DummySingleTypeExtractor extends SingleTypeExtractor { - def apply(pre: Type, sym: Symbol): Type = DummyType - def unapply(tpe: SingleType): Option[(Type, Symbol)] = notSupported() - } - object DummySuperTypeExtractor extends SuperTypeExtractor { - def apply(thistpe: Type, supertpe: Type): Type = DummyType - def unapply(tpe: SuperType): Option[(Type, Type)] = notSupported() - } - object DummyThisTypeExtractor extends ThisTypeExtractor { - def apply(sym: Symbol): Type = DummyType - def unapply(tpe: ThisType): Option[Symbol] = notSupported() - } - object DummyTypeBoundsExtractor extends TypeBoundsExtractor { - def apply(lo: Type, hi: Type): TypeBounds = DummyType - def unapply(tpe: TypeBounds): Option[(Type, Type)] = notSupported() - } - object DummyTypeRefExtractor extends TypeRefExtractor { - def apply(pre: Type, sym: Symbol, args: List[Type]): Type = DummyType - def unapply(tpe: TypeRef): Option[(Type, Symbol, List[Type])] = notSupported() - } - - // Utils - def notSupported() = { - throw new UnsupportedOperationException("Scala reflection not available on this platform." + mirrorDiagnostics(cl)) - } -}
\ No newline at end of file diff --git a/src/library/scala/reflect/DynamicProxy.scala b/src/library/scala/reflect/DynamicProxy.scala deleted file mode 100644 index 3ed17fea41..0000000000 --- a/src/library/scala/reflect/DynamicProxy.scala +++ /dev/null @@ -1,74 +0,0 @@ -package scala.reflect -/** - * A dynamic proxy which redirects method calls and attribute access to a given - * target object at runtime using reflection. - * - * Usage example: - * - * object x{ def hello = "hello world" } - * val d = new DynamicProxy{ val dynamicProxyTarget = x } - * assert( d.hello == "hello world" ) - * - * Not supported (yet): - * - implicit conversions and parameters - * - multiple arguments lists - * - explicit type arguments - */ -trait DynamicProxy extends Dynamic{ - /** Method calls on DynamicProxy are redirected to this object. Needs to be defined in a subclass. */ - val dynamicProxyTarget : AnyRef - - import scala.reflect.mirror._ - /** - * boxing to preserve information on primitive types for overloading resolution - */ - case class DynamicReflectBoxed( class_ : Class[_], value: Any ) - object DynamicReflectBoxed{ - implicit def box[@specialized T]( v:T ) = DynamicReflectBoxed( v.getClass, v ) - } - - def selectDynamic( method:String ) = { - val symbol = classToType( dynamicProxyTarget.getClass ).member( newTermName(method).encodedName ) - invoke( dynamicProxyTarget, symbol )() - } - - def updateDynamic( method:String )( value : Any ) = { - val symbol = classToType( dynamicProxyTarget.getClass ).member( newTermName(method+"_=").encodedName ) - invoke( dynamicProxyTarget, symbol )( value ) - } - - def applyDynamic( method:String )( args:DynamicReflectBoxed* ) : Any - = applyDynamicNamed( method )( args.map( value => ("",value) ) :_* ) - - def applyDynamicNamed( method:String )( args:(String,DynamicReflectBoxed)* ) : Any = { - val class_ = dynamicProxyTarget.getClass - var i = 0 - val toolbox = mkToolBox(mkConsoleFrontEnd(),"") - val symbol = classToType( dynamicProxyTarget.getClass ).member( newTermName(method).encodedName ) - if(args.size == 0){ - invoke( dynamicProxyTarget, symbol )() - } else { - val call = - Apply( - Select( - TypeApply( - Select( - Select( - Ident(newFreeTerm("__this", symbolForName("scala.reflect.DynamicProxy").asType, this)) - , newTermName("dynamicProxyTarget") - ), - newTermName("asInstanceOf") ) - , List(TypeTree().setType(classToType(class_))) - ) - ,newTermName(method).encodedName - ) - ,args.map{ case(name,box) => - val value = Ident(newFreeTerm("__arg"+({i+=1;i}.toString), classToType(box.class_), box.value)) - if( name == "" ) value - else AssignOrNamedArg( Ident(name), value ) - }.toList - ) - toolbox.runExpr( call ) - } - } -} diff --git a/src/library/scala/reflect/ErasureTag.scala b/src/library/scala/reflect/ErasureTag.scala deleted file mode 100644 index f95451fab2..0000000000 --- a/src/library/scala/reflect/ErasureTag.scala +++ /dev/null @@ -1,23 +0,0 @@ -package scala.reflect - -import java.lang.{Class => jClass} - -/** An `ErasureTag[T]` is a descriptor that is requested by the compiler every time - * when it needs to persist an erasure of a type. - * - * Scala library provides a standard implementation of this trait, - * `TypeTag[T]` that carries the `java.lang.Class` erasure for arbitrary types. - * - * However other platforms may reimplement this trait as they see fit - * and then expose the implementation via an implicit macro. - * - * If you need to guarantee that the type does not contain - * references to type parameters or abstract types, use `ClassTag[T]`. - * - * @see [[scala.reflect.api.TypeTags]] - */ -@annotation.implicitNotFound(msg = "No ErasureTag available for ${T}") -trait ErasureTag[T] { - /** Returns an erasure of type `T` */ - def erasure: jClass[_] -} diff --git a/src/library/scala/reflect/Manifest.scala b/src/library/scala/reflect/Manifest.scala index da029f046d..7e320b42eb 100644 --- a/src/library/scala/reflect/Manifest.scala +++ b/src/library/scala/reflect/Manifest.scala @@ -9,7 +9,6 @@ package scala.reflect import scala.collection.mutable.{ ArrayBuilder, WrappedArray } -import mirror._ /** A `Manifest[T]` is an opaque descriptor for type T. Its supported use * is to give access to the erasure of the type as a `Class` instance, as @@ -40,7 +39,7 @@ import mirror._ * */ @annotation.implicitNotFound(msg = "No Manifest available for ${T}.") -@deprecated("Use `@scala.reflect.ConcreteTypeTag` instead", "2.10.0") +@deprecated("Use TypeTag instead", "2.10.0") trait Manifest[T] extends ClassManifest[T] with Equals { override def typeArguments: List[Manifest[_]] = Nil @@ -77,7 +76,7 @@ abstract class AnyValManifest[T <: AnyVal](override val toString: String) extend * It is intended for use by the compiler and should not be used * in client code. */ -@deprecated("Use `@scala.reflect.ConcreteTypeTag` instead", "2.10.0") +@deprecated("Use TypeTag instead", "2.10.0") object Manifest { def valueManifests: List[AnyValManifest[_]] = List(Byte, Short, Char, Int, Long, Float, Double, Boolean, Unit) diff --git a/src/library/scala/reflect/NameTransformer.scala b/src/library/scala/reflect/NameTransformer.scala index 38fbbc98f2..ff56e20d52 100755 --- a/src/library/scala/reflect/NameTransformer.scala +++ b/src/library/scala/reflect/NameTransformer.scala @@ -8,8 +8,8 @@ package scala.reflect -/** - * @author Martin Odersky +/** Provides functions to encode and decode Scala symbolic names. + * Also provides some constants. */ object NameTransformer { // XXX Short term: providing a way to alter these without having to recompile diff --git a/src/library/scala/reflect/ScalaLongSignature.java b/src/library/scala/reflect/ScalaLongSignature.java index 1ffd6d2520..fce58207f1 100644 --- a/src/library/scala/reflect/ScalaLongSignature.java +++ b/src/library/scala/reflect/ScalaLongSignature.java @@ -5,7 +5,9 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -/** */ +/** + * [Martin to Eugene++] Todo: Move to somewhere else? +*/ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface ScalaLongSignature { diff --git a/src/library/scala/reflect/ScalaSignature.java b/src/library/scala/reflect/ScalaSignature.java index d1cdbc0589..f0df99fe79 100644 --- a/src/library/scala/reflect/ScalaSignature.java +++ b/src/library/scala/reflect/ScalaSignature.java @@ -5,7 +5,8 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -/** */ +/** * [Martin to Eugene++] Todo: Move to somewhere else? + */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface ScalaSignature { diff --git a/src/library/scala/reflect/TagInterop.scala b/src/library/scala/reflect/TagInterop.scala deleted file mode 100644 index 6c6bfcc2f2..0000000000 --- a/src/library/scala/reflect/TagInterop.scala +++ /dev/null @@ -1,34 +0,0 @@ -package scala.reflect - -import scala.runtime.ScalaRunTime._ -import mirror._ -import definitions._ - -object TagInterop { - def arrayTagToClassManifest[T](tag: ArrayTag[T]): ClassManifest[T] = { - val erasure = arrayElementClass(tag) - if (erasure.isArray) { - val elementClass = arrayElementClass(erasure) - val elementManifest = arrayTagToClassManifest(ClassTag(elementClass)) - ClassManifest.arrayType(elementManifest).asInstanceOf[ClassManifest[T]] - } else { - ClassManifest.fromClass(erasure.asInstanceOf[Class[T]]) - } - } - - def concreteTypeTagToManifest[T](tag: ConcreteTypeTag[T]): Manifest[T] = { - // todo. reproduce manifest generation code here. toolboxes are too slow. - val implicitly = PredefModule.typeSignature.member(newTermName("implicitly")) - val taggedTpe = appliedType(staticClass("scala.reflect.Manifest").asTypeConstructor, List(tag.tpe)) - val materializer = TypeApply(Ident(implicitly), List(TypeTree(taggedTpe))) - try mkToolBox().runExpr(materializer).asInstanceOf[Manifest[T]] - catch { case ex: Throwable => Manifest.classType(tag.erasure).asInstanceOf[Manifest[T]] } - } - - def manifestToConcreteTypeTag[T](tag: Manifest[T]): ConcreteTypeTag[T] = { - val tpe = - if (tag.typeArguments.isEmpty) classToType(tag.erasure) - else appliedType(classToType(tag.erasure).typeConstructor, tag.typeArguments map (manifestToConcreteTypeTag(_)) map (_.tpe)) - ConcreteTypeTag(tpe, tag.erasure) - } -}
\ No newline at end of file diff --git a/src/library/scala/reflect/api/Attachment.scala b/src/library/scala/reflect/api/Attachment.scala deleted file mode 100644 index 50f55b4aa5..0000000000 --- a/src/library/scala/reflect/api/Attachment.scala +++ /dev/null @@ -1,29 +0,0 @@ -package scala.reflect -package api - -/** Attachment is a generalisation of Position. - * Typically it stores a Position of a tree, but this can be extended to encompass arbitrary payloads. - * - * Attachments have to carry positions, because we don't want to introduce even a single additional field in Tree - * imposing an unnecessary memory tax because of something that will not be used in most cases. - */ -trait Attachment { - /** Gets the underlying position */ - def pos: Position - - /** Creates a copy of this attachment with its position updated */ - def withPos(newPos: Position): Attachment - - /** Gets the underlying payload */ - def payload: Any - - /** Creates a copy of this attachment with its payload updated */ - def withPayload(newPayload: Any): Attachment -} - -// [Eugene] with the introduction of `attach` and `attachment[T]` users don't need to create custom attachments anymore -// however, we cannot move attachments to scala.reflect.internal, because they are used in Trees, which are implemented completely in scala.reflect.api -private[scala] case class NontrivialAttachment(pos: api.Position, payload: collection.mutable.ListBuffer[Any]) extends Attachment { - def withPos(newPos: api.Position) = copy(pos = newPos, payload = payload) - def withPayload(newPayload: Any) = copy(pos = pos, payload = newPayload.asInstanceOf[collection.mutable.ListBuffer[Any]]) -}
\ No newline at end of file diff --git a/src/library/scala/reflect/api/ClassLoaders.scala b/src/library/scala/reflect/api/ClassLoaders.scala deleted file mode 100644 index 7be402d3df..0000000000 --- a/src/library/scala/reflect/api/ClassLoaders.scala +++ /dev/null @@ -1,16 +0,0 @@ -package scala.reflect -package api - -trait ClassLoaders { self: Universe => - - /** The symbol corresponding to the globally accessible class with the - * given fully qualified name `fullName`. - */ - def staticClass(fullName: String): Symbol - - /** The symbol corresponding to the globally accessible object with the - * given fully qualified name `fullName`. - */ - def staticModule(fullName: String): Symbol - -}
\ No newline at end of file diff --git a/src/library/scala/reflect/api/Exprs.scala b/src/library/scala/reflect/api/Exprs.scala deleted file mode 100644 index b8db64422e..0000000000 --- a/src/library/scala/reflect/api/Exprs.scala +++ /dev/null @@ -1,19 +0,0 @@ -/* NSC -- new Scala compiler - * Copyright 2005-2011 LAMP/EPFL - * @author Martin Odersky - */ - -package scala.reflect -package api -import language.implicitConversions - -trait Exprs { self: Universe => - - /** An expression tree tagged with its type */ - case class Expr[+T: TypeTag](tree: Tree) { - def tpe: Type = implicitly[TypeTag[T]].tpe - def eval: T = mkToolBox().runExpr(tree).asInstanceOf[T] - lazy val value: T = eval - override def toString = "Expr["+tpe+"]("+tree+")" - } -}
\ No newline at end of file diff --git a/src/library/scala/reflect/api/FreeVars.scala b/src/library/scala/reflect/api/FreeVars.scala deleted file mode 100644 index 0bef099a55..0000000000 --- a/src/library/scala/reflect/api/FreeVars.scala +++ /dev/null @@ -1,42 +0,0 @@ -package scala.reflect -package api - -trait FreeVars { - self: Universe => - - /** Represents a free term captured by reification. - */ - type FreeTerm <: Symbol - - val FreeTerm: FreeTermExtractor - - abstract class FreeTermExtractor { - def unapply(freeTerm: FreeTerm): Option[(TermName, Type, Any, String)] - } - - /** Extracts free terms from a tree that is reified or contains reified subtrees. - */ - def freeTerms(tree: Tree): List[FreeTerm] - - /** Represents a free type captured by reification. - */ - type FreeType <: Symbol - - val FreeType: FreeTypeExtractor - - abstract class FreeTypeExtractor { - def unapply(freeType: FreeType): Option[(TypeName, Type, String)] - } - - /** Extracts free types from a tree that is reified or contains reified subtrees. - */ - def freeTypes(tree: Tree): List[FreeType] - - /** Substitutes free types in a reified tree. - */ - def substituteFreeTypes(tree: Tree, subs: Map[FreeType, Type]): Tree - - /** Substitutes free types in a reified type. - */ - def substituteFreeTypes(tpe: Type, subs: Map[FreeType, Type]): Type -} diff --git a/src/library/scala/reflect/api/Mirror.scala b/src/library/scala/reflect/api/Mirror.scala deleted file mode 100644 index ed8ead7aaf..0000000000 --- a/src/library/scala/reflect/api/Mirror.scala +++ /dev/null @@ -1,100 +0,0 @@ -package scala.reflect -package api - -/** A mirror establishes connections of - * runtime entities such as class names and object instances - * with a reflexive universe. - */ -trait Mirror extends Universe { - - /** Class loader that is a mastermind behind the reflexive mirror. - * - * By default it is set to system classloader (more precisely, to the classloader that loads the `scala.reflect.package` class). - * However, sometimes it is useful to have a mirror services by a custom classloader. - * - * There are two ways to customize the `classLoader`: - * 1) Create a new mirror using the `scala.reflect.mkMirror(classLoader: ClassLoader)` method - * 2) Set `classLoader` to the new value - * - * The first, immutable, way should be strongly preferred in most situation. - * However sometimes it is necessary to migrate the default reflexive mirror (`scala.reflect.mirror`) to a new classloader. - * In that and only that case, use the setter, but be very careful not to introduce inconsistencies. - */ - var classLoader: ClassLoader - - /** The Scala class symbol that has given fully qualified name - * @param name The fully qualified name of the class to be returned - * @throws java.lang.ClassNotFoundException if no class with that name exists - * to do: throws anything else? - */ - def symbolForName(name: String): Symbol - - /** Return a reference to the companion object of the given class symbol. - */ - def companionInstance(clazz: Symbol): AnyRef - - /** The Scala class symbol corresponding to the runtime class of the given instance. - * @param instance The instance - * @return The class Symbol for the instance - * @throws ? - */ - def symbolOfInstance(instance: Any): Symbol - - /** The Scala type corresponding to the runtime type of given instance. - * If the underlying class is parameterized, this will be an existential type, - * with unknown type arguments. - * - * @param instance The instance. - * @return The Type of the given instance. - * @throws ? - */ - def typeOfInstance(instance: Any): Type - - /** The value of a field on a receiver instance. - * @param receiver The receiver instance - * @param field The field - * @return The value contained in `receiver.field`. - */ - def getValueOfField(receiver: AnyRef, field: Symbol): Any - - /** Sets the value of a field on a receiver instance. - * @param receiver The receiver instance - * @param field The field - * @param value The new value to be stored in the field. - */ - def setValueOfField(receiver: AnyRef, field: Symbol, value: Any): Unit - - /** Invokes a method on a receiver instance with some arguments - * @param receiver The receiver instance - * @param meth The method - * @param args The method call's arguments - * @return The result of invoking `receiver.meth(args)` - */ - def invoke(receiver: AnyRef, meth: Symbol)(args: Any*): Any - - /** Maps a Java class to a Scala type reference - * @param clazz The Java class object - * @return A type (of kind `TypeRef`, or `ExistentialType` if `clazz` is polymorphic) - * that represents the class with all type parameters unknown - * (i.e. any type parameters of `clazz` are existentially quantified). - * */ - def classToType(clazz: java.lang.Class[_]): Type - - /** Maps a Java class to a Scala class symbol - * @param clazz The Java class object - * @return A symbol that represents the Scala view of the class. - */ - def classToSymbol(clazz: java.lang.Class[_]): Symbol - - /** Maps a Scala type to the corresponding Java class object - */ - def typeToClass(tpe: Type): java.lang.Class[_] - - /** Maps a Scala symbol to the corresponding Java class object - * @throws ClassNotFoundException if there is no Java class - * corresponding to the given Scala symbol. - * Note: If the Scala symbol is ArrayClass, a ClassNotFound exception is thrown - * because there is no unique Java class corresponding to a Scala generic array - */ - def symbolToClass(sym: Symbol): java.lang.Class[_] -} diff --git a/src/library/scala/reflect/api/Modifier.scala b/src/library/scala/reflect/api/Modifier.scala deleted file mode 100644 index 1b67929e15..0000000000 --- a/src/library/scala/reflect/api/Modifier.scala +++ /dev/null @@ -1,82 +0,0 @@ -package scala.reflect.api - -import collection.{ immutable, mutable } - -abstract class Modifier private[api] () { - def name: String - def isKeyword: Boolean - def sourceString: String = if (isKeyword) "`" + name + "`" else name - - override def equals(that: Any) = this eq that.asInstanceOf[AnyRef] - override def hashCode = name.hashCode - override def toString = name -} -final class SymbolModifier private (val name: String, val isKeyword: Boolean) extends Modifier { - def this(name: String) = this(name, false) -} -final class SourceModifier private (val name: String) extends Modifier { - def isKeyword = true -} - -object SymbolModifier { - private val seen = mutable.ListBuffer[SymbolModifier]() - private[api] def apply(name: String): SymbolModifier = { - val mod = name match { - case "case" | "trait" => new SymbolModifier(name, isKeyword = true) - case _ => new SymbolModifier(name) - } - seen += mod - mod - } - private[api] def all = seen.toList -} -object SourceModifier { - private val seen = mutable.ListBuffer[SourceModifier]() - private[api] def apply(name: String): SourceModifier = { - val mod = new SourceModifier(name) - seen += mod - mod - } - private[api] def all = seen.toList -} - -object Modifier extends immutable.Set[Modifier] { - val `abstract` = SourceModifier("abstract") - val `final` = SourceModifier("final") - val `implicit` = SourceModifier("implicit") - val `lazy` = SourceModifier("lazy") - val `macro` = SourceModifier("macro") - val `override` = SourceModifier("override") - val `private` = SourceModifier("private") - val `protected` = SourceModifier("protected") - val `sealed` = SourceModifier("sealed") - - val `case` = SymbolModifier("case") - val `trait` = SymbolModifier("trait") - val abstractOverride = SymbolModifier("abstractOverride") - val bynameParameter = SymbolModifier("bynameParameter") - val caseAccessor = SymbolModifier("caseAccessor") - val contravariant = SymbolModifier("contravariant") - val covariant = SymbolModifier("covariant") - val defaultInit = SymbolModifier("defaultInit") - val defaultParameter = SymbolModifier("defaultParameter") - val deferred = SymbolModifier("deferred") - val interface = SymbolModifier("interface") - val java = SymbolModifier("java") - val local = SymbolModifier("local") - val mutable = SymbolModifier("mutable") - val paramAccessor = SymbolModifier("paramAccessor") - val parameter = SymbolModifier("parameter") - val preSuper = SymbolModifier("preSuper") - val static = SymbolModifier("static") - - val sourceModifiers: Set[SourceModifier] = SourceModifier.all.toSet - val symbolModifiers: Set[SymbolModifier] = SymbolModifier.all.toSet - val allModifiers: Set[Modifier] = sourceModifiers ++ symbolModifiers - def values = allModifiers - - def contains(key: Modifier) = allModifiers(key) - def iterator = allModifiers.iterator - def -(elem: Modifier) = allModifiers - elem - def +(elem: Modifier) = allModifiers + elem -} diff --git a/src/library/scala/reflect/api/StandardDefinitions.scala b/src/library/scala/reflect/api/StandardDefinitions.scala deleted file mode 100755 index 21f7c9283b..0000000000 --- a/src/library/scala/reflect/api/StandardDefinitions.scala +++ /dev/null @@ -1,145 +0,0 @@ -/* NSC -- new Scala compiler - * Copyright 2005-2011 LAMP/EPFL - * @author Martin Odersky - */ - -package scala.reflect -package api - -trait StandardTypes { - self: Universe => - - val ByteTpe: Type - val ShortTpe: Type - val CharTpe: Type - val IntTpe: Type - val LongTpe: Type - val FloatTpe: Type - val DoubleTpe: Type - val BooleanTpe: Type - val UnitTpe: Type - - val AnyTpe: Type - val AnyValTpe: Type - val AnyRefTpe: Type - val ObjectTpe: Type - - val NothingTpe: Type - val NullTpe: Type - val StringTpe: Type -} - -trait StandardDefinitions extends StandardTypes { - self: Universe => - - val definitions: AbsDefinitions - - // I intend to pull everything in here out of the public API. - trait AbsDefinitionsInternal { - def ArrayModule: Symbol - def ArrayModule_overloadedApply: Symbol - def Array_apply: Symbol - def Array_clone: Symbol - def Array_length: Symbol - def Array_update: Symbol - def ByNameParamClass: Symbol - def ClassTagModule: Symbol - def ConcreteTypeTagModule: Symbol - def ConsClass: Symbol - def EmptyPackageClass: Symbol - def FunctionClass : Array[Symbol] - def IterableClass: Symbol - def IteratorClass: Symbol - def IteratorModule: Symbol - def Iterator_apply: Symbol - def JavaLangPackageClass: Symbol - def JavaRepeatedParamClass: Symbol - def ListModule: Symbol - def List_apply: Symbol - def NilModule: Symbol - def NoneModule: Symbol - def OptionClass: Symbol - def ProductClass : Array[Symbol] - def RepeatedParamClass: Symbol - def ScalaPackageClass: Symbol - def SeqClass: Symbol - def SeqModule: Symbol - def SomeClass: Symbol - def SomeModule: Symbol - def StringBuilderClass: Symbol - def SymbolClass : Symbol - def TraversableClass: Symbol - def TupleClass : Array[Symbol] - def TypeTagModule: Symbol - def ScalaPrimitiveValueClasses: List[ClassSymbol] - } - - trait AbsDefinitions extends AbsDefinitionsInternal { - // packages - def RootClass: ClassSymbol - def RootPackage: PackageSymbol - def EmptyPackage: PackageSymbol - def ScalaPackage: PackageSymbol - def JavaLangPackage: PackageSymbol - - // top types - def AnyClass : ClassSymbol - def AnyValClass: ClassSymbol - def ObjectClass: ClassSymbol - def AnyRefClass: TypeSymbol - - // bottom types - def NullClass : ClassSymbol - def NothingClass: ClassSymbol - - // the scala value classes - def UnitClass : ClassSymbol - def ByteClass : ClassSymbol - def ShortClass : ClassSymbol - def CharClass : ClassSymbol - def IntClass : ClassSymbol - def LongClass : ClassSymbol - def FloatClass : ClassSymbol - def DoubleClass : ClassSymbol - def BooleanClass: ClassSymbol - - // some special classes - def StringClass : ClassSymbol - def ClassClass : ClassSymbol - def ArrayClass: ClassSymbol - - // collections classes - def ListClass: ClassSymbol - def ListModule: ModuleSymbol - - // collections modules - def PredefModule: ModuleSymbol - - // type tags - def ClassTagClass: ClassSymbol - def TypeTagClass: ClassSymbol - def ConcreteTypeTagClass: ClassSymbol - - /** Given a type T, returns the type corresponding to the VM's - * representation: ClassClass's type constructor applied to `arg`. - */ - def vmClassType(arg: Type): Type // !!! better name? - // [Eugene] we already have arg.erasure, right? - // - // [Paul] You misunderstand the method (it could be better named). - // Given List[String], it returns java.lang.Class[List[String]] - // (or the .Net equivalent), not the erasure of List[String]. - // See def ClassType in definitions - that's what it was called before, - // and obviously that name has to go. - - /** The string representation used by the given type in the VM. - */ - def vmSignature(sym: Symbol, info: Type): String - - /** Is symbol one of the value classes? */ - def isPrimitiveValueClass(sym: Symbol): Boolean // !!! better name? - - /** Is symbol one of the numeric value classes? */ - def isNumericValueClass(sym: Symbol): Boolean // !!! better name? - } -} diff --git a/src/library/scala/reflect/api/ToolBoxes.scala b/src/library/scala/reflect/api/ToolBoxes.scala deleted file mode 100644 index 15c9fcc403..0000000000 --- a/src/library/scala/reflect/api/ToolBoxes.scala +++ /dev/null @@ -1,90 +0,0 @@ -package scala.reflect -package api - -trait ToolBoxes { self: Universe => - - type ToolBox <: AbsToolBox - - def mkToolBox(frontEnd: FrontEnd = mkSilentFrontEnd(), options: String = ""): AbsToolBox - - // [Eugene] what do you think about the interface? namely about the ``freeTypes'' part. - trait AbsToolBox { - - /** Front end of the toolbox. - * - * Accumulates and displays warnings and errors, can drop to interactive mode (if supported). - * The latter can be useful to study the typechecker or to debug complex macros. - */ - def frontEnd: FrontEnd - - /** Typechecks a tree using this ToolBox. - * This populates symbols and types of the tree and possibly transforms it to reflect certain desugarings. - * - * If the tree has unresolved type variables (represented as instances of ``FreeType'' symbols), - * then they might, might be partially or might not be specified in the ``freeTypes'' parameter. - * - * If ``silent'' is false, ``TypeError'' will be thrown in case of a typecheck error. - * If ``silent'' is true, the typecheck is silent and will return ``EmptyTree'' if an error occurs. - * Such errors don't vanish and can be inspected by turning on -Ydebug. - * - * Typechecking can be steered with the following optional parameters: - * ``withImplicitViewsDisabled'' recursively prohibits implicit views (though, implicit vals will still be looked up and filled in), default value is false - * ``withMacrosDisabled'' recursively prohibits macro expansions and macro-based implicits, default value is false - */ - def typeCheck(tree: Tree, pt: Type = WildcardType, freeTypes: Map[FreeType, Type] = Map[FreeType, Type](), silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): Tree - - /** Infers an implicit value of the expected type ``pt'' in the macro callsite context. - * - * If ``silent'' is false, ``TypeError'' will be thrown in case of an inference error. - * If ``silent'' is true, the typecheck is silent and will return ``EmptyTree'' if an error occurs. - * Such errors don't vanish and can be inspected by turning on -Xlog-implicits. - * Unlike in ``typeCheck'', ``silent'' is true by default. - */ - def inferImplicitValue(pt: Type, silent: Boolean = true, withMacrosDisabled: Boolean = false): Tree - - /** Infers an implicit view from the provided tree ``tree'' from the type ``from'' to the type ``to'' in the macro callsite context. - * - * Otional parameter, ``reportAmbiguous`` controls whether ambiguous implicit errors should be reported. - * If we search for a view simply to find out whether one type is coercible to another, it might be desirable to set this flag to ``false''. - * - * If ``silent'' is false, ``TypeError'' will be thrown in case of an inference error. - * If ``silent'' is true, the typecheck is silent and will return ``EmptyTree'' if an error occurs. - * Such errors don't vanish and can be inspected by turning on -Xlog-implicits. - * Unlike in ``typeCheck'', ``silent'' is true by default. - */ - def inferImplicitView(tree: Tree, from: Type, to: Type, silent: Boolean = true, withMacrosDisabled: Boolean = false, reportAmbiguous: Boolean = true): Tree - - /** Recursively resets symbols and types in a given tree. - * - * Note that this does not revert the tree to its pre-typer shape. - * For more info, read up https://issues.scala-lang.org/browse/SI-5464. - */ - def resetAllAttrs(tree: Tree): Tree - - /** Recursively resets locally defined symbols and types in a given tree. - * - * Note that this does not revert the tree to its pre-typer shape. - * For more info, read up https://issues.scala-lang.org/browse/SI-5464. - */ - def resetLocalAttrs(tree: Tree): Tree - - /** Compiles and runs a tree using this ToolBox. - * - * If the tree has unresolved type variables (represented as instances of ``FreeType'' symbols), - * then they all have to be specified in the ``freeTypes'' parameter or an error occurs. - * - * This spawns the compiler at the Namer phase, and pipelines the tree through that compiler. - * Currently ``runExpr'' does not accept trees that already typechecked, because typechecking isn't idempotent. - * For more info, take a look at https://issues.scala-lang.org/browse/SI-5464. - */ - def runExpr(tree: Tree, freeTypes: Map[FreeType, Type] = Map[FreeType, Type]()): Any - - /** Represents an error during toolboxing - */ - type ToolBoxError <: Throwable - val ToolBoxError: ToolBoxErrorExtractor - abstract class ToolBoxErrorExtractor { - def unapply(error: ToolBoxError): Option[(ToolBox, String)] - } - } -}
\ No newline at end of file diff --git a/src/library/scala/reflect/api/TreeBuildUtil.scala b/src/library/scala/reflect/api/TreeBuildUtil.scala deleted file mode 100644 index 87790b3812..0000000000 --- a/src/library/scala/reflect/api/TreeBuildUtil.scala +++ /dev/null @@ -1,159 +0,0 @@ -package scala.reflect -package api - -trait TreeBuildUtil { self: Universe => - - /** The symbol corresponding to the globally accessible class with the given fully qualified name `fullName`. - * Unlike `staticClassIfDefined`, throws `MissingRequirementError` is requested class cannot be found. - */ - def staticClass(fullName: String): Symbol - - /** The symbol corresponding to the globally accessible class with the given fully qualified name `fullName`. - * Unlike `staticClass`, doesn't throw `MissingRequirementError` (returns NoSymbol) is requested class cannot be found. - */ - def staticClassIfDefined(fullName: String): Symbol - - /** The symbol corresponding to the globally accessible object with the given fully qualified name `fullName`. - * Unlike `staticModuleIfDefined`, throws `MissingRequirementError` is requested object cannot be found. - */ - def staticModule(fullName: String): Symbol - - /** The symbol corresponding to the globally accessible object with the given fully qualified name `fullName`. - * Unlike `staticModule`, doesn't throw `MissingRequirementError` (returns NoSymbol) is requested object cannot be found. - */ - def staticModuleIfDefined(fullName: String): Symbol - - /** The this-ptype of the globally accessible object with the - * given fully qualified name `fullName`. - */ - def thisModuleType(fullName: String): Type - - /** Selects type symbol with given simple name `name` from the defined members of `owner`. - * Unlike `selectTypeIfDefined`, throws `MissingRequirementError` is requested type symbol cannot be found. - */ - def selectType(owner: Symbol, name: String): Symbol - - /** Selects type symbol with given simple name `name` from the defined members of `owner`. - * Unlike `selectType`, doesn't throw `MissingRequirementError` (returns NoSymbol) is requested type symbol cannot be found. - */ - def selectTypeIfDefined(owner: Symbol, name: String): Symbol - - /** Selects term symbol with given name and type from the defined members of prefix type - * Unlike `selectTermIfDefined`, throws `MissingRequirementError` is requested term symbol cannot be found. - */ - def selectTerm(owner: Symbol, name: String): Symbol - - /** Selects term symbol with given name and type from the defined members of prefix type - * Unlike `selectTerm`, doesn't throw `MissingRequirementError` (returns NoSymbol) is requested term symbol cannot be found. - */ - def selectTermIfDefined(owner: Symbol, name: String): Symbol - - /** Selects overloaded method symbol with given name and index - * Unlike `selectOverloadedMethodIfDefined`, throws `MissingRequirementError` is requested overloaded method cannot be found. - */ - def selectOverloadedMethod(owner: Symbol, name: String, index: Int): Symbol - - /** Selects overloaded method symbol with given name and index - * Unlike `selectOverloadedMethod`, doesn't throw `MissingRequirementError` (returns NoSymbol) is requested overloaded method cannot be found. - */ - def selectOverloadedMethodIfDefined(owner: Symbol, name: String, index: Int): Symbol - - /** Create a fresh free term symbol. - * @param name the name of the free variable - * @param info the type signature of the free variable - * @param value the value of the free variable at runtime - * @param flags (optional) flags of the free variable - * @param origin debug information that tells where this symbol comes from - */ - def newFreeTerm(name: String, info: Type, value: => Any, flags: Long = 0L, origin: String = null): Symbol - - /** Create a fresh free non-existential type symbol. - * @param name the name of the free variable - * @param info the type signature of the free variable - * @param value a type tag that captures the value of the free variable - * is completely phantom, since the captured type cannot be propagated to the runtime - * if it could be, we wouldn't be creating a free type to begin with - * the only usage for it is preserving the captured symbol for compile-time analysis - * @param flags (optional) flags of the free variable - * @param origin debug information that tells where this symbol comes from - */ - def newFreeType(name: String, info: Type, value: => Any, flags: Long = 0L, origin: String = null): Symbol - - /** Create a fresh free existential type symbol. - * @param name the name of the free variable - * @param info the type signature of the free variable - * @param value a type tag that captures the value of the free variable - * is completely phantom, since the captured type cannot be propagated to the runtime - * if it could be, we wouldn't be creating a free type to begin with - * the only usage for it is preserving the captured symbol for compile-time analysis - * @param flags (optional) flags of the free variable - * @param origin (optional) debug information that tells where this symbol comes from - */ - def newFreeExistential(name: String, info: Type, value: => Any, flags: Long = 0L, origin: String = null): Symbol - - /** Create a Modiiers structure given internal flags, qualifier, annotations */ - def modifiersFromInternalFlags(flags: Long, privateWithin: Name, annotations: List[Tree]): Modifiers - - val gen: TreeGen { val global: TreeBuildUtil.this.type } - - type TreeGen <: AbsTreeGen -} - -// [Eugene to Paul] we need to expose some of the functionality provided by TreeGen -// I added some stuff that was necessary for typetag materialization macros -// but we should think it over and pick other generally useful stuff -// same goes for tree traversers/transformers, type maps, etc -// and once we expose all that, there's another question: how do we stay in sync? -trait AbsTreeGen { - val global: Universe - - import global._ - import definitions._ - - /** Builds a reference to value whose type is given stable prefix. - * The type must be suitable for this. For example, it - * must not be a TypeRef pointing to an abstract type variable. - */ - def mkAttributedQualifier(tpe: Type): Tree - - /** Builds a reference to value whose type is given stable prefix. - * If the type is unsuitable, e.g. it is a TypeRef for an - * abstract type variable, then an Ident will be made using - * termSym as the Ident's symbol. In that case, termSym must - * not be NoSymbol. - */ - def mkAttributedQualifier(tpe: Type, termSym: Symbol): Tree - - /** Builds a typed reference to given symbol with given stable prefix. */ - def mkAttributedRef(pre: Type, sym: Symbol): Tree - - /** Builds a typed reference to given symbol. */ - def mkAttributedRef(sym: Symbol): Tree - - /** Builds a typed This reference to given symbol. */ - def mkAttributedThis(sym: Symbol): Tree - - /** Builds a typed Ident with an underlying symbol. */ - def mkAttributedIdent(sym: Symbol): Tree - - /** Builds a typed Select with an underlying symbol. */ - def mkAttributedSelect(qual: Tree, sym: Symbol): Tree - - /** A creator for method calls, e.g. fn[T1, T2, ...](v1, v2, ...) - * There are a number of variations. - * - * @param receiver symbol of the method receiver - * @param methodName name of the method to call - * @param targs type arguments (if Nil, no TypeApply node will be generated) - * @param args value arguments - * @return the newly created trees. - */ - def mkMethodCall(receiver: Symbol, methodName: Name, targs: List[Type], args: List[Tree]): Tree - def mkMethodCall(method: Symbol, targs: List[Type], args: List[Tree]): Tree - def mkMethodCall(method: Symbol, args: List[Tree]): Tree - def mkMethodCall(target: Tree, args: List[Tree]): Tree - def mkMethodCall(receiver: Symbol, methodName: Name, args: List[Tree]): Tree - def mkMethodCall(receiver: Tree, method: Symbol, targs: List[Type], args: List[Tree]): Tree - def mkMethodCall(target: Tree, targs: List[Type], args: List[Tree]): Tree - def mkNullaryCall(method: Symbol, targs: List[Type]): Tree -} diff --git a/src/library/scala/reflect/api/TypeTags.scala b/src/library/scala/reflect/api/TypeTags.scala deleted file mode 100644 index c58b0fcec2..0000000000 --- a/src/library/scala/reflect/api/TypeTags.scala +++ /dev/null @@ -1,254 +0,0 @@ -/* NSC -- new Scala compiler - * Copyright 2005-2011 LAMP/EPFL - * @author Martin Odersky - */ - -package scala.reflect -package api - -import java.lang.{ Class => jClass } -import language.implicitConversions - -/** - * Type tags encapsulate a representation of type T. - * They are supposed to replace the pre-2.10 concept of a [[scala.reflect.Manifest]]. - * TypeTags are much better integrated with reflection than manifests are, and are consequently much simpler. - * - * === Overview === - * - * Type tags are organized in a hierarchy of five classes: - * [[scala.reflect.ArrayTag]], [[scala.reflect.ErasureTag]], [[scala.reflect.ClassTag]], - * [[scala.reflect.api.Universe#TypeTag]] and [[scala.reflect.api.Universe#ConcreteTypeTag]]. - * - * An [[scala.reflect.ArrayTag]] value carries knowledge about how to build an array of elements of type T. - * Typically such operation is performed by storing an erasure and instantiating arrays via Java reflection, - * but [[scala.reflect.ArrayTag]] only defines an interface, not an implementation, hence it only contains the factory methods - * `newArray` and `wrap` that can be used to build, correspondingly, single-dimensional and multi-dimensional arrays. - * - * An [[scala.reflect.ErasureTag]] value wraps a Java class, which can be accessed via the `erasure` method. - * This notion, previously embodied in a [[scala.reflect.ClassManifest]] together with the notion of array creation, - * deserves a concept of itself. Quite often (e.g. for serialization or classloader introspection) it's useful to - * know an erasure, and only it, so we've implemented this notion in [[scala.reflect.ErasureTag]]. - * - * A [[scala.reflect.ClassTag]] is a standard implementation of both [[scala.reflect.ArrayTag]] and [[scala.reflect.ErasureTag]]. - * It guarantees that the source type T did not to contain any references to type parameters or abstract types. - * [[scala.reflect.ClassTag]] corresponds to a previous notion of [[scala.reflect.ClassManifest]]. - * - * A [[scala.reflect.api.Universe#TypeTag]] value wraps a full Scala type in its tpe field. - * A [[scala.reflect.api.Universe#ConcreteTypeTag]] value is a [[scala.reflect.api.Universe#TypeTag]] - * that is guaranteed not to contain any references to type parameters or abstract types. - * Both flavors of TypeTags also carry an erasure, so [[scala.reflect.api.Universe#TypeTag]] is also an [[scala.reflect.ErasureTag]], - * and [[scala.reflect.api.Universe#ConcreteTypeTag]] is additionally an [[scala.reflect.ArrayTag]] and a [[scala.reflect.ClassTag]] - * - * It is recommended to use the tag supertypes of to precisely express your intent, i.e.: - * use ArrayTag when you want to construct arrays, - * use ErasureTag when you need an erasure and don't mind it being generated for untagged abstract types, - * use ClassTag only when you need an erasure of a type that doesn't refer to untagged abstract types. - * - * === Splicing === - * - * Tags can be spliced, i.e. if compiler generates a tag for a type that contains references to tagged - * type parameters or abstract type members, it will retrieve the corresponding tag and embed it into the result. - * An example that illustrates the TypeTag embedding, consider the following function: - * - * import reflect.mirror._ - * def f[T: TypeTag, U] = { - * type L = T => U - * implicitly[TypeTag[L]] - * } - * - * Then a call of f[String, Int] will yield a result of the form - * - * TypeTag(<[ String => U ]>). - * - * Note that T has been replaced by String, because it comes with a TypeTag in f, whereas U was left as a type parameter. - * - * === ErasureTag vs ClassTag and TypeTag vs ConcreteTypeTag === - * - * Be careful with ErasureTag and TypeTag, because they will reify types even if these types are abstract. - * This makes it easy to forget to tag one of the methods in the call chain and discover it much later in the runtime - * by getting cryptic errors far away from their source. For example, consider the following snippet: - * - * def bind[T: TypeTag](name: String, value: T): IR.Result = bind((name, value)) - * def bind(p: NamedParam): IR.Result = bind(p.name, p.tpe, p.value) - * object NamedParam { - * implicit def namedValue[T: TypeTag](name: String, x: T): NamedParam = apply(name, x) - * def apply[T: TypeTag](name: String, x: T): NamedParam = new Typed[T](name, x) - * } - * - * This fragment of Scala REPL implementation defines a `bind` function that carries a named value along with its type - * into the heart of the REPL. Using a [[scala.reflect.api.Universe#TypeTag]] here is reasonable, because it is desirable - * to work with all types, even if they are type parameters or abstract type members. - * - * However if any of the three `TypeTag` context bounds is omitted, the resulting code will be incorrect, - * because the missing `TypeTag` will be transparently generated by the compiler, carrying meaningless information. - * Most likely, this problem will manifest itself elsewhere, making debugging complicated. - * If `TypeTag` context bounds were replaced with `ConcreteTypeTag`, then such errors would be reported statically. - * But in that case we wouldn't be able to use `bind` in arbitrary contexts. - * - * === Backward compatibility === - * - * TypeTags correspond loosely to Manifests. More precisely: - * The previous notion of a [[scala.reflect.ClassManifest]] corresponds to a scala.reflect.ClassTag, - * The previous notion of a [[scala.reflect.Manifest]] corresponds to scala.reflect.mirror.ConcreteTypeTag, - * Whereas scala.reflect.mirror.TypeTag is approximated by the previous notion of [[scala.reflect.OptManifest]]. - * - * In Scala 2.10, manifests are deprecated, so it's adviseable to migrate them to tags, - * because manifests might be removed in the next major release. - * - * In most cases it will be enough to replace ClassManifests with ClassTags and Manifests with ConcreteTypeTags, - * however there are a few caveats: - * - * 1) The notion of OptManifest is no longer supported. Tags can reify arbitrary types, so they are always available. - * // [Eugene] it might be useful, though, to guard against abstractness of the incoming type. - * - * 2) There's no equivalent for AnyValManifest. Consider comparing your tag with one of the core tags - * (defined in the corresponding companion objects) to find out whether it represents a primitive value class. - * - * 3) There's no replacement for factory methods defined in `ClassManifest` and `Manifest` companion objects. - * Consider assembling corresponding types using reflection API provided by Java (for classes) and Scala (for types). - * - * 4) Certain manifest functions (such as `<:<`, `>:>` and `typeArguments`) weren't included in the tag API. - * Consider using reflection API provided by Java (for classes) and Scala (for types) instead. - */ -trait TypeTags { self: Universe => - - /** - * If an implicit value of type u.TypeTag[T] is required, the compiler will make one up on demand. - * The implicitly created value contains in its tpe field a value of type u.Type that is a reflective representation of T. - * In that value, any occurrences of type parameters or abstract types U - * which come themselves with a TypeTag are represented by the type referenced by that TypeTag. - * - * @see [[scala.reflect.api.TypeTags]] - */ - @annotation.implicitNotFound(msg = "No TypeTag available for ${T}") - trait TypeTag[T] extends ErasureTag[T] with Equals with Serializable { - - def tpe: Type - def sym: Symbol = tpe.typeSymbol - - def isConcrete: Boolean = tpe.isConcrete - def notConcrete: Boolean = !isConcrete - def toConcrete: ConcreteTypeTag[T] = ConcreteTypeTag[T](tpe, erasure) - - /** case class accessories */ - override def canEqual(x: Any) = x.isInstanceOf[TypeTag[_]] - override def equals(x: Any) = x.isInstanceOf[TypeTag[_]] && this.tpe == x.asInstanceOf[TypeTag[_]].tpe - override def hashCode = scala.runtime.ScalaRunTime.hash(tpe) - override def toString = if (!self.isInstanceOf[DummyMirror]) (if (isConcrete) "*ConcreteTypeTag" else "TypeTag") + "[" + tpe + "]" else "TypeTag[?]" - } - - object TypeTag { - val Byte : TypeTag[scala.Byte] = ConcreteTypeTag.Byte - val Short : TypeTag[scala.Short] = ConcreteTypeTag.Short - val Char : TypeTag[scala.Char] = ConcreteTypeTag.Char - val Int : TypeTag[scala.Int] = ConcreteTypeTag.Int - val Long : TypeTag[scala.Long] = ConcreteTypeTag.Long - val Float : TypeTag[scala.Float] = ConcreteTypeTag.Float - val Double : TypeTag[scala.Double] = ConcreteTypeTag.Double - val Boolean : TypeTag[scala.Boolean] = ConcreteTypeTag.Boolean - val Unit : TypeTag[scala.Unit] = ConcreteTypeTag.Unit - val Any : TypeTag[scala.Any] = ConcreteTypeTag.Any - val Object : TypeTag[java.lang.Object] = ConcreteTypeTag.Object - val AnyVal : TypeTag[scala.AnyVal] = ConcreteTypeTag.AnyVal - val AnyRef : TypeTag[scala.AnyRef] = ConcreteTypeTag.AnyRef - val Nothing : TypeTag[scala.Nothing] = ConcreteTypeTag.Nothing - val Null : TypeTag[scala.Null] = ConcreteTypeTag.Null - val String : TypeTag[java.lang.String] = ConcreteTypeTag.String - - // todo. uncomment after I redo the starr - // def apply[T](tpe1: Type, erasure1: jClass[_]): TypeTag[T] = - def apply[T](tpe1: Type, erasure1: jClass[_]): TypeTag[T] = - tpe1 match { - case ByteTpe => TypeTag.Byte.asInstanceOf[TypeTag[T]] - case ShortTpe => TypeTag.Short.asInstanceOf[TypeTag[T]] - case CharTpe => TypeTag.Char.asInstanceOf[TypeTag[T]] - case IntTpe => TypeTag.Int.asInstanceOf[TypeTag[T]] - case LongTpe => TypeTag.Long.asInstanceOf[TypeTag[T]] - case FloatTpe => TypeTag.Float.asInstanceOf[TypeTag[T]] - case DoubleTpe => TypeTag.Double.asInstanceOf[TypeTag[T]] - case BooleanTpe => TypeTag.Boolean.asInstanceOf[TypeTag[T]] - case UnitTpe => TypeTag.Unit.asInstanceOf[TypeTag[T]] - case AnyTpe => TypeTag.Any.asInstanceOf[TypeTag[T]] - case ObjectTpe => TypeTag.Object.asInstanceOf[TypeTag[T]] - case AnyValTpe => TypeTag.AnyVal.asInstanceOf[TypeTag[T]] - case AnyRefTpe => TypeTag.AnyRef.asInstanceOf[TypeTag[T]] - case NothingTpe => TypeTag.Nothing.asInstanceOf[TypeTag[T]] - case NullTpe => TypeTag.Null.asInstanceOf[TypeTag[T]] - case StringTpe => TypeTag.String.asInstanceOf[TypeTag[T]] - case _ => new TypeTag[T]{ def tpe = tpe1; def erasure = erasure1 } - } - - def unapply[T](ttag: TypeTag[T]): Option[Type] = Some(ttag.tpe) - } - - /** - * If an implicit value of type u.ConcreteTypeTag[T] is required, the compiler will make one up on demand following the same procedure as for TypeTags. - * However, if the resulting type still contains references to type parameters or abstract types, a static error results. - * - * @see [[scala.reflect.api.TypeTags]] - */ - @annotation.implicitNotFound(msg = "No ConcreteTypeTag available for ${T}") - trait ConcreteTypeTag[T] extends TypeTag[T] with ClassTag[T] with Equals with Serializable { - if (!self.isInstanceOf[DummyMirror]) { - if (notConcrete) throw new Error("%s (%s) is not concrete and cannot be used to construct a concrete type tag".format(tpe, tpe.kind)) - } - - /** case class accessories */ - override def canEqual(x: Any) = x.isInstanceOf[TypeTag[_]] // this is done on purpose. TypeTag(tpe) and ConcreteTypeTag(tpe) should be equal if tpe's are equal - override def equals(x: Any) = x.isInstanceOf[TypeTag[_]] && this.tpe == x.asInstanceOf[TypeTag[_]].tpe - override def hashCode = scala.runtime.ScalaRunTime.hash(tpe) - override def toString = if (!self.isInstanceOf[DummyMirror]) "ConcreteTypeTag[" + tpe + "]" else "ConcreteTypeTag[?]" - } - - object ConcreteTypeTag { - val Byte : ConcreteTypeTag[scala.Byte] = new ConcreteTypeTag[scala.Byte]{ def tpe = ByteTpe; def erasure = ClassTag.Byte.erasure; private def readResolve() = ConcreteTypeTag.Byte } - val Short : ConcreteTypeTag[scala.Short] = new ConcreteTypeTag[scala.Short]{ def tpe = ShortTpe; def erasure = ClassTag.Short.erasure; private def readResolve() = ConcreteTypeTag.Short } - val Char : ConcreteTypeTag[scala.Char] = new ConcreteTypeTag[scala.Char]{ def tpe = CharTpe; def erasure = ClassTag.Char.erasure; private def readResolve() = ConcreteTypeTag.Char } - val Int : ConcreteTypeTag[scala.Int] = new ConcreteTypeTag[scala.Int]{ def tpe = IntTpe; def erasure = ClassTag.Int.erasure; private def readResolve() = ConcreteTypeTag.Int } - val Long : ConcreteTypeTag[scala.Long] = new ConcreteTypeTag[scala.Long]{ def tpe = LongTpe; def erasure = ClassTag.Long.erasure; private def readResolve() = ConcreteTypeTag.Long } - val Float : ConcreteTypeTag[scala.Float] = new ConcreteTypeTag[scala.Float]{ def tpe = FloatTpe; def erasure = ClassTag.Float.erasure; private def readResolve() = ConcreteTypeTag.Float } - val Double : ConcreteTypeTag[scala.Double] = new ConcreteTypeTag[scala.Double]{ def tpe = DoubleTpe; def erasure = ClassTag.Double.erasure; private def readResolve() = ConcreteTypeTag.Double } - val Boolean : ConcreteTypeTag[scala.Boolean] = new ConcreteTypeTag[scala.Boolean]{ def tpe = BooleanTpe; def erasure = ClassTag.Boolean.erasure; private def readResolve() = ConcreteTypeTag.Boolean } - val Unit : ConcreteTypeTag[scala.Unit] = new ConcreteTypeTag[scala.Unit]{ def tpe = UnitTpe; def erasure = ClassTag.Unit.erasure; private def readResolve() = ConcreteTypeTag.Unit } - val Any : ConcreteTypeTag[scala.Any] = new ConcreteTypeTag[scala.Any]{ def tpe = AnyTpe; def erasure = ClassTag.Any.erasure; private def readResolve() = ConcreteTypeTag.Any } - val Object : ConcreteTypeTag[java.lang.Object] = new ConcreteTypeTag[java.lang.Object]{ def tpe = ObjectTpe; def erasure = ClassTag.Object.erasure; private def readResolve() = ConcreteTypeTag.Object } - val AnyVal : ConcreteTypeTag[scala.AnyVal] = new ConcreteTypeTag[scala.AnyVal]{ def tpe = AnyValTpe; def erasure = ClassTag.AnyVal.erasure; private def readResolve() = ConcreteTypeTag.AnyVal } - val AnyRef : ConcreteTypeTag[scala.AnyRef] = new ConcreteTypeTag[scala.AnyRef]{ def tpe = AnyRefTpe; def erasure = ClassTag.AnyRef.erasure; private def readResolve() = ConcreteTypeTag.AnyRef } - val Nothing : ConcreteTypeTag[scala.Nothing] = new ConcreteTypeTag[scala.Nothing]{ def tpe = NothingTpe; def erasure = ClassTag.Nothing.erasure; private def readResolve() = ConcreteTypeTag.Nothing } - val Null : ConcreteTypeTag[scala.Null] = new ConcreteTypeTag[scala.Null]{ def tpe = NullTpe; def erasure = ClassTag.Null.erasure; private def readResolve() = ConcreteTypeTag.Null } - val String : ConcreteTypeTag[java.lang.String] = new ConcreteTypeTag[java.lang.String]{ def tpe = StringTpe; def erasure = ClassTag.String.erasure; private def readResolve() = ConcreteTypeTag.String } - - // todo. uncomment after I redo the starr - // def apply[T](tpe1: Type, erasure1: jClass[_]): ConcreteTypeTag[T] = - def apply[T](tpe1: Type, erasure1: jClass[_] = null): ConcreteTypeTag[T] = - tpe1 match { - case ByteTpe => ConcreteTypeTag.Byte.asInstanceOf[ConcreteTypeTag[T]] - case ShortTpe => ConcreteTypeTag.Short.asInstanceOf[ConcreteTypeTag[T]] - case CharTpe => ConcreteTypeTag.Char.asInstanceOf[ConcreteTypeTag[T]] - case IntTpe => ConcreteTypeTag.Int.asInstanceOf[ConcreteTypeTag[T]] - case LongTpe => ConcreteTypeTag.Long.asInstanceOf[ConcreteTypeTag[T]] - case FloatTpe => ConcreteTypeTag.Float.asInstanceOf[ConcreteTypeTag[T]] - case DoubleTpe => ConcreteTypeTag.Double.asInstanceOf[ConcreteTypeTag[T]] - case BooleanTpe => ConcreteTypeTag.Boolean.asInstanceOf[ConcreteTypeTag[T]] - case UnitTpe => ConcreteTypeTag.Unit.asInstanceOf[ConcreteTypeTag[T]] - case AnyTpe => ConcreteTypeTag.Any.asInstanceOf[ConcreteTypeTag[T]] - case ObjectTpe => ConcreteTypeTag.Object.asInstanceOf[ConcreteTypeTag[T]] - case AnyValTpe => ConcreteTypeTag.AnyVal.asInstanceOf[ConcreteTypeTag[T]] - case AnyRefTpe => ConcreteTypeTag.AnyRef.asInstanceOf[ConcreteTypeTag[T]] - case NothingTpe => ConcreteTypeTag.Nothing.asInstanceOf[ConcreteTypeTag[T]] - case NullTpe => ConcreteTypeTag.Null.asInstanceOf[ConcreteTypeTag[T]] - case StringTpe => ConcreteTypeTag.String.asInstanceOf[ConcreteTypeTag[T]] - case _ => new ConcreteTypeTag[T]{ def tpe = tpe1; def erasure = erasure1 } - } - - def unapply[T](ttag: TypeTag[T]): Option[Type] = if (ttag.isConcrete) Some(ttag.tpe) else None - } - - // incantations for summoning - // moved to Context, since rm.tags have their own incantations in Predef, and these guys are only useful in macros -// def tag[T](implicit ttag: TypeTag[T]) = ttag -// def typeTag[T](implicit ttag: TypeTag[T]) = ttag -// def concreteTag[T](implicit gttag: ConcreteTypeTag[T]) = cttag -// def concreteTypeTag[T](implicit gttag: ConcreteTypeTag[T]) = cttag -} diff --git a/src/library/scala/reflect/api/AnnotationInfos.scala b/src/library/scala/reflect/base/AnnotationInfos.scala index cc1c4d2b6b..f03644deef 100755..100644 --- a/src/library/scala/reflect/api/AnnotationInfos.scala +++ b/src/library/scala/reflect/base/AnnotationInfos.scala @@ -1,9 +1,10 @@ package scala.reflect -package api +package base trait AnnotationInfos { self: Universe => - type AnnotationInfo <: AnyRef + type AnnotationInfo >: Null <: AnyRef + implicit val AnnotationInfoTag: ClassTag[AnnotationInfo] val AnnotationInfo: AnnotationInfoExtractor abstract class AnnotationInfoExtractor { @@ -11,32 +12,33 @@ trait AnnotationInfos { self: Universe => def unapply(info: AnnotationInfo): Option[(Type, List[Tree], List[(Name, ClassfileAnnotArg)])] } - type ClassfileAnnotArg <: AnyRef - implicit def classfileAnnotArgTag: ArrayTag[ClassfileAnnotArg] // need a precise tag to pass to UnPickle's toArray call + type ClassfileAnnotArg >: Null <: AnyRef + implicit val ClassfileAnnotArgTag: ClassTag[ClassfileAnnotArg] - type LiteralAnnotArg <: ClassfileAnnotArg + type LiteralAnnotArg >: Null <: AnyRef with ClassfileAnnotArg + implicit val LiteralAnnotArgTag: ClassTag[LiteralAnnotArg] val LiteralAnnotArg: LiteralAnnotArgExtractor - type ArrayAnnotArg <: ClassfileAnnotArg - val ArrayAnnotArg: ArrayAnnotArgExtractor - - type NestedAnnotArg <: ClassfileAnnotArg - val NestedAnnotArg: NestedAnnotArgExtractor - abstract class LiteralAnnotArgExtractor { def apply(const: Constant): LiteralAnnotArg def unapply(arg: LiteralAnnotArg): Option[Constant] } + type ArrayAnnotArg >: Null <: AnyRef with ClassfileAnnotArg + implicit val ArrayAnnotArgTag: ClassTag[ArrayAnnotArg] + val ArrayAnnotArg: ArrayAnnotArgExtractor + abstract class ArrayAnnotArgExtractor { - def apply(const: Array[ClassfileAnnotArg]): ArrayAnnotArg + def apply(args: Array[ClassfileAnnotArg]): ArrayAnnotArg def unapply(arg: ArrayAnnotArg): Option[Array[ClassfileAnnotArg]] } + type NestedAnnotArg >: Null <: AnyRef with ClassfileAnnotArg + implicit val NestedAnnotArgTag: ClassTag[NestedAnnotArg] + val NestedAnnotArg: NestedAnnotArgExtractor + abstract class NestedAnnotArgExtractor { - def apply(anninfo: AnnotationInfo): NestedAnnotArg + def apply(annInfo: AnnotationInfo): NestedAnnotArg def unapply(arg: NestedAnnotArg): Option[AnnotationInfo] } -} - - +}
\ No newline at end of file diff --git a/src/library/scala/reflect/base/Attachments.scala b/src/library/scala/reflect/base/Attachments.scala new file mode 100644 index 0000000000..43e870fc4f --- /dev/null +++ b/src/library/scala/reflect/base/Attachments.scala @@ -0,0 +1,42 @@ +package scala.reflect +package base + +/** Attachments is a generalisation of Position. + * Typically it stores a Position of a tree, but this can be extended to encompass arbitrary payloads. + * + * Attachments have to carry positions, because we don't want to introduce even a single additional field in Tree + * imposing an unnecessary memory tax because of something that will not be used in most cases. + */ +abstract class Attachments { self => + + type Pos >: Null + + /** Gets the underlying position */ + def pos: Pos + + /** Creates a copy of this attachment with its position updated */ + def withPos(newPos: Pos): Attachments { type Pos = self.Pos } + + /** Gets the underlying payload */ + def all: Set[Any] = Set.empty + + def get[T: ClassTag]: Option[T] = + (all find (_.getClass == classTag[T].runtimeClass)).asInstanceOf[Option[T]] + + /** Creates a copy of this attachment with its payload updated */ + def add(attachment: Any): Attachments { type Pos = self.Pos } = + new NonemptyAttachments(this.pos, all + attachment) + + def remove[T: ClassTag]: Attachments { type Pos = self.Pos } = { + val newAll = all filterNot (_.getClass == classTag[T].runtimeClass) + if (newAll.isEmpty) pos.asInstanceOf[Attachments { type Pos = self.Pos }] + else new NonemptyAttachments(this.pos, newAll) + } + + private class NonemptyAttachments(override val pos: Pos, override val all: Set[Any]) extends Attachments { + type Pos = self.Pos + def withPos(newPos: Pos) = new NonemptyAttachments(newPos, all) + } +} + + diff --git a/src/library/scala/reflect/base/Base.scala b/src/library/scala/reflect/base/Base.scala new file mode 100644 index 0000000000..461eaa2e9e --- /dev/null +++ b/src/library/scala/reflect/base/Base.scala @@ -0,0 +1,763 @@ +package scala.reflect +package base + +import language.experimental.macros +import java.io.PrintWriter +import scala.annotation.switch +import scala.ref.WeakReference +import collection.mutable + +class Base extends Universe { self => + + private var nextId = 0 + + abstract class Symbol(val name: Name, val flags: FlagSet) extends SymbolBase { + val id = { nextId += 1; nextId } + def owner: Symbol + def fullName: String = + if (isEffectiveRoot || owner.isEffectiveRoot) name.toString else owner.fullName + "." + name + private def isEffectiveRoot = + this == NoSymbol || this == rootMirror.RootClass || this == rootMirror.EmptyPackageClass + + def newTermSymbol(name: TermName, pos: Position = NoPosition, flags: FlagSet = NoFlags): TermSymbol = + new TermSymbol(this, name, flags) + + def newModuleAndClassSymbol(name: Name, pos: Position = NoPosition, flags: FlagSet = NoFlags): (ModuleSymbol, ClassSymbol) = { + val c = newClassSymbol(name.toTypeName, pos, flags) + val m = new ModuleSymbol(this, name.toTermName, flags, c) + (m, c) + } + + def newMethodSymbol(name: TermName, pos: Position = NoPosition, flags: FlagSet = NoFlags): MethodSymbol + = new MethodSymbol(this, name, flags) + + def newTypeSymbol(name: TypeName, pos: Position = NoPosition, flags: FlagSet = NoFlags): TypeSymbol = + new TypeSymbol(this, name, flags) + + def newClassSymbol(name: TypeName, pos: Position = NoPosition, flags: FlagSet = NoFlags): ClassSymbol = + new ClassSymbol(this, name, flags) + + def newFreeTermSymbol(name: TermName, info: Type, value: => Any, flags: FlagSet = NoFlags, origin: String = null) = + new FreeTermSymbol(this, name, flags) + + def newFreeTypeSymbol(name: TypeName, info: Type, value: => Any, flags: FlagSet = NoFlags, origin: String = null) = + new FreeTypeSymbol(this, name, flags) + + private def kindString: String = + if (isModule) "module" + else if (isClass) "class" + else if (isFreeType) "free type" + else if (isType) "type" + else if (isMethod) "method" + else if (isFreeTerm) "free term" + else if (isTerm) "value" + else "symbol" + // [Eugene++ to Martin] base names should expose `decode` + override def toString() = s"$kindString $name" + } + implicit val SymbolTag = ClassTag[Symbol](classOf[Symbol]) + + class TermSymbol(val owner: Symbol, override val name: TermName, flags: FlagSet) + extends Symbol(name, flags) with TermSymbolBase + implicit val TermSymbolTag = ClassTag[TermSymbol](classOf[TermSymbol]) + + class TypeSymbol(val owner: Symbol, override val name: TypeName, flags: FlagSet) + extends Symbol(name, flags) with TypeSymbolBase { + override val asTypeConstructor = TypeRef(ThisType(owner), this, Nil) + } + implicit val TypeSymbolTag = ClassTag[TypeSymbol](classOf[TypeSymbol]) + + class MethodSymbol(owner: Symbol, name: TermName, flags: FlagSet) + extends TermSymbol(owner, name, flags) with MethodSymbolBase + implicit val MethodSymbolTag = ClassTag[MethodSymbol](classOf[MethodSymbol]) + + class ModuleSymbol(owner: Symbol, name: TermName, flags: FlagSet, override val moduleClass: Symbol) + extends TermSymbol(owner, name, flags) with ModuleSymbolBase + implicit val ModuleSymbolTag = ClassTag[ModuleSymbol](classOf[ModuleSymbol]) + + class ClassSymbol(owner: Symbol, name: TypeName, flags: FlagSet) + extends TypeSymbol(owner, name, flags) with ClassSymbolBase + implicit val ClassSymbolTag = ClassTag[ClassSymbol](classOf[ClassSymbol]) + + class FreeTermSymbol(owner: Symbol, name: TermName, flags: FlagSet) + extends TermSymbol(owner, name, flags) with FreeTermSymbolBase + implicit val FreeTermSymbolTag = ClassTag[FreeTermSymbol](classOf[FreeTermSymbol]) + + class FreeTypeSymbol(owner: Symbol, name: TypeName, flags: FlagSet) + extends TypeSymbol(owner, name, flags) with FreeTypeSymbolBase + implicit val FreeTypeSymbolTag = ClassTag[FreeTypeSymbol](classOf[FreeTypeSymbol]) + + + object NoSymbol extends Symbol(nme.NO_NAME, NoFlags) { + override def owner = throw new UnsupportedOperationException("NoSymbol.owner") + } + + // todo. write a decent toString that doesn't crash on recursive types + class Type extends TypeBase { def typeSymbol: Symbol = NoSymbol } + implicit val TypeTagg = ClassTag[Type](classOf[Type]) + + val NoType = new Type + val NoPrefix = new Type + + class SingletonType extends Type + implicit val SingletonTypeTag = ClassTag[SingletonType](classOf[SingletonType]) + + case class ThisType(sym: Symbol) extends SingletonType { override val typeSymbol = sym } + object ThisType extends ThisTypeExtractor + implicit val ThisTypeTag = ClassTag[ThisType](classOf[ThisType]) + + case class SingleType(pre: Type, sym: Symbol) extends SingletonType + object SingleType extends SingleTypeExtractor + implicit val SingleTypeTag = ClassTag[SingleType](classOf[SingleType]) + + case class SuperType(thistpe: Type, supertpe: Type) extends SingletonType + object SuperType extends SuperTypeExtractor + implicit val SuperTypeTag = ClassTag[SuperType](classOf[SuperType]) + + case class ConstantType(value: Constant) extends SingletonType + object ConstantType extends ConstantTypeExtractor + implicit val ConstantTypeTag = ClassTag[ConstantType](classOf[ConstantType]) + + case class TypeRef(pre: Type, sym: Symbol, args: List[Type]) extends Type { override val typeSymbol = sym } + object TypeRef extends TypeRefExtractor + implicit val TypeRefTag = ClassTag[TypeRef](classOf[TypeRef]) + + abstract class CompoundType extends Type + implicit val CompoundTypeTag = ClassTag[CompoundType](classOf[CompoundType]) + + case class RefinedType(parents: List[Type], decls: Scope) extends CompoundType + object RefinedType extends RefinedTypeExtractor { + def apply(parents: List[Type], decls: Scope, clazz: Symbol): RefinedType = + RefinedType(parents, decls) + } + implicit val RefinedTypeTag = ClassTag[RefinedType](classOf[RefinedType]) + + case class ClassInfoType(parents: List[Type], decls: Scope, override val typeSymbol: Symbol) extends CompoundType + object ClassInfoType extends ClassInfoTypeExtractor + implicit val ClassInfoTypeTag = ClassTag[ClassInfoType](classOf[ClassInfoType]) + + case class MethodType(params: List[Symbol], resultType: Type) extends Type + object MethodType extends MethodTypeExtractor + implicit val MethodTypeTag = ClassTag[MethodType](classOf[MethodType]) + + case class NullaryMethodType(resultType: Type) extends Type + object NullaryMethodType extends NullaryMethodTypeExtractor + implicit val NullaryMethodTypeTag = ClassTag[NullaryMethodType](classOf[NullaryMethodType]) + + case class PolyType(typeParams: List[Symbol], resultType: Type) extends Type + object PolyType extends PolyTypeExtractor + implicit val PolyTypeTag = ClassTag[PolyType](classOf[PolyType]) + + case class ExistentialType(quantified: List[Symbol], underlying: Type) extends Type { override def typeSymbol = underlying.typeSymbol } + object ExistentialType extends ExistentialTypeExtractor + implicit val ExistentialTypeTag = ClassTag[ExistentialType](classOf[ExistentialType]) + + case class AnnotatedType(annotations: List[AnnotationInfo], underlying: Type, selfsym: Symbol) extends Type { override def typeSymbol = underlying.typeSymbol } + object AnnotatedType extends AnnotatedTypeExtractor + implicit val AnnotatedTypeTag = ClassTag[AnnotatedType](classOf[AnnotatedType]) + + case class TypeBounds(lo: Type, hi: Type) extends Type + object TypeBounds extends TypeBoundsExtractor + implicit val TypeBoundsTag = ClassTag[TypeBounds](classOf[TypeBounds]) + + val WildcardType = new Type + + case class BoundedWildcardType(bounds: TypeBounds) extends Type + object BoundedWildcardType extends BoundedWildcardTypeExtractor + implicit val BoundedWildcardTypeTag = ClassTag[BoundedWildcardType](classOf[BoundedWildcardType]) + + type Scope = Iterable[Symbol] + implicit val ScopeTag = ClassTag[Scope](classOf[Scope]) + + def newScope = newScopeWith() + def newNestedScope(outer: Iterable[Symbol]) = newScope + def newScopeWith(elems: Symbol*): Scope = elems + + abstract class Name(str: String) extends NameBase { + override def toString = str + } + implicit val NameTag = ClassTag[Name](classOf[Name]) + + class TermName(str: String) extends Name(str) { + def isTermName = true + def isTypeName = false + def toTermName = this + def toTypeName = new TypeName(str) + } + implicit val TermNameTag = ClassTag[TermName](classOf[TermName]) + + class TypeName(str: String) extends Name(str) { + def isTermName = false + def isTypeName = true + def toTermName = new TermName(str) + def toTypeName = this + } + implicit val TypeNameTag = ClassTag[TypeName](classOf[TypeName]) + + def newTermName(str: String) = new TermName(str) + def newTypeName(str: String) = new TypeName(str) + + object nme extends TermNamesBase { + type NameType = TermName + val EMPTY = newTermName("") + val ROOT = newTermName("<root>") + val EMPTY_PACKAGE_NAME = newTermName("<empty>") + val CONSTRUCTOR = newTermName("<init>") + val NO_NAME = newTermName("<none>") + val WILDCARD = newTermName("_") + } + + object tpnme extends TypeNamesBase { + type NameType = TypeName + val EMPTY = nme.EMPTY.toTypeName + val ROOT = nme.ROOT.toTypeName + val EMPTY_PACKAGE_NAME = nme.EMPTY_PACKAGE_NAME.toTypeName + val WILDCARD = nme.WILDCARD.toTypeName + } + + type FlagSet = Long + val NoFlags = 0L + implicit val FlagSetTag = ClassTag[FlagSet](classOf[FlagSet]) + + class Modifiers(override val flags: FlagSet, + override val privateWithin: Name, + override val annotations: List[Tree]) extends ModifiersBase { + def hasFlag(flags: FlagSet) = (this.flags & flags) != 0 + def hasAllFlags(flags: FlagSet) = (flags & ~this.flags) == 0 + } + + implicit val ModifiersTag = ClassTag[Modifiers](classOf[Modifiers]) + + object Modifiers extends ModifiersCreator { + def apply(flags: Long, + privateWithin: Name, + annotations: List[Tree]) = new Modifiers(flags, privateWithin, annotations) + } + + case class Constant(value: Any) + object Constant extends ConstantExtractor + implicit val ConstantTag = ClassTag[Constant](classOf[Constant]) + + case class AnnotationInfo(atp: Type, args: List[Tree], assocs: List[(Name, ClassfileAnnotArg)]) + object AnnotationInfo extends AnnotationInfoExtractor + implicit val AnnotationInfoTag = ClassTag[AnnotationInfo](classOf[AnnotationInfo]) + + abstract class ClassfileAnnotArg + implicit val ClassfileAnnotArgTag = ClassTag[ClassfileAnnotArg](classOf[ClassfileAnnotArg]) + + case class LiteralAnnotArg(const: Constant) extends ClassfileAnnotArg + object LiteralAnnotArg extends LiteralAnnotArgExtractor + implicit val LiteralAnnotArgTag = ClassTag[LiteralAnnotArg](classOf[LiteralAnnotArg]) + + case class ArrayAnnotArg(args: Array[ClassfileAnnotArg]) extends ClassfileAnnotArg + object ArrayAnnotArg extends ArrayAnnotArgExtractor + implicit val ArrayAnnotArgTag = ClassTag[ArrayAnnotArg](classOf[ArrayAnnotArg]) + + case class NestedAnnotArg(annInfo: AnnotationInfo) extends ClassfileAnnotArg + object NestedAnnotArg extends NestedAnnotArgExtractor + implicit val NestedAnnotArgTag = ClassTag[NestedAnnotArg](classOf[NestedAnnotArg]) + + class Position extends Attachments { + override type Pos = Position + def pos = this + def withPos(newPos: Position) = newPos + def isRange = false + def focus = this + } + implicit val PositionTag = ClassTag[Position](classOf[Position]) + + val NoPosition = new Position + + def atPos[T <: Tree](pos: Position)(tree: T): T = tree + + private val generated = new mutable.HashMap[String, WeakReference[Symbol]] + + private def cached(name: String)(symExpr: => Symbol): Symbol = + generated get name match { + case Some(WeakReference(sym)) => + sym + case _ => + val sym = symExpr + generated(name) = WeakReference(sym) + sym + } + + object build extends BuildBase { + def selectType(owner: Symbol, name: String): TypeSymbol = { + val clazz = new ClassSymbol(owner, newTypeName(name), NoFlags) + cached(clazz.fullName)(clazz).asTypeSymbol + } + + def selectTerm(owner: Symbol, name: String): TermSymbol = { + val valu = new MethodSymbol(owner, newTermName(name), NoFlags) + cached(valu.fullName)(valu).asTermSymbol + } + + def selectOverloadedMethod(owner: Symbol, name: String, index: Int): MethodSymbol = + selectTerm(owner, name).asMethodSymbol + + def newNestedSymbol(owner: Symbol, name: Name, pos: Position, flags: Long, isClass: Boolean): Symbol = + if (name.isTypeName) + if (isClass) new ClassSymbol(owner, name.toTypeName, flags) + else new TypeSymbol(owner, name.toTypeName, flags) + else new TermSymbol(owner, name.toTermName, flags) + + def newFreeTerm(name: String, info: Type, value: => Any, flags: Long = 0L, origin: String = null): FreeTermSymbol = + new FreeTermSymbol(rootMirror.RootClass, newTermName(name), flags) + + def newFreeType(name: String, info: Type, value: => Any, flags: Long = 0L, origin: String = null): FreeTypeSymbol = + new FreeTypeSymbol(rootMirror.RootClass, newTypeName(name), flags) + + def newFreeExistential(name: String, info: Type, value: => Any, flags: Long = 0L, origin: String = null): FreeTypeSymbol = + new FreeTypeSymbol(rootMirror.RootClass, newTypeName(name), flags) + + def setTypeSignature[S <: Symbol](sym: S, tpe: Type): S = sym + + def setAnnotations[S <: Symbol](sym: S, annots: List[AnnotationInfo]): S = sym + + def flagsFromBits(bits: Long): FlagSet = bits + + object emptyValDef extends ValDef(NoMods, nme.WILDCARD, TypeTree(NoType), EmptyTree) { + override def isEmpty = true + } + + def This(sym: Symbol): Tree = self.This(sym.name.toTypeName) + + def Select(qualifier: Tree, sym: Symbol): Select = self.Select(qualifier, sym.name) + + def Ident(sym: Symbol): Ident = self.Ident(sym.name) + + def TypeTree(tp: Type): TypeTree = self.TypeTree() + + def thisPrefix(sym: Symbol): Type = SingleType(NoPrefix, sym) + + def setType[T <: Tree](tree: T, tpe: Type): T = tree + + def setSymbol[T <: Tree](tree: T, sym: Symbol): T = tree + } + + import build._ + + class Mirror extends MirrorOf[self.type] { + val universe: self.type = self + + lazy val RootClass = new ClassSymbol(NoSymbol, tpnme.ROOT, NoFlags) + lazy val RootPackage = new ModuleSymbol(NoSymbol, nme.ROOT, NoFlags, RootClass) + lazy val EmptyPackageClass = new ClassSymbol(RootClass, tpnme.EMPTY_PACKAGE_NAME, NoFlags) + lazy val EmptyPackage = new ModuleSymbol(RootClass, nme.EMPTY_PACKAGE_NAME, NoFlags, EmptyPackageClass) + + def staticClass(fullName: String): ClassSymbol = + mkStatic[ClassSymbol](fullName) + + def staticModule(fullName: String): ModuleSymbol = + mkStatic[ModuleSymbol](fullName) + + private def mkStatic[S <: Symbol : ClassTag](fullName: String): S = + cached(fullName) { + val point = fullName lastIndexOf '.' + val owner = + if (point > 0) staticModule(fullName take point).moduleClass + else rootMirror.RootClass + val name = fullName drop point + 1 + val symtag = implicitly[ClassTag[S]] + if (symtag == ClassSymbolTag) new ClassSymbol(owner, newTypeName(name), NoFlags) + else owner.newModuleAndClassSymbol(newTermName(name))._1 + }.asInstanceOf[S] + } + + lazy val rootMirror = new Mirror + + import rootMirror._ + + object definitions extends DefinitionsBase { + lazy val ScalaPackage = staticModule("scala") + lazy val ScalaPackageClass = ScalaPackage.moduleClass.asClassSymbol + + lazy val AnyClass = staticClass("scala.Any") + lazy val AnyValClass = staticClass("scala.Any") + lazy val ObjectClass = staticClass("java.lang.Object") + lazy val AnyRefClass = ObjectClass + + lazy val NullClass = staticClass("scala.Null") + lazy val NothingClass = staticClass("scala.Nothing") + + lazy val UnitClass = staticClass("scala.Unit") + lazy val ByteClass = staticClass("scala.Byte") + lazy val ShortClass = staticClass("scala.Short") + lazy val CharClass = staticClass("scala.Char") + lazy val IntClass = staticClass("scala.Int") + lazy val LongClass = staticClass("scala.Long") + lazy val FloatClass = staticClass("scala.Float") + lazy val DoubleClass = staticClass("scala.Double") + lazy val BooleanClass = staticClass("scala.Boolean") + + lazy val StringClass = staticClass("java.lang.String") + lazy val ClassClass = staticClass("java.lang.Class") + lazy val ArrayClass = staticClass("scala.Array") + lazy val ListClass = staticClass("scala.List") + + lazy val PredefModule = staticModule("scala.Predef") + } + + import definitions._ + + private def thisModuleType(fullName: String): Type = ThisType(staticModule(fullName).moduleClass) + private lazy val ScalaPrefix = thisModuleType("scala") + private lazy val JavaLangPrefix = thisModuleType("java.lang") + + lazy val ByteTpe = TypeRef(ScalaPrefix, ByteClass, Nil) + lazy val ShortTpe = TypeRef(ScalaPrefix, ShortClass, Nil) + lazy val CharTpe = TypeRef(ScalaPrefix, CharClass, Nil) + lazy val IntTpe = TypeRef(ScalaPrefix, IntClass, Nil) + lazy val LongTpe = TypeRef(ScalaPrefix, LongClass, Nil) + lazy val FloatTpe = TypeRef(ScalaPrefix, FloatClass, Nil) + lazy val DoubleTpe = TypeRef(ScalaPrefix, DoubleClass, Nil) + lazy val BooleanTpe = TypeRef(ScalaPrefix, BooleanClass, Nil) + lazy val UnitTpe = TypeRef(ScalaPrefix, UnitClass, Nil) + lazy val AnyTpe = TypeRef(ScalaPrefix, AnyClass, Nil) + lazy val AnyValTpe = TypeRef(ScalaPrefix, AnyValClass, Nil) + lazy val NothingTpe = TypeRef(ScalaPrefix, NothingClass, Nil) + lazy val NullTpe = TypeRef(ScalaPrefix, NullClass, Nil) + lazy val ObjectTpe = TypeRef(JavaLangPrefix, ObjectClass, Nil) + lazy val AnyRefTpe = ObjectTpe + lazy val StringTpe = TypeRef(JavaLangPrefix, StringClass, Nil) + + private var nodeCount = 0 // not synchronized + + abstract class Tree extends TreeBase with Product { + def isDef: Boolean = false + def isEmpty: Boolean = false + + /** The canonical way to test if a Tree represents a term. + */ + def isTerm: Boolean = this match { + case _: TermTree => true + case Bind(name, _) => name.isTermName + case Select(_, name) => name.isTermName + case Ident(name) => name.isTermName + case Annotated(_, arg) => arg.isTerm + case _ => false + } + + /** The canonical way to test if a Tree represents a type. + */ + def isType: Boolean = this match { + case _: TypTree => true + case Bind(name, _) => name.isTypeName + case Select(_, name) => name.isTypeName + case Ident(name) => name.isTypeName + case Annotated(_, arg) => arg.isType + case _ => false + } + } + + def show(tree: Tree) = s"<tree ${tree.getClass}>" + + trait TermTree extends Tree + + trait TypTree extends Tree + + trait SymTree extends Tree + + trait NameTree extends Tree { + def name: Name + } + + trait RefTree extends SymTree with NameTree { + def qualifier: Tree // empty for Idents + def name: Name + } + + abstract class DefTree extends SymTree with NameTree { + def name: Name + override def isDef = true + } + + case object EmptyTree extends TermTree { + override def isEmpty = true + } + + abstract class MemberDef extends DefTree { + def mods: Modifiers + } + + case class PackageDef(pid: RefTree, stats: List[Tree]) + extends MemberDef { + def name = pid.name + def mods = NoMods + } + object PackageDef extends PackageDefExtractor + + abstract class ImplDef extends MemberDef { + def impl: Template + } + + case class ClassDef(mods: Modifiers, name: TypeName, tparams: List[TypeDef], impl: Template) + extends ImplDef + object ClassDef extends ClassDefExtractor + + case class ModuleDef(mods: Modifiers, name: TermName, impl: Template) + extends ImplDef + object ModuleDef extends ModuleDefExtractor + + abstract class ValOrDefDef extends MemberDef { + val name: Name + val tpt: Tree + val rhs: Tree + } + + case class ValDef(mods: Modifiers, name: TermName, tpt: Tree, rhs: Tree) extends ValOrDefDef + object ValDef extends ValDefExtractor + + case class DefDef(mods: Modifiers, name: Name, tparams: List[TypeDef], + vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree) extends ValOrDefDef + object DefDef extends DefDefExtractor + + case class TypeDef(mods: Modifiers, name: TypeName, tparams: List[TypeDef], rhs: Tree) + extends MemberDef + object TypeDef extends TypeDefExtractor + + case class LabelDef(name: TermName, params: List[Ident], rhs: Tree) + extends DefTree with TermTree + object LabelDef extends LabelDefExtractor + + case class ImportSelector(name: Name, namePos: Int, rename: Name, renamePos: Int) + object ImportSelector extends ImportSelectorExtractor + + case class Import(expr: Tree, selectors: List[ImportSelector]) + extends SymTree + object Import extends ImportExtractor + + case class Template(parents: List[Tree], self: ValDef, body: List[Tree]) + extends SymTree + object Template extends TemplateExtractor + + case class Block(stats: List[Tree], expr: Tree) + extends TermTree + object Block extends BlockExtractor + + case class CaseDef(pat: Tree, guard: Tree, body: Tree) + extends Tree + object CaseDef extends CaseDefExtractor + + case class Alternative(trees: List[Tree]) + extends TermTree + object Alternative extends AlternativeExtractor + + case class Star(elem: Tree) + extends TermTree + object Star extends StarExtractor + + case class Bind(name: Name, body: Tree) + extends DefTree + object Bind extends BindExtractor + + case class UnApply(fun: Tree, args: List[Tree]) + extends TermTree + object UnApply extends UnApplyExtractor + + case class ArrayValue(elemtpt: Tree, elems: List[Tree]) + extends TermTree + object ArrayValue extends ArrayValueExtractor + + case class Function(vparams: List[ValDef], body: Tree) + extends TermTree with SymTree + object Function extends FunctionExtractor + + case class Assign(lhs: Tree, rhs: Tree) + extends TermTree + object Assign extends AssignExtractor + + case class AssignOrNamedArg(lhs: Tree, rhs: Tree) + extends TermTree + object AssignOrNamedArg extends AssignOrNamedArgExtractor + + case class If(cond: Tree, thenp: Tree, elsep: Tree) + extends TermTree + object If extends IfExtractor + + case class Match(selector: Tree, cases: List[CaseDef]) + extends TermTree + object Match extends MatchExtractor + + case class Return(expr: Tree) + extends TermTree with SymTree + object Return extends ReturnExtractor + + case class Try(block: Tree, catches: List[CaseDef], finalizer: Tree) + extends TermTree + object Try extends TryExtractor + + case class Throw(expr: Tree) + extends TermTree + object Throw extends ThrowExtractor + + case class New(tpt: Tree) extends TermTree + object New extends NewExtractor + + case class Typed(expr: Tree, tpt: Tree) + extends TermTree + object Typed extends TypedExtractor + + abstract class GenericApply extends TermTree { + val fun: Tree + val args: List[Tree] + } + + case class TypeApply(fun: Tree, args: List[Tree]) + extends GenericApply + object TypeApply extends TypeApplyExtractor + + case class Apply(fun: Tree, args: List[Tree]) + extends GenericApply + object Apply extends ApplyExtractor + + case class ApplyDynamic(qual: Tree, args: List[Tree]) + extends TermTree with SymTree + object ApplyDynamic extends ApplyDynamicExtractor + + case class Super(qual: Tree, mix: TypeName) extends TermTree + object Super extends SuperExtractor + + case class This(qual: TypeName) + extends TermTree with SymTree + object This extends ThisExtractor + + case class Select(qualifier: Tree, name: Name) + extends RefTree + object Select extends SelectExtractor + + case class Ident(name: Name) extends RefTree { + def qualifier: Tree = EmptyTree + } + object Ident extends IdentExtractor + + case class ReferenceToBoxed(ident: Ident) extends TermTree + object ReferenceToBoxed extends ReferenceToBoxedExtractor + + case class Literal(value: Constant) + extends TermTree { + assert(value ne null) + } + object Literal extends LiteralExtractor + + case class Annotated(annot: Tree, arg: Tree) extends Tree + object Annotated extends AnnotatedExtractor + + case class SingletonTypeTree(ref: Tree) + extends TypTree + object SingletonTypeTree extends SingletonTypeTreeExtractor + + case class SelectFromTypeTree(qualifier: Tree, name: TypeName) + extends TypTree with RefTree + object SelectFromTypeTree extends SelectFromTypeTreeExtractor + + case class CompoundTypeTree(templ: Template) + extends TypTree + object CompoundTypeTree extends CompoundTypeTreeExtractor + + case class AppliedTypeTree(tpt: Tree, args: List[Tree]) + extends TypTree + object AppliedTypeTree extends AppliedTypeTreeExtractor + + case class TypeBoundsTree(lo: Tree, hi: Tree) + extends TypTree + object TypeBoundsTree extends TypeBoundsTreeExtractor + + case class ExistentialTypeTree(tpt: Tree, whereClauses: List[Tree]) + extends TypTree + object ExistentialTypeTree extends ExistentialTypeTreeExtractor + + case class TypeTree() extends TypTree { + val original: Tree = null + override def isEmpty = true + } + object TypeTree extends TypeTreeExtractor + + implicit val TreeTag = ClassTag[Tree](classOf[Tree]) + implicit val TermTreeTag = ClassTag[TermTree](classOf[TermTree]) + implicit val TypTreeTag = ClassTag[TypTree](classOf[TypTree]) + implicit val SymTreeTag = ClassTag[SymTree](classOf[SymTree]) + implicit val NameTreeTag = ClassTag[NameTree](classOf[NameTree]) + implicit val RefTreeTag = ClassTag[RefTree](classOf[RefTree]) + implicit val DefTreeTag = ClassTag[DefTree](classOf[DefTree]) + implicit val MemberDefTag = ClassTag[MemberDef](classOf[MemberDef]) + implicit val PackageDefTag = ClassTag[PackageDef](classOf[PackageDef]) + implicit val ImplDefTag = ClassTag[ImplDef](classOf[ImplDef]) + implicit val ClassDefTag = ClassTag[ClassDef](classOf[ClassDef]) + implicit val ModuleDefTag = ClassTag[ModuleDef](classOf[ModuleDef]) + implicit val ValOrDefDefTag = ClassTag[ValOrDefDef](classOf[ValOrDefDef]) + implicit val ValDefTag = ClassTag[ValDef](classOf[ValDef]) + implicit val DefDefTag = ClassTag[DefDef](classOf[DefDef]) + implicit val TypeDefTag = ClassTag[TypeDef](classOf[TypeDef]) + implicit val LabelDefTag = ClassTag[LabelDef](classOf[LabelDef]) + implicit val ImportSelectorTag = ClassTag[ImportSelector](classOf[ImportSelector]) + implicit val ImportTag = ClassTag[Import](classOf[Import]) + implicit val TemplateTag = ClassTag[Template](classOf[Template]) + implicit val BlockTag = ClassTag[Block](classOf[Block]) + implicit val CaseDefTag = ClassTag[CaseDef](classOf[CaseDef]) + implicit val AlternativeTag = ClassTag[Alternative](classOf[Alternative]) + implicit val StarTag = ClassTag[Star](classOf[Star]) + implicit val BindTag = ClassTag[Bind](classOf[Bind]) + implicit val UnApplyTag = ClassTag[UnApply](classOf[UnApply]) + implicit val ArrayValueTag = ClassTag[ArrayValue](classOf[ArrayValue]) + implicit val FunctionTag = ClassTag[Function](classOf[Function]) + implicit val AssignTag = ClassTag[Assign](classOf[Assign]) + implicit val AssignOrNamedArgTag = ClassTag[AssignOrNamedArg](classOf[AssignOrNamedArg]) + implicit val IfTag = ClassTag[If](classOf[If]) + implicit val MatchTag = ClassTag[Match](classOf[Match]) + implicit val ReturnTag = ClassTag[Return](classOf[Return]) + implicit val TryTag = ClassTag[Try](classOf[Try]) + implicit val ThrowTag = ClassTag[Throw](classOf[Throw]) + implicit val NewTag = ClassTag[New](classOf[New]) + implicit val TypedTag = ClassTag[Typed](classOf[Typed]) + implicit val GenericApplyTag = ClassTag[GenericApply](classOf[GenericApply]) + implicit val TypeApplyTag = ClassTag[TypeApply](classOf[TypeApply]) + implicit val ApplyTag = ClassTag[Apply](classOf[Apply]) + implicit val ApplyDynamicTag = ClassTag[ApplyDynamic](classOf[ApplyDynamic]) + implicit val SuperTag = ClassTag[Super](classOf[Super]) + implicit val ThisTag = ClassTag[This](classOf[This]) + implicit val SelectTag = ClassTag[Select](classOf[Select]) + implicit val IdentTag = ClassTag[Ident](classOf[Ident]) + implicit val ReferenceToBoxedTag = ClassTag[ReferenceToBoxed](classOf[ReferenceToBoxed]) + implicit val LiteralTag = ClassTag[Literal](classOf[Literal]) + implicit val AnnotatedTag = ClassTag[Annotated](classOf[Annotated]) + implicit val SingletonTypeTreeTag = ClassTag[SingletonTypeTree](classOf[SingletonTypeTree]) + implicit val SelectFromTypeTreeTag = ClassTag[SelectFromTypeTree](classOf[SelectFromTypeTree]) + implicit val CompoundTypeTreeTag = ClassTag[CompoundTypeTree](classOf[CompoundTypeTree]) + implicit val AppliedTypeTreeTag = ClassTag[AppliedTypeTree](classOf[AppliedTypeTree]) + implicit val TypeBoundsTreeTag = ClassTag[TypeBoundsTree](classOf[TypeBoundsTree]) + implicit val ExistentialTypeTreeTag = ClassTag[ExistentialTypeTree](classOf[ExistentialTypeTree]) + implicit val TypeTreeTag = ClassTag[TypeTree](classOf[TypeTree]) + + // [Eugene++] to be removed after SI-5863 is fixed + def ClassDef(sym: Symbol, impl: Template): ClassDef = ??? + def ModuleDef(sym: Symbol, impl: Template): ModuleDef = ??? + def ValDef(sym: Symbol, rhs: Tree): ValDef = ??? + def ValDef(sym: Symbol): ValDef = ??? + def DefDef(sym: Symbol, mods: Modifiers, vparamss: List[List[ValDef]], rhs: Tree): DefDef = ??? + def DefDef(sym: Symbol, vparamss: List[List[ValDef]], rhs: Tree): DefDef = ??? + def DefDef(sym: Symbol, mods: Modifiers, rhs: Tree): DefDef = ??? + def DefDef(sym: Symbol, rhs: Tree): DefDef = ??? + def DefDef(sym: Symbol, rhs: List[List[Symbol]] => Tree): DefDef = ??? + def TypeDef(sym: Symbol, rhs: Tree): TypeDef = ??? + def TypeDef(sym: Symbol): TypeDef = ??? + def LabelDef(sym: Symbol, params: List[Symbol], rhs: Tree): LabelDef = ??? + def CaseDef(pat: Tree, body: Tree): CaseDef = ??? + def Bind(sym: Symbol, body: Tree): Bind = ??? + def Try(body: Tree, cases: (Tree, Tree)*): Try = ??? + def Throw(tpe: Type, args: Tree*): Throw = ??? + def Apply(sym: Symbol, args: Tree*): Tree = ??? + def New(tpt: Tree, argss: List[List[Tree]]): Tree = ??? + def New(tpe: Type, args: Tree*): Tree = ??? + def New(sym: Symbol, args: Tree*): Tree = ??? + def ApplyConstructor(tpt: Tree, args: List[Tree]): Tree = ??? + def Super(sym: Symbol, mix: TypeName): Tree = ??? + def This(sym: Symbol): Tree = ??? + def Select(qualifier: Tree, name: String): Select = ??? + def Select(qualifier: Tree, sym: Symbol): Select = ??? + def Ident(name: String): Ident = ??? + def Ident(sym: Symbol): Ident = ??? + def Block(stats: Tree*): Block = ??? + def TypeTree(tp: Type): TypeTree = ??? +} diff --git a/src/library/scala/reflect/base/BuildUtils.scala b/src/library/scala/reflect/base/BuildUtils.scala new file mode 100644 index 0000000000..eaba0ec2b7 --- /dev/null +++ b/src/library/scala/reflect/base/BuildUtils.scala @@ -0,0 +1,90 @@ +package scala.reflect +package base + +trait BuildUtils { self: Universe => + + val build: BuildBase + + abstract class BuildBase { + /** Selects type symbol with given simple name `name` from the defined members of `owner`. + */ + def selectType(owner: Symbol, name: String): TypeSymbol + + /** Selects term symbol with given name and type from the defined members of prefix type + */ + def selectTerm(owner: Symbol, name: String): TermSymbol + + /** Selects overloaded method symbol with given name and index + */ + def selectOverloadedMethod(owner: Symbol, name: String, index: Int): MethodSymbol + + /** A fresh symbol with given name `name`, position `pos` and flags `flags` that has + * the current symbol as its owner. + */ + def newNestedSymbol(owner: Symbol, name: Name, pos: Position, flags: FlagSet, isClass: Boolean): Symbol + + /** Create a fresh free term symbol. + * @param name the name of the free variable + * @param info the type signature of the free variable + * @param value the value of the free variable at runtime + * @param flags (optional) flags of the free variable + * @param origin debug information that tells where this symbol comes from + */ + def newFreeTerm(name: String, info: Type, value: => Any, flags: FlagSet = NoFlags, origin: String = null): FreeTermSymbol + + /** Create a fresh free non-existential type symbol. + * @param name the name of the free variable + * @param info the type signature of the free variable + * @param value a type tag that captures the value of the free variable + * is completely phantom, since the captured type cannot be propagated to the runtime + * if it could be, we wouldn't be creating a free type to begin with + * the only usage for it is preserving the captured symbol for compile-time analysis + * @param flags (optional) flags of the free variable + * @param origin debug information that tells where this symbol comes from + */ + def newFreeType(name: String, info: Type, value: => Any, flags: FlagSet = NoFlags, origin: String = null): FreeTypeSymbol + + /** Create a fresh free existential type symbol. + * @param name the name of the free variable + * @param info the type signature of the free variable + * @param value a type tag that captures the value of the free variable + * is completely phantom, since the captured type cannot be propagated to the runtime + * if it could be, we wouldn't be creating a free type to begin with + * the only usage for it is preserving the captured symbol for compile-time analysis + * @param flags (optional) flags of the free variable + * @param origin (optional) debug information that tells where this symbol comes from + * [Martin to Eugene: why needed?] + */ + def newFreeExistential(name: String, info: Type, value: => Any, flags: FlagSet = NoFlags, origin: String = null): FreeTypeSymbol + + /** Set symbol's type signature to given type. + * @return the symbol itself + */ + def setTypeSignature[S <: Symbol](sym: S, tpe: Type): S + + /** Set symbol's annotations to given annotations `annots`. + */ + def setAnnotations[S <: Symbol](sym: S, annots: List[AnnotationInfo]): S + + def flagsFromBits(bits: Long): FlagSet + + // [Eugene++ to Martin] these are necessary for reification + // on a second thought, I added them to BuildUtils instead of base + + def emptyValDef: ValDef + + def This(sym: Symbol): Tree + + def Select(qualifier: Tree, sym: Symbol): Select + + def Ident(sym: Symbol): Ident + + def TypeTree(tp: Type): TypeTree + + def thisPrefix(sym: Symbol): Type + + def setType[T <: Tree](tree: T, tpe: Type): T + + def setSymbol[T <: Tree](tree: T, sym: Symbol): T + } +} diff --git a/src/library/scala/reflect/base/Constants.scala b/src/library/scala/reflect/base/Constants.scala new file mode 100644 index 0000000000..8f98e85ad0 --- /dev/null +++ b/src/library/scala/reflect/base/Constants.scala @@ -0,0 +1,20 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2011 LAMP/EPFL + * @author Martin Odersky + */ + +package scala.reflect +package base + +trait Constants { + self: Universe => + + type Constant >: Null <: AnyRef + implicit val ConstantTag: ClassTag[Constant] + val Constant: ConstantExtractor + + abstract class ConstantExtractor { + def apply(value: Any): Constant + def unapply(arg: Constant): Option[Any] + } +} diff --git a/src/library/scala/reflect/base/FlagSets.scala b/src/library/scala/reflect/base/FlagSets.scala new file mode 100644 index 0000000000..57946d0f27 --- /dev/null +++ b/src/library/scala/reflect/base/FlagSets.scala @@ -0,0 +1,17 @@ +package scala.reflect +package base + +trait FlagSets { self: Universe => + + /** An abstract type representing sets of flags that apply to definition trees and symbols */ + type FlagSet + + /** A tag that preserves the identity of the `FlagSet` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val FlagSetTag: ClassTag[FlagSet] + + /** The empty set of flags */ + val NoFlags: FlagSet +} + diff --git a/src/library/scala/reflect/base/MirrorOf.scala b/src/library/scala/reflect/base/MirrorOf.scala new file mode 100644 index 0000000000..03e035cd81 --- /dev/null +++ b/src/library/scala/reflect/base/MirrorOf.scala @@ -0,0 +1,25 @@ +package scala.reflect +package base + +// [Eugene++ to Martin] why was this a member of `scala.reflect`, but not `scala.reflect.base`? + +abstract class MirrorOf[U <: base.Universe with Singleton] { + /** .. */ + val universe: U + + /** .. */ + def RootClass: U#ClassSymbol + def RootPackage: U#ModuleSymbol + def EmptyPackageClass: U#ClassSymbol + def EmptyPackage: U#ModuleSymbol + + /** The symbol corresponding to the globally accessible class with the + * given fully qualified name `fullName`. + */ + def staticClass(fullName: String): U#ClassSymbol + + /** The symbol corresponding to the globally accessible object with the + * given fully qualified name `fullName`. + */ + def staticModule(fullName: String): U#ModuleSymbol +} diff --git a/src/library/scala/reflect/base/Mirrors.scala b/src/library/scala/reflect/base/Mirrors.scala new file mode 100644 index 0000000000..50866ef000 --- /dev/null +++ b/src/library/scala/reflect/base/Mirrors.scala @@ -0,0 +1,12 @@ +package scala.reflect +package base + +trait Mirrors { + self: Universe => + + /** .. */ + type Mirror >: Null <: MirrorOf[self.type] + + /** .. */ + val rootMirror: Mirror +} diff --git a/src/library/scala/reflect/api/Names.scala b/src/library/scala/reflect/base/Names.scala index 96651ffa88..edf2ba7dc9 100755..100644 --- a/src/library/scala/reflect/api/Names.scala +++ b/src/library/scala/reflect/base/Names.scala @@ -1,5 +1,5 @@ package scala.reflect -package api +package base /** A trait that manages names. * A name is a string in one of two name universes: terms and types. @@ -11,16 +11,21 @@ package api * `name1 == name2` implies `name1 eq name2`. */ trait Names { + /** The abstract type of names */ - type Name >: Null <: AbsName + type Name >: Null <: NameBase + implicit val NameTag: ClassTag[Name] /** The abstract type of names representing terms */ - type TypeName <: Name + type TypeName >: Null <: Name + implicit val TypeNameTag: ClassTag[TypeName] /** The abstract type of names representing types */ - type TermName <: Name + type TermName >: Null <: Name + implicit val TermNameTag: ClassTag[TermName] - abstract class AbsName { + /** The base API that all names support */ + abstract class NameBase { /** Is this name a term name? */ def isTermName: Boolean @@ -32,24 +37,6 @@ trait Names { /** Returns a type name that represents the same string as this name */ def toTypeName: TypeName - - /** Replaces all occurrences of \$op_names in this name by corresponding operator symbols. - * Example: `foo_\$plus\$eq` becomes `foo_+=` - */ - def decoded: String - - /** Replaces all occurrences of operator symbols in this name by corresponding \$op_names. - * Example: `foo_+=` becomes `foo_\$plus\$eq`. - */ - def encoded: String - - /** The decoded name, still represented as a name. - */ - def decodedName: Name - - /** The encoded name, still represented as a name. - */ - def encodedName: Name } /** Create a new term name. diff --git a/src/library/scala/reflect/base/Positions.scala b/src/library/scala/reflect/base/Positions.scala new file mode 100644 index 0000000000..cefeb51c9a --- /dev/null +++ b/src/library/scala/reflect/base/Positions.scala @@ -0,0 +1,22 @@ +package scala.reflect +package base + +trait Positions { + self: Universe => + + /** .. */ + type Position >: Null <: Attachments { type Pos = Position } + + /** A tag that preserves the identity of the `FlagSet` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val PositionTag: ClassTag[Position] + + /** .. */ + val NoPosition: Position + + /** Assigns a given position to all position-less nodes of a given AST. + */ + def atPos[T <: Tree](pos: Position)(tree: T): T + // [Eugene++] why do we have this in base? +} diff --git a/src/library/scala/reflect/api/Scopes.scala b/src/library/scala/reflect/base/Scopes.scala index 4a5702eadc..a5db01c0ce 100755..100644 --- a/src/library/scala/reflect/api/Scopes.scala +++ b/src/library/scala/reflect/base/Scopes.scala @@ -1,9 +1,14 @@ package scala.reflect -package api +package base trait Scopes { self: Universe => - type Scope <: Iterable[Symbol] + type Scope >: Null <: Iterable[Symbol] + + /** A tag that preserves the identity of the `Scope` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val ScopeTag: ClassTag[Scope] /** Create a new scope */ def newScope: Scope diff --git a/src/library/scala/reflect/base/StandardDefinitions.scala b/src/library/scala/reflect/base/StandardDefinitions.scala new file mode 100644 index 0000000000..eff23b539e --- /dev/null +++ b/src/library/scala/reflect/base/StandardDefinitions.scala @@ -0,0 +1,75 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2011 LAMP/EPFL + * @author Martin Odersky + */ + +package scala.reflect +package base + +// [Eugene++] not sure whether we need this in the top level of the universe +trait StandardTypes { + self: Universe => + + val ByteTpe: Type + val ShortTpe: Type + val CharTpe: Type + val IntTpe: Type + val LongTpe: Type + val FloatTpe: Type + val DoubleTpe: Type + val BooleanTpe: Type + val UnitTpe: Type + + val AnyTpe: Type + val AnyValTpe: Type + val AnyRefTpe: Type + val ObjectTpe: Type + + val NothingTpe: Type + val NullTpe: Type + val StringTpe: Type +} + +trait StandardDefinitions extends StandardTypes { + self: Universe => + + val definitions: DefinitionsBase + + // [Eugene] todo. shortcut to these fields if possible when generating tags + // todo. also shortcut to StandardTypes, of course + trait DefinitionsBase { + // packages + def ScalaPackageClass: ClassSymbol + def ScalaPackage: ModuleSymbol + + // top types + def AnyClass : ClassSymbol + def AnyValClass: ClassSymbol + def ObjectClass: ClassSymbol + def AnyRefClass: TypeSymbol + + // bottom types + def NullClass : ClassSymbol + def NothingClass: ClassSymbol + + // the scala value classes + def UnitClass : ClassSymbol + def ByteClass : ClassSymbol + def ShortClass : ClassSymbol + def CharClass : ClassSymbol + def IntClass : ClassSymbol + def LongClass : ClassSymbol + def FloatClass : ClassSymbol + def DoubleClass : ClassSymbol + def BooleanClass: ClassSymbol + + // some special classes + def StringClass : ClassSymbol + def ClassClass : ClassSymbol + def ArrayClass : ClassSymbol + def ListClass : ClassSymbol // [Eugene] I'd say List has earned its right to be here + + // the Predef object + def PredefModule: ModuleSymbol + } +} diff --git a/src/library/scala/reflect/base/StandardNames.scala b/src/library/scala/reflect/base/StandardNames.scala new file mode 100644 index 0000000000..8a3fbe9683 --- /dev/null +++ b/src/library/scala/reflect/base/StandardNames.scala @@ -0,0 +1,29 @@ +/* NSC -- new Scala compiler +* Copyright 2005-2011 LAMP/EPFL +* @author Martin Odersky +*/ + +package scala.reflect +package base + +trait StandardNames { + self: Universe => + + val nme: TermNamesBase + val tpnme: TypeNamesBase + + trait NamesBase { + type NameType >: Null <: Name + val EMPTY: NameType + val ROOT: NameType + val EMPTY_PACKAGE_NAME: NameType + val WILDCARD: NameType + } + + trait TypeNamesBase extends NamesBase + + trait TermNamesBase extends NamesBase { + val CONSTRUCTOR: TermName + val NO_NAME: NameType + } +} diff --git a/src/library/scala/reflect/base/Symbols.scala b/src/library/scala/reflect/base/Symbols.scala new file mode 100644 index 0000000000..9404520073 --- /dev/null +++ b/src/library/scala/reflect/base/Symbols.scala @@ -0,0 +1,272 @@ +package scala.reflect +package base + +trait Symbols { self: Universe => + + // [Eugene++ to Martin] why is Symbol >: Null, whereas all other symbol types are not nullable? + // same question goes for Types + + /** The abstract type of symbols representing declarations */ + type Symbol >: Null <: SymbolBase + + /** A tag that preserves the identity of the `Symbol` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val SymbolTag: ClassTag[Symbol] + + /** The abstract type of type symbols representing type, class, and trait declarations, + * as well as type parameters + */ + type TypeSymbol >: Null <: Symbol with TypeSymbolBase + + /** A tag that preserves the identity of the `TypeSymbol` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val TypeSymbolTag: ClassTag[TypeSymbol] + + /** The abstract type of term symbols representing val, var, def, and object declarations as + * well as packages and value parameters. + */ + type TermSymbol >: Null <: Symbol with TermSymbolBase + + /** A tag that preserves the identity of the `TermSymbol` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val TermSymbolTag: ClassTag[TermSymbol] + + /** The abstract type of method symbols representing def declarations */ + type MethodSymbol >: Null <: TermSymbol with MethodSymbolBase + + /** A tag that preserves the identity of the `MethodSymbol` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val MethodSymbolTag: ClassTag[MethodSymbol] + + /** The abstract type of module symbols representing object declarations */ + type ModuleSymbol >: Null <: TermSymbol with ModuleSymbolBase + + /** A tag that preserves the identity of the `ModuleSymbol` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val ModuleSymbolTag: ClassTag[ModuleSymbol] + + /** The abstract type of class symbols representing class and trait definitions */ + type ClassSymbol >: Null <: TypeSymbol with ClassSymbolBase + + /** A tag that preserves the identity of the `ClassSymbol` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val ClassSymbolTag: ClassTag[ClassSymbol] + + /** The abstract type of free terms introduced by reification */ + type FreeTermSymbol >: Null <: TermSymbol with FreeTermSymbolBase + + /** A tag that preserves the identity of the `FreeTermSymbol` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val FreeTermSymbolTag: ClassTag[FreeTermSymbol] + + /** The abstract type of free types introduced by reification */ + type FreeTypeSymbol >: Null <: TypeSymbol with FreeTypeSymbolBase + + /** A tag that preserves the identity of the `FreeTypeSymbol` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val FreeTypeSymbolTag: ClassTag[FreeTypeSymbol] + + /** A special "missing" symbol */ + val NoSymbol: Symbol + + /** The base API that all symbols support */ + trait SymbolBase { this: Symbol => + + /** An id number which is unique for all symbols in this universe */ + // [Eugene++ to Martin] do we leave this here? + def id: Int + + /** The owner of this symbol. This is the symbol + * that directly contains the current symbol's definition. + * The `NoSymbol` symbol does not have an owner, and calling this method + * on one causes an internal error. + * The owner of the Scala root class [[scala.reflect.api.mirror.RootClass]] + * and the Scala root object [[scala.reflect.api.mirror.RootPackage]] is `NoSymbol`. + * Every other symbol has a chain of owners that ends in + * [[scala.reflect.api.mirror.RootClass]]. + */ + def owner: Symbol + + /** The type of the symbol name. + * Can be either `TermName` or `TypeName` depending on whether this is a `TermSymbol` or a `TypeSymbol`. + * + * Type name namespaces do not intersect with term name namespaces. + * This fact is reflected in different types for names of `TermSymbol` and `TypeSymbol`. + */ + type NameType >: Null <: Name + + /** The name of the symbol as a member of the `Name` type. + */ + def name: Name + + /** The encoded full path name of this symbol, where outer names and inner names + * are separated by periods. + */ + def fullName: String + + /** If this symbol is a class, this symbol; otherwise the next enclosing + * class, or `NoSymbol` if none exists. + */ + def enclosingClass: Symbol = + if (isClass || this == NoSymbol) this else owner.enclosingClass + + /** If this symbol is a method, this symbol; otherwise the next enclosing + * method, or `NoSymbol` if none exists. + */ + def enclosingMethod: Symbol = + if (isMethod || this == NoSymbol) this else owner.enclosingMethod + + /** Does this symbol represent the definition of a type? + * Note that every symbol is either a term or a type. + * So for every symbol `sym`, either `sym.isTerm` is true + * or `sym.isType` is true. + */ + def isType: Boolean = false + + /** This symbol cast to a TypeSymbol. + * Returns ClassCastException if `isType` is false. + */ + def asTypeSymbol: TypeSymbol = throw new ClassCastException(toString) + + /** Does this symbol represent the definition of a term? + * Note that every symbol is either a term or a term. + * So for every symbol `sym`, either `sym.isTerm` is true + * or `sym.isTerm` is true. + */ + def isTerm: Boolean = false + + /** This symbol cast to a TermSymbol. + * Returns ClassCastException if `isTerm` is false. + */ + def asTermSymbol: TermSymbol = throw new ClassCastException(toString) + + /** Does this symbol represent the definition of a method? + * If yes, `isTerm` is also guaranteed to be true. + */ + def isMethod: Boolean = false + + /** This symbol cast to a MethodSymbol. + * Returns ClassCastException if `isMethod` is false. + */ + def asMethodSymbol: MethodSymbol = throw new ClassCastException(toString) + + /** Does this symbol represent the definition of a module (i.e. it + * results from an object definition?). + * If yes, `isTerm` is also guaranteed to be true. + */ + def isModule: Boolean = false + + /** This symbol cast to a ModuleSymbol defined by an object definition. + * Returns ClassCastException if `isModule` is false. + */ + def asModuleSymbol: ModuleSymbol = throw new ClassCastException(toString) + + /** Does this symbol represent the definition of a class or trait? + * If yes, `isType` is also guaranteed to be true. + */ + def isClass: Boolean = false + + /** This symbol cast to a ClassSymbol representing a class or trait. + * Returns ClassCastException if `isClass` is false. + */ + def asClassSymbol: ClassSymbol = throw new ClassCastException(toString) + + /** Does this symbol represent a free term captured by reification? + * If yes, `isTerm` is also guaranteed to be true. + */ + def isFreeTerm: Boolean = false + + /** This symbol cast to a free term symbol. + * Returns ClassCastException if `isFreeTerm` is false. + */ + def asFreeTermSymbol: FreeTermSymbol = throw new ClassCastException(toString) + + /** Does this symbol represent a free type captured by reification? + * If yes, `isType` is also guaranteed to be true. + */ + def isFreeType: Boolean = false + + /** This symbol cast to a free type symbol. + * Returns ClassCastException if `isFreeType` is false. + */ + def asFreeTypeSymbol: FreeTypeSymbol = throw new ClassCastException(toString) + + def newTermSymbol(name: TermName, pos: Position = NoPosition, flags: FlagSet = NoFlags): TermSymbol + def newModuleAndClassSymbol(name: Name, pos: Position = NoPosition, flags: FlagSet = NoFlags): (ModuleSymbol, ClassSymbol) + def newMethodSymbol(name: TermName, pos: Position = NoPosition, flags: FlagSet = NoFlags): MethodSymbol + def newTypeSymbol(name: TypeName, pos: Position = NoPosition, flags: FlagSet = NoFlags): TypeSymbol + def newClassSymbol(name: TypeName, pos: Position = NoPosition, flags: FlagSet = NoFlags): ClassSymbol + } + + /** The base API that all type symbols support */ + trait TypeSymbolBase extends SymbolBase { this: TypeSymbol => + /** Type symbols have their names of type `TypeName`. + */ + final type NameType = TypeName + + /** The type constructor corresponding to this type symbol. + * This is different from `asType` in that type parameters + * are part of results of `asType`, but not of `asTypeConstructor`. + * + * Example: Given a class declaration `class C[T] { ... } `, that generates a symbol + * `C`. Then `C.asType` is the type `C[T]`, but `C.asTypeConstructor` is `C`. + */ + def asTypeConstructor: Type + + override def isType = true + override def asTypeSymbol = this + } + + /** The base API that all term symbols support */ + trait TermSymbolBase extends SymbolBase { this: TermSymbol => + /** Term symbols have their names of type `TermName`. + */ + final type NameType = TermName + + final override def isTerm = true + final override def asTermSymbol = this + } + + /** The base API that all method symbols support */ + trait MethodSymbolBase extends TermSymbolBase { this: MethodSymbol => + final override def isMethod = true + final override def asMethodSymbol = this + } + + /** The base API that all module symbols support */ + trait ModuleSymbolBase extends TermSymbolBase { this: ModuleSymbol => + /** The class implicitly associated with the object definition. + */ + def moduleClass: Symbol // needed for tree traversals + // [Eugene++] when this becomes `moduleClass: ClassSymbol`, it will be the happiest day in my life + + final override def isModule = true + final override def asModuleSymbol = this + } + + /** The base API that all class symbols support */ + trait ClassSymbolBase extends TypeSymbolBase { this: ClassSymbol => + final override def isClass = true + final override def asClassSymbol = this + } + + /** The base API that all free type symbols support */ + trait FreeTypeSymbolBase extends TypeSymbolBase { this: FreeTypeSymbol => + final override def isFreeType = true + final override def asFreeTypeSymbol = this + } + + /** The base API that all free term symbols support */ + trait FreeTermSymbolBase extends TermSymbolBase { this: FreeTermSymbol => + final override def isFreeTerm = true + final override def asFreeTermSymbol = this + } +} diff --git a/src/library/scala/reflect/base/TagInterop.scala b/src/library/scala/reflect/base/TagInterop.scala new file mode 100644 index 0000000000..158d1979e5 --- /dev/null +++ b/src/library/scala/reflect/base/TagInterop.scala @@ -0,0 +1,29 @@ +package scala.reflect +package base + +import scala.runtime.ScalaRunTime._ + +trait TagInterop { self: Universe => + def classTagToClassManifest[T](tag: ClassTag[T]): ClassManifest[T] = { + val runtimeClass = tag.runtimeClass + if (runtimeClass.isArray) { + val elementClass = arrayElementClass(runtimeClass) + val elementManifest = classTagToClassManifest(ClassTag(elementClass)) + ClassManifest.arrayType(elementManifest).asInstanceOf[ClassManifest[T]] + } else { + ClassManifest.fromClass(runtimeClass.asInstanceOf[Class[T]]) + } + } + + // [Eugene++] `mirror` parameters are now of type `Any`, because I can't make these path-dependent types work + // if you're brave enough, replace `Any` with `Mirror`, recompile and run interop_typetags_are_manifests.scala + + // [Eugene++] would be great if we could approximate the interop without any mirrors + // todo. think how to implement that + + def typeTagToManifest[T: ClassTag](mirror: Any, tag: base.Universe # TypeTag[T]): Manifest[T] = + throw new UnsupportedOperationException("This universe does not support tag -> manifest conversions. Use scala.reflect.runtime.universe from scala-reflect.jar.") + + def manifestToTypeTag[T](mirror: Any, manifest: Manifest[T]): base.Universe # TypeTag[T] = + throw new UnsupportedOperationException("This universe does not support manifest -> tag conversions. Use scala.reflect.runtime.universe from scala-reflect.jar.") +} diff --git a/src/library/scala/reflect/base/TreeCreator.scala b/src/library/scala/reflect/base/TreeCreator.scala new file mode 100644 index 0000000000..c9c8de2307 --- /dev/null +++ b/src/library/scala/reflect/base/TreeCreator.scala @@ -0,0 +1,6 @@ +package scala.reflect +package base + +abstract class TreeCreator { + def apply[U <: Universe with Singleton](m: MirrorOf[U]): U # Tree +} diff --git a/src/library/scala/reflect/base/Trees.scala b/src/library/scala/reflect/base/Trees.scala new file mode 100644 index 0000000000..298d229570 --- /dev/null +++ b/src/library/scala/reflect/base/Trees.scala @@ -0,0 +1,1459 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2011 LAMP/EPFL + * @author Martin Odersky + */ +package scala.reflect +package base + +// [Eugene++] of all reflection APIs, this one is in the biggest need of review and documentation + +// Syncnote: Trees are currently not thread-safe. +// [Eugene++] now when trees are finally abstract types, can we do something for this? +trait Trees { self: Universe => + + /** The base API that all trees support */ + abstract class TreeBase extends Product { this: Tree => + /** ... */ + def isDef: Boolean + + /** ... */ + def isEmpty: Boolean + + /** The canonical way to test if a Tree represents a term. + */ + def isTerm: Boolean + + /** The canonical way to test if a Tree represents a type. + */ + def isType: Boolean + + /** Obtains string representation of a tree */ + override def toString: String = show(this) + } + + /** Obtains string representation of a tree */ + def show(tree: Tree): String + + /** Tree is the basis for scala's abstract syntax. The nodes are + * implemented as case classes, and the parameters which initialize + * a given tree are immutable: however Trees have several mutable + * fields which are manipulated in the course of typechecking, + * including pos, symbol, and tpe. + * + * Newly instantiated trees have tpe set to null (though it + * may be set immediately thereafter depending on how it is + * constructed.) When a tree is passed to the typer, typically via + * `typer.typed(tree)`, under normal circumstances the tpe must be + * null or the typer will ignore it. Furthermore, the typer is not + * required to return the same tree it was passed. + * + * Trees can be easily traversed with e.g. foreach on the root node; + * for a more nuanced traversal, subclass Traverser. Transformations + * can be considerably trickier: see the numerous subclasses of + * Transformer found around the compiler. + * + * Copying Trees should be done with care depending on whether + * it need be done lazily or strictly (see LazyTreeCopier and + * StrictTreeCopier) and on whether the contents of the mutable + * fields should be copied. The tree copiers will copy the mutable + * attributes to the new tree; calling Tree#duplicate will copy + * symbol and tpe, but all the positions will be focused. + * + * Trees can be coarsely divided into four mutually exclusive categories: + * + * - TermTrees, representing terms + * - TypTrees, representing types. Note that is `TypTree`, not `TypeTree`. + * - SymTrees, which may represent types or terms. + * - Other Trees, which have none of those as parents. + * + * SymTrees include important nodes Ident and Select, which are + * used as both terms and types; they are distinguishable based on + * whether the Name is a TermName or TypeName. The correct way for + * to test for a type or a term (on any Tree) are the isTerm/isType + * methods on Tree. + * + * "Others" are mostly syntactic or short-lived constructs. Examples + * include CaseDef, which wraps individual match cases: they are + * neither terms nor types, nor do they carry a symbol. Another + * example is Parens, which is eliminated during parsing. + */ + type Tree >: Null <: TreeBase + // [Eugene++] todo. discuss nullability of abstract types + + /** A tag that preserves the identity of the `Tree` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val TreeTag: ClassTag[Tree] + + /** The empty tree */ + val EmptyTree: Tree + + /** A tree for a term. Not all terms are TermTrees; use isTerm + * to reliably identify terms. + */ + type TermTree >: Null <: AnyRef with Tree + + /** A tag that preserves the identity of the `TermTree` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val TermTreeTag: ClassTag[TermTree] + + /** A tree for a type. Not all types are TypTrees; use isType + * to reliably identify types. + */ + type TypTree >: Null <: AnyRef with Tree + + /** A tag that preserves the identity of the `TypTree` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val TypTreeTag: ClassTag[TypTree] + + /** A tree with a mutable symbol field, initialized to NoSymbol. + */ + type SymTree >: Null <: AnyRef with Tree + + /** A tag that preserves the identity of the `SymTree` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val SymTreeTag: ClassTag[SymTree] + + /** A tree with a name - effectively, a DefTree or RefTree. + */ + type NameTree >: Null <: AnyRef with Tree + + /** A tag that preserves the identity of the `NameTree` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val NameTreeTag: ClassTag[NameTree] + + /** A tree which references a symbol-carrying entity. + * References one, as opposed to defining one; definitions + * are in DefTrees. + */ + type RefTree >: Null <: SymTree with NameTree + + /** A tag that preserves the identity of the `RefTree` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val RefTreeTag: ClassTag[RefTree] + + /** A tree which defines a symbol-carrying entity. + */ + type DefTree >: Null <: SymTree with NameTree + + /** A tag that preserves the identity of the `DefTree` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val DefTreeTag: ClassTag[DefTree] + + /** Common base class for all member definitions: types, classes, + * objects, packages, vals and vars, defs. + */ + type MemberDef >: Null <: DefTree + + /** A tag that preserves the identity of the `MemberDef` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val MemberDefTag: ClassTag[MemberDef] + + /** A packaging, such as `package pid { stats }` + */ + type PackageDef >: Null <: MemberDef + + /** A tag that preserves the identity of the `PackageDef` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val PackageDefTag: ClassTag[PackageDef] + + /** The constructor/deconstructor for `PackageDef` instances. */ + val PackageDef: PackageDefExtractor + + /** An extractor class to create and pattern match with syntax `PackageDef(pid, stats)`. + * This AST node corresponds to the following Scala code: + * + * `package` pid { stats } + */ + abstract class PackageDefExtractor { + def apply(pid: RefTree, stats: List[Tree]): PackageDef + def unapply(packageDef: PackageDef): Option[(RefTree, List[Tree])] + } + + /** A common base class for class and object definitions. + */ + type ImplDef >: Null <: MemberDef + + /** A tag that preserves the identity of the `ImplDef` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val ImplDefTag: ClassTag[ImplDef] + + /** A class definition. + */ + type ClassDef >: Null <: ImplDef + + /** A tag that preserves the identity of the `ClassDef` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val ClassDefTag: ClassTag[ClassDef] + + /** The constructor/deconstructor for `ClassDef` instances. */ + val ClassDef: ClassDefExtractor + + /** An extractor class to create and pattern match with syntax `ClassDef(mods, name, tparams, impl)`. + * This AST node corresponds to the following Scala code: + * + * mods `class` name [tparams] impl + * + * Where impl stands for: + * + * `extends` parents { defs } + */ + abstract class ClassDefExtractor { + def apply(mods: Modifiers, name: TypeName, tparams: List[TypeDef], impl: Template): ClassDef + def unapply(classDef: ClassDef): Option[(Modifiers, TypeName, List[TypeDef], Template)] + } + + /** An object definition, e.g. `object Foo`. Internally, objects are + * quite frequently called modules to reduce ambiguity. + * Eliminated by refcheck. + */ + type ModuleDef >: Null <: ImplDef + + /** A tag that preserves the identity of the `ModuleDef` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val ModuleDefTag: ClassTag[ModuleDef] + + /** The constructor/deconstructor for `ModuleDef` instances. */ + val ModuleDef: ModuleDefExtractor + + /** An extractor class to create and pattern match with syntax `ModuleDef(mods, name, impl)`. + * This AST node corresponds to the following Scala code: + * + * mods `object` name impl + * + * Where impl stands for: + * + * `extends` parents { defs } + */ + abstract class ModuleDefExtractor { + def apply(mods: Modifiers, name: TermName, impl: Template): ModuleDef + def unapply(moduleDef: ModuleDef): Option[(Modifiers, TermName, Template)] + } + + /** A common base class for ValDefs and DefDefs. + */ + type ValOrDefDef >: Null <: MemberDef + + /** A tag that preserves the identity of the `ValOrDefDef` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val ValOrDefDefTag: ClassTag[ValOrDefDef] + + /** Broadly speaking, a value definition. All these are encoded as ValDefs: + * + * - immutable values, e.g. "val x" + * - mutable values, e.g. "var x" - the MUTABLE flag set in mods + * - lazy values, e.g. "lazy val x" - the LAZY flag set in mods + * - method parameters, see vparamss in DefDef - the PARAM flag is set in mods + * - explicit self-types, e.g. class A { self: Bar => } - !!! not sure what is set. + */ + type ValDef >: Null <: ValOrDefDef + + /** A tag that preserves the identity of the `ValDef` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val ValDefTag: ClassTag[ValDef] + + /** The constructor/deconstructor for `ValDef` instances. */ + val ValDef: ValDefExtractor + + /** An extractor class to create and pattern match with syntax `ValDef(mods, name, tpt, rhs)`. + * This AST node corresponds to the following Scala code: + * + * mods `val` name: tpt = rhs + * + * mods `var` name: tpt = rhs + * + * mods name: tpt = rhs // in signatures of function and method definitions + * + * self: Bar => // self-types (!!! not sure what is set) + * + * If the type of a value is not specified explicitly (i.e. is meant to be inferred), + * this is expressed by having `tpt` set to `TypeTree()` (but not to an `EmptyTree`!). + */ + abstract class ValDefExtractor { + def apply(mods: Modifiers, name: TermName, tpt: Tree, rhs: Tree): ValDef + def unapply(valDef: ValDef): Option[(Modifiers, TermName, Tree, Tree)] + } + + /** A method or macro definition. + * @param name The name of the method or macro. Can be a type name in case this is a type macro + */ + type DefDef >: Null <: ValOrDefDef + + /** A tag that preserves the identity of the `DefDef` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val DefDefTag: ClassTag[DefDef] + + /** The constructor/deconstructor for `DefDef` instances. */ + val DefDef: DefDefExtractor + + /** An extractor class to create and pattern match with syntax `DefDef(mods, name, tparams, vparamss, tpt, rhs)`. + * This AST node corresponds to the following Scala code: + * + * mods `def` name[tparams](vparams_1)...(vparams_n): tpt = rhs + * + * If the return type is not specified explicitly (i.e. is meant to be inferred), + * this is expressed by having `tpt` set to `TypeTree()` (but not to an `EmptyTree`!). + */ + abstract class DefDefExtractor { + def apply(mods: Modifiers, name: Name, tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree): DefDef + def unapply(defDef: DefDef): Option[(Modifiers, Name, List[TypeDef], List[List[ValDef]], Tree, Tree)] + } + + /** An abstract type, a type parameter, or a type alias. + * Eliminated by erasure. + */ + type TypeDef >: Null <: MemberDef + + /** A tag that preserves the identity of the `TypeDef` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val TypeDefTag: ClassTag[TypeDef] + + /** The constructor/deconstructor for `TypeDef` instances. */ + val TypeDef: TypeDefExtractor + + /** An extractor class to create and pattern match with syntax `TypeDef(mods, name, tparams, rhs)`. + * This AST node corresponds to the following Scala code: + * + * mods `type` name[tparams] = rhs + * + * mods `type` name[tparams] >: lo <: hi + * + * First usage illustrates `TypeDefs` representing type aliases and type parameters. + * Second usage illustrates `TypeDefs` representing abstract types, + * where lo and hi are both `TypeBoundsTrees` and `Modifier.deferred` is set in mods. + */ + abstract class TypeDefExtractor { + def apply(mods: Modifiers, name: TypeName, tparams: List[TypeDef], rhs: Tree): TypeDef + def unapply(typeDef: TypeDef): Option[(Modifiers, TypeName, List[TypeDef], Tree)] + } + + /** A labelled expression. Not expressible in language syntax, but + * generated by the compiler to simulate while/do-while loops, and + * also by the pattern matcher. + * + * The label acts much like a nested function, where `params` represents + * the incoming parameters. The symbol given to the LabelDef should have + * a MethodType, as if it were a nested function. + * + * Jumps are apply nodes attributed with a label's symbol. The + * arguments from the apply node will be passed to the label and + * assigned to the Idents. + * + * Forward jumps within a block are allowed. + */ + type LabelDef >: Null <: DefTree with TermTree + + /** A tag that preserves the identity of the `LabelDef` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val LabelDefTag: ClassTag[LabelDef] + + /** The constructor/deconstructor for `LabelDef` instances. */ + val LabelDef: LabelDefExtractor + + /** An extractor class to create and pattern match with syntax `LabelDef(name, params, rhs)`. + * + * This AST node does not have direct correspondence to Scala code. + * It is used for tailcalls and like. + * For example, while/do are desugared to label defs as follows: + * + * while (cond) body ==> LabelDef($L, List(), if (cond) { body; L$() } else ()) + * do body while (cond) ==> LabelDef($L, List(), body; if (cond) L$() else ()) + */ + abstract class LabelDefExtractor { + def apply(name: TermName, params: List[Ident], rhs: Tree): LabelDef + def unapply(labelDef: LabelDef): Option[(TermName, List[Ident], Tree)] + } + + /** Import selector + * + * Representation of an imported name its optional rename and their optional positions + * + * Eliminated by typecheck. + * + * @param name the imported name + * @param namePos its position or -1 if undefined + * @param rename the name the import is renamed to (== name if no renaming) + * @param renamePos the position of the rename or -1 if undefined + */ + type ImportSelector >: Null <: AnyRef + + /** A tag that preserves the identity of the `ImportSelector` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val ImportSelectorTag: ClassTag[ImportSelector] + + /** The constructor/deconstructor for `ImportSelector` instances. */ + val ImportSelector: ImportSelectorExtractor + + /** An extractor class to create and pattern match with syntax `ImportSelector(name:, namePos, rename, renamePos)`. + * This is not an AST node, it is used as a part of the `Import` node. + */ + abstract class ImportSelectorExtractor { + def apply(name: Name, namePos: Int, rename: Name, renamePos: Int): ImportSelector + def unapply(importSelector: ImportSelector): Option[(Name, Int, Name, Int)] + } + + /** Import clause + * + * @param expr + * @param selectors + */ + type Import >: Null <: SymTree + + /** A tag that preserves the identity of the `Import` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val ImportTag: ClassTag[Import] + + /** The constructor/deconstructor for `Import` instances. */ + val Import: ImportExtractor + + /** An extractor class to create and pattern match with syntax `Import(expr, selectors)`. + * This AST node corresponds to the following Scala code: + * + * import expr.{selectors} + * + * Selectors are a list of pairs of names (from, to). // [Eugene++] obviously, they no longer are. please, document! + * The last (and maybe only name) may be a nme.WILDCARD. For instance: + * + * import qual.{x, y => z, _} + * + * Would be represented as: + * + * Import(qual, List(("x", "x"), ("y", "z"), (WILDCARD, null))) + * + * The symbol of an `Import` is an import symbol @see Symbol.newImport. + * It's used primarily as a marker to check that the import has been typechecked. + */ + abstract class ImportExtractor { + def apply(expr: Tree, selectors: List[ImportSelector]): Import + def unapply(import_ : Import): Option[(Tree, List[ImportSelector])] + } + + /** Instantiation template of a class or trait + * + * @param parents + * @param body + */ + type Template >: Null <: SymTree + + /** A tag that preserves the identity of the `Template` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val TemplateTag: ClassTag[Template] + + /** The constructor/deconstructor for `Template` instances. */ + val Template: TemplateExtractor + + /** An extractor class to create and pattern match with syntax `Template(parents, self, body)`. + * This AST node corresponds to the following Scala code: + * + * `extends` parents { self => body } + * + * In case when the self-type annotation is missing, it is represented as + * an empty value definition with nme.WILDCARD as name and NoType as type. + * + * The symbol of a template is a local dummy. @see Symbol.newLocalDummy + * The owner of the local dummy is the enclosing trait or class. + * The local dummy is itself the owner of any local blocks. For example: + * + * class C { + * def foo { // owner is C + * def bar // owner is local dummy + * } + * } + */ + abstract class TemplateExtractor { + def apply(parents: List[Tree], self: ValDef, body: List[Tree]): Template + def unapply(template: Template): Option[(List[Tree], ValDef, List[Tree])] + } + + /** Block of expressions (semicolon separated expressions) */ + type Block >: Null <: TermTree + + /** A tag that preserves the identity of the `Block` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val BlockTag: ClassTag[Block] + + /** The constructor/deconstructor for `Block` instances. */ + val Block: BlockExtractor + + /** An extractor class to create and pattern match with syntax `Block(stats, expr)`. + * This AST node corresponds to the following Scala code: + * + * { stats; expr } + * + * If the block is empty, the `expr` is set to `Literal(Constant(()))`. // [Eugene++] check this + */ + abstract class BlockExtractor { + def apply(stats: List[Tree], expr: Tree): Block + def unapply(block: Block): Option[(List[Tree], Tree)] + } + + /** Case clause in a pattern match, eliminated during explicitouter + * (except for occurrences in switch statements). + * Eliminated by patmat/explicitouter. + */ + type CaseDef >: Null <: AnyRef with Tree + + /** A tag that preserves the identity of the `CaseDef` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val CaseDefTag: ClassTag[CaseDef] + + /** The constructor/deconstructor for `CaseDef` instances. */ + val CaseDef: CaseDefExtractor + + /** An extractor class to create and pattern match with syntax `CaseDef(pat, guard, body)`. + * This AST node corresponds to the following Scala code: + * + * `case` pat `if` guard => body + * + * If the guard is not present, the `guard` is set to `EmptyTree`. // [Eugene++] check this + * If the body is not specified, the `body` is set to `EmptyTree`. // [Eugene++] check this + */ + abstract class CaseDefExtractor { + def apply(pat: Tree, guard: Tree, body: Tree): CaseDef + def unapply(caseDef: CaseDef): Option[(Tree, Tree, Tree)] + } + + /** Alternatives of patterns, eliminated by explicitouter, except for + * occurrences in encoded Switch stmt (=remaining Match(CaseDef(...))) + * Eliminated by patmat/explicitouter. + */ + type Alternative >: Null <: TermTree + + /** A tag that preserves the identity of the `Alternative` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val AlternativeTag: ClassTag[Alternative] + + /** The constructor/deconstructor for `Alternative` instances. */ + val Alternative: AlternativeExtractor + + /** An extractor class to create and pattern match with syntax `Alternative(trees)`. + * This AST node corresponds to the following Scala code: + * + * pat1 | ... | patn + */ + abstract class AlternativeExtractor { + def apply(trees: List[Tree]): Alternative + def unapply(alternative: Alternative): Option[List[Tree]] + } + + /** Repetition of pattern. + * Eliminated by patmat/explicitouter. + */ + type Star >: Null <: TermTree + + /** A tag that preserves the identity of the `Star` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val StarTag: ClassTag[Star] + + /** The constructor/deconstructor for `Star` instances. */ + val Star: StarExtractor + + /** An extractor class to create and pattern match with syntax `Star(elem)`. + * This AST node corresponds to the following Scala code: + * + * pat* + */ + abstract class StarExtractor { + def apply(elem: Tree): Star + def unapply(star: Star): Option[Tree] + } + + /** Bind of a variable to a rhs pattern, eliminated by explicitouter + * Eliminated by patmat/explicitouter. + * + * @param name + * @param body + */ + type Bind >: Null <: DefTree + + /** A tag that preserves the identity of the `Bind` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val BindTag: ClassTag[Bind] + + /** The constructor/deconstructor for `Bind` instances. */ + val Bind: BindExtractor + + /** An extractor class to create and pattern match with syntax `Bind(name, body)`. + * This AST node corresponds to the following Scala code: + * + * pat* + */ + abstract class BindExtractor { + def apply(name: Name, body: Tree): Bind + def unapply(bind: Bind): Option[(Name, Tree)] + } + + /** Noone knows what this is. + * It is not idempotent w.r.t typechecking. + * Can we, please, remove it? + * Introduced by typer, eliminated by patmat/explicitouter. + */ + type UnApply >: Null <: TermTree + + /** A tag that preserves the identity of the `UnApply` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val UnApplyTag: ClassTag[UnApply] + + /** The constructor/deconstructor for `UnApply` instances. */ + val UnApply: UnApplyExtractor + + /** An extractor class to create and pattern match with syntax `UnApply(fun, args)`. + * This AST node does not have direct correspondence to Scala code, + * and is introduced when typechecking pattern matches and `try` blocks. + */ + abstract class UnApplyExtractor { + def apply(fun: Tree, args: List[Tree]): UnApply + def unapply(unApply: UnApply): Option[(Tree, List[Tree])] + } + + /** Array of expressions, needs to be translated in backend. + * This AST node is used to pass arguments to vararg arguments. + * Introduced by uncurry. + */ + type ArrayValue >: Null <: TermTree + + /** A tag that preserves the identity of the `ArrayValue` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val ArrayValueTag: ClassTag[ArrayValue] + + /** The constructor/deconstructor for `ArrayValue` instances. */ + val ArrayValue: ArrayValueExtractor + + /** An extractor class to create and pattern match with syntax `ArrayValue(elemtpt, elems)`. + * This AST node does not have direct correspondence to Scala code, + * and is used to pass arguments to vararg arguments. For instance: + * + * printf("%s%d", foo, 42) + * + * Is translated to after uncurry to: + * + * Apply( + * Ident("printf"), + * Literal("%s%d"), + * ArrayValue(<Any>, List(Ident("foo"), Literal(42)))) + */ + abstract class ArrayValueExtractor { + def apply(elemtpt: Tree, elems: List[Tree]): ArrayValue + def unapply(arrayValue: ArrayValue): Option[(Tree, List[Tree])] + } + + /** Anonymous function, eliminated by lambdalift */ + type Function >: Null <: TermTree with SymTree + + /** A tag that preserves the identity of the `Function` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val FunctionTag: ClassTag[Function] + + /** The constructor/deconstructor for `Function` instances. */ + val Function: FunctionExtractor + + /** An extractor class to create and pattern match with syntax `Function(vparams, body)`. + * This AST node corresponds to the following Scala code: + * + * vparams => body + * + * The symbol of a Function is a synthetic value of name nme.ANON_FUN_NAME + * It is the owner of the function's parameters. + */ + abstract class FunctionExtractor { + def apply(vparams: List[ValDef], body: Tree): Function + def unapply(function: Function): Option[(List[ValDef], Tree)] + } + + /** Assignment */ + type Assign >: Null <: TermTree + + /** A tag that preserves the identity of the `Assign` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val AssignTag: ClassTag[Assign] + + /** The constructor/deconstructor for `Assign` instances. */ + val Assign: AssignExtractor + + /** An extractor class to create and pattern match with syntax `Assign(lhs, rhs)`. + * This AST node corresponds to the following Scala code: + * + * lhs = rhs + */ + abstract class AssignExtractor { + def apply(lhs: Tree, rhs: Tree): Assign + def unapply(assign: Assign): Option[(Tree, Tree)] + } + + /** Either an assignment or a named argument. Only appears in argument lists, + * eliminated by typecheck (doTypedApply), resurrected by reifier. + */ + type AssignOrNamedArg >: Null <: TermTree + + /** A tag that preserves the identity of the `AssignOrNamedArg` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val AssignOrNamedArgTag: ClassTag[AssignOrNamedArg] + + /** The constructor/deconstructor for `AssignOrNamedArg` instances. */ + val AssignOrNamedArg: AssignOrNamedArgExtractor + + /** An extractor class to create and pattern match with syntax `AssignOrNamedArg(lhs, rhs)`. + * This AST node corresponds to the following Scala code: + * + * @annotation(lhs = rhs) + * + * m.f(lhs = rhs) + */ + abstract class AssignOrNamedArgExtractor { + def apply(lhs: Tree, rhs: Tree): AssignOrNamedArg + def unapply(assignOrNamedArg: AssignOrNamedArg): Option[(Tree, Tree)] + } + + /** Conditional expression */ + type If >: Null <: TermTree + + /** A tag that preserves the identity of the `If` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val IfTag: ClassTag[If] + + /** The constructor/deconstructor for `If` instances. */ + val If: IfExtractor + + /** An extractor class to create and pattern match with syntax `If(cond, thenp, elsep)`. + * This AST node corresponds to the following Scala code: + * + * `if` (cond) thenp `else` elsep + * + * If the alternative is not present, the `elsep` is set to `EmptyTree`. // [Eugene++] check this + */ + abstract class IfExtractor { + def apply(cond: Tree, thenp: Tree, elsep: Tree): If + def unapply(if_ : If): Option[(Tree, Tree, Tree)] + } + + /** - Pattern matching expression (before explicitouter) + * - Switch statements (after explicitouter) + * + * After explicitouter, cases will satisfy the following constraints: + * + * - all guards are `EmptyTree`, + * - all patterns will be either `Literal(Constant(x:Int))` + * or `Alternative(lit|...|lit)` + * - except for an "otherwise" branch, which has pattern + * `Ident(nme.WILDCARD)` + */ + type Match >: Null <: TermTree + + /** A tag that preserves the identity of the `Match` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val MatchTag: ClassTag[Match] + + /** The constructor/deconstructor for `Match` instances. */ + val Match: MatchExtractor + + /** An extractor class to create and pattern match with syntax `Match(selector, cases)`. + * This AST node corresponds to the following Scala code: + * + * selector `match` { cases } + * + * // [Eugene++] say something about `val (foo, bar) = baz` and likes. + */ + abstract class MatchExtractor { + def apply(selector: Tree, cases: List[CaseDef]): Match + def unapply(match_ : Match): Option[(Tree, List[CaseDef])] + } + + /** Return expression */ + type Return >: Null <: TermTree with SymTree + + /** A tag that preserves the identity of the `Return` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val ReturnTag: ClassTag[Return] + + /** The constructor/deconstructor for `Return` instances. */ + val Return: ReturnExtractor + + /** An extractor class to create and pattern match with syntax `Return(expr)`. + * This AST node corresponds to the following Scala code: + * + * `return` expr + * + * The symbol of a Return node is the enclosing method + */ + abstract class ReturnExtractor { + def apply(expr: Tree): Return + def unapply(return_ : Return): Option[Tree] + } + + /** [Eugene++] comment me! */ + type Try >: Null <: TermTree + + /** A tag that preserves the identity of the `Try` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val TryTag: ClassTag[Try] + + /** The constructor/deconstructor for `Try` instances. */ + val Try: TryExtractor + + /** An extractor class to create and pattern match with syntax `Try(block, catches, finalizer)`. + * This AST node corresponds to the following Scala code: + * + * `try` block `catch` { catches } `finally` finalizer + * + * If the finalizer is not present, the `finalizer` is set to `EmptyTree`. // [Eugene++] check this + */ + abstract class TryExtractor { + def apply(block: Tree, catches: List[CaseDef], finalizer: Tree): Try + def unapply(try_ : Try): Option[(Tree, List[CaseDef], Tree)] + } + + /** Throw expression */ + type Throw >: Null <: TermTree + + /** A tag that preserves the identity of the `Throw` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val ThrowTag: ClassTag[Throw] + + /** The constructor/deconstructor for `Throw` instances. */ + val Throw: ThrowExtractor + + /** An extractor class to create and pattern match with syntax `Throw(expr)`. + * This AST node corresponds to the following Scala code: + * + * `throw` expr + */ + abstract class ThrowExtractor { + def apply(expr: Tree): Throw + def unapply(throw_ : Throw): Option[Tree] + } + + /** Object instantiation + * One should always use factory method below to build a user level new. + * + * @param tpt a class type + */ + type New >: Null <: TermTree + + /** A tag that preserves the identity of the `New` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val NewTag: ClassTag[New] + + /** The constructor/deconstructor for `New` instances. */ + val New: NewExtractor + + /** An extractor class to create and pattern match with syntax `New(tpt)`. + * This AST node corresponds to the following Scala code: + * + * `new` T + * + * This node always occurs in the following context: + * + * (`new` tpt).<init>[targs](args) + */ + abstract class NewExtractor { + def apply(tpt: Tree): New + def unapply(new_ : New): Option[Tree] + } + + /** Type annotation, eliminated by cleanup */ + type Typed >: Null <: TermTree + + /** A tag that preserves the identity of the `Typed` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val TypedTag: ClassTag[Typed] + + /** The constructor/deconstructor for `Typed` instances. */ + val Typed: TypedExtractor + + /** An extractor class to create and pattern match with syntax `Typed(expr, tpt)`. + * This AST node corresponds to the following Scala code: + * + * expr: tpt + */ + abstract class TypedExtractor { + def apply(expr: Tree, tpt: Tree): Typed + def unapply(typed: Typed): Option[(Tree, Tree)] + } + + /** Common base class for Apply and TypeApply. This could in principle + * be a SymTree, but whether or not a Tree is a SymTree isn't used + * to settle any interesting questions, and it would add a useless + * field to all the instances (useless, since GenericApply forwards to + * the underlying fun.) + */ + type GenericApply >: Null <: TermTree + + /** A tag that preserves the identity of the `GenericApply` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val GenericApplyTag: ClassTag[GenericApply] + + /** Explicit type application. + * @PP: All signs point toward it being a requirement that args.nonEmpty, + * but I can't find that explicitly stated anywhere. Unless your last name + * is odersky, you should probably treat it as true. + */ + type TypeApply >: Null <: GenericApply + + /** A tag that preserves the identity of the `TypeApply` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val TypeApplyTag: ClassTag[TypeApply] + + /** The constructor/deconstructor for `TypeApply` instances. */ + val TypeApply: TypeApplyExtractor + + /** An extractor class to create and pattern match with syntax `TypeApply(fun, args)`. + * This AST node corresponds to the following Scala code: + * + * fun[args] + */ + abstract class TypeApplyExtractor { + def apply(fun: Tree, args: List[Tree]): TypeApply + def unapply(typeApply: TypeApply): Option[(Tree, List[Tree])] + } + + /** Value application */ + type Apply >: Null <: GenericApply + + /** A tag that preserves the identity of the `Apply` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val ApplyTag: ClassTag[Apply] + + /** The constructor/deconstructor for `Apply` instances. */ + val Apply: ApplyExtractor + + /** An extractor class to create and pattern match with syntax `Apply(fun, args)`. + * This AST node corresponds to the following Scala code: + * + * fun(args) + * + * For instance: + * + * fun[targs](args) + * + * Is expressed as: + * + * Apply(TypeApply(fun, targs), args) + */ + abstract class ApplyExtractor { + def apply(fun: Tree, args: List[Tree]): Apply + def unapply(apply: Apply): Option[(Tree, List[Tree])] + } + + /** Dynamic value application. + * In a dynamic application q.f(as) + * - q is stored in qual + * - as is stored in args + * - f is stored as the node's symbol field. + * [Eugene++] what is it used for? + * Introduced by erasure, eliminated by cleanup. + */ + type ApplyDynamic >: Null <: TermTree with SymTree + + /** A tag that preserves the identity of the `ApplyDynamic` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val ApplyDynamicTag: ClassTag[ApplyDynamic] + + /** The constructor/deconstructor for `ApplyDynamic` instances. */ + val ApplyDynamic: ApplyDynamicExtractor + + /** An extractor class to create and pattern match with syntax `ApplyDynamic(qual, args)`. + * This AST node corresponds to the following Scala code: + * + * fun(args) + * + * The symbol of an ApplyDynamic is the function symbol of `qual`, or NoSymbol, if there is none. + */ + abstract class ApplyDynamicExtractor { + def apply(qual: Tree, args: List[Tree]): ApplyDynamic + def unapply(applyDynamic: ApplyDynamic): Option[(Tree, List[Tree])] + } + + /** Super reference, qual = corresponding this reference + * A super reference C.super[M] is represented as Super(This(C), M). + */ + type Super >: Null <: TermTree + + /** A tag that preserves the identity of the `Super` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val SuperTag: ClassTag[Super] + + /** The constructor/deconstructor for `Super` instances. */ + val Super: SuperExtractor + + /** An extractor class to create and pattern match with syntax `Super(qual, mix)`. + * This AST node corresponds to the following Scala code: + * + * C.super[M] + * + * Which is represented as: + * + * Super(This(C), M) + * + * If `mix` is empty, it is tpnme.EMPTY. + * + * The symbol of a Super is the class _from_ which the super reference is made. + * For instance in C.super(...), it would be C. + */ + abstract class SuperExtractor { + def apply(qual: Tree, mix: TypeName): Super + def unapply(super_ : Super): Option[(Tree, TypeName)] + } + + /** Self reference */ + type This >: Null <: TermTree with SymTree + + /** A tag that preserves the identity of the `This` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val ThisTag: ClassTag[This] + + /** The constructor/deconstructor for `This` instances. */ + val This: ThisExtractor + + /** An extractor class to create and pattern match with syntax `This(qual)`. + * This AST node corresponds to the following Scala code: + * + * qual.this + * + * The symbol of a This is the class to which the this refers. + * For instance in C.this, it would be C. + * + * If `mix` is empty, then ??? + */ + abstract class ThisExtractor { + def apply(qual: TypeName): This + def unapply(this_ : This): Option[TypeName] + } + + /** Designator <qualifier> . <name> */ + type Select >: Null <: RefTree + + /** A tag that preserves the identity of the `Select` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val SelectTag: ClassTag[Select] + + /** The constructor/deconstructor for `Select` instances. */ + val Select: SelectExtractor + + /** An extractor class to create and pattern match with syntax `Select(qual, name)`. + * This AST node corresponds to the following Scala code: + * + * qualifier.selector + */ + abstract class SelectExtractor { + def apply(qualifier: Tree, name: Name): Select + def unapply(select: Select): Option[(Tree, Name)] + } + + /** Identifier <name> */ + type Ident >: Null <: RefTree + + /** A tag that preserves the identity of the `Ident` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val IdentTag: ClassTag[Ident] + + /** The constructor/deconstructor for `Ident` instances. */ + val Ident: IdentExtractor + + /** An extractor class to create and pattern match with syntax `Ident(qual, name)`. + * This AST node corresponds to the following Scala code: + * + * name + * + * Type checker converts idents that refer to enclosing fields or methods to selects. + * For example, name ==> this.name + */ + abstract class IdentExtractor { + def apply(name: Name): Ident + def unapply(ident: Ident): Option[Name] + } + + /** Marks underlying reference to id as boxed. + * @pre id must refer to a captured variable + * A reference such marked will refer to the boxed entity, no dereferencing + * with `.elem` is done on it. + * This tree node can be emitted by macros such as reify that call referenceCapturedVariable. + * It is eliminated in LambdaLift, where the boxing conversion takes place. + */ + type ReferenceToBoxed >: Null <: TermTree + + /** A tag that preserves the identity of the `ReferenceToBoxed` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val ReferenceToBoxedTag: ClassTag[ReferenceToBoxed] + + /** The constructor/deconstructor for `ReferenceToBoxed` instances. */ + val ReferenceToBoxed: ReferenceToBoxedExtractor + + /** An extractor class to create and pattern match with syntax `ReferenceToBoxed(ident)`. + * This AST node does not have direct correspondence to Scala code, + * and is emitted by macros to reference capture vars directly without going through `elem`. + * + * For example: + * + * var x = ... + * fun { x } + * + * Will emit: + * + * Ident(x) + * + * Which gets transformed to: + * + * Select(Ident(x), "elem") + * + * If `ReferenceToBoxed` were used instead of Ident, no transformation would be performed. + */ + abstract class ReferenceToBoxedExtractor { + def apply(ident: Ident): ReferenceToBoxed + def unapply(referenceToBoxed: ReferenceToBoxed): Option[Ident] + } + + /** Literal */ + type Literal >: Null <: TermTree + + /** A tag that preserves the identity of the `Literal` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val LiteralTag: ClassTag[Literal] + + /** The constructor/deconstructor for `Literal` instances. */ + val Literal: LiteralExtractor + + /** An extractor class to create and pattern match with syntax `Literal(value)`. + * This AST node corresponds to the following Scala code: + * + * value + */ + abstract class LiteralExtractor { + def apply(value: Constant): Literal + def unapply(literal: Literal): Option[Constant] + } + + /** A tree that has an annotation attached to it. Only used for annotated types and + * annotation ascriptions, annotations on definitions are stored in the Modifiers. + * Eliminated by typechecker (typedAnnotated), the annotations are then stored in + * an AnnotatedType. + */ + type Annotated >: Null <: AnyRef with Tree + + /** A tag that preserves the identity of the `Annotated` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val AnnotatedTag: ClassTag[Annotated] + + /** The constructor/deconstructor for `Annotated` instances. */ + val Annotated: AnnotatedExtractor + + /** An extractor class to create and pattern match with syntax `Annotated(annot, arg)`. + * This AST node corresponds to the following Scala code: + * + * arg @annot // for types + * arg: @annot // for exprs + */ + abstract class AnnotatedExtractor { + def apply(annot: Tree, arg: Tree): Annotated + def unapply(annotated: Annotated): Option[(Tree, Tree)] + } + + /** Singleton type, eliminated by RefCheck */ + type SingletonTypeTree >: Null <: TypTree + + /** A tag that preserves the identity of the `SingletonTypeTree` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val SingletonTypeTreeTag: ClassTag[SingletonTypeTree] + + /** The constructor/deconstructor for `SingletonTypeTree` instances. */ + val SingletonTypeTree: SingletonTypeTreeExtractor + + /** An extractor class to create and pattern match with syntax `SingletonTypeTree(ref)`. + * This AST node corresponds to the following Scala code: + * + * ref.type + */ + abstract class SingletonTypeTreeExtractor { + def apply(ref: Tree): SingletonTypeTree + def unapply(singletonTypeTree: SingletonTypeTree): Option[Tree] + } + + /** Type selection <qualifier> # <name>, eliminated by RefCheck */ + // [Eugene++] don't see why we need it, when we have Select + type SelectFromTypeTree >: Null <: TypTree with RefTree + + /** A tag that preserves the identity of the `SelectFromTypeTree` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val SelectFromTypeTreeTag: ClassTag[SelectFromTypeTree] + + /** The constructor/deconstructor for `SelectFromTypeTree` instances. */ + val SelectFromTypeTree: SelectFromTypeTreeExtractor + + /** An extractor class to create and pattern match with syntax `SelectFromTypeTree(qualifier, name)`. + * This AST node corresponds to the following Scala code: + * + * qualifier # selector + * + * Note: a path-dependent type p.T is expressed as p.type # T + */ + abstract class SelectFromTypeTreeExtractor { + def apply(qualifier: Tree, name: TypeName): SelectFromTypeTree + def unapply(selectFromTypeTree: SelectFromTypeTree): Option[(Tree, TypeName)] + } + + /** Intersection type <parent1> with ... with <parentN> { <decls> }, eliminated by RefCheck */ + type CompoundTypeTree >: Null <: TypTree + + /** A tag that preserves the identity of the `CompoundTypeTree` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val CompoundTypeTreeTag: ClassTag[CompoundTypeTree] + + /** The constructor/deconstructor for `CompoundTypeTree` instances. */ + val CompoundTypeTree: CompoundTypeTreeExtractor + + /** An extractor class to create and pattern match with syntax `CompoundTypeTree(templ)`. + * This AST node corresponds to the following Scala code: + * + * parent1 with ... with parentN { refinement } + */ + abstract class CompoundTypeTreeExtractor { + def apply(templ: Template): CompoundTypeTree + def unapply(compoundTypeTree: CompoundTypeTree): Option[Template] + } + + /** Applied type <tpt> [ <args> ], eliminated by RefCheck */ + type AppliedTypeTree >: Null <: TypTree + + /** A tag that preserves the identity of the `AppliedTypeTree` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val AppliedTypeTreeTag: ClassTag[AppliedTypeTree] + + /** The constructor/deconstructor for `AppliedTypeTree` instances. */ + val AppliedTypeTree: AppliedTypeTreeExtractor + + /** An extractor class to create and pattern match with syntax `AppliedTypeTree(tpt, args)`. + * This AST node corresponds to the following Scala code: + * + * tpt[args] + */ + abstract class AppliedTypeTreeExtractor { + def apply(tpt: Tree, args: List[Tree]): AppliedTypeTree + def unapply(appliedTypeTree: AppliedTypeTree): Option[(Tree, List[Tree])] + } + + /** Document me! */ + type TypeBoundsTree >: Null <: TypTree + + /** A tag that preserves the identity of the `TypeBoundsTree` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val TypeBoundsTreeTag: ClassTag[TypeBoundsTree] + + /** The constructor/deconstructor for `TypeBoundsTree` instances. */ + val TypeBoundsTree: TypeBoundsTreeExtractor + + /** An extractor class to create and pattern match with syntax `TypeBoundsTree(lo, hi)`. + * This AST node corresponds to the following Scala code: + * + * >: lo <: hi + */ + abstract class TypeBoundsTreeExtractor { + def apply(lo: Tree, hi: Tree): TypeBoundsTree + def unapply(typeBoundsTree: TypeBoundsTree): Option[(Tree, Tree)] + } + + /** Document me! */ + type ExistentialTypeTree >: Null <: TypTree + + /** A tag that preserves the identity of the `ExistentialTypeTree` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val ExistentialTypeTreeTag: ClassTag[ExistentialTypeTree] + + /** The constructor/deconstructor for `ExistentialTypeTree` instances. */ + val ExistentialTypeTree: ExistentialTypeTreeExtractor + + /** An extractor class to create and pattern match with syntax `ExistentialTypeTree(tpt, whereClauses)`. + * This AST node corresponds to the following Scala code: + * + * tpt forSome { whereClauses } + */ + abstract class ExistentialTypeTreeExtractor { + def apply(tpt: Tree, whereClauses: List[Tree]): ExistentialTypeTree + def unapply(existentialTypeTree: ExistentialTypeTree): Option[(Tree, List[Tree])] + } + + /** A synthetic tree holding an arbitrary type. Not to be confused with + * with TypTree, the trait for trees that are only used for type trees. + * TypeTree's are inserted in several places, but most notably in + * `RefCheck`, where the arbitrary type trees are all replaced by + * TypeTree's. */ + type TypeTree >: Null <: TypTree + + /** A tag that preserves the identity of the `TypeTree` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val TypeTreeTag: ClassTag[TypeTree] + + /** The constructor/deconstructor for `TypeTree` instances. */ + val TypeTree: TypeTreeExtractor + + /** An extractor class to create and pattern match with syntax `TypeTree()`. + * This AST node does not have direct correspondence to Scala code, + * and is emitted by everywhere when we want to wrap a `Type` in a `Tree`. + */ + abstract class TypeTreeExtractor { + def apply(): TypeTree + def unapply(typeTree: TypeTree): Boolean + } + + /** ... */ + type Modifiers >: Null <: ModifiersBase + + /** A tag that preserves the identity of the `Modifiers` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val ModifiersTag: ClassTag[Modifiers] + + /** ... */ + abstract class ModifiersBase { + def flags: FlagSet + def hasFlag(flags: FlagSet): Boolean + def hasAllFlags(flags: FlagSet): Boolean + def privateWithin: Name // default: EmptyTypeName + def annotations: List[Tree] // default: List() + def mapAnnotations(f: List[Tree] => List[Tree]): Modifiers = + Modifiers(flags, privateWithin, f(annotations)) + } + + val Modifiers: ModifiersCreator + + abstract class ModifiersCreator { + def apply(): Modifiers = Modifiers(NoFlags, EmptyTypeName, List()) + def apply(flags: FlagSet, privateWithin: Name, annotations: List[Tree]): Modifiers + } + + def Modifiers(flags: FlagSet, privateWithin: Name): Modifiers = Modifiers(flags, privateWithin, List()) + def Modifiers(flags: FlagSet): Modifiers = Modifiers(flags, EmptyTypeName) + + /** ... */ + lazy val NoMods = Modifiers() + + // [Eugene++] temporarily moved here until SI-5863 is fixed +// ---------------------- factories ---------------------------------------------- + + /** @param sym the class symbol + * @param impl the implementation template + */ + def ClassDef(sym: Symbol, impl: Template): ClassDef + + /** + * @param sym the class symbol + * @param impl the implementation template + */ + def ModuleDef(sym: Symbol, impl: Template): ModuleDef + + def ValDef(sym: Symbol, rhs: Tree): ValDef + + def ValDef(sym: Symbol): ValDef + + def DefDef(sym: Symbol, mods: Modifiers, vparamss: List[List[ValDef]], rhs: Tree): DefDef + + def DefDef(sym: Symbol, vparamss: List[List[ValDef]], rhs: Tree): DefDef + + def DefDef(sym: Symbol, mods: Modifiers, rhs: Tree): DefDef + + def DefDef(sym: Symbol, rhs: Tree): DefDef + + def DefDef(sym: Symbol, rhs: List[List[Symbol]] => Tree): DefDef + + /** A TypeDef node which defines given `sym` with given tight hand side `rhs`. */ + def TypeDef(sym: Symbol, rhs: Tree): TypeDef + + /** A TypeDef node which defines abstract type or type parameter for given `sym` */ + def TypeDef(sym: Symbol): TypeDef + + def LabelDef(sym: Symbol, params: List[Symbol], rhs: Tree): LabelDef + + /** Block factory that flattens directly nested blocks. + */ + def Block(stats: Tree*): Block + + /** casedef shorthand */ + def CaseDef(pat: Tree, body: Tree): CaseDef + + def Bind(sym: Symbol, body: Tree): Bind + + def Try(body: Tree, cases: (Tree, Tree)*): Try + + def Throw(tpe: Type, args: Tree*): Throw + + /** Factory method for object creation `new tpt(args_1)...(args_n)` + * A `New(t, as)` is expanded to: `(new t).<init>(as)` + */ + def New(tpt: Tree, argss: List[List[Tree]]): Tree + + /** 0-1 argument list new, based on a type. + */ + def New(tpe: Type, args: Tree*): Tree + + def New(sym: Symbol, args: Tree*): Tree + + def Apply(sym: Symbol, args: Tree*): Tree + + def ApplyConstructor(tpt: Tree, args: List[Tree]): Tree + + def Super(sym: Symbol, mix: TypeName): Tree + + def This(sym: Symbol): Tree + + def Select(qualifier: Tree, name: String): Select + + def Select(qualifier: Tree, sym: Symbol): Select + + def Ident(name: String): Ident + + def Ident(sym: Symbol): Ident + + def TypeTree(tp: Type): TypeTree +}
\ No newline at end of file diff --git a/src/library/scala/reflect/base/TypeCreator.scala b/src/library/scala/reflect/base/TypeCreator.scala new file mode 100644 index 0000000000..8a14e53dd3 --- /dev/null +++ b/src/library/scala/reflect/base/TypeCreator.scala @@ -0,0 +1,6 @@ +package scala.reflect +package base + +abstract class TypeCreator { + def apply[U <: Universe with Singleton](m: MirrorOf[U]): U # Type +} diff --git a/src/library/scala/reflect/base/TypeTags.scala b/src/library/scala/reflect/base/TypeTags.scala new file mode 100644 index 0000000000..774bc6ebea --- /dev/null +++ b/src/library/scala/reflect/base/TypeTags.scala @@ -0,0 +1,246 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2011 LAMP/EPFL + * @author Martin Odersky + */ + +package scala.reflect +package base + +import java.lang.{ Class => jClass } +import language.implicitConversions + +/** + * Type tags encapsulate a representation of type T. + * They are supposed to replace the pre-2.10 concept of a [[scala.reflect.Manifest]]. + * TypeTags are much better integrated with reflection than manifests are, and are consequently much simpler. + * + * === Overview === + * + * Type tags are organized in a hierarchy of three classes: + * [[scala.reflect.ClassTag]], [[scala.reflect.base.Universe#TypeTag]] and [[scala.reflect.base.Universe#AbsTypeTag]]. + * + * A [[scala.reflect.ClassTag]] carries a runtime class that corresponds to the source type T. + * As of such, it possesses the knowledge about how to build single- and multi-dimensional arrays of elements of that type. + * It guarantees that the source type T did not to contain any references to type parameters or abstract types. + * [[scala.reflect.ClassTag]] corresponds to a previous notion of [[scala.reflect.ClassManifest]]. + * + * A [[scala.reflect.base.Universe#AbsTypeTag]] value wraps a full Scala type in its tpe field. + * A [[scala.reflect.base.Universe#TypeTag]] value is an [[scala.reflect.base.Universe#AbsTypeTag]] + * that is guaranteed not to contain any references to type parameters or abstract types. + * + * [Eugene++] also mention sensitivity to prefixes, i.e. that rb.TypeTag is different from ru.TypeTag + * [Eugene++] migratability between mirrors and universes is also worth mentioning + * + * === Splicing === + * + * Tags can be spliced, i.e. if compiler generates a tag for a type that contains references to tagged + * type parameters or abstract type members, it will retrieve the corresponding tag and embed it into the result. + * An example that illustrates the TypeTag embedding, consider the following function: + * + * import reflect.mirror._ + * def f[T: TypeTag, U] = { + * type L = T => U + * implicitly[AbsTypeTag[L]] + * } + * + * Then a call of f[String, Int] will yield a result of the form + * + * AbsTypeTag(<[ String => U ]>). + * + * Note that T has been replaced by String, because it comes with a TypeTag in f, whereas U was left as a type parameter. + * + * === AbsTypeTag vs TypeTag === + * + * Be careful with AbsTypeTag, because it will reify types even if these types are abstract. + * This makes it easy to forget to tag one of the methods in the call chain and discover it much later in the runtime + * by getting cryptic errors far away from their source. For example, consider the following snippet: + * + * def bind[T: AbsTypeTag](name: String, value: T): IR.Result = bind((name, value)) + * def bind(p: NamedParam): IR.Result = bind(p.name, p.tpe, p.value) + * object NamedParam { + * implicit def namedValue[T: AbsTypeTag](name: String, x: T): NamedParam = apply(name, x) + * def apply[T: AbsTypeTag](name: String, x: T): NamedParam = new Typed[T](name, x) + * } + * + * This fragment of Scala REPL implementation defines a `bind` function that carries a named value along with its type + * into the heart of the REPL. Using a [[scala.reflect.base.Universe#AbsTypeTag]] here is reasonable, because it is desirable + * to work with all types, even if they are type parameters or abstract type members. + * + * However if any of the three `AbsTypeTag` context bounds is omitted, the resulting code will be incorrect, + * because the missing `AbsTypeTag` will be transparently generated by the compiler, carrying meaningless information. + * Most likely, this problem will manifest itself elsewhere, making debugging complicated. + * If `AbsTypeTag` context bounds were replaced with `TypeTag`, then such errors would be reported statically. + * But in that case we wouldn't be able to use `bind` in arbitrary contexts. + * + * === Backward compatibility === + * + * Type tags correspond loosely to manifests. + * + * More precisely: + * The previous notion of a [[scala.reflect.ClassManifest]] corresponds to a scala.reflect.ClassTag, + * The previous notion of a [[scala.reflect.Manifest]] corresponds to scala.reflect.runtime.universe.TypeTag, + * + * In Scala 2.10, manifests are deprecated, so it's adviseable to migrate them to tags, + * because manifests might be removed in the next major release. + * + * In most cases it will be enough to replace ClassManifests with ClassTags and Manifests with TypeTags, + * however there are a few caveats: + * + * 1) The notion of OptManifest is no longer supported. Tags can reify arbitrary types, so they are always available. + * // [Eugene++] it might be useful, though, to guard against abstractness of the incoming type. + * + * 2) There's no equivalent for AnyValManifest. Consider comparing your tag with one of the base tags + * (defined in the corresponding companion objects) to find out whether it represents a primitive value class. + * You can also use `<tag>.tpe.typeSymbol.isPrimitiveValueClass` for that purpose (requires scala-reflect.jar). + * + * 3) There's no replacement for factory methods defined in `ClassManifest` and `Manifest` companion objects. + * Consider assembling corresponding types using reflection API provided by Java (for classes) and Scala (for types). + * + * 4) Certain manifest functions (such as `<:<`, `>:>` and `typeArguments`) weren't included in the tag API. + * Consider using reflection API provided by Java (for classes) and Scala (for types) instead. + */ +// [Eugene++] implement serialization for typetags +trait TypeTags { self: Universe => + + /** + * If an implicit value of type u.AbsTypeTag[T] is required, the compiler will make one up on demand. + * The implicitly created value contains in its tpe field a value of type u.Type that is a reflective representation of T. + * In that value, any occurrences of type parameters or abstract types U + * which come themselves with a TypeTag are represented by the type referenced by that TypeTag. + * + * @see [[scala.reflect.base.TypeTags]] + */ + @annotation.implicitNotFound(msg = "No AbsTypeTag available for ${T}") + trait AbsTypeTag[T] extends Equals with Serializable { + val mirror: Mirror + def in[U <: Universe with Singleton](otherMirror: MirrorOf[U]): U # AbsTypeTag[T] + def tpe: Type + + /** case class accessories */ + override def canEqual(x: Any) = x.isInstanceOf[AbsTypeTag[_]] + override def equals(x: Any) = x.isInstanceOf[AbsTypeTag[_]] && this.mirror == x.asInstanceOf[AbsTypeTag[_]].mirror && this.tpe == x.asInstanceOf[AbsTypeTag[_]].tpe + override def hashCode = mirror.hashCode * 31 + tpe.hashCode + override def toString = "AbsTypeTag[" + tpe + "]" + } + + object AbsTypeTag { + val Byte : AbsTypeTag[scala.Byte] = TypeTag.Byte + val Short : AbsTypeTag[scala.Short] = TypeTag.Short + val Char : AbsTypeTag[scala.Char] = TypeTag.Char + val Int : AbsTypeTag[scala.Int] = TypeTag.Int + val Long : AbsTypeTag[scala.Long] = TypeTag.Long + val Float : AbsTypeTag[scala.Float] = TypeTag.Float + val Double : AbsTypeTag[scala.Double] = TypeTag.Double + val Boolean : AbsTypeTag[scala.Boolean] = TypeTag.Boolean + val Unit : AbsTypeTag[scala.Unit] = TypeTag.Unit + val Any : AbsTypeTag[scala.Any] = TypeTag.Any + val Object : AbsTypeTag[java.lang.Object] = TypeTag.Object + val Nothing : AbsTypeTag[scala.Nothing] = TypeTag.Nothing + val Null : AbsTypeTag[scala.Null] = TypeTag.Null + val String : AbsTypeTag[java.lang.String] = TypeTag.String + + def apply[T](mirror1: MirrorOf[self.type], tpec1: TypeCreator): AbsTypeTag[T] = + tpec1(mirror1) match { + case ByteTpe => AbsTypeTag.Byte.asInstanceOf[AbsTypeTag[T]] + case ShortTpe => AbsTypeTag.Short.asInstanceOf[AbsTypeTag[T]] + case CharTpe => AbsTypeTag.Char.asInstanceOf[AbsTypeTag[T]] + case IntTpe => AbsTypeTag.Int.asInstanceOf[AbsTypeTag[T]] + case LongTpe => AbsTypeTag.Long.asInstanceOf[AbsTypeTag[T]] + case FloatTpe => AbsTypeTag.Float.asInstanceOf[AbsTypeTag[T]] + case DoubleTpe => AbsTypeTag.Double.asInstanceOf[AbsTypeTag[T]] + case BooleanTpe => AbsTypeTag.Boolean.asInstanceOf[AbsTypeTag[T]] + case UnitTpe => AbsTypeTag.Unit.asInstanceOf[AbsTypeTag[T]] + case AnyTpe => AbsTypeTag.Any.asInstanceOf[AbsTypeTag[T]] + case ObjectTpe => AbsTypeTag.Object.asInstanceOf[AbsTypeTag[T]] + case NothingTpe => AbsTypeTag.Nothing.asInstanceOf[AbsTypeTag[T]] + case NullTpe => AbsTypeTag.Null.asInstanceOf[AbsTypeTag[T]] + case StringTpe => AbsTypeTag.String.asInstanceOf[AbsTypeTag[T]] + case _ => new AbsTypeTagImpl[T](mirror1.asInstanceOf[Mirror], tpec1) + } + + def unapply[T](ttag: AbsTypeTag[T]): Option[Type] = Some(ttag.tpe) + } + + private class AbsTypeTagImpl[T](val mirror: Mirror, val tpec: TypeCreator) extends AbsTypeTag[T] { + lazy val tpe: Type = tpec[self.type](mirror) + def in[U <: Universe with Singleton](otherMirror: MirrorOf[U]): U # AbsTypeTag[T] = { + val otherMirror1 = otherMirror.asInstanceOf[MirrorOf[otherMirror.universe.type]] + otherMirror.universe.AbsTypeTag[T](otherMirror1, tpec) + } + } + + /** + * If an implicit value of type u.TypeTag[T] is required, the compiler will make one up on demand following the same procedure as for TypeTags. + * However, if the resulting type still contains references to type parameters or abstract types, a static error results. + * + * @see [[scala.reflect.base.TypeTags]] + */ + @annotation.implicitNotFound(msg = "No TypeTag available for ${T}") + trait TypeTag[T] extends AbsTypeTag[T] with Equals with Serializable { + override def in[U <: Universe with Singleton](otherMirror: MirrorOf[U]): U # TypeTag[T] + + /** case class accessories */ + override def canEqual(x: Any) = x.isInstanceOf[TypeTag[_]] + override def equals(x: Any) = x.isInstanceOf[TypeTag[_]] && this.mirror == x.asInstanceOf[TypeTag[_]].mirror && this.tpe == x.asInstanceOf[TypeTag[_]].tpe + override def hashCode = mirror.hashCode * 31 + tpe.hashCode + override def toString = "TypeTag[" + tpe + "]" + } + + object TypeTag { + val Byte: TypeTag[scala.Byte] = new PredefTypeTag[scala.Byte] (ByteTpe, _.TypeTag.Byte) + val Short: TypeTag[scala.Short] = new PredefTypeTag[scala.Short] (ShortTpe, _.TypeTag.Short) + val Char: TypeTag[scala.Char] = new PredefTypeTag[scala.Char] (CharTpe, _.TypeTag.Char) + val Int: TypeTag[scala.Int] = new PredefTypeTag[scala.Int] (IntTpe, _.TypeTag.Int) + val Long: TypeTag[scala.Long] = new PredefTypeTag[scala.Long] (LongTpe, _.TypeTag.Long) + val Float: TypeTag[scala.Float] = new PredefTypeTag[scala.Float] (FloatTpe, _.TypeTag.Float) + val Double: TypeTag[scala.Double] = new PredefTypeTag[scala.Double] (DoubleTpe, _.TypeTag.Double) + val Boolean: TypeTag[scala.Boolean] = new PredefTypeTag[scala.Boolean] (BooleanTpe, _.TypeTag.Boolean) + val Unit: TypeTag[scala.Unit] = new PredefTypeTag[scala.Unit] (UnitTpe, _.TypeTag.Unit) + val Any: TypeTag[scala.Any] = new PredefTypeTag[scala.Any] (AnyTpe, _.TypeTag.Any) + val Object: TypeTag[java.lang.Object] = new PredefTypeTag[java.lang.Object] (ObjectTpe, _.TypeTag.Object) + val Nothing: TypeTag[scala.Nothing] = new PredefTypeTag[scala.Nothing] (NothingTpe, _.TypeTag.Nothing) + val Null: TypeTag[scala.Null] = new PredefTypeTag[scala.Null] (NullTpe, _.TypeTag.Null) + val String: TypeTag[java.lang.String] = new PredefTypeTag[java.lang.String] (StringTpe, _.TypeTag.String) + + def apply[T](mirror1: MirrorOf[self.type], tpec1: TypeCreator): TypeTag[T] = + tpec1(mirror1) match { + case ByteTpe => TypeTag.Byte.asInstanceOf[TypeTag[T]] + case ShortTpe => TypeTag.Short.asInstanceOf[TypeTag[T]] + case CharTpe => TypeTag.Char.asInstanceOf[TypeTag[T]] + case IntTpe => TypeTag.Int.asInstanceOf[TypeTag[T]] + case LongTpe => TypeTag.Long.asInstanceOf[TypeTag[T]] + case FloatTpe => TypeTag.Float.asInstanceOf[TypeTag[T]] + case DoubleTpe => TypeTag.Double.asInstanceOf[TypeTag[T]] + case BooleanTpe => TypeTag.Boolean.asInstanceOf[TypeTag[T]] + case UnitTpe => TypeTag.Unit.asInstanceOf[TypeTag[T]] + case AnyTpe => TypeTag.Any.asInstanceOf[TypeTag[T]] + case ObjectTpe => TypeTag.Object.asInstanceOf[TypeTag[T]] + case NothingTpe => TypeTag.Nothing.asInstanceOf[TypeTag[T]] + case NullTpe => TypeTag.Null.asInstanceOf[TypeTag[T]] + case StringTpe => TypeTag.String.asInstanceOf[TypeTag[T]] + case _ => new TypeTagImpl[T](mirror1.asInstanceOf[Mirror], tpec1) + } + + def unapply[T](ttag: TypeTag[T]): Option[Type] = Some(ttag.tpe) + } + + private class TypeTagImpl[T](mirror: Mirror, tpec: TypeCreator) extends AbsTypeTagImpl[T](mirror, tpec) with TypeTag[T] { + override def in[U <: Universe with Singleton](otherMirror: MirrorOf[U]): U # TypeTag[T] = { + val otherMirror1 = otherMirror.asInstanceOf[MirrorOf[otherMirror.universe.type]] + otherMirror.universe.TypeTag[T](otherMirror1, tpec) + } + } + + private class PredefTypeTag[T](_tpe: Type, copyIn: Universe => Universe # TypeTag[T]) extends TypeTagImpl[T](rootMirror, null) { + override lazy val tpe: Type = _tpe + override def in[U <: Universe with Singleton](otherMirror: MirrorOf[U]): U # TypeTag[T] = + copyIn(otherMirror.universe).asInstanceOf[U # TypeTag[T]] + private def readResolve() = copyIn(self) + } + + // incantations + def typeTag[T](implicit ttag: TypeTag[T]) = ttag + + // big thanks to Viktor Klang for this brilliant idea! + def typeOf[T](implicit ttag: TypeTag[T]): Type = ttag.tpe +} diff --git a/src/library/scala/reflect/api/Types.scala b/src/library/scala/reflect/base/Types.scala index 3d42242641..6106e3fde7 100755..100644 --- a/src/library/scala/reflect/api/Types.scala +++ b/src/library/scala/reflect/base/Types.scala @@ -1,203 +1,36 @@ package scala.reflect -package api +package base trait Types { self: Universe => - /** This class declares operations that are visible in a Type. - */ - abstract class AbsType { + /** The base API that all types support */ + abstract class TypeBase { + /** The type symbol associated with the type, or `NoSymbol` for types * that do not refer to a type symbol. */ def typeSymbol: Symbol - - /** The defined or declared members with name `name` in this type; - * an OverloadedSymbol if several exist, NoSymbol if none exist. - * Alternatives of overloaded symbol appear in the order they are declared. - */ - def declaration(name: Name): Symbol - - /** The collection of declarations in this type - */ - def declarations: Iterable[Symbol] - - /** The member with given name, either directly declared or inherited, - * an OverloadedSymbol if several exist, NoSymbol if none exist. - */ - def member(name: Name): Symbol - - /** The non-private member with given name, either directly declared or inherited, - * an OverloadedSymbol if several exist, NoSymbol if none exist. - */ - def nonPrivateMember(name: Name): Symbol - - /** An iterable containing all members of this type (directly declared or inherited) - * Members appear in the linearization order of their owners. - * Members with the same owner appear in reverse order of their declarations. - */ - def members: Iterable[Symbol] - - /** An iterable containing all non-private members of this type (directly declared or inherited) - * Members appear in the linearization order of their owners. - * Members with the same owner appear in reverse order of their declarations. - */ - def nonPrivateMembers: Iterable[Symbol] - - /** Substitute types in `to` for corresponding occurrences of references to - * symbols `from` in this type. - */ - def substituteTypes(from: List[Symbol], to: List[Type]): Type - - /** If this is a parameterized types, the type arguments. - * Otherwise the empty list - */ - def typeArguments: List[Type] - - /** For a (potentially wrapped) poly type, its type parameters, - * the empty list for all other types */ - def typeParams: List[Symbol] - - /** Is this type a type constructor that is missing its type arguments? - */ - def isHigherKinded: Boolean // !!! This should be called "isTypeConstructor", no? - - /** Returns the corresponding type constructor (e.g. List for List[T] or List[String]) - */ - def typeConstructor: Type - - /** Does this type refer to spliceable types or is a spliceable type? - */ - def isConcrete: Boolean - - /** Is this type an abstract type that needs to be resolved? - */ - def isSpliceable: Boolean - - /** - * Expands type aliases and converts higher-kinded TypeRefs to PolyTypes. - * Functions on types are also implemented as PolyTypes. - * - * Example: (in the below, <List> is the type constructor of List) - * TypeRef(pre, <List>, List()) is replaced by - * PolyType(X, TypeRef(pre, <List>, List(X))) - */ - def normalize: Type // !!! Alternative name? "normalize" is used to mean too many things. - - /** Does this type conform to given type argument `that`? */ - def <:< (that: Type): Boolean - - /** Is this type equivalent to given type argument `that`? */ - def =:= (that: Type): Boolean - - /** The list of all base classes of this type (including its own typeSymbol) - * in reverse linearization order, starting with the class itself and ending - * in class Any. - */ - def baseClasses: List[Symbol] // !!! Alternative name, perhaps linearization? - - /** The least type instance of given class which is a supertype - * of this type. Example: - * {{{ - * class D[T] - * class C extends p.D[Int] - * ThisType(C).baseType(D) = p.D[Int] - * }}} - */ - def baseType(clazz: Symbol): Type - - /** This type as seen from prefix `pre` and class `clazz`. This means: - * Replace all thistypes of `clazz` or one of its subclasses - * by `pre` and instantiate all parameters by arguments of `pre`. - * Proceed analogously for thistypes referring to outer classes. - * - * Example: - * {{{ - * class D[T] { def m: T } - * class C extends p.D[Int] - * T.asSeenFrom(ThisType(C), D) (where D is owner of m) - * = Int - * }}} - */ - def asSeenFrom(pre: Type, clazz: Symbol): Type - - /** The erased type corresponding to this type after - * all transformations from Scala to Java have been performed. - */ - def erasure: Type // !!! "erasedType", compare with "widen" (so "erase") or "underlying" (so "erased") - // why not name it "erasure"? - - /** Apply `f` to each part of this type, returning - * a new type. children get mapped before their parents */ - def map(f: Type => Type): Type - - /** Apply `f` to each part of this type, for side effects only */ - def foreach(f: Type => Unit) - - /** Returns optionally first type (in a preorder traversal) which satisfies predicate `p`, - * or None if none exists. - */ - def find(p: Type => Boolean): Option[Type] - - /** Is there part of this type which satisfies predicate `p`? */ - def exists(p: Type => Boolean): Boolean - - /** Does this type contain a reference to given symbol? */ - def contains(sym: Symbol): Boolean - - /** If this is a compound type, the list of its parent types; - * otherwise the empty list - */ - def parents: List[Type] - - /** If this is a singleton type, returns the type underlying it; - * otherwise returns this type itself. - */ - def underlying: Type - - /** If this is a singleton type, widen it to its nearest underlying non-singleton - * base type by applying one or more `underlying` dereferences. - * If this is not a singleton type, returns this type itself. - * - * Example: - * - * class Outer { class C ; val x: C } - * val o: Outer - * <o.x.type>.widen = o.C - */ - def widen: Type - - /** The kind of this type; used for debugging */ - def kind: String } - /** An object representing an unknown type, used during type inference. - * If you see WildcardType outside of inference it is almost certainly a bug. + /** The type of Scala types, and also Scala type signatures. + * (No difference is internally made between the two). */ - val WildcardType: Type + type Type >: Null <: TypeBase - /** BoundedWildcardTypes, used only during type inference, are created in - * two places that I can find: - * - * 1. If the expected type of an expression is an existential type, - * its hidden symbols are replaced with bounded wildcards. - * 2. When an implicit conversion is being sought based in part on - * the name of a method in the converted type, a HasMethodMatching - * type is created: a MethodType with parameters typed as - * BoundedWildcardTypes. + /** A tag that preserves the identity of the `Type` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. */ - type BoundedWildcardType >: Null <: Type + implicit val TypeTagg: ClassTag[Type] // [Eugene++] rename! - val BoundedWildcardType: BoundedWildcardTypeExtractor - - abstract class BoundedWildcardTypeExtractor { - def apply(bounds: TypeBounds): BoundedWildcardType - def unapply(tpe: BoundedWildcardType): Option[TypeBounds] - } + /** This constant is used as a special value that indicates that no meaningful type exists. + */ + val NoType: Type - /** The type of Scala types, and also Scala type signatures. - * (No difference is internally made between the two). + /** This constant is used as a special value denoting the empty prefix in a path dependent type. + * For instance `x.type` is represented as `SingleType(NoPrefix, <x>)`, where `<x>` stands for + * the symbol for `x`. */ - type Type >: Null <: AbsType + val NoPrefix: Type /** The type of Scala singleton types, i.e. types that are inhabited * by only one nun-null value. These include types of the forms @@ -210,15 +43,10 @@ trait Types { self: Universe => */ type SingletonType >: Null <: Type - /** This constant is used as a special value that indicates that no meaningful type exists. - */ - val NoType: Type - - /** This constant is used as a special value denoting the empty prefix in a path dependent type. - * For instance `x.type` is represented as `SingleType(NoPrefix, <x>)`, where `<x>` stands for - * the symbol for `x`. + /** A tag that preserves the identity of the `SingletonType` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. */ - val NoPrefix: Type + implicit val SingletonTypeTag: ClassTag[SingletonType] /** The `ThisType` type describes types of the form on the left with the * correspnding ThisType representations to the right. @@ -226,7 +54,12 @@ trait Types { self: Universe => * C.this.type ThisType(C) * }}} */ - type ThisType <: SingletonType + type ThisType >: Null <: AnyRef with SingletonType + + /** A tag that preserves the identity of the `ThisType` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val ThisTypeTag: ClassTag[ThisType] /** The constructor/deconstructor for `ThisType` instances. */ val ThisType: ThisTypeExtractor @@ -235,36 +68,10 @@ trait Types { self: Universe => * where `sym` is the class prefix of the this type. */ abstract class ThisTypeExtractor { - def apply(sym: Symbol): Type + def apply(sym: Symbol): Type // not ThisTypebecause of implementation details def unapply(tpe: ThisType): Option[Symbol] } - /** The `TypeRef` type describes types of any of the forms on the left, - * with their TypeRef representations to the right. - * {{{ - * T # C[T_1, ..., T_n] TypeRef(T, C, List(T_1, ..., T_n)) - * p.C[T_1, ..., T_n] TypeRef(p.type, C, List(T_1, ..., T_n)) - * C[T_1, ..., T_n] TypeRef(NoPrefix, C, List(T_1, ..., T_n)) - * T # C TypeRef(T, C, Nil) - * p.C TypeRef(p.type, C, Nil) - * C TypeRef(NoPrefix, C, Nil) - * }}} - */ - type TypeRef <: Type - - /** The constructor/deconstructor for `TypeRef` instances. */ - val TypeRef: TypeRefExtractor - - /** An extractor class to create and pattern match with syntax `TypeRef(pre, sym, args)` - * Here, `pre` is the prefix of the type reference, `sym` is the symbol - * referred to by the type reference, and `args` is a possible empty list of - * type argumenrts. - */ - abstract class TypeRefExtractor { - def apply(pre: Type, sym: Symbol, args: List[Type]): Type - def unapply(tpe: TypeRef): Option[(Type, Symbol, List[Type])] - } - /** The `SingleType` type describes types of any of the forms on the left, * with their TypeRef representations to the right. * {{{ @@ -273,7 +80,12 @@ trait Types { self: Universe => * x.type SingleType(NoPrefix, x) * }}} */ - type SingleType <: SingletonType + type SingleType >: Null <: AnyRef with SingletonType + + /** A tag that preserves the identity of the `SingleType` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val SingleTypeTag: ClassTag[SingleType] /** The constructor/deconstructor for `SingleType` instances. */ val SingleType: SingleTypeExtractor @@ -283,7 +95,7 @@ trait Types { self: Universe => * referred to by the single-type. */ abstract class SingleTypeExtractor { - def apply(pre: Type, sym: Symbol): Type + def apply(pre: Type, sym: Symbol): Type // not SingleTypebecause of implementation details def unapply(tpe: SingleType): Option[(Type, Symbol)] } @@ -296,7 +108,12 @@ trait Types { self: Universe => * in the type arising from C.super, the `thistpe` part would be `ThisType(C)`. * `supertpe` is the type of the super class referred to by the `super`. */ - type SuperType <: SingletonType + type SuperType >: Null <: AnyRef with SingletonType + + /** A tag that preserves the identity of the `SuperType` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val SuperTypeTag: ClassTag[SuperType] /** The constructor/deconstructor for `SuperType` instances. */ val SuperType: SuperTypeExtractor @@ -304,7 +121,7 @@ trait Types { self: Universe => /** An extractor class to create and pattern match with syntax `SingleType(thistpe, supertpe)` */ abstract class SuperTypeExtractor { - def apply(thistpe: Type, supertpe: Type): Type + def apply(thistpe: Type, supertpe: Type): Type // not SuperTypebecause of implementation details def unapply(tpe: SuperType): Option[(Type, Type)] } @@ -315,7 +132,12 @@ trait Types { self: Universe => * "abc" ConstantType(Constant("abc")) * }}} */ - type ConstantType <: SingletonType + type ConstantType >: Null <: AnyRef with SingletonType + + /** A tag that preserves the identity of the `ConstantType` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val ConstantTypeTag: ClassTag[ConstantType] /** The constructor/deconstructor for `ConstantType` instances. */ val ConstantType: ConstantTypeExtractor @@ -328,9 +150,45 @@ trait Types { self: Universe => def unapply(tpe: ConstantType): Option[Constant] } + /** The `TypeRef` type describes types of any of the forms on the left, + * with their TypeRef representations to the right. + * {{{ + * T # C[T_1, ..., T_n] TypeRef(T, C, List(T_1, ..., T_n)) + * p.C[T_1, ..., T_n] TypeRef(p.type, C, List(T_1, ..., T_n)) + * C[T_1, ..., T_n] TypeRef(NoPrefix, C, List(T_1, ..., T_n)) + * T # C TypeRef(T, C, Nil) + * p.C TypeRef(p.type, C, Nil) + * C TypeRef(NoPrefix, C, Nil) + * }}} + */ + type TypeRef >: Null <: AnyRef with Type + + /** A tag that preserves the identity of the `TypeRef` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val TypeRefTag: ClassTag[TypeRef] + + /** The constructor/deconstructor for `TypeRef` instances. */ + val TypeRef: TypeRefExtractor + + /** An extractor class to create and pattern match with syntax `TypeRef(pre, sym, args)` + * Here, `pre` is the prefix of the type reference, `sym` is the symbol + * referred to by the type reference, and `args` is a possible empty list of + * type argumenrts. + */ + abstract class TypeRefExtractor { + def apply(pre: Type, sym: Symbol, args: List[Type]): Type // not TypeRefbecause of implementation details + def unapply(tpe: TypeRef): Option[(Type, Symbol, List[Type])] + } + /** A subtype of Type representing refined types as well as `ClassInfo` signatures. */ - type CompoundType <: Type + type CompoundType >: Null <: AnyRef with Type + + /** A tag that preserves the identity of the `CompoundType` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val CompoundTypeTag: ClassTag[CompoundType] /** The `RefinedType` type defines types of any of the forms on the left, * with their RefinedType representations to the right. @@ -340,7 +198,12 @@ trait Types { self: Universe => * { D_1; ...; D_n} RefinedType(List(AnyRef), Scope(D_1, ..., D_n)) * }}} */ - type RefinedType <: CompoundType + type RefinedType >: Null <: AnyRef with CompoundType + + /** A tag that preserves the identity of the `RefinedType` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val RefinedTypeTag: ClassTag[RefinedType] /** The constructor/deconstructor for `RefinedType` instances. */ val RefinedType: RefinedTypeExtractor @@ -359,21 +222,44 @@ trait Types { self: Universe => def unapply(tpe: RefinedType): Option[(List[Type], Scope)] } - type NullaryMethodType <: Type - val NullaryMethodType: NullaryMethodTypeExtractor + /** The `ClassInfo` type signature is used to define parents and declarations + * of classes, traits, and objects. If a class, trait, or object C is declared like this + * {{{ + * C extends P_1 with ... with P_m { D_1; ...; D_n} + * }}} + * its `ClassInfo` type has the following form: + * {{{ + * ClassInfo(List(P_1, ..., P_m), Scope(D_1, ..., D_n), C) + * }}} + */ + type ClassInfoType >: Null <: AnyRef with CompoundType - type PolyType <: Type - val PolyType: PolyTypeExtractor + /** A tag that preserves the identity of the `ClassInfoType` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val ClassInfoTypeTag: ClassTag[ClassInfoType] - type ExistentialType <: Type - val ExistentialType: ExistentialTypeExtractor + /** The constructor/deconstructor for `ClassInfoType` instances. */ + val ClassInfoType: ClassInfoTypeExtractor - type AnnotatedType <: Type - val AnnotatedType: AnnotatedTypeExtractor + /** An extractor class to create and pattern match with syntax `ClassInfo(parents, decls, clazz)` + * Here, `parents` is the list of parent types of the class, `decls` is the scope + * containing all declarations in the class, and `clazz` is the symbol of the class + * itself. + */ + abstract class ClassInfoTypeExtractor { + def apply(parents: List[Type], decls: Scope, typeSymbol: Symbol): ClassInfoType + def unapply(tpe: ClassInfoType): Option[(List[Type], Scope, Symbol)] + } /** The `MethodType` type signature is used to indicate parameters and result type of a method */ - type MethodType <: Type + type MethodType >: Null <: AnyRef with Type + + /** A tag that preserves the identity of the `MethodType` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val MethodTypeTag: ClassTag[MethodType] /** The constructor/deconstructor for `MethodType` instances. */ val MethodType: MethodTypeExtractor @@ -397,138 +283,150 @@ trait Types { self: Universe => def unapply(tpe: MethodType): Option[(List[Symbol], Type)] } - /** The `TypeBounds` type signature is used to indicate lower and upper type bounds - * of type parameters and abstract types. It is not a first-class type. - * If an abstract type or type parameter is declared with any of the forms - * on the left, its type signature is the TypeBounds type on the right. - * {{{ - * T >: L <: U TypeBounds(L, U) - * T >: L TypeBounds(L, Any) - * T <: U TypeBounds(Nothing, U) - * }}} + /** The `NullaryMethodType` type signature is used for parameterless methods + * with declarations of the form `def foo: T` */ - type TypeBounds <: Type + type NullaryMethodType >: Null <: AnyRef with Type - /** The constructor/deconstructor for `TypeBounds` instances. */ - val TypeBounds: TypeBoundsExtractor - - /** An extractor class to create and pattern match with syntax `TypeBound(lower, upper)` - * Here, `lower` is the lower bound of the `TypeBounds` pair, and `upper` is - * the upper bound. + /** A tag that preserves the identity of the `NullaryMethodType` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. */ - abstract class TypeBoundsExtractor { - def apply(lo: Type, hi: Type): TypeBounds - def unapply(tpe: TypeBounds): Option[(Type, Type)] - } + implicit val NullaryMethodTypeTag: ClassTag[NullaryMethodType] - /** The `ClassInfo` type signature is used to define parents and declarations - * of classes, traits, and objects. If a class, trait, or object C is declared like this - * {{{ - * C extends P_1 with ... with P_m { D_1; ...; D_n} - * }}} - * its `ClassInfo` type has the following form: - * {{{ - * ClassInfo(List(P_1, ..., P_m), Scope(D_1, ..., D_n), C) - * }}} - */ - type ClassInfoType <: CompoundType - - /** The constructor/deconstructor for `ClassInfoType` instances. */ - val ClassInfoType: ClassInfoTypeExtractor + /** The constructor/deconstructor for `NullaryMethodType` instances. */ + val NullaryMethodType: NullaryMethodTypeExtractor - /** An extractor class to create and pattern match with syntax `ClassInfo(parents, decls, clazz)` - * Here, `parents` is the list of parent types of the class, `decls` is the scope - * containing all declarations in the class, and `clazz` is the symbol of the class - * itself. + /** An extractor class to create and pattern match with syntax `NullaryMethodType(resultType)`. + * Here, `resultType` is the result type of the parameterless method. */ - abstract class ClassInfoTypeExtractor { - def apply(parents: List[Type], decls: Scope, clazz: Symbol): ClassInfoType - def unapply(tpe: ClassInfoType): Option[(List[Type], Scope, Symbol)] - } - abstract class NullaryMethodTypeExtractor { def apply(resultType: Type): NullaryMethodType def unapply(tpe: NullaryMethodType): Option[(Type)] } + /** The `PolyType` type signature is used for polymorphic methods + * that have at least one type parameter. + */ + type PolyType >: Null <: AnyRef with Type + + /** A tag that preserves the identity of the `PolyType` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val PolyTypeTag: ClassTag[PolyType] + + /** The constructor/deconstructor for `PolyType` instances. */ + val PolyType: PolyTypeExtractor + + /** An extractor class to create and pattern match with syntax `PolyType(typeParams, resultType)`. + * Here, `typeParams` are the type parameters of the method and `resultType` + * is the type signature following the type parameters. + */ abstract class PolyTypeExtractor { def apply(typeParams: List[Symbol], resultType: Type): PolyType def unapply(tpe: PolyType): Option[(List[Symbol], Type)] } + /** The `ExistentialType` type signature is used for existential types and + * wildcard types. + */ + type ExistentialType >: Null <: AnyRef with Type + + /** A tag that preserves the identity of the `ExistentialType` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val ExistentialTypeTag: ClassTag[ExistentialType] + + /** The constructor/deconstructor for `ExistentialType` instances. */ + val ExistentialType: ExistentialTypeExtractor + + /** An extractor class to create and pattern match with syntax + * `ExistentialType(quantified, underlying)`. + * Here, `quantified` are the type variables bound by the existential type and `underlying` + * is the type that's existentially quantified. + */ abstract class ExistentialTypeExtractor { def apply(quantified: List[Symbol], underlying: Type): ExistentialType def unapply(tpe: ExistentialType): Option[(List[Symbol], Type)] } + /** The `AnnotatedType` type signature is used for annotated types of the + * for `<type> @<annotation>`. + */ + type AnnotatedType >: Null <: AnyRef with Type + + /** A tag that preserves the identity of the `AnnotatedType` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val AnnotatedTypeTag: ClassTag[AnnotatedType] + + /** The constructor/deconstructor for `AnnotatedType` instances. */ + val AnnotatedType: AnnotatedTypeExtractor + + /** An extractor class to create and pattern match with syntax + * `AnnotatedType(annotations, underlying, selfsym)`. + * Here, `annotations` are the annotations decorating the underlying type `underlying`. + * `selfSym` is a symbol representing the annotated type itself. + */ abstract class AnnotatedTypeExtractor { def apply(annotations: List[AnnotationInfo], underlying: Type, selfsym: Symbol): AnnotatedType def unapply(tpe: AnnotatedType): Option[(List[AnnotationInfo], Type, Symbol)] } - /** The least upper bound of a list of types, as determined by `<:<`. */ - def lub(xs: List[Type]): Type - - /** The greatest lower bound of a list of types, as determined by `<:<`. */ - def glb(ts: List[Type]): Type - - // Creators --------------------------------------------------------------- - // too useful and too non-trivial to be left out of public API - // [Eugene to Paul] needs review! + /** The `TypeBounds` type signature is used to indicate lower and upper type bounds + * of type parameters and abstract types. It is not a first-class type. + * If an abstract type or type parameter is declared with any of the forms + * on the left, its type signature is the TypeBounds type on the right. + * {{{ + * T >: L <: U TypeBounds(L, U) + * T >: L TypeBounds(L, Any) + * T <: U TypeBounds(Nothing, U) + * }}} + */ + type TypeBounds >: Null <: AnyRef with Type - /** The canonical creator for single-types */ - def singleType(pre: Type, sym: Symbol): Type + /** A tag that preserves the identity of the `TypeBounds` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val TypeBoundsTag: ClassTag[TypeBounds] - /** the canonical creator for a refined type with a given scope */ - def refinedType(parents: List[Type], owner: Symbol, decls: Scope, pos: Position): Type + /** The constructor/deconstructor for `TypeBounds` instances. */ + val TypeBounds: TypeBoundsExtractor - /** The canonical creator for a refined type with an initially empty scope. + /** An extractor class to create and pattern match with syntax `TypeBound(lower, upper)` + * Here, `lower` is the lower bound of the `TypeBounds` pair, and `upper` is + * the upper bound. */ - def refinedType(parents: List[Type], owner: Symbol): Type + abstract class TypeBoundsExtractor { + def apply(lo: Type, hi: Type): TypeBounds + def unapply(tpe: TypeBounds): Option[(Type, Type)] + } - /** The canonical creator for typerefs + /** An object representing an unknown type, used during type inference. + * If you see WildcardType outside of inference it is almost certainly a bug. */ - def typeRef(pre: Type, sym: Symbol, args: List[Type]): Type - - /** A creator for intersection type where intersections of a single type are - * replaced by the type itself. */ - def intersectionType(tps: List[Type]): Type + val WildcardType: Type - /** A creator for intersection type where intersections of a single type are - * replaced by the type itself, and repeated parent classes are merged. + /** BoundedWildcardTypes, used only during type inference, are created in + * two places that I can find: * - * !!! Repeated parent classes are not merged - is this a bug in the - * comment or in the code? + * 1. If the expected type of an expression is an existential type, + * its hidden symbols are replaced with bounded wildcards. + * 2. When an implicit conversion is being sought based in part on + * the name of a method in the converted type, a HasMethodMatching + * type is created: a MethodType with parameters typed as + * BoundedWildcardTypes. */ - def intersectionType(tps: List[Type], owner: Symbol): Type + type BoundedWildcardType >: Null <: AnyRef with Type - /** A creator for type applications */ - def appliedType(tycon: Type, args: List[Type]): Type - - /** A creator for type parameterizations that strips empty type parameter lists. - * Use this factory method to indicate the type has kind * (it's a polymorphic value) - * until we start tracking explicit kinds equivalent to typeFun (except that the latter requires tparams nonEmpty). + /** A tag that preserves the identity of the `BoundedWildcardType` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. */ - def polyType(tparams: List[Symbol], tpe: Type): Type + implicit val BoundedWildcardTypeTag: ClassTag[BoundedWildcardType] - /** A creator for existential types. This generates: - * - * {{{ - * tpe1 where { tparams } - * }}} - * - * where `tpe1` is the result of extrapolating `tpe` with regard to `tparams`. - * Extrapolating means that type variables in `tparams` occurring - * in covariant positions are replaced by upper bounds, (minus any - * SingletonClass markers), type variables in `tparams` occurring in - * contravariant positions are replaced by upper bounds, provided the - * resulting type is legal with regard to stability, and does not contain - * any type variable in `tparams`. - * - * The abstraction drops all type parameters that are not directly or - * indirectly referenced by type `tpe1`. If there are no remaining type - * parameters, simply returns result type `tpe`. - */ - def existentialAbstraction(tparams: List[Symbol], tpe0: Type): Type -} + val BoundedWildcardType: BoundedWildcardTypeExtractor + abstract class BoundedWildcardTypeExtractor { + def apply(bounds: TypeBounds): BoundedWildcardType + def unapply(tpe: BoundedWildcardType): Option[TypeBounds] + } +} diff --git a/src/library/scala/reflect/base/Universe.scala b/src/library/scala/reflect/base/Universe.scala new file mode 100644 index 0000000000..93ddcb9f55 --- /dev/null +++ b/src/library/scala/reflect/base/Universe.scala @@ -0,0 +1,18 @@ +package scala.reflect +package base + +abstract class Universe extends Symbols + with Types + with FlagSets + with Scopes + with Names + with Trees + with Constants + with AnnotationInfos + with Positions + with TypeTags + with TagInterop + with StandardDefinitions + with StandardNames + with BuildUtils + with Mirrors
\ No newline at end of file diff --git a/src/library/scala/reflect/compat.scala b/src/library/scala/reflect/compat.scala new file mode 100644 index 0000000000..fc0e5fbf9c --- /dev/null +++ b/src/library/scala/reflect/compat.scala @@ -0,0 +1,33 @@ +// [Eugene++] delete this once we merge with trunk and have a working IDE + +package scala.reflect { + trait ArrayTag[T] + trait ErasureTag[T] + trait ConcreteTypeTag[T] +} + +package scala.reflect.api { + trait TypeTags { + trait TypeTag[T] + trait ConcreteTypeTag[T] + } +} + +package scala { + import scala.reflect.base.{Universe => BaseUniverse} + + trait reflect_compat { + lazy val mirror: BaseUniverse = ??? + } +} + +package scala.reflect { + import language.experimental.macros + import scala.reflect.base.{Universe => BaseUniverse} + + trait internal_compat { + private[scala] def materializeArrayTag[T](u: BaseUniverse): ArrayTag[T] = ??? + private[scala] def materializeErasureTag[T](u: BaseUniverse): ErasureTag[T] = ??? + private[scala] def materializeConcreteTypeTag[T](u: BaseUniverse): ConcreteTypeTag[T] = ??? + } +}
\ No newline at end of file diff --git a/src/library/scala/reflect/makro/Aliases.scala b/src/library/scala/reflect/makro/Aliases.scala deleted file mode 100644 index 38b1065a40..0000000000 --- a/src/library/scala/reflect/makro/Aliases.scala +++ /dev/null @@ -1,26 +0,0 @@ -package scala.reflect.makro - -trait Aliases { - self: Context => - - /** Aliases of mirror types */ - type Symbol = mirror.Symbol - type Type = mirror.Type - type Name = mirror.Name - type Tree = mirror.Tree - type Position = mirror.Position - type Scope = mirror.Scope - type Modifiers = mirror.Modifiers - type Expr[+T] = mirror.Expr[T] - type TypeTag[T] = mirror.TypeTag[T] - - /** Creator/extractor objects for Expr and TypeTag values */ - val TypeTag = mirror.TypeTag - val Expr = mirror.Expr - - /** incantations for summoning tags */ - def tag[T](implicit ttag: TypeTag[T]) = ttag - def typeTag[T](implicit ttag: TypeTag[T]) = ttag - def concreteTag[T](implicit cttag: ConcreteTypeTag[T]) = cttag - def concreteTypeTag[T](implicit cttag: ConcreteTypeTag[T]) = cttag -} diff --git a/src/library/scala/reflect/makro/Context.scala b/src/library/scala/reflect/makro/Context.scala deleted file mode 100644 index b8fb0dcce5..0000000000 --- a/src/library/scala/reflect/makro/Context.scala +++ /dev/null @@ -1,44 +0,0 @@ -package scala.reflect.makro - -import language.experimental.macros - -// todo. introduce context hierarchy -// the most lightweight context should just expose the stuff from the SIP -// the full context should include all traits from scala.reflect.makro (and probably reside in scala-compiler.jar) - -trait Context extends Aliases - with CapturedVariables - with Enclosures - with Infrastructure - with Names - with Reifiers - with FrontEnds - with Settings - with Symbols - with Typers - with Util { - - /** The mirror that corresponds to the compile-time universe */ - val mirror: scala.reflect.api.Universe - - /** The type of the prefix tree from which the macro is selected */ - type PrefixType - - /** The prefix tree from which the macro is selected */ - val prefix: Expr[PrefixType] - - /** Alias to the underlying mirror's reify */ - def reify[T](expr: T): Expr[T] = macro Context.reify[T] -} - -object Context { - def reify[T](cc: Context{ type PrefixType = Context })(expr: cc.Expr[T]): cc.Expr[cc.prefix.value.Expr[T]] = { - import cc.mirror._ - import scala.reflect.makro.internal._ - // [Eugene] how do I typecheck this without undergoing this tiresome (and, in general, incorrect) procedure? - val prefix: Tree = Select(cc.prefix.tree, newTermName("mirror")) - val prefixTpe = cc.typeCheck(TypeApply(Select(prefix, newTermName("asInstanceOf")), List(SingletonTypeTree(prefix)))).tpe - prefix setType prefixTpe - cc.Expr(cc.materializeExpr(prefix, expr.tree)) - } -} diff --git a/src/library/scala/reflect/makro/Symbols.scala b/src/library/scala/reflect/makro/Symbols.scala deleted file mode 100644 index ca1c17534c..0000000000 --- a/src/library/scala/reflect/makro/Symbols.scala +++ /dev/null @@ -1,24 +0,0 @@ -package scala.reflect.makro - -trait Symbols { - self: Context => - - /** Can this symbol be loaded by a reflective mirror? - * - * Scalac relies on `ScalaSignature' annotation to retain symbols across compilation runs. - * Such annotations (also called "pickles") are applied on top-level classes and include information - * about all symbols reachable from the annotee. However, local symbols (e.g. classes or definitions local to a block) - * are typically unreachable and information about them gets lost. - * - * This method is useful for macro writers who wish to save certain ASTs to be used at runtime. - * With `isLocatable' it's possible to check whether a tree can be retained as is, or it needs special treatment. - */ - def isLocatable(sym: Symbol): Boolean - - /** Is this symbol static (i.e. with no outer instance)? - * Q: When exactly is a sym marked as STATIC? - * A: If it's a member of a toplevel object, or of an object contained in a toplevel object, or any number of levels deep. - * http://groups.google.com/group/scala-internals/browse_thread/thread/d385bcd60b08faf6 - */ - def isStatic(sym: Symbol): Boolean -}
\ No newline at end of file diff --git a/src/library/scala/reflect/makro/internal/Utils.scala b/src/library/scala/reflect/makro/internal/Utils.scala deleted file mode 100644 index 3af58e1c88..0000000000 --- a/src/library/scala/reflect/makro/internal/Utils.scala +++ /dev/null @@ -1,146 +0,0 @@ -package scala.reflect.makro - -import scala.reflect.api.Universe -import language.implicitConversions -import language.experimental.macros - -/** This package is required by the compiler and <b>should not be used in client code</b>. */ -package object internal { - /** This method is required by the compiler and <b>should not be used in client code</b>. */ - def materializeArrayTag[T](u: Universe): ArrayTag[T] = macro materializeArrayTag_impl[T] - - /** This method is required by the compiler and <b>should not be used in client code</b>. */ - def materializeArrayTag_impl[T: c.TypeTag](c: Context)(u: c.Expr[Universe]): c.Expr[ArrayTag[T]] = - c.Expr[Nothing](c.materializeArrayTag(u.tree, implicitly[c.TypeTag[T]].tpe))(c.TypeTag.Nothing) - - /** This method is required by the compiler and <b>should not be used in client code</b>. */ - def materializeErasureTag[T](u: Universe): ErasureTag[T] = macro materializeErasureTag_impl[T] - - /** This method is required by the compiler and <b>should not be used in client code</b>. */ - def materializeErasureTag_impl[T: c.TypeTag](c: Context)(u: c.Expr[Universe]): c.Expr[ErasureTag[T]] = - c.Expr[Nothing](c.materializeErasureTag(u.tree, implicitly[c.TypeTag[T]].tpe, concrete = false))(c.TypeTag.Nothing) - - /** This method is required by the compiler and <b>should not be used in client code</b>. */ - def materializeClassTag[T](u: Universe): ClassTag[T] = macro materializeClassTag_impl[T] - - /** This method is required by the compiler and <b>should not be used in client code</b>. */ - def materializeClassTag_impl[T: c.TypeTag](c: Context)(u: c.Expr[Universe]): c.Expr[ClassTag[T]] = - c.Expr[Nothing](c.materializeClassTag(u.tree, implicitly[c.TypeTag[T]].tpe))(c.TypeTag.Nothing) - - /** This method is required by the compiler and <b>should not be used in client code</b>. */ - def materializeTypeTag[T](u: Universe): u.TypeTag[T] = macro materializeTypeTag_impl[T] - - /** This method is required by the compiler and <b>should not be used in client code</b>. */ - def materializeTypeTag_impl[T: c.TypeTag](c: Context)(u: c.Expr[Universe]): c.Expr[u.value.TypeTag[T]] = - c.Expr[Nothing](c.materializeTypeTag(u.tree, implicitly[c.TypeTag[T]].tpe, concrete = false))(c.TypeTag.Nothing) - - /** This method is required by the compiler and <b>should not be used in client code</b>. */ - def materializeConcreteTypeTag[T](u: Universe): u.ConcreteTypeTag[T] = macro materializeConcreteTypeTag_impl[T] - - /** This method is required by the compiler and <b>should not be used in client code</b>. */ - def materializeConcreteTypeTag_impl[T: c.TypeTag](c: Context)(u: c.Expr[Universe]): c.Expr[u.value.ConcreteTypeTag[T]] = - c.Expr[Nothing](c.materializeTypeTag(u.tree, implicitly[c.TypeTag[T]].tpe, concrete = true))(c.TypeTag.Nothing) - - /** This method is required by the compiler and <b>should not be used in client code</b>. */ - private[scala] implicit def context2utils(c0: Context) : Utils { val c: c0.type } = new { val c: c0.type = c0 } with Utils -} - -package internal { - private[scala] abstract class Utils { - val c: Context - - import c.mirror._ - import definitions._ - - val coreTags = Map( - ByteClass.asType -> newTermName("Byte"), - ShortClass.asType -> newTermName("Short"), - CharClass.asType -> newTermName("Char"), - IntClass.asType -> newTermName("Int"), - LongClass.asType -> newTermName("Long"), - FloatClass.asType -> newTermName("Float"), - DoubleClass.asType -> newTermName("Double"), - BooleanClass.asType -> newTermName("Boolean"), - UnitClass.asType -> newTermName("Unit"), - AnyClass.asType -> newTermName("Any"), - ObjectClass.asType -> newTermName("Object"), - AnyValClass.asType -> newTermName("AnyVal"), - AnyRefClass.asType -> newTermName("AnyRef"), - NothingClass.asType -> newTermName("Nothing"), - NullClass.asType -> newTermName("Null"), - StringClass.asType -> newTermName("String")) - - // todo. the following two methods won't be necessary once we implement implicit macro generators for tags - - def materializeArrayTag(prefix: Tree, tpe: Type): Tree = - materializeClassTag(prefix, tpe) - - def materializeErasureTag(prefix: Tree, tpe: Type, concrete: Boolean): Tree = - if (concrete) materializeClassTag(prefix, tpe) else materializeTypeTag(prefix, tpe, concrete = false) - - def materializeClassTag(prefix: Tree, tpe: Type): Tree = - materializeTag(prefix, tpe, ClassTagModule, { - val erasure = c.reifyErasure(tpe, concrete = true) - val factory = TypeApply(Select(Ident(ClassTagModule), "apply"), List(TypeTree(tpe))) - Apply(factory, List(erasure)) - }) - - def materializeTypeTag(prefix: Tree, tpe: Type, concrete: Boolean): Tree = { - val tagModule = if (concrete) ConcreteTypeTagModule else TypeTagModule - materializeTag(prefix, tpe, tagModule, c.reifyType(prefix, tpe, dontSpliceAtTopLevel = true, concrete = concrete)) - } - - private def materializeTag(prefix: Tree, tpe: Type, tagModule: Symbol, materializer: => Tree): Tree = { - val result = - tpe match { - case coreTpe if coreTags contains coreTpe => - val ref = if (tagModule.owner.isPackageClass) Ident(tagModule) else Select(prefix, tagModule.name) - Select(ref, coreTags(coreTpe)) - case _ => - val manifestInScope = nonSyntheticManifestInScope(tpe) - if (manifestInScope.isEmpty) translatingReificationErrors(materializer) - else gen.mkMethodCall(staticModule("scala.reflect.package"), newTermName("manifestToConcreteTypeTag"), List(tpe), List(manifestInScope)) - } - try c.typeCheck(result) - catch { case terr @ c.TypeError(pos, msg) => failTag(terr) } - } - - private def nonSyntheticManifestInScope(tpe: Type) = { - val ManifestClass = staticClass("scala.reflect.Manifest") - val ManifestModule = staticModule("scala.reflect.Manifest") - val manifest = c.inferImplicitValue(appliedType(ManifestClass.asTypeConstructor, List(tpe))) - val notOk = manifest.isEmpty || (manifest exists (sub => sub.symbol != null && (sub.symbol == ManifestModule || sub.symbol.owner == ManifestModule))) - if (notOk) EmptyTree else manifest - } - - def materializeExpr(prefix: Tree, expr: Tree): Tree = { - val result = translatingReificationErrors(c.reifyTree(prefix, expr)) - try c.typeCheck(result) - catch { case terr @ c.TypeError(pos, msg) => failExpr(terr) } - } - - private def translatingReificationErrors(materializer: => Tree): Tree = { - try materializer - catch { - case ReificationError(pos, msg) => - c.error(pos.asInstanceOf[c.Position], msg) // this cast is a very small price for the sanity of exception handling - EmptyTree - case UnexpectedReificationError(pos, err, cause) if cause != null => - throw cause - } - } - - private def failTag(reason: Any): Nothing = { - val Apply(TypeApply(fun, List(tpeTree)), _) = c.macroApplication - val tpe = tpeTree.tpe - val PolyType(_, MethodType(_, tagTpe)) = fun.tpe - val tagModule = tagTpe.typeSymbol.companionSymbol - if (c.compilerSettings.contains("-Xlog-implicits")) - c.echo(c.enclosingPosition, "cannot materialize " + tagModule.name + "[" + tpe + "] because:\n" + reason) - c.abort(c.enclosingPosition, "No %s available for %s".format(tagModule.name, tpe)) - } - - private def failExpr(reason: Any): Nothing = - c.abort(c.enclosingPosition, "Cannot materialize Expr because:\n" + reason) - } -} diff --git a/src/library/scala/reflect/makro/internal/macroImpl.scala b/src/library/scala/reflect/makro/internal/macroImpl.scala index 9cf4d23072..0dfa8d1654 100644 --- a/src/library/scala/reflect/makro/internal/macroImpl.scala +++ b/src/library/scala/reflect/makro/internal/macroImpl.scala @@ -1,5 +1,18 @@ package scala.reflect.makro package internal -/** This type is required by the compiler and <b>should not be used in client code</b>. */ -class macroImpl(val referenceToMacroImpl: Any) extends annotation.StaticAnnotation +/** Links macro definitions with their implementation. + * This is necessary to preserve macro def -> macro impl links between compilation runs. + * + * More precisely, after typechecking right-hand side of a macro def + * `typedMacroBody` slaps `macroImpl` annotation onto the macro def + * with the result of typechecking as a sole parameter. + * + * As an unfortunate consequence, this annotation must be defined in scala-library.jar, + * because anyone (even those programmers who compile their programs with only scala-library on classpath) + * must be able to define macros. + * + * To lessen the weirdness we define this annotation as `private[scala]`. + * It will not prevent pickling, but it will prevent application developers (and scaladocs) from seeing the annotation. + */ +private[scala] class macroImpl(val referenceToMacroImpl: Any) extends annotation.StaticAnnotation diff --git a/src/library/scala/reflect/makro/internal/package.scala b/src/library/scala/reflect/makro/internal/package.scala new file mode 100644 index 0000000000..d31a0f0d14 --- /dev/null +++ b/src/library/scala/reflect/makro/internal/package.scala @@ -0,0 +1,16 @@ +package scala.reflect +package makro + +import language.experimental.macros +import scala.reflect.base.{Universe => BaseUniverse} + +// anchors for materialization macros emitted during tag materialization in Implicits.scala +// implementation is magically hardwired into `scala.reflect.reify.Taggers` +// +// todo. once we have implicit macros for tag generation, we can remove these anchors +// [Eugene++] how do I hide this from scaladoc? +package object internal extends scala.reflect.internal_compat { + private[scala] def materializeClassTag[T](u: BaseUniverse): ClassTag[T] = macro ??? + private[scala] def materializeAbsTypeTag[T](u: BaseUniverse): u.AbsTypeTag[T] = macro ??? + private[scala] def materializeTypeTag[T](u: BaseUniverse): u.TypeTag[T] = macro ??? +} diff --git a/src/library/scala/reflect/package.scala b/src/library/scala/reflect/package.scala index 38a144cd49..0ee58df2cd 100644 --- a/src/library/scala/reflect/package.scala +++ b/src/library/scala/reflect/package.scala @@ -1,42 +1,17 @@ package scala -package object reflect { +package object reflect extends reflect_compat { - import ReflectionUtils._ - import scala.compat.Platform.EOL + lazy val basis: base.Universe = new base.Base - // !!! This was a val; we can't throw exceptions that aggressively without breaking - // non-standard environments, e.g. google app engine. I made it a lazy val, but - // I think it would be better yet to throw the exception somewhere else - not during - // initialization, but in response to a doomed attempt to utilize it. + def classTag[T](implicit ctag: ClassTag[T]) = ctag + // typeTag incantation is defined inside scala.reflect.basis and scala.reflect.runtime.universe - // todo. default mirror (a static object) might become a source for memory leaks (because it holds a strong reference to a classloader)! - lazy val mirror: api.Mirror = - try mkMirror(defaultReflectionClassLoader) - catch { - case ex: UnsupportedOperationException => - new DummyMirror(defaultReflectionClassLoader) - } + // ClassTag class is defined in ClassTag.scala + type TypeTag[T] = scala.reflect.basis.TypeTag[T] - private[scala] def mirrorDiagnostics(cl: ClassLoader): String = """ - | - | This error has happened because `scala.reflect.runtime.package` located in - | scala-compiler.jar cannot be loaded. Classloader you are using is: - | %s. - | - | For the instructions for some of the situations that might be relevant - | visit our knowledge base at https://gist.github.com/2391081. - """.stripMargin('|').format(show(cl)) - - def mkMirror(classLoader: ClassLoader): api.Mirror = { - val coreClassLoader = getClass.getClassLoader - val instance = invokeFactoryOpt(coreClassLoader, "scala.reflect.runtime.package", "mkMirror", classLoader) - instance match { - case Some(x: api.Mirror) => x - case Some(_) => throw new UnsupportedOperationException("Available scala reflection implementation is incompatible with this interface." + mirrorDiagnostics(coreClassLoader)) - case None => throw new UnsupportedOperationException("Scala reflection not available on this platform." + mirrorDiagnostics(coreClassLoader)) - } - } + // ClassTag object is defined in ClassTag.scala + lazy val TypeTag = scala.reflect.basis.TypeTag @deprecated("Use `@scala.beans.BeanDescription` instead", "2.10.0") type BeanDescription = scala.beans.BeanDescription @@ -52,19 +27,4 @@ package object reflect { type BooleanBeanProperty = scala.beans.BooleanBeanProperty @deprecated("Use `@scala.beans.ScalaBeanInfo` instead", "2.10.0") type ScalaBeanInfo = scala.beans.ScalaBeanInfo - - // ArrayTag trait is defined separately from the mirror - // ErasureTag trait is defined separately from the mirror - // ConcreteErasureTag trait is defined separately from the mirror - // ClassTag class is defined separately from the mirror - type TypeTag[T] = scala.reflect.mirror.TypeTag[T] - type ConcreteTypeTag[T] = scala.reflect.mirror.ConcreteTypeTag[T] - - // ClassTag object is defined separately from the mirror - lazy val TypeTag = scala.reflect.mirror.TypeTag - lazy val ConcreteTypeTag = scala.reflect.mirror.ConcreteTypeTag - - def arrayTagToClassManifest[T](tag: ArrayTag[T]): ClassManifest[T] = TagInterop.arrayTagToClassManifest[T](tag) - def concreteTypeTagToManifest[T](tag: ConcreteTypeTag[T]): Manifest[T] = TagInterop.concreteTypeTagToManifest[T](tag) - def manifestToConcreteTypeTag[T](tag: Manifest[T]): ConcreteTypeTag[T] = TagInterop.manifestToConcreteTypeTag[T](tag) } diff --git a/src/library/scala/runtime/ScalaRunTime.scala b/src/library/scala/runtime/ScalaRunTime.scala index 5cd301a0fe..e5f5e9dc5d 100644 --- a/src/library/scala/runtime/ScalaRunTime.scala +++ b/src/library/scala/runtime/ScalaRunTime.scala @@ -12,6 +12,7 @@ import scala.collection.{ Seq, IndexedSeq, TraversableView, AbstractIterator } import scala.collection.mutable.WrappedArray import scala.collection.immutable.{ StringLike, NumericRange, List, Stream, Nil, :: } import scala.collection.generic.{ Sorted } +import scala.reflect.{ ClassTag, classTag } import scala.util.control.ControlThrowable import scala.xml.{ Node, MetaData } @@ -59,8 +60,7 @@ object ScalaRunTime { */ def arrayElementClass(schematic: Any): Class[_] = schematic match { case cls: Class[_] => cls.getComponentType - case tag: ClassTag[_] => tag.erasure - case tag: ArrayTag[_] => tag.newArray(0).getClass.getComponentType + case tag: ClassTag[_] => tag.runtimeClass case _ => throw new UnsupportedOperationException("unsupported schematic %s (%s)".format(schematic, if (schematic == null) "null" else schematic.getClass)) } @@ -69,7 +69,7 @@ object ScalaRunTime { * rewrites expressions like 5.getClass to come here. */ def anyValClass[T <: AnyVal : ClassTag](value: T): Class[T] = - classTag[T].erasure.asInstanceOf[Class[T]] + classTag[T].runtimeClass.asInstanceOf[Class[T]] /** Retrieve generic array element */ def array_apply(xs: AnyRef, idx: Int): Any = xs match { diff --git a/src/library/scala/util/Marshal.scala b/src/library/scala/util/Marshal.scala index 209cd6c062..2d3f54a95e 100644 --- a/src/library/scala/util/Marshal.scala +++ b/src/library/scala/util/Marshal.scala @@ -39,7 +39,7 @@ object Marshal { try { // [Eugene] needs review // previously was: found <:< expected - found.erasure.asSubclass(expected.erasure) + found.runtimeClass.asSubclass(expected.runtimeClass) in.readObject.asInstanceOf[A] } catch { case _: ClassCastException => diff --git a/src/library/scala/util/Sorting.scala b/src/library/scala/util/Sorting.scala index 7d98e57741..5f0edf964f 100644 --- a/src/library/scala/util/Sorting.scala +++ b/src/library/scala/util/Sorting.scala @@ -8,7 +8,7 @@ package scala.util -import scala.reflect.ClassTag +import scala.reflect.{ ClassTag, classTag } import scala.math.Ordering /** The Sorting object provides functions that can sort various kinds of @@ -39,14 +39,14 @@ object Sorting { /** Sort an array of K where K is Ordered, preserving the existing order * where the values are equal. */ - def stableSort[K: ArrayTag: Ordering](a: Array[K]) { + def stableSort[K: ClassTag: Ordering](a: Array[K]) { stableSort(a, 0, a.length-1, new Array[K](a.length), Ordering[K].lt _) } /** Sorts an array of `K` given an ordering function `f`. * `f` should return `true` iff its first parameter is strictly less than its second parameter. */ - def stableSort[K: ArrayTag](a: Array[K], f: (K, K) => Boolean) { + def stableSort[K: ClassTag](a: Array[K], f: (K, K) => Boolean) { stableSort(a, 0, a.length-1, new Array[K](a.length), f) } @@ -57,14 +57,14 @@ object Sorting { * @param f the comparison function. * @return the sorted sequence of items. */ - def stableSort[K: ArrayTag](a: Seq[K], f: (K, K) => Boolean): Array[K] = { + def stableSort[K: ClassTag](a: Seq[K], f: (K, K) => Boolean): Array[K] = { val ret = a.toArray stableSort(ret, f) ret } /** Sorts an arbitrary sequence of items that are viewable as ordered. */ - def stableSort[K: ArrayTag: Ordering](a: Seq[K]): Array[K] = + def stableSort[K: ClassTag: Ordering](a: Seq[K]): Array[K] = stableSort(a, Ordering[K].lt _) /** Stably sorts a sequence of items given an extraction function that will @@ -74,8 +74,8 @@ object Sorting { * @param f the comparison function. * @return the sorted sequence of items. */ - def stableSort[K: ArrayTag, M: Ordering](a: Seq[K], f: K => M): Array[K] = - stableSort(a)(implicitly[ArrayTag[K]], Ordering[M] on f) + def stableSort[K: ClassTag, M: Ordering](a: Seq[K], f: K => M): Array[K] = + stableSort(a)(implicitly[ClassTag[K]], Ordering[M] on f) private def sort1[K: Ordering](x: Array[K], off: Int, len: Int) { val ord = Ordering[K] @@ -498,7 +498,7 @@ object Sorting { sort2(off, len) } - private def stableSort[K : ArrayTag](a: Array[K], lo: Int, hi: Int, scratch: Array[K], f: (K,K) => Boolean) { + private def stableSort[K : ClassTag](a: Array[K], lo: Int, hi: Int, scratch: Array[K], f: (K,K) => Boolean) { if (lo < hi) { val mid = (lo+hi) / 2 stableSort(a, lo, mid, scratch, f) diff --git a/src/library/scala/util/control/Exception.scala b/src/library/scala/util/control/Exception.scala index 38f4abb20a..2ee053c92b 100644 --- a/src/library/scala/util/control/Exception.scala +++ b/src/library/scala/util/control/Exception.scala @@ -9,6 +9,7 @@ package scala.util.control import collection.immutable.List +import reflect.{ ClassTag, classTag } import java.lang.reflect.InvocationTargetException import language.implicitConversions @@ -32,7 +33,7 @@ object Exception { def mkCatcher[Ex <: Throwable: ClassTag, T](isDef: Ex => Boolean, f: Ex => T) = new Catcher[T] { private def downcast(x: Throwable): Option[Ex] = - if (classTag[Ex].erasure.isAssignableFrom(x.getClass)) Some(x.asInstanceOf[Ex]) + if (classTag[Ex].runtimeClass.isAssignableFrom(x.getClass)) Some(x.asInstanceOf[Ex]) else None def isDefinedAt(x: Throwable) = downcast(x) exists isDef diff --git a/src/partest/scala/tools/partest/CompilerTest.scala b/src/partest/scala/tools/partest/CompilerTest.scala index 86678760be..89c1a9c2ca 100644 --- a/src/partest/scala/tools/partest/CompilerTest.scala +++ b/src/partest/scala/tools/partest/CompilerTest.scala @@ -5,7 +5,7 @@ package scala.tools.partest -import scala.reflect.{mirror => rm} +import scala.reflect.{basis => rb} import scala.tools.nsc._ /** For testing compiler internals directly. @@ -34,7 +34,7 @@ abstract class CompilerTest extends DirectTest { // Utility functions class MkType(sym: Symbol) { - def apply[M](implicit t: rm.TypeTag[M]): Type = + def apply[M](implicit t: rb.TypeTag[M]): Type = if (sym eq NoSymbol) NoType else appliedType(sym, compilerTypeFromTag(t)) } @@ -50,7 +50,7 @@ abstract class CompilerTest extends DirectTest { } class SymsInPackage(pkgName: String) { - def pkg = getRequiredModule(pkgName) + def pkg = rootMirror.getRequiredModule(pkgName) def classes = allMembers(pkg) filter (_.isClass) def modules = allMembers(pkg) filter (_.isModule) def symbols = classes ++ terms filterNot (_ eq NoSymbol) diff --git a/src/partest/scala/tools/partest/PartestTask.scala b/src/partest/scala/tools/partest/PartestTask.scala index 67b38d2e24..2f694b3cc8 100644 --- a/src/partest/scala/tools/partest/PartestTask.scala +++ b/src/partest/scala/tools/partest/PartestTask.scala @@ -279,6 +279,16 @@ class PartestTask extends Task with CompilationPathProperty { } } getOrElse sys.error("Provided classpath does not contain a Scala library.") + val scalaReflect = { + (classpath.list map { fs => new File(fs) }) find { f => + f.getName match { + case "scala-reflect.jar" => true + case "reflect" if (f.getParentFile.getName == "classes") => true + case _ => false + } + } + } getOrElse sys.error("Provided classpath does not contain a Scala reflection library.") + val scalaCompiler = { (classpath.list map { fs => new File(fs) }) find { f => f.getName match { @@ -342,6 +352,7 @@ class PartestTask extends Task with CompilationPathProperty { antFileManager.failed = runFailed antFileManager.CLASSPATH = ClassPath.join(classpath.list: _*) antFileManager.LATEST_LIB = scalaLibrary.getAbsolutePath + antFileManager.LATEST_REFLECT = scalaReflect.getAbsolutePath antFileManager.LATEST_COMP = scalaCompiler.getAbsolutePath antFileManager.LATEST_PARTEST = scalaPartest.getAbsolutePath antFileManager.LATEST_ACTORS = scalaActors.getAbsolutePath diff --git a/src/partest/scala/tools/partest/SigTest.scala b/src/partest/scala/tools/partest/SigTest.scala index 999d901d21..1d8728294b 100644 --- a/src/partest/scala/tools/partest/SigTest.scala +++ b/src/partest/scala/tools/partest/SigTest.scala @@ -8,6 +8,7 @@ package scala.tools.partest import scala.tools.nsc.Settings import scala.tools.nsc.interpreter.ILoop import java.lang.reflect.{ Method => JMethod, Field => JField } +import scala.reflect.{ClassTag, classTag} /** Support code for testing signatures. */ @@ -21,13 +22,13 @@ trait SigTest { def isObjectMethodName(name: String) = classOf[Object].getMethods exists (_.getName == name) def fields[T: ClassTag](p: JField => Boolean) = { - val cl = classTag[T].erasure + val cl = classTag[T].runtimeClass val fs = (cl.getFields ++ cl.getDeclaredFields).distinct sortBy (_.getName) fs filter p } def methods[T: ClassTag](p: JMethod => Boolean) = { - val cl = classTag[T].erasure + val cl = classTag[T].runtimeClass val ms = (cl.getMethods ++ cl.getDeclaredMethods).distinct sortBy (x => (x.getName, x.isBridge)) ms filter p @@ -44,7 +45,7 @@ trait SigTest { (methodsNamed[T](name) map mstr) ++ (fieldsNamed[T](name) map fstr) def show[T: ClassTag](name: String = "") = { - println(classTag[T].erasure.getName) + println(classTag[T].runtimeClass.getName) if (name == "") allGenericStrings[T]() foreach println else genericStrings[T](name) foreach println } diff --git a/src/partest/scala/tools/partest/nest/AntRunner.scala b/src/partest/scala/tools/partest/nest/AntRunner.scala index dc83e4ea66..ee644c5315 100644 --- a/src/partest/scala/tools/partest/nest/AntRunner.scala +++ b/src/partest/scala/tools/partest/nest/AntRunner.scala @@ -20,6 +20,7 @@ class AntRunner extends DirectRunner { var JAVAC_CMD: String = "javac" var CLASSPATH: String = _ var LATEST_LIB: String = _ + var LATEST_REFLECT: String = _ var LATEST_COMP: String = _ var LATEST_PARTEST: String = _ var LATEST_ACTORS: String = _ diff --git a/src/partest/scala/tools/partest/nest/ConsoleFileManager.scala b/src/partest/scala/tools/partest/nest/ConsoleFileManager.scala index b270a6b65a..68e9753575 100644 --- a/src/partest/scala/tools/partest/nest/ConsoleFileManager.scala +++ b/src/partest/scala/tools/partest/nest/ConsoleFileManager.scala @@ -85,6 +85,7 @@ class ConsoleFileManager extends FileManager { latestLibFile = testClassesDir / "library" latestActorsFile = testClassesDir / "library" / "actors" latestActMigFile = testClassesDir / "actors-migration" + latestReflectFile = testClassesDir / "reflect" latestCompFile = testClassesDir / "compiler" latestPartestFile = testClassesDir / "partest" latestFjbgFile = testParent / "lib" / "fjbg.jar" @@ -96,6 +97,7 @@ class ConsoleFileManager extends FileManager { latestLibFile = dir / "lib/scala-library.jar" latestActorsFile = dir / "lib/scala-actors.jar" latestActMigFile = dir / "lib/scala-actors-migration.jar" + latestReflectFile = dir / "lib/scala-reflect.jar" latestCompFile = dir / "lib/scala-compiler.jar" latestPartestFile = dir / "lib/scala-partest.jar" latestFjbgFile = testParent / "lib" / "fjbg.jar" @@ -107,6 +109,7 @@ class ConsoleFileManager extends FileManager { latestLibFile = prefixFile("build/quick/classes/library") latestActorsFile = prefixFile("build/quick/classes/library/actors") latestActMigFile = prefixFile("build/quick/classes/actors-migration") + latestReflectFile = prefixFile("build/quick/classes/reflect") latestCompFile = prefixFile("build/quick/classes/compiler") latestPartestFile = prefixFile("build/quick/classes/partest") } @@ -118,6 +121,7 @@ class ConsoleFileManager extends FileManager { latestLibFile = prefixFileWith(p, "lib/scala-library.jar") latestActorsFile = prefixFileWith(p, "lib/scala-actors.jar") latestActMigFile = prefixFileWith(p, "lib/scala-actors-migration.jar") + latestReflectFile = prefixFileWith(p, "lib/scala-reflect.jar") latestCompFile = prefixFileWith(p, "lib/scala-compiler.jar") latestPartestFile = prefixFileWith(p, "lib/scala-partest.jar") } @@ -128,6 +132,7 @@ class ConsoleFileManager extends FileManager { latestLibFile = prefixFile("dists/latest/lib/scala-library.jar") latestActorsFile = prefixFile("dists/latest/lib/scala-actors.jar") latestActMigFile = prefixFile("dists/latest/lib/scala-actors-migration.jar") + latestReflectFile = prefixFile("dists/latest/lib/scala-reflect.jar") latestCompFile = prefixFile("dists/latest/lib/scala-compiler.jar") latestPartestFile = prefixFile("dists/latest/lib/scala-partest.jar") } @@ -138,6 +143,7 @@ class ConsoleFileManager extends FileManager { latestLibFile = prefixFile("build/pack/lib/scala-library.jar") latestActorsFile = prefixFile("build/pack/lib/scala-actors.jar") latestActMigFile = prefixFile("build/pack/lib/scala-actors-migration.jar") + latestReflectFile = prefixFile("build/pack/lib/scala-reflect.jar") latestCompFile = prefixFile("build/pack/lib/scala-compiler.jar") latestPartestFile = prefixFile("build/pack/lib/scala-partest.jar") } @@ -151,10 +157,10 @@ class ConsoleFileManager extends FileManager { names map (x => prefixFile(base + "/" + x).lastModified) reduceLeft (_ max _) // detect most recent build - val quickTime = mostRecentOf("build/quick/classes", "compiler/compiler.properties", "library/library.properties") - val packTime = mostRecentOf("build/pack/lib", "scala-compiler.jar", "scala-library.jar") - val distTime = mostRecentOf("dists/latest/lib", "scala-compiler.jar", "scala-library.jar") - val instTime = mostRecentOf("lib", "scala-compiler.jar", "scala-library.jar") + val quickTime = mostRecentOf("build/quick/classes", "compiler/compiler.properties", "reflect/reflect.properties", "library/library.properties") + val packTime = mostRecentOf("build/pack/lib", "scala-compiler.jar", "scala-reflect.jar", "scala-library.jar") + val distTime = mostRecentOf("dists/latest/lib", "scala-compiler.jar", "scala-reflect.jar", "scala-library.jar") + val instTime = mostRecentOf("lib", "scala-compiler.jar", "scala-reflect.jar", "scala-library.jar") val pairs = Map( (quickTime, () => setupQuick()), @@ -170,6 +176,7 @@ class ConsoleFileManager extends FileManager { } LATEST_LIB = latestLibFile.getAbsolutePath + LATEST_REFLECT = latestReflectFile.getAbsolutePath LATEST_COMP = latestCompFile.getAbsolutePath LATEST_PARTEST = latestPartestFile.getAbsolutePath LATEST_ACTORS = latestActorsFile.getAbsolutePath @@ -177,6 +184,7 @@ class ConsoleFileManager extends FileManager { } var LATEST_LIB: String = "" + var LATEST_REFLECT: String = "" var LATEST_COMP: String = "" var LATEST_PARTEST: String = "" var LATEST_ACTORS: String = "" @@ -186,6 +194,7 @@ class ConsoleFileManager extends FileManager { var latestLibFile: File = _ var latestActorsFile: File = _ var latestActMigFile: File = _ + var latestReflectFile: File = _ var latestCompFile: File = _ var latestPartestFile: File = _ var latestFjbgFile: File = _ diff --git a/src/partest/scala/tools/partest/nest/DirectRunner.scala b/src/partest/scala/tools/partest/nest/DirectRunner.scala index 815c27f567..09896edc55 100644 --- a/src/partest/scala/tools/partest/nest/DirectRunner.scala +++ b/src/partest/scala/tools/partest/nest/DirectRunner.scala @@ -58,13 +58,14 @@ trait DirectRunner { //val consFM = new ConsoleFileManager //import consFM.{ latestCompFile, latestLibFile, latestPartestFile } val latestCompFile = new File(fileManager.LATEST_COMP) + val latestReflectFile = new File(fileManager.LATEST_REFLECT) val latestLibFile = new File(fileManager.LATEST_LIB) val latestPartestFile = new File(fileManager.LATEST_PARTEST) val latestActorsFile = new File(fileManager.LATEST_ACTORS) val latestActMigFile = new File(fileManager.LATEST_ACTORS_MIGRATION) val scalacheckURL = PathSettings.scalaCheck.toURL val scalaCheckParentClassLoader = ScalaClassLoader.fromURLs( - scalacheckURL :: (List(latestCompFile, latestLibFile, latestActorsFile, latestActMigFile, latestPartestFile).map(_.toURI.toURL)) + scalacheckURL :: (List(latestCompFile, latestReflectFile, latestLibFile, latestActorsFile, latestActMigFile, latestPartestFile).map(_.toURI.toURL)) ) Output.init() diff --git a/src/partest/scala/tools/partest/nest/FileManager.scala b/src/partest/scala/tools/partest/nest/FileManager.scala index cf7160f521..40bfa36b04 100644 --- a/src/partest/scala/tools/partest/nest/FileManager.scala +++ b/src/partest/scala/tools/partest/nest/FileManager.scala @@ -60,6 +60,7 @@ trait FileManager extends FileUtil { var CLASSPATH: String var LATEST_LIB: String + var LATEST_REFLECT: String var LATEST_COMP: String var LATEST_PARTEST: String var LATEST_ACTORS: String diff --git a/src/partest/scala/tools/partest/nest/NestUI.scala b/src/partest/scala/tools/partest/nest/NestUI.scala index 6b81b66a39..7fd503e769 100644 --- a/src/partest/scala/tools/partest/nest/NestUI.scala +++ b/src/partest/scala/tools/partest/nest/NestUI.scala @@ -84,7 +84,7 @@ object NestUI { println(" --grep <expr> run all tests whose source file contains <expr>") println println(" Other options:") - println(" --pack pick compiler/library in build/pack, and run all tests") + println(" --pack pick compiler/reflect/library in build/pack, and run all tests") println(" --show-log show log") println(" --show-diff show diff between log and check file") println(" --failed run only those tests that failed during the last run") diff --git a/src/partest/scala/tools/partest/nest/ReflectiveRunner.scala b/src/partest/scala/tools/partest/nest/ReflectiveRunner.scala index a5d5952ff7..fa75d96b34 100644 --- a/src/partest/scala/tools/partest/nest/ReflectiveRunner.scala +++ b/src/partest/scala/tools/partest/nest/ReflectiveRunner.scala @@ -48,9 +48,9 @@ class ReflectiveRunner { new ConsoleFileManager import fileManager. - { latestCompFile, latestLibFile, latestPartestFile, latestFjbgFile, latestScalapFile, latestActorsFile, latestActMigFile } + { latestCompFile, latestReflectFile, latestLibFile, latestPartestFile, latestFjbgFile, latestScalapFile, latestActorsFile, latestActMigFile } val files = - Array(latestCompFile, latestLibFile, latestPartestFile, latestFjbgFile, latestScalapFile, latestActorsFile, latestActMigFile) map (x => io.File(x)) + Array(latestCompFile, latestReflectFile, latestLibFile, latestPartestFile, latestFjbgFile, latestScalapFile, latestActorsFile, latestActMigFile) map (x => io.File(x)) val sepUrls = files map (_.toURL) var sepLoader = new URLClassLoader(sepUrls, null) diff --git a/src/partest/scala/tools/partest/nest/SBTRunner.scala b/src/partest/scala/tools/partest/nest/SBTRunner.scala index 14e2dc3df9..7e2f37374b 100644 --- a/src/partest/scala/tools/partest/nest/SBTRunner.scala +++ b/src/partest/scala/tools/partest/nest/SBTRunner.scala @@ -13,6 +13,7 @@ object SBTRunner extends DirectRunner { var JAVAC_CMD: String = "javac" var CLASSPATH: String = _ var LATEST_LIB: String = _ + var LATEST_REFLECT: String = _ var LATEST_COMP: String = _ var LATEST_PARTEST: String = _ var LATEST_ACTORS: String = _ @@ -63,6 +64,7 @@ object SBTRunner extends DirectRunner { } // Find scala library jar file... fileManager.LATEST_LIB = findClasspath("scala-library", "scala-library") getOrElse sys.error("No scala-library found! Classpath = " + fileManager.CLASSPATH) + fileManager.LATEST_REFLECT = findClasspath("scala-reflect", "scala-reflect") getOrElse sys.error("No scala-reflect found! Classpath = " + fileManager.CLASSPATH) fileManager.LATEST_COMP = findClasspath("scala-compiler", "scala-compiler") getOrElse sys.error("No scala-compiler found! Classpath = " + fileManager.CLASSPATH) fileManager.LATEST_PARTEST = findClasspath("scala-partest", "partest") getOrElse sys.error("No scala-partest found! Classpath = " + fileManager.CLASSPATH) fileManager.LATEST_ACTORS = findClasspath("scala-actors", "actors") getOrElse sys.error("No scala-actors found! Classpath = " + fileManager.CLASSPATH) diff --git a/src/partest/scala/tools/partest/nest/Worker.scala b/src/partest/scala/tools/partest/nest/Worker.scala index 40325c6375..48f78e9ddc 100644 --- a/src/partest/scala/tools/partest/nest/Worker.scala +++ b/src/partest/scala/tools/partest/nest/Worker.scala @@ -53,6 +53,7 @@ class ScalaCheckFileManager(val origmanager: FileManager) extends FileManager { var CLASSPATH: String = join(origmanager.CLASSPATH, PathSettings.scalaCheck.path) var LATEST_LIB: String = origmanager.LATEST_LIB + var LATEST_REFLECT: String = origmanager.LATEST_REFLECT var LATEST_COMP: String = origmanager.LATEST_COMP var LATEST_PARTEST: String = origmanager.LATEST_PARTEST var LATEST_ACTORS: String = origmanager.LATEST_ACTORS @@ -323,6 +324,7 @@ class Worker(val fileManager: FileManager, params: TestRunParams) extends Actor "-Djava.library.path="+logFile.getParentFile.getAbsolutePath, "-Dpartest.output="+outDir.getAbsolutePath, "-Dpartest.lib="+LATEST_LIB, + "-Dpartest.reflect="+LATEST_REFLECT, "-Dpartest.cwd="+outDir.getParent, "-Dpartest.test-path="+testFullPath, "-Dpartest.testname="+fileBase, diff --git a/src/reflect/scala/reflect/api/AnnotationInfos.scala b/src/reflect/scala/reflect/api/AnnotationInfos.scala new file mode 100644 index 0000000000..d9f35024d9 --- /dev/null +++ b/src/reflect/scala/reflect/api/AnnotationInfos.scala @@ -0,0 +1,27 @@ +package scala.reflect +package api + +trait AnnotationInfos extends base.AnnotationInfos { self: Universe => + + override type AnnotationInfo >: Null <: AnyRef with AnnotationInfoApi + trait AnnotationInfoApi { + def atp: Type + def args: List[Tree] + def assocs: List[(Name, ClassfileAnnotArg)] + } + + override type LiteralAnnotArg >: Null <: ClassfileAnnotArg with LiteralAnnotArgApi + trait LiteralAnnotArgApi { + def const: Constant + } + + override type ArrayAnnotArg >: Null <: ClassfileAnnotArg with ArrayAnnotArgApi + trait ArrayAnnotArgApi { + def args: Array[ClassfileAnnotArg] + } + + override type NestedAnnotArg >: Null <: ClassfileAnnotArg with NestedAnnotArgApi + trait NestedAnnotArgApi { + def annInfo: AnnotationInfo + } +}
\ No newline at end of file diff --git a/src/library/scala/reflect/api/Constants.scala b/src/reflect/scala/reflect/api/Constants.scala index 42a0fa8a27..7862ab0d25 100755..100644 --- a/src/library/scala/reflect/api/Constants.scala +++ b/src/reflect/scala/reflect/api/Constants.scala @@ -6,13 +6,12 @@ package scala.reflect package api -import java.lang.Integer.toOctalString -import annotation.switch - -trait Constants { +trait Constants extends base.Constants { self: Universe => - abstract class AbsConstant { + override type Constant >: Null <: AnyRef with ConstantApi + + abstract class ConstantApi { val value: Any def tpe: Type def isNaN: Boolean @@ -31,13 +30,4 @@ trait Constants { def convertTo(pt: Type): Constant } - - type Constant <: AbsConstant - - val Constant: ConstantExtractor - - abstract class ConstantExtractor { - def apply(const: Any): Constant - def unapply(arg: Constant): Option[Any] - } } diff --git a/src/reflect/scala/reflect/api/Exprs.scala b/src/reflect/scala/reflect/api/Exprs.scala new file mode 100644 index 0000000000..8b2a3b4ea8 --- /dev/null +++ b/src/reflect/scala/reflect/api/Exprs.scala @@ -0,0 +1,62 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2011 LAMP/EPFL + * @author Martin Odersky + */ + +package scala.reflect +package api + +import scala.reflect.base.TreeCreator + +trait Exprs { self: Universe => + + /** An expression tree tagged with its type */ + trait Expr[+T] extends Equals with Serializable { + val mirror: Mirror + def in[U <: Universe with Singleton](otherMirror: MirrorOf[U]): U # Expr[T] + + def tree: Tree + def staticTpe: Type + def actualTpe: Type + + def splice: T + val value: T + + /** case class accessories */ + override def canEqual(x: Any) = x.isInstanceOf[Expr[_]] + override def equals(x: Any) = x.isInstanceOf[Expr[_]] && this.mirror == x.asInstanceOf[Expr[_]].mirror && this.tree == x.asInstanceOf[Expr[_]].tree + override def hashCode = mirror.hashCode * 31 + tree.hashCode + override def toString = "Expr["+staticTpe+"]("+tree+")" + } + + object Expr { + def apply[T: AbsTypeTag](mirror: MirrorOf[self.type], treec: TreeCreator): Expr[T] = new ExprImpl[T](mirror.asInstanceOf[Mirror], treec) + def unapply[T](expr: Expr[T]): Option[Tree] = Some(expr.tree) + } + + private class ExprImpl[+T: AbsTypeTag](val mirror: Mirror, val treec: TreeCreator) extends Expr[T] { + def in[U <: Universe with Singleton](otherMirror: MirrorOf[U]): U # Expr[T] = { + val otherMirror1 = otherMirror.asInstanceOf[MirrorOf[otherMirror.universe.type]] + val tag1 = (implicitly[AbsTypeTag[T]] in otherMirror).asInstanceOf[otherMirror.universe.AbsTypeTag[T]] + otherMirror.universe.Expr[T](otherMirror1, treec)(tag1) + } + + lazy val tree: Tree = treec[Exprs.this.type](mirror) + // [Eugene++] this is important + // !!! remove when we have improved type inference for singletons + // search for .type] to find other instances + lazy val staticTpe: Type = implicitly[AbsTypeTag[T]].tpe + def actualTpe: Type = tree.tpe + + def splice: T = throw new UnsupportedOperationException(""" + |the function you're calling has not been spliced by the compiler. + |this means there is a cross-stage evaluation involved, and it needs to be invoked explicitly. + |if you're sure this is not an oversight, add scala-compiler.jar to the classpath, + |import `scala.tools.reflect.Eval` and call `<your expr>.eval` instead.""".trim.stripMargin) + lazy val value: T = throw new UnsupportedOperationException(""" + |the value you're calling is only meant to be used in cross-stage path-dependent types. + |if you want to splice the underlying expression, use `<your expr>.splice`. + |if you want to get a value of the underlying expression, add scala-compiler.jar to the classpath, + |import `scala.tools.reflect.Eval` and call `<your expr>.eval` instead.""".trim.stripMargin) + } +}
\ No newline at end of file diff --git a/src/reflect/scala/reflect/api/FlagSets.scala b/src/reflect/scala/reflect/api/FlagSets.scala new file mode 100644 index 0000000000..969176d641 --- /dev/null +++ b/src/reflect/scala/reflect/api/FlagSets.scala @@ -0,0 +1,112 @@ +package scala.reflect +package api + +import scala.language.implicitConversions + +trait FlagSets { self: Universe => + + type FlagSet + + trait FlagOps extends Any { + def | (right: FlagSet): FlagSet + def & (right: FlagSet): FlagSet + def containsAll (right: FlagSet): Boolean + } + + implicit def addFlagOps(left: FlagSet): FlagOps + + val Flag: FlagValues + + type FlagValues >: Null <: FlagValuesApi + + // [Eugene++] any other flags we would like to expose? + + trait FlagValuesApi { + + /** Flag indicating that symbol or tree represents a trait */ + val TRAIT: FlagSet + + /** Flag indicating that symbol or tree represents a module or its internal module class */ + val MODULE: FlagSet + + /** Flag indicating that symbol or tree represents a mutable variable */ + val MUTABLE: FlagSet + + /** Flag indicating that symbol or tree represents a package or its internal package class */ + val PACKAGE: FlagSet + + /** Flag indicating that symbol or tree represents a method */ + val METHOD: FlagSet + + /** Flag indicating that symbol or tree represents a macro definition. */ + val MACRO: FlagSet + + /** Flag indicating that symbol or tree represents an abstract type, method, or value */ + val DEFERRED: FlagSet + + /** Flag indicating that symbol or tree represents an abstract class */ + val ABSTRACT: FlagSet + + /** Flag indicating that symbol or tree has `final` modifier set */ + val FINAL: FlagSet + + /** Flag indicating that symbol or tree has `sealed` modifier set */ + val SEALED: FlagSet + + /** Flag indicating that symbol or tree has `implicit` modifier set */ + val IMPLICIT: FlagSet + + /** Flag indicating that symbol or tree has `lazy` modifier set */ + val LAZY: FlagSet + + /** Flag indicating that symbol or tree has `override` modifier set */ + val OVERRIDE: FlagSet + + /** Flag indicating that symbol or tree has `private` modifier set */ + val PRIVATE: FlagSet + + /** Flag indicating that symbol or tree has `protected` modifier set */ + val PROTECTED: FlagSet + + /** Flag indicating that symbol or tree has `case` modifier set */ + val CASE: FlagSet + + /** Flag indicating that symbol or tree has `abstract` and `override` modifiers set */ + val ABSOVERRIDE: FlagSet + + /** Flag indicating that symbol or tree represents a by-name parameter */ + val BYNAMEPARAM: FlagSet + + /** Flag indicating that symbol or tree represents a class or parameter. + * Both type and value parameters carry the flag. */ + val PARAM: FlagSet + + /** Flag indicating that symbol or tree represents a field of a class + * that was generated from a parameter of that class */ + val PARAMACCESSOR: FlagSet + + /** Flag indicating that symbol or tree represents a field of a case class + * that corresponds to a parameter in the first parameter list of the + * primary constructor of that class */ + val CASEACCESSOR: FlagSet + + /** Flag indicating that symbol or tree represents a contravariant + * type parameter (marked with `+`). */ + val COVARIANT: FlagSet + + /** Flag indicating that symbol or tree represents a contravariant + * type parameter (marked with `-`). */ + val CONTRAVARIANT: FlagSet + + /** Flag indicating that parameter has a default value */ + val DEFAULTPARAM: FlagSet + + /** Flag indicating that trait has neither method implementations nor fields. + * This means the trait can be represented as a Java interface. */ + val INTERFACE: FlagSet + + def union(flags: FlagSet*): FlagSet + def intersection(flag: FlagSet*): FlagSet + def containsAll(superset: FlagSet, subset: FlagSet): Boolean + } +} diff --git a/src/library/scala/reflect/api/FrontEnds.scala b/src/reflect/scala/reflect/api/FrontEnds.scala index 2c1f3feff6..a201b83444 100644 --- a/src/library/scala/reflect/api/FrontEnds.scala +++ b/src/reflect/scala/reflect/api/FrontEnds.scala @@ -1,7 +1,11 @@ package scala.reflect package api -trait FrontEnds { self: Universe => +// [Martin to Eugene] Todo: Needs to be evicted from API +// [Eugene++ to Martin] but how? we need them for macros +trait FrontEnds { + + type Position >: Null trait FrontEnd { object severity extends Enumeration diff --git a/src/library/scala/reflect/api/Importers.scala b/src/reflect/scala/reflect/api/Importers.scala index 1d8890b7db..69d6414f4f 100644 --- a/src/library/scala/reflect/api/Importers.scala +++ b/src/reflect/scala/reflect/api/Importers.scala @@ -1,6 +1,8 @@ package scala.reflect package api +// [Martin] Importers need to be made mirror aware. +// [Eugene++] this is important trait Importers { self: Universe => def mkImporter(from0: Universe): Importer { val from: from0.type } diff --git a/src/reflect/scala/reflect/api/JavaUniverse.scala b/src/reflect/scala/reflect/api/JavaUniverse.scala new file mode 100644 index 0000000000..8bf62a357c --- /dev/null +++ b/src/reflect/scala/reflect/api/JavaUniverse.scala @@ -0,0 +1,19 @@ +package scala.reflect +package api + +// [Martin] Moved to compiler because it needs to see runtime.Universe +// The two will be united in scala-reflect anyway. +trait JavaUniverse extends Universe with Mirrors with TagInterop { self => + + type RuntimeClass = java.lang.Class[_] + + override type Mirror >: Null <: JavaMirror + + trait JavaMirror extends MirrorOf[self.type] with RuntimeMirror { + val classLoader: ClassLoader + override def toString = s"JavaMirror with ${runtime.ReflectionUtils.show(classLoader)}" + } + + def runtimeMirror(cl: ClassLoader): Mirror +} + diff --git a/src/reflect/scala/reflect/api/Mirrors.scala b/src/reflect/scala/reflect/api/Mirrors.scala new file mode 100644 index 0000000000..348ab3656b --- /dev/null +++ b/src/reflect/scala/reflect/api/Mirrors.scala @@ -0,0 +1,208 @@ +package scala.reflect +package api + +trait Mirrors { self: Universe => + + type RuntimeClass >: Null + + // [Eugene] also, it might make sense to provide shortcuts for the API + // + // for example, right now to invoke the same method for several different instances, you need: + // 1) get the method symbol + // 2) get the instance mirror for every instance + // 3) call reflectMethod on the instance mirrors for every instance + // 4) call apply for every instance (okay, this can be united with step #3, but still) + // + // I have several suggestions that we can discuss later: + // 1) For every `reflectXXX(sym: Symbol): XXXMirror`, add `reflectXXX(name: String, types: Type*): XXXMirror` and `reflectXXXs(): List[XXXMirror]` + // 2) Provide a way to skip obtaining InstanceMirror (step #2 in the outline provided above) + + // [Eugene] another improvement would be have mirrors reproduce the structure of the reflection domain + // e.g. a ClassMirror could also have a list of fields, methods, constructors and so on + // read up more on the proposed design in "Reflecting Scala" by Y. Coppel + + /** A mirror that reflects a runtime value */ + trait InstanceMirror { + + /** The instance value reflected by this mirror */ + def instance: Any + + /** The symbol corresponding to the run-time class of the reflected instance. */ + def symbol: ClassSymbol + + /** Get value of field in reflected instance. + * @field A field symbol that should represent a field of the instance class. + * @return The value associated with that field in the reflected instance + * @throws ??? + */ + def reflectField(field: TermSymbol): FieldMirror + + /** Invokes a method on the reflected instance. + * @param meth A method symbol that should represent a method of the instance class + * @param args The arguments to pass to the method + * @return The result of invoking `meth(args)` on the reflected instance. + * @throws ??? + */ + def reflectMethod(method: MethodSymbol): MethodMirror + + /** .. */ + def reflectClass(cls: ClassSymbol): ClassMirror + + /** .. */ + def reflectModule(mod: ModuleSymbol): ModuleMirror + } + + /** A mirror that reflects a field */ + trait FieldMirror { + + /** The object containing the field */ + def receiver: AnyRef + + /** The field symbol representing the field */ + def symbol: TermSymbol + + /** Retrieves the value stored in the field */ + def get: Any + + /** Updates the value stored in the field */ + def set(value: Any): Unit + } + + /** A mirror that reflects a method handle */ + trait MethodMirror { + + /** The receiver object of the method */ + def receiver: AnyRef + + /** The method symbol representing the method */ + def symbol: MethodSymbol + + /** The result of applying the method to the given arguments */ + // [Eugene+++] If it's a constructor, it should account for inner classes + def apply(args: Any*): Any + } + + /** A mirror that reflects the instance or static parts of a runtime class */ + trait TemplateMirror { + + /** The runtime class reflected by this mirror */ + def runtimeClass: RuntimeClass + + /** True if the mirror represents the static part + * if a runtime class or the companion object of a Scala class. + * One has: + * + * this.isStatic == this.isInstanceOf[ModuleMirror] + * !this.isStatic == this.isInstanceOf[ClassMirror] + */ + def isStatic: Boolean + + /** The Scala symbol corresponding to the reflected runtime class or module. */ + def symbol: Symbol + + /** Optionally, the mirror of the companion reflected by this mirror. + * If this mirror reflects a Scala object, the mirror for the companion class, or None + * if the mirror represents a Scala object that comes without a class. + * Otherwise, if the mirror represents the static part of a runtime class, the + * mirror representing the instance part of the same class. + * Otherwise, if the mirror represents a Scala instance class, the mirror for the companion + * object of that class, or None if no such object exists. + * Otherwise, if the mirror represents a runtime instance class, a mirror representing the static + * part of the same class. + */ + def companion: Option[TemplateMirror] + } + + /** A mirror that reflects a Scala object definition or the static parts of a runtime class */ + trait ModuleMirror extends TemplateMirror { + + /** The Scala module symbol corresponding to the reflected module. */ + override def symbol: ModuleSymbol + + /** If the reflected runtime class corresponds to a Scala object definition, + * returns the single instance representing that object. + * If this mirror reflects the static part of a runtime class, returns `null`. + */ + def instance: Any + + /** Optionally, the mirror of the companion class if the object reflected by this mirror. + * If this mirror reflects a Scala object, the mirror for the companion class, or None + * if the mirror represents a Scala object that comes without a class. + * Otherwise, if the mirror represents the static part of a runtime class, the + * mirror representing the instance part of the same class. + */ + def companion: Option[ClassMirror] + } + + /** A mirror that reflects the instance parts of a runtime class */ + trait ClassMirror extends TemplateMirror { + + /** The Scala class symbol corresponding to the reflected class. */ + override def symbol: ClassSymbol + + /** Returns a fresh instance of by invoking that constructor. + * @throws InstantiationException if the class does not have a public + * constructor with an empty parameter list. + * @throws IllegalAccessException if the class or its constructor is not accessible. + * @throws ExceptionInInitializerError if the initialization of the constructor fails. + * @throws SecurityException if creating a new instance is not permitted. + */ + def reflectConstructor(constructor: MethodSymbol): MethodMirror + + /** Optionally, the mirror of the companion object of the class reflected by this mirror. + * If this mirror represents a Scala instance class, the mirror for the companion + * object of that class, or None if no such object exists. + * Otherwise, if the mirror represents a runtime instance class, a mirror representing the static + * part of the same class. + */ + def companion: Option[ModuleMirror] + } + + /** A mirror that reflects instances and static classes */ + trait ReflectiveMirror extends MirrorOf[Mirrors.this.type] { + + /** A reflective mirror for the given object + * @param obj An arbitrary value + * @return The mirror for `obj`. + */ + def reflect(obj: Any): InstanceMirror + + /** .. */ + def reflectClass(cls: ClassSymbol): ClassMirror + + /** .. */ + def reflectModule(mod: ModuleSymbol): ModuleMirror + } + + /** The API of a mirror for a reflective universe */ + trait RuntimeMirror extends ReflectiveMirror { self => + + /** Maps a Scala type to the corresponding Java class object + */ + def runtimeClass(tpe: Type): RuntimeClass + + /** Maps a Scala class symbol to the corresponding Java class object + * @throws ClassNotFoundException if there is no Java class + * corresponding to the given Scala class symbol. + * Note: If the Scala symbol is ArrayClass, a ClassNotFound exception is thrown + * because there is no unique Java class corresponding to a Scala generic array + */ + def runtimeClass(cls: ClassSymbol): RuntimeClass + + /** A class symbol for the specified runtime class. + * @return The class symbol for the runtime class in the current class loader. + * @throws java.lang.ClassNotFoundException if no class with that name exists + * @throws scala.reflect.internal.MissingRequirementError if no corresponding symbol exists + * to do: throws anything else? + */ + def classSymbol(rtcls: RuntimeClass): ClassSymbol + + /** A module symbol for the specified runtime class. + * @return The module symbol for the runtime class in the current class loader. + * @throws java.lang.ClassNotFoundException if no class with that name exists + * @throws scala.reflect.internal.MissingRequirementError if no corresponding symbol exists + * to do: throws anything else? + */ + def moduleSymbol(rtcls: RuntimeClass): ModuleSymbol + } +} diff --git a/src/reflect/scala/reflect/api/Names.scala b/src/reflect/scala/reflect/api/Names.scala new file mode 100644 index 0000000000..222ee5024b --- /dev/null +++ b/src/reflect/scala/reflect/api/Names.scala @@ -0,0 +1,44 @@ +package scala.reflect +package api + +/** A trait that manages names. + * A name is a string in one of two name universes: terms and types. + * The same string can be a name in both universes. + * Two names are equal if they represent the same string and they are + * members of the same universe. + * + * Names are interned. That is, for two names `name11 and `name2`, + * `name1 == name2` implies `name1 eq name2`. + */ +trait Names extends base.Names { + + /** The abstract type of names */ + type Name >: Null <: NameApi + + /** The extended API of names that's supported on reflect mirror via an + * implicit conversion in reflect.ops + */ + abstract class NameApi extends NameBase { + + // [Eugene++] this functionality should be in base + // this is because stuff will be reified in mangled state, and people will need a way to figure it out + + /** Replaces all occurrences of \$op_names in this name by corresponding operator symbols. + * Example: `foo_\$plus\$eq` becomes `foo_+=` + */ + def decoded: String + + /** Replaces all occurrences of operator symbols in this name by corresponding \$op_names. + * Example: `foo_+=` becomes `foo_\$plus\$eq`. + */ + def encoded: String + + /** The decoded name, still represented as a name. + */ + def decodedName: Name + + /** The encoded name, still represented as a name. + */ + def encodedName: Name + } +} diff --git a/src/library/scala/reflect/api/Positions.scala b/src/reflect/scala/reflect/api/Positions.scala index 8f01e0ced1..9d3d90d9f8 100644 --- a/src/library/scala/reflect/api/Positions.scala +++ b/src/reflect/scala/reflect/api/Positions.scala @@ -1,16 +1,11 @@ package scala.reflect package api -trait Positions { +trait Positions extends base.Positions { self: Universe => - // [Eugene] in quite a lot of situations (mostly related to error reporting) we need positions in the API - // however it seems that neither runtime compilation, nor macros need facilities to create positions from scratch - // both emit ASTs, which can be automatically transformed into synthetic sources and assigned with synthetic positions - // hence I added possibilities to inspect everything we can, but add any position factories - // this simplified a lot of things, the biggest of them is that we don't need to expose SourceFile/AbstractFile - type Position <: scala.reflect.api.Position - val NoPosition: Position + /** .. */ + type Position >: Null <: PositionApi { type Pos = Position } /** A position that wraps a set of trees. * The point of the wrapping position is the point of the default position. @@ -31,11 +26,8 @@ trait Positions { * shortening the range or assigning TransparentPositions * to some of the nodes in `tree`. */ - def ensureNonOverlapping(tree: Tree, others: List[Tree]) - - /** Assigns a given position to all position-less nodes of a given AST. - */ - def atPos[T <: Tree](pos: Position)(tree: T): T + //def ensureNonOverlapping(tree: Tree, others: List[Tree]) + // [Eugene++] can this method be of use for macros? } /** The Position class and its subclasses represent positions of ASTs and symbols. @@ -82,7 +74,9 @@ trait Positions { * pos.makeTransparent converts an opaque range position into a transparent one. * returns all other positions unchanged. */ -trait Position extends Attachment { +trait PositionApi extends Attachments { + + type Pos >: Null <: PositionApi /** Java file corresponding to the source file of this position. */ @@ -97,17 +91,17 @@ trait Position extends Attachment { */ def isDefined: Boolean - /** Is this position a transparent position? */ - def isTransparent: Boolean - /** Is this position a range position? */ def isRange: Boolean + /** Is this position a transparent position? */ + def isTransparent: Boolean + /** Is this position a non-transparent range position? */ def isOpaqueRange: Boolean /** if opaque range, make this position transparent */ - def makeTransparent: Position + def makeTransparent: Pos /** The start of the position's range, error if not a range position */ def start: Int @@ -128,73 +122,73 @@ trait Position extends Attachment { def endOrPoint: Int /** The same position with a different start value (if a range) */ - def withStart(off: Int): Position + def withStart(off: Int): Pos /** The same position with a different end value (if a range) */ - def withEnd(off: Int): Position + def withEnd(off: Int): Pos /** The same position with a different point value (if a range or offset) */ - def withPoint(off: Int): Position + def withPoint(off: Int): Pos /** If this is a range, the union with the other range, with the point of this position. * Otherwise, this position */ - def union(pos: Position): Position + def union(pos: Pos): Pos - /** If this is a range position, the offset position of its start. + /** If this is a range position, the offset position of its point. * Otherwise the position itself */ - def focusStart: Position + def focus: Pos - /** If this is a range position, the offset position of its point. + /** If this is a range position, the offset position of its start. * Otherwise the position itself */ - def focus: Position + def focusStart: Pos /** If this is a range position, the offset position of its end. * Otherwise the position itself */ - def focusEnd: Position + def focusEnd: Pos /** Does this position include the given position `pos`. * This holds if `this` is a range position and its range [start..end] * is the same or covers the range of the given position, which may or may not be a range position. */ - def includes(pos: Position): Boolean + def includes(pos: Pos): Boolean /** Does this position properly include the given position `pos` ("properly" meaning their * ranges are not the same)? */ - def properlyIncludes(pos: Position): Boolean + def properlyIncludes(pos: Pos): Boolean /** Does this position precede that position? * This holds if both positions are defined and the end point of this position * is not larger than the start point of the given position. */ - def precedes(pos: Position): Boolean + def precedes(pos: Pos): Boolean /** Does this position properly precede the given position `pos` ("properly" meaning their ranges * do not share a common point). */ - def properlyPrecedes(pos: Position): Boolean + def properlyPrecedes(pos: Pos): Boolean /** Does this position overlap with that position? * This holds if both positions are ranges and there is an interval of * non-zero length that is shared by both position ranges. */ - def overlaps(pos: Position): Boolean + def overlaps(pos: Pos): Boolean /** Does this position cover the same range as that position? * Holds only if both position are ranges */ - def sameRange(pos: Position): Boolean + def sameRange(pos: Pos): Boolean def line: Int def column: Int /** Convert this to a position around `point` that spans a single source line */ - def toSingleLine: Position + def toSingleLine: Pos def lineContent: String diff --git a/src/reflect/scala/reflect/api/StandardDefinitions.scala b/src/reflect/scala/reflect/api/StandardDefinitions.scala new file mode 100644 index 0000000000..c2a89f92dd --- /dev/null +++ b/src/reflect/scala/reflect/api/StandardDefinitions.scala @@ -0,0 +1,48 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2011 LAMP/EPFL + * @author Martin Odersky + */ +package scala.reflect +package api + +trait StandardDefinitions extends base.StandardDefinitions { + self: Universe => + + val definitions: DefinitionsApi + + trait DefinitionsApi extends DefinitionsBase { + def JavaLangPackageClass: ClassSymbol + def JavaLangPackage: ModuleSymbol + def ArrayModule: ModuleSymbol + def ArrayModule_overloadedApply: TermSymbol // todo. fix the bug in Definitions.getMemberMethod + def Array_apply: TermSymbol // todo. fix the bug in Definitions.getMemberMethod + def Array_clone: TermSymbol // todo. fix the bug in Definitions.getMemberMethod + def Array_length: TermSymbol // todo. fix the bug in Definitions.getMemberMethod + def Array_update: TermSymbol // todo. fix the bug in Definitions.getMemberMethod + def ByNameParamClass: ClassSymbol + def ConsClass: ClassSymbol + def FunctionClass : Array[ClassSymbol] + def IterableClass: ClassSymbol + def IteratorClass: ClassSymbol + def IteratorModule: ModuleSymbol + def Iterator_apply: TermSymbol // todo. fix the bug in Definitions.getMemberMethod + def JavaRepeatedParamClass: ClassSymbol + def ListModule: ModuleSymbol + def List_apply: TermSymbol // todo. fix the bug in Definitions.getMemberMethod + def NilModule: ModuleSymbol + def NoneModule: ModuleSymbol + def OptionClass: ClassSymbol + def ProductClass : Array[ClassSymbol] + def RepeatedParamClass: ClassSymbol + def SeqClass: ClassSymbol + def SeqModule: ModuleSymbol + def SomeClass: ClassSymbol + def SomeModule: ModuleSymbol + def StringBuilderClass: ClassSymbol + def SymbolClass : ClassSymbol + def TraversableClass: ClassSymbol + def TupleClass: Array[Symbol] // cannot make it Array[ClassSymbol], because TupleClass(0) is supposed to be NoSymbol. weird + def ScalaPrimitiveValueClasses: List[ClassSymbol] + def ScalaNumericValueClasses: List[ClassSymbol] + } +} diff --git a/src/library/scala/reflect/api/StandardNames.scala b/src/reflect/scala/reflect/api/StandardNames.scala index a17ea216f7..9ec66b8531 100644 --- a/src/library/scala/reflect/api/StandardNames.scala +++ b/src/reflect/scala/reflect/api/StandardNames.scala @@ -2,36 +2,30 @@ * Copyright 2005-2011 LAMP/EPFL * @author Martin Odersky */ - package scala.reflect package api -trait StandardNames { +trait StandardNames extends base.StandardNames { self: Universe => - val nme: AbsTermNames - val tpnme: AbsTypeNames - - trait AbsNames { - type NameType <: Name + val nme: TermNamesApi + val tpnme: TypeNamesApi + trait NamesApi extends NamesBase { val ANON_CLASS_NAME: NameType val ANON_FUN_NAME: NameType val EMPTY: NameType - val EMPTY_PACKAGE_NAME: NameType val ERROR: NameType val IMPORT: NameType val MODULE_VAR_SUFFIX: NameType - val NO_NAME: NameType val PACKAGE: NameType val ROOT: NameType val SPECIALIZED_SUFFIX: NameType - val WILDCARD: NameType def flattenedName(segments: Name*): NameType } - trait AbsTermNames extends AbsNames { + trait TermNamesApi extends NamesApi with TermNamesBase { val EXPAND_SEPARATOR_STRING: String val IMPL_CLASS_SUFFIX: String val INTERPRETER_IMPORT_WRAPPER: String @@ -50,16 +44,20 @@ trait StandardNames { val TRAIT_SETTER_SEPARATOR_STRING: String val ANYNAME: TermName - val CONSTRUCTOR: TermName val FAKE_LOCAL_THIS: TermName val INITIALIZER: TermName val LAZY_LOCAL: TermName - val MIRROR_FREE_PREFIX: TermName - val MIRROR_FREE_THIS_SUFFIX: TermName - val MIRROR_FREE_VALUE_SUFFIX: TermName - val MIRROR_PREFIX: TermName - val MIRROR_SHORT: TermName - val MIRROR_SYMDEF_PREFIX: TermName + val UNIVERSE_BUILD: NameType + val UNIVERSE_BUILD_PREFIX: NameType + val UNIVERSE_PREFIX: NameType + val UNIVERSE_SHORT: NameType + val MIRROR_PREFIX: NameType + val MIRROR_SHORT: NameType + val MIRROR_UNTYPED: NameType + val REIFY_FREE_PREFIX: NameType + val REIFY_FREE_THIS_SUFFIX: NameType + val REIFY_FREE_VALUE_SUFFIX: NameType + val REIFY_SYMDEF_PREFIX: NameType val MIXIN_CONSTRUCTOR: TermName val MODULE_INSTANCE_FIELD: TermName val OUTER: TermName @@ -146,7 +144,7 @@ trait StandardNames { def splitSpecializedName(name: Name): (Name, String, String) } - trait AbsTypeNames extends AbsNames { + trait TypeNamesApi extends NamesApi with TypeNamesBase { val BYNAME_PARAM_CLASS_NAME: TypeName val EQUALS_PATTERN_NAME: TypeName val JAVA_REPEATED_PARAM_CLASS_NAME: TypeName @@ -154,6 +152,8 @@ trait StandardNames { val REFINE_CLASS_NAME: TypeName val REPEATED_PARAM_CLASS_NAME: TypeName val WILDCARD_STAR: TypeName + val REIFY_TYPECREATOR_PREFIX: NameType + val REIFY_TREECREATOR_PREFIX: NameType def dropSingletonName(name: Name): TypeName def implClassName(name: Name): TypeName diff --git a/src/library/scala/reflect/api/Symbols.scala b/src/reflect/scala/reflect/api/Symbols.scala index 32faee2512..1d266dc778 100755..100644 --- a/src/library/scala/reflect/api/Symbols.scala +++ b/src/reflect/scala/reflect/api/Symbols.scala @@ -1,149 +1,55 @@ package scala.reflect package api -trait Symbols { self: Universe => - - type Symbol >: Null <: AbsSymbol - type TypeSymbol <: Symbol with TypeSymbolApi - type TermSymbol <: Symbol with TermSymbolApi - type MethodSymbol <: TermSymbol with MethodSymbolApi - type ModuleSymbol <: TermSymbol with ModuleSymbolApi - type PackageSymbol <: ModuleSymbol with PackageSymbolApi - type ClassSymbol <: TypeSymbol with ClassSymbolApi - - val NoSymbol: Symbol - - trait TypeSymbolApi { - self: TypeSymbol => - - def name: TypeName - } - trait TermSymbolApi { - self: TermSymbol => - - def name: TermName - } - trait MethodSymbolApi extends TermSymbolApi { - self: MethodSymbol => - } - trait ClassSymbolApi extends TypeSymbolApi { - self: ClassSymbol => - } - trait ModuleSymbolApi extends TermSymbolApi { - self: ModuleSymbol => - } - trait PackageSymbolApi extends ModuleSymbolApi { - self: PackageSymbol => - } - - // I intend to pull everything in here out of the public API. - trait AbsSymbolInternal { - this: Symbol => - - /** A fresh symbol with given name `name`, position `pos` and flags `flags` that has - * the current symbol as its owner. - */ - def newNestedSymbol(name: Name, pos: Position, flags: Long, isClass: Boolean): Symbol - // needed by LiftCode !!! not enough reason to have in the api - - /** Low-level operation to set the symbol's flags - * @return the symbol itself - */ - def setInternalFlags(flags: Long): this.type - // needed by LiftCode !!! not enough reason to have in the api - - /** Set symbol's type signature to given type - * @return the symbol itself - */ - def setTypeSignature(tpe: Type): this.type - // needed by LiftCode !!! not enough reason to have in the api - - /** Set symbol's annotations to given annotations `annots`. - */ - def setAnnotations(annots: AnnotationInfo*): this.type - // needed by LiftCode !!! not enough reason to have in the api - - /** Does this symbol represent the definition of a skolem? - * Skolems are used during typechecking to represent type parameters viewed from inside their scopes. - * If yes, `isType` is also guaranteed to be true. - */ - def isSkolem : Boolean - - /** Does this symbol represent a free type captured by reification? - */ - // needed for ones who wish to inspect reified trees - def isFreeType : Boolean - - /** The type signature of this symbol. - * Note if the symbol is a member of a class, one almost always is interested - * in `typeSignatureIn` with a site type instead. - */ - def typeSignature: Type // !!! Since one should almost never use this, let's give it a different name. - - /** A type reference that refers to this type symbol - * Note if symbol is a member of a class, one almost always is interested - * in `asTypeIn` with a site type instead. - * - * Example: Given a class declaration `class C[T] { ... } `, that generates a symbol - * `C`. Then `C.asType` is the type `C[T]`. - * - * By contrast, `C.typeSignature` would be a type signature of form - * `PolyType(ClassInfoType(...))` that describes type parameters, value - * parameters, parent types, and members of `C`. - */ - def asType: Type // !!! Same as typeSignature. - - /** The kind of this symbol; used for debugging */ - def kind: String +trait Symbols extends base.Symbols { self: Universe => + + override type Symbol >: Null <: SymbolApi + override type TypeSymbol >: Null <: Symbol with TypeSymbolApi + override type TermSymbol >: Null <: Symbol with TermSymbolApi + override type MethodSymbol >: Null <: TermSymbol with MethodSymbolApi + override type ModuleSymbol >: Null <: TermSymbol with ModuleSymbolApi + override type ClassSymbol >: Null <: TypeSymbol with ClassSymbolApi + override type FreeTermSymbol >: Null <: TermSymbol with FreeTermSymbolApi + override type FreeTypeSymbol >: Null <: TypeSymbol with FreeTypeSymbolApi + + trait HasFlagsApi { + def flags: FlagSet + def hasFlag(fs: FlagSet): Boolean + def hasAllFlags(fs: FlagSet): Boolean + def flagString: String } - trait AbsSymbol extends AbsSymbolInternal { - this: Symbol => + /** The API of symbols */ + trait SymbolApi extends SymbolBase with HasFlagsApi { this: Symbol => /** The position of this symbol */ def pos: Position - /** The modifiers of this symbol - */ - def modifiers: Set[Modifier] - - /** Does this symbol have given modifier? - */ - def hasModifier(mod: Modifier): Boolean - /** A list of annotations attached to this Symbol. */ - def annotations: List[self.AnnotationInfo] + // [Eugene++] we cannot expose the `annotations` method because it doesn't auto-initialize a symbol (see SI-5423) + // there was an idea to use the `isCompilerUniverse` flag and auto-initialize symbols in `annotations` whenever this flag is false + // but it doesn't work, because the unpickler (that is shared between reflective universes and global universes) is very picky about initialization + // scala.reflect.internal.Types$TypeError: bad reference while unpickling scala.collection.immutable.Nil: type Nothing not found in scala.type not found. + // at scala.reflect.internal.pickling.UnPickler$Scan.toTypeError(UnPickler.scala:836) + // at scala.reflect.internal.pickling.UnPickler$Scan$LazyTypeRef.complete(UnPickler.scala:849) // auto-initialize goes boom + // at scala.reflect.internal.Symbols$Symbol.info(Symbols.scala:1140) + // at scala.reflect.internal.Symbols$Symbol.initialize(Symbols.scala:1272) // this triggers auto-initialize + // at scala.reflect.internal.Symbols$Symbol.annotations(Symbols.scala:1438) // unpickler first tries to get pre-existing annotations + // at scala.reflect.internal.Symbols$Symbol.addAnnotation(Symbols.scala:1458) // unpickler tries to add the annotation being read + // at scala.reflect.internal.pickling.UnPickler$Scan.readSymbolAnnotation(UnPickler.scala:489) // unpickler detects an annotation + // at scala.reflect.internal.pickling.UnPickler$Scan.run(UnPickler.scala:88) + // at scala.reflect.internal.pickling.UnPickler.unpickle(UnPickler.scala:37) + // at scala.reflect.runtime.JavaMirrors$JavaMirror.unpickleClass(JavaMirrors.scala:253) // unpickle from within a reflexive mirror + // def annotations: List[AnnotationInfo] + def getAnnotations: List[AnnotationInfo] /** Whether this symbol carries an annotation for which the given * symbol is its typeSymbol. */ def hasAnnotation(sym: Symbol): Boolean - /** The owner of this symbol. This is the symbol - * that directly contains the current symbol's definition. - * The `NoSymbol` symbol does not have an owner, and calling this method - * on one causes an internal error. - * The owner of the Scala root class [[scala.reflect.api.mirror.RootClass]] - * and the Scala root object [[scala.reflect.api.mirror.RootPackage]] is `NoSymbol`. - * Every other symbol has a chain of owners that ends in - * [[scala.reflect.api.mirror.RootClass]]. - */ - def owner: Symbol - - /** The name of the symbol as a member of the `Name` type. - */ - def name: Name - - /** The encoded full path name of this symbol, where outer names and inner names - * are separated by periods. - */ - def fullName: String - - /** An id number which is unique for all symbols in this universe */ - def id: Int - /** ... */ def orElse(alt: => Symbol): Symbol @@ -152,6 +58,11 @@ trait Symbols { self: Universe => */ def filter(cond: Symbol => Boolean): Symbol + /** If this is a NoSymbol, returns NoSymbol, otherwise + * returns the result of applying `f` to this symbol. + */ + def map(f: Symbol => Symbol): Symbol + /** ... */ def suchThat(cond: Symbol => Boolean): Symbol @@ -189,82 +100,57 @@ trait Symbols { self: Universe => */ def companionSymbol: Symbol - /** If symbol is an object definition, its implied associated class, - * otherwise NoSymbol + /** If this symbol is a package class, this symbol; otherwise the next enclosing + * package class, or `NoSymbol` if none exists. */ - def moduleClass: Symbol // needed for LiftCode + def enclosingPackageClass: Symbol /** If this symbol is a top-level class, this symbol; otherwise the next enclosing * top-level class, or `NoSymbol` if none exists. */ def enclosingTopLevelClass: Symbol - /** If this symbol is a class, this symbol; otherwise the next enclosing - * class, or `NoSymbol` if none exists. - */ - def enclosingClass: Symbol - - /** If this symbol is a method, this symbol; otherwise the next enclosing - * method, or `NoSymbol` if none exists. - */ - def enclosingMethod: Symbol - - /** If this symbol is a package class, this symbol; otherwise the next enclosing - * package class, or `NoSymbol` if none exists. + /** Does this symbol represent a value, i.e. not a module and not a method? + * If yes, `isTerm` is also guaranteed to be true. + * [Eugene++] I need a review of the implementation */ - def enclosingPackageClass: Symbol + def isValue: Boolean - /** Does this symbol represent the definition of term? - * Note that every symbol is either a term or a type. - * So for every symbol `sym`, either `sym.isTerm` is true - * or `sym.isType` is true. + /** Does this symbol represent a mutable value? + * If yes, `isTerm` and `isValue` are also guaranteed to be true. */ - def isTerm : Boolean + def isVariable: Boolean - /** Does this symbol represent a package? + /** Does this symbol represent the definition of a package? * If yes, `isTerm` is also guaranteed to be true. */ - def isPackage : Boolean + def isPackage: Boolean - /** Does this symbol represent the definition of method? - * If yes, `isTerm` is also guaranteed to be true. + /** Does this symbol represent a package class? + * If yes, `isClass` is also guaranteed to be true. */ - def isMethod : Boolean + def isPackageClass: Boolean /** Is this symbol an overloaded method? */ def isOverloaded : Boolean - /** Does this symbol represent a free term captured by reification? - */ - // needed for ones who wish to inspect reified trees - def isFreeTerm : Boolean - - /** Does this symbol represent the definition of type? - * Note that every symbol is either a term or a type. - * So for every symbol `sym`, either `sym.isTerm` is true - * or `sym.isType` is true. - */ - def isType : Boolean - - /** Does this symbol represent the definition of class? - * If yes, `isType` is also guaranteed to be true. - */ - def isClass : Boolean - - /** Does this symbol represent a package class? - * If yes, `isClass` is also guaranteed to be true. - */ - def isPackageClass : Boolean - /** Does this symbol represent the definition of a primitive class? * Namely, is it one of [[scala.Double]], [[scala.Float]], [[scala.Long]], [[scala.Int]], [[scala.Char]], * [[scala.Short]], [[scala.Byte]], [[scala.Unit]] or [[scala.Boolean]]? */ def isPrimitiveValueClass: Boolean + /** Does this symbol represent the definition of a numeric value class? + * Namely, is it one of [[scala.Double]], [[scala.Float]], [[scala.Long]], [[scala.Int]], [[scala.Char]], + * [[scala.Short]], [[scala.Byte]], [[scala.Unit]] or [[scala.Boolean]]? + */ + def isNumericValueClass: Boolean + /** Does this symbol represent the definition of a custom value class? * Namely, is AnyVal among its parent classes? + * TODO: Why not just have in reflect.internal? + * [Eugene++] because it's useful for macros */ def isDerivedValueClass: Boolean @@ -283,6 +169,38 @@ trait Symbols { self: Universe => */ def isExistential : Boolean + /** Does this symbol represent a free type captured by reification? + */ + def isFreeType : Boolean + + /** Does this symbol or its underlying type represent a typechecking error? + */ + def isErroneous : Boolean + + /** The type signature of this symbol seen as a member of given type `site`. + */ + def typeSignatureIn(site: Type): Type + + /** The type signature of this symbol. + * Note if the symbol is a member of a class, one almost always is interested + * in `typeSignatureIn` with a site type instead. + */ + def typeSignature: Type + + /** The string discriminator of this symbol; useful for debugging */ + def kind: String + } + + /** The API of term symbols */ + trait TermSymbolApi extends SymbolApi with HasFlagsApi with TermSymbolBase { this: TermSymbol => + /** The overloaded alternatives of this symbol */ + def alternatives: List[Symbol] + + def resolveOverloaded(pre: Type = NoPrefix, targs: Seq[Type] = List(), actuals: Seq[Type]): Symbol + } + + /** The API of type symbols */ + trait TypeSymbolApi extends SymbolApi with HasFlagsApi with TypeSymbolBase { this: TypeSymbol => /** Is the type parameter represented by this symbol contravariant? */ def isContravariant : Boolean @@ -291,40 +209,60 @@ trait Symbols { self: Universe => */ def isCovariant : Boolean - /** Does this symbol or its underlying type represent a typechecking error? - */ - def isErroneous : Boolean - - /** The type signature of this symbol seen as a member of given type `site`. + /** Does this symbol represent the definition of a skolem? + * Skolems are used during typechecking to represent type parameters viewed from inside their scopes. + * If yes, `isType` is also guaranteed to be true. */ - def typeSignatureIn(site: Type): Type + def isSkolem : Boolean /** A type reference that refers to this type symbol seen * as a member of given type `site`. */ def asTypeIn(site: Type): Type - /** The type constructor corresponding to this type symbol. - * This is different from `asType` in that type parameters - * are part of results of `asType`, but not of `asTypeConstructor`. - * - * Example: Given a class declaration `class C[T] { ... } `, that generates a symbol - * `C`. Then `C.asType` is the type `C[T]`, but `C.asTypeConstructor` is `C`. - */ - def asTypeConstructor: Type // needed by LiftCode + /** A type reference that refers to this type symbol + * Note if symbol is a member of a class, one almost always is interested + * in `asTypeIn` with a site type instead. + * + * Example: Given a class declaration `class C[T] { ... } `, that generates a symbol + * `C`. Then `C.asType` is the type `C[T]`. + * + * By contrast, `C.typeSignature` would be a type signature of form + * `PolyType(ClassInfoType(...))` that describes type parameters, value + * parameters, parent types, and members of `C`. + */ + def asType: Type // !!! Same as typeSignature. + } - /** If this symbol is a class, the type `C.this`, otherwise `NoPrefix`. - */ - def thisPrefix: Type + /** The API of method symbols */ + type MethodSymbolApi = MethodSymbolBase + /** The API of module symbols */ + type ModuleSymbolApi = ModuleSymbolBase + + /** The API of class symbols */ + trait ClassSymbolApi extends TypeSymbolApi with ClassSymbolBase { this: ClassSymbol => /** If this symbol is a class or trait, its self type, otherwise the type * of the symbol itself. */ def selfType: Type - /** The overloaded alternatives of this symbol */ - def alternatives: List[Symbol] + /** The type `C.this`, where `C` is the current class */ + def thisPrefix: Type + } - def resolveOverloaded(pre: Type = NoPrefix, targs: Seq[Type] = List(), actuals: Seq[Type]): Symbol + /** The API of free term symbols */ + trait FreeTermSymbolApi extends TermSymbolApi with FreeTermSymbolBase { this: FreeTermSymbol => + /** The place where this symbol has been spawned */ + def origin: String + + /** The valus this symbol refers to */ + def value: Any + } + + /** The API of free term symbols */ + trait FreeTypeSymbolApi extends TypeSymbolApi with FreeTypeSymbolBase { this: FreeTypeSymbol => + /** The place where this symbol has been spawned */ + def origin: String } } diff --git a/src/reflect/scala/reflect/api/TagInterop.scala b/src/reflect/scala/reflect/api/TagInterop.scala new file mode 100644 index 0000000000..f1938083b5 --- /dev/null +++ b/src/reflect/scala/reflect/api/TagInterop.scala @@ -0,0 +1,38 @@ +package scala.reflect +package api + +import scala.reflect.base.TypeCreator +import scala.reflect.base.{Universe => BaseUniverse} + +// [Martin] Moved to compiler because it needs to see runtime.Universe +// The two will be united in scala-reflect anyway. +trait TagInterop { self: JavaUniverse => + + // [Eugene++] would be great if we could approximate the interop without any mirrors + // todo. think how to implement that + + override def typeTagToManifest[T: ClassTag](mirror0: Any, tag: base.Universe # TypeTag[T]): Manifest[T] = { + // [Eugene++] implement more sophisticated logic + // Martin said it'd be okay to simply copypaste `Implicits.manifestOfType` + val mirror = mirror0.asInstanceOf[Mirror] + val runtimeClass = mirror.runtimeClass(tag.in(mirror).tpe) + Manifest.classType(runtimeClass).asInstanceOf[Manifest[T]] + } + + override def manifestToTypeTag[T](mirror0: Any, manifest: Manifest[T]): base.Universe # TypeTag[T] = + TypeTag(mirror0.asInstanceOf[Mirror], new TypeCreator { + def apply[U <: BaseUniverse with Singleton](mirror: MirrorOf[U]): U # Type = { + mirror.universe match { + case ju: JavaUniverse => + val jm = mirror.asInstanceOf[ju.Mirror] + val sym = jm.classSymbol(manifest.erasure) + val tpe = + if (manifest.typeArguments.isEmpty) sym.asType + else ju.appliedType(sym.asTypeConstructor, manifest.typeArguments map (targ => ju.manifestToTypeTag(jm, targ)) map (_.in(jm).tpe)) + tpe.asInstanceOf[U # Type] + case u => + u.manifestToTypeTag(mirror.asInstanceOf[u.Mirror], manifest).in(mirror).tpe + } + } + }) +} diff --git a/src/library/scala/reflect/api/TreePrinters.scala b/src/reflect/scala/reflect/api/TreePrinters.scala index 3d64ec8e40..08a08e7b90 100644 --- a/src/library/scala/reflect/api/TreePrinters.scala +++ b/src/reflect/scala/reflect/api/TreePrinters.scala @@ -13,7 +13,9 @@ trait TreePrinters { self: Universe => def withUniqueIds: this.type = { uniqueIds = true; this } } - def show(tree: Tree, mkPrinter: PrintWriter => TreePrinter = newTreePrinter): String = { + def show(tree: Tree): String = show(tree, newTreePrinter) + + def show(tree: Tree, mkPrinter: PrintWriter => TreePrinter): String = { val buffer = new StringWriter() val writer = new PrintWriter(buffer) val printer = mkPrinter(writer) @@ -29,13 +31,12 @@ trait TreePrinters { self: Universe => def newTreePrinter(out: PrintWriter): TreePrinter // emits more or less verbatim representation of the provided tree + // [Eugene] todo. needs to be refined + // http://groups.google.com/group/scala-user/browse_thread/thread/de5a5be2e083cf8e class RawTreePrinter(out: PrintWriter) extends TreePrinter { - val EmptyValDef = self.emptyValDef def print(args: Any*): Unit = args foreach { case EmptyTree => print("EmptyTree") - case EmptyValDef => - print("emptyValDef") case tree @ TypeTree() => print("TypeTree()") if (tree.tpe != null) @@ -45,7 +46,7 @@ trait TreePrinters { self: Universe => case Literal(Constant(s: String)) => print("Literal(Constant(\"" + s + "\"))") case tree: Tree => - print(tree.printingPrefix+"(") + print(tree.productPrefix+"(") val it = tree.productIterator while (it.hasNext) { it.next() match { @@ -69,16 +70,12 @@ trait TreePrinters { self: Universe => print(")") case mods: Modifiers => val parts = collection.mutable.ListBuffer[String]() - parts += "Set(" + mods.modifiers.map(_.sourceString).mkString(", ") + ")" - parts += "newTypeName(\"" + mods.privateWithin.toString + "\")" - parts += "List(" + mods.annotations.map{showRaw}.mkString(", ") + ")" - - var keep = 3 - if (keep == 3 && mods.annotations.isEmpty) keep -= 1 - if (keep == 2 && mods.privateWithin == EmptyTypeName) keep -= 1 - if (keep == 1 && mods.modifiers.isEmpty) keep -= 1 - - print("Modifiers(", parts.take(keep).mkString(", "), ")") + parts += mods.flagString + if (mods.privateWithin.toString.nonEmpty) + parts += "newTypeName(\"" + mods.privateWithin.toString + "\")" + if (mods.annotations.nonEmpty) + parts += mods.annotations map showRaw mkString ("List(", ", ", ")") + print(parts mkString ("Modifiers(", ", ", ")")) case name: Name => if (name.isTermName) print("newTermName(\"") else print("newTypeName(\"") print(name.toString) diff --git a/src/reflect/scala/reflect/api/Trees.scala b/src/reflect/scala/reflect/api/Trees.scala new file mode 100644 index 0000000000..2d130daa4e --- /dev/null +++ b/src/reflect/scala/reflect/api/Trees.scala @@ -0,0 +1,689 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2011 LAMP/EPFL + * @author Martin Odersky + */ +package scala.reflect +package api + +// Syncnote: Trees are currently not thread-safe. +trait Trees extends base.Trees { self: Universe => + + override type Tree >: Null <: TreeApi + + /** ... */ + trait TreeApi extends TreeBase { this: Tree => + + /** ... */ + def pos: Position + + /** ... */ + def tpe: Type + + /** Note that symbol is fixed as null at this level. In SymTrees, + * it is overridden and implemented with a var, initialized to NoSymbol. + * + * Trees which are not SymTrees but which carry symbols do so by + * overriding `def symbol` to forward it elsewhere. Examples: + * + * Super(qual, _) // has qual's symbol + * Apply(fun, args) // has fun's symbol + * TypeApply(fun, args) // has fun's symbol + * AppliedTypeTree(tpt, args) // has tpt's symbol + * TypeTree(tpe) // has tpe's typeSymbol, if tpe != null + * + * Attempting to set the symbol of a Tree which does not support + * it will induce an exception. + */ + def symbol: Symbol + + /** ... */ + def hasSymbol: Boolean + + /** Provides an alternate if tree is empty + * @param alt The alternate tree + * @return If this tree is non empty, this tree, otherwise `alt`. + */ + def orElse(alt: => Tree): Tree + + /** Apply `f` to each subtree */ + def foreach(f: Tree => Unit): Unit + + /** Find all subtrees matching predicate `p`. Same as `filter` */ + def withFilter(f: Tree => Boolean): List[Tree] + + /** Find all subtrees matching predicate `p`. Same as `withFilter` */ + def filter(f: Tree => Boolean): List[Tree] + + /** Apply `pf' to each subtree on which the function is defined and collect the results. + */ + def collect[T](pf: PartialFunction[Tree, T]): List[T] + + /** Returns optionally first tree (in a preorder traversal) which satisfies predicate `p`, + * or None if none exists. + */ + def find(p: Tree => Boolean): Option[Tree] + + /** Is there exists a part of this tree which satisfies predicate `p`? */ + def exists(p: Tree => Boolean): Boolean + + /** Do all parts of this tree satisfy predicate `p`? */ + def forAll(p: Tree => Boolean): Boolean + + /** Tests whether two trees are structurall equal. + * Note that `==` on trees is reference equality. + */ + def equalsStructure(that : Tree): Boolean + + /** The direct child trees of this tree. + * EmptyTrees are always omitted. Lists are flattened. + */ + def children: List[Tree] + + /** Extracts free term symbols from a tree that is reified or contains reified subtrees. + */ + def freeTerms: List[FreeTermSymbol] + + /** Extracts free type symbols from a tree that is reified or contains reified subtrees. + */ + def freeTypes: List[FreeTypeSymbol] + + /** Substitute symbols in `to` for corresponding occurrences of references to + * symbols `from` in this type. + */ + def substituteSymbols(from: List[Symbol], to: List[Symbol]): Tree + + /** Substitute types in `to` for corresponding occurrences of references to + * symbols `from` in this tree. + */ + def substituteTypes(from: List[Symbol], to: List[Type]): Tree + + /** Substitute given tree `to` for occurrences of nodes that represent + * `C.this`, where `C` referes to the given class `clazz`. + */ + def substituteThis(clazz: Symbol, to: Tree): Tree + + /** Make a copy of this tree, keeping all attributes, + * except that all positions are focused (so nothing + * in this tree will be found when searching by position). + */ + def duplicate: this.type + } + + override type TermTree >: Null <: Tree with TermTreeApi + + /** The API that all term trees support */ + trait TermTreeApi extends TreeApi { this: TermTree => + } + + override type TypTree >: Null <: Tree with TypTreeApi + + /** The API that all typ trees support */ + trait TypTreeApi extends TreeApi { this: TypTree => + } + + override type SymTree >: Null <: Tree with SymTreeApi + + /** The API that all sym trees support */ + trait SymTreeApi extends TreeApi { this: SymTree => + def symbol: Symbol + } + + override type NameTree >: Null <: Tree with NameTreeApi + + /** The API that all name trees support */ + trait NameTreeApi extends TreeApi { this: NameTree => + def name: Name + } + + override type RefTree >: Null <: SymTree with NameTree with RefTreeApi + + /** The API that all ref trees support */ + trait RefTreeApi extends SymTreeApi with NameTreeApi { this: RefTree => + def qualifier: Tree // empty for Idents + def name: Name + } + + override type DefTree >: Null <: SymTree with NameTree with DefTreeApi + + /** The API that all def trees support */ + trait DefTreeApi extends SymTreeApi with NameTreeApi { this: DefTree => + def name: Name + } + + override type MemberDef >: Null <: DefTree with MemberDefApi + + /** The API that all member defs support */ + trait MemberDefApi extends DefTreeApi { this: MemberDef => + def mods: Modifiers + } + + override type PackageDef >: Null <: MemberDef with PackageDefApi + + /** The API that all package defs support */ + trait PackageDefApi extends MemberDefApi { this: PackageDef => + val pid: RefTree + val stats: List[Tree] + } + + override type ImplDef >: Null <: MemberDef with ImplDefApi + + /** The API that all impl defs support */ + trait ImplDefApi extends MemberDefApi { this: ImplDef => + val impl: Template + } + + override type ClassDef >: Null <: ImplDef with ClassDefApi + + /** The API that all class defs support */ + trait ClassDefApi extends ImplDefApi { this: ClassDef => + val mods: Modifiers + val name: TypeName + val tparams: List[TypeDef] + val impl: Template + } + + override type ModuleDef >: Null <: ImplDef with ModuleDefApi + + /** The API that all module defs support */ + trait ModuleDefApi extends ImplDefApi { this: ModuleDef => + val mods: Modifiers + val name: TermName + val impl: Template + } + + override type ValOrDefDef >: Null <: MemberDef with ValOrDefDefApi + + /** The API that all val defs and def defs support */ + trait ValOrDefDefApi extends MemberDefApi { this: ValOrDefDef => + def name: Name // can't be a TermName because macros can be type names. + def tpt: Tree + def rhs: Tree + } + + override type ValDef >: Null <: ValOrDefDef with ValDefApi + + /** The API that all val defs support */ + trait ValDefApi extends ValOrDefDefApi { this: ValDef => + val mods: Modifiers + val name: TermName + val tpt: Tree + val rhs: Tree + } + + override type DefDef >: Null <: ValOrDefDef with DefDefApi + + /** The API that all def defs support */ + trait DefDefApi extends ValOrDefDefApi { this: DefDef => + val mods: Modifiers + val name: Name + val tparams: List[TypeDef] + val vparamss: List[List[ValDef]] + val tpt: Tree + val rhs: Tree + } + + override type TypeDef >: Null <: MemberDef with TypeDefApi + + /** The API that all type defs support */ + trait TypeDefApi extends MemberDefApi { this: TypeDef => + val mods: Modifiers + val name: TypeName + val tparams: List[TypeDef] + val rhs: Tree + } + + override type LabelDef >: Null <: DefTree with TermTree with LabelDefApi + + /** The API that all label defs support */ + trait LabelDefApi extends DefTreeApi with TermTreeApi { this: LabelDef => + val name: TermName + val params: List[Ident] + val rhs: Tree + } + + override type ImportSelector >: Null <: ImportSelectorApi + + /** The API that all import selectors support */ + trait ImportSelectorApi { this: ImportSelector => + val name: Name + val namePos: Int + val rename: Name + val renamePos: Int + } + + override type Import >: Null <: SymTree with ImportApi + + /** The API that all imports support */ + trait ImportApi extends SymTreeApi { this: Import => + val expr: Tree + val selectors: List[ImportSelector] + } + + override type Template >: Null <: SymTree with TemplateApi + + /** The API that all templates support */ + trait TemplateApi extends SymTreeApi { this: Template => + val parents: List[Tree] + val self: ValDef + val body: List[Tree] + } + + override type Block >: Null <: TermTree with BlockApi + + /** The API that all blocks support */ + trait BlockApi extends TermTreeApi { this: Block => + val stats: List[Tree] + val expr: Tree + } + + override type CaseDef >: Null <: Tree with CaseDefApi + + /** The API that all case defs support */ + trait CaseDefApi extends TreeApi { this: CaseDef => + val pat: Tree + val guard: Tree + val body: Tree + } + + override type Alternative >: Null <: TermTree with AlternativeApi + + /** The API that all alternatives support */ + trait AlternativeApi extends TermTreeApi { this: Alternative => + val trees: List[Tree] + } + + override type Star >: Null <: TermTree with StarApi + + /** The API that all stars support */ + trait StarApi extends TermTreeApi { this: Star => + val elem: Tree + } + + override type Bind >: Null <: DefTree with BindApi + + /** The API that all binds support */ + trait BindApi extends DefTreeApi { this: Bind => + val name: Name + val body: Tree + } + + override type UnApply >: Null <: TermTree with UnApplyApi + + /** The API that all unapplies support */ + trait UnApplyApi extends TermTreeApi { this: UnApply => + val fun: Tree + val args: List[Tree] + } + + override type ArrayValue >: Null <: TermTree with ArrayValueApi + + /** The API that all array values support */ + trait ArrayValueApi extends TermTreeApi { this: ArrayValue => + val elemtpt: Tree + val elems: List[Tree] + } + + override type Function >: Null <: TermTree with SymTree with FunctionApi + + /** The API that all functions support */ + trait FunctionApi extends TermTreeApi with SymTreeApi { this: Function => + val vparams: List[ValDef] + val body: Tree + } + + override type Assign >: Null <: TermTree with AssignApi + + /** The API that all assigns support */ + trait AssignApi extends TermTreeApi { this: Assign => + val lhs: Tree + val rhs: Tree + } + + override type AssignOrNamedArg >: Null <: TermTree with AssignOrNamedArgApi + + /** The API that all assigns support */ + trait AssignOrNamedArgApi extends TermTreeApi { this: AssignOrNamedArg => + val lhs: Tree + val rhs: Tree + } + + override type If >: Null <: TermTree with IfApi + + /** The API that all ifs support */ + trait IfApi extends TermTreeApi { this: If => + val cond: Tree + val thenp: Tree + val elsep: Tree + } + + override type Match >: Null <: TermTree with MatchApi + + /** The API that all matches support */ + trait MatchApi extends TermTreeApi { this: Match => + val selector: Tree + val cases: List[CaseDef] + } + + override type Return >: Null <: TermTree with SymTree with ReturnApi + + /** The API that all returns support */ + trait ReturnApi extends TermTreeApi { this: Return => + val expr: Tree + } + + override type Try >: Null <: TermTree with TryApi + + /** The API that all tries support */ + trait TryApi extends TermTreeApi { this: Try => + val block: Tree + val catches: List[CaseDef] + val finalizer: Tree + } + + override type Throw >: Null <: TermTree with ThrowApi + + /** The API that all tries support */ + trait ThrowApi extends TermTreeApi { this: Throw => + val expr: Tree + } + + override type New >: Null <: TermTree with NewApi + + /** The API that all news support */ + trait NewApi extends TermTreeApi { this: New => + val tpt: Tree + } + + override type Typed >: Null <: TermTree with TypedApi + + /** The API that all typeds support */ + trait TypedApi extends TermTreeApi { this: Typed => + val expr: Tree + val tpt: Tree + } + + override type GenericApply >: Null <: TermTree with GenericApplyApi + + /** The API that all applies support */ + trait GenericApplyApi extends TermTreeApi { this: GenericApply => + val fun: Tree + val args: List[Tree] + } + + override type TypeApply >: Null <: GenericApply with TypeApplyApi + + /** The API that all type applies support */ + trait TypeApplyApi extends GenericApplyApi { this: TypeApply => + } + + override type Apply >: Null <: GenericApply with ApplyApi + + /** The API that all applies support */ + trait ApplyApi extends GenericApplyApi { this: Apply => + } + + override type ApplyDynamic >: Null <: TermTree with SymTree with ApplyDynamicApi + + /** The API that all apply dynamics support */ + trait ApplyDynamicApi extends TermTreeApi with SymTreeApi { this: ApplyDynamic => + val qual: Tree + val args: List[Tree] + } + + override type Super >: Null <: TermTree with SuperApi + + /** The API that all supers support */ + trait SuperApi extends TermTreeApi { this: Super => + val qual: Tree + val mix: TypeName + } + + override type This >: Null <: TermTree with SymTree with ThisApi + + /** The API that all thises support */ + trait ThisApi extends TermTreeApi with SymTreeApi { this: This => + val qual: TypeName + } + + override type Select >: Null <: RefTree with SelectApi + + /** The API that all selects support */ + trait SelectApi extends RefTreeApi { this: Select => + val qualifier: Tree + val name: Name + } + + override type Ident >: Null <: RefTree with IdentApi + + /** The API that all idents support */ + trait IdentApi extends RefTreeApi { this: Ident => + val name: Name + } + + override type ReferenceToBoxed >: Null <: TermTree with ReferenceToBoxedApi + + /** The API that all references support */ + trait ReferenceToBoxedApi extends TermTreeApi { this: ReferenceToBoxed => + val ident: Tree + } + + override type Literal >: Null <: TermTree with LiteralApi + + /** The API that all literals support */ + trait LiteralApi extends TermTreeApi { this: Literal => + val value: Constant + } + + override type Annotated >: Null <: Tree with AnnotatedApi + + /** The API that all annotateds support */ + trait AnnotatedApi extends TreeApi { this: Annotated => + val annot: Tree + val arg: Tree + } + + override type SingletonTypeTree >: Null <: TypTree with SingletonTypeTreeApi + + /** The API that all singleton type trees support */ + trait SingletonTypeTreeApi extends TypTreeApi { this: SingletonTypeTree => + val ref: Tree + } + + override type SelectFromTypeTree >: Null <: TypTree with RefTree with SelectFromTypeTreeApi + + /** The API that all selects from type trees support */ + trait SelectFromTypeTreeApi extends TypTreeApi with RefTreeApi { this: SelectFromTypeTree => + val qualifier: Tree + val name: TypeName + } + + override type CompoundTypeTree >: Null <: TypTree with CompoundTypeTreeApi + + /** The API that all compound type trees support */ + trait CompoundTypeTreeApi extends TypTreeApi { this: CompoundTypeTree => + val templ: Template + } + + override type AppliedTypeTree >: Null <: TypTree with AppliedTypeTreeApi + + /** The API that all applied type trees support */ + trait AppliedTypeTreeApi extends TypTreeApi { this: AppliedTypeTree => + val tpt: Tree + val args: List[Tree] + } + + override type TypeBoundsTree >: Null <: TypTree with TypeBoundsTreeApi + + /** The API that all type bound trees support */ + trait TypeBoundsTreeApi extends TypTreeApi { this: TypeBoundsTree => + val lo: Tree + val hi: Tree + } + + override type ExistentialTypeTree >: Null <: TypTree with ExistentialTypeTreeApi + + /** The API that all existential type trees support */ + trait ExistentialTypeTreeApi extends TypTreeApi { this: ExistentialTypeTree => + val tpt: Tree + val whereClauses: List[Tree] + } + + override type TypeTree >: Null <: TypTree with TypeTreeApi + + /** The API that all type trees support */ + trait TypeTreeApi extends TypTreeApi { this: TypeTree => + def original: Tree + } + + /** An empty deferred value definition corresponding to: + * val _: _ + * This is used as a placeholder in the `self` parameter Template if there is + * no definition of a self value of self type. + */ + val emptyValDef: ValDef + +// ---------------------- copying ------------------------------------------------ + + /** The standard (lazy) tree copier + */ + type TreeCopier <: TreeCopierOps + val treeCopy: TreeCopier = newLazyTreeCopier + + def newStrictTreeCopier: TreeCopier + def newLazyTreeCopier: TreeCopier + + /** The API of a tree copier + * tree copiers are made available by an implicit conversion in reflect.ops + */ + abstract class TreeCopierOps { + def ClassDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], impl: Template): ClassDef + def PackageDef(tree: Tree, pid: RefTree, stats: List[Tree]): PackageDef + def ModuleDef(tree: Tree, mods: Modifiers, name: Name, impl: Template): ModuleDef + def ValDef(tree: Tree, mods: Modifiers, name: Name, tpt: Tree, rhs: Tree): ValDef + def DefDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree): DefDef + def TypeDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], rhs: Tree): TypeDef + def LabelDef(tree: Tree, name: Name, params: List[Ident], rhs: Tree): LabelDef + def Import(tree: Tree, expr: Tree, selectors: List[ImportSelector]): Import + def Template(tree: Tree, parents: List[Tree], self: ValDef, body: List[Tree]): Template + def Block(tree: Tree, stats: List[Tree], expr: Tree): Block + def CaseDef(tree: Tree, pat: Tree, guard: Tree, body: Tree): CaseDef + def Alternative(tree: Tree, trees: List[Tree]): Alternative + def Star(tree: Tree, elem: Tree): Star + def Bind(tree: Tree, name: Name, body: Tree): Bind + def UnApply(tree: Tree, fun: Tree, args: List[Tree]): UnApply + def ArrayValue(tree: Tree, elemtpt: Tree, trees: List[Tree]): ArrayValue + def Function(tree: Tree, vparams: List[ValDef], body: Tree): Function + def Assign(tree: Tree, lhs: Tree, rhs: Tree): Assign + def AssignOrNamedArg(tree: Tree, lhs: Tree, rhs: Tree): AssignOrNamedArg + def If(tree: Tree, cond: Tree, thenp: Tree, elsep: Tree): If + def Match(tree: Tree, selector: Tree, cases: List[CaseDef]): Match + def Return(tree: Tree, expr: Tree): Return + def Try(tree: Tree, block: Tree, catches: List[CaseDef], finalizer: Tree): Try + def Throw(tree: Tree, expr: Tree): Throw + def New(tree: Tree, tpt: Tree): New + def Typed(tree: Tree, expr: Tree, tpt: Tree): Typed + def TypeApply(tree: Tree, fun: Tree, args: List[Tree]): TypeApply + def Apply(tree: Tree, fun: Tree, args: List[Tree]): Apply + def ApplyDynamic(tree: Tree, qual: Tree, args: List[Tree]): ApplyDynamic + def Super(tree: Tree, qual: Tree, mix: TypeName): Super + def This(tree: Tree, qual: Name): This + def Select(tree: Tree, qualifier: Tree, selector: Name): Select + def Ident(tree: Tree, name: Name): Ident + def ReferenceToBoxed(tree: Tree, idt: Ident): ReferenceToBoxed + def Literal(tree: Tree, value: Constant): Literal + def TypeTree(tree: Tree): TypeTree + def Annotated(tree: Tree, annot: Tree, arg: Tree): Annotated + def SingletonTypeTree(tree: Tree, ref: Tree): SingletonTypeTree + def SelectFromTypeTree(tree: Tree, qualifier: Tree, selector: Name): SelectFromTypeTree + def CompoundTypeTree(tree: Tree, templ: Template): CompoundTypeTree + def AppliedTypeTree(tree: Tree, tpt: Tree, args: List[Tree]): AppliedTypeTree + def TypeBoundsTree(tree: Tree, lo: Tree, hi: Tree): TypeBoundsTree + def ExistentialTypeTree(tree: Tree, tpt: Tree, whereClauses: List[Tree]): ExistentialTypeTree + } + +// ---------------------- traversing and transforming ------------------------------ + + class Traverser { + protected[scala] var currentOwner: Symbol = rootMirror.RootClass + + def traverse(tree: Tree): Unit = itraverse(this, tree) + + def traverseTrees(trees: List[Tree]) { + trees foreach traverse + } + def traverseTreess(treess: List[List[Tree]]) { + treess foreach traverseTrees + } + def traverseStats(stats: List[Tree], exprOwner: Symbol) { + stats foreach (stat => + if (exprOwner != currentOwner) atOwner(exprOwner)(traverse(stat)) + else traverse(stat) + ) + } + + def atOwner(owner: Symbol)(traverse: => Unit) { + val prevOwner = currentOwner + currentOwner = owner + traverse + currentOwner = prevOwner + } + + /** Leave apply available in the generic traverser to do something else. + */ + def apply[T <: Tree](tree: T): T = { traverse(tree); tree } + } + + protected def itraverse(traverser: Traverser, tree: Tree): Unit = throw new MatchError(tree) + + protected def xtraverse(traverser: Traverser, tree: Tree): Unit = throw new MatchError(tree) + + abstract class Transformer { + val treeCopy: TreeCopier = newLazyTreeCopier + protected[scala] var currentOwner: Symbol = rootMirror.RootClass + protected def currentMethod = currentOwner.enclosingMethod + protected def currentClass = currentOwner.enclosingClass +// protected def currentPackage = currentOwner.enclosingTopLevelClass.owner + def transform(tree: Tree): Tree = itransform(this, tree) + + def transformTrees(trees: List[Tree]): List[Tree] = + trees mapConserve (transform(_)) + def transformTemplate(tree: Template): Template = + transform(tree: Tree).asInstanceOf[Template] + def transformTypeDefs(trees: List[TypeDef]): List[TypeDef] = + trees mapConserve (tree => transform(tree).asInstanceOf[TypeDef]) + def transformValDef(tree: ValDef): ValDef = + if (tree.isEmpty) tree else transform(tree).asInstanceOf[ValDef] + def transformValDefs(trees: List[ValDef]): List[ValDef] = + trees mapConserve (transformValDef(_)) + def transformValDefss(treess: List[List[ValDef]]): List[List[ValDef]] = + treess mapConserve (transformValDefs(_)) + def transformCaseDefs(trees: List[CaseDef]): List[CaseDef] = + trees mapConserve (tree => transform(tree).asInstanceOf[CaseDef]) + def transformIdents(trees: List[Ident]): List[Ident] = + trees mapConserve (tree => transform(tree).asInstanceOf[Ident]) + def transformStats(stats: List[Tree], exprOwner: Symbol): List[Tree] = + stats mapConserve (stat => + if (exprOwner != currentOwner && stat.isTerm) atOwner(exprOwner)(transform(stat)) + else transform(stat)) filter (EmptyTree != _) + def transformModifiers(mods: Modifiers): Modifiers = + mods.mapAnnotations(transformTrees) + + def atOwner[A](owner: Symbol)(trans: => A): A = { + val prevOwner = currentOwner + currentOwner = owner + val result = trans + currentOwner = prevOwner + result + } + } + + protected def itransform(transformer: Transformer, tree: Tree): Tree = throw new MatchError(tree) + + protected def xtransform(transformer: Transformer, tree: Tree): Tree = throw new MatchError(tree) + + type Modifiers >: Null <: ModifiersApi + + abstract class ModifiersApi extends ModifiersBase with HasFlagsApi + +} + diff --git a/src/reflect/scala/reflect/api/Types.scala b/src/reflect/scala/reflect/api/Types.scala new file mode 100644 index 0000000000..b62a92cbd7 --- /dev/null +++ b/src/reflect/scala/reflect/api/Types.scala @@ -0,0 +1,368 @@ +package scala.reflect +package api + +trait Types extends base.Types { self: Universe => + + override type Type >: Null <: TypeApi + + /** The extended API of types + */ + abstract class TypeApi extends TypeBase { + + /** The defined or declared members with name `name` in this type; + * an OverloadedSymbol if several exist, NoSymbol if none exist. + * Alternatives of overloaded symbol appear in the order they are declared. + */ + def declaration(name: Name): Symbol + + /** The collection of declarations in this type + * [Eugene++] why not List? + */ + def declarations: Iterable[Symbol] + + /** The member with given name, either directly declared or inherited, + * an OverloadedSymbol if several exist, NoSymbol if none exist. + */ + def member(name: Name): Symbol + + /** The non-private member with given name, either directly declared or inherited, + * an OverloadedSymbol if several exist, NoSymbol if none exist. + */ + def nonPrivateMember(name: Name): Symbol + + /** An iterable containing all members of this type (directly declared or inherited) + * Members appear in the linearization order of their owners. + * Members with the same owner appear in reverse order of their declarations. + * [Eugene++] the order needs to be reversed back, at least in the public API + */ + def members: Iterable[Symbol] + + /** An iterable containing all non-private members of this type (directly declared or inherited) + * Members appear in the linearization order of their owners. + * Members with the same owner appear in reverse order of their declarations. + */ + def nonPrivateMembers: Iterable[Symbol] + + /** Substitute symbols in `to` for corresponding occurrences of references to + * symbols `from` in this type. + */ + def substituteSymbols(from: List[Symbol], to: List[Symbol]): Type + + /** Substitute types in `to` for corresponding occurrences of references to + * symbols `from` in this type. + */ + def substituteTypes(from: List[Symbol], to: List[Type]): Type + + /** If this is a parameterized types, the type arguments. + * Otherwise the empty list + */ + def typeArguments: List[Type] + + /** For a (potentially wrapped) poly type, its type parameters, + * the empty list for all other types */ + def typeParams: List[Symbol] + + /** Is this type a type constructor that is missing its type arguments? + */ + def isHigherKinded: Boolean // !!! This should be called "isTypeConstructor", no? + + /** Returns the corresponding type constructor (e.g. List for List[T] or List[String]) + */ + def typeConstructor: Type + + /** Does this type refer to spliceable types or is a spliceable type? + */ + def isConcrete: Boolean + + /** Is this type an abstract type that needs to be resolved? + */ + def isSpliceable: Boolean + + /** + * Expands type aliases and converts higher-kinded TypeRefs to PolyTypes. + * Functions on types are also implemented as PolyTypes. + * + * Example: (in the below, <List> is the type constructor of List) + * TypeRef(pre, <List>, List()) is replaced by + * PolyType(X, TypeRef(pre, <List>, List(X))) + */ + def normalize: Type // !!! Alternative name? "normalize" is used to mean too many things. + + /** Does this type conform to given type argument `that`? */ + def <:< (that: Type): Boolean + + /** Is this type equivalent to given type argument `that`? */ + def =:= (that: Type): Boolean + + /** The list of all base classes of this type (including its own typeSymbol) + * in reverse linearization order, starting with the class itself and ending + * in class Any. + */ + def baseClasses: List[Symbol] // !!! Alternative name, perhaps linearization? + + /** The least type instance of given class which is a supertype + * of this type. Example: + * {{{ + * class D[T] + * class C extends p.D[Int] + * ThisType(C).baseType(D) = p.D[Int] + * }}} + */ + def baseType(clazz: Symbol): Type + + /** This type as seen from prefix `pre` and class `clazz`. This means: + * Replace all thistypes of `clazz` or one of its subclasses + * by `pre` and instantiate all parameters by arguments of `pre`. + * Proceed analogously for thistypes referring to outer classes. + * + * Example: + * {{{ + * class D[T] { def m: T } + * class C extends p.D[Int] + * T.asSeenFrom(ThisType(C), D) (where D is owner of m) + * = Int + * }}} + */ + def asSeenFrom(pre: Type, clazz: Symbol): Type + + /** The erased type corresponding to this type after + * all transformations from Scala to Java have been performed. + */ + def erasure: Type // !!! "erasedType", compare with "widen" (so "erase") or "underlying" (so "erased") + // why not name it "erasure"? + + /** Apply `f` to each part of this type, returning + * a new type. children get mapped before their parents */ + def map(f: Type => Type): Type + + /** Apply `f` to each part of this type, for side effects only */ + def foreach(f: Type => Unit) + + /** Returns optionally first type (in a preorder traversal) which satisfies predicate `p`, + * or None if none exists. + */ + def find(p: Type => Boolean): Option[Type] + + /** Is there part of this type which satisfies predicate `p`? */ + def exists(p: Type => Boolean): Boolean + + /** Does this type contain a reference to given symbol? */ + def contains(sym: Symbol): Boolean + + /** If this is a compound type, the list of its parent types; + * otherwise the empty list + */ + def parents: List[Type] + + /** If this is a singleton type, returns the type underlying it; + * otherwise returns this type itself. + */ + def underlying: Type + + /** If this is a singleton type, widen it to its nearest underlying non-singleton + * base type by applying one or more `underlying` dereferences. + * If this is not a singleton type, returns this type itself. + * + * Example: + * + * class Outer { class C ; val x: C } + * val o: Outer + * <o.x.type>.widen = o.C + */ + def widen: Type + + /** The string discriminator of this type; useful for debugging */ + def kind: String + } + + /** .. */ + override type ThisType >: Null <: SingletonType with ThisTypeApi + + /** The API that all this types support */ + trait ThisTypeApi extends TypeApi { this: ThisType => + val sym: Symbol + } + + /** .. */ + override type SingleType >: Null <: SingletonType with SingleTypeApi + + /** The API that all single types support */ + trait SingleTypeApi extends TypeApi { this: SingleType => + val pre: Type + val sym: Symbol + } + + /** .. */ + override type SuperType >: Null <: SingletonType with SuperTypeApi + + /** The API that all super types support */ + trait SuperTypeApi extends TypeApi { this: SuperType => + val thistpe: Type + val supertpe: Type + } + + /** .. */ + override type ConstantType >: Null <: SingletonType with ConstantTypeApi + + /** The API that all constant types support */ + trait ConstantTypeApi extends TypeApi { this: ConstantType => + val value: Constant + } + + /** .. */ + override type TypeRef >: Null <: Type with TypeRefApi + + /** The API that all type refs support */ + trait TypeRefApi extends TypeApi { this: TypeRef => + val pre: Type + val sym: Symbol + val args: List[Type] + } + + /** .. */ + override type RefinedType >: Null <: CompoundType with RefinedTypeApi + + /** The API that all refined types support */ + trait RefinedTypeApi extends TypeApi { this: RefinedType => + val parents: List[Type] + val decls: Scope + } + + /** .. */ + override type ClassInfoType >: Null <: CompoundType with ClassInfoTypeApi + + /** The API that all class info types support */ + trait ClassInfoTypeApi extends TypeApi { this: ClassInfoType => + val parents: List[Type] + val decls: Scope + val typeSymbol: Symbol + } + + /** .. */ + override type MethodType >: Null <: Type with MethodTypeApi + + /** The API that all method types support */ + trait MethodTypeApi extends TypeApi { this: MethodType => + val params: List[Symbol] + val resultType: Type + } + + /** .. */ + override type NullaryMethodType >: Null <: Type with NullaryMethodTypeApi + + /** The API that all nullary method types support */ + trait NullaryMethodTypeApi extends TypeApi { this: NullaryMethodType => + val resultType: Type + } + + /** .. */ + override type PolyType >: Null <: Type with PolyTypeApi + + /** The API that all polymorphic types support */ + trait PolyTypeApi extends TypeApi { this: PolyType => + val typeParams: List[Symbol] + val resultType: Type + } + + /** .. */ + override type ExistentialType >: Null <: Type with ExistentialTypeApi + + /** The API that all existential types support */ + trait ExistentialTypeApi extends TypeApi { this: ExistentialType => + val quantified: List[Symbol] + val underlying: Type + } + + /** .. */ + override type AnnotatedType >: Null <: Type with AnnotatedTypeApi + + /** The API that all annotated types support */ + trait AnnotatedTypeApi extends TypeApi { this: AnnotatedType => + val annotations: List[AnnotationInfo] + val underlying: Type + val selfsym: Symbol + } + + /** .. */ + override type TypeBounds >: Null <: Type with TypeBoundsApi + + /** The API that all type bounds support */ + trait TypeBoundsApi extends TypeApi { this: TypeBounds => + val lo: Type + val hi: Type + } + + /** .. */ + override type BoundedWildcardType >: Null <: Type with BoundedWildcardTypeApi + + /** The API that all this types support */ + trait BoundedWildcardTypeApi extends TypeApi { this: BoundedWildcardType => + val bounds: TypeBounds + } + + /** The least upper bound of a list of types, as determined by `<:<`. */ + def lub(xs: List[Type]): Type + + /** The greatest lower bound of a list of types, as determined by `<:<`. */ + def glb(ts: List[Type]): Type + + // Creators --------------------------------------------------------------- + // too useful and too non-trivial to be left out of public API + // [Eugene to Paul] needs review! + + /** The canonical creator for single-types */ + def singleType(pre: Type, sym: Symbol): Type + + /** the canonical creator for a refined type with a given scope */ + def refinedType(parents: List[Type], owner: Symbol, decls: Scope, pos: Position): Type + + /** The canonical creator for a refined type with an initially empty scope. + */ + def refinedType(parents: List[Type], owner: Symbol): Type + + /** The canonical creator for typerefs + */ + def typeRef(pre: Type, sym: Symbol, args: List[Type]): Type + + /** A creator for intersection type where intersections of a single type are + * replaced by the type itself. */ + def intersectionType(tps: List[Type]): Type + + /** A creator for intersection type where intersections of a single type are + * replaced by the type itself, and repeated parent classes are merged. + * + * !!! Repeated parent classes are not merged - is this a bug in the + * comment or in the code? + */ + def intersectionType(tps: List[Type], owner: Symbol): Type + + /** A creator for type applications */ + def appliedType(tycon: Type, args: List[Type]): Type + + /** A creator for type parameterizations that strips empty type parameter lists. + * Use this factory method to indicate the type has kind * (it's a polymorphic value) + * until we start tracking explicit kinds equivalent to typeFun (except that the latter requires tparams nonEmpty). + */ + def polyType(tparams: List[Symbol], tpe: Type): Type + + /** A creator for existential types. This generates: + * + * {{{ + * tpe1 where { tparams } + * }}} + * + * where `tpe1` is the result of extrapolating `tpe` with regard to `tparams`. + * Extrapolating means that type variables in `tparams` occurring + * in covariant positions are replaced by upper bounds, (minus any + * SingletonClass markers), type variables in `tparams` occurring in + * contravariant positions are replaced by upper bounds, provided the + * resulting type is legal with regard to stability, and does not contain + * any type variable in `tparams`. + * + * The abstraction drops all type parameters that are not directly or + * indirectly referenced by type `tpe1`. If there are no remaining type + * parameters, simply returns result type `tpe`. + */ + def existentialAbstraction(tparams: List[Symbol], tpe0: Type): Type +} + diff --git a/src/library/scala/reflect/api/Universe.scala b/src/reflect/scala/reflect/api/Universe.scala index 05b5963c73..002cd2e673 100755..100644 --- a/src/library/scala/reflect/api/Universe.scala +++ b/src/reflect/scala/reflect/api/Universe.scala @@ -3,25 +3,22 @@ package api import language.experimental.macros -abstract class Universe extends Symbols - with FreeVars +abstract class Universe extends base.Universe + with Symbols with Types - with Constants - with Scopes + with FlagSets with Names with Trees - with AnnotationInfos + with TreePrinters + with Constants with Positions - with Exprs + with Mirrors with StandardDefinitions - with TypeTags - with TreePrinters with StandardNames - with ClassLoaders - with TreeBuildUtil - with ToolBoxes - with FrontEnds - with Importers { + with Importers + with Exprs + with AnnotationInfos +{ /** Given an expression, generate a tree that when compiled and executed produces the original tree. * The produced tree will be bound to the Universe it was called from. @@ -33,20 +30,20 @@ abstract class Universe extends Symbols * }}} * * The reifier transforms it to the following expression: - * + * * {{{ * <[ - * val $mr: scala.reflect.api.Universe = <reference to the Universe that calls the reify> - * $mr.Expr[Int]($mr.Apply($mr.Select($mr.Ident($mr.newFreeVar("x", <Int>, x), "+"), List($mr.Literal($mr.Constant(1)))))) + * val $u: u.type = u // where u is a reference to the Universe that calls the reify + * $u.Expr[Int]($u.Apply($u.Select($u.Ident($u.newFreeVar("x", <Int>, x), "+"), List($u.Literal($u.Constant(1)))))) * ]> * }}} * - * Reification performs expression splicing (when processing Expr.eval and Expr.value) + * Reification performs expression splicing (when processing Expr.splice) * and type splicing (for every type T that has a TypeTag[T] implicit in scope): * * {{{ - * val two = mirror.reify(2) // Literal(Constant(2)) - * val four = mirror.reify(two.eval + two.eval) // Apply(Select(two.tree, newTermName("$plus")), List(two.tree)) + * val two = mirror.reify(2) // Literal(Constant(2)) + * val four = mirror.reify(two.splice + two.splice) // Apply(Select(two.tree, newTermName("$plus")), List(two.tree)) * * def macroImpl[T](c: Context) = { * ... @@ -66,12 +63,6 @@ abstract class Universe extends Symbols * * Since reified trees can be compiled outside of the scope they've been created in, * special measures are taken to ensure that all members accessed in the reifee remain visible */ - def reify[T](expr: T): Expr[T] = macro Universe.reify[T] -} - -object Universe { - def reify[T](cc: scala.reflect.makro.Context{ type PrefixType = Universe })(expr: cc.Expr[T]): cc.Expr[cc.prefix.value.Expr[T]] = { - import scala.reflect.makro.internal._ - cc.Expr(cc.materializeExpr(cc.prefix.tree, expr.tree)) - } -} + // implementation is magically hardwired to `scala.reflect.reify.Taggers` + def reify[T](expr: T): Expr[T] = macro ??? +}
\ No newline at end of file diff --git a/src/reflect/scala/reflect/api/package.scala b/src/reflect/scala/reflect/api/package.scala new file mode 100644 index 0000000000..d2fce7cf1d --- /dev/null +++ b/src/reflect/scala/reflect/api/package.scala @@ -0,0 +1,12 @@ +package scala.reflect + +package object api { + + // type and value aliases for slices of the base Universe cake that are not + // repeated in api.Universe + type Scopes = base.Scopes + type BuildUtils = base.BuildUtils + type Attachments = base.Attachments + + type MirrorOf[U <: base.Universe with Singleton] = base.MirrorOf[U] +} diff --git a/src/library/scala/reflect/api/RequiredFile.scala b/src/reflect/scala/reflect/internal/AbstractFileApi.scala index 4a54595940..9f37f4536f 100644 --- a/src/library/scala/reflect/api/RequiredFile.scala +++ b/src/reflect/scala/reflect/internal/AbstractFileApi.scala @@ -1,7 +1,7 @@ package scala.reflect -package api +package internal -trait RequiredFile { +trait AbstractFileApi { def path: String def canonicalPath: String } diff --git a/src/compiler/scala/reflect/internal/AnnotationCheckers.scala b/src/reflect/scala/reflect/internal/AnnotationCheckers.scala index 449b0ca0bc..449b0ca0bc 100644 --- a/src/compiler/scala/reflect/internal/AnnotationCheckers.scala +++ b/src/reflect/scala/reflect/internal/AnnotationCheckers.scala diff --git a/src/compiler/scala/reflect/internal/AnnotationInfos.scala b/src/reflect/scala/reflect/internal/AnnotationInfos.scala index 91e1c3d50d..c283ae408e 100644 --- a/src/compiler/scala/reflect/internal/AnnotationInfos.scala +++ b/src/reflect/scala/reflect/internal/AnnotationInfos.scala @@ -46,23 +46,26 @@ trait AnnotationInfos extends api.AnnotationInfos { self: SymbolTable => * - or nested classfile annotations */ abstract class ClassfileAnnotArg extends Product + implicit val ClassfileAnnotArgTag = ClassTag[ClassfileAnnotArg](classOf[ClassfileAnnotArg]) /** Represents a compile-time Constant (`Boolean`, `Byte`, `Short`, * `Char`, `Int`, `Long`, `Float`, `Double`, `String`, `java.lang.Class` or * an instance of a Java enumeration value). */ case class LiteralAnnotArg(const: Constant) - extends ClassfileAnnotArg { + extends ClassfileAnnotArg with LiteralAnnotArgApi { override def toString = const.escapedStringValue } + implicit val LiteralAnnotArgTag = ClassTag[LiteralAnnotArg](classOf[LiteralAnnotArg]) object LiteralAnnotArg extends LiteralAnnotArgExtractor /** Represents an array of classfile annotation arguments */ case class ArrayAnnotArg(args: Array[ClassfileAnnotArg]) - extends ClassfileAnnotArg { + extends ClassfileAnnotArg with ArrayAnnotArgApi { override def toString = args.mkString("[", ", ", "]") } + implicit val ArrayAnnotArgTag = ClassTag[ArrayAnnotArg](classOf[ArrayAnnotArg]) object ArrayAnnotArg extends ArrayAnnotArgExtractor @@ -105,11 +108,12 @@ trait AnnotationInfos extends api.AnnotationInfos { self: SymbolTable => } /** Represents a nested classfile annotation */ - case class NestedAnnotArg(annInfo: AnnotationInfo) extends ClassfileAnnotArg { + case class NestedAnnotArg(annInfo: AnnotationInfo) extends ClassfileAnnotArg with NestedAnnotArgApi { // The nested annotation should not have any Scala annotation arguments assert(annInfo.args.isEmpty, annInfo.args) override def toString = annInfo.toString } + implicit val NestedAnnotArgTag = ClassTag[NestedAnnotArg](classOf[NestedAnnotArg]) object NestedAnnotArg extends NestedAnnotArgExtractor @@ -191,7 +195,7 @@ trait AnnotationInfos extends api.AnnotationInfos { self: SymbolTable => * * `assocs` stores arguments to classfile annotations as name-value pairs. */ - sealed abstract class AnnotationInfo { + sealed abstract class AnnotationInfo extends AnnotationInfoApi { def atp: Type def args: List[Tree] def assocs: List[(Name, ClassfileAnnotArg)] @@ -258,7 +262,7 @@ trait AnnotationInfos extends api.AnnotationInfos { self: SymbolTable => /** Change all ident's with Symbol "from" to instead use symbol "to" */ def substIdentSyms(from: Symbol, to: Symbol) = - AnnotationInfo(atp, args map (_ substTreeSyms (from -> to)), assocs) setPos pos + AnnotationInfo(atp, args map (_ substituteSymbols (List(from), List(to))), assocs) setPos pos def stringArg(index: Int) = constantAtIndex(index) map (_.stringValue) def intArg(index: Int) = constantAtIndex(index) map (_.intValue) @@ -283,7 +287,7 @@ trait AnnotationInfos extends api.AnnotationInfos { self: SymbolTable => } } - lazy val classfileAnnotArgTag: ArrayTag[ClassfileAnnotArg] = arrayTag[ClassfileAnnotArg] + implicit val AnnotationInfoTag = ClassTag[AnnotationInfo](classOf[AnnotationInfo]) object UnmappableAnnotation extends CompleteAnnotationInfo(NoType, Nil, Nil) } diff --git a/src/compiler/scala/reflect/internal/BaseTypeSeqs.scala b/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala index 3753a45133..5f78671012 100644 --- a/src/compiler/scala/reflect/internal/BaseTypeSeqs.scala +++ b/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala @@ -127,38 +127,11 @@ trait BaseTypeSeqs { def exists(p: Type => Boolean): Boolean = elems exists p - lazy val maxDepth: Int = maxDepthOfElems + lazy val maxDepth = maxDepthOfElems - protected def maxDepthOfElems = { + protected def maxDepthOfElems: Int = { var d = 0 - for (i <- 0 until length) d = max(d, maxDpth(elems(i))) - d - } - - /** The maximum depth of type `tp` */ - protected def maxDpth(tp: Type): Int = tp match { - case TypeRef(pre, sym, args) => - max(maxDpth(pre), maxDpth(args) + 1) - case RefinedType(parents, decls) => - max(maxDpth(parents), maxDpth(decls.toList.map(_.info)) + 1) - case TypeBounds(lo, hi) => - max(maxDpth(lo), maxDpth(hi)) - case MethodType(paramtypes, result) => - maxDpth(result) - case NullaryMethodType(result) => - maxDpth(result) - case PolyType(tparams, result) => - max(maxDpth(result), maxDpth(tparams map (_.info)) + 1) - case ExistentialType(tparams, result) => - max(maxDpth(result), maxDpth(tparams map (_.info)) + 1) - case _ => - 1 - } - - /** The maximum depth of all types `tps` */ - private def maxDpth(tps: Seq[Type]): Int = { - var d = 0 - for (tp <- tps) d = max(d, maxDpth(tp)) + for (i <- 1 until length) d = max(d, typeDepth(elems(i))) d } @@ -225,9 +198,9 @@ trait BaseTypeSeqs { nextRawElem(i) match { case RefinedType(variants, decls) => for (tp <- variants) - if (!(minTypes exists (tp =:=))) minTypes = tp :: minTypes + if (!(minTypes exists (tp =:= _))) minTypes = tp :: minTypes case tp => - if (!(minTypes exists (tp =:=))) minTypes = tp :: minTypes + if (!(minTypes exists (tp =:= _))) minTypes = tp :: minTypes } index(i) = index(i) + 1 } @@ -252,7 +225,7 @@ trait BaseTypeSeqs { override def map(g: Type => Type) = lateMap(g) override def lateMap(g: Type => Type) = orig.lateMap(x => g(f(x))) override def exists(p: Type => Boolean) = elems exists (x => p(f(x))) - override protected def maxDepthOfElems: Int = elems map (x => maxDpth(f(x))) max + override protected def maxDepthOfElems: Int = elems map (x => typeDepth(f(x))) max override def toString = elems.mkString("MBTS(", ",", ")") } diff --git a/src/reflect/scala/reflect/internal/BuildUtils.scala b/src/reflect/scala/reflect/internal/BuildUtils.scala new file mode 100644 index 0000000000..3bde57ded8 --- /dev/null +++ b/src/reflect/scala/reflect/internal/BuildUtils.scala @@ -0,0 +1,69 @@ +package scala.reflect +package internal + +import Flags._ + +trait BuildUtils extends base.BuildUtils { self: SymbolTable => + + class BuildImpl extends BuildBase { + + def selectType(owner: Symbol, name: String): TypeSymbol = { + val result = owner.info.decl(newTypeName(name)) + if (result ne NoSymbol) result.asTypeSymbol + else MissingRequirementError.notFound("type %s in %s".format(name, owner.fullName)) + } + + def selectTerm(owner: Symbol, name: String): TermSymbol = { + val sym = owner.info.decl(newTermName(name)) + val result = + if (sym.isOverloaded) sym.suchThat(!_.isMethod) + else sym + if (result ne NoSymbol) result.asTermSymbol + else MissingRequirementError.notFound("term %s in %s".format(name, owner.fullName)) + } + + def selectOverloadedMethod(owner: Symbol, name: String, index: Int): MethodSymbol = { + val result = owner.info.decl(newTermName(name)).alternatives(index) + if (result ne NoSymbol) result.asMethodSymbol + else MissingRequirementError.notFound("overloaded method %s #%d in %s".format(name, index, owner.fullName)) + } + + def newFreeTerm(name: String, info: Type, value: => Any, flags: Long = 0L, origin: String = null): FreeTermSymbol = + newFreeTermSymbol(newTermName(name), info, value, flags, origin) + + def newFreeType(name: String, info: Type, value: => Any, flags: Long = 0L, origin: String = null): FreeTypeSymbol = + newFreeTypeSymbol(newTypeName(name), info, value, (if (flags == 0L) PARAM else flags) | DEFERRED, origin) + + def newFreeExistential(name: String, info: Type, value: => Any, flags: Long = 0L, origin: String = null): FreeTypeSymbol = + newFreeTypeSymbol(newTypeName(name), info, value, (if (flags == 0L) EXISTENTIAL else flags) | DEFERRED, origin) + + def newNestedSymbol(owner: Symbol, name: Name, pos: Position, flags: Long, isClass: Boolean): Symbol = + owner.newNestedSymbol(name, pos, flags, isClass) + + def setAnnotations[S <: Symbol](sym: S, annots: List[AnnotationInfo]): S = + sym.setAnnotations(annots) + + def setTypeSignature[S <: Symbol](sym: S, tpe: Type): S = + sym.setTypeSignature(tpe) + + def flagsFromBits(bits: Long): FlagSet = bits + + def emptyValDef: ValDef = self.emptyValDef + + def This(sym: Symbol): Tree = self.This(sym) + + def Select(qualifier: Tree, sym: Symbol): Select = self.Select(qualifier, sym) + + def Ident(sym: Symbol): Ident = self.Ident(sym) + + def TypeTree(tp: Type): TypeTree = self.TypeTree(tp) + + def thisPrefix(sym: Symbol): Type = sym.thisPrefix + + def setType[T <: Tree](tree: T, tpe: Type): T = { tree.setType(tpe); tree } + + def setSymbol[T <: Tree](tree: T, sym: Symbol): T = { tree.setSymbol(sym); tree } + } + + val build: BuildBase = new BuildImpl +} diff --git a/src/compiler/scala/reflect/internal/CapturedVariables.scala b/src/reflect/scala/reflect/internal/CapturedVariables.scala index 77909d9157..77909d9157 100644 --- a/src/compiler/scala/reflect/internal/CapturedVariables.scala +++ b/src/reflect/scala/reflect/internal/CapturedVariables.scala diff --git a/src/compiler/scala/reflect/internal/Chars.scala b/src/reflect/scala/reflect/internal/Chars.scala index f2c90a6721..50ec71094a 100644 --- a/src/compiler/scala/reflect/internal/Chars.scala +++ b/src/reflect/scala/reflect/internal/Chars.scala @@ -2,10 +2,12 @@ * Copyright 2006-2011 LAMP/EPFL * @author Martin Odersky */ -package scala.reflect.internal +package scala.reflect +package internal import annotation.{ tailrec, switch } import java.lang.{ Character => JCharacter } +import language.postfixOps /** Contains constants and classifier methods for characters */ trait Chars { diff --git a/src/compiler/scala/reflect/internal/ClassfileConstants.scala b/src/reflect/scala/reflect/internal/ClassfileConstants.scala index 3346e9cccb..3346e9cccb 100644 --- a/src/compiler/scala/reflect/internal/ClassfileConstants.scala +++ b/src/reflect/scala/reflect/internal/ClassfileConstants.scala diff --git a/src/compiler/scala/reflect/internal/Constants.scala b/src/reflect/scala/reflect/internal/Constants.scala index 861bc870a7..820dfe0868 100644 --- a/src/compiler/scala/reflect/internal/Constants.scala +++ b/src/reflect/scala/reflect/internal/Constants.scala @@ -30,7 +30,7 @@ trait Constants extends api.Constants { // For supporting java enumerations inside java annotations (see ClassfileParser) final val EnumTag = 13 - case class Constant(value: Any) extends AbsConstant { + case class Constant(value: Any) extends ConstantApi { val tag: Int = value match { case null => NullTag case x: Unit => UnitTag @@ -235,4 +235,6 @@ trait Constants extends api.Constants { } object Constant extends ConstantExtractor + + implicit val ConstantTag = ClassTag[Constant](classOf[Constant]) } diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala index 96819eab91..a9d9b06621 100644 --- a/src/compiler/scala/reflect/internal/Definitions.scala +++ b/src/reflect/scala/reflect/internal/Definitions.scala @@ -10,11 +10,13 @@ import annotation.{ switch, meta } import scala.collection.{ mutable, immutable } import Flags._ import PartialFunction._ -import scala.reflect.{ mirror => rm } +import scala.reflect.base.{Universe => BaseUniverse} -trait Definitions extends reflect.api.StandardDefinitions { +trait Definitions extends api.StandardDefinitions { self: SymbolTable => + import rootMirror.{getModule, getClassByName, getRequiredClass, getRequiredModule, getRequiredPackage, getClassIfDefined, getModuleIfDefined, getPackageObject, getPackageObjectIfDefined, requiredClass, requiredModule} + object definitions extends DefinitionsClass // [Eugene] find a way to make these non-lazy @@ -99,7 +101,7 @@ trait Definitions extends reflect.api.StandardDefinitions { case _ => catastrophicFailure() } } - private def valueCompanionMember(className: Name, methodName: TermName): MethodSymbol = + private def valueCompanionMember(className: Name, methodName: TermName): TermSymbol = getMemberMethod(valueClassCompanion(className.toTermName).moduleClass, methodName) private def classesMap[T](f: Name => T) = symbolsMap(ScalaValueClassesNoUnit, f) @@ -111,7 +113,7 @@ trait Definitions extends reflect.api.StandardDefinitions { lazy val abbrvTag = symbolsMap(ScalaValueClasses, nameToTag) withDefaultValue OBJECT_TAG lazy val numericWeight = symbolsMapFilt(ScalaValueClasses, nameToWeight.keySet, nameToWeight) lazy val boxedModule = classesMap(x => getModule(boxedName(x))) - lazy val boxedClass = classesMap(x => getClass(boxedName(x))) + lazy val boxedClass = classesMap(x => getClassByName(boxedName(x))) lazy val refClass = classesMap(x => getRequiredClass("scala.runtime." + x + "Ref")) lazy val volatileRefClass = classesMap(x => getRequiredClass("scala.runtime.Volatile" + x + "Ref")) lazy val boxMethod = classesMap(x => valueCompanionMember(x, nme.box)) @@ -138,9 +140,9 @@ trait Definitions extends reflect.api.StandardDefinitions { lazy val FloatClass = valueClassSymbol(tpnme.Float) lazy val DoubleClass = valueClassSymbol(tpnme.Double) lazy val BooleanClass = valueClassSymbol(tpnme.Boolean) - lazy val Boolean_and = getMember(BooleanClass, nme.ZAND) - lazy val Boolean_or = getMember(BooleanClass, nme.ZOR) - lazy val Boolean_not = getMember(BooleanClass, nme.UNARY_!) + lazy val Boolean_and = getMemberMethod(BooleanClass, nme.ZAND) + lazy val Boolean_or = getMemberMethod(BooleanClass, nme.ZOR) + lazy val Boolean_not = getMemberMethod(BooleanClass, nme.UNARY_!) lazy val ScalaNumericValueClasses = ScalaValueClasses filterNot Set[Symbol](UnitClass, BooleanClass) @@ -160,68 +162,33 @@ trait Definitions extends reflect.api.StandardDefinitions { def ScalaPrimitiveValueClasses: List[ClassSymbol] = ScalaValueClasses } - abstract class DefinitionsClass extends AbsDefinitions with ValueClassDefinitions { + abstract class DefinitionsClass extends DefinitionsApi with ValueClassDefinitions { private var isInitialized = false def isDefinitionsInitialized = isInitialized // symbols related to packages var emptypackagescope: Scope = null //debug - // TODO - having these as objects means they elude the attempt to - // add synchronization in SynchronizedSymbols. But we should either - // flip on object overrides or find some other accomodation, because - // lazy vals are unnecessarily expensive relative to objects and it - // is very beneficial for a handful of bootstrap symbols to have - // first class identities - sealed trait WellKnownSymbol extends Symbol { - this initFlags TopLevelCreationFlags - } - // Features common to RootClass and RootPackage, the roots of all - // type and term symbols respectively. - sealed trait RootSymbol extends WellKnownSymbol { - final override def isRootSymbol = true - override def owner = NoSymbol - override def typeOfThis = thisSym.tpe - } - // This is the package _root_. The actual root cannot be referenced at - // the source level, but _root_ is essentially a function => <root>. - final object RootPackage extends PackageSymbol(NoSymbol, NoPosition, nme.ROOTPKG) with RootSymbol { - this setInfo NullaryMethodType(RootClass.tpe) - RootClass.sourceModule = this + @deprecated("Moved to rootMirror.RootPackage", "2.10.0") + val RootPackage: ModuleSymbol = rootMirror.RootPackage + + @deprecated("Moved to rootMirror.RootClass", "2.10.0") + val RootClass: ClassSymbol = rootMirror.RootClass + + @deprecated("Moved to rootMirror.EmptyPackage", "2.10.0") + val EmptyPackage: ModuleSymbol = rootMirror.EmptyPackage + + @deprecated("Moved to rootMirror.EmptyPackageClass", "2.10.0") + val EmptyPackageClass: ClassSymbol = rootMirror.RootClass - override def isRootPackage = true - } - // This is <root>, the actual root of everything except the package _root_. - // <root> and _root_ (RootPackage and RootClass) should be the only "well known" - // symbols owned by NoSymbol. All owner chains should go through RootClass, - // although it is probable that some symbols are created as direct children - // of NoSymbol to ensure they will not be stumbled upon. (We should designate - // a better encapsulated place for that.) - final object RootClass extends PackageClassSymbol(NoSymbol, NoPosition, tpnme.ROOT) with RootSymbol { - this setInfo rootLoader - - override def isRoot = true - override def isEffectiveRoot = true - override def isStatic = true - override def isNestedClass = false - override def ownerOfNewSymbols = EmptyPackageClass - } - // The empty package, which holds all top level types without given packages. - final object EmptyPackage extends PackageSymbol(RootClass, NoPosition, nme.EMPTY_PACKAGE_NAME) with WellKnownSymbol { - override def isEmptyPackage = true - } - final object EmptyPackageClass extends PackageClassSymbol(RootClass, NoPosition, tpnme.EMPTY_PACKAGE_NAME) with WellKnownSymbol { - override def isEffectiveRoot = true - override def isEmptyPackageClass = true - } // It becomes tricky to create dedicated objects for other symbols because // of initialization order issues. lazy val JavaLangPackage = getRequiredPackage(sn.JavaLang) - lazy val JavaLangPackageClass = JavaLangPackage.moduleClass + lazy val JavaLangPackageClass = JavaLangPackage.moduleClass.asClassSymbol lazy val ScalaPackage = getRequiredPackage(nme.scala_) - lazy val ScalaPackageClass = ScalaPackage.moduleClass + lazy val ScalaPackageClass = ScalaPackage.moduleClass.asClassSymbol lazy val RuntimePackage = getRequiredPackage("scala.runtime") - lazy val RuntimePackageClass = RuntimePackage.moduleClass + lazy val RuntimePackageClass = RuntimePackage.moduleClass.asClassSymbol lazy val JavaLangEnumClass = requiredClass[java.lang.Enum[_]] @@ -235,9 +202,6 @@ trait Definitions extends reflect.api.StandardDefinitions { private def inttype = IntClass.tpe private def stringtype = StringClass.tpe - // Java types - def javaTypeName(jclazz: Class[_]): TypeName = newTypeName(jclazz.getName) - def javaTypeToValueClass(jtype: Class[_]): Symbol = jtype match { case java.lang.Void.TYPE => UnitClass case java.lang.Byte.TYPE => ByteClass @@ -282,7 +246,7 @@ trait Definitions extends reflect.api.StandardDefinitions { // Note: this is not the type alias AnyRef, it's a companion-like // object used by the @specialize annotation. - lazy val AnyRefModule = getMember(ScalaPackageClass, nme.AnyRef) + lazy val AnyRefModule = getMemberModule(ScalaPackageClass, nme.AnyRef) @deprecated("Use AnyRefModule", "2.10.0") def Predef_AnyRef = AnyRefModule @@ -294,8 +258,8 @@ trait Definitions extends reflect.api.StandardDefinitions { }).asInstanceOf[ClassSymbol] // bottom types - lazy val RuntimeNothingClass = getClass(fulltpnme.RuntimeNothing) - lazy val RuntimeNullClass = getClass(fulltpnme.RuntimeNull) + lazy val RuntimeNothingClass = getClassByName(fulltpnme.RuntimeNothing) + lazy val RuntimeNullClass = getClassByName(fulltpnme.RuntimeNull) sealed abstract class BottomClassSymbol(name: TypeName, parent: Symbol) extends ClassSymbol(ScalaPackageClass, NoPosition, name) { locally { @@ -316,12 +280,12 @@ trait Definitions extends reflect.api.StandardDefinitions { // exceptions and other throwables lazy val ClassCastExceptionClass = requiredClass[ClassCastException] - lazy val IndexOutOfBoundsExceptionClass = getClass(sn.IOOBException) - lazy val InvocationTargetExceptionClass = getClass(sn.InvTargetException) + lazy val IndexOutOfBoundsExceptionClass = getClassByName(sn.IOOBException) + lazy val InvocationTargetExceptionClass = getClassByName(sn.InvTargetException) lazy val MatchErrorClass = requiredClass[MatchError] lazy val NonLocalReturnControlClass = requiredClass[scala.runtime.NonLocalReturnControl[_]] - lazy val NullPointerExceptionClass = getClass(sn.NPException) - lazy val ThrowableClass = getClass(sn.Throwable) + lazy val NullPointerExceptionClass = getClassByName(sn.NPException) + lazy val ThrowableClass = getClassByName(sn.Throwable) lazy val UninitializedErrorClass = requiredClass[UninitializedFieldError] // fundamental reference classes @@ -331,14 +295,17 @@ trait Definitions extends reflect.api.StandardDefinitions { lazy val StringClass = requiredClass[java.lang.String] lazy val StringModule = StringClass.linkedClassOfClass lazy val ClassClass = requiredClass[java.lang.Class[_]] - def Class_getMethod = getMember(ClassClass, nme.getMethod_) + def Class_getMethod = getMemberMethod(ClassClass, nme.getMethod_) lazy val DynamicClass = requiredClass[Dynamic] // fundamental modules lazy val SysPackage = getPackageObject("scala.sys") - def Sys_error = getMember(SysPackage, nme.error) + def Sys_error = getMemberMethod(SysPackage, nme.error) // Modules whose members are in the default namespace + // [Eugene++] ScalaPackage and JavaLangPackage are never ever shared between mirrors + // as a result, `Int` becomes `scala.Int` and `String` becomes `java.lang.String` + // I could just change `isOmittablePrefix`, but there's more to it, so I'm leaving this as a todo for now lazy val UnqualifiedModules = List(PredefModule, ScalaPackage, JavaLangPackage) // Those modules and their module classes lazy val UnqualifiedOwners = UnqualifiedModules.toSet ++ UnqualifiedModules.map(_.moduleClass) @@ -346,11 +313,12 @@ trait Definitions extends reflect.api.StandardDefinitions { lazy val PredefModule = requiredModule[scala.Predef.type] lazy val PredefModuleClass = PredefModule.moduleClass - def Predef_classOf = getMember(PredefModule, nme.classOf) - def Predef_identity = getMember(PredefModule, nme.identity) - def Predef_conforms = getMember(PredefModule, nme.conforms) - def Predef_wrapRefArray = getMember(PredefModule, nme.wrapRefArray) - def Predef_??? = getMember(PredefModule, nme.???) + def Predef_classOf = getMemberMethod(PredefModule, nme.classOf) + def Predef_identity = getMemberMethod(PredefModule, nme.identity) + def Predef_conforms = getMemberMethod(PredefModule, nme.conforms) + def Predef_wrapRefArray = getMemberMethod(PredefModule, nme.wrapRefArray) + def Predef_??? = getMemberMethod(PredefModule, nme.???) + def Predef_implicitly = getMemberMethod(PredefModule, nme.implicitly) /** Is `sym` a member of Predef with the given name? * Note: DON't replace this by sym == Predef_conforms/etc, as Predef_conforms is a `def` @@ -364,32 +332,32 @@ trait Definitions extends reflect.api.StandardDefinitions { /** Specialization. */ lazy val SpecializableModule = requiredModule[Specializable] - lazy val GroupOfSpecializable = getMember(SpecializableModule, tpnme.Group) - - lazy val ConsoleModule: Symbol = requiredModule[scala.Console.type] - lazy val ScalaRunTimeModule: Symbol = requiredModule[scala.runtime.ScalaRunTime.type] - lazy val SymbolModule: Symbol = requiredModule[scala.Symbol.type] - lazy val Symbol_apply = SymbolModule.info decl nme.apply - - def SeqFactory = getMember(ScalaRunTimeModule, nme.Seq) - def arrayApplyMethod = getMember(ScalaRunTimeModule, nme.array_apply) - def arrayUpdateMethod = getMember(ScalaRunTimeModule, nme.array_update) - def arrayLengthMethod = getMember(ScalaRunTimeModule, nme.array_length) - def arrayCloneMethod = getMember(ScalaRunTimeModule, nme.array_clone) - def ensureAccessibleMethod = getMember(ScalaRunTimeModule, nme.ensureAccessible) - def scalaRuntimeSameElements = getMember(ScalaRunTimeModule, nme.sameElements) - def arrayClassMethod = getMember(ScalaRunTimeModule, nme.arrayClass) - def arrayElementClassMethod = getMember(ScalaRunTimeModule, nme.arrayElementClass) + lazy val GroupOfSpecializable = getMemberClass(SpecializableModule, tpnme.Group) + + lazy val ConsoleModule = requiredModule[scala.Console.type] + lazy val ScalaRunTimeModule = requiredModule[scala.runtime.ScalaRunTime.type] + lazy val SymbolModule = requiredModule[scala.Symbol.type] + lazy val Symbol_apply = getMemberMethod(SymbolModule, nme.apply) + + def SeqFactory = getMember(ScalaRunTimeModule, nme.Seq) // [Eugene++] obsolete? + def arrayApplyMethod = getMemberMethod(ScalaRunTimeModule, nme.array_apply) + def arrayUpdateMethod = getMemberMethod(ScalaRunTimeModule, nme.array_update) + def arrayLengthMethod = getMemberMethod(ScalaRunTimeModule, nme.array_length) + def arrayCloneMethod = getMemberMethod(ScalaRunTimeModule, nme.array_clone) + def ensureAccessibleMethod = getMemberMethod(ScalaRunTimeModule, nme.ensureAccessible) + def scalaRuntimeSameElements = getMemberMethod(ScalaRunTimeModule, nme.sameElements) + def arrayClassMethod = getMemberMethod(ScalaRunTimeModule, nme.arrayClass) + def arrayElementClassMethod = getMemberMethod(ScalaRunTimeModule, nme.arrayElementClass) // classes with special meanings lazy val StringAddClass = requiredClass[scala.runtime.StringAdd] lazy val ArrowAssocClass = getRequiredClass("scala.Predef.ArrowAssoc") // SI-5731 - lazy val StringAdd_+ = getMember(StringAddClass, nme.PLUS) + lazy val StringAdd_+ = getMemberMethod(StringAddClass, nme.PLUS) lazy val NotNullClass = getRequiredClass("scala.NotNull") lazy val ScalaNumberClass = requiredClass[scala.math.ScalaNumber] lazy val TraitSetterAnnotationClass = requiredClass[scala.runtime.TraitSetter] lazy val DelayedInitClass = requiredClass[scala.DelayedInit] - def delayedInitMethod = getMember(DelayedInitClass, nme.delayedInit) + def delayedInitMethod = getMemberMethod(DelayedInitClass, nme.delayedInit) // a dummy value that communicates that a delayedInit call is compiler-generated // from phase UnCurry to phase Constructors // !!! This is not used anywhere (it was checked in that way.) @@ -454,37 +422,37 @@ trait Definitions extends reflect.api.StandardDefinitions { lazy val TraversableClass = requiredClass[scala.collection.Traversable[_]] lazy val ListModule = requiredModule[scala.collection.immutable.List.type] - lazy val List_apply = getMember(ListModule, nme.apply) + lazy val List_apply = getMemberMethod(ListModule, nme.apply) lazy val NilModule = requiredModule[scala.collection.immutable.Nil.type] lazy val SeqModule = requiredModule[scala.collection.Seq.type] - lazy val IteratorModule = requiredModule[scala.collection.Iterator.type] - lazy val Iterator_apply = getMember(IteratorModule, nme.apply) + lazy val IteratorModule = requiredModule[scala.collection.Iterator.type] + lazy val Iterator_apply = getMemberMethod(IteratorModule, nme.apply) // arrays and their members - lazy val ArrayModule = requiredModule[scala.Array.type] - lazy val ArrayModule_overloadedApply = getMember(ArrayModule, nme.apply) - lazy val ArrayClass = getRequiredClass("scala.Array") // requiredClass[scala.Array[_]] - lazy val Array_apply = getMember(ArrayClass, nme.apply) - lazy val Array_update = getMember(ArrayClass, nme.update) - lazy val Array_length = getMember(ArrayClass, nme.length) - lazy val Array_clone = getMember(ArrayClass, nme.clone_) + lazy val ArrayModule = requiredModule[scala.Array.type] + lazy val ArrayModule_overloadedApply = getMemberMethod(ArrayModule, nme.apply) + lazy val ArrayClass = getRequiredClass("scala.Array") // requiredClass[scala.Array[_]] + lazy val Array_apply = getMemberMethod(ArrayClass, nme.apply) + lazy val Array_update = getMemberMethod(ArrayClass, nme.update) + lazy val Array_length = getMemberMethod(ArrayClass, nme.length) + lazy val Array_clone = getMemberMethod(ArrayClass, nme.clone_) // reflection / structural types lazy val SoftReferenceClass = requiredClass[java.lang.ref.SoftReference[_]] lazy val WeakReferenceClass = requiredClass[java.lang.ref.WeakReference[_]] - lazy val MethodClass = getClass(sn.MethodAsObject) - def methodClass_setAccessible = getMember(MethodClass, nme.setAccessible) + lazy val MethodClass = getClassByName(sn.MethodAsObject) + def methodClass_setAccessible = getMemberMethod(MethodClass, nme.setAccessible) lazy val EmptyMethodCacheClass = requiredClass[scala.runtime.EmptyMethodCache] lazy val MethodCacheClass = requiredClass[scala.runtime.MethodCache] - def methodCache_find = getMember(MethodCacheClass, nme.find_) - def methodCache_add = getMember(MethodCacheClass, nme.add_) + def methodCache_find = getMemberMethod(MethodCacheClass, nme.find_) + def methodCache_add = getMemberMethod(MethodCacheClass, nme.add_) // scala.reflect - lazy val ReflectPackageClass = getMember(ScalaPackageClass, nme.reflect) - lazy val ReflectPackage = requiredModule[scala.reflect.`package`.type] - def ReflectMirror = getMember(ReflectPackage, nme.mirror) - // [Eugene] is this a good place for ReflectMirrorPrefix? - def ReflectMirrorPrefix = gen.mkAttributedRef(ReflectMirror) setType singleType(ReflectMirror.owner.thisPrefix, ReflectMirror) + lazy val ReflectPackage = requiredModule[scala.reflect.`package`.type] + def ReflectBasis = getMemberValue(ReflectPackage, nme.basis) + lazy val ReflectRuntimePackage = getPackageObjectIfDefined("scala.reflect.runtime") // defined in scala-reflect.jar, so we need to be careful + def ReflectRuntimeUniverse = if (ReflectRuntimePackage != NoSymbol) getMemberValue(ReflectRuntimePackage, nme.universe) else NoSymbol + def ReflectRuntimeCurrentMirror = if (ReflectRuntimePackage != NoSymbol) getMemberMethod(ReflectRuntimePackage, nme.currentMirror) else NoSymbol lazy val PartialManifestClass = requiredClass[scala.reflect.ClassManifest[_]] lazy val PartialManifestModule = requiredModule[scala.reflect.ClassManifest.type] @@ -493,58 +461,53 @@ trait Definitions extends reflect.api.StandardDefinitions { lazy val OptManifestClass = requiredClass[scala.reflect.OptManifest[_]] lazy val NoManifest = requiredModule[scala.reflect.NoManifest.type] - lazy val ExprClass = getMember(requiredClass[scala.reflect.api.Exprs], tpnme.Expr) - def ExprTree = getMember(ExprClass, nme.tree) - def ExprTpe = getMember(ExprClass, nme.tpe) - def ExprEval = getMember(ExprClass, nme.eval) - def ExprValue = getMember(ExprClass, nme.value) - lazy val ExprModule = getMember(requiredClass[scala.reflect.api.Exprs], nme.Expr) + lazy val ExprsClass = getClassIfDefined("scala.reflect.api.Exprs") // defined in scala-reflect.jar, so we need to be careful + lazy val ExprClass = if (ExprsClass != NoSymbol) getMemberClass(ExprsClass, tpnme.Expr) else NoSymbol + def ExprSplice = if (ExprsClass != NoSymbol) getMemberMethod(ExprClass, nme.splice) else NoSymbol + def ExprValue = if (ExprsClass != NoSymbol) getMemberMethod(ExprClass, nme.value) else NoSymbol + lazy val ExprModule = if (ExprsClass != NoSymbol) getMemberModule(ExprsClass, nme.Expr) else NoSymbol - lazy val ArrayTagClass = requiredClass[scala.reflect.ArrayTag[_]] - lazy val ErasureTagClass = requiredClass[scala.reflect.ErasureTag[_]] lazy val ClassTagModule = requiredModule[scala.reflect.ClassTag[_]] lazy val ClassTagClass = requiredClass[scala.reflect.ClassTag[_]] - lazy val TypeTagsClass = requiredClass[scala.reflect.api.TypeTags] + lazy val TypeTagsClass = requiredClass[scala.reflect.base.TypeTags] + lazy val AbsTypeTagClass = getMemberClass(TypeTagsClass, tpnme.AbsTypeTag) + lazy val AbsTypeTagModule = getMemberModule(TypeTagsClass, nme.AbsTypeTag) lazy val TypeTagClass = getMemberClass(TypeTagsClass, tpnme.TypeTag) lazy val TypeTagModule = getMemberModule(TypeTagsClass, nme.TypeTag) - lazy val ConcreteTypeTagClass = getMemberClass(TypeTagsClass, tpnme.ConcreteTypeTag) - lazy val ConcreteTypeTagModule = getMemberModule(TypeTagsClass, nme.ConcreteTypeTag) - - def ArrayTagWrap = getMemberMethod(ArrayTagClass, nme.wrap) - def ArrayTagNewArray = getMemberMethod(ArrayTagClass, nme.newArray) - def ErasureTagErasure = getMemberMethod(ErasureTagClass, nme.erasure) - def ClassTagTpe = getMemberMethod(ClassTagClass, nme.tpe) - def TypeTagTpe = getMemberMethod(TypeTagClass, nme.tpe) - - lazy val MacroContextClass = requiredClass[scala.reflect.makro.Context] - def MacroContextPrefix = getMember(MacroContextClass, nme.prefix) - def MacroContextPrefixType = getMember(MacroContextClass, tpnme.PrefixType) - def MacroContextMirror = getMember(MacroContextClass, nme.mirror) - def MacroContextReify = getMember(MacroContextClass, nme.reify) - lazy val MacroImplAnnotation = requiredClass[scala.reflect.makro.internal.macroImpl] - lazy val MacroInternalPackage = getPackageObject("scala.reflect.makro.internal") - def MacroInternal_materializeArrayTag = getMemberMethod(MacroInternalPackage, nme.materializeArrayTag) - def MacroInternal_materializeErasureTag = getMemberMethod(MacroInternalPackage, nme.materializeErasureTag) - def MacroInternal_materializeClassTag = getMemberMethod(MacroInternalPackage, nme.materializeClassTag) - def MacroInternal_materializeTypeTag = getMemberMethod(MacroInternalPackage, nme.materializeTypeTag) - def MacroInternal_materializeConcreteTypeTag = getMemberMethod(MacroInternalPackage, nme.materializeConcreteTypeTag) + + lazy val BaseUniverseClass = requiredClass[scala.reflect.base.Universe] + lazy val ApiUniverseClass = getClassIfDefined("scala.reflect.api.Universe") // defined in scala-reflect.jar, so we need to be careful + def ApiUniverseReify = if (ApiUniverseClass != NoSymbol) getMemberMethod(ApiUniverseClass, nme.reify) else NoSymbol + lazy val JavaUniverseClass = getClassIfDefined("scala.reflect.api.JavaUniverse") // defined in scala-reflect.jar, so we need to be careful + + lazy val MirrorOfClass = requiredClass[scala.reflect.base.MirrorOf[_]] + + lazy val TypeCreatorClass = requiredClass[scala.reflect.base.TypeCreator] + lazy val TreeCreatorClass = requiredClass[scala.reflect.base.TreeCreator] + + lazy val MacroContextClass = getClassIfDefined("scala.reflect.makro.Context") // defined in scala-reflect.jar, so we need to be careful + def MacroContextPrefix = if (MacroContextClass != NoSymbol) getMemberMethod(MacroContextClass, nme.prefix) else NoSymbol + def MacroContextPrefixType = if (MacroContextClass != NoSymbol) getMemberType(MacroContextClass, tpnme.PrefixType) else NoSymbol + def MacroContextUniverse = if (MacroContextClass != NoSymbol) getMemberMethod(MacroContextClass, nme.universe) else NoSymbol + def MacroContextMirror = if (MacroContextClass != NoSymbol) getMemberMethod(MacroContextClass, nme.mirror) else NoSymbol + def MacroContextReify = if (MacroContextClass != NoSymbol) getMemberMethod(MacroContextClass, nme.reify) else NoSymbol + lazy val MacroImplAnnotation = requiredClass[scala.reflect.makro.internal.macroImpl] + lazy val MacroInternalPackage = getPackageObject("scala.reflect.makro.internal") + def MacroInternal_materializeClassTag = getMemberMethod(MacroInternalPackage, nme.materializeClassTag) + def MacroInternal_materializeAbsTypeTag = getMemberMethod(MacroInternalPackage, nme.materializeAbsTypeTag) + def MacroInternal_materializeTypeTag = getMemberMethod(MacroInternalPackage, nme.materializeTypeTag) lazy val ScalaSignatureAnnotation = requiredClass[scala.reflect.ScalaSignature] lazy val ScalaLongSignatureAnnotation = requiredClass[scala.reflect.ScalaLongSignature] // Option classes - lazy val OptionClass: Symbol = requiredClass[Option[_]] - lazy val SomeClass: Symbol = requiredClass[Some[_]] - lazy val NoneModule: Symbol = requiredModule[scala.None.type] - lazy val SomeModule: Symbol = requiredModule[scala.Some.type] - - // [Eugene] how do I make this work without casts? - // private lazy val importerFromRm = self.mkImporter(rm) - private lazy val importerFromRm = self.mkImporter(rm).asInstanceOf[self.Importer { val from: rm.type }] + lazy val OptionClass: ClassSymbol = requiredClass[Option[_]] + lazy val SomeClass: ClassSymbol = requiredClass[Some[_]] + lazy val NoneModule: ModuleSymbol = requiredModule[scala.None.type] + lazy val SomeModule: ModuleSymbol = requiredModule[scala.Some.type] - def compilerTypeFromTag(t: rm.TypeTag[_]): Type = importerFromRm.importType(t.tpe) - - def compilerSymbolFromTag(t: rm.TypeTag[_]): Symbol = importerFromRm.importSymbol(t.sym) + def compilerTypeFromTag(tt: BaseUniverse # AbsTypeTag[_]): Type = tt.in(rootMirror).tpe + def compilerSymbolFromTag(tt: BaseUniverse # AbsTypeTag[_]): Symbol = tt.in(rootMirror).tpe.typeSymbol // The given symbol represents either String.+ or StringAdd.+ def isStringAddition(sym: Symbol) = sym == String_+ || sym == StringAdd_+ @@ -566,20 +529,21 @@ trait Definitions extends reflect.api.StandardDefinitions { def isNoneType(tp: Type) = tp.typeSymbol eq NoneModule // Product, Tuple, Function, AbstractFunction - private def mkArityArray(name: String, arity: Int, countFrom: Int = 1): Array[Symbol] = { + private def mkArityArray(name: String, arity: Int, countFrom: Int): Array[ClassSymbol] = { val list = countFrom to arity map (i => getRequiredClass("scala." + name + i)) - if (countFrom == 0) list.toArray - else (NoSymbol +: list).toArray + list.toArray } - private def aritySpecificType(symbolArray: Array[Symbol], args: List[Type], others: Type*): Type = { + def prepend[S >: ClassSymbol : ClassTag](elem0: S, elems: Array[ClassSymbol]): Array[S] = elem0 +: elems + + private def aritySpecificType[S <: Symbol](symbolArray: Array[S], args: List[Type], others: Type*): Type = { val arity = args.length if (arity >= symbolArray.length) NoType else appliedType(symbolArray(arity), args ++ others: _*) } val MaxTupleArity, MaxProductArity, MaxFunctionArity = 22 - lazy val ProductClass = { val arr = mkArityArray("Product", MaxProductArity) ; arr(0) = UnitClass ; arr } - lazy val TupleClass = mkArityArray("Tuple", MaxTupleArity) + lazy val ProductClass: Array[ClassSymbol] = prepend(UnitClass, mkArityArray("Product", MaxProductArity, 1)) + lazy val TupleClass: Array[Symbol] = prepend(NoSymbol, mkArityArray("Tuple", MaxTupleArity, 1)) lazy val FunctionClass = mkArityArray("Function", MaxFunctionArity, 0) lazy val AbstractFunctionClass = mkArityArray("runtime.AbstractFunction", MaxFunctionArity, 0) @@ -607,7 +571,7 @@ trait Definitions extends reflect.api.StandardDefinitions { @deprecated("Use isTupleType", "2.10.0") def isTupleTypeOrSubtype(tp: Type) = isTupleType(tp) - def tupleField(n: Int, j: Int) = getMember(TupleClass(n), nme.productAccessorName(j)) + def tupleField(n: Int, j: Int) = getMemberValue(TupleClass(n), nme.productAccessorName(j)) // NOTE: returns true for NoSymbol since it's included in the TupleClass array -- is this intensional? def isTupleSymbol(sym: Symbol) = TupleClass contains unspecializedSymbol(sym) def isProductNClass(sym: Symbol) = ProductClass contains sym @@ -655,8 +619,8 @@ trait Definitions extends reflect.api.StandardDefinitions { def Product_canEqual = getMemberMethod(ProductRootClass, nme.canEqual_) // def Product_productElementName = getMemberMethod(ProductRootClass, nme.productElementName) - def productProj(z:Symbol, j: Int): Symbol = getMember(z, nme.productAccessorName(j)) - def productProj(n: Int, j: Int): Symbol = productProj(ProductClass(n), j) + def productProj(z:Symbol, j: Int): TermSymbol = getMemberValue(z, nme.productAccessorName(j)) + def productProj(n: Int, j: Int): TermSymbol = productProj(ProductClass(n), j) /** returns true if this type is exactly ProductN[T1,...,Tn], not some subclass */ def isExactProductType(tp: Type): Boolean = isProductNClass(tp.typeSymbol) @@ -672,7 +636,7 @@ trait Definitions extends reflect.api.StandardDefinitions { case tp => tp } - def functionApply(n: Int) = getMember(FunctionClass(n), nme.apply) + def functionApply(n: Int) = getMemberMethod(FunctionClass(n), nme.apply) def abstractFunctionForFunctionType(tp: Type) = if (isFunctionType(tp)) abstractFunctionType(tp.typeArgs.init, tp.typeArgs.last) @@ -743,9 +707,9 @@ trait Definitions extends reflect.api.StandardDefinitions { lazy val ComparatorClass = getRequiredClass("scala.runtime.Comparator") // System.ValueType - lazy val ValueTypeClass: Symbol = getClass(sn.ValueType) + lazy val ValueTypeClass: ClassSymbol = getClassByName(sn.ValueType) // System.MulticastDelegate - lazy val DelegateClass: Symbol = getClass(sn.Delegate) + lazy val DelegateClass: ClassSymbol = getClassByName(sn.Delegate) var Delegate_scalaCallers: List[Symbol] = List() // Syncnote: No protection necessary yet as only for .NET where reflection is not supported. // Symbol -> (Symbol, Type): scalaCaller -> (scalaMethodSym, DelegateType) // var Delegate_scalaCallerInfos: HashMap[Symbol, (Symbol, Type)] = _ @@ -784,7 +748,7 @@ trait Definitions extends reflect.api.StandardDefinitions { // Since getClass is not actually a polymorphic method, this requires compiler // participation. At the "Any" level, the return type is Class[_] as it is in // java.lang.Object. Java also special cases the return type. - lazy val Any_getClass = enterNewMethod(AnyClass, nme.getClass_, Nil, getMember(ObjectClass, nme.getClass_).tpe.resultType, DEFERRED) + lazy val Any_getClass = enterNewMethod(AnyClass, nme.getClass_, Nil, getMemberMethod(ObjectClass, nme.getClass_).tpe.resultType, DEFERRED) lazy val Any_isInstanceOf = newT1NullaryMethod(AnyClass, nme.isInstanceOf_, FINAL)(_ => booltype) lazy val Any_asInstanceOf = newT1NullaryMethod(AnyClass, nme.asInstanceOf_, FINAL)(_.typeConstructor) @@ -816,7 +780,7 @@ trait Definitions extends reflect.api.StandardDefinitions { existentialAbstraction( eparams, - ClassType(eparams.head setInfo TypeBounds.upper(upperBound) tpe) + ClassType((eparams.head setInfo TypeBounds.upper(upperBound)).tpe) ) } } @@ -884,14 +848,14 @@ trait Definitions extends reflect.api.StandardDefinitions { ) lazy val String_+ = enterNewMethod(StringClass, nme.raw.PLUS, anyparam, stringtype, FINAL) - def Object_getClass = getMember(ObjectClass, nme.getClass_) - def Object_clone = getMember(ObjectClass, nme.clone_) - def Object_finalize = getMember(ObjectClass, nme.finalize_) - def Object_notify = getMember(ObjectClass, nme.notify_) - def Object_notifyAll = getMember(ObjectClass, nme.notifyAll_) - def Object_equals = getMember(ObjectClass, nme.equals_) - def Object_hashCode = getMember(ObjectClass, nme.hashCode_) - def Object_toString = getMember(ObjectClass, nme.toString_) + def Object_getClass = getMemberMethod(ObjectClass, nme.getClass_) + def Object_clone = getMemberMethod(ObjectClass, nme.clone_) + def Object_finalize = getMemberMethod(ObjectClass, nme.finalize_) + def Object_notify = getMemberMethod(ObjectClass, nme.notify_) + def Object_notifyAll = getMemberMethod(ObjectClass, nme.notifyAll_) + def Object_equals = getMemberMethod(ObjectClass, nme.equals_) + def Object_hashCode = getMemberMethod(ObjectClass, nme.hashCode_) + def Object_toString = getMemberMethod(ObjectClass, nme.toString_) // boxed classes lazy val ObjectRefClass = requiredClass[scala.runtime.ObjectRef[_]] @@ -899,9 +863,9 @@ trait Definitions extends reflect.api.StandardDefinitions { lazy val RuntimeStaticsModule = getRequiredModule("scala.runtime.Statics") lazy val BoxesRunTimeModule = getRequiredModule("scala.runtime.BoxesRunTime") lazy val BoxesRunTimeClass = BoxesRunTimeModule.moduleClass - lazy val BoxedNumberClass = getClass(sn.BoxedNumber) - lazy val BoxedCharacterClass = getClass(sn.BoxedCharacter) - lazy val BoxedBooleanClass = getClass(sn.BoxedBoolean) + lazy val BoxedNumberClass = getClassByName(sn.BoxedNumber) + lazy val BoxedCharacterClass = getClassByName(sn.BoxedCharacter) + lazy val BoxedBooleanClass = getClassByName(sn.BoxedBoolean) lazy val BoxedByteClass = requiredClass[java.lang.Byte] lazy val BoxedShortClass = requiredClass[java.lang.Short] lazy val BoxedIntClass = requiredClass[java.lang.Integer] @@ -909,13 +873,13 @@ trait Definitions extends reflect.api.StandardDefinitions { lazy val BoxedFloatClass = requiredClass[java.lang.Float] lazy val BoxedDoubleClass = requiredClass[java.lang.Double] - lazy val Boxes_isNumberOrBool = getDecl(BoxesRunTimeClass, nme.isBoxedNumberOrBoolean) - lazy val Boxes_isNumber = getDecl(BoxesRunTimeClass, nme.isBoxedNumber) + lazy val Boxes_isNumberOrBool = getDecl(BoxesRunTimeClass, nme.isBoxedNumberOrBoolean) + lazy val Boxes_isNumber = getDecl(BoxesRunTimeClass, nme.isBoxedNumber) lazy val BoxedUnitClass = requiredClass[scala.runtime.BoxedUnit] lazy val BoxedUnitModule = getRequiredModule("scala.runtime.BoxedUnit") - def BoxedUnit_UNIT = getMember(BoxedUnitModule, nme.UNIT) - def BoxedUnit_TYPE = getMember(BoxedUnitModule, nme.TYPE_) + def BoxedUnit_UNIT = getMemberValue(BoxedUnitModule, nme.UNIT) + def BoxedUnit_TYPE = getMemberValue(BoxedUnitModule, nme.TYPE_) // Annotation base classes lazy val AnnotationClass = requiredClass[scala.annotation.Annotation] @@ -966,7 +930,7 @@ trait Definitions extends reflect.api.StandardDefinitions { // Language features lazy val languageFeatureModule = getRequiredModule("scala.languageFeature") - lazy val experimentalModule = getMember(languageFeatureModule, nme.experimental) + lazy val experimentalModule = getMemberModule(languageFeatureModule, nme.experimental) lazy val MacrosFeature = getLanguageFeature("macros", experimentalModule) lazy val DynamicsFeature = getLanguageFeature("dynamics") lazy val PostfixOpsFeature = getLanguageFeature("postfixOps") @@ -985,99 +949,33 @@ trait Definitions extends reflect.api.StandardDefinitions { BeanGetterTargetClass, BeanSetterTargetClass ) - lazy val AnnotationDefaultAttr: Symbol = { + lazy val AnnotationDefaultAttr: ClassSymbol = { val attr = enterNewClass(RuntimePackageClass, tpnme.AnnotationDefaultATTR, List(AnnotationClass.tpe)) // This attribute needs a constructor so that modifiers in parsed Java code make sense attr.info.decls enter attr.newClassConstructor(NoPosition) attr } - def getPackageObjectClass(fullname: String): Symbol = - getPackageObject(fullname).companionClass - - def getPackageObject(fullname: String): Symbol = - getModule(newTermName(fullname)).info member nme.PACKAGE - - def getModule(fullname: Name): ModuleSymbol = - getModuleOrClass(fullname.toTermName) match { - case x: ModuleSymbol => x - case _ => MissingRequirementError.notFound("object " + fullname) - } + @deprecated("Moved to rootMirror.getClass", "2.10.0") + def getClass(fullname: Name): ClassSymbol = rootMirror.getClassByName(fullname) - def getPackage(fullname: Name): PackageSymbol = - getModuleOrClass(fullname.toTermName) match { - case x: PackageSymbol => x - case _ => MissingRequirementError.notFound("package " + fullname) - } - @inline private def wrapMissing(body: => Symbol): Symbol = - try body - catch { case _: MissingRequirementError => NoSymbol } + @deprecated("Moved to rootMirror.getModule", "2.10.0") + def getModule(fullname: Name): ModuleSymbol = rootMirror.getModule(fullname) private def fatalMissingSymbol(owner: Symbol, name: Name, what: String = "member") = { throw new FatalError(owner + " does not have a " + what + " " + name) } - @deprecated("Use getClassByName", "2.10.0") - def getClass(fullname: Name): Symbol = getClassByName(fullname) - - def getRequiredPackage(fullname: String): PackageSymbol = - getPackage(newTermNameCached(fullname)) - - def getRequiredModule(fullname: String): ModuleSymbol = - getModule(newTermNameCached(fullname)) - - def erasureName[T: ErasureTag] : String = { - /** We'd like the String representation to be a valid - * scala type, so we have to decode the jvm's secret language. - */ - def erasureString(clazz: Class[_]): String = { - if (clazz.isArray) "Array[" + erasureString(clazz.getComponentType) + "]" - else clazz.getName - } - erasureString(implicitly[ErasureTag[T]].erasure) - } - - def requiredClass[T: ClassTag] : ClassSymbol = getRequiredClass(erasureName[T]) - - // TODO: What syntax do we think should work here? Say you have an object - // like scala.Predef. You can't say requiredModule[scala.Predef] since there's - // no accompanying Predef class, and if you say requiredModule[scala.Predef.type] - // the name found via the erasure is scala.Predef$. For now I am - // removing the trailing $, but I think that classTag should have - // a method which returns a usable name, one which doesn't expose this - // detail of the backend. - def requiredModule[T: ClassTag] : ModuleSymbol = - getRequiredModule(erasureName[T] stripSuffix "$") - - def getRequiredClass(fullname: String): ClassSymbol = - getClassByName(newTypeNameCached(fullname)) match { - case x: ClassSymbol => x - case _ => MissingRequirementError.notFound("class " + fullname) - } - - def getClassIfDefined(fullname: String): Symbol = - getClassIfDefined(newTypeName(fullname)) - - def getClassIfDefined(fullname: Name): Symbol = - wrapMissing(getClass(fullname.toTypeName)) - - def getModuleIfDefined(fullname: String): Symbol = - getModuleIfDefined(newTermName(fullname)) - - def getModuleIfDefined(fullname: Name): Symbol = - wrapMissing(getModule(fullname.toTermName)) - - def getLanguageFeature(name: String, owner: Symbol = languageFeatureModule) = + def getLanguageFeature(name: String, owner: Symbol = languageFeatureModule): Symbol = + // [Eugene++] `getMemberClass` leads to crashes in mixin: + // "object languageFeature does not have a member class implicitConversions" + // that's because by that time `implicitConversions` becomes a module + // getMemberClass(owner, newTypeName(name)) getMember(owner, newTypeName(name)) def termMember(owner: Symbol, name: String): Symbol = owner.info.member(newTermName(name)) def typeMember(owner: Symbol, name: String): Symbol = owner.info.member(newTypeName(name)) - def findMemberFromRoot(fullName: Name): Symbol = { - val segs = nme.segments(fullName.toString, fullName.isTermName) - if (segs.isEmpty) NoSymbol - else findNamedMember(segs.tail, definitions.RootClass.info member segs.head) - } def findNamedMember(fullName: Name, root: Symbol): Symbol = { val segs = nme.segments(fullName.toString, fullName.isTermName) if (segs.isEmpty || segs.head != root.simpleName) NoSymbol @@ -1097,22 +995,81 @@ trait Definitions extends reflect.api.StandardDefinitions { else fatalMissingSymbol(owner, name) } } + def getMemberValue(owner: Symbol, name: Name): TermSymbol = { + // [Eugene++] should be a ClassCastException instead? + getMember(owner, name.toTermName) match { + case x: TermSymbol => x + case _ => fatalMissingSymbol(owner, name, "member value") + } + } def getMemberModule(owner: Symbol, name: Name): ModuleSymbol = { + // [Eugene++] should be a ClassCastException instead? getMember(owner, name.toTermName) match { case x: ModuleSymbol => x case _ => fatalMissingSymbol(owner, name, "member object") } } + def getMemberType(owner: Symbol, name: Name): TypeSymbol = { + // [Eugene++] should be a ClassCastException instead? + getMember(owner, name.toTypeName) match { + case x: TypeSymbol => x + case _ => fatalMissingSymbol(owner, name, "member type") + } + } def getMemberClass(owner: Symbol, name: Name): ClassSymbol = { + // [Eugene++] should be a ClassCastException instead? + val y = getMember(owner, name.toTypeName) getMember(owner, name.toTypeName) match { case x: ClassSymbol => x case _ => fatalMissingSymbol(owner, name, "member class") } } - def getMemberMethod(owner: Symbol, name: Name): MethodSymbol = { + def getMemberMethod(owner: Symbol, name: Name): TermSymbol = { + // [Eugene++] is this a bug? + // + // System.err.println(result.getClass) + // System.err.println(result.flags) + // System.err.println("isMethod = " + result.isMethod) + // System.err.println("isTerm = " + result.isTerm) + // System.err.println("isValue = " + result.isValue) + // result.asMethodSymbol + // + // prints this: + // + // quick.lib: + // [javac] Compiling 1 source file to C:\Projects\KeplerUnderRefactoring\build\quick\classes\library + // [scalacfork] Compiling 769 files to C:\Projects\KeplerUnderRefactoring\build\quick\classes\library + // [scalacfork] class scala.reflect.internal.Symbols$TermSymbol + // [scalacfork] 8589934592 + // [scalacfork] isMethod = false + // [scalacfork] isTerm = true + // [scalacfork] isValue = true + // [scalacfork] + // [scalacfork] while compiling: C:\Projects\KeplerUnderRefactoring\src\library\scala\LowPriorityImplicits.scala + // [scalacfork] current phase: cleanup + // [scalacfork] library version: version 2.10.0-20120507-185519-665d1d9127 + // [scalacfork] compiler version: version 2.10.0-20120507-185519-665d1d9127 + // [scalacfork] reconstructed args: -Xmacros -classpath C:\\Projects\\KeplerUnderRefactoring\\build\\quick\\classes\\library;C:\\Projects\\KeplerUnderRefactoring\\lib\\forkjoin.jar -d C:\\Projects\\KeplerUnderRefactoring\\build\\quick\\classes\\library -sourcepath C:\\Projects\\KeplerUnderRefactoring\\src\\library + // [scalacfork] + // [scalacfork] unhandled exception while transforming LowPriorityImplicits.scala + // [scalacfork] error: + // [scalacfork] while compiling: C:\Projects\KeplerUnderRefactoring\src\library\scala\LowPriorityImplicits.scala + // [scalacfork] current phase: cleanup + // [scalacfork] library version: version 2.10.0-20120507-185519-665d1d9127 + // [scalacfork] compiler version: version 2.10.0-20120507-185519-665d1d9127 + // [scalacfork] reconstructed args: -Xmacros -classpath C:\\Projects\\KeplerUnderRefactoring\\build\\quick\\classes\\library;C:\\Projects\\KeplerUnderRefactoring\\lib\\forkjoin.jar -d C:\\Projects\\KeplerUnderRefactoring\\build\\quick\\classes\\library -sourcepath C:\\Projects\\KeplerUnderRefactoring\\src\\library + // [scalacfork] + // [scalacfork] uncaught exception during compilation: java.lang.ClassCastException + // [scalacfork] error: java.lang.ClassCastException: value apply + // [scalacfork] at scala.reflect.base.Symbols$SymbolBase$class.asMethodSymbol(Symbols.scala:118) + // [scalacfork] at scala.reflect.internal.Symbols$SymbolContextApiImpl.asMethodSymbol(Symbols.scala:63) + // [scalacfork] at scala.reflect.internal.Definitions$DefinitionsClass.Symbol_apply(Definitions.scala:381) + + // [Eugene++] should be a ClassCastException instead? getMember(owner, name.toTermName) match { - case x: MethodSymbol => x - case _ => fatalMissingSymbol(owner, name, "method") + // case x: MethodSymbol => x + case x: TermSymbol => x + case _ => fatalMissingSymbol(owner, name, "method") } } @@ -1132,34 +1089,6 @@ trait Definitions extends reflect.api.StandardDefinitions { def packageExists(packageName: String): Boolean = getModuleIfDefined(packageName).isPackage - private def getModuleOrClass(path: Name, len: Int): Symbol = { - val point = path lastPos('.', len - 1) - val owner = - if (point > 0) getModuleOrClass(path.toTermName, point) - else RootClass - val name = path subName (point + 1, len) - val sym = owner.info member name - val result = if (path.isTermName) sym.suchThat(_ hasFlag MODULE) else sym - if (result != NoSymbol) result - else { - if (settings.debug.value) { log(sym.info); log(sym.info.members) }//debug - missingHook(owner, name) orElse { - MissingRequirementError.notFound((if (path.isTermName) "object " else "class ")+path) - } - } - } - - /** If you're looking for a class, pass a type name. - * If a module, a term name. - */ - private def getModuleOrClass(path: Name): Symbol = getModuleOrClass(path, path.length) - - def getClassByName(fullname: Name): Symbol = { - var result = getModuleOrClass(fullname.toTypeName) - while (result.isAliasType) result = result.info.typeSymbol - result - } - private def newAlias(owner: Symbol, name: TypeName, alias: Type): AliasTypeSymbol = owner.newAliasType(name) setInfoAndEnter alias @@ -1218,7 +1147,7 @@ trait Definitions extends reflect.api.StandardDefinitions { def unboxedValueClass(sym: Symbol): Symbol = if (isPrimitiveValueClass(sym)) sym else if (sym == BoxedUnitClass) UnitClass - else boxedClass.map(_.swap).getOrElse(sym, NoSymbol) + else boxedClass.map(kvp => (kvp._2: Symbol, kvp._1)).getOrElse(sym, NoSymbol) /** Is type's symbol a numeric value class? */ def isNumericValueType(tp: Type): Boolean = tp match { @@ -1247,28 +1176,7 @@ trait Definitions extends reflect.api.StandardDefinitions { else flatNameString(etp.typeSymbol, '.') } - /** getModule2/getClass2 aren't needed at present but may be again, - * so for now they're mothballed. - */ - // def getModule2(name1: Name, name2: Name) = { - // try getModuleOrClass(name1.toTermName) - // catch { case ex1: FatalError => - // try getModuleOrClass(name2.toTermName) - // catch { case ex2: FatalError => throw ex1 } - // } - // } - // def getClass2(name1: Name, name2: Name) = { - // try { - // val result = getModuleOrClass(name1.toTypeName) - // if (result.isAliasType) getClass(name2) else result - // } - // catch { case ex1: FatalError => - // try getModuleOrClass(name2.toTypeName) - // catch { case ex2: FatalError => throw ex1 } - // } - // } - - /** Surgery on the value classes. Without this, AnyVals defined in source + /** Surgery on the value classes. Without this, AnyVals defined in source * files end up with an AnyRef parent. It is likely there is a better way * to evade that AnyRef. */ @@ -1282,17 +1190,6 @@ trait Definitions extends reflect.api.StandardDefinitions { def init() { if (isInitialized) return - // Still fiddling with whether it's cleaner to do some of this setup here - // or from constructors. The latter approach tends to invite init order issues. - EmptyPackageClass setInfo ClassInfoType(Nil, newPackageScope(EmptyPackageClass), EmptyPackageClass) - EmptyPackage setInfo EmptyPackageClass.tpe - - connectModuleToClass(EmptyPackage, EmptyPackageClass) - connectModuleToClass(RootPackage, RootClass) - - RootClass.info.decls enter EmptyPackage - RootClass.info.decls enter RootPackage - val forced = List( // force initialization of every symbol that is entered as a side effect AnnotationDefaultAttr, // #2264 RepeatedParamClass, @@ -1331,7 +1228,7 @@ trait Definitions extends reflect.api.StandardDefinitions { } //init var nbScalaCallers: Int = 0 - def newScalaCaller(delegateType: Type): Symbol = { + def newScalaCaller(delegateType: Type): MethodSymbol = { assert(forMSIL, "scalaCallers can only be created if target is .NET") // object: reference to object on which to call (scala-)method val paramTypes: List[Type] = List(ObjectClass.tpe) diff --git a/src/compiler/scala/reflect/internal/ExistentialsAndSkolems.scala b/src/reflect/scala/reflect/internal/ExistentialsAndSkolems.scala index f1fe4fc118..f1fe4fc118 100644 --- a/src/compiler/scala/reflect/internal/ExistentialsAndSkolems.scala +++ b/src/reflect/scala/reflect/internal/ExistentialsAndSkolems.scala diff --git a/src/compiler/scala/reflect/internal/FatalError.scala b/src/reflect/scala/reflect/internal/FatalError.scala index c843308480..c843308480 100644 --- a/src/compiler/scala/reflect/internal/FatalError.scala +++ b/src/reflect/scala/reflect/internal/FatalError.scala diff --git a/src/reflect/scala/reflect/internal/FlagSets.scala b/src/reflect/scala/reflect/internal/FlagSets.scala new file mode 100644 index 0000000000..0354d2513c --- /dev/null +++ b/src/reflect/scala/reflect/internal/FlagSets.scala @@ -0,0 +1,66 @@ +package scala.reflect +package internal + +import language.implicitConversions + +trait FlagSets extends api.FlagSets { self: SymbolTable => + + type FlagSet = Long + implicit val FlagSetTag = ClassTag[FlagSet](classOf[FlagSet]) + + implicit def addFlagOps(left: FlagSet): FlagOps = + new FlagOpsImpl(left) + + private class FlagOpsImpl(left: Long) extends FlagOps { + def | (right: Long): Long = left | right + def & (right: Long): Long = left & right + def containsAll (right: Long): Boolean = (right & ~left) == 0 + } + + val NoFlags: FlagSet = 0L + + trait FlagValues extends FlagValuesApi + + object Flag extends FlagValues { + val TRAIT : FlagSet = Flags.TRAIT + val MODULE : FlagSet = Flags.MODULE + val MUTABLE : FlagSet = Flags.MUTABLE + val PACKAGE : FlagSet = Flags.PACKAGE + val METHOD : FlagSet = Flags.METHOD + val MACRO : FlagSet = Flags.MACRO + val DEFERRED : FlagSet = Flags.DEFERRED + val ABSTRACT : FlagSet = Flags.ABSTRACT + val FINAL : FlagSet = Flags.FINAL + val SEALED : FlagSet = Flags.SEALED + val IMPLICIT : FlagSet = Flags.IMPLICIT + val LAZY : FlagSet = Flags.LAZY + val OVERRIDE : FlagSet = Flags.OVERRIDE + val PRIVATE : FlagSet = Flags.PRIVATE + val PROTECTED : FlagSet = Flags.PROTECTED + val CASE : FlagSet = Flags.CASE + val ABSOVERRIDE : FlagSet = Flags.ABSOVERRIDE + val BYNAMEPARAM : FlagSet = Flags.BYNAMEPARAM + val PARAM : FlagSet = Flags.PARAM + val PARAMACCESSOR : FlagSet = Flags.PARAMACCESSOR + val CASEACCESSOR : FlagSet = Flags.CASEACCESSOR + val COVARIANT : FlagSet = Flags.COVARIANT + val CONTRAVARIANT : FlagSet = Flags.CONTRAVARIANT + val DEFAULTPARAM : FlagSet = Flags.DEFAULTPARAM + val INTERFACE : FlagSet = Flags.INTERFACE + + def union(flags: FlagSet*): FlagSet = { + var acc = 0L + for (flag <- flags) acc |= flag + acc + } + + def intersection(flags: FlagSet*): FlagSet = { + var acc = -1L + for (flag <- flags) acc &= flag + acc + } + + def containsAll(superset: FlagSet, subset: FlagSet): Boolean = + (subset & ~superset) == 0 + } +} diff --git a/src/compiler/scala/reflect/internal/Flags.scala b/src/reflect/scala/reflect/internal/Flags.scala index e6820cf78a..37e5a23819 100644 --- a/src/compiler/scala/reflect/internal/Flags.scala +++ b/src/reflect/scala/reflect/internal/Flags.scala @@ -6,7 +6,6 @@ package scala.reflect package internal -import api.Modifier import scala.collection.{ mutable, immutable } // Flags at each index of a flags Long. Those marked with /M are used in @@ -479,46 +478,6 @@ class Flags extends ModifierFlags { front.toList ++ (all filterNot (front contains _)) } final val rawFlagPickledOrder: Array[Long] = pickledListOrder.toArray - - def flagOfModifier(mod: Modifier): Long = mod match { - case Modifier.`protected` => PROTECTED - case Modifier.`private` => PRIVATE - case Modifier.`override` => OVERRIDE - case Modifier.`abstract` => ABSTRACT - case Modifier.`final` => FINAL - case Modifier.`sealed` => SEALED - case Modifier.`implicit` => IMPLICIT - case Modifier.`lazy` => LAZY - case Modifier.`case` => CASE - case Modifier.`trait` => TRAIT - case Modifier.deferred => DEFERRED - case Modifier.interface => INTERFACE - case Modifier.mutable => MUTABLE - case Modifier.parameter => PARAM - case Modifier.`macro` => MACRO - case Modifier.covariant => COVARIANT - case Modifier.contravariant => CONTRAVARIANT - case Modifier.preSuper => PRESUPER - case Modifier.abstractOverride => ABSOVERRIDE - case Modifier.local => LOCAL - case Modifier.java => JAVA - case Modifier.static => STATIC - case Modifier.caseAccessor => CASEACCESSOR - case Modifier.defaultParameter => DEFAULTPARAM - case Modifier.defaultInit => DEFAULTINIT - case Modifier.paramAccessor => PARAMACCESSOR - case Modifier.bynameParameter => BYNAMEPARAM - case _ => 0 - } - - def flagsOfModifiers(mods: List[Modifier]): Long = - (mods :\ 0L) { (mod, curr) => curr | flagOfModifier(mod) } - - def modifierOfFlag(flag: Long): Option[Modifier] = - Modifier.values find { mod => flagOfModifier(mod) == flag } - - def modifiersOfFlags(flags: Long): List[Modifier] = - pickledListOrder map (mask => modifierOfFlag(flags & mask)) flatMap { mod => mod } } object Flags extends Flags { } diff --git a/src/compiler/scala/reflect/internal/HasFlags.scala b/src/reflect/scala/reflect/internal/HasFlags.scala index 0937577ca3..c7c0882209 100644 --- a/src/compiler/scala/reflect/internal/HasFlags.scala +++ b/src/reflect/scala/reflect/internal/HasFlags.scala @@ -102,6 +102,7 @@ trait HasFlags { def isOverride = hasFlag(OVERRIDE) def isParamAccessor = hasFlag(PARAMACCESSOR) def isPrivate = hasFlag(PRIVATE) + def isPackage = hasFlag(PACKAGE) def isPrivateLocal = hasAllFlags(PrivateLocal) def isProtected = hasFlag(PROTECTED) def isProtectedLocal = hasAllFlags(ProtectedLocal) diff --git a/src/compiler/scala/reflect/internal/Importers.scala b/src/reflect/scala/reflect/internal/Importers.scala index 6d6a0ec317..431d9819a5 100644 --- a/src/compiler/scala/reflect/internal/Importers.scala +++ b/src/reflect/scala/reflect/internal/Importers.scala @@ -2,6 +2,7 @@ package scala.reflect package internal import scala.collection.mutable.WeakHashMap +// todo: move importers to a mirror trait Importers { self: SymbolTable => // [Eugene] possible to make this less cast-heavy? @@ -70,9 +71,9 @@ trait Importers { self: SymbolTable => linkReferenced(myowner.newMethod(myname, mypos, myflags), x, importSymbol) case x: from.ModuleSymbol => linkReferenced(myowner.newModuleSymbol(myname, mypos, myflags), x, importSymbol) - case x: from.FreeTerm => + case x: from.FreeTermSymbol => newFreeTermSymbol(importName(x.name).toTermName, importType(x.info), x.value, x.flags, x.origin) - case x: from.FreeType => + case x: from.FreeTypeSymbol => newFreeTypeSymbol(importName(x.name).toTypeName, importType(x.info), x.value, x.flags, x.origin) case x: from.TermSymbol => linkReferenced(myowner.newValue(myname, mypos, myflags), x, importSymbol) @@ -124,7 +125,7 @@ trait Importers { self: SymbolTable => else if (sym == from.NoSymbol) NoSymbol else if (sym.isRoot) - definitions.RootClass + rootMirror.RootClass // !!! replace with actual mirror when we move importers to the mirror else { val name = sym.name val owner = sym.owner @@ -376,8 +377,6 @@ trait Importers { self: SymbolTable => new ApplyToImplicitArgs(importTree(fun), args map importTree) case _: from.ApplyImplicitView => new ApplyImplicitView(importTree(fun), args map importTree) - case _: from.ApplyConstructor => - new ApplyConstructor(importTree(fun), args map importTree) case _ => new Apply(importTree(fun), args map importTree) } @@ -418,17 +417,17 @@ trait Importers { self: SymbolTable => } addFixup({ if (mytree != null) { - val mysym = if (tree hasSymbol) importSymbol(tree.symbol) else NoSymbol + val mysym = if (tree.hasSymbol) importSymbol(tree.symbol) else NoSymbol val mytpe = importType(tree.tpe) mytree match { case mytt: TypeTree => val tt = tree.asInstanceOf[from.TypeTree] - if (mytree hasSymbol) mytt.symbol = mysym + if (mytree.hasSymbol) mytt.symbol = mysym if (tt.wasEmpty) mytt.defineType(mytpe) else mytt.setType(mytpe) if (tt.original != null) mytt.setOriginal(importTree(tt.original)) case _ => - if (mytree hasSymbol) mytree.symbol = importSymbol(tree.symbol) + if (mytree.hasSymbol) mytree.symbol = importSymbol(tree.symbol) mytree.tpe = importType(tree.tpe) } } diff --git a/src/compiler/scala/reflect/internal/InfoTransformers.scala b/src/reflect/scala/reflect/internal/InfoTransformers.scala index e53f714c0c..e53f714c0c 100644 --- a/src/compiler/scala/reflect/internal/InfoTransformers.scala +++ b/src/reflect/scala/reflect/internal/InfoTransformers.scala diff --git a/src/compiler/scala/reflect/internal/Kinds.scala b/src/reflect/scala/reflect/internal/Kinds.scala index eca63c7c15..b736a9192f 100644 --- a/src/compiler/scala/reflect/internal/Kinds.scala +++ b/src/reflect/scala/reflect/internal/Kinds.scala @@ -7,7 +7,7 @@ package scala.reflect package internal import scala.collection.{ mutable, immutable } -import scala.tools.util.StringOps.{ countAsString, countElementsAsString } +import scala.reflect.internal.util.StringOps.{ countAsString, countElementsAsString } trait Kinds { self: SymbolTable => diff --git a/src/reflect/scala/reflect/internal/Mirrors.scala b/src/reflect/scala/reflect/internal/Mirrors.scala new file mode 100644 index 0000000000..e3680b14d5 --- /dev/null +++ b/src/reflect/scala/reflect/internal/Mirrors.scala @@ -0,0 +1,243 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2011 LAMP/EPFL + * Copyright 2005-2011 LAMP/EPFL + * @author Martin Odersky + */ + +package scala.reflect +package internal + +import Flags._ + +trait Mirrors extends api.Mirrors { + self: SymbolTable => + + override type Mirror >: Null <: RootsBase + + abstract class RootsBase(rootOwner: Symbol) extends MirrorOf[Mirrors.this.type] { thisMirror => + + protected[scala] def rootLoader: LazyType + + val RootClass: ClassSymbol + val RootPackage: ModuleSymbol + val EmptyPackageClass: ClassSymbol + val EmptyPackage: ModuleSymbol + + def findMemberFromRoot(fullName: Name): Symbol = { + val segs = nme.segments(fullName.toString, fullName.isTermName) + if (segs.isEmpty) NoSymbol + else definitions.findNamedMember(segs.tail, RootClass.info member segs.head) + } + + /** Todo: organize similar to mkStatic in reflect.Base */ + private def getModuleOrClass(path: Name, len: Int): Symbol = { + val point = path lastPos('.', len - 1) + val owner = + if (point > 0) getModuleOrClass(path.toTermName, point) + else RootClass + val name = path subName (point + 1, len) + val sym = owner.info member name + val result = if (path.isTermName) sym.suchThat(_ hasFlag MODULE) else sym + if (result != NoSymbol) result + else { + if (settings.debug.value) { log(sym.info); log(sym.info.members) }//debug + mirrorMissingHook(owner, name) orElse symbolTableMissingHook(owner, name) orElse { + MissingRequirementError.notFound((if (path.isTermName) "object " else "class ")+path+" in "+thisMirror) + } + } + } + + protected def mirrorMissingHook(owner: Symbol, name: Name): Symbol = NoSymbol + + protected def symbolTableMissingHook(owner: Symbol, name: Name): Symbol = self.missingHook(owner, name) + + /** If you're looking for a class, pass a type name. + * If a module, a term name. + */ + private def getModuleOrClass(path: Name): Symbol = getModuleOrClass(path, path.length) + + override def staticClass(fullName: String): ClassSymbol = getRequiredClass(fullName) + + // todo: get rid of most creation methods and keep just staticClass/Module/Package + + def getClassByName(fullname: Name): ClassSymbol = { + var result = getModuleOrClass(fullname.toTypeName) + while (result.isAliasType) result = result.info.typeSymbol + result match { + case x: ClassSymbol => x + case _ => MissingRequirementError.notFound("class " + fullname) + } + } + + override def staticModule(fullName: String): ModuleSymbol = getRequiredModule(fullName) + + def getModule(fullname: Name): ModuleSymbol = + // [Eugene++] should be a ClassCastException instead? + getModuleOrClass(fullname.toTermName) match { + case x: ModuleSymbol => x + case _ => MissingRequirementError.notFound("object " + fullname) + } + + def getPackage(fullname: Name): ModuleSymbol = getModule(fullname) + + def getRequiredPackage(fullname: String): ModuleSymbol = + getPackage(newTermNameCached(fullname)) + + @deprecated("Use getClassByName", "2.10.0") + def getClass(fullname: Name): ClassSymbol = getClassByName(fullname) + + def getRequiredClass(fullname: String): ClassSymbol = + getClassByName(newTypeNameCached(fullname)) match { + case x: ClassSymbol => x + case _ => MissingRequirementError.notFound("class " + fullname) + } + + def getRequiredModule(fullname: String): ModuleSymbol = + getModule(newTermNameCached(fullname)) + + def erasureName[T: ClassTag] : String = { + /** We'd like the String representation to be a valid + * scala type, so we have to decode the jvm's secret language. + */ + def erasureString(clazz: Class[_]): String = { + if (clazz.isArray) "Array[" + erasureString(clazz.getComponentType) + "]" + else clazz.getName + } + erasureString(classTag[T].runtimeClass) + } + + def requiredClass[T: ClassTag] : ClassSymbol = + getRequiredClass(erasureName[T]) + + // TODO: What syntax do we think should work here? Say you have an object + // like scala.Predef. You can't say requiredModule[scala.Predef] since there's + // no accompanying Predef class, and if you say requiredModule[scala.Predef.type] + // the name found via the erasure is scala.Predef$. For now I am + // removing the trailing $, but I think that classTag should have + // a method which returns a usable name, one which doesn't expose this + // detail of the backend. + def requiredModule[T: ClassTag] : ModuleSymbol = + getRequiredModule(erasureName[T] stripSuffix "$") + + def getClassIfDefined(fullname: String): Symbol = + getClassIfDefined(newTypeName(fullname)) + + def getClassIfDefined(fullname: Name): Symbol = + wrapMissing(getClassByName(fullname.toTypeName)) + + def getModuleIfDefined(fullname: String): Symbol = + getModuleIfDefined(newTermName(fullname)) + + def getModuleIfDefined(fullname: Name): Symbol = + wrapMissing(getModule(fullname.toTermName)) + + def getPackageObject(fullname: String): ModuleSymbol = + (getModule(newTermName(fullname)).info member nme.PACKAGE) match { + case x: ModuleSymbol => x + case _ => MissingRequirementError.notFound("package object " + fullname) + } + + def getPackageObjectIfDefined(fullname: String): Symbol = { + val module = getModuleIfDefined(newTermName(fullname)) + if (module == NoSymbol) NoSymbol + else { + val packageObject = module.info member nme.PACKAGE + packageObject match { + case x: ModuleSymbol => x + case _ => NoSymbol + } + } + } + + @inline private def wrapMissing(body: => Symbol): Symbol = + try body + catch { case _: MissingRequirementError => NoSymbol } + + /** getModule2/getClass2 aren't needed at present but may be again, + * so for now they're mothballed. + */ + // def getModule2(name1: Name, name2: Name) = { + // try getModuleOrClass(name1.toTermName) + // catch { case ex1: FatalError => + // try getModuleOrClass(name2.toTermName) + // catch { case ex2: FatalError => throw ex1 } + // } + // } + // def getClass2(name1: Name, name2: Name) = { + // try { + // val result = getModuleOrClass(name1.toTypeName) + // if (result.isAliasType) getClass(name2) else result + // } + // catch { case ex1: FatalError => + // try getModuleOrClass(name2.toTypeName) + // catch { case ex2: FatalError => throw ex1 } + // } + // } + + def init() { + // Still fiddling with whether it's cleaner to do some of this setup here + // or from constructors. The latter approach tends to invite init order issues. + + EmptyPackageClass setInfo ClassInfoType(Nil, newPackageScope(EmptyPackageClass), EmptyPackageClass) + EmptyPackage setInfo EmptyPackageClass.tpe + + connectModuleToClass(EmptyPackage, EmptyPackageClass) + connectModuleToClass(RootPackage, RootClass) + + RootClass.info.decls enter EmptyPackage + RootClass.info.decls enter RootPackage + } + } + + abstract class Roots(rootOwner: Symbol) extends RootsBase(rootOwner) { thisMirror => + + // TODO - having these as objects means they elude the attempt to + // add synchronization in SynchronizedSymbols. But we should either + // flip on object overrides or find some other accomodation, because + // lazy vals are unnecessarily expensive relative to objects and it + // is very beneficial for a handful of bootstrap symbols to have + // first class identities + sealed trait WellKnownSymbol extends Symbol { + this initFlags TopLevelCreationFlags + } + // Features common to RootClass and RootPackage, the roots of all + // type and term symbols respectively. + sealed trait RootSymbol extends WellKnownSymbol { + final override def isRootSymbol = true + override def owner = rootOwner + override def typeOfThis = thisSym.tpe + } + + // This is the package _root_. The actual root cannot be referenced at + // the source level, but _root_ is essentially a function => <root>. + final object RootPackage extends ModuleSymbol(rootOwner, NoPosition, nme.ROOTPKG) with RootSymbol { + this setInfo NullaryMethodType(RootClass.tpe) + RootClass.sourceModule = this + + override def isRootPackage = true + } + // This is <root>, the actual root of everything except the package _root_. + // <root> and _root_ (RootPackage and RootClass) should be the only "well known" + // symbols owned by NoSymbol. All owner chains should go through RootClass, + // although it is probable that some symbols are created as direct children + // of NoSymbol to ensure they will not be stumbled upon. (We should designate + // a better encapsulated place for that.) + final object RootClass extends PackageClassSymbol(rootOwner, NoPosition, tpnme.ROOT) with RootSymbol { + this setInfo rootLoader + + override def isRoot = true + override def isEffectiveRoot = true + override def isStatic = true + override def isNestedClass = false + override def ownerOfNewSymbols = EmptyPackageClass + } + // The empty package, which holds all top level types without given packages. + final object EmptyPackage extends ModuleSymbol(RootClass, NoPosition, nme.EMPTY_PACKAGE_NAME) with WellKnownSymbol { + override def isEmptyPackage = true + } + final object EmptyPackageClass extends PackageClassSymbol(RootClass, NoPosition, tpnme.EMPTY_PACKAGE_NAME) with WellKnownSymbol { + override def isEffectiveRoot = true + override def isEmptyPackageClass = true + } + } +} diff --git a/src/compiler/scala/reflect/internal/MissingRequirementError.scala b/src/reflect/scala/reflect/internal/MissingRequirementError.scala index fbbbcc1928..fbbbcc1928 100644 --- a/src/compiler/scala/reflect/internal/MissingRequirementError.scala +++ b/src/reflect/scala/reflect/internal/MissingRequirementError.scala diff --git a/src/compiler/scala/reflect/internal/Names.scala b/src/reflect/scala/reflect/internal/Names.scala index 17924f0c0c..18671871ae 100644 --- a/src/compiler/scala/reflect/internal/Names.scala +++ b/src/reflect/scala/reflect/internal/Names.scala @@ -139,8 +139,8 @@ trait Names extends api.Names { * or Strings as Names. Give names the key functions the absence of which * make people want Strings all the time. */ - sealed abstract class Name(protected val index: Int, protected val len: Int) extends AbsName with Function1[Int, Char] { - type ThisNameType <: Name + sealed abstract class Name(protected val index: Int, protected val len: Int) extends NameApi with Function1[Int, Char] { + type ThisNameType >: Null <: Name protected[this] def thisName: ThisNameType /** Index into name table */ @@ -429,6 +429,8 @@ trait Names extends api.Names { def debugString = { val s = decode ; if (isTypeName) s + "!" else s } } + implicit val NameTag = ClassTag[Name](classOf[Name]) + /** A name that contains no operator chars nor dollar signs. * TODO - see if it's any faster to do something along these lines. * Cute: now that exhaustivity kind of works, the mere presence of @@ -491,6 +493,8 @@ trait Names extends api.Names { protected def createCompanionName(h: Int): TypeName } + implicit val TermNameTag = ClassTag[TermName](classOf[TermName]) + sealed abstract class TypeName(index0: Int, len0: Int, hash: Int) extends Name(index0, len0) { type ThisNameType = TypeName protected[this] def thisName: TypeName = this @@ -518,4 +522,6 @@ trait Names extends api.Names { override def decode = if (nameDebug) super.decode + "!" else super.decode protected def createCompanionName(h: Int): TermName } + + implicit val TypeNameTag = ClassTag[TypeName](classOf[TypeName]) } diff --git a/src/compiler/scala/reflect/internal/Phase.scala b/src/reflect/scala/reflect/internal/Phase.scala index 68dc5ce783..68dc5ce783 100644 --- a/src/compiler/scala/reflect/internal/Phase.scala +++ b/src/reflect/scala/reflect/internal/Phase.scala diff --git a/src/compiler/scala/reflect/internal/Positions.scala b/src/reflect/scala/reflect/internal/Positions.scala index 5ec2659098..6ae9b40fcb 100644 --- a/src/compiler/scala/reflect/internal/Positions.scala +++ b/src/reflect/scala/reflect/internal/Positions.scala @@ -3,8 +3,9 @@ package internal trait Positions extends api.Positions { self: SymbolTable => - type Position = scala.tools.nsc.util.Position - val NoPosition = scala.tools.nsc.util.NoPosition + type Position = scala.reflect.internal.util.Position + val NoPosition = scala.reflect.internal.util.NoPosition + implicit val PositionTag = ClassTag[Position](classOf[Position]) /** A position that wraps a set of trees. * The point of the wrapping position is the point of the default position. diff --git a/src/compiler/scala/reflect/internal/Required.scala b/src/reflect/scala/reflect/internal/Required.scala index 6d146354a3..abbe8fbfb7 100644 --- a/src/compiler/scala/reflect/internal/Required.scala +++ b/src/reflect/scala/reflect/internal/Required.scala @@ -5,7 +5,7 @@ import settings.MutableSettings trait Required { self: SymbolTable => - type AbstractFileType >: Null <: api.RequiredFile + type AbstractFileType >: Null <: AbstractFileApi def picklerPhase: Phase diff --git a/src/compiler/scala/reflect/internal/Scopes.scala b/src/reflect/scala/reflect/internal/Scopes.scala index 36e8ebb212..ceacd2afb0 100644 --- a/src/compiler/scala/reflect/internal/Scopes.scala +++ b/src/reflect/scala/reflect/internal/Scopes.scala @@ -317,6 +317,8 @@ trait Scopes extends api.Scopes { self: SymbolTable => } + implicit val ScopeTag = ClassTag[Scope](classOf[Scope]) + /** Create a new scope */ def newScope: Scope = new Scope() diff --git a/src/reflect/scala/reflect/internal/StdAttachments.scala b/src/reflect/scala/reflect/internal/StdAttachments.scala new file mode 100644 index 0000000000..4ea9b27da9 --- /dev/null +++ b/src/reflect/scala/reflect/internal/StdAttachments.scala @@ -0,0 +1,12 @@ +package scala.reflect +package internal + +trait StdAttachments { + self: SymbolTable => + + case object BackquotedIdentifierAttachment + + case class CompoundTypeTreeOriginalAttachment(parents: List[Tree], stats: List[Tree]) + + case class MacroExpansionAttachment(original: Tree) +}
\ No newline at end of file diff --git a/src/reflect/scala/reflect/internal/StdCreators.scala b/src/reflect/scala/reflect/internal/StdCreators.scala new file mode 100644 index 0000000000..3e6b7c1ab4 --- /dev/null +++ b/src/reflect/scala/reflect/internal/StdCreators.scala @@ -0,0 +1,21 @@ +package scala.reflect +package internal + +import scala.reflect.base.{TreeCreator, TypeCreator} +import scala.reflect.base.{Universe => BaseUniverse} + +trait StdCreators { + self: SymbolTable => + + case class FixedMirrorTreeCreator(mirror: MirrorOf[StdCreators.this.type], tree: Tree) extends TreeCreator { + def apply[U <: BaseUniverse with Singleton](m: MirrorOf[U]): U # Tree = + if (m eq mirror) tree.asInstanceOf[U # Tree] + else throw new IllegalArgumentException(s"Expr defined in $mirror cannot be migrated to other mirrors.") + } + + case class FixedMirrorTypeCreator(mirror: MirrorOf[StdCreators.this.type], tpe: Type) extends TypeCreator { + def apply[U <: BaseUniverse with Singleton](m: MirrorOf[U]): U # Type = + if (m eq mirror) tpe.asInstanceOf[U # Type] + else throw new IllegalArgumentException(s"Type tag defined in $mirror cannot be migrated to other mirrors.") + } +}
\ No newline at end of file diff --git a/src/compiler/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala index bd4d9a9f34..bd02013037 100644 --- a/src/compiler/scala/reflect/internal/StdNames.scala +++ b/src/reflect/scala/reflect/internal/StdNames.scala @@ -72,7 +72,7 @@ trait StdNames { val cs = s.toArray val bytes = Codec toUTF8 cs md5 update bytes - val md5chars = md5.digest() map (b => (b & 0xFF).toHexString) mkString + val md5chars = (md5.digest() map (b => (b & 0xFF).toHexString)).mkString prefix + marker + md5chars + marker + suffix } @@ -82,8 +82,8 @@ trait StdNames { ) } - abstract class CommonNames { - type NameType <: Name + abstract class CommonNames extends NamesApi { + type NameType >: Null <: Name protected implicit def createNameType(name: String): NameType def flattenedName(segments: Name*): NameType = @@ -122,14 +122,16 @@ trait StdNames { scala.List(Byte, Char, Short, Int, Long, Float, Double, Boolean, Unit) // some types whose companions we utilize - final val AnyRef: NameType = "AnyRef" - final val Array: NameType = "Array" - final val List: NameType = "List" - final val Seq: NameType = "Seq" - final val Symbol: NameType = "Symbol" - final val ClassTag: NameType = "ClassTag" - final val TypeTag : NameType = "TypeTag" - final val ConcreteTypeTag: NameType = "ConcreteTypeTag" + final val AnyRef: NameType = "AnyRef" + final val Array: NameType = "Array" + final val List: NameType = "List" + final val Seq: NameType = "Seq" + final val Symbol: NameType = "Symbol" + final val ClassTag: NameType = "ClassTag" + final val AbsTypeTag: NameType = "AbsTypeTag" + final val TypeTag : NameType = "TypeTag" + final val Expr: NameType = "Expr" + final val String: NameType = "String" // fictions we use as both types and terms final val ERROR: NameType = "<error>" @@ -200,7 +202,7 @@ trait StdNames { final val javaKeywords = new JavaKeywords() } - abstract class TypeNames extends Keywords { + abstract class TypeNames extends Keywords with TypeNamesApi { type NameType = TypeName protected implicit def createNameType(name: String): TypeName = newTypeNameCached(name) @@ -211,10 +213,13 @@ trait StdNames { final val REFINE_CLASS_NAME: NameType = "<refinement>" final val REPEATED_PARAM_CLASS_NAME: NameType = "<repeated>" final val WILDCARD_STAR: NameType = "_*" + final val REIFY_TREECREATOR_PREFIX: NameType = "$treecreator" + final val REIFY_TYPECREATOR_PREFIX: NameType = "$typecreator" final val Any: NameType = "Any" final val AnyVal: NameType = "AnyVal" - final val Expr: NameType = "Expr" + final val ExprApi: NameType = "ExprApi" + final val Mirror: NameType = "Mirror" final val Nothing: NameType = "Nothing" final val Null: NameType = "Null" final val Object: NameType = "Object" @@ -223,15 +228,15 @@ trait StdNames { final val Product: NameType = "Product" final val Serializable: NameType = "Serializable" final val Singleton: NameType = "Singleton" - final val String: NameType = "String" final val Throwable: NameType = "Throwable" final val Annotation: NameType = "Annotation" final val ClassfileAnnotation: NameType = "ClassfileAnnotation" final val Enum: NameType = "Enum" - final val Group: NameType = "Group" - final val Tree: NameType = "Tree" - final val TypeTree: NameType = "TypeTree" + final val Group: NameType = "Group" + final val Tree: NameType = "Tree" + final val Type : NameType = "Type" + final val TypeTree: NameType = "TypeTree" // Annotation simple names, used in Namer final val BeanPropertyAnnot: NameType = "BeanProperty" @@ -257,13 +262,13 @@ trait StdNames { final val SourceFileATTR: NameType = "SourceFile" final val SyntheticATTR: NameType = "Synthetic" - def dropSingletonName(name: Name): TypeName = name dropRight SINGLETON_SUFFIX.length toTypeName - def singletonName(name: Name): TypeName = name append SINGLETON_SUFFIX toTypeName - def implClassName(name: Name): TypeName = name append IMPL_CLASS_SUFFIX toTypeName - def interfaceName(implname: Name): TypeName = implname dropRight IMPL_CLASS_SUFFIX.length toTypeName + def dropSingletonName(name: Name): TypeName = (name dropRight SINGLETON_SUFFIX.length).toTypeName + def singletonName(name: Name): TypeName = (name append SINGLETON_SUFFIX).toTypeName + def implClassName(name: Name): TypeName = (name append IMPL_CLASS_SUFFIX).toTypeName + def interfaceName(implname: Name): TypeName = (implname dropRight IMPL_CLASS_SUFFIX.length).toTypeName } - abstract class TermNames extends Keywords { + abstract class TermNames extends Keywords with TermNamesApi { type NameType = TermName protected implicit def createNameType(name: String): TermName = newTermNameCached(name) @@ -290,22 +295,29 @@ trait StdNames { // Compiler internal names val ANYNAME: NameType = "<anyname>" val CONSTRUCTOR: NameType = "<init>" + val EQEQ_LOCAL_VAR: NameType = "eqEqTemp$" val FAKE_LOCAL_THIS: NameType = "this$" val INITIALIZER: NameType = CONSTRUCTOR // Is this buying us something? val LAZY_LOCAL: NameType = "$lzy" val LAZY_SLOW_SUFFIX: NameType = "$lzycompute" val LOCAL_SUFFIX_STRING = " " - val MIRROR_FREE_PREFIX: NameType = "free$" - val MIRROR_FREE_THIS_SUFFIX: NameType = "$this" - val MIRROR_FREE_VALUE_SUFFIX: NameType = "$value" - val MIRROR_PREFIX: NameType = "$mr." - val MIRROR_SHORT: NameType = "$mr" - val MIRROR_SYMDEF_PREFIX: NameType = "symdef$" + val UNIVERSE_BUILD_PREFIX: NameType = "$u.build." + val UNIVERSE_BUILD: NameType = "$u.build" + val UNIVERSE_PREFIX: NameType = "$u." + val UNIVERSE_SHORT: NameType = "$u" + val MIRROR_PREFIX: NameType = "$m." + val MIRROR_SHORT: NameType = "$m" + val MIRROR_UNTYPED: NameType = "$m$untyped" + val REIFY_FREE_PREFIX: NameType = "free$" + val REIFY_FREE_THIS_SUFFIX: NameType = "$this" + val REIFY_FREE_VALUE_SUFFIX: NameType = "$value" + val REIFY_SYMDEF_PREFIX: NameType = "symdef$" val MIXIN_CONSTRUCTOR: NameType = "$init$" val MODULE_INSTANCE_FIELD: NameType = NameTransformer.MODULE_INSTANCE_NAME // "MODULE$" val OUTER: NameType = "$outer" val OUTER_LOCAL: NameType = OUTER + LOCAL_SUFFIX_STRING // "$outer ", note the space val OUTER_SYNTH: NameType = "<outer>" // emitted by virtual pattern matcher, replaced by outer accessor in explicitouter + val ROOTPKG: NameType = "_root_" val SELECTOR_DUMMY: NameType = "<unapply-selector>" val SELF: NameType = "$this" val SETTER_SUFFIX: NameType = encode("_=") @@ -511,6 +523,32 @@ trait StdNames { case _ => newTermName("x$" + i) } + @switch def productAccessorName(j: Int): TermName = j match { + case 1 => nme._1 + case 2 => nme._2 + case 3 => nme._3 + case 4 => nme._4 + case 5 => nme._5 + case 6 => nme._6 + case 7 => nme._7 + case 8 => nme._8 + case 9 => nme._9 + case 10 => nme._10 + case 11 => nme._11 + case 12 => nme._12 + case 13 => nme._13 + case 14 => nme._14 + case 15 => nme._15 + case 16 => nme._16 + case 17 => nme._17 + case 18 => nme._18 + case 19 => nme._19 + case 20 => nme._20 + case 21 => nme._21 + case 22 => nme._22 + case _ => newTermName("_" + j) + } + val ??? = encode("???") val wrapRefArray: NameType = "wrapRefArray" @@ -539,12 +577,14 @@ trait StdNames { val EmptyPackage: NameType = "EmptyPackage" val EmptyPackageClass: NameType = "EmptyPackageClass" val ExistentialTypeTree: NameType = "ExistentialTypeTree" - val Expr: NameType = "Expr" + val Flag : NameType = "Flag" val Ident: NameType = "Ident" val Import: NameType = "Import" val Literal: NameType = "Literal" val LiteralAnnotArg: NameType = "LiteralAnnotArg" + val Modifiers: NameType = "Modifiers" val NestedAnnotArg: NameType = "NestedAnnotArg" + val NoFlags: NameType = "NoFlags" val NoPrefix: NameType = "NoPrefix" val NoSymbol: NameType = "NoSymbol" val Nothing: NameType = "Nothing" @@ -556,6 +596,7 @@ trait StdNames { val Select: NameType = "Select" val StringContext: NameType = "StringContext" val This: NameType = "This" + val ThisType: NameType = "ThisType" val Tree : NameType = "Tree" val Tuple2: NameType = "Tuple2" val TYPE_ : NameType = "TYPE" @@ -570,32 +611,40 @@ trait StdNames { val apply: NameType = "apply" val applyDynamic: NameType = "applyDynamic" val applyDynamicNamed: NameType = "applyDynamicNamed" + val applyImpl: NameType = "applyImpl" val applyOrElse: NameType = "applyOrElse" val args : NameType = "args" val argv : NameType = "argv" val arrayClass: NameType = "arrayClass" val arrayElementClass: NameType = "arrayElementClass" - val arrayTagToClassManifest: NameType = "arrayTagToClassManifest" val arrayValue: NameType = "arrayValue" val array_apply : NameType = "array_apply" val array_clone : NameType = "array_clone" val array_length : NameType = "array_length" val array_update : NameType = "array_update" val arraycopy: NameType = "arraycopy" + val asTermSymbol: NameType = "asTermSymbol" + val asModuleSymbol: NameType = "asModuleSymbol" + val asMethodSymbol: NameType = "asMethodSymbol" + val asTypeSymbol: NameType = "asTypeSymbol" + val asClassSymbol: NameType = "asClassSymbol" val asInstanceOf_ : NameType = "asInstanceOf" val asInstanceOf_Ob : NameType = "$asInstanceOf" val asTypeConstructor: NameType = "asTypeConstructor" val assert_ : NameType = "assert" val assume_ : NameType = "assume" + val basis : NameType = "basis" val box: NameType = "box" + val build : NameType = "build" val bytes: NameType = "bytes" val canEqual_ : NameType = "canEqual" val checkInitialized: NameType = "checkInitialized" val classOf: NameType = "classOf" + val classTagToClassManifest: NameType = "classTagToClassManifest" val clone_ : NameType = if (forMSIL) "MemberwiseClone" else "clone" // sn.OClone causes checkinit failure - val concreteTypeTagToManifest: NameType = "concreteTypeTagToManifest" val conforms: NameType = "conforms" val copy: NameType = "copy" + val currentMirror: NameType = "currentMirror" val definitions: NameType = "definitions" val delayedInit: NameType = "delayedInit" val delayedInitArg: NameType = "delayedInit$body" @@ -608,7 +657,6 @@ trait StdNames { val equalsNumNum : NameType = "equalsNumNum" val equalsNumObject : NameType = "equalsNumObject" val equals_ : NameType = if (forMSIL) "Equals" else "equals" - val erasure: NameType = "erasure" val error: NameType = "error" val eval: NameType = "eval" val ex: NameType = "ex" @@ -617,6 +665,7 @@ trait StdNames { val filter: NameType = "filter" val finalize_ : NameType = if (forMSIL) "Finalize" else "finalize" val find_ : NameType = "find" + val flagsFromBits : NameType = "flagsFromBits" val flatMap: NameType = "flatMap" val foreach: NameType = "foreach" val genericArrayOps: NameType = "genericArrayOps" @@ -627,6 +676,8 @@ trait StdNames { val hash_ : NameType = "hash" val head: NameType = "head" val identity: NameType = "identity" + val implicitly: NameType = "implicitly" + val in: NameType = "in" val info: NameType = "info" val inlinedEquals: NameType = "inlinedEquals" val isArray: NameType = "isArray" @@ -645,12 +696,10 @@ trait StdNames { val macroContext : NameType = "c" val main: NameType = "main" val manifest: NameType = "manifest" - val manifestToConcreteTypeTag: NameType = "manifestToConcreteTypeTag" + val manifestToTypeTag: NameType = "manifestToTypeTag" val map: NameType = "map" - val materializeArrayTag: NameType = "materializeArrayTag" val materializeClassTag: NameType = "materializeClassTag" - val materializeConcreteTypeTag: NameType = "materializeConcreteTypeTag" - val materializeErasureTag: NameType= "materializeErasureTag" + val materializeAbsTypeTag: NameType = "materializeAbsTypeTag" val materializeTypeTag: NameType = "materializeTypeTag" val mirror : NameType = "mirror" val moduleClass : NameType = "moduleClass" @@ -679,8 +728,11 @@ trait StdNames { val readResolve: NameType = "readResolve" val reflect : NameType = "reflect" val reify : NameType = "reify" + val rootMirror : NameType = "rootMirror" val runOrElse: NameType = "runOrElse" val runtime: NameType = "runtime" + val runtimeClass: NameType = "runtimeClass" + val runtimeMirror: NameType = "runtimeMirror" val sameElements: NameType = "sameElements" val scala_ : NameType = "scala" val selectDynamic: NameType = "selectDynamic" @@ -693,13 +745,14 @@ trait StdNames { val setSymbol: NameType = "setSymbol" val setType: NameType = "setType" val setTypeSignature: NameType = "setTypeSignature" + val splice: NameType = "splice" val staticClass : NameType = "staticClass" val staticModule : NameType = "staticModule" val synchronized_ : NameType = "synchronized" val tail: NameType = "tail" val `then` : NameType = "then" - val thisModuleType: NameType = "thisModuleType" val this_ : NameType = "this" + val thisPrefix : NameType = "thisPrefix" val throw_ : NameType = "throw" val toArray: NameType = "toArray" val toList: NameType = "toList" @@ -710,9 +763,11 @@ trait StdNames { val tree : NameType = "tree" val true_ : NameType = "true" val typedProductIterator: NameType = "typedProductIterator" + val typeTagToManifest: NameType = "typeTagToManifest" val unapply: NameType = "unapply" val unapplySeq: NameType = "unapplySeq" val unbox: NameType = "unbox" + val universe: NameType = "universe" val update: NameType = "update" val updateDynamic: NameType = "updateDynamic" val value: NameType = "value" @@ -757,90 +812,10 @@ trait StdNames { // overlap with the above, but not for these two. val toCharacter: NameType = "toCharacter" val toInteger: NameType = "toInteger" - } - - object tpnme extends TypeNames with AbsTypeNames { } - - /** For fully qualified type names. - */ - object fulltpnme extends TypeNames { - val RuntimeNothing: NameType = "scala.runtime.Nothing$" - val RuntimeNull: NameType = "scala.runtime.Null$" - } - - /** Java binary names, like scala/runtime/Nothing$. - */ - object binarynme { - def toBinary(name: Name) = name mapName (_.replace('.', '/')) - - val RuntimeNothing = toBinary(fulltpnme.RuntimeNothing).toTypeName - val RuntimeNull = toBinary(fulltpnme.RuntimeNull).toTypeName - } - - val javanme = nme.javaKeywords - - object nme extends TermNames with AbsTermNames { - - /** Translate a String into a list of simple TypeNames and TermNames. - * In all segments before the last, type/term is determined by whether - * the following separator char is '.' or '#'. In the last segment, - * the argument "assumeTerm" determines it. Examples: - * - * package foo { - * object Lorax { object Wog ; class Wog } - * class Lorax { object Zax ; class Zax } - * } - * - * f("foo.Lorax", true) == List("foo": Term, "Lorax": Term) // object Lorax - * f("foo.Lorax", false) == List("foo": Term, "Lorax": Type) // class Lorax - * f("Lorax.Wog", true) == List("Lorax": Term, "Wog": Term) // object Wog - * f("Lorax.Wog", false) == List("Lorax": Term, "Wog": Type) // class Wog - * f("Lorax#Zax", true) == List("Lorax": Type, "Zax": Term) // object Zax - * f("Lorax#Zax", false) == List("Lorax": Type, "Zax": Type) // class Zax - * - * Note that in actual scala syntax you cannot refer to object Zax without an - * instance of Lorax, so Lorax#Zax could only mean the type. One might think - * that Lorax#Zax.type would work, but this is not accepted by the parser. - * For the purposes of referencing that object, the syntax is allowed. - */ - def segments(name: String, assumeTerm: Boolean): List[Name] = { - def mkName(str: String, term: Boolean): Name = - if (term) newTermName(str) else newTypeName(str) - - name.indexWhere(ch => ch == '.' || ch == '#') match { - // it's the last segment: the parameter tells us whether type or term - case -1 => if (name == "") scala.Nil else scala.List(mkName(name, assumeTerm)) - // otherwise, we can tell based on whether '#' or '.' is the following char. - case idx => - val (simple, div, rest) = (name take idx, name charAt idx, newTermName(name) drop (idx + 1)) - mkName(simple, div == '.') :: segments(rest, assumeTerm) - } - } - - def newBitmapName(bitmapPrefix: Name, n: Int) = bitmapPrefix append ("" + n) - - val BITMAP_NORMAL: NameType = BITMAP_PREFIX + "" // initialization bitmap for public/protected lazy vals - val BITMAP_TRANSIENT: NameType = BITMAP_PREFIX + "trans$" // initialization bitmap for transient lazy vals - val BITMAP_CHECKINIT: NameType = BITMAP_PREFIX + "init$" // initialization bitmap for checkinit values - val BITMAP_CHECKINIT_TRANSIENT: NameType = BITMAP_PREFIX + "inittrans$" // initialization bitmap for transient checkinit values def newLazyValSlowComputeName(lzyValName: Name) = lzyValName append LAZY_SLOW_SUFFIX - def isModuleVarName(name: Name): Boolean = - stripAnonNumberSuffix(name) endsWith MODULE_VAR_SUFFIX - - def moduleVarName(name: TermName): TermName = - newTermNameCached("" + name + MODULE_VAR_SUFFIX) - - val ROOTPKG: TermName = "_root_" - val EQEQ_LOCAL_VAR: TermName = "eqEqTemp$" - - def getCause = sn.GetCause - def getClass_ = sn.GetClass - def getComponentType = sn.GetComponentType - def getMethod_ = sn.GetMethod - def invoke_ = sn.Invoke - + // ASCII names for operators val ADD = encode("+") val AND = encode("&") val ASR = encode(">>") @@ -906,9 +881,6 @@ trait StdNames { val testLessThan: NameType = "testLessThan" val testNotEqual: NameType = "testNotEqual" - val isBoxedNumberOrBoolean: NameType = "isBoxedNumberOrBoolean" - val isBoxedNumber: NameType = "isBoxedNumber" - def toUnaryName(name: TermName): TermName = name match { case raw.MINUS => UNARY_- case raw.PLUS => UNARY_+ @@ -958,6 +930,90 @@ trait StdNames { case _ => NO_NAME } + /** Translate a String into a list of simple TypeNames and TermNames. + * In all segments before the last, type/term is determined by whether + * the following separator char is '.' or '#'. In the last segment, + * the argument "assumeTerm" determines it. Examples: + * + * package foo { + * object Lorax { object Wog ; class Wog } + * class Lorax { object Zax ; class Zax } + * } + * + * f("foo.Lorax", true) == List("foo": Term, "Lorax": Term) // object Lorax + * f("foo.Lorax", false) == List("foo": Term, "Lorax": Type) // class Lorax + * f("Lorax.Wog", true) == List("Lorax": Term, "Wog": Term) // object Wog + * f("Lorax.Wog", false) == List("Lorax": Term, "Wog": Type) // class Wog + * f("Lorax#Zax", true) == List("Lorax": Type, "Zax": Term) // object Zax + * f("Lorax#Zax", false) == List("Lorax": Type, "Zax": Type) // class Zax + * + * Note that in actual scala syntax you cannot refer to object Zax without an + * instance of Lorax, so Lorax#Zax could only mean the type. One might think + * that Lorax#Zax.type would work, but this is not accepted by the parser. + * For the purposes of referencing that object, the syntax is allowed. + */ + def segments(name: String, assumeTerm: Boolean): List[Name] = { + def mkName(str: String, term: Boolean): Name = + if (term) newTermName(str) else newTypeName(str) + + name.indexWhere(ch => ch == '.' || ch == '#') match { + // it's the last segment: the parameter tells us whether type or term + case -1 => if (name == "") scala.Nil else scala.List(mkName(name, assumeTerm)) + // otherwise, we can tell based on whether '#' or '.' is the following char. + case idx => + val (simple, div, rest) = (name take idx, name charAt idx, newTermName(name) drop (idx + 1)) + mkName(simple, div == '.') :: segments(rest, assumeTerm) + } + } + + def newBitmapName(bitmapPrefix: Name, n: Int) = bitmapPrefix append ("" + n) + + val BITMAP_NORMAL: NameType = BITMAP_PREFIX + "" // initialization bitmap for public/protected lazy vals + val BITMAP_TRANSIENT: NameType = BITMAP_PREFIX + "trans$" // initialization bitmap for transient lazy vals + val BITMAP_CHECKINIT: NameType = BITMAP_PREFIX + "init$" // initialization bitmap for checkinit values + val BITMAP_CHECKINIT_TRANSIENT: NameType = BITMAP_PREFIX + "inittrans$" // initialization bitmap for transient checkinit values + } + + object tpnme extends TypeNames { } + + /** For fully qualified type names. + */ + object fulltpnme extends TypeNames { + val RuntimeNothing: NameType = "scala.runtime.Nothing$" + val RuntimeNull: NameType = "scala.runtime.Null$" + val JavaLangEnum: NameType = "java.lang.Enum" + } + + /** Java binary names, like scala/runtime/Nothing$. + */ + object binarynme { + def toBinary(name: Name) = name mapName (_.replace('.', '/')) + + val RuntimeNothing = toBinary(fulltpnme.RuntimeNothing).toTypeName + val RuntimeNull = toBinary(fulltpnme.RuntimeNull).toTypeName + } + + val javanme = nme.javaKeywords + + // [Eugene++ to Martin] had to move a lot of stuff from here to TermNames to satisfy the contract + // why do we even have stuff in object nme? cf. object tpnme + object nme extends TermNames { + + def isModuleVarName(name: Name): Boolean = + stripAnonNumberSuffix(name) endsWith MODULE_VAR_SUFFIX + + def moduleVarName(name: TermName): TermName = + newTermNameCached("" + name + MODULE_VAR_SUFFIX) + + def getCause = sn.GetCause + def getClass_ = sn.GetClass + def getComponentType = sn.GetComponentType + def getMethod_ = sn.GetMethod + def invoke_ = sn.Invoke + + val isBoxedNumberOrBoolean: NameType = "isBoxedNumberOrBoolean" + val isBoxedNumber: NameType = "isBoxedNumber" + val reflPolyCacheName: NameType = "reflPoly$Cache" val reflClassCacheName: NameType = "reflClass$Cache" val reflParamsCacheName: NameType = "reflParams$Cache" @@ -973,32 +1029,6 @@ trait StdNames { ) def isReflectionCacheName(name: Name) = reflectionCacheNames exists (name startsWith _) - @switch def productAccessorName(j: Int): TermName = j match { - case 1 => nme._1 - case 2 => nme._2 - case 3 => nme._3 - case 4 => nme._4 - case 5 => nme._5 - case 6 => nme._6 - case 7 => nme._7 - case 8 => nme._8 - case 9 => nme._9 - case 10 => nme._10 - case 11 => nme._11 - case 12 => nme._12 - case 13 => nme._13 - case 14 => nme._14 - case 15 => nme._15 - case 16 => nme._16 - case 17 => nme._17 - case 18 => nme._18 - case 19 => nme._19 - case 20 => nme._20 - case 21 => nme._21 - case 22 => nme._22 - case _ => newTermName("_" + j) - } - @deprecated("Use a method in tpnme", "2.10.0") def dropSingletonName(name: Name): TypeName = tpnme.dropSingletonName(name) @deprecated("Use a method in tpnme", "2.10.0") def singletonName(name: Name): TypeName = tpnme.singletonName(name) @deprecated("Use a method in tpnme", "2.10.0") def implClassName(name: Name): TypeName = tpnme.implClassName(name) @@ -1028,6 +1058,7 @@ trait StdNames { val ForName : TermName val GetCause : TermName val GetClass : TermName + val GetClassLoader : TermName val GetComponentType : TermName val GetMethod : TermName val Invoke : TermName @@ -1117,6 +1148,7 @@ trait StdNames { final val ForName: TermName = newTermName("forName") final val GetCause: TermName = newTermName("getCause") final val GetClass: TermName = newTermName("getClass") + final val GetClassLoader: TermName = newTermName("getClassLoader") final val GetComponentType: TermName = newTermName("getComponentType") final val GetMethod: TermName = newTermName("getMethod") final val Invoke: TermName = newTermName("invoke") @@ -1155,6 +1187,7 @@ trait StdNames { final val ForName: TermName = newTermName("GetType") final val GetCause: TermName = newTermName("InnerException") /* System.Reflection.TargetInvocationException.InnerException */ final val GetClass: TermName = newTermName("GetType") + final lazy val GetClassLoader: TermName = throw new UnsupportedOperationException("Scala reflection is not supported on this platform"); final val GetComponentType: TermName = newTermName("GetElementType") final val GetMethod: TermName = newTermName("GetMethod") final val Invoke: TermName = newTermName("Invoke") diff --git a/src/compiler/scala/reflect/internal/SymbolTable.scala b/src/reflect/scala/reflect/internal/SymbolTable.scala index ddd6c43031..cadd76b1ba 100644 --- a/src/compiler/scala/reflect/internal/SymbolTable.scala +++ b/src/reflect/scala/reflect/internal/SymbolTable.scala @@ -8,17 +8,17 @@ package internal import scala.collection.{ mutable, immutable } import util._ -import scala.tools.nsc.util.WeakHashSet -abstract class SymbolTable extends api.Universe +abstract class SymbolTable extends makro.Universe with Collections with Names with Symbols - with FreeVars with Types with Kinds with ExistentialsAndSkolems + with FlagSets with Scopes + with Mirrors with Definitions with Constants with BaseTypeSeqs @@ -33,12 +33,15 @@ abstract class SymbolTable extends api.Universe with TypeDebugging with Importers with Required - with TreeBuildUtil - with FrontEnds with CapturedVariables with StdAttachments + with StdCreators + with BuildUtils { - def rootLoader: LazyType + + val gen = new TreeGen { val global: SymbolTable.this.type = SymbolTable.this } + val treeBuild = gen + def log(msg: => AnyRef): Unit def abort(msg: String): Nothing = throw new FatalError(supplementErrorMessage(msg)) @@ -110,6 +113,9 @@ abstract class SymbolTable extends api.Universe */ def missingHook(owner: Symbol, name: Name): Symbol = NoSymbol + /** Returns the mirror that loaded given symbol */ + def mirrorThatLoaded(sym: Symbol): Mirror + /** A period is an ordinal number for a phase in a run. * Phases in later runs have higher periods than phases in earlier runs. * Later phases have higher periods than earlier phases in the same run. @@ -295,7 +301,6 @@ abstract class SymbolTable extends api.Universe def clearAll() = { debuglog("Clearing " + caches.size + " caches.") - caches foreach { ref => val cache = ref.get() if (cache == null) @@ -321,8 +326,7 @@ abstract class SymbolTable extends api.Universe /** The phase which has given index as identifier. */ val phaseWithId: Array[Phase] - /** Is this symbol table part of reflexive mirror? In this case - * operations need to be made thread safe. + /** Is this symbol table a part of a compiler universe? */ - def inReflexiveMirror = false + def isCompilerUniverse = false } diff --git a/src/compiler/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index b32b955631..288eb63332 100644 --- a/src/compiler/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -10,7 +10,6 @@ import scala.collection.{ mutable, immutable } import scala.collection.mutable.ListBuffer import util.Statistics._ import Flags._ -import api.Modifier trait Symbols extends api.Symbols { self: SymbolTable => import definitions._ @@ -47,20 +46,20 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** Create a new free term. Its owner is NoSymbol. */ - def newFreeTermSymbol(name: TermName, info: Type, value: => Any, flags: Long = 0L, origin: String): FreeTerm = - new FreeTerm(name, value, origin) initFlags flags setInfo info + def newFreeTermSymbol(name: TermName, info: Type, value: => Any, flags: Long = 0L, origin: String): FreeTermSymbol = + new FreeTermSymbol(name, value, origin) initFlags flags setInfo info /** Create a new free type. Its owner is NoSymbol. */ - def newFreeTypeSymbol(name: TypeName, info: Type, value: => Any, flags: Long = 0L, origin: String): FreeType = - new FreeType(name, value, origin) initFlags flags setInfo info + def newFreeTypeSymbol(name: TypeName, info: Type, value: => Any, flags: Long = 0L, origin: String): FreeTypeSymbol = + new FreeTypeSymbol(name, value, origin) initFlags flags setInfo info /** The original owner of a class. Used by the backend to generate * EnclosingMethod attributes. */ val originalOwner = perRunCaches.newMap[Symbol, Symbol]() - abstract class AbsSymbolImpl extends AbsSymbol { + abstract class SymbolContextApiImpl extends SymbolContextApi { this: Symbol => def kind: String = kindString @@ -71,8 +70,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => case n: TypeName => if (isClass) newClassSymbol(n, pos, newFlags) else newNonClassSymbol(n, pos, newFlags) } - def enclosingClass: Symbol = enclClass - def enclosingMethod: Symbol = enclMethod def thisPrefix: Type = thisType def selfType: Type = typeOfThis def typeSignature: Type = info @@ -83,6 +80,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => def asTypeConstructor: Type = typeConstructor def setInternalFlags(flag: Long): this.type = { setFlag(flag); this } def setTypeSignature(tpe: Type): this.type = { setInfo(tpe); this } + def getAnnotations: List[AnnotationInfo] = { initialize; annotations } def setAnnotations(annots: AnnotationInfo*): this.type = { setAnnotations(annots.toList); this } private def lastElemType(ts: Seq[Type]): Type = ts.last.normalize.typeArgs.head @@ -155,7 +153,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** The class for all symbols */ abstract class Symbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: Name) - extends AbsSymbolImpl + extends SymbolContextApiImpl with HasFlags with Annotatable[Symbol] { @@ -164,7 +162,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => // TODO - don't allow names to be renamed in this unstructured a fashion. // Rename as little as possible. Enforce invariants on all renames. - type NameType >: Null <: Name type TypeOfClonedSymbol >: Null <: Symbol { type NameType = Symbol.this.NameType } // Abstract here so TypeSymbol and TermSymbol can have a private[this] field @@ -183,6 +180,8 @@ trait Symbols extends api.Symbols { self: SymbolTable => private var rawpos = initPos val id = nextId() // identity displayed when -uniqid + //assert(id != 3390, initName) + private[this] var _validTo: Period = NoPeriod if (traceSymbolActivity) @@ -236,19 +235,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => ) ) - /** !!! The logic after "hasFlag" is far too opaque to be unexplained. - * I'm guessing it's attempting to compensate for flag overloading, - * and embedding such logic in an undocumented island like this is a - * notarized guarantee of future breakage. - */ - override def hasModifier(mod: Modifier) = - hasFlag(flagOfModifier(mod)) && - (!(mod == Modifier.bynameParameter) || isTerm) && - (!(mod == Modifier.covariant) || isType) - - override def modifiers: Set[Modifier] = - Modifier.values filter hasModifier - // ------ creators ------------------------------------------------------------------- final def newValue(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): TermSymbol = @@ -263,6 +249,8 @@ trait Symbols extends api.Symbols { self: SymbolTable => newTermSymbol(nme.localDummyName(this), pos) setInfo NoType final def newMethod(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): MethodSymbol = createMethodSymbol(name, pos, METHOD | newFlags) + final def newMethodSymbol(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): MethodSymbol = + createMethodSymbol(name, pos, METHOD | newFlags) final def newLabel(name: TermName, pos: Position = NoPosition): MethodSymbol = newMethod(name, pos, LABEL) @@ -302,6 +290,16 @@ trait Symbols extends api.Symbols { self: SymbolTable => final def newModuleSymbol(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): ModuleSymbol = newTermSymbol(name, pos, newFlags).asInstanceOf[ModuleSymbol] + final def newModuleAndClassSymbol(name: Name, pos: Position, flags: FlagSet): (ModuleSymbol, ClassSymbol) = { + val m = newModuleSymbol(name, pos, flags | MODULE) + val c = newModuleClass(name.toTypeName, pos, m getFlag ModuleToClassFlags) + connectModuleToClass(m, c) + (m, c) + } + + final def newPackageSymbol(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): ModuleSymbol = + newTermSymbol(name, pos, newFlags).asInstanceOf[ModuleSymbol] + final def newModuleClassSymbol(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): ModuleClassSymbol = newClassSymbol(name, pos, newFlags).asInstanceOf[ModuleClassSymbol] @@ -349,6 +347,11 @@ trait Symbols extends api.Symbols { self: SymbolTable => final def newTypeParameter(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): TypeSymbol = newAbstractType(name, pos, PARAM | newFlags) +// is defined in SymbolCreations +// final def newTypeSymbol(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): TypeSymbol = +// (if ((newFlags & DEFERRED) != 0) new AbstractTypeSymbol(this, pos, name) +// else new AbstractTypeSymbol(this, pos, name)) setFlag newFlags + /** Symbol of an existential type T forSome { ... } */ final def newExistential(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): TypeSymbol = @@ -445,18 +448,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => case x: TermName => newErrorValue(x) } - /** To overcome the crazy challenge of more specific types appearing - * in incoming positions. Don't need this much. - */ - def asTypeSymbol: TypeSymbol = this match { - case x: TypeSymbol => x - case x => throw new FatalError(this + " is not a TypeSymbol") - } - def asTermSymbol: TermSymbol = this match { - case x: TermSymbol => x - case x => throw new FatalError(this + " is not a TermSymbol") - } - @deprecated("Use the other signature", "2.10.0") def newClass(pos: Position, name: TypeName): Symbol = newClass(name, pos) @deprecated("Use the other signature", "2.10.0") @@ -526,19 +517,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => // ----- tests ---------------------------------------------------------------------- - /** All symbols are one of three categories: TermSymbol, TypeSymbol, or NoSymbol. - * There is only one NoSymbol. - */ - def isTerm = false - def isType = false - - /** TypeSymbols fall into four named direct subclasses: - * - ClassSymbol - * - AliasTypeSymbol - * - AbstractTypeSymbol - * - TypeSkolem - */ - def isClass = false def isAliasType = false def isAbstractType = false def isSkolem = false @@ -580,7 +558,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => def isTypeParameterOrSkolem = false def isTypeSkolem = false def isTypeMacro = false - def isFreeType = false /** Qualities of Terms, always false for TypeSymbols. */ @@ -593,7 +570,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => def isGetter = false def isLocalDummy = false def isMixinConstructor = false - def isModule = false def isOverloaded = false def isSetter = false def isSetterParameter = false @@ -602,20 +578,17 @@ trait Symbols extends api.Symbols { self: SymbolTable => def isVariable = false override def hasDefault = false def isTermMacro = false - def isFreeTerm = false /** Qualities of MethodSymbols, always false for TypeSymbols * and other TermSymbols. */ def isCaseAccessorMethod = false def isLiftedMethod = false - def isMethod = false def isSourceMethod = false def isVarargsMethod = false override def isLabel = false /** Package/package object tests */ - def isPackage = false def isPackageClass = false def isPackageObject = false def isPackageObjectClass = false @@ -693,7 +666,8 @@ trait Symbols extends api.Symbols { self: SymbolTable => def isClassLocalToConstructor = false final def isDerivedValueClass = - isClass && info.firstParent.typeSymbol == AnyValClass && !isPrimitiveValueClass + isClass && !hasFlag(PACKAGE | TRAIT) && + info.firstParent.typeSymbol == AnyValClass && !isPrimitiveValueClass final def isMethodWithExtension = isMethod && owner.isDerivedValueClass && !isParamAccessor && !isConstructor && !hasFlag(SUPERACCESSOR) @@ -916,7 +890,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => final def isInitialized: Boolean = validTo != NoPeriod - // [Eugene] is this correct? + // [Eugene] todo. needs to be reviewed and [only then] rewritten without explicit returns /** Determines whether this symbol can be loaded by subsequent reflective compilation */ final def isLocatable: Boolean = { if (this == NoSymbol) return false @@ -976,7 +950,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => if (originalOwner contains this) () else originalOwner(this) = rawowner } - assert(!inReflexiveMirror, "owner_= is not thread-safe; cannot be run in reflexive code") + assert(isCompilerUniverse, "owner_= is not thread-safe; cannot be run in reflexive code") if (traceSymbolActivity) traceSymbols.recordNewSymbolOwner(this, owner) _rawowner = owner @@ -1103,8 +1077,8 @@ trait Symbols extends api.Symbols { self: SymbolTable => protected def createModuleSymbol(name: TermName, pos: Position, newFlags: Long): ModuleSymbol = new ModuleSymbol(this, pos, name) initFlags newFlags - protected def createPackageSymbol(name: TermName, pos: Position, newFlags: Long): PackageSymbol = - new PackageSymbol(this, pos, name) initFlags newFlags + protected def createPackageSymbol(name: TermName, pos: Position, newFlags: Long): ModuleSymbol = + new ModuleSymbol(this, pos, name) initFlags newFlags protected def createValueParameterSymbol(name: TermName, pos: Position, newFlags: Long): TermSymbol = new TermSymbol(this, pos, name) initFlags newFlags @@ -1157,10 +1131,10 @@ trait Symbols extends api.Symbols { self: SymbolTable => */ def accessBoundary(base: Symbol): Symbol = { if (hasFlag(PRIVATE) || isLocal) owner - else if (hasAllFlags(PROTECTED | STATIC | JAVA)) RootClass + else if (hasAllFlags(PROTECTED | STATIC | JAVA)) enclosingRootClass else if (hasAccessBoundary && !phase.erasedTypes) privateWithin else if (hasFlag(PROTECTED)) base - else RootClass + else enclosingRootClass } def isLessAccessibleThan(other: Symbol): Boolean = { @@ -1335,7 +1309,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => // adapt to new run in fsc. private def adaptInfos(infos: TypeHistory): TypeHistory = { - assert(!inReflexiveMirror) + assert(isCompilerUniverse) if (infos == null || runId(infos.validFrom) == currentRunId) { infos } else { @@ -1370,7 +1344,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** Was symbol's type updated during given phase? */ final def isUpdatedAt(pid: Phase#Id): Boolean = { - assert(!inReflexiveMirror) + assert(isCompilerUniverse) var infos = this.infos while ((infos ne null) && phaseId(infos.validFrom) != pid + 1) infos = infos.prev infos ne null @@ -1378,7 +1352,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** Was symbol's type updated during given phase? */ final def hasTypeAt(pid: Phase#Id): Boolean = { - assert(!inReflexiveMirror) + assert(isCompilerUniverse) var infos = this.infos while ((infos ne null) && phaseId(infos.validFrom) > pid) infos = infos.prev infos ne null @@ -1527,13 +1501,8 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** After the typer phase (before, look at the definition's Modifiers), contains * the annotations attached to member a definition (class, method, type, field). */ - def annotations: List[AnnotationInfo] = { - // Necessary for reflection, see SI-5423 - if (inReflexiveMirror) - initialize - + def annotations: List[AnnotationInfo] = _annotations - } def setAnnotations(annots: List[AnnotationInfo]): this.type = { _annotations = annots @@ -1619,6 +1588,8 @@ trait Symbols extends api.Symbols { self: SymbolTable => result } + @inline final def map(f: Symbol => Symbol): Symbol = if (this eq NoSymbol) this else f(this) + // ------ cloneing ------------------------------------------------------------------- /** A clone of this symbol. */ @@ -1697,7 +1668,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => * The empty list for all other classes. */ final def caseFieldAccessors: List[Symbol] = - info.decls filter (_.isCaseAccessorMethod) toList + (info.decls filter (_.isCaseAccessorMethod)).toList final def constrParamAccessors: List[Symbol] = info.decls.toList filter (sym => !sym.isMethod && sym.isParamAccessor) @@ -1760,21 +1731,36 @@ trait Symbols extends api.Symbols { self: SymbolTable => */ def mixinClasses: List[Symbol] = { val sc = superClass - ancestors takeWhile (sc ne) + ancestors takeWhile (sc ne _) } /** All directly or indirectly inherited classes. */ def ancestors: List[Symbol] = info.baseClasses drop 1 + @inline final def enclosingSuchThat(p: Symbol => Boolean): Symbol = { + var sym = this + while (sym != NoSymbol && !p(sym)) + sym = sym.owner + sym + } + /** The package class containing this symbol, or NoSymbol if there - * is not one. */ + * is not one. + * TODO: formulate as enclosingSuchThat, after making sure + * we can start with current symbol rather than onwner. + * TODO: Also harmonize with enclClass, enclMethod etc. + */ def enclosingPackageClass: Symbol = { - var packSym = this.owner - while (packSym != NoSymbol && !packSym.isPackageClass) - packSym = packSym.owner - packSym + var sym = this.owner + while (sym != NoSymbol && !sym.isPackageClass) + sym = sym.owner + sym } + /** The package class containing this symbol, or NoSymbol if there + * is not one. */ + def enclosingRootClass: Symbol = enclosingSuchThat(_.isRoot) + /** The package containing this symbol, or NoSymbol if there * is not one. */ def enclosingPackage: Symbol = enclosingPackageClass.companionModule @@ -2009,7 +1995,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => * pre: `this.owner` is in the base class sequence of `base`. */ final def superSymbol(base: Symbol): Symbol = { - var bcs = base.info.baseClasses.dropWhile(owner !=).tail + var bcs = base.info.baseClasses.dropWhile(owner != _).tail var sym: Symbol = NoSymbol while (!bcs.isEmpty && sym == NoSymbol) { if (!bcs.head.isImplClass) @@ -2167,8 +2153,8 @@ trait Symbols extends api.Symbols { self: SymbolTable => private def symbolKind: SymbolKind = { var kind = if (isTermMacro) ("macro method", "macro method", "MAC") - else if (isInstanceOf[FreeTerm]) ("free term", "free term", "FTE") - else if (isInstanceOf[FreeType]) ("free type", "free type", "FTY") + else if (isInstanceOf[FreeTermSymbol]) ("free term", "free term", "FTE") + else if (isInstanceOf[FreeTypeSymbol]) ("free type", "free type", "FTY") else if (isPackage) ("package", "package", "PK") else if (isPackageClass) ("package class", "package", "PKC") else if (isPackageObject) ("package object", "package", "PKO") @@ -2327,6 +2313,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => "val " + tpnme.dropSingletonName(name) + ": " + dropSingletonType(info.bounds.hi) else defString } + implicit val SymbolTag = ClassTag[Symbol](classOf[Symbol]) /** A class for term symbols */ class TermSymbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: TermName) @@ -2334,7 +2321,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => private[this] var _referenced: Symbol = NoSymbol privateWithin = NoSymbol - final type NameType = TermName type TypeOfClonedSymbol = TermSymbol private[this] var _rawname: TermName = initName @@ -2349,8 +2335,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => } final def asNameType(n: Name) = n.toTermName - final override def isTerm = true - /** Term symbols with the exception of static parts of Java classes and packages. */ override def isValue = !(isModule && hasFlag(PACKAGE | JAVA)) @@ -2496,6 +2480,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => cook(sym2) } } + implicit val TermSymbolTag = ClassTag[TermSymbol](classOf[TermSymbol]) /** A class for module symbols */ class ModuleSymbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: TermName) @@ -2505,7 +2490,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => override def associatedFile = moduleClass.associatedFile override def associatedFile_=(f: AbstractFileType) { moduleClass.associatedFile = f } - override def isModule = true override def moduleClass = referenced override def companionClass = flatOwnerInfo.decl(name.toTypeName).suchThat(_ isCoDefinedWith this) @@ -2524,11 +2508,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => else rawname ) } - - class PackageSymbol protected[Symbols] (owner0: Symbol, pos0: Position, name0: TermName) - extends ModuleSymbol(owner0, pos0, name0) with PackageSymbolApi { - override def isPackage = true - } + implicit val ModuleSymbolTag = ClassTag[ModuleSymbol](classOf[ModuleSymbol]) /** A class for method symbols */ class MethodSymbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: TermName) @@ -2538,7 +2518,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => private[this] var mtpeResult: Type = _ private[this] var mtpeInfo: Type = _ - override def isMethod = true override def isLabel = this hasFlag LABEL override def isVarargsMethod = this hasFlag VARARGS override def isLiftedMethod = this hasFlag LIFTED @@ -2566,6 +2545,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => res } } + implicit val MethodSymbolTag = ClassTag[MethodSymbol](classOf[MethodSymbol]) class AliasTypeSymbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: TypeName) extends TypeSymbol(initOwner, initPos, initName) { @@ -2593,7 +2573,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => privateWithin = NoSymbol private[this] var _rawname: TypeName = initName - final type NameType = TypeName type TypeOfClonedSymbol >: Null <: TypeSymbol // cloneSymbolImpl still abstract in TypeSymbol. @@ -2601,7 +2580,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => def name = _rawname final def asNameType(n: Name) = n.toTypeName - final override def isType = true override def isNonClassType = true override def isTypeMacro = hasFlag(MACRO) @@ -2737,6 +2715,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => incCounter(typeSymbolCount) } + implicit val TypeSymbolTag = ClassTag[TypeSymbol](classOf[TypeSymbol]) /** A class for type parameters viewed from inside their scopes * @@ -2808,7 +2787,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => case _ => super.resolveOverloadedFlag(flag) } - final override def isClass = true final override def isNonClassType = false final override def isAbstractType = false final override def isAliasType = false @@ -2953,6 +2931,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => incCounter(classSymbolCount) } + implicit val ClassSymbolTag = ClassTag[ClassSymbol](classOf[ClassSymbol]) /** A class for module class symbols * Note: Not all module classes are of this type; when unpickled, we get @@ -3048,15 +3027,15 @@ trait Symbols extends api.Symbols { self: SymbolTable => trait FreeSymbol extends Symbol { def origin: String } - class FreeTerm(name0: TermName, value0: => Any, val origin: String) extends TermSymbol(NoSymbol, NoPosition, name0) with FreeSymbol { + class FreeTermSymbol(name0: TermName, value0: => Any, val origin: String) extends TermSymbol(NoSymbol, NoPosition, name0) with FreeSymbol with FreeTermSymbolApi { def value = value0 - override def isFreeTerm = true } + implicit val FreeTermSymbolTag = ClassTag[FreeTermSymbol](classOf[FreeTermSymbol]) - class FreeType(name0: TypeName, value0: => Any, val origin: String) extends TypeSkolem(NoSymbol, NoPosition, name0, NoSymbol) with FreeSymbol { + class FreeTypeSymbol(name0: TypeName, value0: => Any, val origin: String) extends TypeSkolem(NoSymbol, NoPosition, name0, NoSymbol) with FreeSymbol with FreeTypeSymbolApi { def value = value0 - override def isFreeType = true } + implicit val FreeTypeSymbolTag = ClassTag[FreeTypeSymbol](classOf[FreeTypeSymbol]) /** An object representing a missing symbol */ class NoSymbol protected[Symbols]() extends Symbol(null, NoPosition, nme.NO_NAME) { @@ -3101,7 +3080,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => override def existentialBound: Type = NoType override def rawInfo: Type = NoType protected def doCookJavaRawInfo() {} - override def accessBoundary(base: Symbol): Symbol = RootClass + override def accessBoundary(base: Symbol): Symbol = enclosingRootClass def cloneSymbolImpl(owner: Symbol, newFlags: Long) = abort("NoSymbol.clone()") override def originalEnclosingMethod = this diff --git a/src/compiler/scala/reflect/internal/TreeGen.scala b/src/reflect/scala/reflect/internal/TreeGen.scala index f2f9842595..c3a6fce164 100644 --- a/src/compiler/scala/reflect/internal/TreeGen.scala +++ b/src/reflect/scala/reflect/internal/TreeGen.scala @@ -1,7 +1,7 @@ package scala.reflect package internal -abstract class TreeGen extends api.AbsTreeGen { +abstract class TreeGen extends makro.TreeBuilder { val global: SymbolTable import global._ @@ -269,4 +269,12 @@ abstract class TreeGen extends api.AbsTreeGen { // tree1 OR tree2 def mkOr(tree1: Tree, tree2: Tree): Tree = Apply(Select(tree1, Boolean_or), List(tree2)) + + def mkBasisUniverseRef: Tree = + mkAttributedRef(ReflectBasis) setType singleType(ReflectBasis.owner.thisPrefix, ReflectBasis) + + def mkRuntimeUniverseRef: Tree = { + assert(ReflectRuntimeUniverse != NoSymbol) + mkAttributedRef(ReflectRuntimeUniverse) setType singleType(ReflectRuntimeUniverse.owner.thisPrefix, ReflectRuntimeUniverse) + } } diff --git a/src/compiler/scala/reflect/internal/TreeInfo.scala b/src/reflect/scala/reflect/internal/TreeInfo.scala index 1528061adb..698d219634 100644 --- a/src/compiler/scala/reflect/internal/TreeInfo.scala +++ b/src/reflect/scala/reflect/internal/TreeInfo.scala @@ -326,6 +326,12 @@ abstract class TreeInfo { case _ => false } + /** a Match(Typed(_, tpt), _) is unchecked if isUncheckedAnnotation(tpt.tpe) */ + def isUncheckedAnnotation(tpe: Type) = tpe hasAnnotation definitions.UncheckedClass + + /** a Match(Typed(_, tpt), _) must be translated into a switch if isSwitchAnnotation(tpt.tpe) */ + def isSwitchAnnotation(tpe: Type) = tpe hasAnnotation definitions.SwitchClass + /** can this type be a type pattern */ def mayBeTypePat(tree: Tree): Boolean = tree match { case CompoundTypeTree(Template(tps, _, Nil)) => tps exists mayBeTypePat @@ -568,200 +574,4 @@ abstract class TreeInfo { object DynamicUpdate extends DynamicApplicationExtractor(_ == nme.updateDynamic) object DynamicApplication extends DynamicApplicationExtractor(isApplyDynamicName) object DynamicApplicationNamed extends DynamicApplicationExtractor(_ == nme.applyDynamicNamed) - - - // domain-specific extractors for reification - - import definitions._ - - object TypedOrAnnotated { - def unapply(tree: Tree): Option[Tree] = tree match { - case ty @ Typed(_, _) => - Some(ty) - case at @ Annotated(_, _) => - Some(at) - case _ => - None - } - } - - object TreeSplice { - def unapply(tree: Tree): Option[Tree] = tree match { - case Select(splicee, _) if tree.symbol == ExprEval || tree.symbol == ExprValue => - Some(splicee) - case _ => - None - } - } - - object EvalSplice { - def unapply(tree: Tree): Option[Tree] = tree match { - case Select(splicee, _) if tree.symbol == ExprEval => - Some(splicee) - case _ => - None - } - } - - object ValueSplice { - def unapply(tree: Tree): Option[Tree] = tree match { - case Select(splicee, _) if tree.symbol == ExprValue => - Some(splicee) - case _ => - None - } - } - - object Reified { - def unapply(tree: Tree): Option[(Tree, List[Tree], Tree)] = tree match { - case ReifiedTree(reifee, symbolTable, reified, _) => - Some(reifee, symbolTable, reified) - case ReifiedType(reifee, symbolTable, reified) => - Some(reifee, symbolTable, reified) - case _ => - None - } - } - - object ReifiedTree { - def unapply(tree: Tree): Option[(Tree, List[Tree], Tree, Tree)] = tree match { - case reifee @ Block((mrDef @ ValDef(_, _, _, _)) :: symbolTable, Apply(Apply(_, List(tree)), List(Apply(_, tpe :: _)))) if mrDef.name == nme.MIRROR_SHORT => - Some(reifee, symbolTable, tree, tpe) - case _ => - None - } - } - - object InlineableTreeSplice { - def unapply(tree: Tree): Option[(Tree, List[Tree], Tree, Tree, Symbol)] = tree match { - case select @ Select(ReifiedTree(splicee, symbolTable, tree, tpe), _) if select.symbol == ExprEval || select.symbol == ExprValue => - Some(splicee, symbolTable, tree, tpe, select.symbol) - case _ => - None - } - } - - object InlinedTreeSplice { - def unapply(tree: Tree): Option[(Tree, List[Tree], Tree, Tree)] = tree match { - case Select(ReifiedTree(splicee, symbolTable, tree, tpe), name) if name == ExprTree.name => - Some(splicee, symbolTable, tree, tpe) - case _ => - None - } - } - - object ReifiedType { - def unapply(tree: Tree): Option[(Tree, List[Tree], Tree)] = tree match { - case reifee @ Block((mrDef @ ValDef(_, _, _, _)) :: symbolTable, Apply(_, tpe :: _)) if mrDef.name == nme.MIRROR_SHORT => - Some(reifee, symbolTable, tpe) - case _ => - None - } - } - - object InlinedTypeSplice { - def unapply(tree: Tree): Option[(Tree, List[Tree], Tree)] = tree match { - case Select(ReifiedType(splicee, symbolTable, tpe), name) if name == TypeTagTpe.name => - Some(splicee, symbolTable, tpe) - case _ => - None - } - } - - object FreeDef { - def unapply(tree: Tree): Option[(Tree, TermName, Tree, Long, String)] = tree match { - case FreeTermDef(mrRef, name, binding, flags, origin) => - Some(mrRef, name, binding, flags, origin) - case FreeTypeDef(mrRef, name, binding, flags, origin) => - Some(mrRef, name, binding, flags, origin) - case _ => - None - } - } - - object FreeTermDef { - lazy val newFreeTermMethod = getMember(getRequiredClass("scala.reflect.api.TreeBuildUtil"), nme.newFreeTerm) - - def unapply(tree: Tree): Option[(Tree, TermName, Tree, Long, String)] = tree match { - case ValDef(_, name, _, Apply(Select(mrRef @ Ident(_), newFreeTerm), List(_, _, binding, Literal(Constant(flags: Long)), Literal(Constant(origin: String))))) - if mrRef.name == nme.MIRROR_SHORT && newFreeTerm == newFreeTermMethod.name => - Some(mrRef, name, binding, flags, origin) - case _ => - None - } - } - - object FreeTypeDef { - lazy val newFreeExistentialMethod = getMember(getRequiredClass("scala.reflect.api.TreeBuildUtil"), nme.newFreeType) - lazy val newFreeTypeMethod = getMember(getRequiredClass("scala.reflect.api.TreeBuildUtil"), nme.newFreeExistential) - - def unapply(tree: Tree): Option[(Tree, TermName, Tree, Long, String)] = tree match { - case ValDef(_, name, _, Apply(Select(mrRef1 @ Ident(_), newFreeType), List(_, _, value, Literal(Constant(flags: Long)), Literal(Constant(origin: String))))) - if mrRef1.name == nme.MIRROR_SHORT && (newFreeType == newFreeTypeMethod.name || newFreeType == newFreeExistentialMethod.name) => - value match { - case Apply(TypeApply(Select(Select(mrRef2 @ Ident(_), typeTag), apply), List(binding)), List(Literal(Constant(null)), _)) - if mrRef2.name == nme.MIRROR_SHORT && typeTag == nme.TypeTag && apply == nme.apply => - Some(mrRef1, name, binding, flags, origin) - case Apply(TypeApply(Select(mrRef2 @ Ident(_), typeTag), List(binding)), List(Literal(Constant(null)), _)) - if mrRef2.name == nme.MIRROR_SHORT && typeTag == nme.TypeTag => - Some(mrRef1, name, binding, flags, origin) - case _ => - throw new Error("unsupported free type def: %s%n%s".format(value, showRaw(value))) - } - case _ => - None - } - } - - object FreeRef { - def unapply(tree: Tree): Option[(Tree, TermName)] = tree match { - case Apply(Select(mrRef @ Ident(_), ident), List(Ident(name: TermName))) if ident == nme.Ident && name.startsWith(nme.MIRROR_FREE_PREFIX) => - Some(mrRef, name) - case _ => - None - } - } - - object TypeRefToFreeType { - def unapply(tree: Tree): Option[TermName] = tree match { - case Apply(Select(Select(mrRef @ Ident(_), typeRef), apply), List(Select(_, noSymbol), Ident(freeType: TermName), nil)) - if (mrRef.name == nme.MIRROR_SHORT && typeRef == nme.TypeRef && noSymbol == nme.NoSymbol && freeType.startsWith(nme.MIRROR_FREE_PREFIX)) => - Some(freeType) - case _ => - None - } - } - - object NestedExpr { - def unapply(tree: Tree): Option[(Tree, Tree, Tree)] = tree match { - case Apply(Apply(factory @ Select(expr, apply), List(tree)), List(typetag)) if expr.symbol == ExprModule && apply == nme.apply => - Some(factory, tree, typetag) - case _ => - None - } - } - - object BoundTerm { - def unapply(tree: Tree): Option[Tree] = tree match { - case Ident(name) if name.isTermName => - Some(tree) - case This(_) => - Some(tree) - case _ => - None - } - } - - object BoundType { - def unapply(tree: Tree): Option[Tree] = tree match { - case Select(_, name) if name.isTypeName => - Some(tree) - case SelectFromTypeTree(_, name) if name.isTypeName => - Some(tree) - case Ident(name) if name.isTypeName => - Some(tree) - case _ => - None - } - } } diff --git a/src/compiler/scala/reflect/internal/TreePrinters.scala b/src/reflect/scala/reflect/internal/TreePrinters.scala index b3e4318fdc..6d035c8b9d 100644 --- a/src/compiler/scala/reflect/internal/TreePrinters.scala +++ b/src/reflect/scala/reflect/internal/TreePrinters.scala @@ -3,6 +3,8 @@ * @author Martin Odersky */ +// [Eugene++ to Martin] we need to unify this prettyprinter with NodePrinters + package scala.reflect package internal @@ -27,7 +29,9 @@ trait TreePrinters extends api.TreePrinters { self: SymbolTable => private def symNameInternal(tree: Tree, name: Name, decoded: Boolean): String = { val sym = tree.symbol - if (sym != null && sym != NoSymbol) { + if (sym.name.toString == nme.ERROR.toString) { + "<" + quotedName(name, decoded) + ": error>" + } else if (sym != null && sym != NoSymbol) { val prefix = if (sym.isMixinConstructor) "/*%s*/".format(quotedName(sym.owner.name, decoded)) else "" var suffix = "" if (settings.uniqid.value) suffix += ("#" + sym.id) @@ -167,6 +171,12 @@ trait TreePrinters extends api.TreePrinters { self: SymbolTable => } def printAnnotations(tree: Tree) { + if (!isCompilerUniverse && tree.symbol != null && tree.symbol != NoSymbol) + // [Eugene++] todo. this is not 100% correct, but is necessary for sane printing + // the problem is that getting annotations doesn't automatically initialize the symbol + // so we might easily print something as if it doesn't have annotations, whereas it does + tree.symbol.initialize + val annots = tree.symbol.annotations match { case Nil => tree.asInstanceOf[MemberDef].mods.annotations case anns => anns @@ -445,7 +455,7 @@ trait TreePrinters extends api.TreePrinters { self: SymbolTable => /** Hook for extensions */ def xprintTree(treePrinter: TreePrinter, tree: Tree) = - treePrinter.print(tree.printingPrefix+tree.productIterator.mkString("(", ", ", ")")) + treePrinter.print(tree.productPrefix+tree.productIterator.mkString("(", ", ", ")")) def newTreePrinter(writer: PrintWriter): TreePrinter = new TreePrinter(writer) def newTreePrinter(stream: OutputStream): TreePrinter = newTreePrinter(new PrintWriter(stream)) diff --git a/src/library/scala/reflect/api/Trees.scala b/src/reflect/scala/reflect/internal/Trees.scala index 3427136fde..75bb0e6d49 100644 --- a/src/library/scala/reflect/api/Trees.scala +++ b/src/reflect/scala/reflect/internal/Trees.scala @@ -4,198 +4,43 @@ */ package scala.reflect -package api +package internal -import scala.collection.mutable.ListBuffer +import Flags._ +import base.Attachments +import collection.mutable.{ListBuffer, LinkedHashSet} -// Syncnote: Trees are currently not thread-safe. -trait Trees { self: Universe => +trait Trees extends api.Trees { self: SymbolTable => private[scala] var nodeCount = 0 - type Modifiers >: Null <: AbsModifiers - val NoMods: Modifiers - - // TODO - Where do I put this? - object BackquotedIdentifier - - abstract class AbsModifiers { - def modifiers: Set[Modifier] - def hasModifier(mod: Modifier): Boolean - def privateWithin: Name // default: EmptyTypeName - def annotations: List[Tree] // default: List() - def mapAnnotations(f: List[Tree] => List[Tree]): Modifiers - } - - def Modifiers(mods: Set[Modifier] = Set(), - privateWithin: Name = EmptyTypeName, - annotations: List[Tree] = List()): Modifiers - - /** Tree is the basis for scala's abstract syntax. The nodes are - * implemented as case classes, and the parameters which initialize - * a given tree are immutable: however Trees have several mutable - * fields which are manipulated in the course of typechecking, - * including pos, symbol, and tpe. - * - * Newly instantiated trees have tpe set to null (though it - * may be set immediately thereafter depending on how it is - * constructed.) When a tree is passed to the typer, typically via - * `typer.typed(tree)`, under normal circumstances the tpe must be - * null or the typer will ignore it. Furthermore, the typer is not - * required to return the same tree it was passed. - * - * Trees can be easily traversed with e.g. foreach on the root node; - * for a more nuanced traversal, subclass Traverser. Transformations - * can be considerably trickier: see the numerous subclasses of - * Transformer found around the compiler. - * - * Copying Trees should be done with care depending on whether - * it need be done lazily or strictly (see LazyTreeCopier and - * StrictTreeCopier) and on whether the contents of the mutable - * fields should be copied. The tree copiers will copy the mutable - * attributes to the new tree; calling Tree#duplicate will copy - * symbol and tpe, but all the positions will be focused. - * - * Trees can be coarsely divided into four mutually exclusive categories: - * - * - TermTrees, representing terms - * - TypTrees, representing types. Note that is `TypTree`, not `TypeTree`. - * - SymTrees, which may represent types or terms. - * - Other Trees, which have none of those as parents. - * - * SymTrees include important nodes Ident and Select, which are - * used as both terms and types; they are distinguishable based on - * whether the Name is a TermName or TypeName. The correct way for - * to test for a type or a term (on any Tree) are the isTerm/isType - * methods on Tree. - * - * "Others" are mostly syntactic or short-lived constructs. Examples - * include CaseDef, which wraps individual match cases: they are - * neither terms nor types, nor do they carry a symbol. Another - * example is Parens, which is eliminated during parsing. - */ - abstract class Tree extends Product { - val id = nodeCount + abstract class Tree extends TreeContextApiImpl with Product { + val id = nodeCount // TODO: add to attachment? nodeCount += 1 - /** Prefix under which to print this tree type. Defaults to product - * prefix (e.g. DefTree) but because that is used in reification - * it cannot be altered without breaking reflection. - */ - def printingPrefix = productPrefix - - def pos: Position = rawatt.pos.asInstanceOf[Position] // [Eugene] how do we get rid of this cast? - def pos_=(pos: Position): Unit = rawatt = (rawatt withPos pos) // the "withPos" part is crucial to robustness + @inline final def pos: Position = rawatt.pos + def pos_=(pos: Position): Unit = rawatt = (rawatt withPos pos) def setPos(newpos: Position): this.type = { pos = newpos; this } - // [Eugene] can we make this more type-safe - private var rawatt: Attachment = NoPosition - def attach(att: Any): Unit = - rawatt match { - case NontrivialAttachment(pos, payload) => - val index = payload.indexWhere(p => p.getClass == att.getClass) - if (index == -1) payload += att - else payload(index) = att - case _ => - rawatt = NontrivialAttachment(pos, collection.mutable.ListBuffer[Any](att)) - } - - // a) why didn't this method already exist - // b) what is all this "Any" business? - // c) am I reverse-engineering this correctly? It shouldn't be hard - // to figure out what is attached. - def attachments: List[Any] = rawatt match { - case NoPosition => Nil - case NontrivialAttachment(pos, atts) => pos :: atts.toList - case x => List(x) - } - // Writing "Any" repeatedly to work within this structure - // is making my skin crawl. - def hasAttachment(x: Any) = attachments contains x - - def withAttachment(att: Any): this.type = { attach(att); this } - def detach(att: Any): Unit = - detach(att.getClass) - def detach(clazz: java.lang.Class[_]): Unit = - rawatt match { - case NontrivialAttachment(pos, payload) => - val index = payload.indexWhere(p => p.getClass == clazz) - if (index != -1) payload.remove(index) - case _ => - // do nothing - } - def withoutAttachment(att: Any): this.type = { detach(att); this } - def attachment[T: ClassTag]: T = attachmentOpt[T] getOrElse { throw new Error("no attachment of type %s".format(classTag[T].erasure)) } - def attachmentOpt[T: ClassTag]: Option[T] = - firstAttachment { case attachment if attachment.getClass == classTag[T].erasure => attachment.asInstanceOf[T] } - - def firstAttachment[T](p: PartialFunction[Any, T]): Option[T] = - rawatt match { - case NontrivialAttachment(pos, payload) => payload.collectFirst(p) - case _ => None - } + private var rawatt: Attachments { type Pos = Position } = NoPosition + def attachments = rawatt + def addAttachment(attachment: Any): this.type = { rawatt = rawatt.add(attachment); this } + def removeAttachment[T: ClassTag]: this.type = { rawatt = rawatt.remove[T]; this } private[this] var rawtpe: Type = _ - - def tpe = rawtpe + @inline final def tpe = rawtpe def tpe_=(t: Type) = rawtpe = t - - def resetType(): this.type = { tpe = null ; this } - def resetSymbol(): this.type = { if (hasSymbol) symbol = NoSymbol ; this } - - /** Set tpe to give `tp` and return this. - */ def setType(tp: Type): this.type = { rawtpe = tp; this } - - /** Like `setType`, but if this is a previously empty TypeTree that - * fact is remembered so that resetAllAttrs will snap back. - * - * @PP: Attempting to elaborate on the above, I find: If defineType - * is called on a TypeTree whose type field is null or NoType, - * this is recorded as "wasEmpty = true". That value is used in - * ResetAttrs, which nulls out the type field of TypeTrees - * for which wasEmpty is true, leaving the others alone. - * - * resetAllAttrs is used in situations where some speculative - * typing of a tree takes place, fails, and the tree needs to be - * returned to its former state to try again. So according to me: - * using `defineType` instead of `setType` is how you communicate - * that the type being set does not depend on any previous state, - * and therefore should be abandoned if the current line of type - * inquiry doesn't work out. - */ def defineType(tp: Type): this.type = setType(tp) - /** Note that symbol is fixed as null at this level. In SymTrees, - * it is overridden and implemented with a var, initialized to NoSymbol. - * - * Trees which are not SymTrees but which carry symbols do so by - * overriding `def symbol` to forward it elsewhere. Examples: - * - * Super(qual, _) // has qual's symbol - * Apply(fun, args) // has fun's symbol - * TypeApply(fun, args) // has fun's symbol - * AppliedTypeTree(tpt, args) // has tpt's symbol - * TypeTree(tpe) // has tpe's typeSymbol, if tpe != null - * - * Attempting to set the symbol of a Tree which does not support - * it will induce an exception. - */ def symbol: Symbol = null def symbol_=(sym: Symbol) { throw new UnsupportedOperationException("symbol_= inapplicable for " + this) } def setSymbol(sym: Symbol): this.type = { symbol = sym; this } - def hasSymbol = false - def isDef = false - def isEmpty = false - @inline final def orElse(alt: => Tree) = if (!isEmpty) this else alt - @inline final def andAlso(f: Tree => Unit): Tree = { if (!this.isEmpty) f(this) ; this } - def hasAssignedType = (tpe ne null) && (tpe ne NoType) - def hasAssignedSymbol = (symbol ne null) && (symbol ne NoSymbol) + def isDef = false - @inline final def hasSymbolWhich(f: Symbol => Boolean) = hasAssignedSymbol && f(symbol) - @inline final def hasTypeWhich(f: Type => Boolean) = hasAssignedType && f(tpe) + def isEmpty = false /** The canonical way to test if a Tree represents a term. */ @@ -219,61 +64,70 @@ trait Trees { self: Universe => case _ => false } - /** Apply `f` to each subtree */ - def foreach(f: Tree => Unit) { new ForeachTreeTraverser(f).traverse(this) } + private[scala] def copyAttrs(tree: Tree): this.type = { + rawatt = tree.rawatt + tpe = tree.tpe + if (hasSymbol) symbol = tree.symbol + this + } + + override def hashCode(): Int = System.identityHashCode(this) + override def equals(that: Any) = this eq that.asInstanceOf[AnyRef] + + override def duplicate: this.type = + (duplicator transform this).asInstanceOf[this.type] + } - /** Find all subtrees matching predicate `p` */ - def withFilter(f: Tree => Boolean): List[Tree] = { + abstract class TreeContextApiImpl extends TreeContextApi { this: Tree => + + override def orElse(alt: => Tree) = if (!isEmpty) this else alt + + override def foreach(f: Tree => Unit) { new ForeachTreeTraverser(f).traverse(this) } + + override def withFilter(f: Tree => Boolean): List[Tree] = { val ft = new FilterTreeTraverser(f) ft.traverse(this) ft.hits.toList } - def filter(f: Tree => Boolean): List[Tree] = withFilter(f) - /** Apply `pf' to each subtree on which the function is defined */ - def collect[T](pf: PartialFunction[Tree, T]): List[T] = { + override def filter(f: Tree => Boolean): List[Tree] = withFilter(f) + + override def collect[T](pf: PartialFunction[Tree, T]): List[T] = { val ctt = new CollectTreeTraverser[T](pf) ctt.traverse(this) ctt.results.toList } - /** Returns optionally first tree (in a preorder traversal) which satisfies predicate `p`, - * or None if none exists. - */ - def find(p: Tree => Boolean): Option[Tree] = { + override def find(p: Tree => Boolean): Option[Tree] = { val ft = new FindTreeTraverser(p) ft.traverse(this) ft.result } - /** Is there exists a part of this tree which satisfies predicate `p`? */ - def exists(p: Tree => Boolean): Boolean = !find(p).isEmpty + override def exists(p: Tree => Boolean): Boolean = !find(p).isEmpty + + override def forAll(p: Tree => Boolean): Boolean = find(!p(_)).isEmpty - /** Do all parts of this tree satisfy predicate `p`? */ - def forAll(p: Tree => Boolean): Boolean = find(!p(_)).isEmpty + override def equalsStructure(that : Tree) = correspondsStructure(that)(_ eq _) - def equalsStructure(that : Tree) = equalsStructure0(that)(_ eq _) - def equalsStructure0(that: Tree)(f: (Tree,Tree) => Boolean): Boolean = - f(this, that) || ((this.productArity == that.productArity) && { + def correspondsStructure(that: Tree)(f: (Tree,Tree) => Boolean): Boolean = + f(this, that) || ((productArity == that.productArity) && { def equals0(this0: Any, that0: Any): Boolean = (this0, that0) match { - case (x: Tree, y: Tree) => f(x, y) || (x equalsStructure0 y)(f) + case (x: Tree, y: Tree) => f(x, y) || (x correspondsStructure y)(f) case (xs: List[_], ys: List[_]) => (xs corresponds ys)(equals0) case _ => this0 == that0 } def compareOriginals() = (this, that) match { case (x: TypeTree, y: TypeTree) if x.original != null && y.original != null => - (x.original equalsStructure0 y.original)(f) + (x.original correspondsStructure y.original)(f) case _ => true } - (this.productIterator zip that.productIterator forall { case (x, y) => equals0(x, y) }) && compareOriginals() + (productIterator zip that.productIterator forall { case (x, y) => equals0(x, y) }) && compareOriginals() }) - /** The direct child trees of this tree. - * EmptyTrees are always omitted. Lists are flattened. - */ - def children: List[Tree] = { + override def children: List[Tree] = { def subtrees(x: Any): List[Tree] = x match { case EmptyTree => Nil case t: Tree => List(t) @@ -283,385 +137,258 @@ trait Trees { self: Universe => productIterator.toList flatMap subtrees } - /** Make a copy of this tree, keeping all attributes, - * except that all positions are focused (so nothing - * in this tree will be found when searching by position). + override def freeTerms: List[FreeTermSymbol] = freeSyms[FreeTermSymbol](_.isFreeTerm, _.termSymbol) + override def freeTypes: List[FreeTypeSymbol] = freeSyms[FreeTypeSymbol](_.isFreeType, _.typeSymbol) + + private def freeSyms[S <: Symbol](isFree: Symbol => Boolean, symOfType: Type => Symbol): List[S] = { + val s = collection.mutable.LinkedHashSet[S]() + def addIfFree(sym: Symbol): Unit = if (sym != null && isFree(sym)) s += sym.asInstanceOf[S] + for (t <- this) { + addIfFree(t.symbol) + if (t.tpe != null) { + for (tp <- t.tpe) { + addIfFree(symOfType(tp)) + } + } + } + s.toList + } + + override def substituteSymbols(from: List[Symbol], to: List[Symbol]): Tree = + new TreeSymSubstituter(from, to)(this) + + override def substituteTypes(from: List[Symbol], to: List[Type]): Tree = + new TreeTypeSubstituter(from, to)(this) + + override def substituteThis(clazz: Symbol, to: Tree): Tree = + new ThisSubstituter(clazz, to) transform this + + def hasSymbolWhich(f: Symbol => Boolean) = + hasSymbol && symbol != null && f(symbol) + + def isErroneous = (tpe ne null) && tpe.isErroneous + def isTyped = (tpe ne null) && !tpe.isErroneous + + /** Sets the tree's type to the result of the given function. + * If the type is null, it remains null - the function is not called. */ - def duplicate: this.type = - duplicateTree(this).asInstanceOf[this.type] + def modifyType(f: Type => Type): Tree = + if (tpe eq null) this + else this setType f(tpe) - private[scala] def copyAttrs(tree: Tree): this.type = { - rawatt = tree.rawatt - tpe = tree.tpe - if (hasSymbol) symbol = tree.symbol - this + /** If `pf` is defined for a given subtree, call super.traverse(pf(tree)), + * otherwise super.traverse(tree). + */ + def foreachPartial(pf: PartialFunction[Tree, Tree]) { + new ForeachPartialTreeTraverser(pf).traverse(this) } - override def toString: String = show(this) - override def hashCode(): Int = System.identityHashCode(this) - override def equals(that: Any) = this eq that.asInstanceOf[AnyRef] + def changeOwner(pairs: (Symbol, Symbol)*): Tree = { + pairs.foldLeft(this) { case (t, (oldOwner, newOwner)) => + new ChangeOwnerTraverser(oldOwner, newOwner) apply t + } + } + + def shallowDuplicate: Tree = new ShallowDuplicator(this) transform this + def shortClass: String = (getClass.getName split "[.$]").last + + def isErrorTyped = (tpe ne null) && tpe.isError + + /** When you want to know a little more than the class, but a lot + * less than the whole tree. + */ + def summaryString: String = this match { + case Literal(const) => "Literal(" + const + ")" + case Ident(name) => "Ident(%s)".format(name.decode) + case Select(qual, name) => "Select(%s, %s)".format(qual.summaryString, name.decode) + case t: NameTree => t.name.longString + case t => + t.shortClass + ( + if (t.symbol != null && t.symbol != NoSymbol) "(" + t.symbol + ")" + else "" + ) + } } - /** A tree for a term. Not all terms are TermTrees; use isTerm - * to reliably identify terms. - */ - trait TermTree extends Tree + trait TermTree extends Tree with TermTreeApi - /** A tree for a type. Not all types are TypTrees; use isType - * to reliably identify types. - */ - trait TypTree extends Tree + trait TypTree extends Tree with TypTreeApi - /** A tree with a mutable symbol field, initialized to NoSymbol. - */ - trait SymTree extends Tree { + trait SymTree extends Tree with SymTreeContextApi { override def hasSymbol = true override var symbol: Symbol = NoSymbol } - /** A tree with a name - effectively, a DefTree or RefTree. - */ - trait NameTree extends Tree { + trait NameTree extends Tree with NameTreeApi { def name: Name } - /** A tree which references a symbol-carrying entity. - * References one, as opposed to defining one; definitions - * are in DefTrees. - */ - trait RefTree extends SymTree with NameTree { + trait RefTree extends SymTree with NameTree with RefTreeApi { def qualifier: Tree // empty for Idents def name: Name } - /** A tree which defines a symbol-carrying entity. - */ - abstract class DefTree extends SymTree with NameTree { + abstract class DefTree extends SymTree with NameTree with DefTreeApi { def name: Name override def isDef = true } -// ----- tree node alternatives -------------------------------------- - - /** The empty tree */ case object EmptyTree extends TermTree { super.tpe_=(NoType) override def tpe_=(t: Type) = if (t != NoType) throw new UnsupportedOperationException("tpe_=("+t+") inapplicable for <empty>") override def isEmpty = true - override def resetType(): this.type = this } - /** Common base class for all member definitions: types, classes, - * objects, packages, vals and vars, defs. - */ - abstract class MemberDef extends DefTree { + abstract class MemberDef extends DefTree with MemberDefApi { def mods: Modifiers def keyword: String = this match { case TypeDef(_, _, _, _) => "type" - case ClassDef(mods, _, _, _) => if (mods hasModifier Modifier.`trait`) "trait" else "class" + case ClassDef(mods, _, _, _) => if (mods hasFlag TRAIT) "trait" else "class" case DefDef(_, _, _, _, _, _) => "def" case ModuleDef(_, _, _) => "object" case PackageDef(_, _) => "package" - case ValDef(mods, _, _, _) => if (mods hasModifier Modifier.mutable) "var" else "val" + case ValDef(mods, _, _, _) => if (mods hasFlag MUTABLE) "var" else "val" case _ => "" } } - /** A packaging, such as `package pid { stats }` - */ case class PackageDef(pid: RefTree, stats: List[Tree]) - extends MemberDef { + extends MemberDef with PackageDefApi { def name = pid.name - def mods = Modifiers() + def mods = NoMods } + object PackageDef extends PackageDefExtractor - /** A common base class for class and object definitions. - */ - abstract class ImplDef extends MemberDef { + abstract class ImplDef extends MemberDef with ImplDefApi { def impl: Template } - /** A class definition. - */ case class ClassDef(mods: Modifiers, name: TypeName, tparams: List[TypeDef], impl: Template) - extends ImplDef - - /** @param sym the class symbol - * @return the implementation template - */ - def ClassDef(sym: Symbol, impl: Template): ClassDef + extends ImplDef with ClassDefApi + object ClassDef extends ClassDefExtractor - /** An object definition, e.g. `object Foo`. Internally, objects are - * quite frequently called modules to reduce ambiguity. - */ case class ModuleDef(mods: Modifiers, name: TermName, impl: Template) - extends ImplDef - - /** - * @param sym the class symbol - * @param impl the implementation template - */ - def ModuleDef(sym: Symbol, impl: Template): ModuleDef + extends ImplDef with ModuleDefApi + object ModuleDef extends ModuleDefExtractor - /** A common base class for ValDefs and DefDefs. - */ - abstract class ValOrDefDef extends MemberDef { - def name: Name // can't be a TermName because macros can be type names. + abstract class ValOrDefDef extends MemberDef with ValOrDefDefApi { + def name: Name def tpt: Tree def rhs: Tree } - /** Broadly speaking, a value definition. All these are encoded as ValDefs: - * - * - immutable values, e.g. "val x" - * - mutable values, e.g. "var x" - the MUTABLE flag set in mods - * - lazy values, e.g. "lazy val x" - the LAZY flag set in mods - * - method parameters, see vparamss in DefDef - the PARAM flag is set in mods - * - explicit self-types, e.g. class A { self: Bar => } - !!! not sure what is set. - */ - case class ValDef(mods: Modifiers, name: TermName, tpt: Tree, rhs: Tree) extends ValOrDefDef - - def ValDef(sym: Symbol, rhs: Tree): ValDef - - def ValDef(sym: Symbol): ValDef + case class ValDef(mods: Modifiers, name: TermName, tpt: Tree, rhs: Tree) extends ValOrDefDef with ValDefApi + object ValDef extends ValDefExtractor - /** A method or macro definition. - * @param name The name of the method or macro. Can be a type name in case this is a type macro - */ case class DefDef(mods: Modifiers, name: Name, tparams: List[TypeDef], - vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree) extends ValOrDefDef - - def DefDef(sym: Symbol, mods: Modifiers, vparamss: List[List[ValDef]], rhs: Tree): DefDef - - def DefDef(sym: Symbol, vparamss: List[List[ValDef]], rhs: Tree): DefDef - - def DefDef(sym: Symbol, mods: Modifiers, rhs: Tree): DefDef - - def DefDef(sym: Symbol, rhs: Tree): DefDef - - def DefDef(sym: Symbol, rhs: List[List[Symbol]] => Tree): DefDef + vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree) extends ValOrDefDef with DefDefApi + object DefDef extends DefDefExtractor - /** An abstract type, a type parameter, or a type alias. - */ case class TypeDef(mods: Modifiers, name: TypeName, tparams: List[TypeDef], rhs: Tree) - extends MemberDef - - /** A TypeDef node which defines given `sym` with given tight hand side `rhs`. */ - def TypeDef(sym: Symbol, rhs: Tree): TypeDef + extends MemberDef with TypeDefApi + object TypeDef extends TypeDefExtractor - /** A TypeDef node which defines abstract type or type parameter for given `sym` */ - def TypeDef(sym: Symbol): TypeDef - - /** A labelled expression. Not expressible in language syntax, but - * generated by the compiler to simulate while/do-while loops, and - * also by the pattern matcher. - * - * The label acts much like a nested function, where `params` represents - * the incoming parameters. The symbol given to the LabelDef should have - * a MethodType, as if it were a nested function. - * - * Jumps are apply nodes attributed with a label's symbol. The - * arguments from the apply node will be passed to the label and - * assigned to the Idents. - * - * Forward jumps within a block are allowed. - */ case class LabelDef(name: TermName, params: List[Ident], rhs: Tree) - extends DefTree with TermTree - - def LabelDef(sym: Symbol, params: List[Symbol], rhs: Tree): LabelDef - - /** Import selector - * - * Representation of an imported name its optional rename and their optional positions - * - * @param name the imported name - * @param namePos its position or -1 if undefined - * @param rename the name the import is renamed to (== name if no renaming) - * @param renamePos the position of the rename or -1 if undefined - */ - case class ImportSelector(name: Name, namePos: Int, rename: Name, renamePos: Int) + extends DefTree with TermTree with LabelDefApi + object LabelDef extends LabelDefExtractor + + case class ImportSelector(name: Name, namePos: Int, rename: Name, renamePos: Int) extends ImportSelectorApi + object ImportSelector extends ImportSelectorExtractor - /** Import clause - * - * @param expr - * @param selectors - */ case class Import(expr: Tree, selectors: List[ImportSelector]) - extends SymTree - // The symbol of an Import is an import symbol @see Symbol.newImport - // It's used primarily as a marker to check that the import has been typechecked. - - /** Instantiation template of a class or trait - * - * @param parents - * @param body - */ + extends SymTree with ImportApi + object Import extends ImportExtractor + case class Template(parents: List[Tree], self: ValDef, body: List[Tree]) - extends SymTree { - // the symbol of a template is a local dummy. @see Symbol.newLocalDummy - // the owner of the local dummy is the enclosing trait or class. - // the local dummy is itself the owner of any local blocks - // For example: - // - // class C { - // def foo // owner is C - // { - // def bar // owner is local dummy - // } - } + extends SymTree with TemplateApi + object Template extends TemplateExtractor - /** Block of expressions (semicolon separated expressions) */ case class Block(stats: List[Tree], expr: Tree) - extends TermTree + extends TermTree with BlockApi + object Block extends BlockExtractor - /** Block factory that flattens directly nested blocks. - */ - def Block(stats: Tree*): Block - - /** Case clause in a pattern match, eliminated during explicitouter - * (except for occurrences in switch statements) - */ case class CaseDef(pat: Tree, guard: Tree, body: Tree) - extends Tree - - /** casedef shorthand */ - def CaseDef(pat: Tree, body: Tree): CaseDef + extends Tree with CaseDefApi + object CaseDef extends CaseDefExtractor - /** Alternatives of patterns, eliminated by explicitouter, except for - * occurrences in encoded Switch stmt (=remaining Match(CaseDef(...)) - */ case class Alternative(trees: List[Tree]) - extends TermTree + extends TermTree with AlternativeApi + object Alternative extends AlternativeExtractor - /** Repetition of pattern, eliminated by explicitouter */ case class Star(elem: Tree) - extends TermTree + extends TermTree with StarApi + object Star extends StarExtractor - /** Bind of a variable to a rhs pattern, eliminated by explicitouter - * - * @param name - * @param body - */ case class Bind(name: Name, body: Tree) - extends DefTree - - def Bind(sym: Symbol, body: Tree): Bind + extends DefTree with BindApi + object Bind extends BindExtractor case class UnApply(fun: Tree, args: List[Tree]) - extends TermTree + extends TermTree with UnApplyApi + object UnApply extends UnApplyExtractor - /** Array of expressions, needs to be translated in backend, - */ case class ArrayValue(elemtpt: Tree, elems: List[Tree]) - extends TermTree + extends TermTree with ArrayValueApi + object ArrayValue extends ArrayValueExtractor - /** Anonymous function, eliminated by analyzer */ case class Function(vparams: List[ValDef], body: Tree) - extends TermTree with SymTree - // The symbol of a Function is a synthetic value of name nme.ANON_FUN_NAME - // It is the owner of the function's parameters. + extends TermTree with SymTree with FunctionApi + object Function extends FunctionExtractor - /** Assignment */ case class Assign(lhs: Tree, rhs: Tree) - extends TermTree + extends TermTree with AssignApi + object Assign extends AssignExtractor - /** Either an assignment or a named argument. Only appears in argument lists, - * eliminated by typecheck (doTypedApply) - */ case class AssignOrNamedArg(lhs: Tree, rhs: Tree) - extends TermTree + extends TermTree with AssignOrNamedArgApi + object AssignOrNamedArg extends AssignOrNamedArgExtractor - /** Conditional expression */ case class If(cond: Tree, thenp: Tree, elsep: Tree) - extends TermTree - - /** - Pattern matching expression (before explicitouter) - * - Switch statements (after explicitouter) - * - * After explicitouter, cases will satisfy the following constraints: - * - * - all guards are `EmptyTree`, - * - all patterns will be either `Literal(Constant(x:Int))` - * or `Alternative(lit|...|lit)` - * - except for an "otherwise" branch, which has pattern - * `Ident(nme.WILDCARD)` - */ + extends TermTree with IfApi + object If extends IfExtractor + case class Match(selector: Tree, cases: List[CaseDef]) - extends TermTree + extends TermTree with MatchApi + object Match extends MatchExtractor - /** Return expression */ case class Return(expr: Tree) - extends TermTree with SymTree - // The symbol of a Return node is the enclosing method. + extends TermTree with SymTree with ReturnApi + object Return extends ReturnExtractor case class Try(block: Tree, catches: List[CaseDef], finalizer: Tree) - extends TermTree - - def Try(body: Tree, cases: (Tree, Tree)*): Try + extends TermTree with TryApi + object Try extends TryExtractor - /** Throw expression */ case class Throw(expr: Tree) - extends TermTree - - def Throw(tpe: Type, args: Tree*): Throw - - /** Object instantiation - * One should always use factory method below to build a user level new. - * - * @param tpt a class type - */ - case class New(tpt: Tree) extends TermTree - - /** Factory method for object creation `new tpt(args_1)...(args_n)` - * A `New(t, as)` is expanded to: `(new t).<init>(as)` - */ - def New(tpt: Tree, argss: List[List[Tree]]): Tree - - /** 0-1 argument list new, based on a type. - */ - def New(tpe: Type, args: Tree*): Tree + extends TermTree with ThrowApi + object Throw extends ThrowExtractor - def New(sym: Symbol, args: Tree*): Tree + case class New(tpt: Tree) extends TermTree with NewApi + object New extends NewExtractor - /** Type annotation, eliminated by explicit outer */ case class Typed(expr: Tree, tpt: Tree) - extends TermTree + extends TermTree with TypedApi + object Typed extends TypedExtractor - /** Common base class for Apply and TypeApply. This could in principle - * be a SymTree, but whether or not a Tree is a SymTree isn't used - * to settle any interesting questions, and it would add a useless - * field to all the instances (useless, since GenericApply forwards to - * the underlying fun.) - */ - abstract class GenericApply extends TermTree { + abstract class GenericApply extends TermTree with GenericApplyApi { val fun: Tree val args: List[Tree] } - /** Explicit type application. - * @PP: All signs point toward it being a requirement that args.nonEmpty, - * but I can't find that explicitly stated anywhere. Unless your last name - * is odersky, you should probably treat it as true. - */ case class TypeApply(fun: Tree, args: List[Tree]) - extends GenericApply { - - // Testing the above theory re: args.nonEmpty. - require(args.nonEmpty, this) + extends GenericApply with TypeApplyApi { override def symbol: Symbol = fun.symbol override def symbol_=(sym: Symbol) { fun.symbol = sym } } + object TypeApply extends TypeApplyExtractor - /** Value application */ case class Apply(fun: Tree, args: List[Tree]) - extends GenericApply { + extends GenericApply with ApplyApi { override def symbol: Symbol = fun.symbol override def symbol_=(sym: Symbol) { fun.symbol = sym } } - - def Apply(sym: Symbol, args: Tree*): Tree + object Apply extends ApplyExtractor // TODO remove this class, add a tree attachment to Apply to track whether implicits were involved // copying trees will all too easily forget to distinguish subclasses @@ -671,120 +398,78 @@ trait Trees { self: Universe => // copying trees will all too easily forget to distinguish subclasses class ApplyImplicitView(fun: Tree, args: List[Tree]) extends Apply(fun, args) - // TODO: use a factory method, not a class (???) - // as a case in point of the comment that should go here by similarity to ApplyToImplicitArgs, - // this tree is considered in importers, but not in treecopier - class ApplyConstructor(tpt: Tree, args: List[Tree]) extends Apply(Select(New(tpt), nme.CONSTRUCTOR), args) { - override def printingPrefix = "ApplyConstructor" - } + def ApplyConstructor(tpt: Tree, args: List[Tree]) = Apply(Select(New(tpt), nme.CONSTRUCTOR), args) - /** Dynamic value application. - * In a dynamic application q.f(as) - * - q is stored in qual - * - as is stored in args - * - f is stored as the node's symbol field. - */ case class ApplyDynamic(qual: Tree, args: List[Tree]) - extends TermTree with SymTree - // The symbol of an ApplyDynamic is the function symbol of `qual`, or NoSymbol, if there is none. + extends TermTree with SymTree with ApplyDynamicApi + object ApplyDynamic extends ApplyDynamicExtractor - /** Super reference, qual = corresponding this reference - * A super reference C.super[M] is represented as Super(This(C), M). - */ - case class Super(qual: Tree, mix: TypeName) extends TermTree { - // The symbol of a Super is the class _from_ which the super reference is made. - // For instance in C.super(...), it would be C. + case class Super(qual: Tree, mix: TypeName) extends TermTree with SuperApi { override def symbol: Symbol = qual.symbol override def symbol_=(sym: Symbol) { qual.symbol = sym } } + object Super extends SuperExtractor - def Super(sym: Symbol, mix: TypeName): Tree - - /** Self reference */ case class This(qual: TypeName) - extends TermTree with SymTree - // The symbol of a This is the class to which the this refers. - // For instance in C.this, it would be C. - - def This(sym: Symbol): Tree + extends TermTree with SymTree with ThisApi + object This extends ThisExtractor - /** Designator <qualifier> . <name> */ case class Select(qualifier: Tree, name: Name) - extends RefTree + extends RefTree with SelectApi + object Select extends SelectExtractor - def Select(qualifier: Tree, name: String): Select - - def Select(qualifier: Tree, sym: Symbol): Select - - /** Identifier <name> */ - case class Ident(name: Name) extends RefTree { + case class Ident(name: Name) extends RefTree with IdentContextApi { def qualifier: Tree = EmptyTree - def isBackquoted = this hasAttachment BackquotedIdentifier + def isBackquoted = this.attachments.get[BackquotedIdentifierAttachment.type].isDefined } + object Ident extends IdentExtractor - def Ident(name: String): Ident - - def Ident(sym: Symbol): Ident - - /** Marks underlying reference to id as boxed. - * @pre id must refer to a captured variable - * A reference such marked will refer to the boxed entity, no dereferencing - * with `.elem` is done on it. - * This tree node can be emitted by macros such as reify that call referenceCapturedVariable. - * It is eliminated in LambdaLift, where the boxing conversion takes place. - */ - case class ReferenceToBoxed(ident: Ident) extends TermTree { + case class ReferenceToBoxed(ident: Ident) extends TermTree with ReferenceToBoxedApi { override def symbol: Symbol = ident.symbol override def symbol_=(sym: Symbol) { ident.symbol = sym } } + object ReferenceToBoxed extends ReferenceToBoxedExtractor - /** Literal */ case class Literal(value: Constant) - extends TermTree { + extends TermTree with LiteralApi { assert(value ne null) } + object Literal extends LiteralExtractor // @deprecated("will be removed and then be re-introduced with changed semantics, use Literal(Constant(x)) instead") // def Literal(x: Any) = new Literal(Constant(x)) - /** A tree that has an annotation attached to it. Only used for annotated types and - * annotation ascriptions, annotations on definitions are stored in the Modifiers. - * Eliminated by typechecker (typedAnnotated), the annotations are then stored in - * an AnnotatedType. - */ - case class Annotated(annot: Tree, arg: Tree) extends Tree + case class Annotated(annot: Tree, arg: Tree) extends Tree with AnnotatedApi + object Annotated extends AnnotatedExtractor - /** Singleton type, eliminated by RefCheck */ case class SingletonTypeTree(ref: Tree) - extends TypTree + extends TypTree with SingletonTypeTreeApi + object SingletonTypeTree extends SingletonTypeTreeExtractor - /** Type selection <qualifier> # <name>, eliminated by RefCheck */ case class SelectFromTypeTree(qualifier: Tree, name: TypeName) - extends TypTree with RefTree + extends TypTree with RefTree with SelectFromTypeTreeApi + object SelectFromTypeTree extends SelectFromTypeTreeExtractor - /** Intersection type <parent1> with ... with <parentN> { <decls> }, eliminated by RefCheck */ case class CompoundTypeTree(templ: Template) - extends TypTree + extends TypTree with CompoundTypeTreeApi + object CompoundTypeTree extends CompoundTypeTreeExtractor - /** Applied type <tpt> [ <args> ], eliminated by RefCheck */ case class AppliedTypeTree(tpt: Tree, args: List[Tree]) - extends TypTree { + extends TypTree with AppliedTypeTreeApi { override def symbol: Symbol = tpt.symbol override def symbol_=(sym: Symbol) { tpt.symbol = sym } } + object AppliedTypeTree extends AppliedTypeTreeExtractor case class TypeBoundsTree(lo: Tree, hi: Tree) - extends TypTree + extends TypTree with TypeBoundsTreeApi + object TypeBoundsTree extends TypeBoundsTreeExtractor case class ExistentialTypeTree(tpt: Tree, whereClauses: List[Tree]) - extends TypTree - - /** A synthetic tree holding an arbitrary type. Not to be confused with - * with TypTree, the trait for trees that are only used for type trees. - * TypeTree's are inserted in several places, but most notably in - * `RefCheck`, where the arbitrary type trees are all replaced by - * TypeTree's. */ - case class TypeTree() extends TypTree { + extends TypTree with ExistentialTypeTreeApi + object ExistentialTypeTree extends ExistentialTypeTreeExtractor + + case class TypeTree() extends TypTree with TypeTreeContextApi { private var orig: Tree = null private[scala] var wasEmpty: Boolean = false @@ -798,8 +483,8 @@ trait Trees { self: Universe => case t => t } - orig = followOriginal(tree) - this setPos tree.pos + orig = followOriginal(tree); setPos(tree.pos); + this } override def defineType(tp: Type): this.type = { @@ -807,306 +492,10 @@ trait Trees { self: Universe => setType(tp) } } + object TypeTree extends TypeTreeExtractor def TypeTree(tp: Type): TypeTree = TypeTree() setType tp - /** An empty deferred value definition corresponding to: - * val _: _ - * This is used as a placeholder in the `self` parameter Template if there is - * no definition of a self value of self type. - */ - def emptyValDef: ValDef - - // ------ traversers, copiers, and transformers --------------------------------------------- - - val treeCopy = newLazyTreeCopier - - def copyDefDef(tree: Tree)( - mods: Modifiers = null, - name: Name = null, - tparams: List[TypeDef] = null, - vparamss: List[List[ValDef]] = null, - tpt: Tree = null, - rhs: Tree = null - ): DefDef = tree match { - case DefDef(mods0, name0, tparams0, vparamss0, tpt0, rhs0) => - treeCopy.DefDef(tree, - if (mods eq null) mods0 else mods, - if (name eq null) name0 else name, - if (tparams eq null) tparams0 else tparams, - if (vparamss eq null) vparamss0 else vparamss, - if (tpt eq null) tpt0 else tpt, - if (rhs eq null) rhs0 else rhs - ) - case t => - sys.error("Not a DefDef: " + t + "/" + t.getClass) - } - def copyValDef(tree: Tree)( - mods: Modifiers = null, - name: Name = null, - tpt: Tree = null, - rhs: Tree = null - ): ValDef = tree match { - case ValDef(mods0, name0, tpt0, rhs0) => - treeCopy.ValDef(tree, - if (mods eq null) mods0 else mods, - if (name eq null) name0 else name, - if (tpt eq null) tpt0 else tpt, - if (rhs eq null) rhs0 else rhs - ) - case t => - sys.error("Not a ValDef: " + t + "/" + t.getClass) - } - def copyClassDef(tree: Tree)( - mods: Modifiers = null, - name: Name = null, - tparams: List[TypeDef] = null, - impl: Template = null - ): ClassDef = tree match { - case ClassDef(mods0, name0, tparams0, impl0) => - treeCopy.ClassDef(tree, - if (mods eq null) mods0 else mods, - if (name eq null) name0 else name, - if (tparams eq null) tparams0 else tparams, - if (impl eq null) impl0 else impl - ) - case t => - sys.error("Not a ClassDef: " + t + "/" + t.getClass) - } - - def deriveDefDef(ddef: Tree)(applyToRhs: Tree => Tree): DefDef = ddef match { - case DefDef(mods0, name0, tparams0, vparamss0, tpt0, rhs0) => - treeCopy.DefDef(ddef, mods0, name0, tparams0, vparamss0, tpt0, applyToRhs(rhs0)) - case t => - sys.error("Not a DefDef: " + t + "/" + t.getClass) - } - def deriveValDef(vdef: Tree)(applyToRhs: Tree => Tree): ValDef = vdef match { - case ValDef(mods0, name0, tpt0, rhs0) => - treeCopy.ValDef(vdef, mods0, name0, tpt0, applyToRhs(rhs0)) - case t => - sys.error("Not a ValDef: " + t + "/" + t.getClass) - } - def deriveTemplate(templ: Tree)(applyToBody: List[Tree] => List[Tree]): Template = templ match { - case Template(parents0, self0, body0) => - treeCopy.Template(templ, parents0, self0, applyToBody(body0)) - case t => - sys.error("Not a Template: " + t + "/" + t.getClass) - } - def deriveClassDef(cdef: Tree)(applyToImpl: Template => Template): ClassDef = cdef match { - case ClassDef(mods0, name0, tparams0, impl0) => - treeCopy.ClassDef(cdef, mods0, name0, tparams0, applyToImpl(impl0)) - case t => - sys.error("Not a ClassDef: " + t + "/" + t.getClass) - } - def deriveModuleDef(mdef: Tree)(applyToImpl: Template => Template): ModuleDef = mdef match { - case ModuleDef(mods0, name0, impl0) => - treeCopy.ModuleDef(mdef, mods0, name0, applyToImpl(impl0)) - case t => - sys.error("Not a ModuleDef: " + t + "/" + t.getClass) - } - def deriveCaseDef(cdef: Tree)(applyToBody: Tree => Tree): CaseDef = cdef match { - case CaseDef(pat0, guard0, body0) => - treeCopy.CaseDef(cdef, pat0, guard0, applyToBody(body0)) - case t => - sys.error("Not a CaseDef: " + t + "/" + t.getClass) - } - def deriveLabelDef(ldef: Tree)(applyToRhs: Tree => Tree): LabelDef = ldef match { - case LabelDef(name0, params0, rhs0) => - treeCopy.LabelDef(ldef, name0, params0, applyToRhs(rhs0)) - case t => - sys.error("Not a LabelDef: " + t + "/" + t.getClass) - } - - class Traverser { - protected var currentOwner: Symbol = definitions.RootClass - - def traverse(tree: Tree): Unit = tree match { - case EmptyTree => - ; - case PackageDef(pid, stats) => - traverse(pid) - atOwner(tree.symbol.moduleClass) { - traverseTrees(stats) - } - case ClassDef(mods, name, tparams, impl) => - atOwner(tree.symbol) { - traverseTrees(mods.annotations); traverseTrees(tparams); traverse(impl) - } - case ModuleDef(mods, name, impl) => - atOwner(tree.symbol.moduleClass) { - traverseTrees(mods.annotations); traverse(impl) - } - case ValDef(mods, name, tpt, rhs) => - atOwner(tree.symbol) { - traverseTrees(mods.annotations); traverse(tpt); traverse(rhs) - } - case DefDef(mods, name, tparams, vparamss, tpt, rhs) => - atOwner(tree.symbol) { - traverseTrees(mods.annotations); traverseTrees(tparams); traverseTreess(vparamss); traverse(tpt); traverse(rhs) - } - case TypeDef(mods, name, tparams, rhs) => - atOwner(tree.symbol) { - traverseTrees(mods.annotations); traverseTrees(tparams); traverse(rhs) - } - case LabelDef(name, params, rhs) => - traverseTrees(params); traverse(rhs) - case Import(expr, selectors) => - traverse(expr) - case Annotated(annot, arg) => - traverse(annot); traverse(arg) - case Template(parents, self, body) => - traverseTrees(parents) - if (!self.isEmpty) traverse(self) - traverseStats(body, tree.symbol) - case Block(stats, expr) => - traverseTrees(stats); traverse(expr) - case CaseDef(pat, guard, body) => - traverse(pat); traverse(guard); traverse(body) - case Alternative(trees) => - traverseTrees(trees) - case Star(elem) => - traverse(elem) - case Bind(name, body) => - traverse(body) - case UnApply(fun, args) => - traverse(fun); traverseTrees(args) - case ArrayValue(elemtpt, trees) => - traverse(elemtpt); traverseTrees(trees) - case Function(vparams, body) => - atOwner(tree.symbol) { - traverseTrees(vparams); traverse(body) - } - case Assign(lhs, rhs) => - traverse(lhs); traverse(rhs) - case AssignOrNamedArg(lhs, rhs) => - traverse(lhs); traverse(rhs) - case If(cond, thenp, elsep) => - traverse(cond); traverse(thenp); traverse(elsep) - case Match(selector, cases) => - traverse(selector); traverseTrees(cases) - case Return(expr) => - traverse(expr) - case Try(block, catches, finalizer) => - traverse(block); traverseTrees(catches); traverse(finalizer) - case Throw(expr) => - traverse(expr) - case New(tpt) => - traverse(tpt) - case Typed(expr, tpt) => - traverse(expr); traverse(tpt) - case TypeApply(fun, args) => - traverse(fun); traverseTrees(args) - case Apply(fun, args) => - traverse(fun); traverseTrees(args) - case ApplyDynamic(qual, args) => - traverse(qual); traverseTrees(args) - case Super(qual, _) => - traverse(qual) - case This(_) => - ; - case Select(qualifier, selector) => - traverse(qualifier) - case Ident(_) => - ; - case ReferenceToBoxed(idt) => - traverse(idt) - case Literal(_) => - ; - case TypeTree() => - ; - case SingletonTypeTree(ref) => - traverse(ref) - case SelectFromTypeTree(qualifier, selector) => - traverse(qualifier) - case CompoundTypeTree(templ) => - traverse(templ) - case AppliedTypeTree(tpt, args) => - traverse(tpt); traverseTrees(args) - case TypeBoundsTree(lo, hi) => - traverse(lo); traverse(hi) - case ExistentialTypeTree(tpt, whereClauses) => - traverse(tpt); traverseTrees(whereClauses) - case _ => xtraverse(this, tree) - } - - def traverseTrees(trees: List[Tree]) { - trees foreach traverse - } - def traverseTreess(treess: List[List[Tree]]) { - treess foreach traverseTrees - } - def traverseStats(stats: List[Tree], exprOwner: Symbol) { - stats foreach (stat => - if (exprOwner != currentOwner) atOwner(exprOwner)(traverse(stat)) - else traverse(stat) - ) - } - - def atOwner(owner: Symbol)(traverse: => Unit) { - val prevOwner = currentOwner - currentOwner = owner - traverse - currentOwner = prevOwner - } - - /** Leave apply available in the generic traverser to do something else. - */ - def apply[T <: Tree](tree: T): T = { traverse(tree); tree } - } - - protected def xtraverse(traverser: Traverser, tree: Tree): Unit = throw new MatchError(tree) - - // to be implemented in subclasses: - type TreeCopier <: TreeCopierOps - def newStrictTreeCopier: TreeCopier - def newLazyTreeCopier: TreeCopier - - trait TreeCopierOps { - def ClassDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], impl: Template): ClassDef - def PackageDef(tree: Tree, pid: RefTree, stats: List[Tree]): PackageDef - def ModuleDef(tree: Tree, mods: Modifiers, name: Name, impl: Template): ModuleDef - def ValDef(tree: Tree, mods: Modifiers, name: Name, tpt: Tree, rhs: Tree): ValDef - def DefDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree): DefDef - def TypeDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], rhs: Tree): TypeDef - def LabelDef(tree: Tree, name: Name, params: List[Ident], rhs: Tree): LabelDef - def Import(tree: Tree, expr: Tree, selectors: List[ImportSelector]): Import - def Template(tree: Tree, parents: List[Tree], self: ValDef, body: List[Tree]): Template - def Block(tree: Tree, stats: List[Tree], expr: Tree): Block - def CaseDef(tree: Tree, pat: Tree, guard: Tree, body: Tree): CaseDef - def Alternative(tree: Tree, trees: List[Tree]): Alternative - def Star(tree: Tree, elem: Tree): Star - def Bind(tree: Tree, name: Name, body: Tree): Bind - def UnApply(tree: Tree, fun: Tree, args: List[Tree]): UnApply - def ArrayValue(tree: Tree, elemtpt: Tree, trees: List[Tree]): ArrayValue - def Function(tree: Tree, vparams: List[ValDef], body: Tree): Function - def Assign(tree: Tree, lhs: Tree, rhs: Tree): Assign - def AssignOrNamedArg(tree: Tree, lhs: Tree, rhs: Tree): AssignOrNamedArg - def If(tree: Tree, cond: Tree, thenp: Tree, elsep: Tree): If - def Match(tree: Tree, selector: Tree, cases: List[CaseDef]): Match - def Return(tree: Tree, expr: Tree): Return - def Try(tree: Tree, block: Tree, catches: List[CaseDef], finalizer: Tree): Try - def Throw(tree: Tree, expr: Tree): Throw - def New(tree: Tree, tpt: Tree): New - def Typed(tree: Tree, expr: Tree, tpt: Tree): Typed - def TypeApply(tree: Tree, fun: Tree, args: List[Tree]): TypeApply - def Apply(tree: Tree, fun: Tree, args: List[Tree]): Apply - def ApplyDynamic(tree: Tree, qual: Tree, args: List[Tree]): ApplyDynamic - def Super(tree: Tree, qual: Tree, mix: TypeName): Super - def This(tree: Tree, qual: Name): This - def Select(tree: Tree, qualifier: Tree, selector: Name): Select - def Ident(tree: Tree, name: Name): Ident - def ReferenceToBoxed(tree: Tree, idt: Ident): ReferenceToBoxed - def Literal(tree: Tree, value: Constant): Literal - def TypeTree(tree: Tree): TypeTree - def Annotated(tree: Tree, annot: Tree, arg: Tree): Annotated - def SingletonTypeTree(tree: Tree, ref: Tree): SingletonTypeTree - def SelectFromTypeTree(tree: Tree, qualifier: Tree, selector: Name): SelectFromTypeTree - def CompoundTypeTree(tree: Tree, templ: Template): CompoundTypeTree - def AppliedTypeTree(tree: Tree, tpt: Tree, args: List[Tree]): AppliedTypeTree - def TypeBoundsTree(tree: Tree, lo: Tree, hi: Tree): TypeBoundsTree - def ExistentialTypeTree(tree: Tree, tpt: Tree, whereClauses: List[Tree]): ExistentialTypeTree - } - class StrictTreeCopier extends TreeCopierOps { def ClassDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], impl: Template) = new ClassDef(mods, name.toTypeName, tparams, impl).copyAttrs(tree) @@ -1177,11 +566,8 @@ trait Trees { self: Universe => new This(qual.toTypeName).copyAttrs(tree) def Select(tree: Tree, qualifier: Tree, selector: Name) = new Select(qualifier, selector).copyAttrs(tree) - def Ident(tree: Tree, name: Name) = { - val t = new Ident(name) copyAttrs tree - if (tree hasAttachment BackquotedIdentifier) t withAttachment BackquotedIdentifier - else t - } + def Ident(tree: Tree, name: Name) = + new Ident(name) copyAttrs tree def ReferenceToBoxed(tree: Tree, idt: Ident) = new ReferenceToBoxed(idt).copyAttrs(tree) def Literal(tree: Tree, value: Constant) = @@ -1423,19 +809,349 @@ trait Trees { self: Universe => } } - abstract class Transformer { - val treeCopy: TreeCopier = newLazyTreeCopier - protected var currentOwner: Symbol = definitions.RootClass - protected def currentMethod = currentOwner.enclosingMethod - protected def currentClass = currentOwner.enclosingClass - protected def currentPackage = currentOwner.enclosingTopLevelClass.owner - def transform(tree: Tree): Tree = tree match { + // Belongs in TreeInfo but then I can't reach it from TreePrinters. + def isReferenceToScalaMember(t: Tree, Id: Name) = t match { + case Ident(Id) => true + case Select(Ident(nme.scala_), Id) => true + case Select(Select(Ident(nme.ROOTPKG), nme.scala_), Id) => true + case _ => false + } + /** Is the tree Predef, scala.Predef, or _root_.scala.Predef? + */ + def isReferenceToPredef(t: Tree) = isReferenceToScalaMember(t, nme.Predef) + def isReferenceToAnyVal(t: Tree) = isReferenceToScalaMember(t, tpnme.AnyVal) + + // --- modifiers implementation --------------------------------------- + + /** @param privateWithin the qualifier for a private (a type name) + * or tpnme.EMPTY, if none is given. + * @param annotations the annotations for the definition. + * '''Note:''' the typechecker drops these annotations, + * use the AnnotationInfo's (Symbol.annotations) in later phases. + */ + case class Modifiers(flags: Long, + privateWithin: Name, + annotations: List[Tree]) extends ModifiersApi with HasFlags { + + var positions: Map[Long, Position] = Map() + + def setPositions(poss: Map[Long, Position]): this.type = { + positions = poss; this + } + + /* Abstract types from HasFlags. */ + type AccessBoundaryType = Name + type AnnotationType = Tree + + def hasAnnotationNamed(name: TypeName) = { + annotations exists { + case Apply(Select(New(Ident(`name`)), _), _) => true + case Apply(Select(New(Select(_, `name`)), _), _) => true + case _ => false + } + } + + def hasAccessBoundary = privateWithin != tpnme.EMPTY + def hasAllFlags(mask: Long): Boolean = (flags & mask) == mask + def hasFlag(flag: Long) = (flag & flags) != 0L + + def & (flag: Long): Modifiers = { + val flags1 = flags & flag + if (flags1 == flags) this + else Modifiers(flags1, privateWithin, annotations) setPositions positions + } + def &~ (flag: Long): Modifiers = { + val flags1 = flags & (~flag) + if (flags1 == flags) this + else Modifiers(flags1, privateWithin, annotations) setPositions positions + } + def | (flag: Long): Modifiers = { + val flags1 = flags | flag + if (flags1 == flags) this + else Modifiers(flags1, privateWithin, annotations) setPositions positions + } + def withAnnotations(annots: List[Tree]) = + if (annots.isEmpty) this + else copy(annotations = annotations ::: annots) setPositions positions + + def withPosition(flag: Long, position: Position) = + copy() setPositions positions + (flag -> position) + + override def mapAnnotations(f: List[Tree] => List[Tree]): Modifiers = + Modifiers(flags, privateWithin, f(annotations)) setPositions positions + + override def toString = "Modifiers(%s, %s, %s)".format(flagString, annotations mkString ", ", positions) + } + + object Modifiers extends ModifiersCreator + + implicit val ModifiersTag = ClassTag[Modifiers](classOf[Modifiers]) + + // ---- values and creators --------------------------------------- + + /** @param sym the class symbol + * @return the implementation template + */ + def ClassDef(sym: Symbol, impl: Template): ClassDef = + atPos(sym.pos) { + ClassDef(Modifiers(sym.flags), + sym.name.toTypeName, + sym.typeParams map TypeDef, + impl) setSymbol sym + } + + /** + * @param sym the class symbol + * @param impl the implementation template + */ + def ModuleDef(sym: Symbol, impl: Template): ModuleDef = + atPos(sym.pos) { + ModuleDef(Modifiers(sym.flags), sym.name.toTermName, impl) setSymbol sym + } + + def ValDef(sym: Symbol, rhs: Tree): ValDef = + atPos(sym.pos) { + ValDef(Modifiers(sym.flags), sym.name.toTermName, + TypeTree(sym.tpe) setPos sym.pos.focus, + rhs) setSymbol sym + } + + def ValDef(sym: Symbol): ValDef = ValDef(sym, EmptyTree) + + object emptyValDef extends ValDef(Modifiers(PRIVATE), nme.WILDCARD, TypeTree(NoType), EmptyTree) { + override def isEmpty = true + super.setPos(NoPosition) + override def setPos(pos: Position) = { assert(false); this } + } + + def DefDef(sym: Symbol, mods: Modifiers, vparamss: List[List[ValDef]], rhs: Tree): DefDef = + atPos(sym.pos) { + assert(sym != NoSymbol) + DefDef(mods, + sym.name.toTermName, + sym.typeParams map TypeDef, + vparamss, + TypeTree(sym.tpe.finalResultType) setPos sym.pos.focus, + rhs) setSymbol sym + } + + def DefDef(sym: Symbol, vparamss: List[List[ValDef]], rhs: Tree): DefDef = + DefDef(sym, Modifiers(sym.flags), vparamss, rhs) + + def DefDef(sym: Symbol, mods: Modifiers, rhs: Tree): DefDef = + DefDef(sym, mods, mapParamss(sym)(ValDef), rhs) + + def DefDef(sym: Symbol, rhs: Tree): DefDef = + DefDef(sym, Modifiers(sym.flags), rhs) + + def DefDef(sym: Symbol, rhs: List[List[Symbol]] => Tree): DefDef = + DefDef(sym, rhs(sym.info.paramss)) + + /** A TypeDef node which defines given `sym` with given tight hand side `rhs`. */ + def TypeDef(sym: Symbol, rhs: Tree): TypeDef = + atPos(sym.pos) { + TypeDef(Modifiers(sym.flags), sym.name.toTypeName, sym.typeParams map TypeDef, rhs) setSymbol sym + } + + /** A TypeDef node which defines abstract type or type parameter for given `sym` */ + def TypeDef(sym: Symbol): TypeDef = + TypeDef(sym, TypeBoundsTree(TypeTree(sym.info.bounds.lo), TypeTree(sym.info.bounds.hi))) + + def LabelDef(sym: Symbol, params: List[Symbol], rhs: Tree): LabelDef = + atPos(sym.pos) { + LabelDef(sym.name.toTermName, params map Ident, rhs) setSymbol sym + } + + /** casedef shorthand */ + def CaseDef(pat: Tree, body: Tree): CaseDef = + CaseDef(pat, EmptyTree, body) + + def Bind(sym: Symbol, body: Tree): Bind = + Bind(sym.name, body) setSymbol sym + + def Try(body: Tree, cases: (Tree, Tree)*): Try = + Try(body, cases.toList map { case (pat, rhs) => CaseDef(pat, EmptyTree, rhs) }, EmptyTree) + + def Throw(tpe: Type, args: Tree*): Throw = + Throw(New(tpe, args: _*)) + + def Apply(sym: Symbol, args: Tree*): Tree = + Apply(Ident(sym), args.toList) + + /** Factory method for object creation `new tpt(args_1)...(args_n)` + * A `New(t, as)` is expanded to: `(new t).<init>(as)` + */ + def New(tpt: Tree, argss: List[List[Tree]]): Tree = argss match { + case Nil => ApplyConstructor(tpt, Nil) + case xs :: rest => { + def mkApply(fun: Tree, args: List[Tree]) = Apply(fun, args) + rest.foldLeft(ApplyConstructor(tpt, xs): Tree)(mkApply) + // [Eugene++] no longer compiles after I moved the `Apply` case class here + // rest.foldLeft(ApplyConstructor(tpt, xs): Tree)(Apply) + } + } + + /** 0-1 argument list new, based on a type. + */ + def New(tpe: Type, args: Tree*): Tree = + ApplyConstructor(TypeTree(tpe), args.toList) + + def New(sym: Symbol, args: Tree*): Tree = + New(sym.tpe, args: _*) + + def Super(sym: Symbol, mix: TypeName): Tree = + Super(This(sym), mix) + + def This(sym: Symbol): Tree = + This(sym.name.toTypeName) setSymbol sym + + def Select(qualifier: Tree, name: String): Select = + Select(qualifier, newTermName(name)) + + def Select(qualifier: Tree, sym: Symbol): Select = + Select(qualifier, sym.name) setSymbol sym + + def Ident(name: String): Ident = + Ident(newTermName(name)) + + def Ident(sym: Symbol): Ident = + Ident(sym.name) setSymbol sym + + /** Block factory that flattens directly nested blocks. + */ + def Block(stats: Tree*): Block = { + if (stats.isEmpty) Block(Nil, Literal(Constant(()))) + else stats match { + case Seq(b @ Block(_, _)) => b + case Seq(stat) => Block(stats.toList, Literal(Constant(()))) + case Seq(_, rest @ _*) => Block(stats.init.toList, stats.last) + } + } + + // --- generic traversers and transformers + + override protected def itraverse(traverser: Traverser, tree: Tree): Unit = { + import traverser._ + tree match { + case EmptyTree => + ; + case PackageDef(pid, stats) => + traverse(pid) + atOwner(mclass(tree.symbol)) { + traverseTrees(stats) + } + case ClassDef(mods, name, tparams, impl) => + atOwner(tree.symbol) { + traverseTrees(mods.annotations); traverseTrees(tparams); traverse(impl) + } + case ModuleDef(mods, name, impl) => + atOwner(mclass(tree.symbol)) { + traverseTrees(mods.annotations); traverse(impl) + } + case ValDef(mods, name, tpt, rhs) => + atOwner(tree.symbol) { + traverseTrees(mods.annotations); traverse(tpt); traverse(rhs) + } + case DefDef(mods, name, tparams, vparamss, tpt, rhs) => + atOwner(tree.symbol) { + traverseTrees(mods.annotations); traverseTrees(tparams); traverseTreess(vparamss); traverse(tpt); traverse(rhs) + } + case TypeDef(mods, name, tparams, rhs) => + atOwner(tree.symbol) { + traverseTrees(mods.annotations); traverseTrees(tparams); traverse(rhs) + } + case LabelDef(name, params, rhs) => + traverseTrees(params); traverse(rhs) + case Import(expr, selectors) => + traverse(expr) + case Annotated(annot, arg) => + traverse(annot); traverse(arg) + case Template(parents, self, body) => + traverseTrees(parents) + if (!self.isEmpty) traverse(self) + traverseStats(body, tree.symbol) + case Block(stats, expr) => + traverseTrees(stats); traverse(expr) + case CaseDef(pat, guard, body) => + traverse(pat); traverse(guard); traverse(body) + case Alternative(trees) => + traverseTrees(trees) + case Star(elem) => + traverse(elem) + case Bind(name, body) => + traverse(body) + case UnApply(fun, args) => + traverse(fun); traverseTrees(args) + case ArrayValue(elemtpt, trees) => + traverse(elemtpt); traverseTrees(trees) + case Function(vparams, body) => + atOwner(tree.symbol) { + traverseTrees(vparams); traverse(body) + } + case Assign(lhs, rhs) => + traverse(lhs); traverse(rhs) + case AssignOrNamedArg(lhs, rhs) => + traverse(lhs); traverse(rhs) + case If(cond, thenp, elsep) => + traverse(cond); traverse(thenp); traverse(elsep) + case Match(selector, cases) => + traverse(selector); traverseTrees(cases) + case Return(expr) => + traverse(expr) + case Try(block, catches, finalizer) => + traverse(block); traverseTrees(catches); traverse(finalizer) + case Throw(expr) => + traverse(expr) + case New(tpt) => + traverse(tpt) + case Typed(expr, tpt) => + traverse(expr); traverse(tpt) + case TypeApply(fun, args) => + traverse(fun); traverseTrees(args) + case Apply(fun, args) => + traverse(fun); traverseTrees(args) + case ApplyDynamic(qual, args) => + traverse(qual); traverseTrees(args) + case Super(qual, _) => + traverse(qual) + case This(_) => + ; + case Select(qualifier, selector) => + traverse(qualifier) + case Ident(_) => + ; + case ReferenceToBoxed(idt) => + traverse(idt) + case Literal(_) => + ; + case TypeTree() => + ; + case SingletonTypeTree(ref) => + traverse(ref) + case SelectFromTypeTree(qualifier, selector) => + traverse(qualifier) + case CompoundTypeTree(templ) => + traverse(templ) + case AppliedTypeTree(tpt, args) => + traverse(tpt); traverseTrees(args) + case TypeBoundsTree(lo, hi) => + traverse(lo); traverse(hi) + case ExistentialTypeTree(tpt, whereClauses) => + traverse(tpt); traverseTrees(whereClauses) + case _ => xtraverse(traverser, tree) + } + } + + override protected def itransform(transformer: Transformer, tree: Tree): Tree = { + import transformer._ + val treeCopy = transformer.treeCopy + tree match { case EmptyTree => tree case PackageDef(pid, stats) => treeCopy.PackageDef( tree, transform(pid).asInstanceOf[RefTree], - atOwner(tree.symbol.moduleClass) { + atOwner(mclass(tree.symbol)) { transformStats(stats, currentOwner) } ) @@ -1445,7 +1161,7 @@ trait Trees { self: Universe => transformTypeDefs(tparams), transformTemplate(impl)) } case ModuleDef(mods, name, impl) => - atOwner(tree.symbol.moduleClass) { + atOwner(mclass(tree.symbol)) { treeCopy.ModuleDef(tree, transformModifiers(mods), name, transformTemplate(impl)) } @@ -1542,42 +1258,144 @@ trait Trees { self: Universe => case ExistentialTypeTree(tpt, whereClauses) => treeCopy.ExistentialTypeTree(tree, transform(tpt), transformTrees(whereClauses)) case _ => - xtransform(this, tree) - } - - def transformTrees(trees: List[Tree]): List[Tree] = - trees mapConserve (transform(_)) - def transformTemplate(tree: Template): Template = - transform(tree: Tree).asInstanceOf[Template] - def transformTypeDefs(trees: List[TypeDef]): List[TypeDef] = - trees mapConserve (tree => transform(tree).asInstanceOf[TypeDef]) - def transformValDef(tree: ValDef): ValDef = - if (tree.isEmpty) tree else transform(tree).asInstanceOf[ValDef] - def transformValDefs(trees: List[ValDef]): List[ValDef] = - trees mapConserve (transformValDef(_)) - def transformValDefss(treess: List[List[ValDef]]): List[List[ValDef]] = - treess mapConserve (transformValDefs(_)) - def transformCaseDefs(trees: List[CaseDef]): List[CaseDef] = - trees mapConserve (tree => transform(tree).asInstanceOf[CaseDef]) - def transformIdents(trees: List[Ident]): List[Ident] = - trees mapConserve (tree => transform(tree).asInstanceOf[Ident]) - def transformStats(stats: List[Tree], exprOwner: Symbol): List[Tree] = - stats mapConserve (stat => - if (exprOwner != currentOwner && stat.isTerm) atOwner(exprOwner)(transform(stat)) - else transform(stat)) filter (EmptyTree != _) - def transformModifiers(mods: Modifiers): Modifiers = - mods.mapAnnotations(transformTrees) - - def atOwner[A](owner: Symbol)(trans: => A): A = { - val prevOwner = currentOwner - currentOwner = owner - val result = trans - currentOwner = prevOwner - result + xtransform(transformer, tree) + } + } + + private def mclass(sym: Symbol) = sym map (_.asModuleSymbol.moduleClass) + + // --- specific traversers and transformers + + @deprecated("Moved to tree.duplicate", "2.10.0") + protected[scala] def duplicateTree(tree: Tree): Tree = tree.duplicate + + class ForeachPartialTreeTraverser(pf: PartialFunction[Tree, Tree]) extends Traverser { + override def traverse(tree: Tree) { + val t = if (pf isDefinedAt tree) pf(tree) else tree + super.traverse(t) + } + } + + class ChangeOwnerTraverser(val oldowner: Symbol, val newowner: Symbol) extends Traverser { + def changeOwner(tree: Tree) = tree match { + case Return(expr) => + if (tree.symbol == oldowner) { + // SI-5612 + if (newowner hasTransOwner oldowner) + log("NOT changing owner of %s because %s is nested in %s".format(tree, newowner, oldowner)) + else { + log("changing owner of %s: %s => %s".format(tree, oldowner, newowner)) + tree.symbol = newowner + } + } + case _: DefTree | _: Function => + if (tree.symbol != NoSymbol && tree.symbol.owner == oldowner) { + tree.symbol.owner = newowner + } + case _ => + } + override def traverse(tree: Tree) { + changeOwner(tree) + super.traverse(tree) + } + } + + private class ShallowDuplicator(orig: Tree) extends Transformer { + override val treeCopy = newStrictTreeCopier + override def transform(tree: Tree) = + if (tree eq orig) super.transform(tree) + else tree + } + // Create a readable string describing a substitution. + private def substituterString(fromStr: String, toStr: String, from: List[Any], to: List[Any]): String = { + "subst[%s, %s](%s)".format(fromStr, toStr, (from, to).zipped map (_ + " -> " + _) mkString ", ") + } + + // NOTE: calls shallowDuplicate on trees in `to` to avoid problems when symbols in `from` + // occur multiple times in the `tree` passed to `transform`, + // otherwise, the resulting Tree would be a graph, not a tree... this breaks all sorts of stuff, + // notably concerning the mutable aspects of Trees (such as setting their .tpe) + class TreeSubstituter(from: List[Symbol], to: List[Tree]) extends Transformer { + override def transform(tree: Tree): Tree = tree match { + case Ident(_) => + def subst(from: List[Symbol], to: List[Tree]): Tree = + if (from.isEmpty) tree + else if (tree.symbol == from.head) to.head.shallowDuplicate // TODO: does it ever make sense *not* to perform a shallowDuplicate on `to.head`? + else subst(from.tail, to.tail); + subst(from, to) + case _ => + super.transform(tree) + } + override def toString = substituterString("Symbol", "Tree", from, to) + } + + /** Substitute clazz.this with `to`. `to` must be an attributed tree. + */ + class ThisSubstituter(clazz: Symbol, to: => Tree) extends Transformer { + val newtpe = to.tpe + override def transform(tree: Tree) = { + if (tree.tpe ne null) tree.tpe = tree.tpe.substThis(clazz, newtpe) + tree match { + case This(_) if tree.symbol == clazz => to + case _ => super.transform(tree) + } + } + } + + class TypeMapTreeSubstituter(val typeMap: TypeMap) extends Traverser { + override def traverse(tree: Tree) { + if (tree.tpe ne null) + tree.tpe = typeMap(tree.tpe) + if (tree.isDef) + tree.symbol modifyInfo typeMap + + super.traverse(tree) + } + override def apply[T <: Tree](tree: T): T = super.apply(tree.duplicate) + } + + class TreeTypeSubstituter(val from: List[Symbol], val to: List[Type]) extends TypeMapTreeSubstituter(new SubstTypeMap(from, to)) { + def isEmpty = from.isEmpty && to.isEmpty + override def toString() = "TreeTypeSubstituter("+from+","+to+")" + } + + lazy val EmptyTreeTypeSubstituter = new TreeTypeSubstituter(List(), List()) + + class TreeSymSubstTraverser(val from: List[Symbol], val to: List[Symbol]) extends TypeMapTreeSubstituter(new SubstSymMap(from, to)) { + override def toString() = "TreeSymSubstTraverser/" + substituterString("Symbol", "Symbol", from, to) + } + + /** Substitute symbols in `from` with symbols in `to`. Returns a new + * tree using the new symbols and whose Ident and Select nodes are + * name-consistent with the new symbols. + */ + class TreeSymSubstituter(from: List[Symbol], to: List[Symbol]) extends Transformer { + val symSubst = new SubstSymMap(from, to) + override def transform(tree: Tree): Tree = { + def subst(from: List[Symbol], to: List[Symbol]) { + if (!from.isEmpty) + if (tree.symbol == from.head) tree setSymbol to.head + else subst(from.tail, to.tail) + } + + if (tree.tpe ne null) tree.tpe = symSubst(tree.tpe) + if (tree.hasSymbol) { + subst(from, to) + tree match { + case Ident(name0) if tree.symbol != NoSymbol => + treeCopy.Ident(tree, tree.symbol.name) + case Select(qual, name0) if tree.symbol != NoSymbol => + treeCopy.Select(tree, transform(qual), tree.symbol.name) + case _ => + super.transform(tree) + } + } else + super.transform(tree) } + def apply[T <: Tree](tree: T): T = transform(tree).asInstanceOf[T] + override def toString() = "TreeSymSubstituter/" + substituterString("Symbol", "Symbol", from, to) } - protected def xtransform(transformer: Transformer, tree: Tree): Tree = throw new MatchError(tree) class ForeachTreeTraverser(f: Tree => Unit) extends Traverser { override def traverse(t: Tree) { @@ -1612,119 +1430,166 @@ trait Trees { self: Universe => } } - protected def duplicateTree(tree: Tree): Tree - -/* A standard pattern match - case EmptyTree => - case PackageDef(pid, stats) => - // package pid { stats } - case ClassDef(mods, name, tparams, impl) => - // mods class name [tparams] impl where impl = extends parents { defs } - case ModuleDef(mods, name, impl) => (eliminated by refcheck) - // mods object name impl where impl = extends parents { defs } - case ValDef(mods, name, tpt, rhs) => - // mods val name: tpt = rhs - // note missing type information is expressed by tpt = TypeTree() - case DefDef(mods, name, tparams, vparamss, tpt, rhs) => - // mods def name[tparams](vparams_1)...(vparams_n): tpt = rhs - // note missing type information is expressed by tpt = TypeTree() - case TypeDef(mods, name, tparams, rhs) => (eliminated by erasure) - // mods type name[tparams] = rhs - // mods type name[tparams] >: lo <: hi, where lo, hi are in a TypeBoundsTree, - and DEFERRED is set in mods - case LabelDef(name, params, rhs) => - // used for tailcalls and like - // while/do are desugared to label defs as follows: - // while (cond) body ==> LabelDef($L, List(), if (cond) { body; L$() } else ()) - // do body while (cond) ==> LabelDef($L, List(), body; if (cond) L$() else ()) - case Import(expr, selectors) => (eliminated by typecheck) - // import expr.{selectors} - // Selectors are a list of pairs of names (from, to). - // The last (and maybe only name) may be a nme.WILDCARD - // for instance - // import qual.{x, y => z, _} would be represented as - // Import(qual, List(("x", "x"), ("y", "z"), (WILDCARD, null))) - case Template(parents, self, body) => - // extends parents { self => body } - // if self is missing it is represented as emptyValDef - case Block(stats, expr) => - // { stats; expr } - case CaseDef(pat, guard, body) => (eliminated by transmatch/explicitouter) - // case pat if guard => body - case Alternative(trees) => (eliminated by transmatch/explicitouter) - // pat1 | ... | patn - case Star(elem) => (eliminated by transmatch/explicitouter) - // pat* - case Bind(name, body) => (eliminated by transmatch/explicitouter) - // name @ pat - case UnApply(fun: Tree, args) (introduced by typer, eliminated by transmatch/explicitouter) - // used for unapply's - case ArrayValue(elemtpt, trees) => (introduced by uncurry) - // used to pass arguments to vararg arguments - // for instance, printf("%s%d", foo, 42) is translated to after uncurry to: - // Apply( - // Ident("printf"), - // Literal("%s%d"), - // ArrayValue(<Any>, List(Ident("foo"), Literal(42)))) - case Function(vparams, body) => (eliminated by lambdaLift) - // vparams => body where vparams:List[ValDef] - case Assign(lhs, rhs) => - // lhs = rhs - case AssignOrNamedArg(lhs, rhs) => (eliminated by typer, resurrected by reifier) - // @annotation(lhs = rhs) - case If(cond, thenp, elsep) => - // if (cond) thenp else elsep - case Match(selector, cases) => - // selector match { cases } - case Return(expr) => - // return expr - case Try(block, catches, finalizer) => - // try block catch { catches } finally finalizer where catches: List[CaseDef] - case Throw(expr) => - // throw expr - case New(tpt) => - // new tpt always in the context: (new tpt).<init>[targs](args) - case Typed(expr, tpt) => (eliminated by erasure) - // expr: tpt - case TypeApply(fun, args) => - // fun[args] - case Apply(fun, args) => - // fun(args) - // for instance fun[targs](args) is expressed as Apply(TypeApply(fun, targs), args) - case ApplyDynamic(qual, args) (introduced by erasure, eliminated by cleanup) - // fun(args) - case Super(qual, mix) => - // qual.super[mix] qual is always This(something), if mix is empty, it is tpnme.EMPTY - case This(qual) => - // qual.this - case Select(qualifier, selector) => - // qualifier.selector - case Ident(name) => - // name - // note: type checker converts idents that refer to enclosing fields or methods - // to selects; name ==> this.name - case ReferenceToBoxed(ident) => (created by typer, eliminated by lambdalift) - // synthetic node emitted by macros to reference capture vars directly without going through ``elem'' - // var x = ...; fun { x } will emit Ident(x), which gets transformed to Select(Ident(x), "elem") - // if ReferenceToBoxed were used instead of Ident, no transformation would be performed - case Literal(value) => - // value - case TypeTree() => (introduced by refcheck) - // a type that's not written out, but given in the tpe attribute - case Annotated(annot, arg) => (eliminated by typer) - // arg @annot for types, arg: @annot for exprs - case SingletonTypeTree(ref) => (eliminated by uncurry) - // ref.type - case SelectFromTypeTree(qualifier, selector) => (eliminated by uncurry) - // qualifier # selector, a path-dependent type p.T is expressed as p.type # T - case CompoundTypeTree(templ: Template) => (eliminated by uncurry) - // parent1 with ... with parentN { refinement } - case AppliedTypeTree(tpt, args) => (eliminated by uncurry) - // tpt[args] - case TypeBoundsTree(lo, hi) => (eliminated by uncurry) - // >: lo <: hi - case ExistentialTypeTree(tpt, whereClauses) => (eliminated by uncurry) - // tpt forSome { whereClauses } -*/ -} + private lazy val duplicator = new Transformer { + override val treeCopy = newStrictTreeCopier + override def transform(t: Tree) = { + val t1 = super.transform(t) + if ((t1 ne t) && t1.pos.isRange) t1 setPos t.pos.focus + t1 + } + } + + // ------ copiers ------------------------------------------- + + def copyDefDef(tree: Tree)( + mods: Modifiers = null, + name: Name = null, + tparams: List[TypeDef] = null, + vparamss: List[List[ValDef]] = null, + tpt: Tree = null, + rhs: Tree = null + ): DefDef = tree match { + case DefDef(mods0, name0, tparams0, vparamss0, tpt0, rhs0) => + treeCopy.DefDef(tree, + if (mods eq null) mods0 else mods, + if (name eq null) name0 else name, + if (tparams eq null) tparams0 else tparams, + if (vparamss eq null) vparamss0 else vparamss, + if (tpt eq null) tpt0 else tpt, + if (rhs eq null) rhs0 else rhs + ) + case t => + sys.error("Not a DefDef: " + t + "/" + t.getClass) + } + def copyValDef(tree: Tree)( + mods: Modifiers = null, + name: Name = null, + tpt: Tree = null, + rhs: Tree = null + ): ValDef = tree match { + case ValDef(mods0, name0, tpt0, rhs0) => + treeCopy.ValDef(tree, + if (mods eq null) mods0 else mods, + if (name eq null) name0 else name, + if (tpt eq null) tpt0 else tpt, + if (rhs eq null) rhs0 else rhs + ) + case t => + sys.error("Not a ValDef: " + t + "/" + t.getClass) + } + def copyClassDef(tree: Tree)( + mods: Modifiers = null, + name: Name = null, + tparams: List[TypeDef] = null, + impl: Template = null + ): ClassDef = tree match { + case ClassDef(mods0, name0, tparams0, impl0) => + treeCopy.ClassDef(tree, + if (mods eq null) mods0 else mods, + if (name eq null) name0 else name, + if (tparams eq null) tparams0 else tparams, + if (impl eq null) impl0 else impl + ) + case t => + sys.error("Not a ClassDef: " + t + "/" + t.getClass) + } + def deriveDefDef(ddef: Tree)(applyToRhs: Tree => Tree): DefDef = ddef match { + case DefDef(mods0, name0, tparams0, vparamss0, tpt0, rhs0) => + treeCopy.DefDef(ddef, mods0, name0, tparams0, vparamss0, tpt0, applyToRhs(rhs0)) + case t => + sys.error("Not a DefDef: " + t + "/" + t.getClass) + } + def deriveValDef(vdef: Tree)(applyToRhs: Tree => Tree): ValDef = vdef match { + case ValDef(mods0, name0, tpt0, rhs0) => + treeCopy.ValDef(vdef, mods0, name0, tpt0, applyToRhs(rhs0)) + case t => + sys.error("Not a ValDef: " + t + "/" + t.getClass) + } + def deriveTemplate(templ: Tree)(applyToBody: List[Tree] => List[Tree]): Template = templ match { + case Template(parents0, self0, body0) => + treeCopy.Template(templ, parents0, self0, applyToBody(body0)) + case t => + sys.error("Not a Template: " + t + "/" + t.getClass) + } + def deriveClassDef(cdef: Tree)(applyToImpl: Template => Template): ClassDef = cdef match { + case ClassDef(mods0, name0, tparams0, impl0) => + treeCopy.ClassDef(cdef, mods0, name0, tparams0, applyToImpl(impl0)) + case t => + sys.error("Not a ClassDef: " + t + "/" + t.getClass) + } + def deriveModuleDef(mdef: Tree)(applyToImpl: Template => Template): ModuleDef = mdef match { + case ModuleDef(mods0, name0, impl0) => + treeCopy.ModuleDef(mdef, mods0, name0, applyToImpl(impl0)) + case t => + sys.error("Not a ModuleDef: " + t + "/" + t.getClass) + } + def deriveCaseDef(cdef: Tree)(applyToBody: Tree => Tree): CaseDef = cdef match { + case CaseDef(pat0, guard0, body0) => + treeCopy.CaseDef(cdef, pat0, guard0, applyToBody(body0)) + case t => + sys.error("Not a CaseDef: " + t + "/" + t.getClass) + } + def deriveLabelDef(ldef: Tree)(applyToRhs: Tree => Tree): LabelDef = ldef match { + case LabelDef(name0, params0, rhs0) => + treeCopy.LabelDef(ldef, name0, params0, applyToRhs(rhs0)) + case t => + sys.error("Not a LabelDef: " + t + "/" + t.getClass) + } + + implicit val TreeTag = ClassTag[Tree](classOf[Tree]) + implicit val TermTreeTag = ClassTag[TermTree](classOf[TermTree]) + implicit val TypTreeTag = ClassTag[TypTree](classOf[TypTree]) + implicit val SymTreeTag = ClassTag[SymTree](classOf[SymTree]) + implicit val NameTreeTag = ClassTag[NameTree](classOf[NameTree]) + implicit val RefTreeTag = ClassTag[RefTree](classOf[RefTree]) + implicit val DefTreeTag = ClassTag[DefTree](classOf[DefTree]) + implicit val MemberDefTag = ClassTag[MemberDef](classOf[MemberDef]) + implicit val PackageDefTag = ClassTag[PackageDef](classOf[PackageDef]) + implicit val ImplDefTag = ClassTag[ImplDef](classOf[ImplDef]) + implicit val ClassDefTag = ClassTag[ClassDef](classOf[ClassDef]) + implicit val ModuleDefTag = ClassTag[ModuleDef](classOf[ModuleDef]) + implicit val ValOrDefDefTag = ClassTag[ValOrDefDef](classOf[ValOrDefDef]) + implicit val ValDefTag = ClassTag[ValDef](classOf[ValDef]) + implicit val DefDefTag = ClassTag[DefDef](classOf[DefDef]) + implicit val TypeDefTag = ClassTag[TypeDef](classOf[TypeDef]) + implicit val LabelDefTag = ClassTag[LabelDef](classOf[LabelDef]) + implicit val ImportSelectorTag = ClassTag[ImportSelector](classOf[ImportSelector]) + implicit val ImportTag = ClassTag[Import](classOf[Import]) + implicit val TemplateTag = ClassTag[Template](classOf[Template]) + implicit val BlockTag = ClassTag[Block](classOf[Block]) + implicit val CaseDefTag = ClassTag[CaseDef](classOf[CaseDef]) + implicit val AlternativeTag = ClassTag[Alternative](classOf[Alternative]) + implicit val StarTag = ClassTag[Star](classOf[Star]) + implicit val BindTag = ClassTag[Bind](classOf[Bind]) + implicit val UnApplyTag = ClassTag[UnApply](classOf[UnApply]) + implicit val ArrayValueTag = ClassTag[ArrayValue](classOf[ArrayValue]) + implicit val FunctionTag = ClassTag[Function](classOf[Function]) + implicit val AssignTag = ClassTag[Assign](classOf[Assign]) + implicit val AssignOrNamedArgTag = ClassTag[AssignOrNamedArg](classOf[AssignOrNamedArg]) + implicit val IfTag = ClassTag[If](classOf[If]) + implicit val MatchTag = ClassTag[Match](classOf[Match]) + implicit val ReturnTag = ClassTag[Return](classOf[Return]) + implicit val TryTag = ClassTag[Try](classOf[Try]) + implicit val ThrowTag = ClassTag[Throw](classOf[Throw]) + implicit val NewTag = ClassTag[New](classOf[New]) + implicit val TypedTag = ClassTag[Typed](classOf[Typed]) + implicit val GenericApplyTag = ClassTag[GenericApply](classOf[GenericApply]) + implicit val TypeApplyTag = ClassTag[TypeApply](classOf[TypeApply]) + implicit val ApplyTag = ClassTag[Apply](classOf[Apply]) + implicit val ApplyDynamicTag = ClassTag[ApplyDynamic](classOf[ApplyDynamic]) + implicit val SuperTag = ClassTag[Super](classOf[Super]) + implicit val ThisTag = ClassTag[This](classOf[This]) + implicit val SelectTag = ClassTag[Select](classOf[Select]) + implicit val IdentTag = ClassTag[Ident](classOf[Ident]) + implicit val ReferenceToBoxedTag = ClassTag[ReferenceToBoxed](classOf[ReferenceToBoxed]) + implicit val LiteralTag = ClassTag[Literal](classOf[Literal]) + implicit val AnnotatedTag = ClassTag[Annotated](classOf[Annotated]) + implicit val SingletonTypeTreeTag = ClassTag[SingletonTypeTree](classOf[SingletonTypeTree]) + implicit val SelectFromTypeTreeTag = ClassTag[SelectFromTypeTree](classOf[SelectFromTypeTree]) + implicit val CompoundTypeTreeTag = ClassTag[CompoundTypeTree](classOf[CompoundTypeTree]) + implicit val AppliedTypeTreeTag = ClassTag[AppliedTypeTree](classOf[AppliedTypeTree]) + implicit val TypeBoundsTreeTag = ClassTag[TypeBoundsTree](classOf[TypeBoundsTree]) + implicit val ExistentialTypeTreeTag = ClassTag[ExistentialTypeTree](classOf[ExistentialTypeTree]) + implicit val TypeTreeTag = ClassTag[TypeTree](classOf[TypeTree]) +} diff --git a/src/compiler/scala/reflect/internal/TypeDebugging.scala b/src/reflect/scala/reflect/internal/TypeDebugging.scala index 85a1767067..33f6a645e8 100644 --- a/src/compiler/scala/reflect/internal/TypeDebugging.scala +++ b/src/reflect/scala/reflect/internal/TypeDebugging.scala @@ -24,7 +24,7 @@ trait TypeDebugging { def ptBlock(label: String, pairs: (String, Any)*): String = { if (pairs.isEmpty) label + "{ }" else { - val width = pairs map (_._1.length) max + val width = (pairs map (_._1.length)).max val fmt = "%-" + (width + 1) + "s %s" val strs = pairs map { case (k, v) => fmt.format(k, to_s(v)) } diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index a839e44182..8a4394bf1d 100644 --- a/src/compiler/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -14,6 +14,7 @@ import Flags._ import scala.util.control.ControlThrowable import scala.annotation.tailrec import util.Statistics._ +import language.postfixOps /* A standard type pattern match: case ErrorType => @@ -260,7 +261,7 @@ trait Types extends api.Types { self: SymbolTable => } } - abstract class AbsTypeImpl extends AbsType { this: Type => + abstract class TypeApiImpl extends TypeApi { this: Type => def declaration(name: Name): Symbol = decl(name) def nonPrivateDeclaration(name: Name): Symbol = nonPrivateDecl(name) def declarations = decls @@ -268,7 +269,7 @@ trait Types extends api.Types { self: SymbolTable => def erasure = this match { case ConstantType(value) => widen.erasure // [Eugene to Martin] constant types are unaffected by erasure. weird. case _ => - var result = transformedType(this) + var result: Type = transformedType(this) result = result.normalize match { // necessary to deal with erasures of HK types, typeConstructor won't work case PolyType(undets, underlying) => existentialAbstraction(undets, underlying) // we don't want undets in the result case _ => result @@ -282,6 +283,7 @@ trait Types extends api.Types { self: SymbolTable => }) result } + def substituteSymbols(from: List[Symbol], to: List[Symbol]): Type = substSym(from, to) def substituteTypes(from: List[Symbol], to: List[Type]): Type = subst(from, to) // [Eugene] to be discussed and refactored @@ -315,7 +317,7 @@ trait Types extends api.Types { self: SymbolTable => } /** The base class for all types */ - abstract class Type extends AbsTypeImpl with Annotatable[Type] { + abstract class Type extends TypeApiImpl with Annotatable[Type] { /** Types for which asSeenFrom always is the identity, no matter what * prefix or owner. */ @@ -898,8 +900,8 @@ trait Types extends api.Types { self: SymbolTable => */ def baseTypeSeq: BaseTypeSeq = baseTypeSingletonSeq(this) - /** The maximum depth (@see maxDepth) - * of each type in the BaseTypeSeq of this type. + /** The maximum depth (@see typeDepth) + * of each type in the BaseTypeSeq of this type except the first. */ def baseTypeSeqDepth: Int = 1 @@ -1243,7 +1245,7 @@ trait Types extends api.Types { self: SymbolTable => * type is created: a MethodType with parameters typed as * BoundedWildcardTypes. */ - case class BoundedWildcardType(override val bounds: TypeBounds) extends Type { + case class BoundedWildcardType(override val bounds: TypeBounds) extends Type with BoundedWildcardTypeApi { override def isWildcard = true override def safeToString: String = "?" + bounds override def kind = "BoundedWildcardType" @@ -1271,7 +1273,7 @@ trait Types extends api.Types { self: SymbolTable => /** A class for this-types of the form <sym>.this.type */ - abstract case class ThisType(sym: Symbol) extends SingletonType { + abstract case class ThisType(sym: Symbol) extends SingletonType with ThisTypeApi { assert(sym.isClass) //assert(sym.isClass && !sym.isModuleClass || sym.isRoot, sym) override def isTrivial: Boolean = sym.isPackageClass @@ -1306,7 +1308,7 @@ trait Types extends api.Types { self: SymbolTable => /** A class for singleton types of the form `<prefix>.<sym.name>.type`. * Cannot be created directly; one should always use `singleType` for creation. */ - abstract case class SingleType(pre: Type, sym: Symbol) extends SingletonType { + abstract case class SingleType(pre: Type, sym: Symbol) extends SingletonType with SingleTypeApi { override val isTrivial: Boolean = pre.isTrivial override def isGround = sym.isPackageClass || pre.isGround @@ -1366,13 +1368,13 @@ trait Types extends api.Types { self: SymbolTable => tpe.underlyingPeriod = currentPeriod if (!isValid(period)) { // [Eugene to Paul] needs review - tpe.underlyingCache = if (tpe.sym == NoSymbol) ThisType(RootClass) else tpe.pre.memberType(tpe.sym).resultType; + tpe.underlyingCache = if (tpe.sym == NoSymbol) ThisType(rootMirror.RootClass) else tpe.pre.memberType(tpe.sym).resultType; assert(tpe.underlyingCache ne tpe, tpe) } } } - abstract case class SuperType(thistpe: Type, supertpe: Type) extends SingletonType { + abstract case class SuperType(thistpe: Type, supertpe: Type) extends SingletonType with SuperTypeApi { override val isTrivial: Boolean = thistpe.isTrivial && supertpe.isTrivial override def isNotNull = true; override def typeSymbol = thistpe.typeSymbol @@ -1394,7 +1396,7 @@ trait Types extends api.Types { self: SymbolTable => /** A class for the bounds of abstract types and type parameters */ - abstract case class TypeBounds(lo: Type, hi: Type) extends SubType { + abstract case class TypeBounds(lo: Type, hi: Type) extends SubType with TypeBoundsApi { def supertype = hi override val isTrivial: Boolean = lo.isTrivial && hi.isTrivial override def bounds: TypeBounds = this @@ -1600,7 +1602,7 @@ trait Types extends api.Types { self: SymbolTable => * one should always use `refinedType` for creation. */ case class RefinedType(override val parents: List[Type], - override val decls: Scope) extends CompoundType { + override val decls: Scope) extends CompoundType with RefinedTypeApi { override def isHigherKinded = ( parents.nonEmpty && @@ -1695,7 +1697,7 @@ trait Types extends api.Types { self: SymbolTable => case class ClassInfoType( override val parents: List[Type], override val decls: Scope, - override val typeSymbol: Symbol) extends CompoundType + override val typeSymbol: Symbol) extends CompoundType with ClassInfoTypeApi { validateClassInfo(this) @@ -1874,7 +1876,7 @@ trait Types extends api.Types { self: SymbolTable => * * @param value ... */ - abstract case class ConstantType(value: Constant) extends SingletonType { + abstract case class ConstantType(value: Constant) extends SingletonType with ConstantTypeApi { override def underlying: Type = value.tpe assert(underlying.typeSymbol != UnitClass) override def isTrivial: Boolean = true @@ -2183,7 +2185,7 @@ trait Types extends api.Types { self: SymbolTable => * * @M: a higher-kinded type is represented as a TypeRef with sym.typeParams.nonEmpty, but args.isEmpty */ - abstract case class TypeRef(pre: Type, sym: Symbol, args: List[Type]) extends Type { + abstract case class TypeRef(pre: Type, sym: Symbol, args: List[Type]) extends Type with TypeRefApi { private[reflect] var parentsCache: List[Type] = _ private[reflect] var parentsPeriod = NoPeriod private[reflect] var baseTypeSeqCache: BaseTypeSeq = _ @@ -2406,7 +2408,7 @@ trait Types extends api.Types { self: SymbolTable => * def m: Int NullaryMethodType(Int) */ case class MethodType(override val params: List[Symbol], - override val resultType: Type) extends Type { + override val resultType: Type) extends Type with MethodTypeApi { override def isTrivial: Boolean = isTrivial0 && (resultType eq resultType.withoutAnnotations) private lazy val isTrivial0 = resultType.isTrivial && params.forall{p => p.tpe.isTrivial && ( @@ -2462,7 +2464,7 @@ trait Types extends api.Types { self: SymbolTable => override def isJava = true } - case class NullaryMethodType(override val resultType: Type) extends Type { + case class NullaryMethodType(override val resultType: Type) extends Type with NullaryMethodTypeApi { override def isTrivial = resultType.isTrivial && (resultType eq resultType.withoutAnnotations) override def prefix: Type = resultType.prefix override def narrow: Type = resultType.narrow @@ -2496,7 +2498,7 @@ trait Types extends api.Types { self: SymbolTable => * A polytype is of kind * iff its resultType is a (nullary) method type. */ case class PolyType(override val typeParams: List[Symbol], override val resultType: Type) - extends Type { + extends Type with PolyTypeApi { //assert(!(typeParams contains NoSymbol), this) assert(typeParams nonEmpty, this) // used to be a marker for nullary method type, illegal now (see @NullaryMethodType) @@ -2556,7 +2558,7 @@ trait Types extends api.Types { self: SymbolTable => } case class ExistentialType(quantified: List[Symbol], - override val underlying: Type) extends RewrappingTypeProxy + override val underlying: Type) extends RewrappingTypeProxy with ExistentialTypeApi { override protected def rewrap(newtp: Type) = existentialAbstraction(quantified, newtp) @@ -3025,7 +3027,7 @@ trait Types extends api.Types { self: SymbolTable => // this is a higher-kinded type var with same arity as tp. // side effect: adds the type constructor itself as a bound addBound(tp.typeConstructor) - isSubArgs(lhs, rhs, params) + isSubArgs(lhs, rhs, params, AnyDepth) } } } @@ -3177,7 +3179,7 @@ trait Types extends api.Types { self: SymbolTable => case class AnnotatedType(override val annotations: List[AnnotationInfo], override val underlying: Type, override val selfsym: Symbol) - extends RewrappingTypeProxy { + extends RewrappingTypeProxy with AnnotatedTypeApi { assert(!annotations.isEmpty, "" + underlying) @@ -3250,7 +3252,7 @@ trait Types extends api.Types { self: SymbolTable => if (annots.isEmpty) underlying else AnnotatedType(annots, underlying, selfsym) - object AnnotatedType extends AnnotatedTypeExtractor { } + object AnnotatedType extends AnnotatedTypeExtractor /** A class representing types with a name. When an application uses * named arguments, the named argument types for calling isApplicable @@ -3331,7 +3333,7 @@ trait Types extends api.Types { self: SymbolTable => if (phase.erasedTypes) sym.tpe.resultType else if (sym.isRootPackage) - ThisType(RootClass) + ThisType(sym.moduleClass) else { var sym1 = rebind(pre, sym) val pre1 = removeSuper(pre, sym1) @@ -4947,18 +4949,54 @@ trait Types extends api.Types { self: SymbolTable => // Helper Methods ------------------------------------------------------------- - final val LubGlbMargin = 0 - /** The maximum allowable depth of lubs or glbs over types `ts`. - * This is the maximum depth of all types in the base type sequences - * of each of the types `ts`, plus LubGlbMargin. */ - def lubDepth(ts: List[Type]) = { + def lubDepth(ts: List[Type]): Int = { + val td = typeDepth(ts) + val bd = baseTypeSeqDepth(ts) + lubDepthAdjust(td, td max bd) + } + + /** The maximum allowable depth of lubs or glbs over given types, + * as a function over the maximum depth `td` of these types, and + * the maximum depth `bd` of all types in the base type sequences of these types. + */ + private def lubDepthAdjust(td: Int, bd: Int): Int = + if (settings.XfullLubs.value) bd + else if (bd <= 3) bd + else if (bd <= 5) td max (bd - 1) + else if (bd <= 7) td max (bd - 2) + else (td - 1) max (bd - 3) + + /** The maximum depth of type `tp` */ + def typeDepth(tp: Type): Int = tp match { + case TypeRef(pre, sym, args) => + typeDepth(pre) max typeDepth(args) + 1 + case RefinedType(parents, decls) => + typeDepth(parents) max typeDepth(decls.toList.map(_.info)) + 1 + case TypeBounds(lo, hi) => + typeDepth(lo) max typeDepth(hi) + case MethodType(paramtypes, result) => + typeDepth(result) + case NullaryMethodType(result) => + typeDepth(result) + case PolyType(tparams, result) => + typeDepth(result) max typeDepth(tparams map (_.info)) + 1 + case ExistentialType(tparams, result) => + typeDepth(result) max typeDepth(tparams map (_.info)) + 1 + case _ => + 1 + } + + private def maxDepth(tps: Seq[Type], by: Type => Int): Int = { var d = 0 - for (tp <- ts) d = math.max(d, tp.baseTypeSeqDepth) - d + LubGlbMargin + for (tp <- tps) d = d max by(tp) + d } + private def typeDepth(tps: Seq[Type]): Int = maxDepth(tps, typeDepth) + private def baseTypeSeqDepth(tps: Seq[Type]): Int = maxDepth(tps, _.baseTypeSeqDepth) + /** Is intersection of given types populated? That is, * for all types tp1, tp2 in intersection * for all common base classes bc of tp1 and tp2 @@ -5053,6 +5091,13 @@ trait Types extends api.Types { self: SymbolTable => pre1 =:= pre2 } + private def isSubPre(pre1: Type, pre2: Type, sym: Symbol) = + if ((pre1 ne pre2) && (pre1 ne NoPrefix) && (pre2 ne NoPrefix) && pre1 <:< pre2) { + if (settings.debug.value) println(s"new isSubPre $sym: $pre1 <:< $pre2") + true + } else + false + private def equalSymsAndPrefixes(sym1: Symbol, pre1: Type, sym2: Symbol, pre2: Type): Boolean = if (sym1 == sym2) sym1.hasPackageFlag || phase.erasedTypes || pre1 =:= pre2 else (sym1.name == sym2.name) && isUnifiable(pre1, pre2) @@ -5215,9 +5260,9 @@ trait Types extends api.Types { self: SymbolTable => true else if ((tp1 eq NoType) || (tp2 eq NoType)) false - else if (tp1 eq NoPrefix) + else if (tp1 eq NoPrefix) // !! I do not see how this would be warranted by the spec tp2.typeSymbol.isPackageClass - else if (tp2 eq NoPrefix) + else if (tp2 eq NoPrefix) // !! I do not see how this would be warranted by the spec tp1.typeSymbol.isPackageClass else { isSameType2(tp1, tp2) || { @@ -5509,11 +5554,12 @@ trait Types extends api.Types { self: SymbolTable => // --> thus, cannot be subtypes (Any/Nothing has already been checked) })) - def isSubArg(t1: Type, t2: Type, variance: Int) = - (variance > 0 || t2 <:< t1) && (variance < 0 || t1 <:< t2) - - def isSubArgs(tps1: List[Type], tps2: List[Type], tparams: List[Symbol]): Boolean = + def isSubArgs(tps1: List[Type], tps2: List[Type], tparams: List[Symbol], depth: Int): Boolean = { + def isSubArg(t1: Type, t2: Type, variance: Int) = + (variance > 0 || isSubType(t2, t1, depth)) && + (variance < 0 || isSubType(t1, t2, depth)) corresponds3(tps1, tps2, tparams map (_.variance))(isSubArg) + } def differentOrNone(tp1: Type, tp2: Type) = if (tp1 eq tp2) NoType else tp1 @@ -5521,7 +5567,7 @@ trait Types extends api.Types { self: SymbolTable => private def isSubType2(tp1: Type, tp2: Type, depth: Int): Boolean = { if ((tp1 eq tp2) || isErrorOrWildcard(tp1) || isErrorOrWildcard(tp2)) return true if ((tp1 eq NoType) || (tp2 eq NoType)) return false - if (tp1 eq NoPrefix) return (tp2 eq NoPrefix) || tp2.typeSymbol.isPackageClass + if (tp1 eq NoPrefix) return (tp2 eq NoPrefix) || tp2.typeSymbol.isPackageClass // !! I do not see how the "isPackageClass" would be warranted by the spec if (tp2 eq NoPrefix) return tp1.typeSymbol.isPackageClass if (isSingleType(tp1) && isSingleType(tp2) || isConstantType(tp1) && isConstantType(tp2)) return tp1 =:= tp2 if (tp1.isHigherKinded || tp2.isHigherKinded) return isHKSubType0(tp1, tp2, depth) @@ -5540,14 +5586,16 @@ trait Types extends api.Types { self: SymbolTable => val sym2 = tr2.sym val pre1 = tr1.pre val pre2 = tr2.pre - (((if (sym1 == sym2) phase.erasedTypes || pre1 <:< pre2 + (((if (sym1 == sym2) phase.erasedTypes || isSubType(pre1, pre2, depth) else (sym1.name == sym2.name && !sym1.isModuleClass && !sym2.isModuleClass && - (isUnifiable(pre1, pre2) || isSameSpecializedSkolem(sym1, sym2, pre1, pre2)))) && - isSubArgs(tr1.args, tr2.args, sym1.typeParams)) + (isUnifiable(pre1, pre2) || + isSameSpecializedSkolem(sym1, sym2, pre1, pre2) || + sym2.isAbstractType && isSubPre(pre1, pre2, sym2)))) && + isSubArgs(tr1.args, tr2.args, sym1.typeParams, depth)) || sym2.isClass && { val base = tr1 baseType sym2 - (base ne tr1) && base <:< tr2 + (base ne tr1) && isSubType(base, tr2, depth) } || thirdTryRef(tr1, tr2)) @@ -5555,9 +5603,10 @@ trait Types extends api.Types { self: SymbolTable => secondTry } case AnnotatedType(_, _, _) => - tp1.withoutAnnotations <:< tp2.withoutAnnotations && annotationsConform(tp1, tp2) + isSubType(tp1.withoutAnnotations, tp2.withoutAnnotations, depth) && + annotationsConform(tp1, tp2) case BoundedWildcardType(bounds) => - tp1 <:< bounds.hi + isSubType(tp1, bounds.hi, depth) case tv2 @ TypeVar(_, constr2) => tp1 match { case AnnotatedType(_, _, _) | BoundedWildcardType(_) => @@ -5576,15 +5625,16 @@ trait Types extends api.Types { self: SymbolTable => */ def secondTry = tp1 match { case AnnotatedType(_, _, _) => - tp1.withoutAnnotations <:< tp2.withoutAnnotations && annotationsConform(tp1, tp2) + isSubType(tp1.withoutAnnotations, tp2.withoutAnnotations, depth) && + annotationsConform(tp1, tp2) case BoundedWildcardType(bounds) => - tp1.bounds.lo <:< tp2 + isSubType(tp1.bounds.lo, tp2, depth) case tv @ TypeVar(_,_) => tv.registerBound(tp2, false) case ExistentialType(_, _) => try { skolemizationLevel += 1 - tp1.skolemizeExistential <:< tp2 + isSubType(tp1.skolemizeExistential, tp2, depth) } finally { skolemizationLevel -= 1 } @@ -5607,7 +5657,9 @@ trait Types extends api.Types { self: SymbolTable => case _: TypeSymbol => if (sym2 hasFlag DEFERRED) { val tp2a = tp2.bounds.lo - isDifferentTypeConstructor(tp2, tp2a) && tp1 <:< tp2a || fourthTry + isDifferentTypeConstructor(tp2, tp2a) && + isSubType(tp1, tp2a, depth) || + fourthTry } else { isSubType(tp1.normalize, tp2.normalize, depth) } @@ -5625,12 +5677,12 @@ trait Types extends api.Types { self: SymbolTable => case tr2: TypeRef => thirdTryRef(tp1, tr2) case rt2: RefinedType => - (rt2.parents forall (tp1 <:< _)) && - (rt2.decls forall tp1.specializes) + (rt2.parents forall (isSubType(tp1, _, depth))) && + (rt2.decls forall (specializesSym(tp1, _, depth))) case et2: ExistentialType => - et2.withTypeVars(tp1 <:< _, depth) || fourthTry + et2.withTypeVars(isSubType(tp1, _, depth), depth) || fourthTry case nn2: NotNullType => - tp1.isNotNull && tp1 <:< nn2.underlying + tp1.isNotNull && isSubType(tp1, nn2.underlying, depth) case mt2: MethodType => tp1 match { case mt1 @ MethodType(params1, res1) => @@ -5639,7 +5691,7 @@ trait Types extends api.Types { self: SymbolTable => (sameLength(params1, params2) && mt1.isImplicit == mt2.isImplicit && matchingParams(params1, params2, mt1.isJava, mt2.isJava) && - (res1 <:< res2.substSym(params2, params1))) + isSubType(res1, res2.substSym(params2, params1), depth)) // TODO: if mt1.params.isEmpty, consider NullaryMethodType? case _ => false @@ -5648,14 +5700,14 @@ trait Types extends api.Types { self: SymbolTable => tp1 match { // TODO: consider MethodType mt for which mt.params.isEmpty?? case pt1 @ NullaryMethodType(_) => - pt1.resultType <:< pt2.resultType + isSubType(pt1.resultType, pt2.resultType, depth) case _ => false } case TypeBounds(lo2, hi2) => tp1 match { case TypeBounds(lo1, hi1) => - lo2 <:< lo1 && hi1 <:< hi2 + isSubType(lo2, lo1, depth) && isSubType(hi1, hi2, depth) case _ => false } @@ -5675,7 +5727,7 @@ trait Types extends api.Types { self: SymbolTable => case TypeRef(_, sym2, _) => containsNull(sym2) case _ => - isSingleType(tp2) && tp1 <:< tp2.widen + isSingleType(tp2) && isSubType(tp1, tp2.widen, depth) } case _: ClassSymbol => if (isRaw(sym1, tr1.args)) @@ -5691,7 +5743,7 @@ trait Types extends api.Types { self: SymbolTable => case _: TypeSymbol => if (sym1 hasFlag DEFERRED) { val tp1a = tp1.bounds.hi - isDifferentTypeConstructor(tp1, tp1a) && tp1a <:< tp2 + isDifferentTypeConstructor(tp1, tp1a) && isSubType(tp1a, tp2, depth) } else { isSubType(tp1.normalize, tp2.normalize, depth) } @@ -5699,9 +5751,9 @@ trait Types extends api.Types { self: SymbolTable => false } case RefinedType(parents1, _) => - parents1 exists (_ <:< tp2) + parents1 exists (isSubType(_, tp2, depth)) case _: SingletonType | _: NotNullType => - tp1.underlying <:< tp2 + isSubType(tp1.underlying, tp2, depth) case _ => false } @@ -5724,19 +5776,22 @@ trait Types extends api.Types { self: SymbolTable => * refinement type, otherwise we might return false negatives. */ def specializesSym(tp: Type, sym: Symbol): Boolean = + specializesSym(tp, sym, AnyDepth) + + def specializesSym(tp: Type, sym: Symbol, depth: Int): Boolean = tp.typeSymbol == NothingClass || tp.typeSymbol == NullClass && containsNull(sym.owner) || (tp.nonPrivateMember(sym.name).alternatives exists - (alt => sym == alt || specializesSym(tp.narrow, alt, sym.owner.thisType, sym))) + (alt => sym == alt || specializesSym(tp.narrow, alt, sym.owner.thisType, sym, depth))) /** Does member `sym1` of `tp1` have a stronger type * than member `sym2` of `tp2`? */ - private def specializesSym(tp1: Type, sym1: Symbol, tp2: Type, sym2: Symbol): Boolean = { + private def specializesSym(tp1: Type, sym1: Symbol, tp2: Type, sym2: Symbol, depth: Int): Boolean = { val info1 = tp1.memberInfo(sym1) val info2 = tp2.memberInfo(sym2).substThis(tp2.typeSymbol, tp1) //System.out.println("specializes "+tp1+"."+sym1+":"+info1+sym1.locationString+" AND "+tp2+"."+sym2+":"+info2)//DEBUG - ( sym2.isTerm && (info1 <:< info2) && (!sym2.isStable || sym1.isStable) + ( sym2.isTerm && isSubType(info1, info2, depth) && (!sym2.isStable || sym1.isStable) || sym2.isAbstractType && { val memberTp1 = tp1.memberType(sym1) // println("kinds conform? "+(memberTp1, tp1, sym2, kindsConform(List(sym2), List(memberTp1), tp2, sym2.owner))) @@ -5984,7 +6039,7 @@ trait Types extends api.Types { self: SymbolTable => // Lubs and Glbs --------------------------------------------------------- private def printLubMatrix(btsMap: Map[Type, List[Type]], depth: Int) { - import scala.tools.nsc.util.TableDef + import util.TableDef import TableDef.Column def str(tp: Type) = { if (tp == NoType) "" @@ -6253,11 +6308,14 @@ trait Types extends api.Types { self: SymbolTable => case List() => NothingClass.tpe case List(t) => t case _ => + incCounter(lubCount) + val start = startTimer(lubNanos) try { - lub(ts, lubDepth(ts)) + lub(ts, lubDepth(ts)) } finally { lubResults.clear() glbResults.clear() + stopTimer(lubNanos, start) } } @@ -6332,14 +6390,14 @@ trait Types extends api.Types { self: SymbolTable => !syms.isEmpty && (syms forall (alt => // todo alt != sym is strictly speaking not correct, but without it we lose // efficiency. - alt != sym && !specializesSym(lubThisType, sym, tp, alt))) + alt != sym && !specializesSym(lubThisType, sym, tp, alt, depth))) } // add a refinement symbol for all non-class members of lubBase // which are refined by every type in ts. for (sym <- lubBase.nonPrivateMembers ; if !excludeFromLub(sym)) { try { val lsym = lubsym(sym) - if (lsym != NoSymbol) addMember(lubThisType, lubRefined, lsym) + if (lsym != NoSymbol) addMember(lubThisType, lubRefined, lsym, depth) } catch { case ex: NoCommonType => } @@ -6351,7 +6409,7 @@ trait Types extends api.Types { self: SymbolTable => // In theory this should not be necessary, but higher-order type // parameters are not handled correctly. val ok = ts forall { t => - (t <:< lubRefined) || { + isSubType(t, lubRefined, depth) || { if (settings.debug.value || printLubs) { Console.println( "Malformed lub: " + lubRefined + "\n" + @@ -6373,6 +6431,7 @@ trait Types extends api.Types { self: SymbolTable => indent = indent + " " assert(indent.length <= 100) } + incCounter(nestedLubCount) val res = lub0(ts) if (printLubs) { indent = indent stripSuffix " " @@ -6397,12 +6456,15 @@ trait Types extends api.Types { self: SymbolTable => case List() => AnyClass.tpe case List(t) => t case ts0 => + incCounter(lubCount) + val start = startTimer(lubNanos) try { glbNorm(ts0, lubDepth(ts0)) } finally { lubResults.clear() glbResults.clear() - } + stopTimer(lubNanos, start) + } } private def glb(ts: List[Type], depth: Int): Type = elimSuper(ts) match { @@ -6496,9 +6558,9 @@ trait Types extends api.Types { self: SymbolTable => globalGlbDepth += 1 val dss = ts flatMap refinedToDecls for (ds <- dss; sym <- ds.iterator) - if (globalGlbDepth < globalGlbLimit && !(glbThisType specializes sym)) + if (globalGlbDepth < globalGlbLimit && !specializesSym(glbThisType, sym, depth)) try { - addMember(glbThisType, glbRefined, glbsym(sym)) + addMember(glbThisType, glbRefined, glbsym(sym), depth) } catch { case ex: NoCommonType => } @@ -6516,6 +6578,7 @@ trait Types extends api.Types { self: SymbolTable => } // if (settings.debug.value) { println(indent + "glb of " + ts + " at depth "+depth); indent = indent + " " } //DEBUG + incCounter(nestedLubCount) val res = glb0(ts) // if (settings.debug.value) { indent = indent.substring(0, indent.length() - 2); log(indent + "glb of " + ts + " is " + res) }//DEBUG @@ -6630,16 +6693,18 @@ trait Types extends api.Types { self: SymbolTable => assert(false, tps); None } + def addMember(thistp: Type, tp: Type, sym: Symbol): Unit = addMember(thistp, tp, sym, AnyDepth) + /** Make symbol `sym` a member of scope `tp.decls` * where `thistp` is the narrowed owner type of the scope. */ - def addMember(thistp: Type, tp: Type, sym: Symbol) { + def addMember(thistp: Type, tp: Type, sym: Symbol, depth: Int) { assert(sym != NoSymbol) // debuglog("add member " + sym+":"+sym.info+" to "+thistp) //DEBUG - if (!(thistp specializes sym)) { + if (!specializesSym(thistp, sym, depth)) { if (sym.isTerm) for (alt <- tp.nonPrivateDecl(sym.name).alternatives) - if (specializesSym(thistp, sym, thistp, alt)) + if (specializesSym(thistp, sym, thistp, alt, depth)) tp.decls unlink alt; tp.decls enter sym } @@ -6789,4 +6854,21 @@ trait Types extends api.Types { self: SymbolTable => tostringRecursions -= 1 } + implicit val AnnotatedTypeTag = ClassTag[AnnotatedType](classOf[AnnotatedType]) + implicit val BoundedWildcardTypeTag = ClassTag[BoundedWildcardType](classOf[BoundedWildcardType]) + implicit val ClassInfoTypeTag = ClassTag[ClassInfoType](classOf[ClassInfoType]) + implicit val CompoundTypeTag = ClassTag[CompoundType](classOf[CompoundType]) + implicit val ConstantTypeTag = ClassTag[ConstantType](classOf[ConstantType]) + implicit val ExistentialTypeTag = ClassTag[ExistentialType](classOf[ExistentialType]) + implicit val MethodTypeTag = ClassTag[MethodType](classOf[MethodType]) + implicit val NullaryMethodTypeTag = ClassTag[NullaryMethodType](classOf[NullaryMethodType]) + implicit val PolyTypeTag = ClassTag[PolyType](classOf[PolyType]) + implicit val RefinedTypeTag = ClassTag[RefinedType](classOf[RefinedType]) + implicit val SingletonTypeTag = ClassTag[SingletonType](classOf[SingletonType]) + implicit val SingleTypeTag = ClassTag[SingleType](classOf[SingleType]) + implicit val SuperTypeTag = ClassTag[SuperType](classOf[SuperType]) + implicit val ThisTypeTag = ClassTag[ThisType](classOf[ThisType]) + implicit val TypeBoundsTag = ClassTag[TypeBounds](classOf[TypeBounds]) + implicit val TypeRefTag = ClassTag[TypeRef](classOf[TypeRef]) + implicit val TypeTagg = ClassTag[Type](classOf[Type]) } diff --git a/src/reflect/scala/reflect/internal/package.scala b/src/reflect/scala/reflect/internal/package.scala new file mode 100644 index 0000000000..99b837152d --- /dev/null +++ b/src/reflect/scala/reflect/internal/package.scala @@ -0,0 +1,6 @@ +package scala.reflect + +package object internal { + + type MirrorOf[U <: base.Universe with Singleton] = base.MirrorOf[U] +} diff --git a/src/compiler/scala/reflect/internal/pickling/ByteCodecs.scala b/src/reflect/scala/reflect/internal/pickling/ByteCodecs.scala index 4670bd4eef..4670bd4eef 100644 --- a/src/compiler/scala/reflect/internal/pickling/ByteCodecs.scala +++ b/src/reflect/scala/reflect/internal/pickling/ByteCodecs.scala diff --git a/src/compiler/scala/reflect/internal/pickling/PickleBuffer.scala b/src/reflect/scala/reflect/internal/pickling/PickleBuffer.scala index 7f0895ce64..7f0895ce64 100644 --- a/src/compiler/scala/reflect/internal/pickling/PickleBuffer.scala +++ b/src/reflect/scala/reflect/internal/pickling/PickleBuffer.scala diff --git a/src/compiler/scala/reflect/internal/pickling/PickleFormat.scala b/src/reflect/scala/reflect/internal/pickling/PickleFormat.scala index 16747af08a..16747af08a 100644 --- a/src/compiler/scala/reflect/internal/pickling/PickleFormat.scala +++ b/src/reflect/scala/reflect/internal/pickling/PickleFormat.scala diff --git a/src/compiler/scala/reflect/internal/pickling/UnPickler.scala b/src/reflect/scala/reflect/internal/pickling/UnPickler.scala index fd3fac1b37..757163a074 100644 --- a/src/compiler/scala/reflect/internal/pickling/UnPickler.scala +++ b/src/reflect/scala/reflect/internal/pickling/UnPickler.scala @@ -53,6 +53,8 @@ abstract class UnPickler /*extends reflect.generic.UnPickler*/ { checkVersion() + private val loadingMirror = mirrorThatLoaded(classRoot) + /** A map from entry numbers to array offsets */ private val index = createIndex @@ -195,13 +197,13 @@ abstract class UnPickler /*extends reflect.generic.UnPickler*/ { def readExtSymbol(): Symbol = { val name = readNameRef() - val owner = if (atEnd) definitions.RootClass else readSymbolRef() + val owner = if (atEnd) loadingMirror.RootClass else readSymbolRef() def adjust(sym: Symbol) = if (tag == EXTref) sym else sym.moduleClass def fromName(name: Name) = name.toTermName match { - case nme.ROOT => definitions.RootClass - case nme.ROOTPKG => definitions.RootPackage + case nme.ROOT => loadingMirror.RootClass + case nme.ROOTPKG => loadingMirror.RootPackage case _ => adjust(owner.info.decl(name)) } def nestedObjectSymbol: Symbol = { @@ -356,7 +358,7 @@ abstract class UnPickler /*extends reflect.generic.UnPickler*/ { case POLYtpe => val restpe = readTypeRef() val typeParams = until(end, readSymbolRef) - if(typeParams nonEmpty) { + if (typeParams.nonEmpty) { // NMT_TRANSITION: old class files denoted a polymorphic nullary method as PolyType(tps, restpe), we now require PolyType(tps, NullaryMethodType(restpe)) // when a type of kind * is expected (forceProperType is true), we know restpe should be wrapped in a NullaryMethodType (if it wasn't suitably wrapped yet) def transitionNMT(restpe: Type) = { @@ -447,7 +449,7 @@ abstract class UnPickler /*extends reflect.generic.UnPickler*/ { private def readArrayAnnot() = { readByte() // skip the `annotargarray` tag val end = readNat() + readIndex - until(end, () => readClassfileAnnotArg(readNat())).toArray(classfileAnnotArgTag) + until(end, () => readClassfileAnnotArg(readNat())).toArray(ClassfileAnnotArgTag) } protected def readClassfileAnnotArg(i: Int): ClassfileAnnotArg = bytes(index(i)) match { case ANNOTINFO => NestedAnnotArg(at(i, readAnnotation)) @@ -816,9 +818,8 @@ abstract class UnPickler /*extends reflect.generic.UnPickler*/ { throw new RuntimeException("malformed Scala signature of " + classRoot.name + " at " + readIndex + "; " + msg) protected def errorMissingRequirement(name: Name, owner: Symbol): Symbol = - missingHook(owner, name) orElse MissingRequirementError.notFound( - "bad reference while unpickling %s: %s not found in %s".format( - filename, name.longString, owner.tpe.widen) + missingHook(owner, name) orElse MissingRequirementError.signal( + s"bad reference while unpickling $filename: ${name.longString} not found in ${owner.tpe.widen}" ) def inferMethodAlternative(fun: Tree, argtpes: List[Type], restpe: Type) {} // can't do it; need a compiler for that. diff --git a/src/compiler/scala/reflect/internal/settings/AbsSettings.scala b/src/reflect/scala/reflect/internal/settings/AbsSettings.scala index 9bbba3f079..9bbba3f079 100644 --- a/src/compiler/scala/reflect/internal/settings/AbsSettings.scala +++ b/src/reflect/scala/reflect/internal/settings/AbsSettings.scala diff --git a/src/compiler/scala/reflect/internal/settings/MutableSettings.scala b/src/reflect/scala/reflect/internal/settings/MutableSettings.scala index 8640a23aa7..e9899f690d 100644 --- a/src/compiler/scala/reflect/internal/settings/MutableSettings.scala +++ b/src/reflect/scala/reflect/internal/settings/MutableSettings.scala @@ -45,4 +45,5 @@ abstract class MutableSettings extends AbsSettings { def Xexperimental: BooleanSetting def XoldPatmat: BooleanSetting def XnoPatmatAnalysis: BooleanSetting + def XfullLubs: BooleanSetting }
\ No newline at end of file diff --git a/src/compiler/scala/reflect/internal/transform/Erasure.scala b/src/reflect/scala/reflect/internal/transform/Erasure.scala index 5beec70d62..5beec70d62 100644 --- a/src/compiler/scala/reflect/internal/transform/Erasure.scala +++ b/src/reflect/scala/reflect/internal/transform/Erasure.scala diff --git a/src/compiler/scala/reflect/internal/transform/RefChecks.scala b/src/reflect/scala/reflect/internal/transform/RefChecks.scala index d6108ab665..d6108ab665 100644 --- a/src/compiler/scala/reflect/internal/transform/RefChecks.scala +++ b/src/reflect/scala/reflect/internal/transform/RefChecks.scala diff --git a/src/compiler/scala/reflect/internal/transform/Transforms.scala b/src/reflect/scala/reflect/internal/transform/Transforms.scala index a7cc99ba3b..c4c5dc3a1c 100644 --- a/src/compiler/scala/reflect/internal/transform/Transforms.scala +++ b/src/reflect/scala/reflect/internal/transform/Transforms.scala @@ -2,6 +2,8 @@ package scala.reflect package internal package transform +import language.existentials + trait Transforms { self: SymbolTable => /** We need to encode laziness by hand here because the three components refChecks, uncurry and erasure diff --git a/src/compiler/scala/reflect/internal/transform/UnCurry.scala b/src/reflect/scala/reflect/internal/transform/UnCurry.scala index 0c1640ceb9..0c1640ceb9 100644 --- a/src/compiler/scala/reflect/internal/transform/UnCurry.scala +++ b/src/reflect/scala/reflect/internal/transform/UnCurry.scala diff --git a/src/compiler/scala/reflect/internal/util/Collections.scala b/src/reflect/scala/reflect/internal/util/Collections.scala index 1f8eb15c90..1f8eb15c90 100644 --- a/src/compiler/scala/reflect/internal/util/Collections.scala +++ b/src/reflect/scala/reflect/internal/util/Collections.scala diff --git a/src/compiler/scala/reflect/internal/util/HashSet.scala b/src/reflect/scala/reflect/internal/util/HashSet.scala index a771dad2b0..a771dad2b0 100644 --- a/src/compiler/scala/reflect/internal/util/HashSet.scala +++ b/src/reflect/scala/reflect/internal/util/HashSet.scala diff --git a/src/compiler/scala/reflect/internal/util/Origins.scala b/src/reflect/scala/reflect/internal/util/Origins.scala index 0bd5ad55ca..0bd5ad55ca 100644 --- a/src/compiler/scala/reflect/internal/util/Origins.scala +++ b/src/reflect/scala/reflect/internal/util/Origins.scala diff --git a/src/compiler/scala/tools/nsc/util/Position.scala b/src/reflect/scala/reflect/internal/util/Position.scala index 208cd5703a..3c251b3b31 100644 --- a/src/compiler/scala/tools/nsc/util/Position.scala +++ b/src/reflect/scala/reflect/internal/util/Position.scala @@ -4,8 +4,11 @@ * */ -package scala.tools.nsc -package util +package scala.reflect.internal.util + +import reflect.ClassTag +import reflect.base.Attachments +import reflect.api.PositionApi object Position { val tabInc = 8 @@ -33,22 +36,13 @@ object Position { } } -trait Position extends scala.reflect.api.Position with scala.reflect.api.Attachment { - /** Exposes itself as payload of Attachment */ - // necessary for conformance with Attachment - def pos: Position = this +abstract class Position extends PositionApi { self => - /** A bit weird method that is necessary to safely update positions without destroying custom attachments */ - // necessary for conformance with Attachment - def withPos(newPos: scala.reflect.api.Position): scala.reflect.api.Attachment = newPos + type Pos = Position - /** Exposes itself as payload of Attachment */ - // necessary for conformance with Attachment - def payload: Position = this + def pos: Position = this - /** A bit weird method that is necessary to safely update positions without destroying custom attachments */ - // necessary for conformance with Attachment - def withPayload(newPos: Any): scala.reflect.api.Attachment = newPos.asInstanceOf[Position] + def withPos(newPos: Position): Attachments { type Pos = self.Pos } = newPos /** Java file corresponding to the source file of this position. */ @@ -118,7 +112,7 @@ trait Position extends scala.reflect.api.Position with scala.reflect.api.Attachm /** If this is a range, the union with the other range, with the point of this position. * Otherwise, this position */ - def union(pos: scala.reflect.api.Position): Position = this + def union(pos: Position): Position = this /** If this is a range position, the offset position of its start. * Otherwise the position itself @@ -139,39 +133,39 @@ trait Position extends scala.reflect.api.Position with scala.reflect.api.Attachm * This holds if `this` is a range position and its range [start..end] * is the same or covers the range of the given position, which may or may not be a range position. */ - def includes(pos: scala.reflect.api.Position): Boolean = false + def includes(pos: Position): Boolean = false /** Does this position properly include the given position `pos` ("properly" meaning their * ranges are not the same)? */ - def properlyIncludes(pos: scala.reflect.api.Position): Boolean = + def properlyIncludes(pos: Position): Boolean = includes(pos) && (start < pos.startOrPoint || pos.endOrPoint < end) /** Does this position precede that position? * This holds if both positions are defined and the end point of this position * is not larger than the start point of the given position. */ - def precedes(pos: scala.reflect.api.Position): Boolean = + def precedes(pos: Position): Boolean = isDefined && pos.isDefined && endOrPoint <= pos.startOrPoint /** Does this position properly precede the given position `pos` ("properly" meaning their ranges * do not share a common point). */ - def properlyPrecedes(pos: scala.reflect.api.Position): Boolean = + def properlyPrecedes(pos: Position): Boolean = isDefined && pos.isDefined && endOrPoint < pos.startOrPoint /** Does this position overlap with that position? * This holds if both positions are ranges and there is an interval of * non-zero length that is shared by both position ranges. */ - def overlaps(pos: scala.reflect.api.Position): Boolean = + def overlaps(pos: Position): Boolean = isRange && pos.isRange && ((pos.start < end && start < pos.end) || (start < pos.end && pos.start < end)) /** Does this position cover the same range as that position? * Holds only if both position are ranges */ - def sameRange(pos: scala.reflect.api.Position): Boolean = + def sameRange(pos: Position): Boolean = isRange && pos.isRange && start == pos.start && end == pos.end def line: Int = throw new UnsupportedOperationException("Position.line") @@ -224,10 +218,7 @@ class OffsetPosition(override val source: SourceFile, override val point: Int) e col + 1 } - override def union(pos: scala.reflect.api.Position) = - // [Eugene] how do I get rid of this cast? - // I could introduce a "type PositionType <: scala.reflect.api.Position", but that's also ugly - if (pos.isRange) pos.asInstanceOf[Position] else this + override def union(pos: Position) = if (pos.isRange) pos else this override def equals(that : Any) = that match { case that : OffsetPosition => point == that.point && source.file == that.source.file @@ -261,8 +252,8 @@ extends OffsetPosition(source, point) { } override def focusEnd = new OffsetPosition(source, end) override def makeTransparent = new TransparentPosition(source, start, point, end) - override def includes(pos: scala.reflect.api.Position) = pos.isDefined && start <= pos.startOrPoint && pos.endOrPoint <= end - override def union(pos: scala.reflect.api.Position): Position = + override def includes(pos: Position) = pos.isDefined && start <= pos.startOrPoint && pos.endOrPoint <= end + override def union(pos: Position): Position = if (pos.isRange) new RangePosition(source, start min pos.start, point, end max pos.end) else this override def toSingleLine: Position = source match { diff --git a/src/compiler/scala/reflect/internal/util/Set.scala b/src/reflect/scala/reflect/internal/util/Set.scala index cfc3e7eada..cfc3e7eada 100644 --- a/src/compiler/scala/reflect/internal/util/Set.scala +++ b/src/reflect/scala/reflect/internal/util/Set.scala diff --git a/src/compiler/scala/tools/nsc/util/SourceFile.scala b/src/reflect/scala/reflect/internal/util/SourceFile.scala index e1ae96da8c..7c80ddd37d 100644 --- a/src/compiler/scala/tools/nsc/util/SourceFile.scala +++ b/src/reflect/scala/reflect/internal/util/SourceFile.scala @@ -4,10 +4,9 @@ */ -package scala.tools.nsc -package util +package scala.reflect.internal.util -import io.{ AbstractFile, VirtualFile } +import scala.tools.nsc.io.{ AbstractFile, VirtualFile } import scala.collection.mutable.ArrayBuffer import annotation.tailrec import java.util.regex.Pattern diff --git a/src/compiler/scala/reflect/internal/util/StatBase.scala b/src/reflect/scala/reflect/internal/util/StatBase.scala index b033ff98bc..b033ff98bc 100644 --- a/src/compiler/scala/reflect/internal/util/StatBase.scala +++ b/src/reflect/scala/reflect/internal/util/StatBase.scala diff --git a/src/compiler/scala/reflect/internal/util/Statistics.scala b/src/reflect/scala/reflect/internal/util/Statistics.scala index ef17327fda..de0830aa3a 100644 --- a/src/compiler/scala/reflect/internal/util/Statistics.scala +++ b/src/reflect/scala/reflect/internal/util/Statistics.scala @@ -28,6 +28,9 @@ class Statistics extends StatBase { val baseTypeSeqLenTotal = new Counter val typeSymbolCount = new Counter val classSymbolCount = new Counter + val lubCount = new Counter + val nestedLubCount = new Counter + val lubNanos = new Timer } object Statistics extends Statistics diff --git a/src/compiler/scala/tools/util/StringOps.scala b/src/reflect/scala/reflect/internal/util/StringOps.scala index 725e0afb79..281ade8134 100644 --- a/src/compiler/scala/tools/util/StringOps.scala +++ b/src/reflect/scala/reflect/internal/util/StringOps.scala @@ -7,8 +7,7 @@ \* */ -package scala.tools -package util +package scala.reflect.internal.util /** This object provides utility methods to extract elements * from Strings. diff --git a/src/compiler/scala/tools/nsc/util/TableDef.scala b/src/reflect/scala/reflect/internal/util/TableDef.scala index 10c63eeee2..d692a6d8f5 100644 --- a/src/compiler/scala/tools/nsc/util/TableDef.scala +++ b/src/reflect/scala/reflect/internal/util/TableDef.scala @@ -1,5 +1,4 @@ -package scala.tools.nsc -package util +package scala.reflect.internal.util import TableDef._ diff --git a/src/compiler/scala/reflect/internal/util/TraceSymbolActivity.scala b/src/reflect/scala/reflect/internal/util/TraceSymbolActivity.scala index 1424226042..5fbeb5f576 100644 --- a/src/compiler/scala/reflect/internal/util/TraceSymbolActivity.scala +++ b/src/reflect/scala/reflect/internal/util/TraceSymbolActivity.scala @@ -2,12 +2,13 @@ package scala.reflect.internal package util import scala.collection.{ mutable, immutable } +import language.postfixOps trait TraceSymbolActivity { val global: SymbolTable import global._ - if (traceSymbolActivity && !global.inReflexiveMirror) + if (traceSymbolActivity && global.isCompilerUniverse) scala.sys addShutdownHook showAllSymbols() private type Set[T] = scala.collection.immutable.Set[T] diff --git a/src/compiler/scala/tools/nsc/util/WeakHashSet.scala b/src/reflect/scala/reflect/internal/util/WeakHashSet.scala index 5bbb766e21..9882aad5e5 100644 --- a/src/compiler/scala/tools/nsc/util/WeakHashSet.scala +++ b/src/reflect/scala/reflect/internal/util/WeakHashSet.scala @@ -1,4 +1,4 @@ -package scala.tools.nsc.util +package scala.reflect.internal.util import scala.collection.mutable import scala.collection.mutable.ArrayBuffer diff --git a/src/reflect/scala/reflect/makro/Aliases.scala b/src/reflect/scala/reflect/makro/Aliases.scala new file mode 100644 index 0000000000..4bd246572f --- /dev/null +++ b/src/reflect/scala/reflect/makro/Aliases.scala @@ -0,0 +1,26 @@ +package scala.reflect +package makro + +trait Aliases { + self: Context => + + type Symbol = universe.Symbol + type Type = universe.Type + type Name = universe.Name + type TermName = universe.TermName + type TypeName = universe.TypeName + type Tree = universe.Tree + // type Position = universe.Position + type Scope = universe.Scope + type Modifiers = universe.Modifiers + + type Expr[+T] = universe.Expr[T] + val Expr = universe.Expr + + type AbsTypeTag[T] = universe.AbsTypeTag[T] + type TypeTag[T] = universe.TypeTag[T] + val AbsTypeTag = universe.AbsTypeTag + val TypeTag = universe.TypeTag + def typeTag[T](implicit ttag: TypeTag[T]) = ttag + def typeOf[T](implicit ttag: TypeTag[T]): Type = ttag.tpe +} diff --git a/src/library/scala/reflect/makro/CapturedVariables.scala b/src/reflect/scala/reflect/makro/CapturedVariables.scala index 6ce832b2b3..592e28b3b2 100644 --- a/src/library/scala/reflect/makro/CapturedVariables.scala +++ b/src/reflect/scala/reflect/makro/CapturedVariables.scala @@ -1,4 +1,5 @@ -package scala.reflect.makro +package scala.reflect +package makro trait CapturedVariables { self: Context => diff --git a/src/reflect/scala/reflect/makro/Context.scala b/src/reflect/scala/reflect/makro/Context.scala new file mode 100644 index 0000000000..f9858a063c --- /dev/null +++ b/src/reflect/scala/reflect/makro/Context.scala @@ -0,0 +1,40 @@ +package scala.reflect +package makro + +import language.experimental.macros + +// todo. introduce context hierarchy +// the most lightweight context should just expose the stuff from the SIP +// the full context should include all traits from scala.reflect.makro (and probably reside in scala-compiler.jar) + +trait Context extends Aliases + with CapturedVariables + with Enclosures + with Infrastructure + with Names + with Reifiers + with FrontEnds + with Settings + with Typers + with Parsers + with Exprs + with TypeTags + with Evals + with ExprUtils { + + /** The compile-time universe */ + val universe: Universe + + /** The mirror of the compile-time universe */ + val mirror: MirrorOf[universe.type] + + /** The type of the prefix tree from which the macro is selected */ + type PrefixType + + /** The prefix tree from which the macro is selected */ + val prefix: Expr[PrefixType] + + /** Alias to the underlying mirror's reify */ + // implementation is magically hardwired to `scala.reflect.makro.runtime.ContextReifiers` + def reify[T](expr: T): Expr[T] = macro ??? +} diff --git a/src/library/scala/reflect/makro/Enclosures.scala b/src/reflect/scala/reflect/makro/Enclosures.scala index 136d39498e..69bd8d09c7 100644 --- a/src/library/scala/reflect/makro/Enclosures.scala +++ b/src/reflect/scala/reflect/makro/Enclosures.scala @@ -1,4 +1,5 @@ -package scala.reflect.makro +package scala.reflect +package makro trait Enclosures { self: Context => diff --git a/src/reflect/scala/reflect/makro/Evals.scala b/src/reflect/scala/reflect/makro/Evals.scala new file mode 100644 index 0000000000..4e5fc2f97f --- /dev/null +++ b/src/reflect/scala/reflect/makro/Evals.scala @@ -0,0 +1,9 @@ +package scala.reflect +package makro + +trait Evals { + self: Context => + + /** .. */ + def eval[T](expr: Expr[T]): T +}
\ No newline at end of file diff --git a/src/library/scala/reflect/makro/Util.scala b/src/reflect/scala/reflect/makro/ExprUtils.scala index 16eb2395a9..c3e5cc6bc1 100644 --- a/src/library/scala/reflect/makro/Util.scala +++ b/src/reflect/scala/reflect/makro/ExprUtils.scala @@ -1,6 +1,7 @@ -package scala.reflect.makro +package scala.reflect +package makro -trait Util { +trait ExprUtils { self: Context => def literalNull: Expr[Null] diff --git a/src/reflect/scala/reflect/makro/Exprs.scala b/src/reflect/scala/reflect/makro/Exprs.scala new file mode 100644 index 0000000000..91d3dafbf2 --- /dev/null +++ b/src/reflect/scala/reflect/makro/Exprs.scala @@ -0,0 +1,8 @@ +package scala.reflect +package makro + +trait Exprs { + self: Context => + + def Expr[T: AbsTypeTag](tree: Tree): Expr[T] +} diff --git a/src/library/scala/reflect/makro/FrontEnds.scala b/src/reflect/scala/reflect/makro/FrontEnds.scala index a1e24dcea3..5087f90174 100644 --- a/src/library/scala/reflect/makro/FrontEnds.scala +++ b/src/reflect/scala/reflect/makro/FrontEnds.scala @@ -1,10 +1,13 @@ -package scala.reflect.makro +package scala.reflect +package makro -trait FrontEnds { +trait FrontEnds extends scala.reflect.api.FrontEnds { self: Context => import mirror._ + type Position = universe.Position + /** Exposes means to control the compiler UI */ def frontEnd: FrontEnd def setFrontEnd(frontEnd: FrontEnd): this.type diff --git a/src/library/scala/reflect/makro/Infrastructure.scala b/src/reflect/scala/reflect/makro/Infrastructure.scala index 2bf49dca77..e6bfe33366 100644 --- a/src/library/scala/reflect/makro/Infrastructure.scala +++ b/src/reflect/scala/reflect/makro/Infrastructure.scala @@ -1,4 +1,5 @@ -package scala.reflect.makro +package scala.reflect +package makro trait Infrastructure { self: Context => @@ -23,6 +24,35 @@ trait Infrastructure { */ val currentRun: Run + /** Exposes library classpath. + */ + val libraryClassPath: List[java.net.URL] + + /** Exposes a classloader that corresponds to the library classpath. + * + * With this classloader you can perform on-the-fly evaluation of macro arguments. + * For example, consider this code snippet: + * + * def staticEval[T](x: T) = macro staticEval[T] + * + * def staticEval[T: c.TypeTag](c: Context)(x: c.Expr[T]) = { + * import scala.reflect.runtime.{universe => ru} + * val mirror = ru.runtimeMirror(c.libraryClassLoader) + * import scala.tools.reflect.ToolBox + * val toolBox = mirror.mkToolBox() + * val importer = ru.mkImporter(c.universe).asInstanceOf[ru.Importer { val from: c.universe.type }] + * val tree = c.resetAllAttrs(x.tree.duplicate) + * val imported = importer.importTree(tree) + * val valueOfX = toolBox.runExpr(imported).asInstanceOf[T] + * ... + * } + * + * // [Eugene++] using this guy will tremendously slow down the compilation + * // https://twitter.com/xeno_by/status/201248317831774208 + * // todo. we need to address this somehow + */ + def libraryClassLoader: ClassLoader + /** As seen by macro API, compilation run is an opaque type that can be deconstructed into: * 1) Current compilation unit * 2) List of all compilation units that comprise the run diff --git a/src/library/scala/reflect/makro/Names.scala b/src/reflect/scala/reflect/makro/Names.scala index 8a823d19cb..909976d83c 100644 --- a/src/library/scala/reflect/makro/Names.scala +++ b/src/reflect/scala/reflect/makro/Names.scala @@ -1,4 +1,5 @@ -package scala.reflect.makro +package scala.reflect +package makro trait Names { self: Context => @@ -10,5 +11,5 @@ trait Names { def fresh(name: String): String /** Creates a fresh name from the provided name */ - def fresh(name: Name): Name + def fresh[NameType <: Name](name: NameType): NameType } diff --git a/src/reflect/scala/reflect/makro/Parsers.scala b/src/reflect/scala/reflect/makro/Parsers.scala new file mode 100644 index 0000000000..9866b7e491 --- /dev/null +++ b/src/reflect/scala/reflect/makro/Parsers.scala @@ -0,0 +1,18 @@ +package scala.reflect +package makro + +trait Parsers { + self: Context => + + /** .. */ + // todo. distinguish between `parseExpr` and `parse` + def parse(code: String): Tree + + /** Represents an error during parsing + */ + type ParseError <: Throwable + val ParseError: ParseErrorExtractor + abstract class ParseErrorExtractor { + def unapply(error: ParseError): Option[(Position, String)] + } +}
\ No newline at end of file diff --git a/src/library/scala/reflect/makro/Reifiers.scala b/src/reflect/scala/reflect/makro/Reifiers.scala index b1de8d9957..f39f56f935 100644 --- a/src/library/scala/reflect/makro/Reifiers.scala +++ b/src/reflect/scala/reflect/makro/Reifiers.scala @@ -1,17 +1,26 @@ -package scala.reflect.makro +package scala.reflect +package makro trait Reifiers { self: Context => - /** Reification prefix that refers to the standard reflexive mirror, ``scala.reflect.mirror''. + /** Reification prefix that refers to the base reflexive universe, ``scala.reflect.basis''. * Providing it for the ``prefix'' parameter of ``reifyTree'' or ``reifyType'' will create a tree that can be inspected at runtime. */ - val reflectMirrorPrefix: Tree + val basisUniverse: Tree + + /** Reification prefix that refers to the runtime reflexive universe, ``scala.reflect.runtime.universe''. + * Providing it for the ``prefix'' parameter of ``reifyTree'' or ``reifyType'' will create a full-fledged tree that can be inspected at runtime. + */ + val runtimeUniverse: Tree /** Given a tree, generate a tree that when compiled and executed produces the original tree. - * The produced tree will be bound to the mirror specified by ``prefix'' (also see ``reflectMirrorPrefix''). * For more information and examples see the documentation for ``Universe.reify''. * + * The produced tree will be bound to the specified ``universe'' and ``mirror''. + * Possible values for ``universe'' include ``basisUniverse'' and ``runtimeUniverse''. + * Possible values for ``mirror'' include ``EmptyTree'' (in that case the reifier will automatically pick an appropriate mirror). + * * This function is deeply connected to ``Universe.reify'', a macro that reifies arbitrary expressions into runtime trees. * They do very similar things (``Universe.reify'' calls ``Context.reifyTree'' to implement itself), but they operate on different metalevels (see below). * @@ -40,18 +49,23 @@ trait Reifiers { * Typical usage of this function is to retain some of the trees received/created by a macro * into the form that can be inspected (via pattern matching) or compiled/run (by a reflective ToolBox) during the runtime. */ - def reifyTree(prefix: Tree, tree: Tree): Tree + def reifyTree(universe: Tree, mirror: Tree, tree: Tree): Tree /** Given a type, generate a tree that when compiled and executed produces the original type. - * The produced tree will be bound to the mirror specified by ``prefix'' (also see ``reflectMirrorPrefix''). + * The produced tree will be bound to the specified ``universe'' and ``mirror''. * For more information and examples see the documentation for ``Context.reifyTree'' and ``Universe.reify''. */ - def reifyType(prefix: Tree, tpe: Type, dontSpliceAtTopLevel: Boolean = false, concrete: Boolean = false): Tree + def reifyType(universe: Tree, mirror: Tree, tpe: Type, concrete: Boolean = false): Tree + + /** Given a type, generate a tree that when compiled and executed produces the runtime class of the original type. + * If ``concrete'' is true, then this function will bail on types, who refer to abstract types (like `ClassTag` does). + */ + def reifyRuntimeClass(tpe: Type, concrete: Boolean = true): Tree - /** Given a type, generate a tree that when compiled and executed produces the erasure of the original type. - * If ``concrete'' is true, then this function will bail on types, whose erasure includes abstract types (like `ClassTag` does). + /** Given a type, generate a tree that when compiled and executed produces the runtime class of the enclosing class or module. + * Returns `EmptyTree` if there does not exist an enclosing class or module. */ - def reifyErasure(tpe: Type, concrete: Boolean = true): Tree + def reifyEnclosingRuntimeClass: Tree /** Undoes reification of a tree. * @@ -72,6 +86,6 @@ trait Reifiers { // made these guys non path-dependent, otherwise exception handling quickly becomes a mess -case class ReificationError(var pos: reflect.api.Position, val msg: String) extends Throwable(msg) +case class ReificationError(val pos: reflect.api.PositionApi, val msg: String) extends Throwable(msg) -case class UnexpectedReificationError(val pos: reflect.api.Position, val msg: String, val cause: Throwable = null) extends Throwable(msg, cause)
\ No newline at end of file +case class UnexpectedReificationError(val pos: reflect.api.PositionApi, val msg: String, val cause: Throwable = null) extends Throwable(msg, cause) diff --git a/src/library/scala/reflect/makro/Settings.scala b/src/reflect/scala/reflect/makro/Settings.scala index c4a8ebd1b5..c6c7e5870b 100644 --- a/src/library/scala/reflect/makro/Settings.scala +++ b/src/reflect/scala/reflect/makro/Settings.scala @@ -1,4 +1,5 @@ -package scala.reflect.makro +package scala.reflect +package makro trait Settings { self: Context => @@ -18,6 +19,7 @@ trait Settings { /** Updates current compiler settings with an option string. * Use `scalac -help`, `scalac -X` and `scalac -Y` to learn about currently supported options. + * todo. http://groups.google.com/group/scala-internals/browse_thread/thread/07c18cff41f59203 */ def setCompilerSettings(options: String): this.type diff --git a/src/reflect/scala/reflect/makro/TreeBuilder.scala b/src/reflect/scala/reflect/makro/TreeBuilder.scala new file mode 100644 index 0000000000..c4179b9c80 --- /dev/null +++ b/src/reflect/scala/reflect/makro/TreeBuilder.scala @@ -0,0 +1,60 @@ +package scala.reflect +package makro + +// [Eugene] I added some stuff that was necessary for typetag materialization macros +// but we should think it over and pick other generally useful stuff +// same goes for tree traversers/transformers, type maps, etc +// and once we expose all that, there's another question: how do we stay in sync? +abstract class TreeBuilder { + val global: Universe + + import global._ + import definitions._ + + /** Builds a reference to value whose type is given stable prefix. + * The type must be suitable for this. For example, it + * must not be a TypeRef pointing to an abstract type variable. + */ + def mkAttributedQualifier(tpe: Type): Tree + + /** Builds a reference to value whose type is given stable prefix. + * If the type is unsuitable, e.g. it is a TypeRef for an + * abstract type variable, then an Ident will be made using + * termSym as the Ident's symbol. In that case, termSym must + * not be NoSymbol. + */ + def mkAttributedQualifier(tpe: Type, termSym: Symbol): Tree + + /** Builds a typed reference to given symbol with given stable prefix. */ + def mkAttributedRef(pre: Type, sym: Symbol): Tree + + /** Builds a typed reference to given symbol. */ + def mkAttributedRef(sym: Symbol): Tree + + /** Builds a typed This reference to given symbol. */ + def mkAttributedThis(sym: Symbol): Tree + + /** Builds a typed Ident with an underlying symbol. */ + def mkAttributedIdent(sym: Symbol): Tree + + /** Builds a typed Select with an underlying symbol. */ + def mkAttributedSelect(qual: Tree, sym: Symbol): Tree + + /** A creator for method calls, e.g. fn[T1, T2, ...](v1, v2, ...) + * There are a number of variations. + * + * @param receiver symbol of the method receiver + * @param methodName name of the method to call + * @param targs type arguments (if Nil, no TypeApply node will be generated) + * @param args value arguments + * @return the newly created trees. + */ + def mkMethodCall(receiver: Symbol, methodName: Name, targs: List[Type], args: List[Tree]): Tree + def mkMethodCall(method: Symbol, targs: List[Type], args: List[Tree]): Tree + def mkMethodCall(method: Symbol, args: List[Tree]): Tree + def mkMethodCall(target: Tree, args: List[Tree]): Tree + def mkMethodCall(receiver: Symbol, methodName: Name, args: List[Tree]): Tree + def mkMethodCall(receiver: Tree, method: Symbol, targs: List[Type], args: List[Tree]): Tree + def mkMethodCall(target: Tree, targs: List[Type], args: List[Tree]): Tree + def mkNullaryCall(method: Symbol, targs: List[Type]): Tree +} diff --git a/src/reflect/scala/reflect/makro/TypeTags.scala b/src/reflect/scala/reflect/makro/TypeTags.scala new file mode 100644 index 0000000000..53a9b116e3 --- /dev/null +++ b/src/reflect/scala/reflect/makro/TypeTags.scala @@ -0,0 +1,9 @@ +package scala.reflect +package makro + +trait TypeTags { + self: Context => + + def AbsTypeTag[T](tpe: Type): AbsTypeTag[T] + def TypeTag[T](tpe: Type): TypeTag[T] +} diff --git a/src/library/scala/reflect/makro/Typers.scala b/src/reflect/scala/reflect/makro/Typers.scala index 90024a4f7a..2610d7dd50 100644 --- a/src/library/scala/reflect/makro/Typers.scala +++ b/src/reflect/scala/reflect/makro/Typers.scala @@ -1,9 +1,10 @@ -package scala.reflect.makro +package scala.reflect +package makro trait Typers { self: Context => - import mirror._ + import universe._ /** Contexts that represent macros in-flight, including the current one. Very much like a stack trace, but for macros only. * Can be useful for interoperating with other macros and for imposing compiler-friendly limits on macro expansion. diff --git a/src/reflect/scala/reflect/makro/Universe.scala b/src/reflect/scala/reflect/makro/Universe.scala new file mode 100644 index 0000000000..ffc4042a0a --- /dev/null +++ b/src/reflect/scala/reflect/makro/Universe.scala @@ -0,0 +1,118 @@ +package scala.reflect +package makro + +abstract class Universe extends scala.reflect.api.Universe { + + val treeBuild: TreeBuilder { val global: Universe.this.type } + + // Symbol extensions --------------------------------------------------------------- + + override type Symbol >: Null <: SymbolContextApi + + /** The extended API of symbols that's supported in macro context universes + */ + trait SymbolContextApi extends SymbolApi { this: Symbol => + + // [Eugene++ to Martin] should we also add mutability methods here (similarly to what's done below for trees)? + // I'm talking about `setAnnotations` and friends + + /** Can this symbol be loaded by a reflective mirror? + * + * Scalac relies on `ScalaSignature' annotation to retain symbols across compilation runs. + * Such annotations (also called "pickles") are applied on top-level classes and include information + * about all symbols reachable from the annotee. However, local symbols (e.g. classes or definitions local to a block) + * are typically unreachable and information about them gets lost. + * + * This method is useful for macro writers who wish to save certain ASTs to be used at runtime. + * With `isLocatable' it's possible to check whether a tree can be retained as is, or it needs special treatment. + */ + def isLocatable: Boolean + + /** Is this symbol static (i.e. with no outer instance)? + * Q: When exactly is a sym marked as STATIC? + * A: If it's a member of a toplevel object, or of an object contained in a toplevel object, or any number of levels deep. + * http://groups.google.com/group/scala-internals/browse_thread/thread/d385bcd60b08faf6 + */ + def isStatic: Boolean + } + + // Tree extensions --------------------------------------------------------------- + + override type Tree >: Null <: TreeContextApi + + /** The extended API of trees that's supported in macro context universes + */ + trait TreeContextApi extends TreeApi { this: Tree => + + /** ... */ + def pos_=(pos: Position): Unit + + /** ... */ + def setPos(newpos: Position): this.type + + /** ... */ + def tpe_=(t: Type): Unit + + /** Set tpe to give `tp` and return this. + */ + def setType(tp: Type): this.type + + /** Like `setType`, but if this is a previously empty TypeTree that + * fact is remembered so that resetAllAttrs will snap back. + * + * @PP: Attempting to elaborate on the above, I find: If defineType + * is called on a TypeTree whose type field is null or NoType, + * this is recorded as "wasEmpty = true". That value is used in + * ResetAttrsTraverser, which nulls out the type field of TypeTrees + * for which wasEmpty is true, leaving the others alone. + * + * resetAllAttrs is used in situations where some speculative + * typing of a tree takes place, fails, and the tree needs to be + * returned to its former state to try again. So according to me: + * using `defineType` instead of `setType` is how you communicate + * that the type being set does not depend on any previous state, + * and therefore should be abandoned if the current line of type + * inquiry doesn't work out. + */ + def defineType(tp: Type): this.type + + /** ... */ + def symbol_=(sym: Symbol): Unit + + /** ... */ + def setSymbol(sym: Symbol): this.type + + /** ... */ + def attachments: base.Attachments { type Pos = Position } + + /** ... */ + def addAttachment(attachment: Any): this.type + + /** ... */ + def removeAttachment[T: ClassTag]: this.type + } + + override type SymTree >: Null <: Tree with SymTreeContextApi + + /** The extended API of sym trees that's supported in macro context universes + */ + trait SymTreeContextApi extends SymTreeApi { this: SymTree => + var symbol: Symbol + } + + override type TypeTree >: Null <: TypTree with TypeTreeContextApi + + /** The extended API of sym trees that's supported in macro context universes + */ + trait TypeTreeContextApi extends TypeTreeApi { this: TypeTree => + def setOriginal(tree: Tree): this.type + } + + override type Ident >: Null <: RefTree with IdentContextApi + + /** The extended API of idents that's supported in macro context universes + */ + trait IdentContextApi extends IdentApi { this: Ident => + def isBackquoted: Boolean + } +}
\ No newline at end of file diff --git a/src/reflect/scala/reflect/makro/package.scala b/src/reflect/scala/reflect/makro/package.scala new file mode 100644 index 0000000000..3c0e51030e --- /dev/null +++ b/src/reflect/scala/reflect/makro/package.scala @@ -0,0 +1,6 @@ +package scala.reflect + +package object makro { + + type MirrorOf[U <: base.Universe with Singleton] = base.MirrorOf[U] +} diff --git a/src/compiler/scala/reflect/runtime/AbstractFile.scala b/src/reflect/scala/reflect/runtime/AbstractFile.scala index 414bba020b..0f88af1b0a 100644 --- a/src/compiler/scala/reflect/runtime/AbstractFile.scala +++ b/src/reflect/scala/reflect/runtime/AbstractFile.scala @@ -1,7 +1,7 @@ package scala.reflect package runtime -class AbstractFile(val jfile: java.io.File) extends api.RequiredFile { +class AbstractFile(val jfile: java.io.File) extends internal.AbstractFileApi { def path: String = jfile.getPath() def canonicalPath: String = jfile.getCanonicalPath() } diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala new file mode 100644 index 0000000000..38d280ec73 --- /dev/null +++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala @@ -0,0 +1,1037 @@ +package scala.reflect +package runtime + +import scala.ref.WeakReference +import scala.collection.mutable.WeakHashMap + +import java.lang.{Class => jClass, Package => jPackage} +import java.lang.reflect.{ + Method => jMethod, Constructor => jConstructor, Modifier => jModifier, Field => jField, + Member => jMember, Type => jType, TypeVariable => jTypeVariable, Array => jArray, + GenericDeclaration, GenericArrayType, ParameterizedType, WildcardType, AnnotatedElement } +import java.io.IOException +import internal.MissingRequirementError +import internal.pickling.ByteCodecs +import internal.ClassfileConstants._ +import internal.pickling.UnPickler +import collection.mutable.{ HashMap, ListBuffer } +import internal.Flags._ +//import scala.tools.nsc.util.ScalaClassLoader +//import scala.tools.nsc.util.ScalaClassLoader._ +import ReflectionUtils.{singletonInstance} +import language.existentials + +trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: SymbolTable => + + private lazy val mirrors = new WeakHashMap[ClassLoader, WeakReference[JavaMirror]]() + + private def createMirror(owner: Symbol, cl: ClassLoader): Mirror = { + val jm = new JavaMirror(owner, cl) + mirrors(cl) = new WeakReference(jm) + jm.init() + jm + } + + override type RuntimeClass = java.lang.Class[_] + + override type Mirror = JavaMirror + + override lazy val rootMirror: Mirror = createMirror(NoSymbol, rootClassLoader) + + // overriden by ReflectGlobal + def rootClassLoader: ClassLoader = this.getClass.getClassLoader + + def init() = { + definitions.AnyValClass // force it. + + // establish root association to avoid cyclic dependency errors later + rootMirror.classToScala(classOf[java.lang.Object]).initialize + + // println("initializing definitions") + definitions.init() + } + + def runtimeMirror(cl: ClassLoader): Mirror = mirrors get cl match { + case Some(WeakReference(m)) => m + case _ => createMirror(rootMirror.RootClass, cl) + } + + /** The API of a mirror for a reflective universe */ + class JavaMirror(owner: Symbol, + /** Class loader that is a mastermind behind the reflexive mirror */ + val classLoader: ClassLoader + ) extends Roots(owner) with super.JavaMirror { wholemirror => + + val universe: self.type = self + + import definitions._ + + /** The lazy type for root. + */ + override lazy val rootLoader = new LazyType { + override def complete(sym: Symbol) = sym setInfo new LazyPackageType + } + +// ----------- Caching ------------------------------------------------------------------ + + // [Eugene++ to Martin] not weak? why? + private val classCache = new TwoWayCache[jClass[_], ClassSymbol] + private val packageCache = new TwoWayCache[Package, ModuleSymbol] + private val methodCache = new TwoWayCache[jMethod, MethodSymbol] + private val constructorCache = new TwoWayCache[jConstructor[_], MethodSymbol] + private val fieldCache = new TwoWayCache[jField, TermSymbol] + private val tparamCache = new TwoWayCache[jTypeVariable[_ <: GenericDeclaration], TypeSymbol] + + def toScala[J: HasJavaClass, S](cache: TwoWayCache[J, S], key: J)(body: (JavaMirror, J) => S): S = + cache.toScala(key){ + val jclazz = implicitly[HasJavaClass[J]] getClazz key + body(mirrorDefining(jclazz), key) + } + + private implicit val classHasJavaClass: HasJavaClass[jClass[_]] = + new HasJavaClass(identity) + private implicit val methHasJavaClass: HasJavaClass[jMethod] + = new HasJavaClass(_.getDeclaringClass) + private implicit val fieldHasJavaClass: HasJavaClass[jField] = + new HasJavaClass(_.getDeclaringClass) + private implicit val constrHasJavaClass: HasJavaClass[jConstructor[_]] = + new HasJavaClass(_.getDeclaringClass) + private implicit val tparamHasJavaClass: HasJavaClass[jTypeVariable[_ <: GenericDeclaration]] = + new HasJavaClass ( (tparam: jTypeVariable[_ <: GenericDeclaration]) => { + tparam.getGenericDeclaration match { + case jclazz: jClass[_] => jclazz + case jmeth: jMethod => jmeth.getDeclaringClass + case jconstr: jConstructor[_] => jconstr.getDeclaringClass + } + }) + +// ----------- Implementations of mirror operations and classes ------------------- + + def reflect(obj: Any): InstanceMirror = new JavaInstanceMirror(obj.asInstanceOf[AnyRef]) + + def reflectClass(cls: ClassSymbol): ClassMirror = { + if (!cls.isStatic) throw new Error("this is an inner class, use reflectClass on an InstanceMirror to obtain its ClassMirror") + new JavaClassMirror(null, cls) + } + + def reflectModule(mod: ModuleSymbol): ModuleMirror = { + if (!mod.isStatic) throw new Error("this is an inner module, use reflectModule on an InstanceMirror to obtain its ModuleMirror") + new JavaModuleMirror(null, mod) + } + + def runtimeClass(tpe: Type): RuntimeClass = typeToJavaClass(tpe) + + def runtimeClass(cls: ClassSymbol): RuntimeClass = classToJava(cls) + + def classSymbol(rtcls: RuntimeClass): ClassSymbol = classToScala(rtcls) + + def moduleSymbol(rtcls: RuntimeClass): ModuleSymbol = classToScala(rtcls).companionModule.asModuleSymbol + + private class JavaInstanceMirror(obj: AnyRef) + extends InstanceMirror { + def instance = obj + def symbol = wholemirror.classSymbol(obj.getClass) + def reflectField(field: TermSymbol): FieldMirror = { + // [Eugene+++] check whether `field` represents a member of a `symbol` + if (field.isMethod || field.isModule) throw new Error(s""" + |expected a field symbol, you provided a ${field.kind} symbol + |A typical cause of this problem is using a field accessor symbol instead of a field symbol. + |To obtain a field symbol append nme.LOCAL_SUFFIX_STRING to the name of the field, + |when searching for a member with Type.members or Type.declarations. + |This is a temporary inconvenience that will be resolved before 2.10.0-final. + |More information can be found here: https://issues.scala-lang.org/browse/SI-5895. + """.trim.stripMargin) + new JavaFieldMirror(obj, field) + } + def reflectMethod(method: MethodSymbol): MethodMirror = { + // [Eugene+++] check whether `method` represents a member of a `symbol` + new JavaMethodMirror(obj, method) + } + def reflectClass(cls: ClassSymbol): ClassMirror = { + // [Eugene+++] check whether `cls` represents a member of a `symbol` + if (cls.isStatic) throw new Error("this is a static class, use reflectClass on a RuntimeMirror to obtain its ClassMirror") + new JavaClassMirror(instance, cls) + } + def reflectModule(mod: ModuleSymbol): ModuleMirror = { + // [Eugene+++] check whether `mod` represents a member of a `symbol` + if (mod.isStatic) throw new Error("this is a static module, use reflectModule on a RuntimeMirror to obtain its ModuleMirror") + new JavaModuleMirror(instance, mod) + } + } + + private class JavaFieldMirror(val receiver: AnyRef, val symbol: TermSymbol) + extends FieldMirror { + lazy val jfield = { + val jfield = fieldToJava(symbol) + if (!jfield.isAccessible) jfield.setAccessible(true) + jfield + } + def get = jfield.get(receiver) + def set(value: Any) = { + if (!symbol.isMutable) throw new Error("cannot set an immutable field") + jfield.set(receiver, value) + } + } + + private class JavaMethodMirror(val receiver: AnyRef, val symbol: MethodSymbol) + extends MethodMirror { + lazy val jmeth = { + val jmeth = methodToJava(symbol) + if (!jmeth.isAccessible) jmeth.setAccessible(true) + jmeth + } + def apply(args: Any*): Any = + if (symbol.owner == ArrayClass) + symbol.name match { + case nme.length => jArray.getLength(receiver) + case nme.apply => jArray.get(receiver, args(0).asInstanceOf[Int]) + case nme.update => jArray.set(receiver, args(0).asInstanceOf[Int], args(1)) + case _ => throw new Error(s"unexpected array method $symbol") + } + else + jmeth.invoke(receiver, args.asInstanceOf[Seq[AnyRef]]: _*) + } + + private class JavaConstructorMirror(val outer: AnyRef, val symbol: MethodSymbol) + extends MethodMirror { + override val receiver = outer + lazy val jconstr = { + val jconstr = constructorToJava(symbol) + if (!jconstr.isAccessible) jconstr.setAccessible(true) + jconstr + } + def apply(args: Any*): Any = { + val effectiveArgs = + if (outer == null) args.asInstanceOf[Seq[AnyRef]] + else outer +: args.asInstanceOf[Seq[AnyRef]] + jconstr.newInstance(effectiveArgs: _*) + } + } + + + private abstract class JavaTemplateMirror + extends TemplateMirror { + def outer: AnyRef + def erasure: ClassSymbol + lazy val runtimeClass = classToJava(erasure) + lazy val signature = typeToScala(runtimeClass) + } + + private class JavaClassMirror(val outer: AnyRef, val symbol: ClassSymbol) + extends JavaTemplateMirror with ClassMirror { + def erasure = symbol + def isStatic = false + def reflectConstructor(constructor: MethodSymbol) = new JavaConstructorMirror(outer, constructor) + def companion: Option[ModuleMirror] = symbol.companionModule match { + case module: ModuleSymbol => Some(new JavaModuleMirror(outer, module)) + case _ => None + } + } + + private class JavaModuleMirror(val outer: AnyRef, val symbol: ModuleSymbol) + extends JavaTemplateMirror with ModuleMirror { + def erasure = symbol.moduleClass.asClassSymbol + def isStatic = true + def instance = { + if (!symbol.owner.isPackageClass) throw new Error("inner and nested modules are not supported yet") + singletonInstance(classLoader, symbol.fullName) + } + def companion: Option[ClassMirror] = symbol.companionClass match { + case cls: ClassSymbol => Some(new JavaClassMirror(outer, cls)) + case _ => None + } + } + +// -------------------- Java to Scala ----------------------------------- + + /** Does method `meth` erase to Java method `jmeth`? + * This is true if the Java method type is the same as the Scala method type after performing + * all Scala-specific transformations in InfoTransformers. (to be done) + */ + private def erasesTo(meth: Symbol, jmeth: jMethod): Boolean = { + val mtpe = transformedType(meth) + (mtpe.paramTypes map runtimeClass) == jmeth.getParameterTypes.toList && + runtimeClass(mtpe.resultType) == jmeth.getReturnType + } + + private def erasesTo(meth: Symbol, jconstr: jConstructor[_]): Boolean = { + val mtpe = transformedType(meth) + (mtpe.paramTypes map runtimeClass) == jconstr.getParameterTypes.toList && + runtimeClass(mtpe.resultType) == jconstr.getDeclaringClass + } + + def javaClass(path: String): jClass[_] = + Class.forName(path, true, classLoader) + + /** Does `path` correspond to a Java class with that fully qualified name in the current class loader? */ + def tryJavaClass(path: String): Option[jClass[_]] = + try { + Some(javaClass(path)) + } catch { + case (_: ClassNotFoundException) | (_: NoClassDefFoundError) | (_: IncompatibleClassChangeError) => + None + } + + /** The mirror that corresponds to the classloader that original defined the given Java class */ + def mirrorDefining(jclazz: jClass[_]): JavaMirror = { + val cl = jclazz.getClassLoader + if (cl == this.classLoader) this else runtimeMirror(cl) + } + + private object unpickler extends UnPickler { + val global: self.type = self + } + + /** how connected???? + * Generate types for top-level Scala root class and root companion object + * from the pickled information stored in a corresponding Java class + * @param clazz The top-level Scala class for which info is unpickled + * @param module The top-level Scala companion object for which info is unpickled + * @param jclazz The Java class which contains the unpickled information in a + * ScalaSignature or ScalaLongSignature annotation. + */ + def unpickleClass(clazz: Symbol, module: Symbol, jclazz: jClass[_]): Unit = { + def markAbsent(tpe: Type) = setAllInfos(clazz, module, tpe) + def handleError(ex: Exception) = { + markAbsent(ErrorType) + if (settings.debug.value) ex.printStackTrace() + val msg = ex.getMessage() + MissingRequirementError.signal( + (if (msg eq null) "reflection error while loading " + clazz.name + else "error while loading " + clazz.name) + ", " + msg) + } + // don't use classOf[scala.reflect.ScalaSignature] here, because it will use getClass.getClassLoader, not mirror's classLoader + // don't use asInstanceOf either because of the same reason (lol, I cannot believe I fell for it) + // don't use structural types to simplify reflective invocations because of the same reason + def loadAnnotation(name: String): Option[java.lang.annotation.Annotation] = + tryJavaClass(name) flatMap { annotClass => + val anns = jclazz.getAnnotations + val result = anns find (_.annotationType == annotClass) + if (result.isEmpty && (anns exists (_.annotationType.getName == name))) + throw new ClassNotFoundException( + s"""Mirror classloader mismatch: $jclazz (loaded by ${ReflectionUtils.show(jclazz.getClassLoader)}) + |is unrelated to the mirror's classloader: (${ReflectionUtils.show(classLoader)})""".stripMargin) + result + } + def loadBytes[T: ClassTag](name: String): Option[T] = + loadAnnotation(name) map { ssig => + val bytesMethod = ssig.annotationType.getMethod("bytes") + bytesMethod.invoke(ssig).asInstanceOf[T] + } + + try { + markAbsent(NoType) + loadBytes[String]("scala.reflect.ScalaSignature") match { + case Some(ssig) => + info(s"unpickling Scala $clazz and $module, owner = ${clazz.owner}") + val bytes = ssig.getBytes + val len = ByteCodecs.decode(bytes) + unpickler.unpickle(bytes take len, 0, clazz, module, jclazz.getName) + case None => + loadBytes[Array[String]]("scala.reflect.ScalaLongSignature") match { + case Some(slsig) => + info(s"unpickling Scala $clazz and $module with long Scala signature") + val byteSegments = slsig map (_.getBytes) + val lens = byteSegments map ByteCodecs.decode + val bytes = Array.ofDim[Byte](lens.sum) + var len = 0 + for ((bs, l) <- byteSegments zip lens) { + bs.copyToArray(bytes, len, l) + len += l + } + unpickler.unpickle(bytes, 0, clazz, module, jclazz.getName) + case None => + // class does not have a Scala signature; it's a Java class + info("translating reflection info for Java " + jclazz) //debug + initClassModule(clazz, module, new FromJavaClassCompleter(clazz, module, jclazz)) + } + } + } catch { + case ex: MissingRequirementError => + handleError(ex) + case ex: IOException => + handleError(ex) + } + } + + /** + * A fresh Scala type parameter that corresponds to a Java type variable. + * The association between Scala type parameter and Java type variable is entered in the cache. + * @param jtvar The Java type variable + */ + private def createTypeParameter(jtvar: jTypeVariable[_ <: GenericDeclaration]): TypeSymbol = { + val tparam = sOwner(jtvar).newTypeParameter(newTypeName(jtvar.getName)) + .setInfo(new TypeParamCompleter(jtvar)) + tparamCache enter (jtvar, tparam) + tparam + } + + /** + * A completer that fills in the type of a Scala type parameter from the bounds of a Java type variable. + * @param jtvar The Java type variable + */ + private class TypeParamCompleter(jtvar: jTypeVariable[_ <: GenericDeclaration]) extends LazyType { + override def load(sym: Symbol) = complete(sym) + override def complete(sym: Symbol) = { + sym setInfo TypeBounds.upper(glb(jtvar.getBounds.toList map typeToScala map objToAny)) + } + } + + /** + * Copy all annotations of Java annotated element `jann` over to Scala symbol `sym`. + * Pre: `sym` is already initialized with a concrete type. + * Note: If `sym` is a method or constructor, its parameter annotations are copied as well. + */ + private def copyAnnotations(sym: Symbol, jann: AnnotatedElement) { + // to do: implement + } + + /** + * A completer that fills in the types of a Scala class and its companion object + * by copying corresponding type info from a Java class. This completer is used + * to reflect classes in Scala that do not have a Scala pickle info, be it + * because they are local classes or have been compiled from Java sources. + * @param clazz The Scala class for which info is copied + * @param module The Scala companion object for which info is copied + * @param jclazz The Java class + */ + private class FromJavaClassCompleter(clazz: Symbol, module: Symbol, jclazz: jClass[_]) extends LazyType { + + /** used to avoid cycles while initializing classes */ + private var parentsLevel = 0 + private var pendingLoadActions: List[() => Unit] = Nil + + override def load(sym: Symbol): Unit = { + debugInfo("completing from Java " + sym + "/" + clazz.fullName)//debug + assert(sym == clazz || (module != NoSymbol && (sym == module || sym == module.moduleClass)), sym) + val flags = toScalaClassFlags(jclazz.getModifiers) + clazz setFlag (flags | JAVA) + if (module != NoSymbol) { + module setFlag (flags & PRIVATE | JAVA) + module.moduleClass setFlag (flags & PRIVATE | JAVA) + } + + copyAnnotations(clazz, jclazz) + // to do: annotations to set also for module? + + clazz setInfo new LazyPolyType(jclazz.getTypeParameters.toList map createTypeParameter) + if (module != NoSymbol) { + module setInfo module.moduleClass.tpe + module.moduleClass setInfo new LazyPolyType(List()) + } + } + + override def complete(sym: Symbol): Unit = { + load(sym) + completeRest() + } + + def completeRest(): Unit = self.synchronized { + val tparams = clazz.rawInfo.typeParams + + val parents = try { + parentsLevel += 1 + val jsuperclazz = jclazz.getGenericSuperclass + val superclazz = if (jsuperclazz == null) AnyClass.tpe else typeToScala(jsuperclazz) + superclazz :: (jclazz.getGenericInterfaces.toList map typeToScala) + } finally { + parentsLevel -= 1 + } + clazz setInfo GenPolyType(tparams, new ClassInfoType(parents, newScope, clazz)) + if (module != NoSymbol) { + module.moduleClass setInfo new ClassInfoType(List(), newScope, module.moduleClass) + } + + def enter(sym: Symbol, mods: Int) = + (if (jModifier.isStatic(mods)) module.moduleClass else clazz).info.decls enter sym + + for (jinner <- jclazz.getDeclaredClasses) { + enter(jclassAsScala(jinner, clazz), jinner.getModifiers) + } + + pendingLoadActions = { () => + + for (jfield <- jclazz.getDeclaredFields) + enter(jfieldAsScala(jfield), jfield.getModifiers) + + for (jmeth <- jclazz.getDeclaredMethods) + enter(jmethodAsScala(jmeth), jmeth.getModifiers) + + for (jconstr <- jclazz.getConstructors) + enter(jconstrAsScala(jconstr), jconstr.getModifiers) + + } :: pendingLoadActions + + if (parentsLevel == 0) { + while (!pendingLoadActions.isEmpty) { + val item = pendingLoadActions.head + pendingLoadActions = pendingLoadActions.tail + item() + } + } + } + + class LazyPolyType(override val typeParams: List[Symbol]) extends LazyType { + override def complete(sym: Symbol) { + completeRest() + } + } + } + + /** + * If Java modifiers `mods` contain STATIC, return the module class + * of the companion module of `clazz`, otherwise the class `clazz` itself. + */ + private def followStatic(clazz: Symbol, mods: Int) = + if (jModifier.isStatic(mods)) clazz.companionModule.moduleClass else clazz + + implicit class RichClass(jclazz: jClass[_]) { + // [Eugene++] `jclazz.isLocalClass` doesn't work because of problems with `getSimpleName` + // java.lang.Error: sOwner(class Test$A$1) has failed + // Caused by: java.lang.InternalError: Malformed class name + // at java.lang.Class.getSimpleName(Class.java:1133) + // at java.lang.Class.isAnonymousClass(Class.java:1188) + // at java.lang.Class.isLocalClass(Class.java:1199) + // (see t5256c.scala for more details) + // hence we have to approximate by removing the `isAnonymousClass` check +// def isLocalClass0: Boolean = jclazz.isLocalClass + def isLocalClass0: Boolean = jclazz.getEnclosingMethod != null || jclazz.getEnclosingConstructor != null + } + + // [Eugene++] overflow from Paul's changes made concurrently with reflection refactoring + // https://github.com/scala/scala/commit/90d2bee45b25844f809f8c5300aefcb1bfe9e336 + // + // /** Methods which need to be wrapped because they either are getSimpleName + // * or call getSimpleName: + // * + // * public String getSimpleName() + // * public boolean isAnonymousClass() + // * public boolean isLocalClass() + // * public boolean isMemberClass() + // * public String getCanonicalName() + // * + // * TODO - find all such calls and wrap them. + // * TODO - create mechanism to avoid the recurrence of unwrapped calls. + // */ + // private def wrapClassCheck[T](alt: T)(body: => T): T = + // try body catch { case x: InternalError if x.getMessage == "Malformed class name" => alt } + + // private def wrapIsLocalClass(clazz: jClass[_]): Boolean = + // wrapClassCheck(false)(clazz.isLocalClass) + + // private def wrapGetSimpleName(clazz: jClass[_]): String = + // wrapClassCheck("")(clazz.getSimpleName) + + /** + * The Scala owner of the Scala class corresponding to the Java class `jclazz` + */ + private def sOwner(jclazz: jClass[_]): Symbol = + if (jclazz.isMemberClass) { + val jEnclosingClass = jclazz.getEnclosingClass + val sEnclosingClass = classToScala(jEnclosingClass) + followStatic(sEnclosingClass, jclazz.getModifiers) + } else if (jclazz.isLocalClass0) { + val jEnclosingMethod = jclazz.getEnclosingMethod + if (jEnclosingMethod != null) { + methodToScala(jEnclosingMethod) + } else { + val jEnclosingConstructor = jclazz.getEnclosingConstructor + constructorToScala(jEnclosingConstructor) + } + } else if (jclazz.isPrimitive || jclazz.isArray) { + ScalaPackageClass + } else if (jclazz.getPackage != null) { + val jPackage = jclazz.getPackage + packageToScala(jPackage).moduleClass + } else { + // @eb: a weird classloader might return a null package for something with a non-empty package name + // for example, http://groups.google.com/group/scala-internals/browse_thread/thread/7be09ff8f67a1e5c + // in that case we could invoke packageNameToScala(jPackageName) and, probably, be okay + // however, I think, it's better to blow up, since weirdness of the class loader might bite us elsewhere + // [martin] I think it's better to be forgiving here. Restoring packageNameToScala. + val jPackageName = jclazz.getName take jclazz.getName.lastIndexOf('.') + packageNameToScala(jPackageName).moduleClass + } + + /** + * The Scala owner of the Scala symbol corresponding to the Java member `jmember` + */ + private def sOwner(jmember: jMember): Symbol = { + followStatic(classToScala(jmember.getDeclaringClass), jmember.getModifiers) + } + + /** + * The Scala owner of the Scala type parameter corresponding to the Java type variable `jtvar` + */ + private def sOwner(jtvar: jTypeVariable[_ <: GenericDeclaration]): Symbol = + genericDeclarationToScala(jtvar.getGenericDeclaration) + + /** + * Find declarations or definition in class `clazz` that maps to a Java + * entity with name `jname`. Because of name-mangling, this is more difficult + * than a simple name-based lookup via `decl`. If `decl` fails, members + * that start with the given name are searched instead. + */ + private def lookup(clazz: Symbol, jname: String): Symbol = { + def approximateMatch(sym: Symbol, jstr: String): Boolean = + (sym.name.toString == jstr) || + sym.isPrivate && nme.expandedName(sym.name.toTermName, sym.owner).toString == jstr + + clazz.info.decl(newTermName(jname)) orElse { + (clazz.info.decls.iterator filter (approximateMatch(_, jname))).toList match { + case List() => NoSymbol + case List(sym) => sym + case alts => clazz.newOverloaded(alts.head.tpe.prefix, alts) + } + } + } + + /** + * The Scala method corresponding to given Java method. + * @param jmeth The Java method + * @return A Scala method object that corresponds to `jmeth`. + */ + def methodToScala(jmeth: jMethod): MethodSymbol = + toScala(methodCache, jmeth)(_ methodToScala1 _) + + private def methodToScala1(jmeth: jMethod): MethodSymbol = { + val jOwner = jmeth.getDeclaringClass + val preOwner = classToScala(jOwner) + val owner = followStatic(preOwner, jmeth.getModifiers) + (lookup(owner, jmeth.getName) suchThat (erasesTo(_, jmeth)) orElse jmethodAsScala(jmeth)) + .asMethodSymbol + } + + /** + * The Scala constructor corresponding to given Java constructor. + * @param jconstr The Java constructor + * @return A Scala method object that corresponds to `jconstr`. + */ + def constructorToScala(jconstr: jConstructor[_]): MethodSymbol = + toScala(constructorCache, jconstr)(_ constructorToScala1 _) + + private def constructorToScala1(jconstr: jConstructor[_]): MethodSymbol = { + val owner = followStatic(classToScala(jconstr.getDeclaringClass), jconstr.getModifiers) + (lookup(owner, jconstr.getName) suchThat (erasesTo(_, jconstr)) orElse jconstrAsScala(jconstr)) + .asMethodSymbol + } + + /** + * The Scala field corresponding to given Java field. + * @param jfield The Java field + * @return A Scala field object that corresponds to `jfield`. + * // ??? should we return the getter instead? + */ + def fieldToScala(jfield: jField): TermSymbol = + toScala(fieldCache, jfield)(_ fieldToScala1 _) + + private def fieldToScala1(jfield: jField): TermSymbol = { + val owner = followStatic(classToScala(jfield.getDeclaringClass), jfield.getModifiers) + (lookup(owner, jfield.getName) suchThat (!_.isMethod) orElse jfieldAsScala(jfield)) + .asTermSymbol + } + + /** + * The Scala package corresponding to given Java package + */ + def packageToScala(jpkg: jPackage): ModuleSymbol = packageCache.toScala(jpkg) { + makeScalaPackage(jpkg.getName) + } + + /** + * The Scala package with given fully qualified name. + */ + def packageNameToScala(fullname: String): ModuleSymbol = { + if (fullname == "") EmptyPackage + else { + val jpkg = jPackage.getPackage(fullname) + if (jpkg != null) packageToScala(jpkg) else makeScalaPackage(fullname) + } + } + + /** + * The Scala package with given fully qualified name. Unlike `packageNameToScala`, + * this one bypasses the cache. + */ + private[JavaMirrors] def makeScalaPackage(fullname: String): ModuleSymbol = { + val split = fullname lastIndexOf '.' + val ownerModule: ModuleSymbol = + if (split > 0) packageNameToScala(fullname take split) else this.RootPackage + val owner = ownerModule.moduleClass + val name = newTermName(fullname drop (split + 1)) + val opkg = owner.info decl name + if (opkg.isPackage) + opkg.asModuleSymbol + else if (opkg == NoSymbol) { + val pkg = owner.newPackage(name) + pkg.moduleClass setInfo new LazyPackageType + pkg setInfoAndEnter pkg.moduleClass.tpe + info("made Scala "+pkg) + pkg + } else + throw new ReflectError(opkg+" is not a package") + } + + private def scalaSimpleName(jclazz: jClass[_]): TypeName = { + val owner = sOwner(jclazz) + val enclosingClass = jclazz.getEnclosingClass + var prefix = if (enclosingClass != null) enclosingClass.getName else "" + val isObject = owner.isModuleClass && !owner.isPackageClass + if (isObject && !prefix.endsWith(nme.MODULE_SUFFIX_STRING)) prefix += nme.MODULE_SUFFIX_STRING + assert(jclazz.getName.startsWith(prefix)) + var name = jclazz.getName.substring(prefix.length) + name = name.substring(name.lastIndexOf(".") + 1) + newTypeName(name) + } + + /** + * The Scala class that corresponds to a given Java class. + * @param jclazz The Java class + * @return A Scala class symbol that reflects all elements of the Java class, + * in the form they appear in the Scala pickling info, or, if that is + * not available, wrapped from the Java reflection info. + */ + def classToScala(jclazz: jClass[_]): ClassSymbol = + toScala(classCache, jclazz)(_ classToScala1 _) + + private def classToScala1(jclazz: jClass[_]): ClassSymbol = { + val jname = newTypeName(jclazz.getName) + if (jname == fulltpnme.RuntimeNothing) NothingClass + else if (jname == fulltpnme.RuntimeNull) NullClass + else { + val owner = sOwner(jclazz) + val simpleName = scalaSimpleName(jclazz) + + def lookupClass = { + def coreLookup(name: Name): Symbol = + owner.info.decl(name) orElse { + if (name.startsWith(nme.NAME_JOIN_STRING)) coreLookup(name drop 1) else NoSymbol + } + if (nme.isModuleName(simpleName)) + coreLookup(nme.stripModuleSuffix(simpleName).toTermName) map (_.moduleClass) + else + coreLookup(simpleName) + } + + val cls = + if (jclazz.isMemberClass && !nme.isImplClassName(jname)) + lookupClass + else if (jclazz.isLocalClass0 || isInvalidClassName(jname)) + // local classes and implementation classes not preserved by unpickling - treat as Java + jclassAsScala(jclazz) + else if (jclazz.isArray) + ArrayClass + else + javaTypeToValueClass(jclazz) orElse lookupClass + + assert (cls.isType, + s"""${if (cls == NoSymbol) "not a type: symbol" else "no symbol could be"} + | loaded from $jclazz in $owner with name $simpleName and classloader $classLoader""".stripMargin) + + cls.asClassSymbol + } + } + + /** + * The Scala type parameter that corresponds to a given Java type parameter. + * @param jparam The Java type parameter + * @return A Scala type parameter symbol that has the same owner and name as the Java type parameter + */ + def typeParamToScala(jparam: jTypeVariable[_ <: GenericDeclaration]): TypeSymbol = + toScala(tparamCache, jparam)(_ typeParamToScala1 _) + + private def typeParamToScala1(jparam: jTypeVariable[_ <: GenericDeclaration]): TypeSymbol = { + val owner = genericDeclarationToScala(jparam.getGenericDeclaration) + owner.info match { + case PolyType(tparams, _) => tparams.find(_.name.toString == jparam.getName).get.asTypeSymbol + } + } + + /** + * The Scala symbol that corresponds to a given Java generic declaration (class, method, or constructor) + */ + def genericDeclarationToScala(jdecl: GenericDeclaration): Symbol = jdecl match { + case jclazz: jClass[_] => classToScala(jclazz) + case jmeth: jMethod => methodToScala(jmeth) + case jconstr: jConstructor[_] => constructorToScala(jconstr) + } + + /** + * Given some Java type arguments, a corresponding list of Scala types, plus potentially + * some existentially bound type variables that represent wildcard arguments. + */ + private def targsToScala(owner: Symbol, args: List[jType]): (List[Type], List[TypeSymbol]) = { + val tparams = new ListBuffer[TypeSymbol] + def targToScala(arg: jType): Type = arg match { + case jwild: WildcardType => + val tparam = owner.newExistential(newTypeName("T$" + tparams.length)) + .setInfo(TypeBounds( + lub(jwild.getLowerBounds.toList map typeToScala), + glb(jwild.getUpperBounds.toList map typeToScala map objToAny))) + tparams += tparam + typeRef(NoPrefix, tparam, List()) + case _ => + typeToScala(arg) + } + (args map targToScala, tparams.toList) + } + + /** + * The Scala type that corresponds to given Java type + */ + def typeToScala(jtpe: jType): Type = jtpe match { + case jclazz: jClass[_] => + if (jclazz.isArray) + arrayType(typeToScala(jclazz.getComponentType)) + else { + val clazz = classToScala(jclazz) + rawToExistential(typeRef(clazz.owner.thisType, clazz, List())) + } + case japplied: ParameterizedType => + val (pre, sym) = typeToScala(japplied.getRawType) match { + case ExistentialType(tparams, TypeRef(pre, sym, _)) => (pre, sym) + case TypeRef(pre, sym, _) => (pre, sym) + } + val args0 = japplied.getActualTypeArguments + val (args, bounds) = targsToScala(pre.typeSymbol, args0.toList) + ExistentialType(bounds, typeRef(pre, sym, args)) + case jarr: GenericArrayType => + arrayType(typeToScala(jarr.getGenericComponentType)) + case jtvar: jTypeVariable[_] => + val tparam = typeParamToScala(jtvar) + typeRef(NoPrefix, tparam, List()) + } + + /** + * The Scala class that corresponds to given Java class without taking + * Scala pickling info into account. + * @param jclazz The Java class + * @return A Scala class symbol that wraps all reflection info of `jclazz` + */ + private def jclassAsScala(jclazz: jClass[_]): Symbol = jclassAsScala(jclazz, sOwner(jclazz)) + + private def jclassAsScala(jclazz: jClass[_], owner: Symbol): ClassSymbol = { + val name = scalaSimpleName(jclazz) + val completer = (clazz: Symbol, module: Symbol) => new FromJavaClassCompleter(clazz, module, jclazz) + val (clazz, module) = createClassModule(owner, name, completer) + classCache enter (jclazz, clazz) + clazz + } + + /** + * The Scala field that corresponds to given Java field without taking + * Scala pickling info into account. + * @param jfield The Java field + * @return A Scala value symbol that wraps all reflection info of `jfield` + */ + private def jfieldAsScala(jfield: jField): TermSymbol = + toScala(fieldCache, jfield)(_ jfieldAsScala1 _) + + private def jfieldAsScala1(jfield: jField): TermSymbol = { + val field = sOwner(jfield) + .newValue(newTermName(jfield.getName), NoPosition, toScalaFieldFlags(jfield.getModifiers)) + .setInfo(typeToScala(jfield.getGenericType)) + fieldCache enter (jfield, field) + copyAnnotations(field, jfield) + field + } + + private def setMethType(meth: Symbol, tparams: List[Symbol], paramtpes: List[Type], restpe: Type) = { + meth setInfo GenPolyType(tparams, MethodType(meth.owner.newSyntheticValueParams(paramtpes map objToAny), restpe)) + } + + /** + * The Scala method that corresponds to given Java method without taking + * Scala pickling info into account. + * @param jmeth The Java method + * @return A Scala method symbol that wraps all reflection info of `jmethod` + */ + private def jmethodAsScala(jmeth: jMethod): MethodSymbol = + toScala(methodCache, jmeth)(_ jmethodAsScala1 _) + + private def jmethodAsScala1(jmeth: jMethod): MethodSymbol = { + val clazz = sOwner(jmeth) + val meth = clazz.newMethod(newTermName(jmeth.getName), NoPosition, toScalaMethodFlags(jmeth.getModifiers)) + methodCache enter (jmeth, meth) + val tparams = jmeth.getTypeParameters.toList map createTypeParameter + val paramtpes = jmeth.getGenericParameterTypes.toList map typeToScala + val resulttpe = typeToScala(jmeth.getGenericReturnType) + setMethType(meth, tparams, paramtpes, resulttpe) + copyAnnotations(meth, jmeth) + if ((jmeth.getModifiers & JAVA_ACC_VARARGS) != 0) meth.setInfo(arrayToRepeated(meth.info)) + meth + } + + /** + * The Scala constructor that corresponds to given Java constructor without taking + * Scala pickling info into account. + * @param jconstr The Java constructor + * @return A Scala constructor symbol that wraps all reflection info of `jconstr` + */ + private def jconstrAsScala(jconstr: jConstructor[_]): MethodSymbol = + toScala(constructorCache, jconstr)(_ jconstrAsScala1 _) + + private def jconstrAsScala1(jconstr: jConstructor[_]): MethodSymbol = { + // [Martin] Note: I know there's a lot of duplication wrt jmethodAsScala, but don't think it's worth it to factor this out. + val clazz = sOwner(jconstr) + val constr = clazz.newConstructor(NoPosition, toScalaMethodFlags(jconstr.getModifiers)) + constructorCache enter (jconstr, constr) + val tparams = jconstr.getTypeParameters.toList map createTypeParameter + val paramtpes = jconstr.getGenericParameterTypes.toList map typeToScala + setMethType(constr, tparams, paramtpes, clazz.tpe) + constr setInfo GenPolyType(tparams, MethodType(clazz.newSyntheticValueParams(paramtpes), clazz.tpe)) + copyAnnotations(constr, jconstr) + constr + } + +// -------------------- Scala to Java ----------------------------------- + + /** Optionally, the Java package corresponding to a given Scala package, or None if no such Java package exists. + * @param pkg The Scala package + */ + def packageToJavaOption(pkg: ModuleSymbol): Option[jPackage] = packageCache.toJavaOption(pkg) { + Option(jPackage.getPackage(pkg.fullName.toString)) + } + + /** The Java class corresponding to given Scala class. + * Note: This only works for + * - top-level classes + * - Scala classes that were generated via jclassToScala + * - classes that have a class owner that has a corresponding Java class + * @throws A `ClassNotFoundException` for all Scala classes not in one of these categories. + */ + @throws(classOf[ClassNotFoundException]) + def classToJava(clazz: ClassSymbol): jClass[_] = classCache.toJava(clazz) { + def noClass = throw new ClassNotFoundException("no Java class corresponding to "+clazz+" found") + //println("classToJava "+clazz+" "+clazz.owner+" "+clazz.owner.isPackageClass)//debug + if (clazz.isPrimitiveValueClass) + valueClassToJavaType(clazz) + else if (clazz == ArrayClass) + noClass + else if (clazz.owner.isPackageClass) + javaClass(clazz.javaClassName) + else if (clazz.owner.isClass) + classToJava(clazz.owner.asClassSymbol) + .getDeclaredClasses + .find(_.getSimpleName == clazz.name.toString) + .getOrElse(noClass) + else + noClass + } + + private def expandedName(sym: Symbol): String = + if (sym.isPrivate) nme.expandedName(sym.name.toTermName, sym.owner).toString + else sym.name.toString + + /** The Java field corresponding to a given Scala field. + * @param meth The Scala field. + */ + def fieldToJava(fld: TermSymbol): jField = fieldCache.toJava(fld) { + val jclazz = classToJava(fld.owner.asClassSymbol) + val jname = nme.dropLocalSuffix(fld.name).toString + try jclazz getDeclaredField jname + catch { + case ex: NoSuchFieldException => jclazz getDeclaredField expandedName(fld) + } + } + + /** The Java method corresponding to a given Scala method. + * @param meth The Scala method + */ + def methodToJava(meth: MethodSymbol): jMethod = methodCache.toJava(meth) { + val jclazz = classToJava(meth.owner.asClassSymbol) + val paramClasses = transformedType(meth).paramTypes map typeToJavaClass + val jname = nme.dropLocalSuffix(meth.name).toString + try jclazz getDeclaredMethod (jname, paramClasses: _*) + catch { + case ex: NoSuchMethodException => + jclazz getDeclaredMethod (expandedName(meth), paramClasses: _*) + } + } + + /** The Java constructor corresponding to a given Scala constructor. + * @param constr The Scala constructor + */ + def constructorToJava(constr: MethodSymbol): jConstructor[_] = constructorCache.toJava(constr) { + val jclazz = classToJava(constr.owner.asClassSymbol) + val paramClasses = transformedType(constr).paramTypes map typeToJavaClass + val effectiveParamClasses = + if (!constr.owner.owner.isStaticOwner) jclazz.getEnclosingClass +: paramClasses + else paramClasses + jclazz getConstructor (effectiveParamClasses: _*) + } + + private def jArrayClass(elemClazz: jClass[_]): jClass[_] = { + jArray.newInstance(elemClazz, 0).getClass + } + + /** The Java class that corresponds to given Scala type. + * Pre: Scala type is already transformed to Java level. + */ + def typeToJavaClass(tpe: Type): jClass[_] = tpe match { + case ExistentialType(_, rtpe) => typeToJavaClass(rtpe) + case TypeRef(_, ArrayClass, List(elemtpe)) => jArrayClass(typeToJavaClass(elemtpe)) + case TypeRef(_, sym: ClassSymbol, _) => classToJava(sym.asClassSymbol) + case _ => throw new NoClassDefFoundError("no Java class corresponding to "+tpe+" found") + } + } + + /** Assert that packages have package scopes */ + override def validateClassInfo(tp: ClassInfoType) { + assert(!tp.typeSymbol.isPackageClass || tp.decls.isInstanceOf[PackageScope]) + } + + override def newPackageScope(pkgClass: Symbol) = new PackageScope(pkgClass) + + override def scopeTransform(owner: Symbol)(op: => Scope): Scope = + if (owner.isPackageClass) owner.info.decls else op + + private lazy val rootToLoader = new WeakHashMap[Symbol, ClassLoader] + + override def mirrorThatLoaded(sym: Symbol): Mirror = { + val root = sym.enclosingRootClass + def findLoader = { + val loaders = (mirrors collect { case (cl, ref) if ref.get.get.RootClass == root => cl }) + assert(loaders.nonEmpty, sym) + loaders.head + } + mirrors(rootToLoader getOrElseUpdate(root, findLoader)).get.get + } + + private def byName(sym: Symbol): (Name, Symbol) = sym.name -> sym + + private lazy val phantomTypes: Map[Name, Symbol] = + Map(byName(definitions.AnyRefClass)) ++ (definitions.isPhantomClass map byName) + + /** 1. If `owner` is a package class (but not the empty package) and `name` is a term name, make a new package + * <owner>.<name>, otherwise return NoSymbol. + * Exception: If owner is root and a java class with given name exists, create symbol in empty package instead + * 2. If `owner` is the scala package and `name` designates a phantom class, return + * the corresponding class symbol and enter it into this mirror's ScalaPackage. + */ + override def missingHook(owner: Symbol, name: Name): Symbol = { + if (owner.hasPackageFlag) { + val mirror = mirrorThatLoaded(owner) + // [Eugene++] this makes toolbox tests pass, but it's a mere workaround for SI-5865 +// assert((owner.info decl name) == NoSymbol, s"already exists: $owner . $name") + if (owner.isRootSymbol && mirror.tryJavaClass(name.toString).isDefined) + return mirror.EmptyPackageClass.info decl name + if (name.isTermName && !owner.isEmptyPackageClass) + return mirror.makeScalaPackage( + if (owner.isRootSymbol) name.toString else owner.fullName+"."+name) + if (owner.name.toTermName == nme.scala_ && owner.owner.isRoot) + phantomTypes get name match { + case Some(tsym) => + owner.info.decls enter tsym + return tsym + case None => + } + } + info("*** missing: "+name+"/"+name.isTermName+"/"+owner+"/"+owner.hasPackageFlag+"/"+owner.info.decls.getClass) + super.missingHook(owner, name) + } +} + +class ReflectError(msg: String) extends java.lang.Error(msg) + +class HasJavaClass[J](val getClazz: J => java.lang.Class[_]) diff --git a/src/reflect/scala/reflect/runtime/JavaUniverse.scala b/src/reflect/scala/reflect/runtime/JavaUniverse.scala new file mode 100644 index 0000000000..d4a83b960d --- /dev/null +++ b/src/reflect/scala/reflect/runtime/JavaUniverse.scala @@ -0,0 +1,33 @@ +package scala.reflect +package runtime + +import internal.{SomePhase, NoPhase, Phase, TreeGen} + +/** The universe for standard runtime reflection from Java. + * This type implements all abstract term members in internal.SymbolTable. + */ +class JavaUniverse extends internal.SymbolTable with ReflectSetup with runtime.SymbolTable { self => + + type AbstractFileType = AbstractFile + + def picklerPhase = SomePhase + + type TreeGen = internal.TreeGen + + override type Position = scala.reflect.internal.util.Position + + override val gen = new TreeGen { val global: self.type = self } + + lazy val settings = new Settings + def forInteractive = false + def forScaladoc = false + + def log(msg: => AnyRef): Unit = println(" [] "+msg) + + type TreeCopier = TreeCopierOps + def newStrictTreeCopier: TreeCopier = new StrictTreeCopier + def newLazyTreeCopier: TreeCopier = new LazyTreeCopier + + init() +} + diff --git a/src/reflect/scala/reflect/runtime/ReflectSetup.scala b/src/reflect/scala/reflect/runtime/ReflectSetup.scala new file mode 100644 index 0000000000..6e28fc8520 --- /dev/null +++ b/src/reflect/scala/reflect/runtime/ReflectSetup.scala @@ -0,0 +1,12 @@ +package scala.reflect +package runtime + +import internal.{SomePhase, NoPhase, Phase, TreeGen} + +/** A helper trait to initialize things that need to be set before JavaMirrors and other + * reflect specific traits are initialized */ +private[runtime] trait ReflectSetup extends internal.SymbolTable { + override val phaseWithId: Array[Phase] = Array(NoPhase, SomePhase) + override val currentRunId = 1 // fake a run id so that it is different from NoRunId + phase = SomePhase // set to a phase different from NoPhase +} diff --git a/src/library/scala/reflect/ReflectionUtils.scala b/src/reflect/scala/reflect/runtime/ReflectionUtils.scala index 6ea69cb80d..4e82fe8ad2 100644 --- a/src/library/scala/reflect/ReflectionUtils.scala +++ b/src/reflect/scala/reflect/runtime/ReflectionUtils.scala @@ -3,7 +3,7 @@ * @author Paul Phillips */ -package scala.reflect +package scala.reflect.runtime import java.lang.{Class => jClass} import java.lang.reflect.{ InvocationTargetException, UndeclaredThrowableException } @@ -33,33 +33,29 @@ object ReflectionUtils { System.getProperties.asScala.iterator } - private def searchForBootClasspath = ( + private def inferBootClasspath: String = ( systemProperties find (_._1 endsWith ".boot.class.path") map (_._2) getOrElse "" ) def show(cl: ClassLoader) = { - def inferClasspath(cl: ClassLoader) = cl match { - case cl: java.net.URLClassLoader => "[" + (cl.getURLs mkString ",") + "]" - case _ => "<unknown>" + def inferClasspath(cl: ClassLoader): String = cl match { + case cl: java.net.URLClassLoader => + "[" + (cl.getURLs mkString ",") + "]" + case cl if cl != null && cl.getClass.getName == "scala.tools.nsc.interpreter.AbstractFileClassLoader" => + "[" + cl.asInstanceOf[{val root: scala.reflect.internal.AbstractFileApi}].root + "] and " + inferClasspath(cl.getParent) + case null => + inferBootClasspath + case _ => + "<unknown>" } cl match { case cl if cl != null => "%s of type %s with classpath %s".format(cl, cl.getClass, inferClasspath(cl)) case null => - "primordial classloader with boot classpath [%s]".format(searchForBootClasspath) + "primordial classloader with boot classpath [%s]".format(inferClasspath(cl)) } } - def defaultReflectionClassLoader() = { - // say no to non-determinism of mirror classloaders - // default classloader will be instantiated using current system classloader - // if you wish so, you can rebind it by setting ``mirror.classLoader'' to whatever is necessary -// val cl = Thread.currentThread.getContextClassLoader -// if (cl == null) getClass.getClassLoader else cl -// cl - getClass.getClassLoader - } - def singletonInstance(cl: ClassLoader, className: String): AnyRef = { val name = if (className endsWith "$") className else className + "$" val clazz = java.lang.Class.forName(name, true, cl) diff --git a/src/compiler/scala/reflect/runtime/Settings.scala b/src/reflect/scala/reflect/runtime/Settings.scala index b247797c6c..eedb88320b 100644 --- a/src/compiler/scala/reflect/runtime/Settings.scala +++ b/src/reflect/scala/reflect/runtime/Settings.scala @@ -36,4 +36,5 @@ class Settings extends internal.settings.MutableSettings { val deepCloning = new BooleanSetting (false) val XoldPatmat = new BooleanSetting(false) val XnoPatmatAnalysis = new BooleanSetting(false) + val XfullLubs = new BooleanSetting(false) } diff --git a/src/compiler/scala/reflect/runtime/SymbolLoaders.scala b/src/reflect/scala/reflect/runtime/SymbolLoaders.scala index 7c1cc16152..c1cd5d2911 100644 --- a/src/compiler/scala/reflect/runtime/SymbolLoaders.scala +++ b/src/reflect/scala/reflect/runtime/SymbolLoaders.scala @@ -7,12 +7,6 @@ import collection.mutable trait SymbolLoaders { self: SymbolTable => - /** The lazy type for root. - */ - override val rootLoader = new LazyType { - override def complete(sym: Symbol) = sym setInfo new LazyPackageType - } - /** The standard completer for top-level classes * @param clazz The top-level class * @param module The companion object of `clazz` @@ -35,7 +29,9 @@ trait SymbolLoaders { self: SymbolTable => assert(sym == clazz || sym == module || sym == module.moduleClass) // try { atPhaseNotLaterThan(picklerPhase) { - unpickleClass(clazz, module, javaClass(clazz.javaClassName)) + val loadingMirror = mirrorThatLoaded(sym) + val javaClass = loadingMirror.javaClass(clazz.javaClassName) + loadingMirror.unpickleClass(clazz, module, javaClass) // } catch { // case ex: ClassNotFoundException => makePackage() // case ex: NoClassDefFoundError => makePackage() @@ -65,8 +61,14 @@ trait SymbolLoaders { self: SymbolTable => assert(!(name.toString endsWith "[]"), name) val clazz = owner.newClass(name) val module = owner.newModule(name.toTermName) - owner.info.decls enter clazz - owner.info.decls enter module + // [Eugene++] am I doing this right? + // todo: drop condition, see what goes wrong + // [Eugene++ to Martin] test/files/run/t5256g and test/files/run/t5256h will crash + // reflection meeting verdict: need to enter the symbols into the first symbol in the owner chain that has a non-empty scope + if (owner.info.decls != EmptyScope) { + owner.info.decls enter clazz + owner.info.decls enter module + } initClassModule(clazz, module, completer(clazz, module)) (clazz, module) } @@ -92,7 +94,7 @@ trait SymbolLoaders { self: SymbolTable => /** Is the given name valid for a top-level class? We exclude names with embedded $-signs, because * these are nested classes or anonymous classes, */ - def invalidClassName(name: Name) = { + def isInvalidClassName(name: Name) = { val dp = name pos '$' 0 < dp && dp < (name.length - 1) } @@ -104,20 +106,35 @@ trait SymbolLoaders { self: SymbolTable => val e = super.lookupEntry(name) if (e != null) e - else if (invalidClassName(name) || (negatives contains name)) + else if (isInvalidClassName(name) || (negatives contains name)) null else { val path = if (pkgClass.isEmptyPackageClass) name.toString else pkgClass.fullName + "." + name - if (isJavaClass(path)) { - val (clazz, module) = createClassModule(pkgClass, name.toTypeName, new TopClassCompleter(_, _)) - debugInfo("created "+module+"/"+module.moduleClass+" in "+pkgClass) - lookupEntry(name) - } else { - debugInfo("*** not found : "+path) - negatives += name - null + val currentMirror = mirrorThatLoaded(pkgClass) + currentMirror.tryJavaClass(path) match { + case Some(cls) => + val loadingMirror = currentMirror.mirrorDefining(cls) + val (clazz, module) = + if (loadingMirror eq currentMirror) { + createClassModule(pkgClass, name.toTypeName, new TopClassCompleter(_, _)) + } else { + val origOwner = loadingMirror.packageNameToScala(pkgClass.fullName) + val clazz = origOwner.info decl name.toTypeName + val module = origOwner.info decl name.toTermName + assert(clazz != NoSymbol) + assert(module != NoSymbol) + pkgClass.info.decls enter clazz + pkgClass.info.decls enter module + (clazz, module) + } + debugInfo(s"created $module/${module.moduleClass} in $pkgClass") + lookupEntry(name) + case none => + debugInfo("*** not found : "+path) + negatives += name + null } } } diff --git a/src/compiler/scala/reflect/runtime/SymbolTable.scala b/src/reflect/scala/reflect/runtime/SymbolTable.scala index 64a5894d01..c90665508b 100644 --- a/src/compiler/scala/reflect/runtime/SymbolTable.scala +++ b/src/reflect/scala/reflect/runtime/SymbolTable.scala @@ -3,14 +3,15 @@ package runtime /** * This symbol table trait fills in the definitions so that class information is obtained by refection. - * It can be used either from the reflexive mirror itself (class Mirror), or else from + * It can be used either from a reflexive universe (class scala.reflect.runtime.JavaUniverse), or else from * a runtime compiler that uses reflection to get a class information (class scala.tools.nsc.ReflectGlobal) */ -trait SymbolTable extends internal.SymbolTable with JavaToScala with ScalaToJava with ClassLoaders with SymbolLoaders with SynchronizedOps { +trait SymbolTable extends internal.SymbolTable with JavaMirrors with SymbolLoaders with SynchronizedOps { def info(msg: => String) = if (settings.verbose.value) println("[reflect-compiler] "+msg) def debugInfo(msg: => String) = if (settings.debug.value) info(msg) + } diff --git a/src/compiler/scala/reflect/runtime/SynchronizedOps.scala b/src/reflect/scala/reflect/runtime/SynchronizedOps.scala index 907c0dd369..907c0dd369 100644 --- a/src/compiler/scala/reflect/runtime/SynchronizedOps.scala +++ b/src/reflect/scala/reflect/runtime/SynchronizedOps.scala diff --git a/src/compiler/scala/reflect/runtime/SynchronizedSymbols.scala b/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala index 2322911220..3b28ddf42c 100644 --- a/src/compiler/scala/reflect/runtime/SynchronizedSymbols.scala +++ b/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala @@ -14,11 +14,11 @@ trait SynchronizedSymbols extends internal.Symbols { self: SymbolTable => override def connectModuleToClass(m: ModuleSymbol, moduleClass: ClassSymbol): ModuleSymbol = synchronized { super.connectModuleToClass(m, moduleClass) } - override def newFreeTermSymbol(name: TermName, info: Type, value: => Any, flags: Long = 0L, origin: String = null): FreeTerm = - new FreeTerm(name, value, origin) with SynchronizedTermSymbol initFlags flags setInfo info + override def newFreeTermSymbol(name: TermName, info: Type, value: => Any, flags: Long = 0L, origin: String = null): FreeTermSymbol = + new FreeTermSymbol(name, value, origin) with SynchronizedTermSymbol initFlags flags setInfo info - override def newFreeTypeSymbol(name: TypeName, info: Type, value: => Any, flags: Long = 0L, origin: String = null): FreeType = - new FreeType(name, value, origin) with SynchronizedTypeSymbol initFlags flags setInfo info + override def newFreeTypeSymbol(name: TypeName, info: Type, value: => Any, flags: Long = 0L, origin: String = null): FreeTypeSymbol = + new FreeTypeSymbol(name, value, origin) with SynchronizedTypeSymbol initFlags flags setInfo info override protected def makeNoSymbol: NoSymbol = new NoSymbol with SynchronizedSymbol @@ -92,8 +92,7 @@ trait SynchronizedSymbols extends internal.Symbols { self: SymbolTable => override protected def createModuleSymbol(name: TermName, pos: Position, newFlags: Long): ModuleSymbol = new ModuleSymbol(this, pos, name) with SynchronizedTermSymbol initFlags newFlags - override protected def createPackageSymbol(name: TermName, pos: Position, newFlags: Long): PackageSymbol = - new PackageSymbol(this, pos, name) with SynchronizedTermSymbol initFlags newFlags + override protected def createPackageSymbol(name: TermName, pos: Position, newFlags: Long): ModuleSymbol = createModuleSymbol(name, pos, newFlags) // TODO // override protected def createValueParameterSymbol(name: TermName, pos: Position, newFlags: Long) @@ -133,7 +132,8 @@ trait SynchronizedSymbols extends internal.Symbols { self: SymbolTable => trait SynchronizedModuleClassSymbol extends ModuleClassSymbol with SynchronizedClassSymbol { override def sourceModule = synchronized { super.sourceModule } - override def sourceModule_=(module: Symbol) = synchronized { super.sourceModule_=(module: Symbol) } + // [Eugene++ to Martin] doesn't override anything. no longer necessary? + // def sourceModule_=(module: ModuleSymbol) = synchronized { super.sourceModule_=(module) } override def implicitMembers: List[Symbol] = synchronized { super.implicitMembers } } } diff --git a/src/compiler/scala/reflect/runtime/SynchronizedTypes.scala b/src/reflect/scala/reflect/runtime/SynchronizedTypes.scala index e5a508f802..e1eb7a57fe 100644 --- a/src/compiler/scala/reflect/runtime/SynchronizedTypes.scala +++ b/src/reflect/scala/reflect/runtime/SynchronizedTypes.scala @@ -9,7 +9,8 @@ trait SynchronizedTypes extends internal.Types { self: SymbolTable => // No sharing of map objects: override protected def commonOwnerMap = new CommonOwnerMap - private val uniqueLock = new Object + private object uniqueLock + override def unique[T <: Type](tp: T): T = uniqueLock.synchronized { super.unique(tp) } class SynchronizedUndoLog extends UndoLog { @@ -29,7 +30,7 @@ trait SynchronizedTypes extends internal.Types { self: SymbolTable => override protected def baseTypeOfNonClassTypeRef(tpe: NonClassTypeRef, clazz: Symbol) = synchronized { super.baseTypeOfNonClassTypeRef(tpe, clazz) } - private val subsametypeLock = new Object + private object subsametypeLock override def isSameType(tp1: Type, tp2: Type): Boolean = subsametypeLock.synchronized { super.isSameType(tp1, tp2) } @@ -40,7 +41,7 @@ trait SynchronizedTypes extends internal.Types { self: SymbolTable => override def isSubType(tp1: Type, tp2: Type, depth: Int): Boolean = subsametypeLock.synchronized { super.isSubType(tp1, tp2, depth) } - private val lubglbLock = new Object + private object lubglbLock override def glb(ts: List[Type]): Type = lubglbLock.synchronized { super.glb(ts) } @@ -48,13 +49,13 @@ trait SynchronizedTypes extends internal.Types { self: SymbolTable => override def lub(ts: List[Type]): Type = lubglbLock.synchronized { super.lub(ts) } - private val indentLock = new Object + private object indentLock override protected def explain[T](op: String, p: (Type, T) => Boolean, tp1: Type, arg2: T): Boolean = { indentLock.synchronized { super.explain(op, p, tp1, arg2) } } - private val toStringLock = new Object + private object toStringLock override protected def typeToString(tpe: Type): String = toStringLock.synchronized(super.typeToString(tpe)) @@ -84,4 +85,4 @@ trait SynchronizedTypes extends internal.Types { self: SymbolTable => override protected def defineBaseTypeSeqOfTypeRef(tpe: TypeRef) = tpe.synchronized { super.defineBaseTypeSeqOfTypeRef(tpe) } -}
\ No newline at end of file +} diff --git a/src/reflect/scala/reflect/runtime/TwoWayCache.scala b/src/reflect/scala/reflect/runtime/TwoWayCache.scala new file mode 100644 index 0000000000..c7bfb3435d --- /dev/null +++ b/src/reflect/scala/reflect/runtime/TwoWayCache.scala @@ -0,0 +1,52 @@ +package scala.reflect +package runtime + +/** A cache that maintains a bijection between Java reflection type `J` + * and Scala reflection type `S`. + */ +import collection.mutable.HashMap + +private[runtime] class TwoWayCache[J, S] { + + private val toScalaMap = new HashMap[J, S] + private val toJavaMap = new HashMap[S, J] + + def enter(j: J, s: S) = synchronized { + // debugInfo("cached: "+j+"/"+s) + toScalaMap(j) = s + toJavaMap(s) = j + } + + def toScala(key: J)(body: => S): S = synchronized { + toScalaMap get key match { + case Some(v) => + v + case none => + val result = body + enter(key, result) + result + } + } + + def toJava(key: S)(body: => J): J = synchronized { + toJavaMap get key match { + case Some(v) => + v + case none => + val result = body + enter(result, key) + result + } + } + + def toJavaOption(key: S)(body: => Option[J]): Option[J] = synchronized { + toJavaMap get key match { + case None => + val result = body + for (value <- result) enter(value, key) + result + case some => some + } + } +} + diff --git a/src/reflect/scala/reflect/runtime/package.scala b/src/reflect/scala/reflect/runtime/package.scala new file mode 100644 index 0000000000..a5809a2629 --- /dev/null +++ b/src/reflect/scala/reflect/runtime/package.scala @@ -0,0 +1,26 @@ +package scala.reflect + +import language.experimental.macros + +package object runtime { + + // type is api.JavaUniverse because we only want to expose the `scala.reflect.api.*` subset of reflection + lazy val universe: api.JavaUniverse = new runtime.JavaUniverse + + // [Eugene++ to Martin] removed `mirrorOfLoader`, because one can use `universe.runtimeMirror` instead + + def currentMirror: universe.Mirror = macro Macros.currentMirror +} + +package runtime { + object Macros { + def currentMirror(c: scala.reflect.makro.Context): c.Expr[universe.Mirror] = { + import c.universe._ + val runtimeClass = c.reifyEnclosingRuntimeClass + if (runtimeClass.isEmpty) c.abort(c.enclosingPosition, "call site does not have an enclosing class") + val runtimeUniverse = Select(Select(Select(Ident(newTermName("scala")), newTermName("reflect")), newTermName("runtime")), newTermName("universe")) + val currentMirror = Apply(Select(runtimeUniverse, newTermName("runtimeMirror")), List(Select(runtimeClass, newTermName("getClassLoader")))) + c.Expr[Nothing](currentMirror)(c.TypeTag.Nothing) + } + } +} diff --git a/src/compiler/scala/tools/nsc/io/AbstractFile.scala b/src/reflect/scala/tools/nsc/io/AbstractFile.scala index deb914f806..fd56608fab 100644 --- a/src/compiler/scala/tools/nsc/io/AbstractFile.scala +++ b/src/reflect/scala/tools/nsc/io/AbstractFile.scala @@ -8,9 +8,9 @@ package scala.tools.nsc package io import java.io.{ FileOutputStream, IOException, InputStream, OutputStream, BufferedOutputStream } +import java.io.{ File => JFile } import java.net.URL import scala.collection.mutable.ArrayBuffer -import scala.reflect.api.RequiredFile /** * @author Philippe Altherr @@ -82,7 +82,7 @@ object AbstractFile { * <code>global.settings.encoding.value</code>. * </p> */ -abstract class AbstractFile extends AnyRef with RequiredFile with Iterable[AbstractFile] { +abstract class AbstractFile extends reflect.internal.AbstractFileApi with Iterable[AbstractFile] { /** Returns the name of this abstract file. */ def name: String diff --git a/src/compiler/scala/tools/nsc/io/Directory.scala b/src/reflect/scala/tools/nsc/io/Directory.scala index b4ceba682a..ebd6edc8d8 100644 --- a/src/compiler/scala/tools/nsc/io/Directory.scala +++ b/src/reflect/scala/tools/nsc/io/Directory.scala @@ -9,6 +9,8 @@ package scala.tools.nsc package io +import java.io.{ File => JFile } + object Directory { import scala.util.Properties.{ tmpDir, userHome, userDir } diff --git a/src/compiler/scala/tools/nsc/io/File.scala b/src/reflect/scala/tools/nsc/io/File.scala index 06cb20e4ac..eedf92ef98 100644 --- a/src/compiler/scala/tools/nsc/io/File.scala +++ b/src/reflect/scala/tools/nsc/io/File.scala @@ -13,6 +13,7 @@ package io import java.io.{ FileInputStream, FileOutputStream, BufferedReader, BufferedWriter, InputStreamReader, OutputStreamWriter, BufferedInputStream, BufferedOutputStream, IOException, PrintStream, PrintWriter, Closeable => JCloseable } +import java.io.{ File => JFile } import java.nio.channels.{ Channel, FileChannel } import scala.io.Codec import language.{reflectiveCalls, implicitConversions} diff --git a/src/compiler/scala/tools/nsc/io/FileOperationException.scala b/src/reflect/scala/tools/nsc/io/FileOperationException.scala index f23658efbc..f23658efbc 100644 --- a/src/compiler/scala/tools/nsc/io/FileOperationException.scala +++ b/src/reflect/scala/tools/nsc/io/FileOperationException.scala diff --git a/src/compiler/scala/tools/nsc/io/NoAbstractFile.scala b/src/reflect/scala/tools/nsc/io/NoAbstractFile.scala index 36cf42d7ec..04568b0e2e 100644 --- a/src/compiler/scala/tools/nsc/io/NoAbstractFile.scala +++ b/src/reflect/scala/tools/nsc/io/NoAbstractFile.scala @@ -7,6 +7,7 @@ package scala.tools.nsc package io import java.io.InputStream +import java.io.{ File => JFile } /** A distinguished object so you can avoid both null * and Option. diff --git a/src/compiler/scala/tools/nsc/io/Path.scala b/src/reflect/scala/tools/nsc/io/Path.scala index b8cf15bfcf..984c96dfbb 100644 --- a/src/compiler/scala/tools/nsc/io/Path.scala +++ b/src/reflect/scala/tools/nsc/io/Path.scala @@ -9,6 +9,7 @@ package io import java.io.{ FileInputStream, FileOutputStream, BufferedReader, BufferedWriter, InputStreamReader, OutputStreamWriter, BufferedInputStream, BufferedOutputStream, RandomAccessFile } +import java.io.{ File => JFile } import java.net.{ URI, URL } import scala.util.Random.alphanumeric import language.implicitConversions @@ -42,7 +43,8 @@ object Path { if (i < 0) "" else name.substring(i + 1).toLowerCase } - def isJarOrZip(f: Path, examineFile: Boolean = true) = Jar.isJarOrZip(f, examineFile) + // [Eugene++] I hope that noone relied on this method +// def isJarOrZip(f: Path, examineFile: Boolean = true) = Jar.isJarOrZip(f, examineFile) // not certain these won't be problematic, but looks good so far implicit def string2path(s: String): Path = apply(s) diff --git a/src/compiler/scala/tools/nsc/io/PlainFile.scala b/src/reflect/scala/tools/nsc/io/PlainFile.scala index 21276e8740..21276e8740 100644 --- a/src/compiler/scala/tools/nsc/io/PlainFile.scala +++ b/src/reflect/scala/tools/nsc/io/PlainFile.scala diff --git a/src/compiler/scala/tools/nsc/io/Streamable.scala b/src/reflect/scala/tools/nsc/io/Streamable.scala index 03318674ee..03318674ee 100644 --- a/src/compiler/scala/tools/nsc/io/Streamable.scala +++ b/src/reflect/scala/tools/nsc/io/Streamable.scala diff --git a/src/compiler/scala/tools/nsc/io/VirtualDirectory.scala b/src/reflect/scala/tools/nsc/io/VirtualDirectory.scala index 0bcb2de43f..0bcb2de43f 100644 --- a/src/compiler/scala/tools/nsc/io/VirtualDirectory.scala +++ b/src/reflect/scala/tools/nsc/io/VirtualDirectory.scala diff --git a/src/compiler/scala/tools/nsc/io/VirtualFile.scala b/src/reflect/scala/tools/nsc/io/VirtualFile.scala index 450d86b599..b9a946598c 100644 --- a/src/compiler/scala/tools/nsc/io/VirtualFile.scala +++ b/src/reflect/scala/tools/nsc/io/VirtualFile.scala @@ -8,6 +8,7 @@ package scala.tools.nsc package io import java.io.{ ByteArrayInputStream, ByteArrayOutputStream, InputStream, OutputStream } +import java.io.{ File => JFile } /** This class implements an in-memory file. * diff --git a/src/compiler/scala/tools/nsc/io/ZipArchive.scala b/src/reflect/scala/tools/nsc/io/ZipArchive.scala index 01f3619ba7..766b1fd093 100644 --- a/src/compiler/scala/tools/nsc/io/ZipArchive.scala +++ b/src/reflect/scala/tools/nsc/io/ZipArchive.scala @@ -8,6 +8,7 @@ package io import java.net.URL import java.io.{ IOException, InputStream, ByteArrayInputStream } +import java.io.{ File => JFile } import java.util.zip.{ ZipEntry, ZipFile, ZipInputStream } import scala.collection.{ immutable, mutable } import annotation.tailrec diff --git a/src/scalacheck/org/scalacheck/Arbitrary.scala b/src/scalacheck/org/scalacheck/Arbitrary.scala index 9bb235f917..28e116b479 100644 --- a/src/scalacheck/org/scalacheck/Arbitrary.scala +++ b/src/scalacheck/org/scalacheck/Arbitrary.scala @@ -10,6 +10,7 @@ package org.scalacheck import util.{FreqMap,Buildable} +import scala.reflect.ClassTag sealed abstract class Arbitrary[T] { val arbitrary: Gen[T] diff --git a/src/scalacheck/org/scalacheck/util/Buildable.scala b/src/scalacheck/org/scalacheck/util/Buildable.scala index 662bc6146b..5c960c3ba8 100644 --- a/src/scalacheck/org/scalacheck/util/Buildable.scala +++ b/src/scalacheck/org/scalacheck/util/Buildable.scala @@ -10,6 +10,7 @@ package org.scalacheck.util import scala.collection._ +import scala.reflect.ClassTag trait Buildable[T,C[_]] { def builder: mutable.Builder[T,C[T]] |