diff options
Diffstat (limited to 'src/compiler')
120 files changed, 4127 insertions, 2621 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/compiler/scala/reflect/internal/AbstractFileApi.scala b/src/compiler/scala/reflect/internal/AbstractFileApi.scala new file mode 100644 index 0000000000..9f37f4536f --- /dev/null +++ b/src/compiler/scala/reflect/internal/AbstractFileApi.scala @@ -0,0 +1,7 @@ +package scala.reflect +package internal + +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/compiler/scala/reflect/runtime/ReflectionUtils.scala b/src/compiler/scala/reflect/runtime/ReflectionUtils.scala new file mode 100644 index 0000000000..4e82fe8ad2 --- /dev/null +++ b/src/compiler/scala/reflect/runtime/ReflectionUtils.scala @@ -0,0 +1,80 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2011 LAMP/EPFL + * @author Paul Phillips + */ + +package scala.reflect.runtime + +import java.lang.{Class => jClass} +import java.lang.reflect.{ InvocationTargetException, UndeclaredThrowableException } + +/** A few java-reflection oriented utility functions useful during reflection bootstrapping. + */ +object ReflectionUtils { + // Unwraps some chained exceptions which arise during reflective calls. + def unwrapThrowable(x: Throwable): Throwable = x match { + case _: InvocationTargetException | // thrown by reflectively invoked method or constructor + _: ExceptionInInitializerError | // thrown when running a static initializer (e.g. a scala module constructor) + _: UndeclaredThrowableException | // invocation on a proxy instance if its invocation handler's `invoke` throws an exception + _: ClassNotFoundException | // no definition for a class instantiated by name + _: NoClassDefFoundError // the definition existed when the executing class was compiled, but can no longer be found + if x.getCause != null => + unwrapThrowable(x.getCause) + case _ => x + } + // Transforms an exception handler into one which will only receive the unwrapped + // exceptions (for the values of wrap covered in unwrapThrowable.) + def unwrapHandler[T](pf: PartialFunction[Throwable, T]): PartialFunction[Throwable, T] = { + case ex if pf isDefinedAt unwrapThrowable(ex) => pf(unwrapThrowable(ex)) + } + + private def systemProperties: Iterator[(String, String)] = { + import scala.collection.JavaConverters._ + System.getProperties.asScala.iterator + } + + private def inferBootClasspath: String = ( + systemProperties find (_._1 endsWith ".boot.class.path") map (_._2) getOrElse "" + ) + + def show(cl: ClassLoader) = { + def inferClasspath(cl: ClassLoader): String = cl match { + case cl: java.net.URLClassLoader => + "[" + (cl.getURLs mkString ",") + "]" + case cl if cl != null && cl.getClass.getName == "scala.tools.nsc.interpreter.AbstractFileClassLoader" => + "[" + cl.asInstanceOf[{val root: scala.reflect.internal.AbstractFileApi}].root + "] and " + inferClasspath(cl.getParent) + case null => + inferBootClasspath + case _ => + "<unknown>" + } + cl match { + case cl if cl != null => + "%s of type %s with classpath %s".format(cl, cl.getClass, inferClasspath(cl)) + case null => + "primordial classloader with boot classpath [%s]".format(inferClasspath(cl)) + } + } + + def singletonInstance(cl: ClassLoader, className: String): AnyRef = { + val name = if (className endsWith "$") className else className + "$" + val clazz = java.lang.Class.forName(name, true, cl) + val singleton = clazz getField "MODULE$" get null + singleton + } + + // Retrieves the MODULE$ field for the given class name. + def singletonInstanceOpt(cl: ClassLoader, className: String): Option[AnyRef] = + try Some(singletonInstance(cl, className)) + catch { case _: ClassNotFoundException => None } + + def invokeFactory(cl: ClassLoader, className: String, methodName: String, args: AnyRef*): AnyRef = { + val singleton = singletonInstance(cl, className) + val method = singleton.getClass.getMethod(methodName, classOf[ClassLoader]) + method.invoke(singleton, args: _*) + } + + def invokeFactoryOpt(cl: ClassLoader, className: String, methodName: String, args: AnyRef*): Option[AnyRef] = + try Some(invokeFactory(cl, className, methodName, args: _*)) + catch { case _: ClassNotFoundException => None } +} 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] + } + } +} |