diff options
Diffstat (limited to 'src')
188 files changed, 8999 insertions, 6401 deletions
diff --git a/src/compiler/scala/reflect/api/JavaUniverse.scala b/src/compiler/scala/reflect/api/JavaUniverse.scala new file mode 100644 index 0000000000..8bf62a357c --- /dev/null +++ b/src/compiler/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/compiler/scala/reflect/api/TagInterop.scala b/src/compiler/scala/reflect/api/TagInterop.scala new file mode 100644 index 0000000000..a5b303bb37 --- /dev/null +++ b/src/compiler/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 concreteTypeTagToManifest[T: ClassTag](mirror0: Any, tag: base.Universe # ConcreteTypeTag[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 erasure = mirror.runtimeClass(tag.in(mirror).tpe) + Manifest.classType(erasure).asInstanceOf[Manifest[T]] + } + + override def manifestToConcreteTypeTag[T](mirror0: Any, manifest: Manifest[T]): base.Universe # ConcreteTypeTag[T] = + ConcreteTypeTag(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.reflectClass(manifest.erasure).symbol + val tpe = + if (manifest.typeArguments.isEmpty) sym.asType + else ju.appliedType(sym.asTypeConstructor, manifest.typeArguments map (targ => ju.manifestToConcreteTypeTag(jm, targ)) map (_.in(jm).tpe)) + tpe.asInstanceOf[U # Type] + case u => + u.manifestToConcreteTypeTag(mirror.asInstanceOf[u.Mirror], manifest).in(mirror).tpe + } + } + }) +} diff --git a/src/library/scala/reflect/api/RequiredFile.scala b/src/compiler/scala/reflect/internal/AbstractFileApi.scala index 4a54595940..9f37f4536f 100644 --- a/src/library/scala/reflect/api/RequiredFile.scala +++ b/src/compiler/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/AnnotationInfos.scala b/src/compiler/scala/reflect/internal/AnnotationInfos.scala index 91e1c3d50d..c283ae408e 100644 --- a/src/compiler/scala/reflect/internal/AnnotationInfos.scala +++ b/src/compiler/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/BuildUtils.scala b/src/compiler/scala/reflect/internal/BuildUtils.scala new file mode 100644 index 0000000000..3bde57ded8 --- /dev/null +++ b/src/compiler/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/Constants.scala b/src/compiler/scala/reflect/internal/Constants.scala index 861bc870a7..820dfe0868 100644 --- a/src/compiler/scala/reflect/internal/Constants.scala +++ b/src/compiler/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/compiler/scala/reflect/internal/Definitions.scala index 6141cc184d..b3a651563e 100644 --- a/src/compiler/scala/reflect/internal/Definitions.scala +++ b/src/compiler/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,21 @@ 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 - - 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 +190,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 +234,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 +246,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 +268,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 +283,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 +301,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 +320,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,40 +410,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 ApiUniverseClass = requiredClass[scala.reflect.api.Universe] - def ApiUniverseReify = getMemberMethod(ApiUniverseClass, nme.reify) + 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] @@ -496,38 +449,39 @@ 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 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 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 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_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) @@ -536,18 +490,13 @@ trait Definitions extends reflect.api.StandardDefinitions { 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 # TypeTag[_]): Type = tt.in(rootMirror).tpe + def compilerSymbolFromTag(tt: BaseUniverse # TypeTag[_]): Symbol = tt.in(rootMirror).tpe.typeSymbol // The given symbol represents either String.+ or StringAdd.+ def isStringAddition(sym: Symbol) = sym == String_+ || sym == StringAdd_+ @@ -569,20 +518,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) @@ -610,7 +560,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 @@ -658,8 +608,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) @@ -675,7 +625,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) @@ -746,9 +696,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)] = _ @@ -787,7 +737,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) @@ -887,14 +837,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[_]] @@ -902,9 +852,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] @@ -912,13 +862,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] @@ -969,7 +919,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") @@ -988,99 +938,27 @@ 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) - } - - 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 } - 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 @@ -1100,22 +978,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") } } @@ -1135,34 +1072,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 @@ -1221,7 +1130,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 { @@ -1250,28 +1159,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. */ @@ -1285,17 +1173,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, @@ -1334,7 +1211,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/FlagSets.scala b/src/compiler/scala/reflect/internal/FlagSets.scala new file mode 100644 index 0000000000..0354d2513c --- /dev/null +++ b/src/compiler/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/compiler/scala/reflect/internal/Flags.scala index e6820cf78a..37e5a23819 100644 --- a/src/compiler/scala/reflect/internal/Flags.scala +++ b/src/compiler/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/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/HasFlags.scala b/src/compiler/scala/reflect/internal/HasFlags.scala index 0937577ca3..c7c0882209 100644 --- a/src/compiler/scala/reflect/internal/HasFlags.scala +++ b/src/compiler/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/compiler/scala/reflect/internal/Importers.scala index 6d6a0ec317..72b6288d87 100644 --- a/src/compiler/scala/reflect/internal/Importers.scala +++ b/src/compiler/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) } diff --git a/src/compiler/scala/reflect/internal/Mirrors.scala b/src/compiler/scala/reflect/internal/Mirrors.scala new file mode 100644 index 0000000000..fa411bc935 --- /dev/null +++ b/src/compiler/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].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 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/Names.scala b/src/compiler/scala/reflect/internal/Names.scala index 17924f0c0c..18671871ae 100644 --- a/src/compiler/scala/reflect/internal/Names.scala +++ b/src/compiler/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/Positions.scala b/src/compiler/scala/reflect/internal/Positions.scala index 5ec2659098..bbd8880e35 100644 --- a/src/compiler/scala/reflect/internal/Positions.scala +++ b/src/compiler/scala/reflect/internal/Positions.scala @@ -5,6 +5,7 @@ trait Positions extends api.Positions { self: SymbolTable => type Position = scala.tools.nsc.util.Position val NoPosition = scala.tools.nsc.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/compiler/scala/reflect/internal/Required.scala index 6d146354a3..abbe8fbfb7 100644 --- a/src/compiler/scala/reflect/internal/Required.scala +++ b/src/compiler/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/compiler/scala/reflect/internal/Scopes.scala index 36e8ebb212..ceacd2afb0 100644 --- a/src/compiler/scala/reflect/internal/Scopes.scala +++ b/src/compiler/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/compiler/scala/reflect/internal/StdAttachments.scala b/src/compiler/scala/reflect/internal/StdAttachments.scala index ae2ad87deb..33e3eb03b7 100644 --- a/src/compiler/scala/reflect/internal/StdAttachments.scala +++ b/src/compiler/scala/reflect/internal/StdAttachments.scala @@ -7,4 +7,6 @@ trait StdAttachments { self: SymbolTable => case class ReifyAttachment(original: Symbol) + + case object BackquotedIdentifierAttachment }
\ No newline at end of file diff --git a/src/compiler/scala/reflect/internal/StdCreators.scala b/src/compiler/scala/reflect/internal/StdCreators.scala new file mode 100644 index 0000000000..3e6b7c1ab4 --- /dev/null +++ b/src/compiler/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/compiler/scala/reflect/internal/StdNames.scala index 14d42387f7..e166994b98 100644 --- a/src/compiler/scala/reflect/internal/StdNames.scala +++ b/src/compiler/scala/reflect/internal/StdNames.scala @@ -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,15 +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 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 String: NameType = "String" + final val Expr: NameType = "Expr" + final val String: NameType = "String" // fictions we use as both types and terms final val ERROR: NameType = "<error>" @@ -201,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) @@ -215,7 +216,8 @@ trait StdNames { 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" @@ -229,9 +231,10 @@ trait StdNames { 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" @@ -263,7 +266,7 @@ trait StdNames { 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,6 +293,7 @@ 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" @@ -306,6 +310,7 @@ trait StdNames { 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 +516,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 +570,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 +589,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,6 +604,7 @@ 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" @@ -582,12 +617,19 @@ trait StdNames { 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" @@ -596,6 +638,7 @@ trait StdNames { 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" @@ -617,6 +660,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 +671,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" @@ -650,7 +696,6 @@ trait StdNames { val materializeArrayTag: NameType = "materializeArrayTag" val materializeClassTag: NameType = "materializeClassTag" val materializeConcreteTypeTag: NameType = "materializeConcreteTypeTag" - val materializeErasureTag: NameType= "materializeErasureTag" val materializeTypeTag: NameType = "materializeTypeTag" val mirror : NameType = "mirror" val moduleClass : NameType = "moduleClass" @@ -679,8 +724,10 @@ 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 runtimeMirror: NameType = "runtimeMirror" val sameElements: NameType = "sameElements" val scala_ : NameType = "scala" val selectDynamic: NameType = "selectDynamic" @@ -693,13 +740,15 @@ 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 thisModuleType : NameType = "thisModuleType" + val thisPrefix : NameType = "thisPrefix" val throw_ : NameType = "throw" val toArray: NameType = "toArray" val toList: NameType = "toList" @@ -713,6 +762,7 @@ trait StdNames { 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 +807,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 +876,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 +925,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 +1024,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 +1053,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 +1143,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 +1182,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/compiler/scala/reflect/internal/SymbolTable.scala index ddd6c43031..cf6db7d438 100644 --- a/src/compiler/scala/reflect/internal/SymbolTable.scala +++ b/src/compiler/scala/reflect/internal/SymbolTable.scala @@ -10,15 +10,16 @@ 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 +34,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 +114,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 +302,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 +327,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/compiler/scala/reflect/internal/Symbols.scala index b32b955631..7305cdaf16 100644 --- a/src/compiler/scala/reflect/internal/Symbols.scala +++ b/src/compiler/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 @@ -916,7 +889,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 +949,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 +1076,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 +1130,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 +1308,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 +1343,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 +1351,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 +1500,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 +1587,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. */ @@ -1766,15 +1736,30 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** 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 @@ -2167,8 +2152,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 +2312,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 +2320,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 +2334,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 +2479,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 +2489,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 +2507,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 +2517,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 +2544,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 +2572,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 +2579,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 +2714,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 +2786,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 +2930,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 +3026,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 +3079,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/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/TreeGen.scala b/src/compiler/scala/reflect/internal/TreeGen.scala index f2f9842595..c3a6fce164 100644 --- a/src/compiler/scala/reflect/internal/TreeGen.scala +++ b/src/compiler/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/compiler/scala/reflect/internal/TreeInfo.scala index 1528061adb..fc6e31ce1b 100644 --- a/src/compiler/scala/reflect/internal/TreeInfo.scala +++ b/src/compiler/scala/reflect/internal/TreeInfo.scala @@ -587,25 +587,7 @@ abstract class TreeInfo { 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 => + case Select(splicee, _) if tree.symbol == ExprSplice => Some(splicee) case _ => None @@ -634,7 +616,7 @@ abstract class TreeInfo { 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 => + case select @ Select(ReifiedTree(splicee, symbolTable, tree, tpe), _) if select.symbol == ExprSplice => Some(splicee, symbolTable, tree, tpe, select.symbol) case _ => None @@ -643,7 +625,7 @@ abstract class TreeInfo { 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 => + case Select(ReifiedTree(splicee, symbolTable, tree, tpe), name) if name == nme.tree => Some(splicee, symbolTable, tree, tpe) case _ => None @@ -661,7 +643,7 @@ abstract class TreeInfo { object InlinedTypeSplice { def unapply(tree: Tree): Option[(Tree, List[Tree], Tree)] = tree match { - case Select(ReifiedType(splicee, symbolTable, tpe), name) if name == TypeTagTpe.name => + case Select(ReifiedType(splicee, symbolTable, tpe), name) if name == nme.tpe => Some(splicee, symbolTable, tpe) case _ => None @@ -680,11 +662,9 @@ abstract class TreeInfo { } 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 => + if mrRef.name == nme.MIRROR_SHORT && newFreeTerm == nme.newFreeTerm => Some(mrRef, name, binding, flags, origin) case _ => None @@ -692,12 +672,9 @@ abstract class TreeInfo { } 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) => + if mrRef1.name == nme.MIRROR_SHORT && (newFreeType == nme.newFreeType || newFreeType == nme.newFreeExistential) => 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 => diff --git a/src/compiler/scala/reflect/internal/TreePrinters.scala b/src/compiler/scala/reflect/internal/TreePrinters.scala index e5a98c6b4e..6d035c8b9d 100644 --- a/src/compiler/scala/reflect/internal/TreePrinters.scala +++ b/src/compiler/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 @@ -169,7 +171,7 @@ trait TreePrinters extends api.TreePrinters { self: SymbolTable => } def printAnnotations(tree: Tree) { - if (inReflexiveMirror && tree.symbol != null && tree.symbol != NoSymbol) + 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 @@ -453,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/compiler/scala/reflect/internal/Trees.scala b/src/compiler/scala/reflect/internal/Trees.scala index 3e7f23800c..11d0790100 100644 --- a/src/compiler/scala/reflect/internal/Trees.scala +++ b/src/compiler/scala/reflect/internal/Trees.scala @@ -7,10 +7,808 @@ package scala.reflect package internal import Flags._ -import api.Modifier +import base.Attachments +import collection.mutable.{ListBuffer, LinkedHashSet} trait Trees extends api.Trees { self: SymbolTable => + private[scala] var nodeCount = 0 + + abstract class Tree extends TreeContextApiImpl with Product { + val id = nodeCount // TODO: add to attachment? + nodeCount += 1 + + @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 } + + 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 = _ + @inline final def tpe = rawtpe + def tpe_=(t: Type) = rawtpe = t + def setType(tp: Type): this.type = { rawtpe = tp; this } + def defineType(tp: Type): this.type = setType(tp) + + 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 + + /** 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 + } + + 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] + } + + 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 + } + + 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 + } + + override def find(p: Tree => Boolean): Option[Tree] = { + val ft = new FindTreeTraverser(p) + ft.traverse(this) + ft.result + } + + override def exists(p: Tree => Boolean): Boolean = !find(p).isEmpty + + override def forAll(p: Tree => Boolean): Boolean = find(!p(_)).isEmpty + + override def equalsStructure(that : Tree) = correspondsStructure(that)(_ eq _) + + 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 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 correspondsStructure y.original)(f) + case _ => + true + } + + (productIterator zip that.productIterator forall { case (x, y) => equals0(x, y) }) && compareOriginals() + }) + + override def children: List[Tree] = { + def subtrees(x: Any): List[Tree] = x match { + case EmptyTree => Nil + case t: Tree => List(t) + case xs: List[_] => xs flatMap subtrees + case _ => Nil + } + productIterator.toList flatMap subtrees + } + + 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 modifyType(f: Type => Type): Tree = + if (tpe eq null) this + else this setType f(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(this) + } + + 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 "" + ) + } + } + + trait TermTree extends Tree with TermTreeApi + + trait TypTree extends Tree with TypTreeApi + + trait SymTree extends Tree with SymTreeContextApi { + override def hasSymbol = true + override var symbol: Symbol = NoSymbol + } + + trait NameTree extends Tree with NameTreeApi { + def name: Name + } + + trait RefTree extends SymTree with NameTree with RefTreeApi { + def qualifier: Tree // empty for Idents + def name: Name + } + + abstract class DefTree extends SymTree with NameTree with DefTreeApi { + def name: Name + override def isDef = true + } + + 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 + } + + abstract class MemberDef extends DefTree with MemberDefApi { + def mods: Modifiers + def keyword: String = this match { + case TypeDef(_, _, _, _) => "type" + case ClassDef(mods, _, _, _) => if (mods hasFlag TRAIT) "trait" else "class" + case DefDef(_, _, _, _, _, _) => "def" + case ModuleDef(_, _, _) => "object" + case PackageDef(_, _) => "package" + case ValDef(mods, _, _, _) => if (mods hasFlag MUTABLE) "var" else "val" + case _ => "" + } + } + + case class PackageDef(pid: RefTree, stats: List[Tree]) + extends MemberDef with PackageDefApi { + def name = pid.name + def mods = NoMods + } + object PackageDef extends PackageDefExtractor + + abstract class ImplDef extends MemberDef with ImplDefApi { + def impl: Template + } + + case class ClassDef(mods: Modifiers, name: TypeName, tparams: List[TypeDef], impl: Template) + extends ImplDef with ClassDefApi + object ClassDef extends ClassDefExtractor + + case class ModuleDef(mods: Modifiers, name: TermName, impl: Template) + extends ImplDef with ModuleDefApi + object ModuleDef extends ModuleDefExtractor + + abstract class ValOrDefDef extends MemberDef with ValOrDefDefApi { + def name: Name + def tpt: Tree + def rhs: Tree + } + + case class ValDef(mods: Modifiers, name: TermName, tpt: Tree, rhs: Tree) extends ValOrDefDef with ValDefApi + object ValDef extends ValDefExtractor + + case class DefDef(mods: Modifiers, name: Name, tparams: List[TypeDef], + vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree) extends ValOrDefDef with DefDefApi + object DefDef extends DefDefExtractor + + case class TypeDef(mods: Modifiers, name: TypeName, tparams: List[TypeDef], rhs: Tree) + extends MemberDef with TypeDefApi + object TypeDef extends TypeDefExtractor + + case class LabelDef(name: TermName, params: List[Ident], rhs: Tree) + 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 + + case class Import(expr: Tree, selectors: List[ImportSelector]) + extends SymTree with ImportApi + object Import extends ImportExtractor + + case class Template(parents: List[Tree], self: ValDef, body: List[Tree]) + extends SymTree with TemplateApi + object Template extends TemplateExtractor + + case class Block(stats: List[Tree], expr: Tree) + extends TermTree with BlockApi + object Block extends BlockExtractor + + case class CaseDef(pat: Tree, guard: Tree, body: Tree) + extends Tree with CaseDefApi + object CaseDef extends CaseDefExtractor + + case class Alternative(trees: List[Tree]) + extends TermTree with AlternativeApi + object Alternative extends AlternativeExtractor + + case class Star(elem: Tree) + extends TermTree with StarApi + object Star extends StarExtractor + + case class Bind(name: Name, body: Tree) + extends DefTree with BindApi + object Bind extends BindExtractor + + case class UnApply(fun: Tree, args: List[Tree]) + extends TermTree with UnApplyApi + object UnApply extends UnApplyExtractor + + case class ArrayValue(elemtpt: Tree, elems: List[Tree]) + extends TermTree with ArrayValueApi + object ArrayValue extends ArrayValueExtractor + + case class Function(vparams: List[ValDef], body: Tree) + extends TermTree with SymTree with FunctionApi + object Function extends FunctionExtractor + + case class Assign(lhs: Tree, rhs: Tree) + extends TermTree with AssignApi + object Assign extends AssignExtractor + + case class AssignOrNamedArg(lhs: Tree, rhs: Tree) + extends TermTree with AssignOrNamedArgApi + object AssignOrNamedArg extends AssignOrNamedArgExtractor + + case class If(cond: Tree, thenp: Tree, elsep: Tree) + extends TermTree with IfApi + object If extends IfExtractor + + case class Match(selector: Tree, cases: List[CaseDef]) + extends TermTree with MatchApi + object Match extends MatchExtractor + + case class Return(expr: Tree) + extends TermTree with SymTree with ReturnApi + object Return extends ReturnExtractor + + case class Try(block: Tree, catches: List[CaseDef], finalizer: Tree) + extends TermTree with TryApi + object Try extends TryExtractor + + case class Throw(expr: Tree) + extends TermTree with ThrowApi + object Throw extends ThrowExtractor + + case class New(tpt: Tree) extends TermTree with NewApi + object New extends NewExtractor + + case class Typed(expr: Tree, tpt: Tree) + extends TermTree with TypedApi + object Typed extends TypedExtractor + + abstract class GenericApply extends TermTree with GenericApplyApi { + val fun: Tree + val args: List[Tree] + } + + case class TypeApply(fun: Tree, args: List[Tree]) + extends GenericApply with TypeApplyApi { + override def symbol: Symbol = fun.symbol + override def symbol_=(sym: Symbol) { fun.symbol = sym } + } + object TypeApply extends TypeApplyExtractor + + case class Apply(fun: Tree, args: List[Tree]) + extends GenericApply with ApplyApi { + override def symbol: Symbol = fun.symbol + override def symbol_=(sym: Symbol) { fun.symbol = sym } + } + 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 + class ApplyToImplicitArgs(fun: Tree, args: List[Tree]) extends Apply(fun, args) + + // 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 + class ApplyImplicitView(fun: Tree, args: List[Tree]) extends Apply(fun, args) + + def ApplyConstructor(tpt: Tree, args: List[Tree]) = Apply(Select(New(tpt), nme.CONSTRUCTOR), args) + + case class ApplyDynamic(qual: Tree, args: List[Tree]) + extends TermTree with SymTree with ApplyDynamicApi + object ApplyDynamic extends ApplyDynamicExtractor + + 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 + + case class This(qual: TypeName) + extends TermTree with SymTree with ThisApi + object This extends ThisExtractor + + case class Select(qualifier: Tree, name: Name) + extends RefTree with SelectApi + object Select extends SelectExtractor + + case class Ident(name: Name) extends RefTree with IdentContextApi { + def qualifier: Tree = EmptyTree + def isBackquoted = this.attachments.get[BackquotedIdentifierAttachment.type].isDefined + } + object Ident extends IdentExtractor + + 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 + + case class Literal(value: Constant) + 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)) + + case class Annotated(annot: Tree, arg: Tree) extends Tree with AnnotatedApi + object Annotated extends AnnotatedExtractor + + case class SingletonTypeTree(ref: Tree) + extends TypTree with SingletonTypeTreeApi + object SingletonTypeTree extends SingletonTypeTreeExtractor + + case class SelectFromTypeTree(qualifier: Tree, name: TypeName) + extends TypTree with RefTree with SelectFromTypeTreeApi + object SelectFromTypeTree extends SelectFromTypeTreeExtractor + + case class CompoundTypeTree(templ: Template) + extends TypTree with CompoundTypeTreeApi + object CompoundTypeTree extends CompoundTypeTreeExtractor + + case class AppliedTypeTree(tpt: Tree, args: List[Tree]) + 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 with TypeBoundsTreeApi + object TypeBoundsTree extends TypeBoundsTreeExtractor + + case class ExistentialTypeTree(tpt: Tree, whereClauses: List[Tree]) + 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 + + override def symbol = if (tpe == null) null else tpe.typeSymbol + override def isEmpty = (tpe eq null) || tpe == NoType + + def original: Tree = orig + def setOriginal(tree: Tree): this.type = { + def followOriginal(t: Tree): Tree = t match { + case tt: TypeTree => followOriginal(tt.original) + case t => t + } + + orig = followOriginal(tree); setPos(tree.pos); + this + } + + override def defineType(tp: Type): this.type = { + wasEmpty = isEmpty + setType(tp) + } + } + object TypeTree extends TypeTreeExtractor + + def TypeTree(tp: Type): TypeTree = TypeTree() setType tp + + 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) + def PackageDef(tree: Tree, pid: RefTree, stats: List[Tree]) = + new PackageDef(pid, stats).copyAttrs(tree) + def ModuleDef(tree: Tree, mods: Modifiers, name: Name, impl: Template) = + new ModuleDef(mods, name.toTermName, impl).copyAttrs(tree) + def ValDef(tree: Tree, mods: Modifiers, name: Name, tpt: Tree, rhs: Tree) = + new ValDef(mods, name.toTermName, tpt, rhs).copyAttrs(tree) + def DefDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree) = + new DefDef(mods, name.toTermName, tparams, vparamss, tpt, rhs).copyAttrs(tree) + def TypeDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], rhs: Tree) = + new TypeDef(mods, name.toTypeName, tparams, rhs).copyAttrs(tree) + def LabelDef(tree: Tree, name: Name, params: List[Ident], rhs: Tree) = + new LabelDef(name.toTermName, params, rhs).copyAttrs(tree) + def Import(tree: Tree, expr: Tree, selectors: List[ImportSelector]) = + new Import(expr, selectors).copyAttrs(tree) + def Template(tree: Tree, parents: List[Tree], self: ValDef, body: List[Tree]) = + new Template(parents, self, body).copyAttrs(tree) + def Block(tree: Tree, stats: List[Tree], expr: Tree) = + new Block(stats, expr).copyAttrs(tree) + def CaseDef(tree: Tree, pat: Tree, guard: Tree, body: Tree) = + new CaseDef(pat, guard, body).copyAttrs(tree) + def Alternative(tree: Tree, trees: List[Tree]) = + new Alternative(trees).copyAttrs(tree) + def Star(tree: Tree, elem: Tree) = + new Star(elem).copyAttrs(tree) + def Bind(tree: Tree, name: Name, body: Tree) = + new Bind(name, body).copyAttrs(tree) + def UnApply(tree: Tree, fun: Tree, args: List[Tree]) = + new UnApply(fun, args).copyAttrs(tree) + def ArrayValue(tree: Tree, elemtpt: Tree, trees: List[Tree]) = + new ArrayValue(elemtpt, trees).copyAttrs(tree) + def Function(tree: Tree, vparams: List[ValDef], body: Tree) = + new Function(vparams, body).copyAttrs(tree) + def Assign(tree: Tree, lhs: Tree, rhs: Tree) = + new Assign(lhs, rhs).copyAttrs(tree) + def AssignOrNamedArg(tree: Tree, lhs: Tree, rhs: Tree) = + new AssignOrNamedArg(lhs, rhs).copyAttrs(tree) + def If(tree: Tree, cond: Tree, thenp: Tree, elsep: Tree) = + new If(cond, thenp, elsep).copyAttrs(tree) + def Match(tree: Tree, selector: Tree, cases: List[CaseDef]) = + new Match(selector, cases).copyAttrs(tree) + def Return(tree: Tree, expr: Tree) = + new Return(expr).copyAttrs(tree) + def Try(tree: Tree, block: Tree, catches: List[CaseDef], finalizer: Tree) = + new Try(block, catches, finalizer).copyAttrs(tree) + def Throw(tree: Tree, expr: Tree) = + new Throw(expr).copyAttrs(tree) + def New(tree: Tree, tpt: Tree) = + new New(tpt).copyAttrs(tree) + def Typed(tree: Tree, expr: Tree, tpt: Tree) = + new Typed(expr, tpt).copyAttrs(tree) + def TypeApply(tree: Tree, fun: Tree, args: List[Tree]) = + new TypeApply(fun, args).copyAttrs(tree) + def Apply(tree: Tree, fun: Tree, args: List[Tree]) = + (tree match { // TODO: use a tree attachment to track whether this is an apply to implicit args or a view + case _: ApplyToImplicitArgs => new ApplyToImplicitArgs(fun, args) + case _: ApplyImplicitView => new ApplyImplicitView(fun, args) + // TODO: ApplyConstructor ??? + case _ => new Apply(fun, args) + }).copyAttrs(tree) + def ApplyDynamic(tree: Tree, qual: Tree, args: List[Tree]) = + new ApplyDynamic(qual, args).copyAttrs(tree) + def Super(tree: Tree, qual: Tree, mix: TypeName) = + new Super(qual, mix).copyAttrs(tree) + def This(tree: Tree, qual: Name) = + 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) = + new Ident(name) copyAttrs tree + def ReferenceToBoxed(tree: Tree, idt: Ident) = + new ReferenceToBoxed(idt).copyAttrs(tree) + def Literal(tree: Tree, value: Constant) = + new Literal(value).copyAttrs(tree) + def TypeTree(tree: Tree) = + new TypeTree().copyAttrs(tree) + def Annotated(tree: Tree, annot: Tree, arg: Tree) = + new Annotated(annot, arg).copyAttrs(tree) + def SingletonTypeTree(tree: Tree, ref: Tree) = + new SingletonTypeTree(ref).copyAttrs(tree) + def SelectFromTypeTree(tree: Tree, qualifier: Tree, selector: Name) = + new SelectFromTypeTree(qualifier, selector.toTypeName).copyAttrs(tree) + def CompoundTypeTree(tree: Tree, templ: Template) = + new CompoundTypeTree(templ).copyAttrs(tree) + def AppliedTypeTree(tree: Tree, tpt: Tree, args: List[Tree]) = + new AppliedTypeTree(tpt, args).copyAttrs(tree) + def TypeBoundsTree(tree: Tree, lo: Tree, hi: Tree) = + new TypeBoundsTree(lo, hi).copyAttrs(tree) + def ExistentialTypeTree(tree: Tree, tpt: Tree, whereClauses: List[Tree]) = + new ExistentialTypeTree(tpt, whereClauses).copyAttrs(tree) + } + + class LazyTreeCopier extends TreeCopierOps { + val treeCopy: TreeCopier = newStrictTreeCopier + def ClassDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], impl: Template) = tree match { + case t @ ClassDef(mods0, name0, tparams0, impl0) + if (mods0 == mods) && (name0 == name) && (tparams0 == tparams) && (impl0 == impl) => t + case _ => treeCopy.ClassDef(tree, mods, name, tparams, impl) + } + def PackageDef(tree: Tree, pid: RefTree, stats: List[Tree]) = tree match { + case t @ PackageDef(pid0, stats0) + if (pid0 == pid) && (stats0 == stats) => t + case _ => treeCopy.PackageDef(tree, pid, stats) + } + def ModuleDef(tree: Tree, mods: Modifiers, name: Name, impl: Template) = tree match { + case t @ ModuleDef(mods0, name0, impl0) + if (mods0 == mods) && (name0 == name) && (impl0 == impl) => t + case _ => treeCopy.ModuleDef(tree, mods, name, impl) + } + def ValDef(tree: Tree, mods: Modifiers, name: Name, tpt: Tree, rhs: Tree) = tree match { + case t @ ValDef(mods0, name0, tpt0, rhs0) + if (mods0 == mods) && (name0 == name) && (tpt0 == tpt) && (rhs0 == rhs) => t + case _ => treeCopy.ValDef(tree, mods, name, tpt, rhs) + } + def DefDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree) = tree match { + case t @ DefDef(mods0, name0, tparams0, vparamss0, tpt0, rhs0) + if (mods0 == mods) && (name0 == name) && (tparams0 == tparams) && + (vparamss0 == vparamss) && (tpt0 == tpt) && (rhs == rhs0) => t + case _ => treeCopy.DefDef(tree, mods, name, tparams, vparamss, tpt, rhs) + } + def TypeDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], rhs: Tree) = tree match { + case t @ TypeDef(mods0, name0, tparams0, rhs0) + if (mods0 == mods) && (name0 == name) && (tparams0 == tparams) && (rhs0 == rhs) => t + case _ => treeCopy.TypeDef(tree, mods, name, tparams, rhs) + } + def LabelDef(tree: Tree, name: Name, params: List[Ident], rhs: Tree) = tree match { + case t @ LabelDef(name0, params0, rhs0) + if (name0 == name) && (params0 == params) && (rhs0 == rhs) => t + case _ => treeCopy.LabelDef(tree, name, params, rhs) + } + def Import(tree: Tree, expr: Tree, selectors: List[ImportSelector]) = tree match { + case t @ Import(expr0, selectors0) + if (expr0 == expr) && (selectors0 == selectors) => t + case _ => treeCopy.Import(tree, expr, selectors) + } + def Template(tree: Tree, parents: List[Tree], self: ValDef, body: List[Tree]) = tree match { + case t @ Template(parents0, self0, body0) + if (parents0 == parents) && (self0 == self) && (body0 == body) => t + case _ => treeCopy.Template(tree, parents, self, body) + } + def Block(tree: Tree, stats: List[Tree], expr: Tree) = tree match { + case t @ Block(stats0, expr0) + if ((stats0 == stats) && (expr0 == expr)) => t + case _ => treeCopy.Block(tree, stats, expr) + } + def CaseDef(tree: Tree, pat: Tree, guard: Tree, body: Tree) = tree match { + case t @ CaseDef(pat0, guard0, body0) + if (pat0 == pat) && (guard0 == guard) && (body0 == body) => t + case _ => treeCopy.CaseDef(tree, pat, guard, body) + } + def Alternative(tree: Tree, trees: List[Tree]) = tree match { + case t @ Alternative(trees0) + if trees0 == trees => t + case _ => treeCopy.Alternative(tree, trees) + } + def Star(tree: Tree, elem: Tree) = tree match { + case t @ Star(elem0) + if elem0 == elem => t + case _ => treeCopy.Star(tree, elem) + } + def Bind(tree: Tree, name: Name, body: Tree) = tree match { + case t @ Bind(name0, body0) + if (name0 == name) && (body0 == body) => t + case _ => treeCopy.Bind(tree, name, body) + } + def UnApply(tree: Tree, fun: Tree, args: List[Tree]) = tree match { + case t @ UnApply(fun0, args0) + if (fun0 == fun) && (args0 == args) => t + case _ => treeCopy.UnApply(tree, fun, args) + } + def ArrayValue(tree: Tree, elemtpt: Tree, trees: List[Tree]) = tree match { + case t @ ArrayValue(elemtpt0, trees0) + if (elemtpt0 == elemtpt) && (trees0 == trees) => t + case _ => treeCopy.ArrayValue(tree, elemtpt, trees) + } + def Function(tree: Tree, vparams: List[ValDef], body: Tree) = tree match { + case t @ Function(vparams0, body0) + if (vparams0 == vparams) && (body0 == body) => t + case _ => treeCopy.Function(tree, vparams, body) + } + def Assign(tree: Tree, lhs: Tree, rhs: Tree) = tree match { + case t @ Assign(lhs0, rhs0) + if (lhs0 == lhs) && (rhs0 == rhs) => t + case _ => treeCopy.Assign(tree, lhs, rhs) + } + def AssignOrNamedArg(tree: Tree, lhs: Tree, rhs: Tree) = tree match { + case t @ AssignOrNamedArg(lhs0, rhs0) + if (lhs0 == lhs) && (rhs0 == rhs) => t + case _ => treeCopy.AssignOrNamedArg(tree, lhs, rhs) + } + def If(tree: Tree, cond: Tree, thenp: Tree, elsep: Tree) = tree match { + case t @ If(cond0, thenp0, elsep0) + if (cond0 == cond) && (thenp0 == thenp) && (elsep0 == elsep) => t + case _ => treeCopy.If(tree, cond, thenp, elsep) + } + def Match(tree: Tree, selector: Tree, cases: List[CaseDef]) = tree match { + case t @ Match(selector0, cases0) + if (selector0 == selector) && (cases0 == cases) => t + case _ => treeCopy.Match(tree, selector, cases) + } + def Return(tree: Tree, expr: Tree) = tree match { + case t @ Return(expr0) + if expr0 == expr => t + case _ => treeCopy.Return(tree, expr) + } + def Try(tree: Tree, block: Tree, catches: List[CaseDef], finalizer: Tree) = tree match { + case t @ Try(block0, catches0, finalizer0) + if (block0 == block) && (catches0 == catches) && (finalizer0 == finalizer) => t + case _ => treeCopy.Try(tree, block, catches, finalizer) + } + def Throw(tree: Tree, expr: Tree) = tree match { + case t @ Throw(expr0) + if expr0 == expr => t + case _ => treeCopy.Throw(tree, expr) + } + def New(tree: Tree, tpt: Tree) = tree match { + case t @ New(tpt0) + if tpt0 == tpt => t + case _ => treeCopy.New(tree, tpt) + } + def Typed(tree: Tree, expr: Tree, tpt: Tree) = tree match { + case t @ Typed(expr0, tpt0) + if (expr0 == expr) && (tpt0 == tpt) => t + case _ => treeCopy.Typed(tree, expr, tpt) + } + def TypeApply(tree: Tree, fun: Tree, args: List[Tree]) = tree match { + case t @ TypeApply(fun0, args0) + if (fun0 == fun) && (args0 == args) => t + case _ => treeCopy.TypeApply(tree, fun, args) + } + def Apply(tree: Tree, fun: Tree, args: List[Tree]) = tree match { + case t @ Apply(fun0, args0) + if (fun0 == fun) && (args0 == args) => t + case _ => treeCopy.Apply(tree, fun, args) + } + def ApplyDynamic(tree: Tree, qual: Tree, args: List[Tree]) = tree match { + case t @ ApplyDynamic(qual0, args0) + if (qual0 == qual) && (args0 == args) => t + case _ => treeCopy.ApplyDynamic(tree, qual, args) + } + def Super(tree: Tree, qual: Tree, mix: TypeName) = tree match { + case t @ Super(qual0, mix0) + if (qual0 == qual) && (mix0 == mix) => t + case _ => treeCopy.Super(tree, qual, mix) + } + def This(tree: Tree, qual: Name) = tree match { + case t @ This(qual0) + if qual0 == qual => t + case _ => treeCopy.This(tree, qual) + } + def Select(tree: Tree, qualifier: Tree, selector: Name) = tree match { + case t @ Select(qualifier0, selector0) + if (qualifier0 == qualifier) && (selector0 == selector) => t + case _ => treeCopy.Select(tree, qualifier, selector) + } + def Ident(tree: Tree, name: Name) = tree match { + case t @ Ident(name0) + if name0 == name => t + case _ => treeCopy.Ident(tree, name) + } + def ReferenceToBoxed(tree: Tree, idt: Ident) = tree match { + case t @ ReferenceToBoxed(idt0) + if (idt0 == idt) => t + case _ => this.treeCopy.ReferenceToBoxed(tree, idt) + } + def Literal(tree: Tree, value: Constant) = tree match { + case t @ Literal(value0) + if value0 == value => t + case _ => treeCopy.Literal(tree, value) + } + def TypeTree(tree: Tree) = tree match { + case t @ TypeTree() => t + case _ => treeCopy.TypeTree(tree) + } + def Annotated(tree: Tree, annot: Tree, arg: Tree) = tree match { + case t @ Annotated(annot0, arg0) + if (annot0==annot) => t + case _ => treeCopy.Annotated(tree, annot, arg) + } + def SingletonTypeTree(tree: Tree, ref: Tree) = tree match { + case t @ SingletonTypeTree(ref0) + if ref0 == ref => t + case _ => treeCopy.SingletonTypeTree(tree, ref) + } + def SelectFromTypeTree(tree: Tree, qualifier: Tree, selector: Name) = tree match { + case t @ SelectFromTypeTree(qualifier0, selector0) + if (qualifier0 == qualifier) && (selector0 == selector) => t + case _ => treeCopy.SelectFromTypeTree(tree, qualifier, selector) + } + def CompoundTypeTree(tree: Tree, templ: Template) = tree match { + case t @ CompoundTypeTree(templ0) + if templ0 == templ => t + case _ => treeCopy.CompoundTypeTree(tree, templ) + } + def AppliedTypeTree(tree: Tree, tpt: Tree, args: List[Tree]) = tree match { + case t @ AppliedTypeTree(tpt0, args0) + if (tpt0 == tpt) && (args0 == args) => t + case _ => treeCopy.AppliedTypeTree(tree, tpt, args) + } + def TypeBoundsTree(tree: Tree, lo: Tree, hi: Tree) = tree match { + case t @ TypeBoundsTree(lo0, hi0) + if (lo0 == lo) && (hi0 == hi) => t + case _ => treeCopy.TypeBoundsTree(tree, lo, hi) + } + def ExistentialTypeTree(tree: Tree, tpt: Tree, whereClauses: List[Tree]) = tree match { + case t @ ExistentialTypeTree(tpt0, whereClauses0) + if (tpt0 == tpt) && (whereClauses0 == whereClauses) => t + case _ => treeCopy.ExistentialTypeTree(tree, tpt, whereClauses) + } + } + // Belongs in TreeInfo but then I can't reach it from TreePrinters. def isReferenceToScalaMember(t: Tree, Id: Name) = t match { case Ident(Id) => true @@ -33,7 +831,7 @@ trait Trees extends api.Trees { self: SymbolTable => */ case class Modifiers(flags: Long, privateWithin: Name, - annotations: List[Tree]) extends AbsModifiers with HasFlags { + annotations: List[Tree]) extends ModifiersApi with HasFlags { var positions: Map[Long, Position] = Map() @@ -79,82 +877,15 @@ trait Trees extends api.Trees { self: SymbolTable => 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) + object Modifiers extends ModifiersCreator - 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 "" - ) - } - } + implicit val ModifiersTag = ClassTag[Modifiers](classOf[Modifiers]) // ---- values and creators --------------------------------------- @@ -251,14 +982,19 @@ trait Trees extends api.Trees { self: SymbolTable => * 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) + 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 = - new ApplyConstructor(TypeTree(tpe), args.toList) + ApplyConstructor(TypeTree(tpe), args.toList) def New(sym: Symbol, args: Tree*): Tree = New(sym.tpe, args: _*) @@ -292,20 +1028,244 @@ trait Trees extends api.Trees { self: SymbolTable => } } - // --- specific traversers and transformers - // todo. move these into scala.reflect.api - - protected[scala] def duplicateTree(tree: Tree): Tree = duplicator transform tree + // --- 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) + } + } - 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 + 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(mclass(tree.symbol)) { + transformStats(stats, currentOwner) + } + ) + case ClassDef(mods, name, tparams, impl) => + atOwner(tree.symbol) { + treeCopy.ClassDef(tree, transformModifiers(mods), name, + transformTypeDefs(tparams), transformTemplate(impl)) + } + case ModuleDef(mods, name, impl) => + atOwner(mclass(tree.symbol)) { + treeCopy.ModuleDef(tree, transformModifiers(mods), + name, transformTemplate(impl)) + } + case ValDef(mods, name, tpt, rhs) => + atOwner(tree.symbol) { + treeCopy.ValDef(tree, transformModifiers(mods), + name, transform(tpt), transform(rhs)) + } + case DefDef(mods, name, tparams, vparamss, tpt, rhs) => + atOwner(tree.symbol) { + treeCopy.DefDef(tree, transformModifiers(mods), name, + transformTypeDefs(tparams), transformValDefss(vparamss), + transform(tpt), transform(rhs)) + } + case TypeDef(mods, name, tparams, rhs) => + atOwner(tree.symbol) { + treeCopy.TypeDef(tree, transformModifiers(mods), name, + transformTypeDefs(tparams), transform(rhs)) + } + case LabelDef(name, params, rhs) => + treeCopy.LabelDef(tree, name, transformIdents(params), transform(rhs)) //bq: Martin, once, atOwner(...) works, also change `LamdaLifter.proxy' + case Import(expr, selectors) => + treeCopy.Import(tree, transform(expr), selectors) + case Template(parents, self, body) => + treeCopy.Template(tree, transformTrees(parents), transformValDef(self), transformStats(body, tree.symbol)) + case Block(stats, expr) => + treeCopy.Block(tree, transformStats(stats, currentOwner), transform(expr)) + case CaseDef(pat, guard, body) => + treeCopy.CaseDef(tree, transform(pat), transform(guard), transform(body)) + case Alternative(trees) => + treeCopy.Alternative(tree, transformTrees(trees)) + case Star(elem) => + treeCopy.Star(tree, transform(elem)) + case Bind(name, body) => + treeCopy.Bind(tree, name, transform(body)) + case UnApply(fun, args) => + treeCopy.UnApply(tree, fun, transformTrees(args)) // bq: see test/.../unapplyContexts2.scala + case ArrayValue(elemtpt, trees) => + treeCopy.ArrayValue(tree, transform(elemtpt), transformTrees(trees)) + case Function(vparams, body) => + atOwner(tree.symbol) { + treeCopy.Function(tree, transformValDefs(vparams), transform(body)) + } + case Assign(lhs, rhs) => + treeCopy.Assign(tree, transform(lhs), transform(rhs)) + case AssignOrNamedArg(lhs, rhs) => + treeCopy.AssignOrNamedArg(tree, transform(lhs), transform(rhs)) + case If(cond, thenp, elsep) => + treeCopy.If(tree, transform(cond), transform(thenp), transform(elsep)) + case Match(selector, cases) => + treeCopy.Match(tree, transform(selector), transformCaseDefs(cases)) + case Return(expr) => + treeCopy.Return(tree, transform(expr)) + case Try(block, catches, finalizer) => + treeCopy.Try(tree, transform(block), transformCaseDefs(catches), transform(finalizer)) + case Throw(expr) => + treeCopy.Throw(tree, transform(expr)) + case New(tpt) => + treeCopy.New(tree, transform(tpt)) + case Typed(expr, tpt) => + treeCopy.Typed(tree, transform(expr), transform(tpt)) + case TypeApply(fun, args) => + treeCopy.TypeApply(tree, transform(fun), transformTrees(args)) + case Apply(fun, args) => + treeCopy.Apply(tree, transform(fun), transformTrees(args)) + case ApplyDynamic(qual, args) => + treeCopy.ApplyDynamic(tree, transform(qual), transformTrees(args)) + case Super(qual, mix) => + treeCopy.Super(tree, transform(qual), mix) + case This(qual) => + treeCopy.This(tree, qual) + case Select(qualifier, selector) => + treeCopy.Select(tree, transform(qualifier), selector) + case Ident(name) => + treeCopy.Ident(tree, name) + case ReferenceToBoxed(idt) => + treeCopy.ReferenceToBoxed(tree, transform(idt) match { case idt1: Ident => idt1 }) + case Literal(value) => + treeCopy.Literal(tree, value) + case TypeTree() => + treeCopy.TypeTree(tree) + case Annotated(annot, arg) => + treeCopy.Annotated(tree, transform(annot), transform(arg)) + case SingletonTypeTree(ref) => + treeCopy.SingletonTypeTree(tree, transform(ref)) + case SelectFromTypeTree(qualifier, selector) => + treeCopy.SelectFromTypeTree(tree, transform(qualifier), selector) + case CompoundTypeTree(templ) => + treeCopy.CompoundTypeTree(tree, transformTemplate(templ)) + case AppliedTypeTree(tpt, args) => + treeCopy.AppliedTypeTree(tree, transform(tpt), transformTrees(args)) + case TypeBoundsTree(lo, hi) => + treeCopy.TypeBoundsTree(tree, transform(lo), transform(hi)) + case ExistentialTypeTree(tpt, whereClauses) => + treeCopy.ExistentialTypeTree(tree, transform(tpt), transformTrees(whereClauses)) + case _ => + xtransform(transformer, tree) } } + private def mclass(sym: Symbol) = sym map (_.asModuleSymbol.moduleClass) + + // --- specific traversers and transformers + class ForeachPartialTreeTraverser(pf: PartialFunction[Tree, Tree]) extends Traverser { override def traverse(tree: Tree) { val t = if (pf isDefinedAt tree) pf(tree) else tree @@ -432,4 +1392,201 @@ trait Trees extends api.Trees { self: SymbolTable => def apply[T <: Tree](tree: T): T = transform(tree).asInstanceOf[T] override def toString() = "TreeSymSubstituter/" + substituterString("Symbol", "Symbol", from, to) } + + + class ForeachTreeTraverser(f: Tree => Unit) extends Traverser { + override def traverse(t: Tree) { + f(t) + super.traverse(t) + } + } + + class FilterTreeTraverser(p: Tree => Boolean) extends Traverser { + val hits = new ListBuffer[Tree] + override def traverse(t: Tree) { + if (p(t)) hits += t + super.traverse(t) + } + } + + class CollectTreeTraverser[T](pf: PartialFunction[Tree, T]) extends Traverser { + val results = new ListBuffer[T] + override def traverse(t: Tree) { + if (pf.isDefinedAt(t)) results += pf(t) + super.traverse(t) + } + } + + class FindTreeTraverser(p: Tree => Boolean) extends Traverser { + var result: Option[Tree] = None + override def traverse(t: Tree) { + if (result.isEmpty) { + if (p(t)) result = Some(t) + super.traverse(t) + } + } + } + + 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/Types.scala b/src/compiler/scala/reflect/internal/Types.scala index a839e44182..ce7a697439 100644 --- a/src/compiler/scala/reflect/internal/Types.scala +++ b/src/compiler/scala/reflect/internal/Types.scala @@ -260,7 +260,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 +268,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 +282,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 +316,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. */ @@ -1243,7 +1244,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 +1272,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 +1307,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 +1367,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 +1395,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 +1601,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 +1696,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 +1875,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 +2184,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 +2407,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 +2463,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 +2497,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 +2557,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) @@ -3177,7 +3178,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 +3251,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 +3332,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) @@ -5053,6 +5054,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 +5223,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) || { @@ -5521,7 +5529,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) @@ -5542,7 +5550,9 @@ trait Types extends api.Types { self: SymbolTable => val pre2 = tr2.pre (((if (sym1 == sym2) phase.erasedTypes || pre1 <:< pre2 else (sym1.name == sym2.name && !sym1.isModuleClass && !sym2.isModuleClass && - (isUnifiable(pre1, pre2) || isSameSpecializedSkolem(sym1, sym2, pre1, pre2)))) && + (isUnifiable(pre1, pre2) || + isSameSpecializedSkolem(sym1, sym2, pre1, pre2) || + sym2.isAbstractType && isSubPre(pre1, pre2, sym2)))) && isSubArgs(tr1.args, tr2.args, sym1.typeParams)) || sym2.isClass && { @@ -6789,4 +6799,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/compiler/scala/reflect/internal/package.scala b/src/compiler/scala/reflect/internal/package.scala new file mode 100644 index 0000000000..99b837152d --- /dev/null +++ b/src/compiler/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/UnPickler.scala b/src/compiler/scala/reflect/internal/pickling/UnPickler.scala index fd3fac1b37..bfccdd3988 100644 --- a/src/compiler/scala/reflect/internal/pickling/UnPickler.scala +++ b/src/compiler/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 = { @@ -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/util/TraceSymbolActivity.scala b/src/compiler/scala/reflect/internal/util/TraceSymbolActivity.scala index 1424226042..d8c53c0162 100644 --- a/src/compiler/scala/reflect/internal/util/TraceSymbolActivity.scala +++ b/src/compiler/scala/reflect/internal/util/TraceSymbolActivity.scala @@ -7,7 +7,7 @@ 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/reflect/makro/runtime/AbortMacroException.scala b/src/compiler/scala/reflect/makro/runtime/AbortMacroException.scala index d78eae9237..d0d40d6f42 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.tools.nsc.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..30b015b201 100644 --- a/src/compiler/scala/reflect/makro/runtime/Aliases.scala +++ b/src/compiler/scala/reflect/makro/runtime/Aliases.scala @@ -9,13 +9,15 @@ trait Aliases { override type Type = mirror.Type override type Name = mirror.Name override type Tree = mirror.Tree - override type Position = mirror.Position + // 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 ConcreteTypeTag[T] = mirror.ConcreteTypeTag[T] /** Creator/extractor objects for Expr and TypeTag values */ override val TypeTag = mirror.TypeTag + override val ConcreteTypeTag = mirror.ConcreteTypeTag override val Expr = mirror.Expr }
\ 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..6faf045d75 100644 --- a/src/compiler/scala/reflect/makro/runtime/Context.scala +++ b/src/compiler/scala/reflect/makro/runtime/Context.scala @@ -12,8 +12,9 @@ abstract class Context extends scala.reflect.makro.Context with Reifiers with FrontEnds with Settings - with Symbols with Typers + with Exprs + with TypeTags with Util with Traces { 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..d47ff4e450 --- /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: TypeTag](tree: Tree): Expr[T] = mirror.Expr[T](mirror.rootMirror, mirror.FixedMirrorTreeCreator(mirror.rootMirror, tree)) +} diff --git a/src/compiler/scala/reflect/makro/runtime/FrontEnds.scala b/src/compiler/scala/reflect/makro/runtime/FrontEnds.scala index 7cfa8e80f3..a21c8f90c9 100644 --- a/src/compiler/scala/reflect/makro/runtime/FrontEnds.scala +++ b/src/compiler/scala/reflect/makro/runtime/FrontEnds.scala @@ -1,11 +1,13 @@ package scala.reflect.makro package runtime -trait FrontEnds { +trait FrontEnds extends scala.tools.reflect.FrontEnds { self: Context => import mirror._ + override type Position = mirror.Position + def frontEnd: FrontEnd = wrapReporter(mirror.reporter) def setFrontEnd(frontEnd: FrontEnd): this.type = { diff --git a/src/compiler/scala/reflect/makro/runtime/Reifiers.scala b/src/compiler/scala/reflect/makro/runtime/Reifiers.scala index 1c5af4b752..fd683fd229 100644 --- a/src/compiler/scala/reflect/makro/runtime/Reifiers.scala +++ b/src/compiler/scala/reflect/makro/runtime/Reifiers.scala @@ -12,23 +12,17 @@ trait Reifiers { import mirror._ import definitions._ - lazy val reflectMirrorPrefix: Tree = ReflectMirrorPrefix + lazy val reflectMirrorPrefix: Tree = ??? - def reifyTree(prefix: Tree, tree: Tree): Tree = { - val result = scala.reflect.reify.`package`.reifyTree(mirror)(callsiteTyper, prefix, tree) - logFreeVars(enclosingPosition, result) - result - } + def reifyTree(prefix: Tree, tree: Tree): Tree = + scala.reflect.reify.`package`.reifyTree(mirror)(callsiteTyper, prefix, tree) - 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) - logFreeVars(enclosingPosition, result) - result - } + def reifyType(prefix: Tree, tpe: Type, dontSpliceAtTopLevel: Boolean = false, concrete: Boolean = false): Tree = + scala.reflect.reify.`package`.reifyType(mirror)(callsiteTyper, prefix, tpe, dontSpliceAtTopLevel, concrete) def reifyErasure(tpe: Type, concrete: Boolean = true): Tree = scala.reflect.reify.`package`.reifyErasure(mirror)(callsiteTyper, tpe, concrete) def unreifyTree(tree: Tree): Tree = - Select(tree, definitions.ExprEval) + Select(tree, definitions.ExprSplice) } 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/TypeTags.scala b/src/compiler/scala/reflect/makro/runtime/TypeTags.scala new file mode 100644 index 0000000000..a8e67da56a --- /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 TypeTag[T](tpe: Type): TypeTag[T] = mirror.TypeTag[T](mirror.rootMirror, mirror.FixedMirrorTypeCreator(mirror.rootMirror, tpe)) + def ConcreteTypeTag[T](tpe: Type): ConcreteTypeTag[T] = mirror.ConcreteTypeTag[T](mirror.rootMirror, mirror.FixedMirrorTypeCreator(mirror.rootMirror, tpe)) +} diff --git a/src/compiler/scala/reflect/reify/NodePrinters.scala b/src/compiler/scala/reflect/reify/NodePrinters.scala index eaca9a4968..f0d0d0f5d4 100644 --- a/src/compiler/scala/reflect/reify/NodePrinters.scala +++ b/src/compiler/scala/reflect/reify/NodePrinters.scala @@ -18,94 +18,7 @@ trait NodePrinters { self: scala.tools.nsc.ast.NodePrinters => 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 + "temporarily disabled until reification is repaired" } } }
\ No newline at end of file diff --git a/src/compiler/scala/reflect/reify/Taggers.scala b/src/compiler/scala/reflect/reify/Taggers.scala index 5665c0948e..d0ef6fcdbf 100644 --- a/src/compiler/scala/reflect/reify/Taggers.scala +++ b/src/compiler/scala/reflect/reify/Taggers.scala @@ -21,8 +21,6 @@ abstract class Taggers { 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")) @@ -32,9 +30,6 @@ abstract class Taggers { 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) @@ -54,22 +49,12 @@ abstract class Taggers { 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)) + translatingReificationErrors(materializer) } try c.typeCheck(result) catch { case terr @ c.TypeError(pos, msg) => failTag(result, 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) diff --git a/src/compiler/scala/reflect/reify/codegen/Symbols.scala b/src/compiler/scala/reflect/reify/codegen/Symbols.scala index 21a08b7efb..5ab8a11efe 100644 --- a/src/compiler/scala/reflect/reify/codegen/Symbols.scala +++ b/src/compiler/scala/reflect/reify/codegen/Symbols.scala @@ -15,13 +15,13 @@ trait Symbols { if (sym == NoSymbol) mirrorSelect(nme.NoSymbol) - else if (sym == RootPackage) + else if (sym == rootMirror.RootPackage) Select(mirrorSelect(nme.definitions), nme.RootPackage) - else if (sym == RootClass) + else if (sym == rootMirror.RootClass) Select(mirrorSelect(nme.definitions), nme.RootClass) - else if (sym == EmptyPackage) + else if (sym == rootMirror.EmptyPackage) Select(mirrorSelect(nme.definitions), nme.EmptyPackage) - else if (sym == EmptyPackageClass) + else if (sym == rootMirror.EmptyPackageClass) Select(mirrorSelect(nme.definitions), nme.EmptyPackageClass) else if (sym.isModuleClass) Select(reify(sym.sourceModule), nme.moduleClass) @@ -105,7 +105,7 @@ trait Symbols { filledIn = false newSymbolTable foreach { case entry => - val att = entry.attachmentOpt[ReifyAttachment] + val att = entry.attachments.get[ReifyAttachment] att match { case Some(ReifyAttachment(sym)) => // don't duplicate reified symbols when merging inlined reifee @@ -134,7 +134,7 @@ trait Symbols { // 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) + val local = ValDef(NoMods, name, TypeTree(), reified) addAttachment ReifyAttachment(sym) localReifications += local filledIn = false locallyReified(sym) = Ident(name) @@ -149,7 +149,7 @@ trait Symbols { 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] + val att = reified.attachments.get[ReifyAttachment] att match { case Some(ReifyAttachment(sym)) => fillIns += fillInSymbol(sym) case other => // do nothing diff --git a/src/compiler/scala/reflect/reify/codegen/Trees.scala b/src/compiler/scala/reflect/reify/codegen/Trees.scala index c9f5fc5b8d..a4543d84c1 100644 --- a/src/compiler/scala/reflect/reify/codegen/Trees.scala +++ b/src/compiler/scala/reflect/reify/codegen/Trees.scala @@ -7,7 +7,6 @@ trait Trees { import mirror._ 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 @@ -106,7 +105,7 @@ trait Trees { private def spliceTree(tree: Tree): Tree = { tree match { - case EvalSplice(splicee) => + case TreeSplice(splicee) => if (reifyDebug) println("splicing eval " + tree) // see ``Metalevels'' for more info about metalevel breaches @@ -138,9 +137,6 @@ trait Trees { }.transform(tree) } } - case ValueSplice(splicee) => - // todo. implement this - ??? case _ => EmptyTree } diff --git a/src/compiler/scala/reflect/runtime/AbstractFile.scala b/src/compiler/scala/reflect/runtime/AbstractFile.scala index 414bba020b..0f88af1b0a 100644 --- a/src/compiler/scala/reflect/runtime/AbstractFile.scala +++ b/src/compiler/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/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/JavaMirrors.scala b/src/compiler/scala/reflect/runtime/JavaMirrors.scala new file mode 100644 index 0000000000..a8120d220a --- /dev/null +++ b/src/compiler/scala/reflect/runtime/JavaMirrors.scala @@ -0,0 +1,981 @@ +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 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(runtimeClass: RuntimeClass): ClassMirror = + new JavaClassMirror(classToScala(runtimeClass)) + + def reflectClass(fullName: String): ClassMirror = + reflectClass(java.lang.Class.forName(fullName)) + + def reflectModule(runtimeClass: RuntimeClass): ModuleMirror = + new JavaModuleMirror(classToScala(runtimeClass).companionModule.asModuleSymbol) + + def reflectModule(fullName: String): ModuleMirror = + reflectModule(java.lang.Class.forName(fullName)) + + def runtimeClass(tpe: Type): RuntimeClass = typeToJavaClass(tpe) + + def runtimeClass(cls: ClassSymbol): RuntimeClass = classToJava(cls) + + private class JavaInstanceMirror(obj: AnyRef) + extends InstanceMirror { + def instance = obj + def reflectClass = wholemirror.reflectClass(obj.getClass) + def reflectField(field: TermSymbol): FieldMirror = new JavaFieldMirror(obj, field) + def reflectMethod(method: MethodSymbol): MethodMirror = new JavaMethodMirror(obj, method) + } + + private class JavaFieldMirror(val receiver: AnyRef, val field: TermSymbol) + extends FieldMirror { + lazy val jfield = fieldToJava(field) + def get = jfield.get(receiver) + def set(value: Any) = jfield.set(receiver, value) + } + + private class JavaMethodMirror(val receiver: AnyRef, val method: MethodSymbol) + extends MethodMirror { + lazy val jmeth = methodToJava(method) + def apply(args: Any*): Any = + if (method.owner == ArrayClass) + method.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 $method") + } + else + jmeth.invoke(receiver, args.asInstanceOf[Seq[AnyRef]]: _*) + } + + private class JavaConstructorMirror(val method: MethodSymbol) + extends MethodMirror { + override val receiver = null + lazy val jconstr = constructorToJava(method) + def apply(args: Any*): Any = jconstr.newInstance(args.asInstanceOf[Seq[AnyRef]]: _*) + } + + + private abstract class JavaTemplateMirror + extends TemplateMirror { + def erasure: ClassSymbol + lazy val runtimeClass = classToJava(erasure) + lazy val signature = typeToScala(runtimeClass) + } + + private class JavaClassMirror(val symbol: ClassSymbol) + extends JavaTemplateMirror with ClassMirror { + def erasure = symbol + def isStatic = false + def reflectConstructor(constructor: MethodSymbol) = new JavaConstructorMirror(constructor) + def companion: Option[ModuleMirror] = symbol.companionModule match { + case module: ModuleSymbol => Some(new JavaModuleMirror(module)) + case _ => None + } + } + + private class JavaModuleMirror(val symbol: ModuleSymbol) + extends JavaTemplateMirror with ModuleMirror { + def erasure = symbol.moduleClass.asClassSymbol + def isStatic = true + def instance = singletonInstance(classLoader, symbol.fullName) + def companion: Option[ClassMirror] = symbol.companionClass match { + case cls: ClassSymbol => Some(new JavaClassMirror(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) + try jclazz getDeclaredField fld.name.toString + 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 + try jclazz getDeclaredMethod (meth.name.toString, 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 + 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: 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/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/JavaUniverse.scala b/src/compiler/scala/reflect/runtime/JavaUniverse.scala new file mode 100644 index 0000000000..9dcf8786c5 --- /dev/null +++ b/src/compiler/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.tools.nsc.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/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/ReflectSetup.scala b/src/compiler/scala/reflect/runtime/ReflectSetup.scala new file mode 100644 index 0000000000..6e28fc8520 --- /dev/null +++ b/src/compiler/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/compiler/scala/reflect/runtime/ReflectionUtils.scala index aa1285d5a0..4e82fe8ad2 100644 --- a/src/library/scala/reflect/ReflectionUtils.scala +++ b/src/compiler/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 } @@ -42,7 +42,7 @@ object ReflectionUtils { 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: api.RequiredFile}].root + "] and " + inferClasspath(cl.getParent) + "[" + cl.asInstanceOf[{val root: scala.reflect.internal.AbstractFileApi}].root + "] and " + inferClasspath(cl.getParent) case null => inferBootClasspath case _ => @@ -56,16 +56,6 @@ object ReflectionUtils { } } - 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/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/SymbolLoaders.scala b/src/compiler/scala/reflect/runtime/SymbolLoaders.scala index 7c1cc16152..c1cd5d2911 100644 --- a/src/compiler/scala/reflect/runtime/SymbolLoaders.scala +++ b/src/compiler/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/compiler/scala/reflect/runtime/SymbolTable.scala index 64a5894d01..c90665508b 100644 --- a/src/compiler/scala/reflect/runtime/SymbolTable.scala +++ b/src/compiler/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/SynchronizedSymbols.scala b/src/compiler/scala/reflect/runtime/SynchronizedSymbols.scala index 2322911220..3b28ddf42c 100644 --- a/src/compiler/scala/reflect/runtime/SynchronizedSymbols.scala +++ b/src/compiler/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/compiler/scala/reflect/runtime/SynchronizedTypes.scala index e5a508f802..e1eb7a57fe 100644 --- a/src/compiler/scala/reflect/runtime/SynchronizedTypes.scala +++ b/src/compiler/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/compiler/scala/reflect/runtime/TwoWayCache.scala b/src/compiler/scala/reflect/runtime/TwoWayCache.scala new file mode 100644 index 0000000000..c7bfb3435d --- /dev/null +++ b/src/compiler/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/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 index 52ab2c5deb..531873c661 100644 --- a/src/compiler/scala/reflect/runtime/package.scala +++ b/src/compiler/scala/reflect/runtime/package.scala @@ -1,5 +1,13 @@ package scala.reflect +import language.experimental.macros + package object runtime { - def mkMirror(classLoader: ClassLoader): api.Mirror = new Mirror(classLoader) -}
\ No newline at end of file + + // 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 = ??? +} diff --git a/src/compiler/scala/tools/cmd/FromString.scala b/src/compiler/scala/tools/cmd/FromString.scala index dd3b680afe..29f1baaa0c 100644 --- a/src/compiler/scala/tools/cmd/FromString.scala +++ b/src/compiler/scala/tools/cmd/FromString.scala @@ -7,6 +7,7 @@ package scala.tools package cmd import nsc.io.{ Path, File, Directory } +import scala.reflect.runtime.{universe => ru} import scala.tools.reflect.StdTags._ /** A general mechanism for defining how a command line argument @@ -14,7 +15,7 @@ import scala.tools.reflect.StdTags._ * 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("") 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/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 271dca3157..57124b9c1c 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -31,21 +31,42 @@ import backend.icode.analysis._ import language.postfixOps import reflect.internal.StdAttachments -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 +98,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 +405,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 +708,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 +871,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 +935,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 +996,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 +1542,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 +1631,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/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/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..a01756b35b 100755 --- a/src/compiler/scala/tools/nsc/ast/DocComments.scala +++ b/src/compiler/scala/tools/nsc/ast/DocComments.scala @@ -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 17d8def2e9..ba1f3b2e3c 100644 --- a/src/compiler/scala/tools/nsc/ast/NodePrinters.scala +++ b/src/compiler/scala/tools/nsc/ast/NodePrinters.scala @@ -169,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/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/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index 226c17f10d..688da4fd04 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -1026,7 +1026,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) { 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/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..f302318185 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala @@ -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._ 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/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/interactive/Picklers.scala b/src/compiler/scala/tools/nsc/interactive/Picklers.scala index b7a9c7329c..7c635c6d65 100644 --- a/src/compiler/scala/tools/nsc/interactive/Picklers.scala +++ b/src/compiler/scala/tools/nsc/interactive/Picklers.scala @@ -115,7 +115,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/RangePositions.scala b/src/compiler/scala/tools/nsc/interactive/RangePositions.scala index 49ba9d0aeb..c3eb06f2ff 100644 --- a/src/compiler/scala/tools/nsc/interactive/RangePositions.scala +++ b/src/compiler/scala/tools/nsc/interactive/RangePositions.scala @@ -189,7 +189,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/interpreter/ILoop.scala b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala index 84836ce1db..fdf7db1b9f 100644 --- a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala +++ b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala @@ -106,7 +106,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) } def isAsync = !settings.Yreplsync.value - lazy val power = new Power(intp, new StdReplVals(this))(tagOfStdReplVals) + 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 */ @@ -831,7 +831,7 @@ 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(NamedParam[IMain]("$intp", intp)(tagOfIMain))) + addThunk(intp.quietBind(NamedParam[IMain]("$intp", intp)(tagOfIMain, classTag[IMain]))) addThunk({ import scala.tools.nsc.io._ import Properties.userHome diff --git a/src/compiler/scala/tools/nsc/interpreter/IMain.scala b/src/compiler/scala/tools/nsc/interpreter/IMain.scala index 7ae8ea4535..94f51b78ed 100644 --- a/src/compiler/scala/tools/nsc/interpreter/IMain.scala +++ b/src/compiler/scala/tools/nsc/interpreter/IMain.scala @@ -25,6 +25,7 @@ import IMain._ import java.util.concurrent.Future import typechecker.Analyzer import language.implicitConversions +import scala.reflect.runtime.{ universe => ru } import scala.tools.reflect.StdTags._ /** directory to save .class files to */ @@ -196,17 +197,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 @@ -333,14 +325,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 @@ -501,11 +486,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 @@ -653,8 +644,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 @@ -670,12 +661,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() { @@ -718,7 +709,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends val unwrapped = unwrap(t) withLastExceptionLock[String]({ - directBind[Throwable]("lastException", unwrapped)(classTag[Throwable]) + directBind[Throwable]("lastException", unwrapped)(tagOfThrowable, classTag[Throwable]) util.stackTraceString(unwrapped) }, util.stackTraceString(unwrapped)) } @@ -1052,7 +1043,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) } 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/NamedParam.scala b/src/compiler/scala/tools/nsc/interpreter/NamedParam.scala index a3cbfffc3b..61a61de1e9 100644 --- a/src/compiler/scala/tools/nsc/interpreter/NamedParam.scala +++ b/src/compiler/scala/tools/nsc/interpreter/NamedParam.scala @@ -8,23 +8,24 @@ package interpreter import NamedParam._ import language.implicitConversions +import scala.reflect.runtime.{universe => ru} 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..a0687c824b 100644 --- a/src/compiler/scala/tools/nsc/interpreter/Power.scala +++ b/src/compiler/scala/tools/nsc/interpreter/Power.scala @@ -14,6 +14,7 @@ import scala.io.Codec import java.net.{ URL, MalformedURLException } import io.{ Path } import language.implicitConversions +import scala.reflect.runtime.{universe => ru} /** Collecting some power mode examples. @@ -42,10 +43,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 +164,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 +175,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 +188,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], erasureEvidence: 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,8 +228,8 @@ 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 tag = typeEvidence + def erasure = erasureEvidence.erasure def shortClass = erasure.getName split "[$.]" last def baseClasses = tpe.baseClasses @@ -236,9 +238,9 @@ 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) @@ -362,7 +364,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 +380,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/ReplVals.scala b/src/compiler/scala/tools/nsc/interpreter/ReplVals.scala index 280247f20c..ff99cd47da 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 # TypeTag[_]): 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/TypeStrings.scala b/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala index 5d5123811e..cea9b9e112 100644 --- a/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala +++ b/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala @@ -10,7 +10,7 @@ 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 typechecker.DestructureTypes import scala.tools.util.StringOps.ojoin @@ -192,7 +192,7 @@ trait TypeStrings { else enclClass.getName + "." + (name stripPrefix enclPre) ) } - def scalaName(m: ClassTag[_]): String = scalaName(m.erasure) + def scalaName(ct: ClassTag[_]): String = scalaName(ct.erasure) def anyClass(x: Any): JClass = if (x == null) null else x.getClass private def brackets(tps: String*): String = @@ -209,10 +209,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 +226,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].erasure) + tparamString[T] /** Reducing fully qualified noise for some common packages. */ diff --git a/src/compiler/scala/tools/nsc/io/AbstractFile.scala b/src/compiler/scala/tools/nsc/io/AbstractFile.scala index deb914f806..08b9df2fa8 100644 --- a/src/compiler/scala/tools/nsc/io/AbstractFile.scala +++ b/src/compiler/scala/tools/nsc/io/AbstractFile.scala @@ -10,7 +10,6 @@ package io import java.io.{ FileOutputStream, IOException, InputStream, OutputStream, BufferedOutputStream } import java.net.URL import scala.collection.mutable.ArrayBuffer -import scala.reflect.api.RequiredFile /** * @author Philippe Altherr @@ -82,7 +81,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/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/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/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/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala index 9cffb6a1e1..6d6430207d 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) } } 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..d45db9ea5d 100644 --- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala +++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala @@ -66,11 +66,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 +435,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 } @@ -1695,7 +1696,10 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { private def forwardCall(pos: 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 @@ -1737,7 +1741,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/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..aebe3454b1 100644 --- a/src/compiler/scala/tools/nsc/typechecker/DestructureTypes.scala +++ b/src/compiler/scala/tools/nsc/typechecker/DestructureTypes.scala @@ -64,7 +64,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 6a2a9b850c..f3afa2d33f 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -1133,7 +1133,6 @@ 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 @@ -1166,9 +1165,9 @@ trait Implicits { } val prefix = ( - // ClassTags only exist for scala.reflect.mirror, so their materializer + // ClassTags and ArrayTags only exist for scala.reflect, so their materializer // doesn't care about prefixes - if ((tagClass eq ArrayTagClass) || (tagClass eq ErasureTagClass) || (tagClass eq ClassTagClass)) ReflectMirrorPrefix + if ((tagClass eq ArrayTagClass) || (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 @@ -1295,13 +1294,33 @@ trait Implicits { } val tagInScope = - if (full) context.withMacrosDisabled(resolveTypeTag(ReflectMirrorPrefix.tpe, tp, pos, true)) - else context.withMacrosDisabled(resolveArrayTag(tp, pos)) + if (full) resolveTypeTag(NoType, tp, pos, concrete = true) + else resolveArrayTag(tp, pos) 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 (resolveErasureTag(tp, pos, concrete = 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.concreteTypeTagToManifest, List(tp), List(cm, tagInScope)) + } else gen.mkMethodCall(ReflectRuntimeUniverse, nme.arrayTagToClassManifest, 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..1ed9350d3f 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 */ diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala index 8895642893..ed3f372cb2 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala @@ -4,7 +4,7 @@ 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 util.Statistics._ @@ -796,7 +796,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { 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 => Expr(rootMirror, FixedMirrorTreeCreator(rootMirror, arg))(TypeTag.Nothing))) collectMacroArgs(fn) case TypeApply(fn, args) => typeArgs = args @@ -806,7 +806,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { case _ => } collectMacroArgs(expandee) - val context = expandee.attachmentOpt[MacroAttachment].flatMap(_.macroContext).getOrElse(macroContext(typer, prefixTree, expandee)) + val context = expandee.attachments.get[MacroAttachment].flatMap(_.macroContext).getOrElse(macroContext(typer, prefixTree, expandee)) var argss: List[List[Any]] = List(context) :: exprArgs.toList macroTraceVerbose("argss: ")(argss) val rawArgss = @@ -897,13 +897,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { } 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 - }) + val tags = paramss.last takeWhile (_.isType) map (resolved(_)) map (tpe => if (tpe.isConcrete) context.ConcreteTypeTag(tpe) else context.TypeTag(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 @@ -1059,7 +1053,7 @@ trait Macros extends scala.tools.reflect.FastTrack with 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, @@ -1086,8 +1080,8 @@ trait Macros extends scala.tools.reflect.FastTrack with 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 @@ -1121,7 +1115,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { 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)) + expandee addAttachment MacroAttachment(delayed = true, typerContext = typer.context, macroContext = Some(context.asInstanceOf[MacroContext])) Delay(expandee) } else { @@ -1136,7 +1130,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { case x => x } finally { - expandee.detach(classOf[MacroAttachment]) + expandee.removeAttachment[MacroAttachment] if (!isSuccess) openMacros = openMacros.tail } } @@ -1287,7 +1281,7 @@ trait Macros extends scala.tools.reflect.FastTrack with 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[MacroAttachment].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..d26f3247da 100644 --- a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala +++ b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala @@ -8,7 +8,7 @@ package typechecker import symtab.Flags._ import scala.collection.{ mutable, immutable } import scala.tools.util.StringOps.{ ojoin } -import scala.reflect.{ mirror => rm } +import scala.reflect.runtime.{ universe => ru } import language.higherKinds /** Logic related to method synthesis which involves cooperation between @@ -22,7 +22,7 @@ trait MethodSynthesis { import CODE._ object synthesisUtil { - type CTT[T] = rm.ConcreteTypeTag[T] + type CTT[T] = ru.ConcreteTypeTag[T] type CT[T] = ClassTag[T] def ValOrDefDef(sym: Symbol, body: Tree) = @@ -30,7 +30,7 @@ trait MethodSynthesis { else DefDef(sym, body) def applyTypeInternal(tags: List[CTT[_]]): Type = { - // [Eugene to Paul] needs review!! + // [Eugene++ to Paul] needs review!! val symbols = tags map compilerSymbolFromTag val container :: args = symbols val tparams = container.typeConstructor.typeParams @@ -44,26 +44,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.erasure.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](implicit t1: CTT[CC]): Type = + applyTypeInternal(List(t1)) - def applyType[CC[X1], X1](implicit m1: CTT[CC[_]], m2: CTT[X1]): Type = - applyTypeInternal(List(m1, m2)) + def applyType[CC[X1], X1](implicit t1: CTT[CC[_]], t2: CTT[X1]): Type = + applyTypeInternal(List[CTT[_]](t1, t2)) - 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], X1, X2](implicit t1: CTT[CC[_,_]], t2: CTT[X1], t3: CTT[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.CTT[CC[_, _]], scala.tools.nsc.typechecker.MethodSynthesis.synthesisUtil.CTT[X1], scala.tools.nsc.typechecker.MethodSynthesis.synthesisUtil.CTT[X2]) + // [scalacfork] --- because --- + // [scalacfork] undetermined type + // [scalacfork] applyTypeInternal(List(t1, t2, t3)) + applyTypeInternal(List[CTT[_]](t1, t2, t3)) - 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 applyType[CC[X1, X2, X3], X1, X2, X3](implicit t1: CTT[CC[_,_,_]], t2: CTT[X1], t3: CTT[X2], t4: CTT[X3]): Type = + applyTypeInternal(List[CTT[_]](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: CTT[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/PatternMatching.scala b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala index 48985213d1..eb77ec8224 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 @@ -1488,7 +1488,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 553294d0fe..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" + 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 index fb0d6fb3c5..bbcfa2920b 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Taggings.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Taggings.scala @@ -48,7 +48,7 @@ trait Taggings { * 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)) + val taggedTp = appliedType(if (concrete) ClassTagClass.typeConstructor else ???, List(tp)) resolveTag(taggedTp, pos) } 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 a2ef06fe38..cc36ed7428 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1361,7 +1361,7 @@ trait Typers extends Modes with Adaptations with Taggings { case List(acc) => def isUnderlyingAcc(sym: Symbol) = sym == acc || acc.hasAccessorFlag && sym == acc.accessed - if (acc.accessBoundary(clazz) != RootClass) + 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)) @@ -2315,7 +2315,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)) @@ -2383,7 +2383,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) } @@ -2401,7 +2401,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) } @@ -4402,7 +4402,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 = ( @@ -4530,7 +4530,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) { @@ -4912,7 +4912,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) => 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/Position.scala b/src/compiler/scala/tools/nsc/util/Position.scala index 208cd5703a..b27ca17bfe 100644 --- a/src/compiler/scala/tools/nsc/util/Position.scala +++ b/src/compiler/scala/tools/nsc/util/Position.scala @@ -7,6 +7,9 @@ package scala.tools.nsc package util +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/tools/nsc/util/ScalaClassLoader.scala b/src/compiler/scala/tools/nsc/util/ScalaClassLoader.scala index 4c7920d6b3..1db6b4a170 100644 --- a/src/compiler/scala/tools/nsc/util/ScalaClassLoader.scala +++ b/src/compiler/scala/tools/nsc/util/ScalaClassLoader.scala @@ -11,7 +11,7 @@ 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 diff --git a/src/compiler/scala/tools/reflect/FastTrack.scala b/src/compiler/scala/tools/reflect/FastTrack.scala index 738bcd01a7..8658e3225d 100644 --- a/src/compiler/scala/tools/reflect/FastTrack.scala +++ b/src/compiler/scala/tools/reflect/FastTrack.scala @@ -35,7 +35,6 @@ trait FastTrack { var registry = Map[Symbol, FastTrackEntry]() implicit class BindTo(sym: Symbol) { def bindTo(expander: FastTrackExpander): Unit = if (sym != NoSymbol) registry += sym -> FastTrackEntry(sym, expander) } MacroInternal_materializeArrayTag bindTo { case (c, Apply(TypeApply(_, List(tt)), List(u))) => c.materializeArrayTag(u, tt.tpe) } - MacroInternal_materializeErasureTag bindTo { case (c, Apply(TypeApply(_, List(tt)), List(u))) => c.materializeErasureTag(u, tt.tpe, concrete = false) } MacroInternal_materializeClassTag bindTo { case (c, Apply(TypeApply(_, List(tt)), List(u))) => c.materializeClassTag(u, tt.tpe) } MacroInternal_materializeTypeTag bindTo { case (c, Apply(TypeApply(_, List(tt)), List(u))) => c.materializeTypeTag(u, tt.tpe, concrete = false) } MacroInternal_materializeConcreteTypeTag bindTo { case (c, Apply(TypeApply(_, List(tt)), List(u))) => c.materializeTypeTag(u, tt.tpe, concrete = true) } diff --git a/src/compiler/scala/reflect/internal/FrontEnds.scala b/src/compiler/scala/tools/reflect/FrontEnds.scala index 74501c7686..52eadc4e04 100644 --- a/src/compiler/scala/reflect/internal/FrontEnds.scala +++ b/src/compiler/scala/tools/reflect/FrontEnds.scala @@ -1,10 +1,12 @@ -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.tools.nsc.reporters._ - import scala.tools.nsc.Settings +trait FrontEnds extends scala.reflect.api.FrontEnds { + + type Position = scala.tools.nsc.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 index d6dba5df1b..914219c04e 100644 --- a/src/compiler/scala/tools/reflect/StdTags.scala +++ b/src/compiler/scala/tools/reflect/StdTags.scala @@ -2,21 +2,36 @@ package scala.tools package reflect import java.lang.{Class => jClass} -import scala.reflect.mirror._ +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 { - lazy val tagOfString = TypeTag.String - lazy val tagOfListOfString = TypeTag[List[String]]({ - val pre = ThisType(staticModule("scala.collection.immutable").moduleClass) - TypeRef(pre, definitions.ListClass, List(definitions.StringClass.asTypeConstructor)) - }, classOf[List[String]]) + // 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)) + } + }) - private def tagOfStaticClass[T: ClassTag] = TypeTag[T](staticClass(classTag[T].erasure.getName).asTypeConstructor, classTag[T].erasure) - lazy val tagOfInt = TypeTag.Int + // 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].erasure.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] 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..3ef2337e0f 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 @@ -8,31 +8,45 @@ import scala.tools.nsc.Global import scala.tools.nsc.typechecker.Modes import scala.tools.nsc.io.VirtualDirectory import scala.tools.nsc.interpreter.AbstractFileClassLoader -import scala.tools.nsc.util.FreshNameCreator +import scala.tools.nsc.util.{FreshNameCreator, BatchSourceFile} import scala.reflect.internal.Flags import scala.tools.nsc.util.{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,25 +60,21 @@ 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) @@ -76,7 +86,8 @@ trait ToolBoxes extends { self: Universe => 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.tools.nsc.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/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/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/Predef.scala b/src/library/scala/Predef.scala index c08462ac1b..a6477f1709 100644 --- a/src/library/scala/Predef.scala +++ b/src/library/scala/Predef.scala @@ -113,7 +113,6 @@ object Predef extends LowPriorityImplicits { // 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] @@ -124,7 +123,6 @@ object Predef extends LowPriorityImplicits { // [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 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 index ba0c075723..3eba901f4f 100644 --- a/src/library/scala/reflect/ArrayTag.scala +++ b/src/library/scala/reflect/ArrayTag.scala @@ -13,7 +13,7 @@ package scala.reflect * 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]] + * @see [[scala.reflect.base.TypeTags]] */ @annotation.implicitNotFound(msg = "No ArrayTag available for ${T}") trait ArrayTag[T] { diff --git a/src/library/scala/reflect/ClassTag.scala b/src/library/scala/reflect/ClassTag.scala index e485691747..ec66a42730 100644 --- a/src/library/scala/reflect/ClassTag.scala +++ b/src/library/scala/reflect/ClassTag.scala @@ -1,7 +1,6 @@ package scala.reflect import java.lang.{ Class => jClass } -import scala.reflect.{ mirror => rm } import language.{implicitConversions, existentials} import scala.runtime.ScalaRunTime.arrayClass @@ -21,13 +20,16 @@ import scala.runtime.ScalaRunTime.arrayClass * 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 ArrayTag[T] with 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 an erasure of type `T` */ + def erasure: jClass[_] + /** Produces a `ClassTag` that knows how to build `Array[Array[T]]` */ def wrap: ClassTag[Array[T]] = ClassTag[Array[T]](arrayClass(erasure)) 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/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..559b82b177 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 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/AnnotationInfos.scala b/src/library/scala/reflect/api/AnnotationInfos.scala index cc1c4d2b6b..d9f35024d9 100755 --- a/src/library/scala/reflect/api/AnnotationInfos.scala +++ b/src/library/scala/reflect/api/AnnotationInfos.scala @@ -1,42 +1,27 @@ package scala.reflect package api -trait AnnotationInfos { self: Universe => +trait AnnotationInfos extends base.AnnotationInfos { self: Universe => - type AnnotationInfo <: AnyRef - val AnnotationInfo: AnnotationInfoExtractor - - abstract class AnnotationInfoExtractor { - def apply(atp: Type, args: List[Tree], assocs: List[(Name, ClassfileAnnotArg)]): AnnotationInfo - def unapply(info: AnnotationInfo): Option[(Type, List[Tree], List[(Name, ClassfileAnnotArg)])] + override type AnnotationInfo >: Null <: AnyRef with AnnotationInfoApi + trait AnnotationInfoApi { + def atp: Type + def args: List[Tree] + def assocs: List[(Name, ClassfileAnnotArg)] } - type ClassfileAnnotArg <: AnyRef - implicit def classfileAnnotArgTag: ArrayTag[ClassfileAnnotArg] // need a precise tag to pass to UnPickle's toArray call - - type LiteralAnnotArg <: ClassfileAnnotArg - 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] + override type LiteralAnnotArg >: Null <: ClassfileAnnotArg with LiteralAnnotArgApi + trait LiteralAnnotArgApi { + def const: Constant } - abstract class ArrayAnnotArgExtractor { - def apply(const: Array[ClassfileAnnotArg]): ArrayAnnotArg - def unapply(arg: ArrayAnnotArg): Option[Array[ClassfileAnnotArg]] + override type ArrayAnnotArg >: Null <: ClassfileAnnotArg with ArrayAnnotArgApi + trait ArrayAnnotArgApi { + def args: Array[ClassfileAnnotArg] } - abstract class NestedAnnotArgExtractor { - def apply(anninfo: AnnotationInfo): NestedAnnotArg - def unapply(arg: NestedAnnotArg): Option[AnnotationInfo] + 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/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/Constants.scala b/src/library/scala/reflect/api/Constants.scala index 42a0fa8a27..7862ab0d25 100755 --- a/src/library/scala/reflect/api/Constants.scala +++ b/src/library/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/library/scala/reflect/api/Exprs.scala b/src/library/scala/reflect/api/Exprs.scala index b8db64422e..dd09d8e7c6 100644 --- a/src/library/scala/reflect/api/Exprs.scala +++ b/src/library/scala/reflect/api/Exprs.scala @@ -6,14 +6,57 @@ package scala.reflect package api import language.implicitConversions +import scala.reflect.base.TreeCreator 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+")" + 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: TypeTag](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: TypeTag](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[TypeTag[T]] in otherMirror).asInstanceOf[otherMirror.universe.TypeTag[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[TypeTag[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/library/scala/reflect/api/FlagSets.scala b/src/library/scala/reflect/api/FlagSets.scala new file mode 100644 index 0000000000..969176d641 --- /dev/null +++ b/src/library/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/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/FrontEnds.scala b/src/library/scala/reflect/api/FrontEnds.scala index 2c1f3feff6..a201b83444 100644 --- a/src/library/scala/reflect/api/FrontEnds.scala +++ b/src/library/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/library/scala/reflect/api/Importers.scala index 1d8890b7db..69d6414f4f 100644 --- a/src/library/scala/reflect/api/Importers.scala +++ b/src/library/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/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/Mirrors.scala b/src/library/scala/reflect/api/Mirrors.scala new file mode 100644 index 0000000000..2fcee8f227 --- /dev/null +++ b/src/library/scala/reflect/api/Mirrors.scala @@ -0,0 +1,213 @@ +package scala.reflect +package api + +trait Mirrors { self: Universe => + + type RuntimeClass >: Null + + // [Eugene++ to Martin] how do we reflect against inner classes? + // presumably, we should add `reflectClass` to both InstanceMirror (inner classes) and TemplateMirror (nested classes) + // in the former case, the resulting ClassMirror should remember the outer instance that spawned it to use it in reflective construction + + // [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 mirror corresponding to the run-time class of the reflected instance. */ + def reflectClass: ClassMirror + + /** 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 + } + + /** A mirror that reflects a field */ + trait FieldMirror { + + /** The object containing the field */ + def receiver: AnyRef + + /** The field symbol representing the field */ + def field: 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 method: MethodSymbol + + /** The result of applying the method to the given arguments */ + 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 + + // [Eugene++ to Martin] I've removed `typeSignature`, because we can obtain it via `symbol.typeSignature` + + /** 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] + } + + /** The API of a mirror for a reflective universe */ + trait RuntimeMirror extends MirrorOf[Mirrors.this.type] { self => + + /** A reflective mirror for the given object + * @param obj An arbitrary value + * @return The mirror for `obj`. + */ + def reflect(obj: Any): InstanceMirror + + /** A reflective mirror for the given Runtime class + * @param runtimeClass A Runtime class object + * @return The mirror for `runtimeClass` + */ + def reflectClass(runtimeClass: RuntimeClass): ClassMirror + + /** A reflective mirror for the Runtime class with the given name in the + * current classloader. + * @param name The fully qualified name of the class + * @return The mirror for the runtime class with fully qualified name + * `name` in the current class loader. + * @throws java.lang.ClassNotFoundException if no class with that name exists + * to do: throws anything else? + */ + def reflectClass(fullName: String): ClassMirror + + /** A reflective mirror for the given Runtime class + * @param runtimeClass A Runtime class object + * @return The mirror for `runtimeClass` + */ + def reflectModule(runtimeClass: RuntimeClass): ModuleMirror + + /** A reflective mirror for the Runtime class with the given name in the + * current classloader. + * @param name The fully qualified name of the class + * @return The mirror for the runtime class with fully qualified name + * `name` in the current class loader. + * @throws java.lang.ClassNotFoundException if no class with that name exists + * to do: throws anything else? + */ + def reflectModule(fullName: String): ModuleMirror + + /** 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 + } +} 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/Names.scala b/src/library/scala/reflect/api/Names.scala index 96651ffa88..222ee5024b 100755 --- a/src/library/scala/reflect/api/Names.scala +++ b/src/library/scala/reflect/api/Names.scala @@ -10,28 +10,18 @@ package api * Names are interned. That is, for two names `name11 and `name2`, * `name1 == name2` implies `name1 eq name2`. */ -trait Names { - /** The abstract type of names */ - type Name >: Null <: AbsName - - /** The abstract type of names representing terms */ - type TypeName <: Name - - /** The abstract type of names representing types */ - type TermName <: Name +trait Names extends base.Names { - abstract class AbsName { - /** Is this name a term name? */ - def isTermName: Boolean - - /** Is this name a type name? */ - def isTypeName: Boolean + /** The abstract type of names */ + type Name >: Null <: NameApi - /** Returns a term name that represents the same string as this name */ - def toTermName: TermName + /** The extended API of names that's supported on reflect mirror via an + * implicit conversion in reflect.ops + */ + abstract class NameApi extends NameBase { - /** Returns a type name that represents the same string as this name */ - def toTypeName: TypeName + // [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_+=` @@ -51,16 +41,4 @@ trait Names { */ def encodedName: Name } - - /** Create a new term name. - */ - def newTermName(s: String): TermName - - /** Creates a new type name. - */ - def newTypeName(s: String): TypeName - - def EmptyTermName: TermName = newTermName("") - - def EmptyTypeName: TypeName = EmptyTermName.toTypeName } diff --git a/src/library/scala/reflect/api/Positions.scala b/src/library/scala/reflect/api/Positions.scala index 8f01e0ced1..9d3d90d9f8 100644 --- a/src/library/scala/reflect/api/Positions.scala +++ b/src/library/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/library/scala/reflect/api/StandardDefinitions.scala b/src/library/scala/reflect/api/StandardDefinitions.scala index 21f7c9283b..c2a89f92dd 100755 --- a/src/library/scala/reflect/api/StandardDefinitions.scala +++ b/src/library/scala/reflect/api/StandardDefinitions.scala @@ -2,144 +2,47 @@ * 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 { +trait StandardDefinitions extends base.StandardDefinitions { 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 + 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 - - // 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? + 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/library/scala/reflect/api/StandardNames.scala index a17ea216f7..80aed04073 100644 --- a/src/library/scala/reflect/api/StandardNames.scala +++ b/src/library/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,15 @@ 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 MIRROR_FREE_PREFIX: NameType + val MIRROR_FREE_THIS_SUFFIX: NameType + val MIRROR_FREE_VALUE_SUFFIX: NameType + val MIRROR_PREFIX: NameType + val MIRROR_SHORT: NameType + val MIRROR_SYMDEF_PREFIX: NameType val MIXIN_CONSTRUCTOR: TermName val MODULE_INSTANCE_FIELD: TermName val OUTER: TermName @@ -146,7 +139,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 diff --git a/src/library/scala/reflect/api/Symbols.scala b/src/library/scala/reflect/api/Symbols.scala index 32faee2512..1d266dc778 100755 --- a/src/library/scala/reflect/api/Symbols.scala +++ b/src/library/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/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/TreePrinters.scala b/src/library/scala/reflect/api/TreePrinters.scala index 3d64ec8e40..08a08e7b90 100644 --- a/src/library/scala/reflect/api/TreePrinters.scala +++ b/src/library/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/library/scala/reflect/api/Trees.scala b/src/library/scala/reflect/api/Trees.scala index 3427136fde..2d130daa4e 100644 --- a/src/library/scala/reflect/api/Trees.scala +++ b/src/library/scala/reflect/api/Trees.scala @@ -2,169 +2,22 @@ * Copyright 2005-2011 LAMP/EPFL * @author Martin Odersky */ - package scala.reflect package api -import scala.collection.mutable.ListBuffer - // Syncnote: Trees are currently not thread-safe. -trait Trees { self: Universe => +trait Trees extends base.Trees { self: Universe => - private[scala] var nodeCount = 0 + override type Tree >: Null <: TreeApi - type Modifiers >: Null <: AbsModifiers - val NoMods: Modifiers + /** ... */ + trait TreeApi extends TreeBase { this: Tree => - // TODO - Where do I put this? - object BackquotedIdentifier + /** ... */ + def pos: Position - 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 - 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 - 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[this] var rawtpe: Type = _ - - 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) + /** ... */ + 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. @@ -181,887 +34,528 @@ trait Trees { self: Universe => * 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 symbol: Symbol - 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 hasSymbol: Boolean - def hasAssignedType = (tpe ne null) && (tpe ne NoType) - def hasAssignedSymbol = (symbol ne null) && (symbol ne NoSymbol) - - @inline final def hasSymbolWhich(f: Symbol => Boolean) = hasAssignedSymbol && f(symbol) - @inline final def hasTypeWhich(f: Type => Boolean) = hasAssignedType && f(tpe) - - /** The canonical way to test if a Tree represents a term. + /** Provides an alternate if tree is empty + * @param alt The alternate tree + * @return If this tree is non empty, this tree, otherwise `alt`. */ - 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 orElse(alt: => Tree): Tree /** Apply `f` to each subtree */ - def foreach(f: Tree => Unit) { new ForeachTreeTraverser(f).traverse(this) } + def foreach(f: Tree => Unit): Unit - /** Find all subtrees matching predicate `p` */ - 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) + /** Find all subtrees matching predicate `p`. Same as `filter` */ + def withFilter(f: Tree => Boolean): List[Tree] - /** Apply `pf' to each subtree on which the function is defined */ - def collect[T](pf: PartialFunction[Tree, T]): List[T] = { - val ctt = new CollectTreeTraverser[T](pf) - ctt.traverse(this) - ctt.results.toList - } + /** 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] = { - val ft = new FindTreeTraverser(p) - ft.traverse(this) - ft.result - } + 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 = !find(p).isEmpty + def exists(p: Tree => Boolean): Boolean /** Do all parts of this tree satisfy predicate `p`? */ - def forAll(p: Tree => Boolean): Boolean = find(!p(_)).isEmpty - - def equalsStructure(that : Tree) = equalsStructure0(that)(_ eq _) - def equalsStructure0(that: Tree)(f: (Tree,Tree) => Boolean): Boolean = - f(this, that) || ((this.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 (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) - case _ => - true - } - - (this.productIterator zip that.productIterator forall { case (x, y) => equals0(x, y) }) && compareOriginals() - }) + 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] = { - def subtrees(x: Any): List[Tree] = x match { - case EmptyTree => Nil - case t: Tree => List(t) - case xs: List[_] => xs flatMap subtrees - case _ => Nil - } - productIterator.toList flatMap subtrees - } + 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 = - duplicateTree(this).asInstanceOf[this.type] - - private[scala] def copyAttrs(tree: Tree): this.type = { - rawatt = tree.rawatt - tpe = tree.tpe - if (hasSymbol) symbol = tree.symbol - this - } + def duplicate: this.type + } + + override type TermTree >: Null <: Tree with TermTreeApi - override def toString: String = show(this) - override def hashCode(): Int = System.identityHashCode(this) - override def equals(that: Any) = this eq that.asInstanceOf[AnyRef] + /** The API that all term trees support */ + trait TermTreeApi extends TreeApi { this: TermTree => } - /** A tree for a term. Not all terms are TermTrees; use isTerm - * to reliably identify terms. - */ - trait TermTree extends Tree + override type TypTree >: Null <: Tree with TypTreeApi - /** A tree for a type. Not all types are TypTrees; use isType - * to reliably identify types. - */ - trait TypTree extends Tree + /** The API that all typ trees support */ + trait TypTreeApi extends TreeApi { this: TypTree => + } - /** A tree with a mutable symbol field, initialized to NoSymbol. - */ - trait SymTree extends Tree { - override def hasSymbol = true - override var symbol: Symbol = NoSymbol + override type SymTree >: Null <: Tree with SymTreeApi + + /** The API that all sym trees support */ + trait SymTreeApi extends TreeApi { this: SymTree => + def symbol: Symbol } - /** A tree with a name - effectively, a DefTree or RefTree. - */ - trait NameTree extends Tree { + override type NameTree >: Null <: Tree with NameTreeApi + + /** The API that all name trees support */ + trait NameTreeApi extends TreeApi { this: NameTree => 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 { + 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 } - /** A tree which defines a symbol-carrying entity. - */ - abstract class DefTree extends SymTree with NameTree { + 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 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 - } + override type MemberDef >: Null <: DefTree with MemberDefApi - /** Common base class for all member definitions: types, classes, - * objects, packages, vals and vars, defs. - */ - abstract class MemberDef extends DefTree { + /** The API that all member defs support */ + trait MemberDefApi extends DefTreeApi { this: MemberDef => def mods: Modifiers - def keyword: String = this match { - case TypeDef(_, _, _, _) => "type" - case ClassDef(mods, _, _, _) => if (mods hasModifier Modifier.`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 _ => "" - } } - /** A packaging, such as `package pid { stats }` - */ - case class PackageDef(pid: RefTree, stats: List[Tree]) - extends MemberDef { - def name = pid.name - 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] } - /** A common base class for class and object definitions. - */ - abstract class ImplDef extends MemberDef { - def impl: Template + override type ImplDef >: Null <: MemberDef with ImplDefApi + + /** The API that all impl defs support */ + trait ImplDefApi extends MemberDefApi { this: ImplDef => + val impl: Template } - /** A class definition. - */ - case class ClassDef(mods: Modifiers, name: TypeName, tparams: List[TypeDef], impl: Template) - extends ImplDef + override type ClassDef >: Null <: ImplDef with ClassDefApi - /** @param sym the class symbol - * @return the implementation template - */ - def ClassDef(sym: Symbol, impl: Template): ClassDef + /** 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 + } - /** 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 + override type ModuleDef >: Null <: ImplDef with ModuleDefApi - /** - * @param sym the class symbol - * @param impl the implementation template - */ - def ModuleDef(sym: Symbol, impl: Template): ModuleDef + /** The API that all module defs support */ + trait ModuleDefApi extends ImplDefApi { this: ModuleDef => + val mods: Modifiers + val name: TermName + val impl: Template + } - /** A common base class for ValDefs and DefDefs. - */ - abstract class ValOrDefDef extends MemberDef { + 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 } - /** 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 + override type ValDef >: Null <: ValOrDefDef with ValDefApi - def ValDef(sym: Symbol, rhs: Tree): ValDef + /** 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 + } - def ValDef(sym: Symbol): ValDef + override type DefDef >: Null <: ValOrDefDef with DefDefApi - /** 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 + /** 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 + } - def DefDef(sym: Symbol, mods: Modifiers, vparamss: List[List[ValDef]], rhs: Tree): DefDef + override type TypeDef >: Null <: MemberDef with TypeDefApi - def DefDef(sym: Symbol, vparamss: List[List[ValDef]], rhs: Tree): DefDef + /** 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 + } - def DefDef(sym: Symbol, mods: Modifiers, rhs: Tree): DefDef + override type LabelDef >: Null <: DefTree with TermTree with LabelDefApi - def DefDef(sym: Symbol, rhs: Tree): DefDef + /** 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 + } - def DefDef(sym: Symbol, rhs: List[List[Symbol]] => Tree): DefDef + override type ImportSelector >: Null <: ImportSelectorApi - /** 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 - - /** 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) - - /** 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 - */ - 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 - // } + /** The API that all import selectors support */ + trait ImportSelectorApi { this: ImportSelector => + val name: Name + val namePos: Int + val rename: Name + val renamePos: Int } - /** Block of expressions (semicolon separated expressions) */ - case class Block(stats: List[Tree], expr: Tree) - extends TermTree + override type Import >: Null <: SymTree with ImportApi - /** Block factory that flattens directly nested blocks. - */ - def Block(stats: Tree*): Block + /** The API that all imports support */ + trait ImportApi extends SymTreeApi { this: Import => + val expr: Tree + val selectors: List[ImportSelector] + } - /** 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 + override type Template >: Null <: SymTree with TemplateApi - /** casedef shorthand */ - def CaseDef(pat: Tree, body: Tree): CaseDef + /** The API that all templates support */ + trait TemplateApi extends SymTreeApi { this: Template => + val parents: List[Tree] + val self: ValDef + val body: List[Tree] + } - /** Alternatives of patterns, eliminated by explicitouter, except for - * occurrences in encoded Switch stmt (=remaining Match(CaseDef(...)) - */ - case class Alternative(trees: List[Tree]) - extends TermTree + override type Block >: Null <: TermTree with BlockApi - /** Repetition of pattern, eliminated by explicitouter */ - case class Star(elem: Tree) - extends TermTree + /** The API that all blocks support */ + trait BlockApi extends TermTreeApi { this: Block => + val stats: List[Tree] + val expr: Tree + } - /** Bind of a variable to a rhs pattern, eliminated by explicitouter - * - * @param name - * @param body - */ - case class Bind(name: Name, body: Tree) - extends DefTree + override type CaseDef >: Null <: Tree with CaseDefApi - def Bind(sym: Symbol, body: Tree): Bind + /** The API that all case defs support */ + trait CaseDefApi extends TreeApi { this: CaseDef => + val pat: Tree + val guard: Tree + val body: Tree + } - case class UnApply(fun: Tree, args: List[Tree]) - extends TermTree + override type Alternative >: Null <: TermTree with AlternativeApi - /** Array of expressions, needs to be translated in backend, - */ - case class ArrayValue(elemtpt: Tree, elems: List[Tree]) - extends TermTree + /** The API that all alternatives support */ + trait AlternativeApi extends TermTreeApi { this: Alternative => + val trees: List[Tree] + } - /** 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. + override type Star >: Null <: TermTree with StarApi - /** Assignment */ - case class Assign(lhs: Tree, rhs: Tree) - extends TermTree + /** The API that all stars support */ + trait StarApi extends TermTreeApi { this: Star => + val elem: Tree + } - /** 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 - - /** 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)` - */ - case class Match(selector: Tree, cases: List[CaseDef]) - extends TermTree + override type Bind >: Null <: DefTree with BindApi - /** Return expression */ - case class Return(expr: Tree) - extends TermTree with SymTree - // The symbol of a Return node is the enclosing method. + /** The API that all binds support */ + trait BindApi extends DefTreeApi { this: Bind => + val name: Name + val body: Tree + } - case class Try(block: Tree, catches: List[CaseDef], finalizer: Tree) - extends TermTree + override type UnApply >: Null <: TermTree with UnApplyApi - def Try(body: Tree, cases: (Tree, Tree)*): Try + /** The API that all unapplies support */ + trait UnApplyApi extends TermTreeApi { this: UnApply => + val fun: Tree + val args: List[Tree] + } - /** Throw expression */ - case class Throw(expr: Tree) - extends TermTree + override type ArrayValue >: Null <: TermTree with ArrayValueApi - def Throw(tpe: Type, args: Tree*): Throw + /** The API that all array values support */ + trait ArrayValueApi extends TermTreeApi { this: ArrayValue => + val elemtpt: Tree + val elems: List[Tree] + } - /** 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 + override type Function >: Null <: TermTree with SymTree with FunctionApi - /** 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 + /** The API that all functions support */ + trait FunctionApi extends TermTreeApi with SymTreeApi { this: Function => + val vparams: List[ValDef] + val body: Tree + } - /** 0-1 argument list new, based on a type. - */ - def New(tpe: Type, args: Tree*): Tree + override type Assign >: Null <: TermTree with AssignApi - def New(sym: Symbol, args: Tree*): Tree + /** The API that all assigns support */ + trait AssignApi extends TermTreeApi { this: Assign => + val lhs: Tree + val rhs: Tree + } - /** Type annotation, eliminated by explicit outer */ - case class Typed(expr: Tree, tpt: Tree) - extends TermTree + override type AssignOrNamedArg >: Null <: TermTree with AssignOrNamedArgApi - /** 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 { - val fun: Tree - val args: List[Tree] + /** The API that all assigns support */ + trait AssignOrNamedArgApi extends TermTreeApi { this: AssignOrNamedArg => + val lhs: Tree + val rhs: 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 { + override type If >: Null <: TermTree with IfApi - // Testing the above theory re: args.nonEmpty. - require(args.nonEmpty, this) - override def symbol: Symbol = fun.symbol - override def symbol_=(sym: Symbol) { fun.symbol = sym } + /** The API that all ifs support */ + trait IfApi extends TermTreeApi { this: If => + val cond: Tree + val thenp: Tree + val elsep: Tree } - /** Value application */ - case class Apply(fun: Tree, args: List[Tree]) - extends GenericApply { - override def symbol: Symbol = fun.symbol - override def symbol_=(sym: Symbol) { fun.symbol = sym } + 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] } - def Apply(sym: Symbol, args: Tree*): Tree + override type Return >: Null <: TermTree with SymTree with ReturnApi - // 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 - class ApplyToImplicitArgs(fun: Tree, args: List[Tree]) extends Apply(fun, args) + /** The API that all returns support */ + trait ReturnApi extends TermTreeApi { this: Return => + val expr: Tree + } - // 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 - class ApplyImplicitView(fun: Tree, args: List[Tree]) extends Apply(fun, args) + override type Try >: Null <: TermTree with TryApi - // 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" + /** The API that all tries support */ + trait TryApi extends TermTreeApi { this: Try => + val block: Tree + val catches: List[CaseDef] + val finalizer: 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. - */ - 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. + override type Throw >: Null <: TermTree with ThrowApi - /** 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. - override def symbol: Symbol = qual.symbol - override def symbol_=(sym: Symbol) { qual.symbol = sym } + /** The API that all tries support */ + trait ThrowApi extends TermTreeApi { this: Throw => + val expr: Tree } - 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. + override type New >: Null <: TermTree with NewApi - def This(sym: Symbol): Tree + /** The API that all news support */ + trait NewApi extends TermTreeApi { this: New => + val tpt: Tree + } - /** Designator <qualifier> . <name> */ - case class Select(qualifier: Tree, name: Name) - extends RefTree + override type Typed >: Null <: TermTree with TypedApi - def Select(qualifier: Tree, name: String): Select + /** The API that all typeds support */ + trait TypedApi extends TermTreeApi { this: Typed => + val expr: Tree + val tpt: Tree + } - def Select(qualifier: Tree, sym: Symbol): Select + override type GenericApply >: Null <: TermTree with GenericApplyApi - /** Identifier <name> */ - case class Ident(name: Name) extends RefTree { - def qualifier: Tree = EmptyTree - def isBackquoted = this hasAttachment BackquotedIdentifier + /** The API that all applies support */ + trait GenericApplyApi extends TermTreeApi { this: GenericApply => + val fun: Tree + val args: List[Tree] } - def Ident(name: String): Ident + override type TypeApply >: Null <: GenericApply with TypeApplyApi - 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 { - override def symbol: Symbol = ident.symbol - override def symbol_=(sym: Symbol) { ident.symbol = sym } + /** The API that all type applies support */ + trait TypeApplyApi extends GenericApplyApi { this: TypeApply => } - /** Literal */ - case class Literal(value: Constant) - extends TermTree { - assert(value ne null) + override type Apply >: Null <: GenericApply with ApplyApi + + /** The API that all applies support */ + trait ApplyApi extends GenericApplyApi { this: Apply => } -// @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)) + override type ApplyDynamic >: Null <: TermTree with SymTree with ApplyDynamicApi - /** 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 + /** The API that all apply dynamics support */ + trait ApplyDynamicApi extends TermTreeApi with SymTreeApi { this: ApplyDynamic => + val qual: Tree + val args: List[Tree] + } - /** Singleton type, eliminated by RefCheck */ - case class SingletonTypeTree(ref: Tree) - extends TypTree + override type Super >: Null <: TermTree with SuperApi - /** Type selection <qualifier> # <name>, eliminated by RefCheck */ - case class SelectFromTypeTree(qualifier: Tree, name: TypeName) - extends TypTree with RefTree + /** The API that all supers support */ + trait SuperApi extends TermTreeApi { this: Super => + val qual: Tree + val mix: TypeName + } - /** Intersection type <parent1> with ... with <parentN> { <decls> }, eliminated by RefCheck */ - case class CompoundTypeTree(templ: Template) - extends TypTree + override type This >: Null <: TermTree with SymTree with ThisApi - /** Applied type <tpt> [ <args> ], eliminated by RefCheck */ - case class AppliedTypeTree(tpt: Tree, args: List[Tree]) - extends TypTree { - override def symbol: Symbol = tpt.symbol - override def symbol_=(sym: Symbol) { tpt.symbol = sym } + /** The API that all thises support */ + trait ThisApi extends TermTreeApi with SymTreeApi { this: This => + val qual: TypeName } - case class TypeBoundsTree(lo: Tree, hi: Tree) - extends TypTree - - 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 { - private var orig: Tree = null - private[scala] var wasEmpty: Boolean = false - - override def symbol = if (tpe == null) null else tpe.typeSymbol - override def isEmpty = (tpe eq null) || tpe == NoType - - def original: Tree = orig - def setOriginal(tree: Tree): this.type = { - def followOriginal(t: Tree): Tree = t match { - case tt: TypeTree => followOriginal(tt.original) - case t => t - } - - orig = followOriginal(tree) - this setPos tree.pos - } + override type Select >: Null <: RefTree with SelectApi - override def defineType(tp: Type): this.type = { - wasEmpty = isEmpty - setType(tp) - } + /** The API that all selects support */ + trait SelectApi extends RefTreeApi { this: Select => + val qualifier: Tree + val name: Name } - def TypeTree(tp: Type): TypeTree = TypeTree() setType tp + override type Ident >: Null <: RefTree with IdentApi - /** 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) + /** The API that all idents support */ + trait IdentApi extends RefTreeApi { this: Ident => + val name: Name } - 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) + + override type ReferenceToBoxed >: Null <: TermTree with ReferenceToBoxedApi + + /** The API that all references support */ + trait ReferenceToBoxedApi extends TermTreeApi { this: ReferenceToBoxed => + val ident: Tree } - 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) + override type Literal >: Null <: TermTree with LiteralApi + + /** The API that all literals support */ + trait LiteralApi extends TermTreeApi { this: Literal => + val value: Constant } - 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) + + 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 } - 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) + + override type SingletonTypeTree >: Null <: TypTree with SingletonTypeTreeApi + + /** The API that all singleton type trees support */ + trait SingletonTypeTreeApi extends TypTreeApi { this: SingletonTypeTree => + val ref: Tree } - 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) + + 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 } - 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) + + override type CompoundTypeTree >: Null <: TypTree with CompoundTypeTreeApi + + /** The API that all compound type trees support */ + trait CompoundTypeTreeApi extends TypTreeApi { this: CompoundTypeTree => + val templ: Template } - 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) + + 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] } - 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) + + 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 } - 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) - } + override type ExistentialTypeTree >: Null <: TypTree with ExistentialTypeTreeApi - 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) - ) - } + /** The API that all existential type trees support */ + trait ExistentialTypeTreeApi extends TypTreeApi { this: ExistentialTypeTree => + val tpt: Tree + val whereClauses: List[Tree] + } - def atOwner(owner: Symbol)(traverse: => Unit) { - val prevOwner = currentOwner - currentOwner = owner - traverse - currentOwner = prevOwner - } + override type TypeTree >: Null <: TypTree with TypeTreeApi - /** Leave apply available in the generic traverser to do something else. - */ - def apply[T <: Tree](tree: T): T = { traverse(tree); tree } + /** The API that all type trees support */ + trait TypeTreeApi extends TypTreeApi { this: TypeTree => + def original: Tree } - protected def xtraverse(traverser: Traverser, tree: Tree): Unit = throw new MatchError(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 ------------------------------------------------ - // to be implemented in subclasses: + /** The standard (lazy) tree copier + */ type TreeCopier <: TreeCopierOps + val treeCopy: TreeCopier = newLazyTreeCopier + def newStrictTreeCopier: TreeCopier def newLazyTreeCopier: TreeCopier - trait TreeCopierOps { + /** 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 @@ -1107,443 +601,49 @@ trait Trees { self: Universe => 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) - def PackageDef(tree: Tree, pid: RefTree, stats: List[Tree]) = - new PackageDef(pid, stats).copyAttrs(tree) - def ModuleDef(tree: Tree, mods: Modifiers, name: Name, impl: Template) = - new ModuleDef(mods, name.toTermName, impl).copyAttrs(tree) - def ValDef(tree: Tree, mods: Modifiers, name: Name, tpt: Tree, rhs: Tree) = - new ValDef(mods, name.toTermName, tpt, rhs).copyAttrs(tree) - def DefDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree) = - new DefDef(mods, name.toTermName, tparams, vparamss, tpt, rhs).copyAttrs(tree) - def TypeDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], rhs: Tree) = - new TypeDef(mods, name.toTypeName, tparams, rhs).copyAttrs(tree) - def LabelDef(tree: Tree, name: Name, params: List[Ident], rhs: Tree) = - new LabelDef(name.toTermName, params, rhs).copyAttrs(tree) - def Import(tree: Tree, expr: Tree, selectors: List[ImportSelector]) = - new Import(expr, selectors).copyAttrs(tree) - def Template(tree: Tree, parents: List[Tree], self: ValDef, body: List[Tree]) = - new Template(parents, self, body).copyAttrs(tree) - def Block(tree: Tree, stats: List[Tree], expr: Tree) = - new Block(stats, expr).copyAttrs(tree) - def CaseDef(tree: Tree, pat: Tree, guard: Tree, body: Tree) = - new CaseDef(pat, guard, body).copyAttrs(tree) - def Alternative(tree: Tree, trees: List[Tree]) = - new Alternative(trees).copyAttrs(tree) - def Star(tree: Tree, elem: Tree) = - new Star(elem).copyAttrs(tree) - def Bind(tree: Tree, name: Name, body: Tree) = - new Bind(name, body).copyAttrs(tree) - def UnApply(tree: Tree, fun: Tree, args: List[Tree]) = - new UnApply(fun, args).copyAttrs(tree) - def ArrayValue(tree: Tree, elemtpt: Tree, trees: List[Tree]) = - new ArrayValue(elemtpt, trees).copyAttrs(tree) - def Function(tree: Tree, vparams: List[ValDef], body: Tree) = - new Function(vparams, body).copyAttrs(tree) - def Assign(tree: Tree, lhs: Tree, rhs: Tree) = - new Assign(lhs, rhs).copyAttrs(tree) - def AssignOrNamedArg(tree: Tree, lhs: Tree, rhs: Tree) = - new AssignOrNamedArg(lhs, rhs).copyAttrs(tree) - def If(tree: Tree, cond: Tree, thenp: Tree, elsep: Tree) = - new If(cond, thenp, elsep).copyAttrs(tree) - def Match(tree: Tree, selector: Tree, cases: List[CaseDef]) = - new Match(selector, cases).copyAttrs(tree) - def Return(tree: Tree, expr: Tree) = - new Return(expr).copyAttrs(tree) - def Try(tree: Tree, block: Tree, catches: List[CaseDef], finalizer: Tree) = - new Try(block, catches, finalizer).copyAttrs(tree) - def Throw(tree: Tree, expr: Tree) = - new Throw(expr).copyAttrs(tree) - def New(tree: Tree, tpt: Tree) = - new New(tpt).copyAttrs(tree) - def Typed(tree: Tree, expr: Tree, tpt: Tree) = - new Typed(expr, tpt).copyAttrs(tree) - def TypeApply(tree: Tree, fun: Tree, args: List[Tree]) = - new TypeApply(fun, args).copyAttrs(tree) - def Apply(tree: Tree, fun: Tree, args: List[Tree]) = - (tree match { // TODO: use a tree attachment to track whether this is an apply to implicit args or a view - case _: ApplyToImplicitArgs => new ApplyToImplicitArgs(fun, args) - case _: ApplyImplicitView => new ApplyImplicitView(fun, args) - // TODO: ApplyConstructor ??? - case _ => new Apply(fun, args) - }).copyAttrs(tree) - def ApplyDynamic(tree: Tree, qual: Tree, args: List[Tree]) = - new ApplyDynamic(qual, args).copyAttrs(tree) - def Super(tree: Tree, qual: Tree, mix: TypeName) = - new Super(qual, mix).copyAttrs(tree) - def This(tree: Tree, qual: Name) = - 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 ReferenceToBoxed(tree: Tree, idt: Ident) = - new ReferenceToBoxed(idt).copyAttrs(tree) - def Literal(tree: Tree, value: Constant) = - new Literal(value).copyAttrs(tree) - def TypeTree(tree: Tree) = - new TypeTree().copyAttrs(tree) - def Annotated(tree: Tree, annot: Tree, arg: Tree) = - new Annotated(annot, arg).copyAttrs(tree) - def SingletonTypeTree(tree: Tree, ref: Tree) = - new SingletonTypeTree(ref).copyAttrs(tree) - def SelectFromTypeTree(tree: Tree, qualifier: Tree, selector: Name) = - new SelectFromTypeTree(qualifier, selector.toTypeName).copyAttrs(tree) - def CompoundTypeTree(tree: Tree, templ: Template) = - new CompoundTypeTree(templ).copyAttrs(tree) - def AppliedTypeTree(tree: Tree, tpt: Tree, args: List[Tree]) = - new AppliedTypeTree(tpt, args).copyAttrs(tree) - def TypeBoundsTree(tree: Tree, lo: Tree, hi: Tree) = - new TypeBoundsTree(lo, hi).copyAttrs(tree) - def ExistentialTypeTree(tree: Tree, tpt: Tree, whereClauses: List[Tree]) = - new ExistentialTypeTree(tpt, whereClauses).copyAttrs(tree) - } +// ---------------------- traversing and transforming ------------------------------ - class LazyTreeCopier extends TreeCopierOps { - val treeCopy: TreeCopier = newStrictTreeCopier - def ClassDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], impl: Template) = tree match { - case t @ ClassDef(mods0, name0, tparams0, impl0) - if (mods0 == mods) && (name0 == name) && (tparams0 == tparams) && (impl0 == impl) => t - case _ => treeCopy.ClassDef(tree, mods, name, tparams, impl) - } - def PackageDef(tree: Tree, pid: RefTree, stats: List[Tree]) = tree match { - case t @ PackageDef(pid0, stats0) - if (pid0 == pid) && (stats0 == stats) => t - case _ => treeCopy.PackageDef(tree, pid, stats) - } - def ModuleDef(tree: Tree, mods: Modifiers, name: Name, impl: Template) = tree match { - case t @ ModuleDef(mods0, name0, impl0) - if (mods0 == mods) && (name0 == name) && (impl0 == impl) => t - case _ => treeCopy.ModuleDef(tree, mods, name, impl) - } - def ValDef(tree: Tree, mods: Modifiers, name: Name, tpt: Tree, rhs: Tree) = tree match { - case t @ ValDef(mods0, name0, tpt0, rhs0) - if (mods0 == mods) && (name0 == name) && (tpt0 == tpt) && (rhs0 == rhs) => t - case _ => treeCopy.ValDef(tree, mods, name, tpt, rhs) - } - def DefDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree) = tree match { - case t @ DefDef(mods0, name0, tparams0, vparamss0, tpt0, rhs0) - if (mods0 == mods) && (name0 == name) && (tparams0 == tparams) && - (vparamss0 == vparamss) && (tpt0 == tpt) && (rhs == rhs0) => t - case _ => treeCopy.DefDef(tree, mods, name, tparams, vparamss, tpt, rhs) - } - def TypeDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], rhs: Tree) = tree match { - case t @ TypeDef(mods0, name0, tparams0, rhs0) - if (mods0 == mods) && (name0 == name) && (tparams0 == tparams) && (rhs0 == rhs) => t - case _ => treeCopy.TypeDef(tree, mods, name, tparams, rhs) - } - def LabelDef(tree: Tree, name: Name, params: List[Ident], rhs: Tree) = tree match { - case t @ LabelDef(name0, params0, rhs0) - if (name0 == name) && (params0 == params) && (rhs0 == rhs) => t - case _ => treeCopy.LabelDef(tree, name, params, rhs) - } - def Import(tree: Tree, expr: Tree, selectors: List[ImportSelector]) = tree match { - case t @ Import(expr0, selectors0) - if (expr0 == expr) && (selectors0 == selectors) => t - case _ => treeCopy.Import(tree, expr, selectors) - } - def Template(tree: Tree, parents: List[Tree], self: ValDef, body: List[Tree]) = tree match { - case t @ Template(parents0, self0, body0) - if (parents0 == parents) && (self0 == self) && (body0 == body) => t - case _ => treeCopy.Template(tree, parents, self, body) - } - def Block(tree: Tree, stats: List[Tree], expr: Tree) = tree match { - case t @ Block(stats0, expr0) - if ((stats0 == stats) && (expr0 == expr)) => t - case _ => treeCopy.Block(tree, stats, expr) - } - def CaseDef(tree: Tree, pat: Tree, guard: Tree, body: Tree) = tree match { - case t @ CaseDef(pat0, guard0, body0) - if (pat0 == pat) && (guard0 == guard) && (body0 == body) => t - case _ => treeCopy.CaseDef(tree, pat, guard, body) - } - def Alternative(tree: Tree, trees: List[Tree]) = tree match { - case t @ Alternative(trees0) - if trees0 == trees => t - case _ => treeCopy.Alternative(tree, trees) - } - def Star(tree: Tree, elem: Tree) = tree match { - case t @ Star(elem0) - if elem0 == elem => t - case _ => treeCopy.Star(tree, elem) - } - def Bind(tree: Tree, name: Name, body: Tree) = tree match { - case t @ Bind(name0, body0) - if (name0 == name) && (body0 == body) => t - case _ => treeCopy.Bind(tree, name, body) - } - def UnApply(tree: Tree, fun: Tree, args: List[Tree]) = tree match { - case t @ UnApply(fun0, args0) - if (fun0 == fun) && (args0 == args) => t - case _ => treeCopy.UnApply(tree, fun, args) - } - def ArrayValue(tree: Tree, elemtpt: Tree, trees: List[Tree]) = tree match { - case t @ ArrayValue(elemtpt0, trees0) - if (elemtpt0 == elemtpt) && (trees0 == trees) => t - case _ => treeCopy.ArrayValue(tree, elemtpt, trees) - } - def Function(tree: Tree, vparams: List[ValDef], body: Tree) = tree match { - case t @ Function(vparams0, body0) - if (vparams0 == vparams) && (body0 == body) => t - case _ => treeCopy.Function(tree, vparams, body) - } - def Assign(tree: Tree, lhs: Tree, rhs: Tree) = tree match { - case t @ Assign(lhs0, rhs0) - if (lhs0 == lhs) && (rhs0 == rhs) => t - case _ => treeCopy.Assign(tree, lhs, rhs) - } - def AssignOrNamedArg(tree: Tree, lhs: Tree, rhs: Tree) = tree match { - case t @ AssignOrNamedArg(lhs0, rhs0) - if (lhs0 == lhs) && (rhs0 == rhs) => t - case _ => treeCopy.AssignOrNamedArg(tree, lhs, rhs) - } - def If(tree: Tree, cond: Tree, thenp: Tree, elsep: Tree) = tree match { - case t @ If(cond0, thenp0, elsep0) - if (cond0 == cond) && (thenp0 == thenp) && (elsep0 == elsep) => t - case _ => treeCopy.If(tree, cond, thenp, elsep) - } - def Match(tree: Tree, selector: Tree, cases: List[CaseDef]) = tree match { - case t @ Match(selector0, cases0) - if (selector0 == selector) && (cases0 == cases) => t - case _ => treeCopy.Match(tree, selector, cases) - } - def Return(tree: Tree, expr: Tree) = tree match { - case t @ Return(expr0) - if expr0 == expr => t - case _ => treeCopy.Return(tree, expr) - } - def Try(tree: Tree, block: Tree, catches: List[CaseDef], finalizer: Tree) = tree match { - case t @ Try(block0, catches0, finalizer0) - if (block0 == block) && (catches0 == catches) && (finalizer0 == finalizer) => t - case _ => treeCopy.Try(tree, block, catches, finalizer) - } - def Throw(tree: Tree, expr: Tree) = tree match { - case t @ Throw(expr0) - if expr0 == expr => t - case _ => treeCopy.Throw(tree, expr) - } - def New(tree: Tree, tpt: Tree) = tree match { - case t @ New(tpt0) - if tpt0 == tpt => t - case _ => treeCopy.New(tree, tpt) - } - def Typed(tree: Tree, expr: Tree, tpt: Tree) = tree match { - case t @ Typed(expr0, tpt0) - if (expr0 == expr) && (tpt0 == tpt) => t - case _ => treeCopy.Typed(tree, expr, tpt) - } - def TypeApply(tree: Tree, fun: Tree, args: List[Tree]) = tree match { - case t @ TypeApply(fun0, args0) - if (fun0 == fun) && (args0 == args) => t - case _ => treeCopy.TypeApply(tree, fun, args) - } - def Apply(tree: Tree, fun: Tree, args: List[Tree]) = tree match { - case t @ Apply(fun0, args0) - if (fun0 == fun) && (args0 == args) => t - case _ => treeCopy.Apply(tree, fun, args) - } - def ApplyDynamic(tree: Tree, qual: Tree, args: List[Tree]) = tree match { - case t @ ApplyDynamic(qual0, args0) - if (qual0 == qual) && (args0 == args) => t - case _ => treeCopy.ApplyDynamic(tree, qual, args) - } - def Super(tree: Tree, qual: Tree, mix: TypeName) = tree match { - case t @ Super(qual0, mix0) - if (qual0 == qual) && (mix0 == mix) => t - case _ => treeCopy.Super(tree, qual, mix) - } - def This(tree: Tree, qual: Name) = tree match { - case t @ This(qual0) - if qual0 == qual => t - case _ => treeCopy.This(tree, qual) - } - def Select(tree: Tree, qualifier: Tree, selector: Name) = tree match { - case t @ Select(qualifier0, selector0) - if (qualifier0 == qualifier) && (selector0 == selector) => t - case _ => treeCopy.Select(tree, qualifier, selector) - } - def Ident(tree: Tree, name: Name) = tree match { - case t @ Ident(name0) - if name0 == name => t - case _ => treeCopy.Ident(tree, name) - } - def ReferenceToBoxed(tree: Tree, idt: Ident) = tree match { - case t @ ReferenceToBoxed(idt0) - if (idt0 == idt) => t - case _ => this.treeCopy.ReferenceToBoxed(tree, idt) - } - def Literal(tree: Tree, value: Constant) = tree match { - case t @ Literal(value0) - if value0 == value => t - case _ => treeCopy.Literal(tree, value) - } - def TypeTree(tree: Tree) = tree match { - case t @ TypeTree() => t - case _ => treeCopy.TypeTree(tree) - } - def Annotated(tree: Tree, annot: Tree, arg: Tree) = tree match { - case t @ Annotated(annot0, arg0) - if (annot0==annot) => t - case _ => treeCopy.Annotated(tree, annot, arg) - } - def SingletonTypeTree(tree: Tree, ref: Tree) = tree match { - case t @ SingletonTypeTree(ref0) - if ref0 == ref => t - case _ => treeCopy.SingletonTypeTree(tree, ref) - } - def SelectFromTypeTree(tree: Tree, qualifier: Tree, selector: Name) = tree match { - case t @ SelectFromTypeTree(qualifier0, selector0) - if (qualifier0 == qualifier) && (selector0 == selector) => t - case _ => treeCopy.SelectFromTypeTree(tree, qualifier, selector) - } - def CompoundTypeTree(tree: Tree, templ: Template) = tree match { - case t @ CompoundTypeTree(templ0) - if templ0 == templ => t - case _ => treeCopy.CompoundTypeTree(tree, templ) + 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 AppliedTypeTree(tree: Tree, tpt: Tree, args: List[Tree]) = tree match { - case t @ AppliedTypeTree(tpt0, args0) - if (tpt0 == tpt) && (args0 == args) => t - case _ => treeCopy.AppliedTypeTree(tree, tpt, args) + def traverseTreess(treess: List[List[Tree]]) { + treess foreach traverseTrees } - def TypeBoundsTree(tree: Tree, lo: Tree, hi: Tree) = tree match { - case t @ TypeBoundsTree(lo0, hi0) - if (lo0 == lo) && (hi0 == hi) => t - case _ => treeCopy.TypeBoundsTree(tree, lo, hi) + def traverseStats(stats: List[Tree], exprOwner: Symbol) { + stats foreach (stat => + if (exprOwner != currentOwner) atOwner(exprOwner)(traverse(stat)) + else traverse(stat) + ) } - def ExistentialTypeTree(tree: Tree, tpt: Tree, whereClauses: List[Tree]) = tree match { - case t @ ExistentialTypeTree(tpt0, whereClauses0) - if (tpt0 == tpt) && (whereClauses0 == whereClauses) => t - case _ => treeCopy.ExistentialTypeTree(tree, tpt, whereClauses) + + 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 var currentOwner: Symbol = definitions.RootClass + 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 = tree match { - case EmptyTree => - tree - case PackageDef(pid, stats) => - treeCopy.PackageDef( - tree, transform(pid).asInstanceOf[RefTree], - atOwner(tree.symbol.moduleClass) { - transformStats(stats, currentOwner) - } - ) - case ClassDef(mods, name, tparams, impl) => - atOwner(tree.symbol) { - treeCopy.ClassDef(tree, transformModifiers(mods), name, - transformTypeDefs(tparams), transformTemplate(impl)) - } - case ModuleDef(mods, name, impl) => - atOwner(tree.symbol.moduleClass) { - treeCopy.ModuleDef(tree, transformModifiers(mods), - name, transformTemplate(impl)) - } - case ValDef(mods, name, tpt, rhs) => - atOwner(tree.symbol) { - treeCopy.ValDef(tree, transformModifiers(mods), - name, transform(tpt), transform(rhs)) - } - case DefDef(mods, name, tparams, vparamss, tpt, rhs) => - atOwner(tree.symbol) { - treeCopy.DefDef(tree, transformModifiers(mods), name, - transformTypeDefs(tparams), transformValDefss(vparamss), - transform(tpt), transform(rhs)) - } - case TypeDef(mods, name, tparams, rhs) => - atOwner(tree.symbol) { - treeCopy.TypeDef(tree, transformModifiers(mods), name, - transformTypeDefs(tparams), transform(rhs)) - } - case LabelDef(name, params, rhs) => - treeCopy.LabelDef(tree, name, transformIdents(params), transform(rhs)) //bq: Martin, once, atOwner(...) works, also change `LamdaLifter.proxy' - case Import(expr, selectors) => - treeCopy.Import(tree, transform(expr), selectors) - case Template(parents, self, body) => - treeCopy.Template(tree, transformTrees(parents), transformValDef(self), transformStats(body, tree.symbol)) - case Block(stats, expr) => - treeCopy.Block(tree, transformStats(stats, currentOwner), transform(expr)) - case CaseDef(pat, guard, body) => - treeCopy.CaseDef(tree, transform(pat), transform(guard), transform(body)) - case Alternative(trees) => - treeCopy.Alternative(tree, transformTrees(trees)) - case Star(elem) => - treeCopy.Star(tree, transform(elem)) - case Bind(name, body) => - treeCopy.Bind(tree, name, transform(body)) - case UnApply(fun, args) => - treeCopy.UnApply(tree, fun, transformTrees(args)) // bq: see test/.../unapplyContexts2.scala - case ArrayValue(elemtpt, trees) => - treeCopy.ArrayValue(tree, transform(elemtpt), transformTrees(trees)) - case Function(vparams, body) => - atOwner(tree.symbol) { - treeCopy.Function(tree, transformValDefs(vparams), transform(body)) - } - case Assign(lhs, rhs) => - treeCopy.Assign(tree, transform(lhs), transform(rhs)) - case AssignOrNamedArg(lhs, rhs) => - treeCopy.AssignOrNamedArg(tree, transform(lhs), transform(rhs)) - case If(cond, thenp, elsep) => - treeCopy.If(tree, transform(cond), transform(thenp), transform(elsep)) - case Match(selector, cases) => - treeCopy.Match(tree, transform(selector), transformCaseDefs(cases)) - case Return(expr) => - treeCopy.Return(tree, transform(expr)) - case Try(block, catches, finalizer) => - treeCopy.Try(tree, transform(block), transformCaseDefs(catches), transform(finalizer)) - case Throw(expr) => - treeCopy.Throw(tree, transform(expr)) - case New(tpt) => - treeCopy.New(tree, transform(tpt)) - case Typed(expr, tpt) => - treeCopy.Typed(tree, transform(expr), transform(tpt)) - case TypeApply(fun, args) => - treeCopy.TypeApply(tree, transform(fun), transformTrees(args)) - case Apply(fun, args) => - treeCopy.Apply(tree, transform(fun), transformTrees(args)) - case ApplyDynamic(qual, args) => - treeCopy.ApplyDynamic(tree, transform(qual), transformTrees(args)) - case Super(qual, mix) => - treeCopy.Super(tree, transform(qual), mix) - case This(qual) => - treeCopy.This(tree, qual) - case Select(qualifier, selector) => - treeCopy.Select(tree, transform(qualifier), selector) - case Ident(name) => - treeCopy.Ident(tree, name) - case ReferenceToBoxed(idt) => - treeCopy.ReferenceToBoxed(tree, transform(idt) match { case idt1: Ident => idt1 }) - case Literal(value) => - treeCopy.Literal(tree, value) - case TypeTree() => - treeCopy.TypeTree(tree) - case Annotated(annot, arg) => - treeCopy.Annotated(tree, transform(annot), transform(arg)) - case SingletonTypeTree(ref) => - treeCopy.SingletonTypeTree(tree, transform(ref)) - case SelectFromTypeTree(qualifier, selector) => - treeCopy.SelectFromTypeTree(tree, transform(qualifier), selector) - case CompoundTypeTree(templ) => - treeCopy.CompoundTypeTree(tree, transformTemplate(templ)) - case AppliedTypeTree(tpt, args) => - treeCopy.AppliedTypeTree(tree, transform(tpt), transformTrees(args)) - case TypeBoundsTree(lo, hi) => - treeCopy.TypeBoundsTree(tree, transform(lo), transform(hi)) - case ExistentialTypeTree(tpt, whereClauses) => - treeCopy.ExistentialTypeTree(tree, transform(tpt), transformTrees(whereClauses)) - case _ => - xtransform(this, tree) - } +// protected def currentPackage = currentOwner.enclosingTopLevelClass.owner + def transform(tree: Tree): Tree = itransform(this, tree) def transformTrees(trees: List[Tree]): List[Tree] = trees mapConserve (transform(_)) @@ -1577,154 +677,13 @@ trait Trees { self: Universe => } } - protected def xtransform(transformer: Transformer, tree: Tree): Tree = throw new MatchError(tree) - - class ForeachTreeTraverser(f: Tree => Unit) extends Traverser { - override def traverse(t: Tree) { - f(t) - super.traverse(t) - } - } + protected def itransform(transformer: Transformer, tree: Tree): Tree = throw new MatchError(tree) - class FilterTreeTraverser(p: Tree => Boolean) extends Traverser { - val hits = new ListBuffer[Tree] - override def traverse(t: Tree) { - if (p(t)) hits += t - super.traverse(t) - } - } + protected def xtransform(transformer: Transformer, tree: Tree): Tree = throw new MatchError(tree) - class CollectTreeTraverser[T](pf: PartialFunction[Tree, T]) extends Traverser { - val results = new ListBuffer[T] - override def traverse(t: Tree) { - if (pf.isDefinedAt(t)) results += pf(t) - super.traverse(t) - } - } + type Modifiers >: Null <: ModifiersApi - class FindTreeTraverser(p: Tree => Boolean) extends Traverser { - var result: Option[Tree] = None - override def traverse(t: Tree) { - if (result.isEmpty) { - if (p(t)) result = Some(t) - super.traverse(t) - } - } - } + abstract class ModifiersApi extends ModifiersBase with HasFlagsApi - 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 } -*/ } diff --git a/src/library/scala/reflect/api/Types.scala b/src/library/scala/reflect/api/Types.scala index 3d42242641..b62a92cbd7 100755 --- a/src/library/scala/reflect/api/Types.scala +++ b/src/library/scala/reflect/api/Types.scala @@ -1,15 +1,13 @@ package scala.reflect package api -trait Types { self: Universe => +trait Types extends base.Types { self: Universe => - /** This class declares operations that are visible in a Type. + override type Type >: Null <: TypeApi + + /** The extended API of types */ - abstract class AbsType { - /** The type symbol associated with the type, or `NoSymbol` for types - * that do not refer to a type symbol. - */ - def typeSymbol: Symbol + 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. @@ -18,6 +16,7 @@ trait Types { self: Universe => def declaration(name: Name): Symbol /** The collection of declarations in this type + * [Eugene++] why not List? */ def declarations: Iterable[Symbol] @@ -34,6 +33,7 @@ trait Types { self: Universe => /** 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] @@ -43,6 +43,11 @@ trait Types { self: Universe => */ 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. */ @@ -166,304 +171,133 @@ trait Types { self: Universe => */ def widen: Type - /** The kind of this type; used for debugging */ + /** The string discriminator of this type; useful 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. - */ - val WildcardType: Type - - /** 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. - */ - type BoundedWildcardType >: Null <: Type - - val BoundedWildcardType: BoundedWildcardTypeExtractor + /** .. */ + override type ThisType >: Null <: SingletonType with ThisTypeApi - abstract class BoundedWildcardTypeExtractor { - def apply(bounds: TypeBounds): BoundedWildcardType - def unapply(tpe: BoundedWildcardType): Option[TypeBounds] + /** The API that all this types support */ + trait ThisTypeApi extends TypeApi { this: ThisType => + val sym: Symbol } - /** The type of Scala types, and also Scala type signatures. - * (No difference is internally made between the two). - */ - type Type >: Null <: AbsType - - /** The type of Scala singleton types, i.e. types that are inhabited - * by only one nun-null value. These include types of the forms - * {{{ - * C.this.type - * C.super.type - * x.type - * }}} - * as well as constant types. - */ - type SingletonType >: Null <: Type + /** .. */ + override type SingleType >: Null <: SingletonType with SingleTypeApi - /** 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`. - */ - val NoPrefix: Type - - /** The `ThisType` type describes types of the form on the left with the - * correspnding ThisType representations to the right. - * {{{ - * C.this.type ThisType(C) - * }}} - */ - type ThisType <: SingletonType - - /** The constructor/deconstructor for `ThisType` instances. */ - val ThisType: ThisTypeExtractor - - /** An extractor class to create and pattern match with syntax `ThisType(sym)` - * where `sym` is the class prefix of the this type. - */ - abstract class ThisTypeExtractor { - def apply(sym: Symbol): Type - def unapply(tpe: ThisType): Option[Symbol] + /** The API that all single types support */ + trait SingleTypeApi extends TypeApi { this: SingleType => + val pre: Type + val sym: 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 + /** .. */ + override type SuperType >: Null <: SingletonType with SuperTypeApi - /** 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 API that all super types support */ + trait SuperTypeApi extends TypeApi { this: SuperType => + val thistpe: Type + val supertpe: Type } - /** The `SingleType` type describes types of any of the forms on the left, - * with their TypeRef representations to the right. - * {{{ - * (T # x).type SingleType(T, x) - * p.x.type SingleType(p.type, x) - * x.type SingleType(NoPrefix, x) - * }}} - */ - type SingleType <: SingletonType + /** .. */ + override type ConstantType >: Null <: SingletonType with ConstantTypeApi - /** The constructor/deconstructor for `SingleType` instances. */ - val SingleType: SingleTypeExtractor - - /** An extractor class to create and pattern match with syntax `SingleType(pre, sym)` - * Here, `pre` is the prefix of the single-type, and `sym` is the stable value symbol - * referred to by the single-type. - */ - abstract class SingleTypeExtractor { - def apply(pre: Type, sym: Symbol): Type - def unapply(tpe: SingleType): Option[(Type, Symbol)] + /** The API that all constant types support */ + trait ConstantTypeApi extends TypeApi { this: ConstantType => + val value: Constant } - /** The `SuperType` type is not directly written, but arises when `C.super` is used - * as a prefix in a `TypeRef` or `SingleType`. It's internal presentation is - * {{{ - * SuperType(thistpe, supertpe) - * }}} - * Here, `thistpe` is the type of the corresponding this-type. For instance, - * 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 - - /** The constructor/deconstructor for `SuperType` instances. */ - val SuperType: SuperTypeExtractor + /** .. */ + override type TypeRef >: Null <: Type with TypeRefApi - /** An extractor class to create and pattern match with syntax `SingleType(thistpe, supertpe)` - */ - abstract class SuperTypeExtractor { - def apply(thistpe: Type, supertpe: Type): Type - def unapply(tpe: SuperType): Option[(Type, Type)] + /** The API that all type refs support */ + trait TypeRefApi extends TypeApi { this: TypeRef => + val pre: Type + val sym: Symbol + val args: List[Type] } - /** The `ConstantType` type is not directly written in user programs, but arises as the type of a constant. - * The REPL expresses constant types like Int(11). Here are some constants with their types. - * {{{ - * 1 ConstantType(Constant(1)) - * "abc" ConstantType(Constant("abc")) - * }}} - */ - type ConstantType <: SingletonType - - /** The constructor/deconstructor for `ConstantType` instances. */ - val ConstantType: ConstantTypeExtractor + /** .. */ + override type RefinedType >: Null <: CompoundType with RefinedTypeApi - /** An extractor class to create and pattern match with syntax `ConstantType(constant)` - * Here, `constant` is the constant value represented by the type. - */ - abstract class ConstantTypeExtractor { - def apply(value: Constant): ConstantType - def unapply(tpe: ConstantType): Option[Constant] + /** The API that all refined types support */ + trait RefinedTypeApi extends TypeApi { this: RefinedType => + val parents: List[Type] + val decls: Scope } - /** A subtype of Type representing refined types as well as `ClassInfo` signatures. - */ - type CompoundType <: Type + /** .. */ + override type ClassInfoType >: Null <: CompoundType with ClassInfoTypeApi - /** The `RefinedType` type defines types of any of the forms on the left, - * with their RefinedType representations to the right. - * {{{ - * P_1 with ... with P_m { D_1; ...; D_n} RefinedType(List(P_1, ..., P_m), Scope(D_1, ..., D_n)) - * P_1 with ... with P_m RefinedType(List(P_1, ..., P_m), Scope()) - * { D_1; ...; D_n} RefinedType(List(AnyRef), Scope(D_1, ..., D_n)) - * }}} - */ - type RefinedType <: CompoundType - - /** The constructor/deconstructor for `RefinedType` instances. */ - val RefinedType: RefinedTypeExtractor - - /** An extractor class to create and pattern match with syntax `RefinedType(parents, decls)` - * Here, `parents` is the list of parent types of the class, and `decls` is the scope - * containing all declarations in the class. - */ - abstract class RefinedTypeExtractor { - def apply(parents: List[Type], decls: Scope): RefinedType - - /** An alternative constructor that passes in the synthetic classs symbol - * that backs the refined type. (Normally, a fresh class symbol is created automatically). - */ - def apply(parents: List[Type], decls: Scope, clazz: Symbol): RefinedType - def unapply(tpe: RefinedType): Option[(List[Type], Scope)] + /** The API that all class info types support */ + trait ClassInfoTypeApi extends TypeApi { this: ClassInfoType => + val parents: List[Type] + val decls: Scope + val typeSymbol: Symbol } - type NullaryMethodType <: Type - val NullaryMethodType: NullaryMethodTypeExtractor + /** .. */ + override type MethodType >: Null <: Type with MethodTypeApi - type PolyType <: Type - val PolyType: PolyTypeExtractor - - type ExistentialType <: Type - val ExistentialType: ExistentialTypeExtractor + /** The API that all method types support */ + trait MethodTypeApi extends TypeApi { this: MethodType => + val params: List[Symbol] + val resultType: Type + } - type AnnotatedType <: Type - val AnnotatedType: AnnotatedTypeExtractor + /** .. */ + override type NullaryMethodType >: Null <: Type with NullaryMethodTypeApi - /** The `MethodType` type signature is used to indicate parameters and result type of a method - */ - type MethodType <: Type + /** The API that all nullary method types support */ + trait NullaryMethodTypeApi extends TypeApi { this: NullaryMethodType => + val resultType: Type + } - /** The constructor/deconstructor for `MethodType` instances. */ - val MethodType: MethodTypeExtractor + /** .. */ + override type PolyType >: Null <: Type with PolyTypeApi - /** An extractor class to create and pattern match with syntax `MethodType(params, respte)` - * Here, `params` is a potentially empty list of parameter symbols of the method, - * and `restpe` is the result type of the method. If the method is curried, `restpe` would - * be another `MethodType`. - * Note: `MethodType(Nil, Int)` would be the type of a method defined with an empty parameter list. - * {{{ - * def f(): Int - * }}} - * If the method is completely parameterless, as in - * {{{ - * def f: Int - * }}} - * its type is a `NullaryMethodType`. - */ - abstract class MethodTypeExtractor { - def apply(params: List[Symbol], resultType: Type): MethodType - def unapply(tpe: MethodType): Option[(List[Symbol], Type)] + /** The API that all polymorphic types support */ + trait PolyTypeApi extends TypeApi { this: PolyType => + val typeParams: List[Symbol] + val resultType: 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) - * }}} - */ - type TypeBounds <: Type + /** .. */ + override type ExistentialType >: Null <: Type with ExistentialTypeApi - /** 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. - */ - abstract class TypeBoundsExtractor { - def apply(lo: Type, hi: Type): TypeBounds - def unapply(tpe: TypeBounds): Option[(Type, Type)] + /** The API that all existential types support */ + trait ExistentialTypeApi extends TypeApi { this: ExistentialType => + val quantified: List[Symbol] + val underlying: Type } - /** 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 + /** .. */ + override type AnnotatedType >: Null <: Type with AnnotatedTypeApi - /** The constructor/deconstructor for `ClassInfoType` instances. */ - val ClassInfoType: ClassInfoTypeExtractor - - /** 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, clazz: Symbol): ClassInfoType - def unapply(tpe: ClassInfoType): Option[(List[Type], Scope, Symbol)] + /** The API that all annotated types support */ + trait AnnotatedTypeApi extends TypeApi { this: AnnotatedType => + val annotations: List[AnnotationInfo] + val underlying: Type + val selfsym: Symbol } - abstract class NullaryMethodTypeExtractor { - def apply(resultType: Type): NullaryMethodType - def unapply(tpe: NullaryMethodType): Option[(Type)] - } + /** .. */ + override type TypeBounds >: Null <: Type with TypeBoundsApi - abstract class PolyTypeExtractor { - def apply(typeParams: List[Symbol], resultType: Type): PolyType - def unapply(tpe: PolyType): Option[(List[Symbol], Type)] + /** The API that all type bounds support */ + trait TypeBoundsApi extends TypeApi { this: TypeBounds => + val lo: Type + val hi: Type } - abstract class ExistentialTypeExtractor { - def apply(quantified: List[Symbol], underlying: Type): ExistentialType - def unapply(tpe: ExistentialType): Option[(List[Symbol], Type)] - } + /** .. */ + override type BoundedWildcardType >: Null <: Type with BoundedWildcardTypeApi - abstract class AnnotatedTypeExtractor { - def apply(annotations: List[AnnotationInfo], underlying: Type, selfsym: Symbol): AnnotatedType - def unapply(tpe: AnnotatedType): Option[(List[AnnotationInfo], Type, Symbol)] + /** 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 `<:<`. */ diff --git a/src/library/scala/reflect/api/Universe.scala b/src/library/scala/reflect/api/Universe.scala index ce1b806812..002cd2e673 100755 --- a/src/library/scala/reflect/api/Universe.scala +++ b/src/library/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. @@ -36,17 +33,17 @@ abstract class Universe extends Symbols * * {{{ * <[ - * 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) = { * ... diff --git a/src/library/scala/reflect/api/package.scala b/src/library/scala/reflect/api/package.scala new file mode 100644 index 0000000000..d2fce7cf1d --- /dev/null +++ b/src/library/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/base/AnnotationInfos.scala b/src/library/scala/reflect/base/AnnotationInfos.scala new file mode 100644 index 0000000000..f03644deef --- /dev/null +++ b/src/library/scala/reflect/base/AnnotationInfos.scala @@ -0,0 +1,44 @@ +package scala.reflect +package base + +trait AnnotationInfos { self: Universe => + + type AnnotationInfo >: Null <: AnyRef + implicit val AnnotationInfoTag: ClassTag[AnnotationInfo] + val AnnotationInfo: AnnotationInfoExtractor + + abstract class AnnotationInfoExtractor { + def apply(atp: Type, args: List[Tree], assocs: List[(Name, ClassfileAnnotArg)]): AnnotationInfo + def unapply(info: AnnotationInfo): Option[(Type, List[Tree], List[(Name, ClassfileAnnotArg)])] + } + + type ClassfileAnnotArg >: Null <: AnyRef + implicit val ClassfileAnnotArgTag: ClassTag[ClassfileAnnotArg] + + type LiteralAnnotArg >: Null <: AnyRef with ClassfileAnnotArg + implicit val LiteralAnnotArgTag: ClassTag[LiteralAnnotArg] + val LiteralAnnotArg: LiteralAnnotArgExtractor + + 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(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 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..76606ca958 --- /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].erasure)).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].erasure) + 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/base/Names.scala b/src/library/scala/reflect/base/Names.scala new file mode 100644 index 0000000000..edf2ba7dc9 --- /dev/null +++ b/src/library/scala/reflect/base/Names.scala @@ -0,0 +1,53 @@ +package scala.reflect +package base + +/** 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 { + + /** The abstract type of names */ + type Name >: Null <: NameBase + implicit val NameTag: ClassTag[Name] + + /** The abstract type of names representing terms */ + type TypeName >: Null <: Name + implicit val TypeNameTag: ClassTag[TypeName] + + /** The abstract type of names representing types */ + type TermName >: Null <: Name + implicit val TermNameTag: ClassTag[TermName] + + /** The base API that all names support */ + abstract class NameBase { + /** Is this name a term name? */ + def isTermName: Boolean + + /** Is this name a type name? */ + def isTypeName: Boolean + + /** Returns a term name that represents the same string as this name */ + def toTermName: TermName + + /** Returns a type name that represents the same string as this name */ + def toTypeName: TypeName + } + + /** Create a new term name. + */ + def newTermName(s: String): TermName + + /** Creates a new type name. + */ + def newTypeName(s: String): TypeName + + def EmptyTermName: TermName = newTermName("") + + def EmptyTypeName: TypeName = EmptyTermName.toTypeName +} 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..0ec4d06a6c --- /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 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]]) + } + } + + // [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_concretetypetags_are_manifests.scala + + // [Eugene++] would be great if we could approximate the interop without any mirrors + // todo. think how to implement that + + def concreteTypeTagToManifest[T: ClassTag](mirror: Any, tag: base.Universe # ConcreteTypeTag[T]): Manifest[T] = + throw new UnsupportedOperationException("This universe does not support tag -> manifest conversions. Use scala.reflect.runtime.universe from scala-reflect.jar.") + + def manifestToConcreteTypeTag[T](mirror: Any, manifest: Manifest[T]): base.Universe # ConcreteTypeTag[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/api/TypeTags.scala b/src/library/scala/reflect/base/TypeTags.scala index c58b0fcec2..5c55f45cf7 100644 --- a/src/library/scala/reflect/api/TypeTags.scala +++ b/src/library/scala/reflect/base/TypeTags.scala @@ -4,7 +4,7 @@ */ package scala.reflect -package api +package base import java.lang.{ Class => jClass } import language.implicitConversions @@ -16,34 +16,29 @@ import language.implicitConversions * * === 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]]. + * Type tags are organized in a hierarchy of four classes: + * [[scala.reflect.ArrayTag]], [[scala.reflect.ClassTag]], + * [[scala.reflect.base.Universe#TypeTag]] and [[scala.reflect.base.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, + * Typically such operation is performed by storing an erasure and instantiating arrays via 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]]. + * A [[scala.reflect.ClassTag]] is a standard implementation of [[scala.reflect.ArrayTag]]. * 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]] + * A [[scala.reflect.base.Universe#TypeTag]] value wraps a full Scala type in its tpe field. + * A [[scala.reflect.base.Universe#ConcreteTypeTag]] value is a [[scala.reflect.base.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. + * use ArrayTag when you just want to construct arrays, + * use ClassTag only when you need an erasure, e.g. for serialization or pattern matching. + * + * [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 === * @@ -63,9 +58,9 @@ import language.implicitConversions * * 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 === + * === TypeTag vs ConcreteTypeTag === * - * Be careful with ErasureTag and TypeTag, because they will reify types even if these types are abstract. + * Be careful with TypeTag, 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: * @@ -77,7 +72,7 @@ import language.implicitConversions * } * * 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 + * into the heart of the REPL. Using a [[scala.reflect.base.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, @@ -100,10 +95,11 @@ import language.implicitConversions * 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. + * // [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 + * 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). @@ -111,6 +107,7 @@ import language.implicitConversions * 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 => /** @@ -119,23 +116,19 @@ trait TypeTags { self: Universe => * 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]] + * @see [[scala.reflect.base.TypeTags]] */ @annotation.implicitNotFound(msg = "No TypeTag available for ${T}") - trait TypeTag[T] extends ErasureTag[T] with Equals with Serializable { - + trait TypeTag[T] extends Equals with Serializable { + val mirror: Mirror + def in[U <: Universe with Singleton](otherMirror: MirrorOf[U]): U # TypeTag[T] 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[?]" + 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 { @@ -150,16 +143,12 @@ trait TypeTags { self: Universe => 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 { + 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]] @@ -171,58 +160,56 @@ trait TypeTags { self: Universe => 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 } + case _ => new TypeTagImpl[T](mirror1.asInstanceOf[Mirror], tpec1) } def unapply[T](ttag: TypeTag[T]): Option[Type] = Some(ttag.tpe) } + private class TypeTagImpl[T](val mirror: Mirror, val tpec: TypeCreator) extends TypeTag[T] { + lazy val tpe: Type = tpec[self.type](mirror) + 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) + } + } + /** * 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]] + * @see [[scala.reflect.base.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)) - } - + trait ConcreteTypeTag[T] extends TypeTag[T] with Equals with Serializable { /** 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[?]" + override def canEqual(x: Any) = x.isInstanceOf[ConcreteTypeTag[_]] + override def equals(x: Any) = x.isInstanceOf[ConcreteTypeTag[_]] && this.mirror == x.asInstanceOf[ConcreteTypeTag[_]].mirror && this.tpe == x.asInstanceOf[ConcreteTypeTag[_]].tpe + override def hashCode = mirror.hashCode * 31 + tpe.hashCode + override def toString = "ConcreteTypeTag[" + tpe + "]" } 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 { + val Byte: ConcreteTypeTag[scala.Byte] = new PredefConcreteTypeTag[scala.Byte] (ByteTpe, _.ConcreteTypeTag.Byte) + val Short: ConcreteTypeTag[scala.Short] = new PredefConcreteTypeTag[scala.Short] (ShortTpe, _.ConcreteTypeTag.Short) + val Char: ConcreteTypeTag[scala.Char] = new PredefConcreteTypeTag[scala.Char] (CharTpe, _.ConcreteTypeTag.Char) + val Int: ConcreteTypeTag[scala.Int] = new PredefConcreteTypeTag[scala.Int] (IntTpe, _.ConcreteTypeTag.Int) + val Long: ConcreteTypeTag[scala.Long] = new PredefConcreteTypeTag[scala.Long] (LongTpe, _.ConcreteTypeTag.Long) + val Float: ConcreteTypeTag[scala.Float] = new PredefConcreteTypeTag[scala.Float] (FloatTpe, _.ConcreteTypeTag.Float) + val Double: ConcreteTypeTag[scala.Double] = new PredefConcreteTypeTag[scala.Double] (DoubleTpe, _.ConcreteTypeTag.Double) + val Boolean: ConcreteTypeTag[scala.Boolean] = new PredefConcreteTypeTag[scala.Boolean] (BooleanTpe, _.ConcreteTypeTag.Boolean) + val Unit: ConcreteTypeTag[scala.Unit] = new PredefConcreteTypeTag[scala.Unit] (UnitTpe, _.ConcreteTypeTag.Unit) + val Any: ConcreteTypeTag[scala.Any] = new PredefConcreteTypeTag[scala.Any] (AnyTpe, _.ConcreteTypeTag.Any) + val Object: ConcreteTypeTag[java.lang.Object] = new PredefConcreteTypeTag[java.lang.Object] (ObjectTpe, _.ConcreteTypeTag.Object) + val Nothing: ConcreteTypeTag[scala.Nothing] = new PredefConcreteTypeTag[scala.Nothing] (NothingTpe, _.ConcreteTypeTag.Nothing) + val Null: ConcreteTypeTag[scala.Null] = new PredefConcreteTypeTag[scala.Null] (NullTpe, _.ConcreteTypeTag.Null) + val String: ConcreteTypeTag[java.lang.String] = new PredefConcreteTypeTag[java.lang.String] (StringTpe, _.ConcreteTypeTag.String) + + def apply[T](mirror1: MirrorOf[self.type], tpec1: TypeCreator): ConcreteTypeTag[T] = + tpec1(mirror1) match { case ByteTpe => ConcreteTypeTag.Byte.asInstanceOf[ConcreteTypeTag[T]] case ShortTpe => ConcreteTypeTag.Short.asInstanceOf[ConcreteTypeTag[T]] case CharTpe => ConcreteTypeTag.Char.asInstanceOf[ConcreteTypeTag[T]] @@ -234,21 +221,33 @@ trait TypeTags { self: Universe => 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 } + case _ => new ConcreteTypeTagImpl[T](mirror1.asInstanceOf[Mirror], tpec1) } - def unapply[T](ttag: TypeTag[T]): Option[Type] = if (ttag.isConcrete) Some(ttag.tpe) else None + def unapply[T](ttag: ConcreteTypeTag[T]): Option[Type] = Some(ttag.tpe) + } + + private class ConcreteTypeTagImpl[T](mirror: Mirror, tpec: TypeCreator) extends TypeTagImpl[T](mirror, tpec) with ConcreteTypeTag[T] { + override def in[U <: Universe with Singleton](otherMirror: MirrorOf[U]): U # TypeTag[T] = { + val otherMirror1 = otherMirror.asInstanceOf[MirrorOf[otherMirror.universe.type]] + otherMirror.universe.ConcreteTypeTag[T](otherMirror1, tpec) + } } - // 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 + private class PredefConcreteTypeTag[T](_tpe: Type, copyIn: Universe => Universe # TypeTag[T]) extends ConcreteTypeTagImpl[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 + def concreteTypeTag[T](implicit cttag: ConcreteTypeTag[T]) = cttag + + // 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/base/Types.scala b/src/library/scala/reflect/base/Types.scala new file mode 100644 index 0000000000..6106e3fde7 --- /dev/null +++ b/src/library/scala/reflect/base/Types.scala @@ -0,0 +1,432 @@ +package scala.reflect +package base + +trait Types { self: Universe => + + /** 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 type of Scala types, and also Scala type signatures. + * (No difference is internally made between the two). + */ + type Type >: Null <: TypeBase + + /** A tag that preserves the identity of the `Type` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val TypeTagg: ClassTag[Type] // [Eugene++] rename! + + /** 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`. + */ + 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 + * {{{ + * C.this.type + * C.super.type + * x.type + * }}} + * as well as constant types. + */ + type SingletonType >: Null <: Type + + /** A tag that preserves the identity of the `SingletonType` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val SingletonTypeTag: ClassTag[SingletonType] + + /** The `ThisType` type describes types of the form on the left with the + * correspnding ThisType representations to the right. + * {{{ + * C.this.type ThisType(C) + * }}} + */ + 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 + + /** An extractor class to create and pattern match with syntax `ThisType(sym)` + * where `sym` is the class prefix of the this type. + */ + abstract class ThisTypeExtractor { + def apply(sym: Symbol): Type // not ThisTypebecause of implementation details + def unapply(tpe: ThisType): Option[Symbol] + } + + /** The `SingleType` type describes types of any of the forms on the left, + * with their TypeRef representations to the right. + * {{{ + * (T # x).type SingleType(T, x) + * p.x.type SingleType(p.type, x) + * x.type SingleType(NoPrefix, x) + * }}} + */ + 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 + + /** An extractor class to create and pattern match with syntax `SingleType(pre, sym)` + * Here, `pre` is the prefix of the single-type, and `sym` is the stable value symbol + * referred to by the single-type. + */ + abstract class SingleTypeExtractor { + def apply(pre: Type, sym: Symbol): Type // not SingleTypebecause of implementation details + def unapply(tpe: SingleType): Option[(Type, Symbol)] + } + + /** The `SuperType` type is not directly written, but arises when `C.super` is used + * as a prefix in a `TypeRef` or `SingleType`. It's internal presentation is + * {{{ + * SuperType(thistpe, supertpe) + * }}} + * Here, `thistpe` is the type of the corresponding this-type. For instance, + * 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 >: 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 + + /** An extractor class to create and pattern match with syntax `SingleType(thistpe, supertpe)` + */ + abstract class SuperTypeExtractor { + def apply(thistpe: Type, supertpe: Type): Type // not SuperTypebecause of implementation details + def unapply(tpe: SuperType): Option[(Type, Type)] + } + + /** The `ConstantType` type is not directly written in user programs, but arises as the type of a constant. + * The REPL expresses constant types like Int(11). Here are some constants with their types. + * {{{ + * 1 ConstantType(Constant(1)) + * "abc" ConstantType(Constant("abc")) + * }}} + */ + 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 + + /** An extractor class to create and pattern match with syntax `ConstantType(constant)` + * Here, `constant` is the constant value represented by the type. + */ + abstract class ConstantTypeExtractor { + def apply(value: Constant): ConstantType + 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 >: 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. + * {{{ + * P_1 with ... with P_m { D_1; ...; D_n} RefinedType(List(P_1, ..., P_m), Scope(D_1, ..., D_n)) + * P_1 with ... with P_m RefinedType(List(P_1, ..., P_m), Scope()) + * { D_1; ...; D_n} RefinedType(List(AnyRef), Scope(D_1, ..., D_n)) + * }}} + */ + 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 + + /** An extractor class to create and pattern match with syntax `RefinedType(parents, decls)` + * Here, `parents` is the list of parent types of the class, and `decls` is the scope + * containing all declarations in the class. + */ + abstract class RefinedTypeExtractor { + def apply(parents: List[Type], decls: Scope): RefinedType + + /** An alternative constructor that passes in the synthetic classs symbol + * that backs the refined type. (Normally, a fresh class symbol is created automatically). + */ + def apply(parents: List[Type], decls: Scope, clazz: Symbol): RefinedType + def unapply(tpe: RefinedType): Option[(List[Type], Scope)] + } + + /** 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 + + /** 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] + + /** The constructor/deconstructor for `ClassInfoType` instances. */ + val ClassInfoType: ClassInfoTypeExtractor + + /** 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 >: 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 + + /** An extractor class to create and pattern match with syntax `MethodType(params, respte)` + * Here, `params` is a potentially empty list of parameter symbols of the method, + * and `restpe` is the result type of the method. If the method is curried, `restpe` would + * be another `MethodType`. + * Note: `MethodType(Nil, Int)` would be the type of a method defined with an empty parameter list. + * {{{ + * def f(): Int + * }}} + * If the method is completely parameterless, as in + * {{{ + * def f: Int + * }}} + * its type is a `NullaryMethodType`. + */ + abstract class MethodTypeExtractor { + def apply(params: List[Symbol], resultType: Type): MethodType + def unapply(tpe: MethodType): Option[(List[Symbol], Type)] + } + + /** The `NullaryMethodType` type signature is used for parameterless methods + * with declarations of the form `def foo: T` + */ + type NullaryMethodType >: Null <: AnyRef with Type + + /** A tag that preserves the identity of the `NullaryMethodType` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val NullaryMethodTypeTag: ClassTag[NullaryMethodType] + + /** The constructor/deconstructor for `NullaryMethodType` instances. */ + val NullaryMethodType: NullaryMethodTypeExtractor + + /** An extractor class to create and pattern match with syntax `NullaryMethodType(resultType)`. + * Here, `resultType` is the result type of the parameterless method. + */ + 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 `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 + + /** 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 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. + */ + abstract class TypeBoundsExtractor { + def apply(lo: Type, hi: Type): TypeBounds + def unapply(tpe: TypeBounds): Option[(Type, Type)] + } + + /** An object representing an unknown type, used during type inference. + * If you see WildcardType outside of inference it is almost certainly a bug. + */ + val WildcardType: Type + + /** 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. + */ + type BoundedWildcardType >: Null <: AnyRef with Type + + /** A tag that preserves the identity of the `BoundedWildcardType` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val BoundedWildcardTypeTag: ClassTag[BoundedWildcardType] + + 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..7bfe9f38e1 --- /dev/null +++ b/src/library/scala/reflect/compat.scala @@ -0,0 +1,29 @@ +// [Eugene++] delete this once we merge with trunk and have a working IDE + +package scala.reflect { + trait ErasureTag[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 materializeErasureTag[T](u: BaseUniverse): ErasureTag[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 index 38b1065a40..d7dd111f22 100644 --- a/src/library/scala/reflect/makro/Aliases.scala +++ b/src/library/scala/reflect/makro/Aliases.scala @@ -8,14 +8,16 @@ trait Aliases { type Type = mirror.Type type Name = mirror.Name type Tree = mirror.Tree - type Position = mirror.Position + // type Position = mirror.Position type Scope = mirror.Scope type Modifiers = mirror.Modifiers type Expr[+T] = mirror.Expr[T] type TypeTag[T] = mirror.TypeTag[T] + type ConcreteTypeTag[T] = mirror.ConcreteTypeTag[T] /** Creator/extractor objects for Expr and TypeTag values */ val TypeTag = mirror.TypeTag + val ConcreteTypeTag = mirror.ConcreteTypeTag val Expr = mirror.Expr /** incantations for summoning tags */ diff --git a/src/library/scala/reflect/makro/Context.scala b/src/library/scala/reflect/makro/Context.scala index b0e15fd572..fb77405d37 100644 --- a/src/library/scala/reflect/makro/Context.scala +++ b/src/library/scala/reflect/makro/Context.scala @@ -14,12 +14,13 @@ trait Context extends Aliases with Reifiers with FrontEnds with Settings - with Symbols with Typers + with Exprs + with TypeTags with Util { /** The mirror that corresponds to the compile-time universe */ - val mirror: scala.reflect.api.Universe + val mirror: Universe /** The type of the prefix tree from which the macro is selected */ type PrefixType diff --git a/src/library/scala/reflect/makro/Exprs.scala b/src/library/scala/reflect/makro/Exprs.scala new file mode 100644 index 0000000000..ab0ea83d73 --- /dev/null +++ b/src/library/scala/reflect/makro/Exprs.scala @@ -0,0 +1,7 @@ +package scala.reflect.makro + +trait Exprs { + self: Context => + + def Expr[T: TypeTag](tree: Tree): Expr[T] +} diff --git a/src/library/scala/reflect/makro/FrontEnds.scala b/src/library/scala/reflect/makro/FrontEnds.scala index a1e24dcea3..d76907cdc8 100644 --- a/src/library/scala/reflect/makro/FrontEnds.scala +++ b/src/library/scala/reflect/makro/FrontEnds.scala @@ -1,10 +1,12 @@ package scala.reflect.makro -trait FrontEnds { +trait FrontEnds extends scala.reflect.api.FrontEnds { self: Context => import mirror._ + type Position = mirror.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/Reifiers.scala b/src/library/scala/reflect/makro/Reifiers.scala index b1de8d9957..0e0a4a765e 100644 --- a/src/library/scala/reflect/makro/Reifiers.scala +++ b/src/library/scala/reflect/makro/Reifiers.scala @@ -72,6 +72,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(var 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/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/TreeBuilder.scala b/src/library/scala/reflect/makro/TreeBuilder.scala new file mode 100644 index 0000000000..3510932c13 --- /dev/null +++ b/src/library/scala/reflect/makro/TreeBuilder.scala @@ -0,0 +1,59 @@ +package scala.reflect.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/library/scala/reflect/makro/TypeTags.scala b/src/library/scala/reflect/makro/TypeTags.scala new file mode 100644 index 0000000000..7b98f391a7 --- /dev/null +++ b/src/library/scala/reflect/makro/TypeTags.scala @@ -0,0 +1,8 @@ +package scala.reflect.makro + +trait TypeTags { + self: Context => + + def TypeTag[T](tpe: Type): TypeTag[T] + def ConcreteTypeTag[T](tpe: Type): ConcreteTypeTag[T] +} diff --git a/src/library/scala/reflect/makro/Universe.scala b/src/library/scala/reflect/makro/Universe.scala new file mode 100644 index 0000000000..d970e2474e --- /dev/null +++ b/src/library/scala/reflect/makro/Universe.scala @@ -0,0 +1,117 @@ +package scala.reflect.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: scala.reflect.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/library/scala/reflect/makro/internal/package.scala b/src/library/scala/reflect/makro/internal/package.scala index 4c4acec096..c0518384ab 100644 --- a/src/library/scala/reflect/makro/internal/package.scala +++ b/src/library/scala/reflect/makro/internal/package.scala @@ -1,17 +1,16 @@ package scala.reflect.makro import language.experimental.macros -import scala.reflect.api.{Universe => ApiUniverse} +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 { - private[scala] def materializeArrayTag[T](u: ApiUniverse): ArrayTag[T] = macro ??? - private[scala] def materializeErasureTag[T](u: ApiUniverse): ErasureTag[T] = macro ??? - private[scala] def materializeClassTag[T](u: ApiUniverse): ClassTag[T] = macro ??? - private[scala] def materializeTypeTag[T](u: ApiUniverse): u.TypeTag[T] = macro ??? - private[scala] def materializeConcreteTypeTag[T](u: ApiUniverse): u.ConcreteTypeTag[T] = macro ??? +package object internal extends scala.reflect.internal_compat { + private[scala] def materializeArrayTag[T](u: BaseUniverse): ArrayTag[T] = macro ??? + private[scala] def materializeClassTag[T](u: BaseUniverse): ClassTag[T] = macro ??? + private[scala] def materializeTypeTag[T](u: BaseUniverse): u.TypeTag[T] = macro ??? + private[scala] def materializeConcreteTypeTag[T](u: BaseUniverse): u.ConcreteTypeTag[T] = macro ??? } diff --git a/src/library/scala/reflect/package.scala b/src/library/scala/reflect/package.scala index 38a144cd49..ba93a1c91f 100644 --- a/src/library/scala/reflect/package.scala +++ b/src/library/scala/reflect/package.scala @@ -1,42 +1,8 @@ package scala -package object reflect { +package object reflect extends reflect_compat { - import ReflectionUtils._ - import scala.compat.Platform.EOL - - // !!! 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. - - // 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) - } - - 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)) - } - } + lazy val basis: base.Universe = new base.Base @deprecated("Use `@scala.beans.BeanDescription` instead", "2.10.0") type BeanDescription = scala.beans.BeanDescription @@ -53,18 +19,12 @@ package object reflect { @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 + // ArrayTag trait is defined outside the basis + // ClassTag class is defined outside the basis + type TypeTag[T] = scala.reflect.basis.TypeTag[T] + type ConcreteTypeTag[T] = scala.reflect.basis.ConcreteTypeTag[T] - 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) + // ClassTag object is defined outside the basis + lazy val TypeTag = scala.reflect.basis.TypeTag + lazy val ConcreteTypeTag = scala.reflect.basis.ConcreteTypeTag } 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) |