diff options
Diffstat (limited to 'src/reflect')
-rw-r--r-- | src/reflect/scala/reflect/api/Trees.scala | 14 | ||||
-rw-r--r-- | src/reflect/scala/reflect/api/Universe.scala | 2 | ||||
-rw-r--r-- | src/reflect/scala/reflect/api/package.scala | 4 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/Definitions.scala | 62 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/Importers.scala | 664 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/StdNames.scala | 5 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/TreeInfo.scala | 13 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/Trees.scala | 13 | ||||
-rw-r--r-- | src/reflect/scala/reflect/macros/Macro.scala | 39 | ||||
-rw-r--r-- | src/reflect/scala/reflect/runtime/JavaMirrors.scala | 4 | ||||
-rw-r--r-- | src/reflect/scala/reflect/runtime/package.scala | 2 |
11 files changed, 466 insertions, 356 deletions
diff --git a/src/reflect/scala/reflect/api/Trees.scala b/src/reflect/scala/reflect/api/Trees.scala index f4ada814af..f7a6a68946 100644 --- a/src/reflect/scala/reflect/api/Trees.scala +++ b/src/reflect/scala/reflect/api/Trees.scala @@ -296,6 +296,20 @@ trait Trees { self: Universe => def name: Name } + /** The constructor/extractor for `RefTree` instances. + * @group Extractors + */ + val RefTree: RefTreeExtractor + + /** An extractor class to create and pattern match with syntax `RefTree(qual, name)`. + * This AST node corresponds to either Ident, Select or SelectFromTypeTree. + * @group Extractors + */ + abstract class RefTreeExtractor { + def apply(qualifier: Tree, name: Name): RefTree + def unapply(refTree: RefTree): Option[(Tree, Name)] + } + /** A tree which defines a symbol-carrying entity. * @group Trees * @template diff --git a/src/reflect/scala/reflect/api/Universe.scala b/src/reflect/scala/reflect/api/Universe.scala index 799fbd0dfb..cb629f9c5a 100644 --- a/src/reflect/scala/reflect/api/Universe.scala +++ b/src/reflect/scala/reflect/api/Universe.scala @@ -94,5 +94,5 @@ abstract class Universe extends Symbols */ // implementation is hardwired to `scala.reflect.reify.Taggers` // using the mechanism implemented in `scala.tools.reflect.FastTrack` - def reify[T](expr: T): Expr[T] = ??? // macro + def reify[T](expr: T): Expr[T] = macro ??? } diff --git a/src/reflect/scala/reflect/api/package.scala b/src/reflect/scala/reflect/api/package.scala index 14dcc9247f..a8f409e123 100644 --- a/src/reflect/scala/reflect/api/package.scala +++ b/src/reflect/scala/reflect/api/package.scala @@ -43,6 +43,6 @@ package object api { // implementation is hardwired into `scala.reflect.reify.Taggers` // using the mechanism implemented in `scala.tools.reflect.FastTrack` // todo. once we have implicit macros for tag generation, we can remove these anchors - private[scala] def materializeWeakTypeTag[T](u: ApiUniverse): u.WeakTypeTag[T] = ??? // macro - private[scala] def materializeTypeTag[T](u: ApiUniverse): u.TypeTag[T] = ??? // macro + private[scala] def materializeWeakTypeTag[T](u: ApiUniverse): u.WeakTypeTag[T] = macro ??? + private[scala] def materializeTypeTag[T](u: ApiUniverse): u.TypeTag[T] = macro ??? }
\ No newline at end of file diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala index 5cd86b7eed..1b46d9e00b 100644 --- a/src/reflect/scala/reflect/internal/Definitions.scala +++ b/src/reflect/scala/reflect/internal/Definitions.scala @@ -491,8 +491,8 @@ trait Definitions extends api.StandardDefinitions { lazy val ReflectPackage = requiredModule[scala.reflect.`package`.type] lazy val ReflectApiPackage = getPackageObjectIfDefined("scala.reflect.api") // defined in scala-reflect.jar, so we need to be careful 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 + def ReflectRuntimeUniverse = ReflectRuntimePackage.map(sym => getMemberValue(sym, nme.universe)) + def ReflectRuntimeCurrentMirror = ReflectRuntimePackage.map(sym => getMemberMethod(sym, nme.currentMirror)) lazy val PartialManifestClass = getTypeMember(ReflectPackage, tpnme.ClassManifest) lazy val PartialManifestModule = requiredModule[scala.reflect.ClassManifestFactory.type] @@ -501,24 +501,38 @@ trait Definitions extends api.StandardDefinitions { lazy val OptManifestClass = requiredClass[scala.reflect.OptManifest[_]] lazy val NoManifest = requiredModule[scala.reflect.NoManifest.type] + lazy val TreesClass = getClassIfDefined("scala.reflect.api.Trees") // defined in scala-reflect.jar, so we need to be careful + lazy val TreesTreeType = TreesClass.map(sym => getTypeMember(sym, tpnme.Tree)) + object TreeType { + def unapply(tpe: Type): Boolean = unapply(tpe.typeSymbol) + def unapply(sym: Symbol): Boolean = sym.overrideChain contains TreesTreeType + } + 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 ExprClass = ExprsClass.map(sym => getMemberClass(sym, tpnme.Expr)) + def ExprSplice = ExprClass.map(sym => getMemberMethod(sym, nme.splice)) + def ExprValue = ExprClass.map(sym => getMemberMethod(sym, nme.value)) + object ExprClassOf { + def unapply(tpe: Type): Option[Type] = tpe.dealias match { + case ExistentialType(_, underlying) => unapply(underlying) + case TypeRef(_, ExprClass, t :: Nil) => Some(t) + case _ => None + } + } lazy val ClassTagModule = requiredModule[scala.reflect.ClassTag[_]] lazy val ClassTagClass = requiredClass[scala.reflect.ClassTag[_]] lazy val TypeTagsClass = getClassIfDefined("scala.reflect.api.TypeTags") // defined in scala-reflect.jar, so we need to be careful - lazy val WeakTypeTagClass = if (TypeTagsClass != NoSymbol) getMemberClass(TypeTagsClass, tpnme.WeakTypeTag) else NoSymbol - lazy val WeakTypeTagModule = if (TypeTagsClass != NoSymbol) getMemberModule(TypeTagsClass, nme.WeakTypeTag) else NoSymbol - lazy val TypeTagClass = if (TypeTagsClass != NoSymbol) getMemberClass(TypeTagsClass, tpnme.TypeTag) else NoSymbol - lazy val TypeTagModule = if (TypeTagsClass != NoSymbol) getMemberModule(TypeTagsClass, nme.TypeTag) else NoSymbol + lazy val WeakTypeTagClass = TypeTagsClass.map(sym => getMemberClass(sym, tpnme.WeakTypeTag)) + lazy val WeakTypeTagModule = TypeTagsClass.map(sym => getMemberModule(sym, nme.WeakTypeTag)) + lazy val TypeTagClass = TypeTagsClass.map(sym => getMemberClass(sym, tpnme.TypeTag)) + lazy val TypeTagModule = TypeTagsClass.map(sym => getMemberModule(sym, nme.TypeTag)) def materializeClassTag = getMemberMethod(ReflectPackage, nme.materializeClassTag) - def materializeWeakTypeTag = if (ReflectApiPackage != NoSymbol) getMemberMethod(ReflectApiPackage, nme.materializeWeakTypeTag) else NoSymbol - def materializeTypeTag = if (ReflectApiPackage != NoSymbol) getMemberMethod(ReflectApiPackage, nme.materializeTypeTag) else NoSymbol + def materializeWeakTypeTag = ReflectApiPackage.map(sym => getMemberMethod(sym, nme.materializeWeakTypeTag)) + def materializeTypeTag = ReflectApiPackage.map(sym => getMemberMethod(sym, nme.materializeTypeTag)) 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 + def ApiUniverseReify = ApiUniverseClass.map(sym => getMemberMethod(sym, nme.reify)) lazy val JavaUniverseClass = getClassIfDefined("scala.reflect.api.JavaUniverse") // defined in scala-reflect.jar, so we need to be careful lazy val MirrorClass = getClassIfDefined("scala.reflect.api.Mirror") // defined in scala-reflect.jar, so we need to be careful @@ -526,14 +540,18 @@ trait Definitions extends api.StandardDefinitions { lazy val TypeCreatorClass = getClassIfDefined("scala.reflect.api.TypeCreator") // defined in scala-reflect.jar, so we need to be careful lazy val TreeCreatorClass = getClassIfDefined("scala.reflect.api.TreeCreator") // defined in scala-reflect.jar, so we need to be careful - lazy val MacroContextClass = getClassIfDefined("scala.reflect.macros.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) getTypeMember(MacroContextClass, tpnme.PrefixType) else NoSymbol - def MacroContextUniverse = if (MacroContextClass != NoSymbol) getMemberMethod(MacroContextClass, nme.universe) else NoSymbol - lazy val MacroImplAnnotation = requiredClass[scala.reflect.macros.internal.macroImpl] + lazy val MacroClass = getClassIfDefined("scala.reflect.macros.Macro") // defined in scala-reflect.jar, so we need to be careful + lazy val MacroContextClass = getClassIfDefined("scala.reflect.macros.Context") // defined in scala-reflect.jar, so we need to be careful + def MacroContextPrefix = MacroContextClass.map(sym => getMemberMethod(sym, nme.prefix)) + def MacroContextPrefixType = MacroContextClass.map(sym => getTypeMember(sym, tpnme.PrefixType)) + def MacroContextUniverse = MacroContextClass.map(sym => getMemberMethod(sym, nme.universe)) + def MacroContextExprClass = MacroContextClass.map(sym => getTypeMember(sym, tpnme.Expr)) + def MacroContextWeakTypeTagClass = MacroContextClass.map(sym => getTypeMember(sym, tpnme.WeakTypeTag)) + def MacroContextTreeType = MacroContextClass.map(sym => getTypeMember(sym, tpnme.Tree)) + lazy val MacroImplAnnotation = requiredClass[scala.reflect.macros.internal.macroImpl] - lazy val StringContextClass = requiredClass[scala.StringContext] - def StringContext_f = getMemberMethod(StringContextClass, nme.f) + lazy val StringContextClass = requiredClass[scala.StringContext] + def StringContext_f = getMemberMethod(StringContextClass, nme.f) lazy val ScalaSignatureAnnotation = requiredClass[scala.reflect.ScalaSignature] lazy val ScalaLongSignatureAnnotation = requiredClass[scala.reflect.ScalaLongSignature] @@ -640,6 +658,12 @@ trait Definitions extends api.StandardDefinitions { } def isTupleType(tp: Type) = isTupleTypeDirect(tp.dealiasWiden) + def isMacroBundleType(tp: Type) = { + val isNonTrivial = tp != ErrorType && tp != NothingTpe && tp != NullTpe + val isMacroCompatible = MacroClass != NoSymbol && tp <:< MacroClass.tpe + isNonTrivial && isMacroCompatible + } + lazy val ProductRootClass: ClassSymbol = requiredClass[scala.Product] def Product_productArity = getMemberMethod(ProductRootClass, nme.productArity) def Product_productElement = getMemberMethod(ProductRootClass, nme.productElement) diff --git a/src/reflect/scala/reflect/internal/Importers.scala b/src/reflect/scala/reflect/internal/Importers.scala index b0d3cda629..f8584ac9b0 100644 --- a/src/reflect/scala/reflect/internal/Importers.scala +++ b/src/reflect/scala/reflect/internal/Importers.scala @@ -6,17 +6,17 @@ import scala.collection.mutable.WeakHashMap import scala.ref.WeakReference // SI-6241: move importers to a mirror -trait Importers extends api.Importers { self: SymbolTable => +trait Importers extends api.Importers { to: SymbolTable => def mkImporter(from0: api.Universe): Importer { val from: from0.type } = ( - if (self eq from0) { + if (to eq from0) { new Importer { val from = from0 - val reverse = this.asInstanceOf[from.Importer{ val from: self.type }] - def importSymbol(sym: from.Symbol) = sym.asInstanceOf[self.Symbol] - def importType(tpe: from.Type) = tpe.asInstanceOf[self.Type] - def importTree(tree: from.Tree) = tree.asInstanceOf[self.Tree] - def importPosition(pos: from.Position) = pos.asInstanceOf[self.Position] + val reverse = this.asInstanceOf[from.Importer{ val from: to.type }] + def importSymbol(their: from.Symbol) = their.asInstanceOf[to.Symbol] + def importType(their: from.Type) = their.asInstanceOf[to.Type] + def importTree(their: from.Tree) = their.asInstanceOf[to.Tree] + def importPosition(their: from.Position) = their.asInstanceOf[to.Position] } } else { // todo. fix this loophole @@ -29,8 +29,8 @@ trait Importers extends api.Importers { self: SymbolTable => val from: SymbolTable - protected lazy val symMap = new Cache[from.Symbol, Symbol]() - protected lazy val tpeMap = new Cache[from.Type, Type]() + protected lazy val symMap = new Cache[from.Symbol, to.Symbol]() + protected lazy val tpeMap = new Cache[from.Type, to.Type]() protected class Cache[K <: AnyRef, V <: AnyRef] extends WeakHashMap[K, WeakReference[V]] { def weakGet(key: K): Option[V] = this get key flatMap WeakReference.unapply def weakUpdate(key: K, value: V) = this.update(key, WeakReference(value)) @@ -50,158 +50,162 @@ trait Importers extends api.Importers { self: SymbolTable => } object reverse extends from.StandardImporter { - val from: self.type = self + val from: to.type = to // FIXME this and reverse should be constantly kept in sync // not just synced once upon the first usage of reverse - for ((fromsym, WeakReference(mysym)) <- StandardImporter.this.symMap) symMap += ((mysym, WeakReference(fromsym))) - for ((fromtpe, WeakReference(mytpe)) <- StandardImporter.this.tpeMap) tpeMap += ((mytpe, WeakReference(fromtpe))) + for ((theirsym, WeakReference(mysym)) <- StandardImporter.this.symMap) symMap += ((mysym, WeakReference(theirsym))) + for ((theirtpe, WeakReference(mytpe)) <- StandardImporter.this.tpeMap) tpeMap += ((mytpe, WeakReference(theirtpe))) } - // todo. careful import of positions - def importPosition(pos: from.Position): Position = - pos.asInstanceOf[Position] + // ============== SYMBOLS ============== + + protected def recreatedSymbolCompleter(my: to.Symbol, their: from.Symbol) = { + // we lock the symbol that is imported for a very short period of time + // i.e. only for when type parameters of the symbol are being imported + // the lock is used to communicate to the recursive importSymbol calls + // that type parameters need to be created from scratch + // because otherwise type parameters are imported by looking into owner.typeParams + // which is obviously unavailable while the completer is being created + try { + my setFlag Flags.LOCKED + val mytypeParams = their.typeParams map importSymbol + new LazyPolyType(mytypeParams) with FlagAgnosticCompleter { + override def complete(my: to.Symbol): Unit = { + val theirCore = their.info match { + case from.PolyType(_, core) => core + case core => core + } + my setInfo GenPolyType(mytypeParams, importType(theirCore)) + my setAnnotations (their.annotations map importAnnotationInfo) + } + } + } finally { + my resetFlag Flags.LOCKED + } + } + + protected def recreateSymbol(their: from.Symbol): to.Symbol = { + val myowner = importSymbol(their.owner) + val mypos = importPosition(their.pos) + val myname = importName(their.name) + val myflags = their.flags + def linkReferenced(my: TermSymbol, their: from.TermSymbol, op: from.Symbol => Symbol): Symbol = { + symMap.weakUpdate(their, my) + my.referenced = op(their.referenced) + my + } + val my = their match { + case their: from.MethodSymbol => + linkReferenced(myowner.newMethod(myname.toTermName, mypos, myflags), their, importSymbol) + case their: from.ModuleSymbol => + val ret = linkReferenced(myowner.newModuleSymbol(myname.toTermName, mypos, myflags), their, importSymbol) + ret.associatedFile = their.associatedFile + ret + case their: from.FreeTermSymbol => + newFreeTermSymbol(myname.toTermName, their.value, their.flags, their.origin) setInfo importType(their.info) + case their: from.FreeTypeSymbol => + newFreeTypeSymbol(myname.toTypeName, their.flags, their.origin) + case their: from.TermSymbol => + linkReferenced(myowner.newValue(myname.toTermName, mypos, myflags), their, importSymbol) + case their: from.TypeSkolem => + val origin = their.unpackLocation match { + case null => null + case theirloc: from.Tree => importTree(theirloc) + case theirloc: from.Symbol => importSymbol(theirloc) + } + myowner.newTypeSkolemSymbol(myname.toTypeName, origin, mypos, myflags) + case their: from.ModuleClassSymbol => + val my = myowner.newModuleClass(myname.toTypeName, mypos, myflags) + symMap.weakUpdate(their, my) + my.sourceModule = importSymbol(their.sourceModule) + my + case their: from.ClassSymbol => + val my = myowner.newClassSymbol(myname.toTypeName, mypos, myflags) + symMap.weakUpdate(their, my) + if (their.thisSym != their) { + my.typeOfThis = importType(their.typeOfThis) + my.thisSym setName importName(their.thisSym.name) + } + my.associatedFile = their.associatedFile + my + case their: from.TypeSymbol => + myowner.newTypeSymbol(myname.toTypeName, mypos, myflags) + } + symMap.weakUpdate(their, my) + my setInfo recreatedSymbolCompleter(my, their) + } - def importSymbol(sym0: from.Symbol): Symbol = { - def doImport(sym: from.Symbol): Symbol = - symMap weakGet sym match { + def importSymbol(their0: from.Symbol): Symbol = { + def cachedRecreateSymbol(their: from.Symbol): Symbol = + symMap weakGet their match { case Some(result) => result - case _ => - val myowner = importSymbol(sym.owner) - val mypos = importPosition(sym.pos) - val myname = importName(sym.name).toTermName - val myflags = sym.flags - def linkReferenced(mysym: TermSymbol, x: from.TermSymbol, op: from.Symbol => Symbol): Symbol = { - symMap.weakUpdate(x, mysym) - mysym.referenced = op(x.referenced) - mysym - } - val mysym = sym match { - case x: from.MethodSymbol => - linkReferenced(myowner.newMethod(myname, mypos, myflags), x, importSymbol) - case x: from.ModuleSymbol => - linkReferenced(myowner.newModuleSymbol(myname, mypos, myflags), x, importSymbol) - case x: from.FreeTermSymbol => - newFreeTermSymbol(importName(x.name).toTermName, x.value, x.flags, x.origin) setInfo importType(x.info) - case x: from.FreeTypeSymbol => - newFreeTypeSymbol(importName(x.name).toTypeName, x.flags, x.origin) - case x: from.TermSymbol => - linkReferenced(myowner.newValue(myname, mypos, myflags), x, importSymbol) - case x: from.TypeSkolem => - val origin = x.unpackLocation match { - case null => null - case y: from.Tree => importTree(y) - case y: from.Symbol => importSymbol(y) - } - myowner.newTypeSkolemSymbol(myname.toTypeName, origin, mypos, myflags) - case x: from.ModuleClassSymbol => - val mysym = myowner.newModuleClass(myname.toTypeName, mypos, myflags) - symMap.weakUpdate(x, mysym) - mysym.sourceModule = importSymbol(x.sourceModule) - mysym - case x: from.ClassSymbol => - val mysym = myowner.newClassSymbol(myname.toTypeName, mypos, myflags) - symMap.weakUpdate(x, mysym) - if (sym.thisSym != sym) { - mysym.typeOfThis = importType(sym.typeOfThis) - mysym.thisSym setName importName(sym.thisSym.name) - } - mysym - case x: from.TypeSymbol => - myowner.newTypeSymbol(myname.toTypeName, mypos, myflags) - } - symMap.weakUpdate(sym, mysym) - mysym setFlag Flags.LOCKED - mysym setInfo { - val mytypeParams = sym.typeParams map importSymbol - new LazyPolyType(mytypeParams) with FlagAgnosticCompleter { - override def complete(s: Symbol) { - val result = sym.info match { - case from.PolyType(_, res) => res - case result => result - } - s setInfo GenPolyType(mytypeParams, importType(result)) - s setAnnotations (sym.annotations map importAnnotationInfo) - } - } - } - mysym resetFlag Flags.LOCKED - } // end doImport + case _ => recreateSymbol(their) + } - def importOrRelink: Symbol = { - val sym = sym0 // makes sym visible in the debugger - if (sym == null) + def recreateOrRelink: Symbol = { + val their = their0 // makes their visible in the debugger + if (their == null) null - else if (sym == from.NoSymbol) + else if (their == from.NoSymbol) NoSymbol - else if (sym.isRoot) + else if (their.isRoot) rootMirror.RootClass // !!! replace with actual mirror when we move importers to the mirror else { - val name = sym.name - val owner = sym.owner - var scope = if (owner.isClass && !owner.isRefinementClass) owner.info else from.NoType - var existing = scope.decl(name) - if (sym.isModuleClass) - existing = existing.moduleClass - - if (!existing.exists) scope = from.NoType - - val myname = importName(name) - val myowner = importSymbol(owner) - val myscope = if (scope != from.NoType && !(myowner hasFlag Flags.LOCKED)) myowner.info else NoType - var myexisting = if (myscope != NoType) myowner.info.decl(myname) else NoSymbol // cannot load myexisting in general case, because it creates cycles for methods - if (sym.isModuleClass) - myexisting = importSymbol(sym.sourceModule).moduleClass - - if (!sym.isOverloaded && myexisting.isOverloaded) { - myexisting = - if (sym.isMethod) { - val localCopy = doImport(sym) - myexisting filter (_.tpe matches localCopy.tpe) - } else { - myexisting filter (!_.isMethod) + val isModuleClass = their.isModuleClass + val isTparam = their.isTypeParameter && their.paramPos >= 0 + val isOverloaded = their.isOverloaded + + var theirscope = if (their.owner.isClass && !their.owner.isRefinementClass) their.owner.info else from.NoType + val theirexisting = if (isModuleClass) theirscope.decl(their.name).moduleClass else theirscope.decl(their.name) + if (!theirexisting.exists) theirscope = from.NoType + + val myname = importName(their.name) + val myowner = importSymbol(their.owner) + val myscope = if (theirscope != from.NoType && !(myowner hasFlag Flags.LOCKED)) myowner.info else NoType + val myexisting = { + if (isModuleClass) importSymbol(their.sourceModule).moduleClass + else if (isTparam) (if (myowner hasFlag Flags.LOCKED) NoSymbol else myowner.typeParams(their.paramPos)) + else if (isOverloaded) myowner.newOverloaded(myowner.thisType, their.alternatives map importSymbol) + else { + def disambiguate(my: Symbol) = { + val result = + if (their.isMethod) { + val localCopy = cachedRecreateSymbol(their) + my filter (_.tpe matches localCopy.tpe) + } else { + my filter (!_.isMethod) + } + assert(!result.isOverloaded, + "import failure: cannot determine unique overloaded method alternative from\n "+ + (result.alternatives map (_.defString) mkString "\n")+"\n that matches "+their+":"+their.tpe) + result } - assert(!myexisting.isOverloaded, - "import failure: cannot determine unique overloaded method alternative from\n "+ - (myexisting.alternatives map (_.defString) mkString "\n")+"\n that matches "+sym+":"+sym.tpe) - } - val mysym = { - if (sym.isOverloaded) { - myowner.newOverloaded(myowner.thisType, sym.alternatives map importSymbol) - } else if (sym.isTypeParameter && sym.paramPos >= 0 && !(myowner hasFlag Flags.LOCKED)) { - assert(myowner.typeParams.length > sym.paramPos, - "import failure: cannot determine parameter "+sym+" (#"+sym.paramPos+") in "+ - myowner+typeParamsString(myowner.rawInfo)+"\n original symbol was: "+ - sym.owner+from.typeParamsString(sym.owner.info)) - myowner.typeParams(sym.paramPos) - } else { - if (myexisting != NoSymbol) { - myexisting - } else { - val mysym = doImport(sym) - - if (myscope != NoType) { - assert(myowner.info.decls.lookup(myname) == NoSymbol, myname+" "+myowner.info.decl(myname)+" "+myexisting) - myowner.info.decls enter mysym - } - - mysym - } + val myexisting = if (myscope != NoType) myscope.decl(myname) else NoSymbol + if (myexisting.isOverloaded) disambiguate(myexisting) + else myexisting } } - mysym + myexisting.orElse { + val my = cachedRecreateSymbol(their) + if (myscope != NoType) { + assert(myscope.decls.lookup(myname) == NoSymbol, myname+" "+myscope.decl(myname)+" "+myexisting) + myscope.decls enter my + } + my + } } - } // end importOrRelink + } // end recreateOrRelink - val sym = sym0 - symMap.weakGet(sym) match { + val their = their0 + symMap.weakGet(their) match { case Some(result) => result case None => pendingSyms += 1 try { - val result = importOrRelink - symMap.weakUpdate(sym, result) + val result = recreateOrRelink + symMap.weakUpdate(their, result) result } finally { pendingSyms -= 1 @@ -210,69 +214,70 @@ trait Importers extends api.Importers { self: SymbolTable => } } - def importType(tpe: from.Type): Type = { - def doImport(tpe: from.Type): Type = tpe match { - case from.TypeRef(pre, sym, args) => - TypeRef(importType(pre), importSymbol(sym), args map importType) - case from.ThisType(clazz) => - ThisType(importSymbol(clazz)) - case from.SingleType(pre, sym) => - SingleType(importType(pre), importSymbol(sym)) - case from.MethodType(params, restpe) => - MethodType(params map importSymbol, importType(restpe)) - case from.PolyType(tparams, restpe) => - PolyType(tparams map importSymbol, importType(restpe)) - case from.NullaryMethodType(restpe) => - NullaryMethodType(importType(restpe)) - case from.ConstantType(constant @ from.Constant(_)) => - ConstantType(importConstant(constant)) - case from.SuperType(thistpe, supertpe) => - SuperType(importType(thistpe), importType(supertpe)) - case from.TypeBounds(lo, hi) => - TypeBounds(importType(lo), importType(hi)) - case from.BoundedWildcardType(bounds) => - BoundedWildcardType(importTypeBounds(bounds)) - case from.ClassInfoType(parents, decls, clazz) => - val myclazz = importSymbol(clazz) - val myscope = if (myclazz.isPackageClass) newPackageScope(myclazz) else newScope - val myclazzTpe = ClassInfoType(parents map importType, myscope, myclazz) - myclazz setInfo GenPolyType(myclazz.typeParams, myclazzTpe) // needed so that newly created symbols find their scope - decls foreach importSymbol // will enter itself into myclazz - myclazzTpe - case from.RefinedType(parents, decls) => - RefinedType(parents map importType, importScope(decls), importSymbol(tpe.typeSymbol)) - case from.ExistentialType(tparams, restpe) => - newExistentialType(tparams map importSymbol, importType(restpe)) - case from.OverloadedType(pre, alts) => - OverloadedType(importType(pre), alts map importSymbol) - case from.AntiPolyType(pre, targs) => - AntiPolyType(importType(pre), targs map importType) - case x: from.TypeVar => - TypeVar(importType(x.origin), importTypeConstraint(x.constr), x.typeArgs map importType, x.params map importSymbol) - case from.AnnotatedType(annots, tpe, selfsym) => - AnnotatedType(annots map importAnnotationInfo, importType(tpe), importSymbol(selfsym)) - case from.ErrorType => - ErrorType - case from.WildcardType => - WildcardType - case from.NoType => - NoType - case from.NoPrefix => - NoPrefix - case null => - null - } // end doImport - - def importOrRelink: Type = - doImport(tpe) + // ============== TYPES ============== + + def recreateType(their: from.Type): Type = their match { + case from.TypeRef(pre, sym, args) => + TypeRef(importType(pre), importSymbol(sym), args map importType) + case from.ThisType(clazz) => + ThisType(importSymbol(clazz)) + case from.SingleType(pre, sym) => + SingleType(importType(pre), importSymbol(sym)) + case from.MethodType(params, result) => + MethodType(params map importSymbol, importType(result)) + case from.PolyType(tparams, result) => + PolyType(tparams map importSymbol, importType(result)) + case from.NullaryMethodType(result) => + NullaryMethodType(importType(result)) + case from.ConstantType(constant @ from.Constant(_)) => + ConstantType(importConstant(constant)) + case from.SuperType(thistpe, supertpe) => + SuperType(importType(thistpe), importType(supertpe)) + case from.TypeBounds(lo, hi) => + TypeBounds(importType(lo), importType(hi)) + case from.BoundedWildcardType(bounds) => + BoundedWildcardType(importType(bounds).asInstanceOf[TypeBounds]) + case from.ClassInfoType(parents, decls, clazz) => + val myclazz = importSymbol(clazz) + val myscope = if (myclazz.isPackageClass) newPackageScope(myclazz) else newScope + val myclazzTpe = ClassInfoType(parents map importType, myscope, myclazz) + myclazz setInfo GenPolyType(myclazz.typeParams, myclazzTpe) // needed so that newly created symbols find their scope + decls foreach importSymbol // will enter itself into myclazz + myclazzTpe + case from.RefinedType(parents, decls) => + RefinedType(parents map importType, importScope(decls), importSymbol(their.typeSymbol)) + case from.ExistentialType(tparams, result) => + newExistentialType(tparams map importSymbol, importType(result)) + case from.OverloadedType(pre, alts) => + OverloadedType(importType(pre), alts map importSymbol) + case from.AntiPolyType(pre, targs) => + AntiPolyType(importType(pre), targs map importType) + case their: from.TypeVar => + val myconstr = new TypeConstraint(their.constr.loBounds map importType, their.constr.hiBounds map importType) + myconstr.inst = importType(their.constr.inst) + TypeVar(importType(their.origin), myconstr, their.typeArgs map importType, their.params map importSymbol) + case from.AnnotatedType(annots, result, selfsym) => + AnnotatedType(annots map importAnnotationInfo, importType(result), importSymbol(selfsym)) + case from.ErrorType => + ErrorType + case from.WildcardType => + WildcardType + case from.NoType => + NoType + case from.NoPrefix => + NoPrefix + case null => + null + } - tpeMap.weakGet(tpe) match { + def importType(their: from.Type): Type = { + tpeMap.weakGet(their) match { case Some(result) => result case None => pendingTpes += 1 try { - val result = importOrRelink - tpeMap.weakUpdate(tpe, result) + val result = recreateType(their) + tpeMap.weakUpdate(their, result) result } finally { pendingTpes -= 1 @@ -281,7 +286,136 @@ trait Importers extends api.Importers { self: SymbolTable => } } - def importTypeBounds(bounds: from.TypeBounds) = importType(bounds).asInstanceOf[TypeBounds] + // ============== TREES ============== + + def recreatedTreeCompleter(their: from.Tree, my: to.Tree): Unit = { + if (their.canHaveAttrs) { + if (my.hasSymbolField) my.symbol = importSymbol(their.symbol) + my.pos = importPosition(their.pos) + (their, my) match { + case (their: from.TypeTree, my: to.TypeTree) => + if (their.wasEmpty) my.defineType(importType(their.tpe)) else my.setType(importType(their.tpe)) + case (_, _) => + my.tpe = importType(their.tpe) + } + } + } + + def recreateTree(their: from.Tree): to.Tree = their match { + case from.ClassDef(mods, name, tparams, impl) => + new ClassDef(importModifiers(mods), importName(name).toTypeName, tparams map importTypeDef, importTemplate(impl)) + case from.PackageDef(pid, stats) => + new PackageDef(importRefTree(pid), stats map importTree) + case from.ModuleDef(mods, name, impl) => + new ModuleDef(importModifiers(mods), importName(name).toTermName, importTemplate(impl)) + case from.emptyValDef => + emptyValDef + case from.pendingSuperCall => + pendingSuperCall + case from.ValDef(mods, name, tpt, rhs) => + new ValDef(importModifiers(mods), importName(name).toTermName, importTree(tpt), importTree(rhs)) + case from.DefDef(mods, name, tparams, vparamss, tpt, rhs) => + new DefDef(importModifiers(mods), importName(name).toTermName, tparams map importTypeDef, mmap(vparamss)(importValDef), importTree(tpt), importTree(rhs)) + case from.TypeDef(mods, name, tparams, rhs) => + new TypeDef(importModifiers(mods), importName(name).toTypeName, tparams map importTypeDef, importTree(rhs)) + case from.LabelDef(name, params, rhs) => + new LabelDef(importName(name).toTermName, params map importIdent, importTree(rhs)) + case from.Import(expr, selectors) => + new Import(importTree(expr), selectors map importImportSelector) + case from.Template(parents, self, body) => + new Template(parents map importTree, importValDef(self), body map importTree) + case from.Block(stats, expr) => + new Block(stats map importTree, importTree(expr)) + case from.CaseDef(pat, guard, body) => + new CaseDef(importTree(pat), importTree(guard), importTree(body)) + case from.Alternative(trees) => + new Alternative(trees map importTree) + case from.Star(elem) => + new Star(importTree(elem)) + case from.Bind(name, body) => + new Bind(importName(name), importTree(body)) + case from.UnApply(fun, args) => + new UnApply(importTree(fun), args map importTree) + case from.ArrayValue(elemtpt ,elems) => + new ArrayValue(importTree(elemtpt), elems map importTree) + case from.Function(vparams, body) => + new Function(vparams map importValDef, importTree(body)) + case from.Assign(lhs, rhs) => + new Assign(importTree(lhs), importTree(rhs)) + case from.AssignOrNamedArg(lhs, rhs) => + new AssignOrNamedArg(importTree(lhs), importTree(rhs)) + case from.If(cond, thenp, elsep) => + new If(importTree(cond), importTree(thenp), importTree(elsep)) + case from.Match(selector, cases) => + new Match(importTree(selector), cases map importCaseDef) + case from.Return(expr) => + new Return(importTree(expr)) + case from.Try(block, catches, finalizer) => + new Try(importTree(block), catches map importCaseDef, importTree(finalizer)) + case from.Throw(expr) => + new Throw(importTree(expr)) + case from.New(tpt) => + new New(importTree(tpt)) + case from.Typed(expr, tpt) => + new Typed(importTree(expr), importTree(tpt)) + case from.TypeApply(fun, args) => + new TypeApply(importTree(fun), args map importTree) + case from.Apply(fun, args) => their match { + case _: from.ApplyToImplicitArgs => + new ApplyToImplicitArgs(importTree(fun), args map importTree) + case _: from.ApplyImplicitView => + new ApplyImplicitView(importTree(fun), args map importTree) + case _ => + new Apply(importTree(fun), args map importTree) + } + case from.ApplyDynamic(qual, args) => + new ApplyDynamic(importTree(qual), args map importTree) + case from.Super(qual, mix) => + new Super(importTree(qual), importName(mix).toTypeName) + case from.This(qual) => + new This(importName(qual).toTypeName) + case from.Select(qual, name) => + new Select(importTree(qual), importName(name)) + case from.Ident(name) => + new Ident(importName(name)) + case from.ReferenceToBoxed(ident) => + new ReferenceToBoxed(importTree(ident) match { case ident: Ident => ident }) + case from.Literal(constant @ from.Constant(_)) => + new Literal(importConstant(constant)) + case theirtt @ from.TypeTree() => + val mytt = TypeTree() + if (theirtt.original != null) mytt.setOriginal(importTree(theirtt.original)) + mytt + case from.Annotated(annot, arg) => + new Annotated(importTree(annot), importTree(arg)) + case from.SingletonTypeTree(ref) => + new SingletonTypeTree(importTree(ref)) + case from.SelectFromTypeTree(qual, name) => + new SelectFromTypeTree(importTree(qual), importName(name).toTypeName) + case from.CompoundTypeTree(templ) => + new CompoundTypeTree(importTemplate(templ)) + case from.AppliedTypeTree(tpt, args) => + new AppliedTypeTree(importTree(tpt), args map importTree) + case from.TypeBoundsTree(lo, hi) => + new TypeBoundsTree(importTree(lo), importTree(hi)) + case from.ExistentialTypeTree(tpt, whereClauses) => + new ExistentialTypeTree(importTree(tpt), whereClauses map importTree) + case from.EmptyTree => + EmptyTree + case null => + null + } + + def importTree(their: from.Tree): Tree = { + val my = recreateTree(their) + if (my != null) { + addFixup(recreatedTreeCompleter(their, my)) + tryFixup() + } + my + } + + // ============== MISCELLANEOUS ============== def importAnnotationInfo(ann: from.AnnotationInfo): AnnotationInfo = { val atp1 = importType(ann.atp) @@ -302,11 +436,9 @@ trait Importers extends api.Importers { self: SymbolTable => NestedAnnotArg(importAnnotationInfo(annInfo)) } - def importTypeConstraint(constr: from.TypeConstraint): TypeConstraint = { - val result = new TypeConstraint(constr.loBounds map importType, constr.hiBounds map importType) - result.inst = importType(constr.inst) - result - } + // todo. careful import of positions + def importPosition(their: from.Position): to.Position = + their.asInstanceOf[Position] // !!! todo: override to cater for PackageScopes def importScope(decls: from.Scope): Scope = @@ -314,138 +446,12 @@ trait Importers extends api.Importers { self: SymbolTable => def importName(name: from.Name): Name = if (name.isTypeName) newTypeName(name.toString) else newTermName(name.toString) - def importTypeName(name: from.TypeName): TypeName = importName(name).toTypeName def importModifiers(mods: from.Modifiers): Modifiers = new Modifiers(mods.flags, importName(mods.privateWithin), mods.annotations map importTree) def importImportSelector(sel: from.ImportSelector): ImportSelector = new ImportSelector(importName(sel.name), sel.namePos, if (sel.rename != null) importName(sel.rename) else null, sel.renamePos) - - def importTree(tree: from.Tree): Tree = { - val mytree = tree match { - case from.ClassDef(mods, name, tparams, impl) => - new ClassDef(importModifiers(mods), importName(name).toTypeName, tparams map importTypeDef, importTemplate(impl)) - case from.PackageDef(pid, stats) => - new PackageDef(importRefTree(pid), stats map importTree) - case from.ModuleDef(mods, name, impl) => - new ModuleDef(importModifiers(mods), importName(name).toTermName, importTemplate(impl)) - case from.emptyValDef => - emptyValDef - case from.pendingSuperCall => - pendingSuperCall - case from.ValDef(mods, name, tpt, rhs) => - new ValDef(importModifiers(mods), importName(name).toTermName, importTree(tpt), importTree(rhs)) - case from.DefDef(mods, name, tparams, vparamss, tpt, rhs) => - new DefDef(importModifiers(mods), importName(name).toTermName, tparams map importTypeDef, mmap(vparamss)(importValDef), importTree(tpt), importTree(rhs)) - case from.TypeDef(mods, name, tparams, rhs) => - new TypeDef(importModifiers(mods), importName(name).toTypeName, tparams map importTypeDef, importTree(rhs)) - case from.LabelDef(name, params, rhs) => - new LabelDef(importName(name).toTermName, params map importIdent, importTree(rhs)) - case from.Import(expr, selectors) => - new Import(importTree(expr), selectors map importImportSelector) - case from.Template(parents, self, body) => - new Template(parents map importTree, importValDef(self), body map importTree) - case from.Block(stats, expr) => - new Block(stats map importTree, importTree(expr)) - case from.CaseDef(pat, guard, body) => - new CaseDef(importTree(pat), importTree(guard), importTree(body)) - case from.Alternative(trees) => - new Alternative(trees map importTree) - case from.Star(elem) => - new Star(importTree(elem)) - case from.Bind(name, body) => - new Bind(importName(name), importTree(body)) - case from.UnApply(fun, args) => - new UnApply(importTree(fun), args map importTree) - case from.ArrayValue(elemtpt ,elems) => - new ArrayValue(importTree(elemtpt), elems map importTree) - case from.Function(vparams, body) => - new Function(vparams map importValDef, importTree(body)) - case from.Assign(lhs, rhs) => - new Assign(importTree(lhs), importTree(rhs)) - case from.AssignOrNamedArg(lhs, rhs) => - new AssignOrNamedArg(importTree(lhs), importTree(rhs)) - case from.If(cond, thenp, elsep) => - new If(importTree(cond), importTree(thenp), importTree(elsep)) - case from.Match(selector, cases) => - new Match(importTree(selector), cases map importCaseDef) - case from.Return(expr) => - new Return(importTree(expr)) - case from.Try(block, catches, finalizer) => - new Try(importTree(block), catches map importCaseDef, importTree(finalizer)) - case from.Throw(expr) => - new Throw(importTree(expr)) - case from.New(tpt) => - new New(importTree(tpt)) - case from.Typed(expr, tpt) => - new Typed(importTree(expr), importTree(tpt)) - case from.TypeApply(fun, args) => - new TypeApply(importTree(fun), args map importTree) - case from.Apply(fun, args) => tree match { - case _: from.ApplyToImplicitArgs => - new ApplyToImplicitArgs(importTree(fun), args map importTree) - case _: from.ApplyImplicitView => - new ApplyImplicitView(importTree(fun), args map importTree) - case _ => - new Apply(importTree(fun), args map importTree) - } - case from.ApplyDynamic(qual, args) => - new ApplyDynamic(importTree(qual), args map importTree) - case from.Super(qual, mix) => - new Super(importTree(qual), importTypeName(mix)) - case from.This(qual) => - new This(importName(qual).toTypeName) - case from.Select(qual, name) => - new Select(importTree(qual), importName(name)) - case from.Ident(name) => - new Ident(importName(name)) - case from.ReferenceToBoxed(ident) => - new ReferenceToBoxed(importTree(ident) match { case ident: Ident => ident }) - case from.Literal(constant @ from.Constant(_)) => - new Literal(importConstant(constant)) - case from.TypeTree() => - new TypeTree() - case from.Annotated(annot, arg) => - new Annotated(importTree(annot), importTree(arg)) - case from.SingletonTypeTree(ref) => - new SingletonTypeTree(importTree(ref)) - case from.SelectFromTypeTree(qual, name) => - new SelectFromTypeTree(importTree(qual), importName(name).toTypeName) - case from.CompoundTypeTree(templ) => - new CompoundTypeTree(importTemplate(templ)) - case from.AppliedTypeTree(tpt, args) => - new AppliedTypeTree(importTree(tpt), args map importTree) - case from.TypeBoundsTree(lo, hi) => - new TypeBoundsTree(importTree(lo), importTree(hi)) - case from.ExistentialTypeTree(tpt, whereClauses) => - new ExistentialTypeTree(importTree(tpt), whereClauses map importTree) - case from.EmptyTree => - EmptyTree - case null => - null - } - addFixup({ - if (mytree != null) { - val mysym = if (tree.hasSymbolField) importSymbol(tree.symbol) else NoSymbol - val mytpe = importType(tree.tpe) - - mytree match { - case mytt: TypeTree => - val tt = tree.asInstanceOf[from.TypeTree] - if (mytree.hasSymbolField) mytt.symbol = mysym - if (tt.wasEmpty) mytt.defineType(mytpe) else mytt.setType(mytpe) - if (tt.original != null) mytt.setOriginal(importTree(tt.original)) - case _ => - if (mytree.hasSymbolField) mytree.symbol = importSymbol(tree.symbol) - mytree setType importType(tree.tpe) - } - } - }) - tryFixup() - mytree - } - def importValDef(tree: from.ValDef): ValDef = importTree(tree).asInstanceOf[ValDef] def importTypeDef(tree: from.TypeDef): TypeDef = importTree(tree).asInstanceOf[TypeDef] def importTemplate(tree: from.Template): Template = importTree(tree).asInstanceOf[Template] diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala index a20307882d..81fffc833c 100644 --- a/src/reflect/scala/reflect/internal/StdNames.scala +++ b/src/reflect/scala/reflect/internal/StdNames.scala @@ -8,6 +8,7 @@ package reflect package internal import java.security.MessageDigest +import java.util.UUID.randomUUID import Chars.isOperatorPart import scala.annotation.switch import scala.language.implicitConversions @@ -290,6 +291,9 @@ trait StdNames { val FAKE_LOCAL_THIS: NameType = "this$" val LAZY_LOCAL: NameType = "$lzy" val LAZY_SLOW_SUFFIX: NameType = "$lzycompute" + val MACRO_INVOKER_PACKAGE: NameType = "scala.reflect.macros.synthetic" + // TODO: if I use dollars in MACRO_INVOKER_SUFFIX, as in "$Invoker$", then Scala reflection fails to load implementations + val MACRO_INVOKER_SUFFIX: NameType = "Invoker" val UNIVERSE_BUILD_PREFIX: NameType = "$u.build." val UNIVERSE_PREFIX: NameType = "$u." val UNIVERSE_SHORT: NameType = "$u" @@ -584,6 +588,7 @@ trait StdNames { val box: NameType = "box" val build : NameType = "build" val bytes: NameType = "bytes" + val c: NameType = "c" val canEqual_ : NameType = "canEqual" val checkInitialized: NameType = "checkInitialized" val classOf: NameType = "classOf" diff --git a/src/reflect/scala/reflect/internal/TreeInfo.scala b/src/reflect/scala/reflect/internal/TreeInfo.scala index e9ef9c7945..d1e8a04553 100644 --- a/src/reflect/scala/reflect/internal/TreeInfo.scala +++ b/src/reflect/scala/reflect/internal/TreeInfo.scala @@ -836,8 +836,17 @@ abstract class TreeInfo { } def unapply(tree: Tree) = refPart(tree) match { - case ref: RefTree => Some((ref.qualifier.symbol, ref.symbol, dissectApplied(tree).targs)) - case _ => None + case ref: RefTree => { + val isBundle = definitions.isMacroBundleType(ref.qualifier.tpe) + val owner = + if (isBundle) ref.qualifier.tpe.typeSymbol + else { + val sym = ref.qualifier.symbol + if (sym.isModule) sym.moduleClass else sym + } + Some((isBundle, owner, ref.symbol, dissectApplied(tree).targs)) + } + case _ => None } } diff --git a/src/reflect/scala/reflect/internal/Trees.scala b/src/reflect/scala/reflect/internal/Trees.scala index 833adb99c7..8781423a6d 100644 --- a/src/reflect/scala/reflect/internal/Trees.scala +++ b/src/reflect/scala/reflect/internal/Trees.scala @@ -253,6 +253,19 @@ trait Trees extends api.Trees { self: SymbolTable => def name: Name } + object RefTree extends RefTreeExtractor { + def apply(qualifier: Tree, name: Name): RefTree = qualifier match { + case EmptyTree => + Ident(name) + case qual if qual.isTerm => + Select(qual, name) + case qual if qual.isType => + assert(name.isTypeName, s"qual = $qual, name = $name") + SelectFromTypeTree(qual, name.toTypeName) + } + def unapply(refTree: RefTree): Option[(Tree, Name)] = Some((refTree.qualifier, refTree.name)) + } + abstract class DefTree extends SymTree with NameTree with DefTreeApi { def name: Name override def isDef = true diff --git a/src/reflect/scala/reflect/macros/Macro.scala b/src/reflect/scala/reflect/macros/Macro.scala new file mode 100644 index 0000000000..44bedf483d --- /dev/null +++ b/src/reflect/scala/reflect/macros/Macro.scala @@ -0,0 +1,39 @@ +package scala.reflect +package macros + +/** + * <span class="badge badge-red" style="float: right;">EXPERIMENTAL</span> + * + * Traditionally macro implementations are defined as methods, + * but this trait provides an alternative way of encoding macro impls as + * bundles, traits which extend `scala.reflect.macros.Macro`. + * + * Instead of: + * + * def impl[T: c.WeakTypeTag](c: Context)(x: c.Expr[Int]) = ... + * + * One can write: + * + * trait Impl extends Macro { + * def apply[T: c.WeakTypeTag](x: c.Expr[Int]) = ... + * } + * + * Without changing anything else at all. + * + * This language feature is useful in itself in cases when macro implementations + * are complex and need to be modularized. State of the art technique of addressing this need is quite heavyweight: + * http://docs.scala-lang.org/overviews/macros/overview.html#writing_bigger_macros. + * + * However utility of this approach to writing macros isn't limited to just convenience. + * When a macro implementation becomes not just a function, but a full-fledged module, + * it can define callbacks that will be called by the compiler upon interesting events. + * In subsequent commits I will add support for programmable type inference + */ +trait Macro { + /** The context to be used by the macro implementation. + * + * Vanilla macro implementations have to carry it in their signatures, however when a macro is a full-fledged module, + * it can define the context next to the implementation, makes implementation signature more lightweight. + */ + val c: Context +} diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala index adee155db0..a3684f602f 100644 --- a/src/reflect/scala/reflect/runtime/JavaMirrors.scala +++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala @@ -972,8 +972,8 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni javaTypeToValueClass(jclazz) orElse lookupClass assert (cls.isType, - sm"""${if (cls == NoSymbol) "not a type: symbol" else "no symbol could be"} - | loaded from $jclazz in $owner with name $simpleName and classloader $classLoader""") + (if (cls != NoSymbol) s"not a type: symbol $cls" else "no symbol could be") + + s" loaded from $jclazz in $owner with name $simpleName and classloader $classLoader") cls.asClass } diff --git a/src/reflect/scala/reflect/runtime/package.scala b/src/reflect/scala/reflect/runtime/package.scala index 0354b424d2..41c1310e17 100644 --- a/src/reflect/scala/reflect/runtime/package.scala +++ b/src/reflect/scala/reflect/runtime/package.scala @@ -21,7 +21,7 @@ package object runtime { */ // implementation hardwired to the `currentMirror` method below // using the mechanism implemented in `scala.tools.reflect.FastTrack` - def currentMirror: universe.Mirror = ??? // macro + def currentMirror: universe.Mirror = macro ??? } package runtime { |