summaryrefslogtreecommitdiff
path: root/src/reflect/scala/reflect/internal/Importers.scala
diff options
context:
space:
mode:
authorEugene Burmako <xeno.by@gmail.com>2012-06-08 02:36:10 +0200
committerEugene Burmako <xeno.by@gmail.com>2012-06-08 15:32:28 +0200
commit0b2f1bcf75d31c59b25e19eebcb80f39c155365b (patch)
tree8d9dfc50ef01ca48c068b232af7e67a723325388 /src/reflect/scala/reflect/internal/Importers.scala
parent13213e3df0384b1fd815c0798758a22284572cdb (diff)
downloadscala-0b2f1bcf75d31c59b25e19eebcb80f39c155365b.tar.gz
scala-0b2f1bcf75d31c59b25e19eebcb80f39c155365b.tar.bz2
scala-0b2f1bcf75d31c59b25e19eebcb80f39c155365b.zip
Introduces scala-reflect.jar
Diffstat (limited to 'src/reflect/scala/reflect/internal/Importers.scala')
-rw-r--r--src/reflect/scala/reflect/internal/Importers.scala451
1 files changed, 451 insertions, 0 deletions
diff --git a/src/reflect/scala/reflect/internal/Importers.scala b/src/reflect/scala/reflect/internal/Importers.scala
new file mode 100644
index 0000000000..431d9819a5
--- /dev/null
+++ b/src/reflect/scala/reflect/internal/Importers.scala
@@ -0,0 +1,451 @@
+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?
+ def mkImporter(from0: api.Universe): Importer { val from: from0.type } = (
+ if (self 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]
+ }
+ } else {
+ // todo. fix this loophole
+ assert(from0.isInstanceOf[SymbolTable], "`from` should be an instance of scala.reflect.internal.SymbolTable")
+ new StandardImporter { val from = from0.asInstanceOf[SymbolTable] }
+ }
+ ).asInstanceOf[Importer { val from: from0.type }]
+
+ abstract class StandardImporter extends Importer {
+
+ val from: SymbolTable
+
+ lazy val symMap: WeakHashMap[from.Symbol, Symbol] = new WeakHashMap
+ lazy val tpeMap: WeakHashMap[from.Type, Type] = new WeakHashMap
+
+ // fixups and maps prevent stackoverflows in importer
+ var pendingSyms = 0
+ var pendingTpes = 0
+ lazy val fixups = collection.mutable.MutableList[Function0[Unit]]()
+ def addFixup(fixup: => Unit): Unit = fixups += (() => fixup)
+ def tryFixup(): Unit = {
+ if (pendingSyms == 0 && pendingTpes == 0) {
+ val fixups = this.fixups.toList
+ this.fixups.clear()
+ fixups foreach { _() }
+ }
+ }
+
+ object reverse extends from.StandardImporter {
+ val from: self.type = self
+ for ((fromsym, mysym) <- StandardImporter.this.symMap) symMap += ((mysym, fromsym))
+ for ((fromtpe, mytpe) <- StandardImporter.this.tpeMap) tpeMap += ((mytpe, fromtpe))
+ }
+
+ // todo. careful import of positions
+ def importPosition(pos: from.Position): Position =
+ pos.asInstanceOf[Position]
+
+ def importSymbol(sym0: from.Symbol): Symbol = {
+ def doImport(sym: from.Symbol): Symbol = {
+ if (symMap.contains(sym))
+ return symMap(sym)
+
+ 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(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, importType(x.info), x.value, x.flags, x.origin)
+ 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)
+ 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(x) = mysym
+ mysym.sourceModule = importSymbol(x.sourceModule)
+ mysym
+ case x: from.ClassSymbol =>
+ val mysym = myowner.newClassSymbol(myname.toTypeName, mypos, myflags)
+ symMap(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(sym) = mysym
+ mysym setFlag Flags.LOCKED
+ mysym setInfo {
+ val mytypeParams = sym.typeParams map importSymbol
+ new LazyPolyType(mytypeParams) {
+ 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
+
+ def importOrRelink: Symbol = {
+ val sym = sym0 // makes sym visible in the debugger
+ if (sym == null)
+ null
+ else if (sym == from.NoSymbol)
+ NoSymbol
+ else if (sym.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)
+ }
+ 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
+ }
+ }
+ }
+
+ mysym
+ }
+ } // end importOrRelink
+
+ val sym = sym0
+ if (symMap contains sym) {
+ symMap(sym)
+ } else {
+ pendingSyms += 1
+
+ try {
+ symMap getOrElseUpdate (sym, importOrRelink)
+ } finally {
+ pendingSyms -= 1
+ tryFixup()
+ }
+ }
+ }
+
+ 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.constr0), x.typeArgs map importType, x.params map importSymbol)
+ case from.NotNullType(tpe) =>
+ NotNullType(importType(tpe))
+ 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)
+
+ if (tpeMap contains tpe) {
+ tpeMap(tpe)
+ } else {
+ pendingTpes += 1
+
+ try {
+ tpeMap getOrElseUpdate (tpe, importOrRelink)
+ } finally {
+ pendingTpes -= 1
+ tryFixup()
+ }
+ }
+ }
+
+ def importTypeBounds(bounds: from.TypeBounds) = importType(bounds).asInstanceOf[TypeBounds]
+
+ def importAnnotationInfo(ann: from.AnnotationInfo): AnnotationInfo = {
+ val atp1 = importType(ann.atp)
+ val args1 = ann.args map importTree
+ val assocs1 = ann.assocs map { case (name, arg) => (importName(name), importAnnotArg(arg)) }
+ val original1 = importTree(ann.original)
+ AnnotationInfo(atp1, args1, assocs1) setOriginal original1
+ }
+
+ def importAnnotArg(arg: from.ClassfileAnnotArg): ClassfileAnnotArg = arg match {
+ case from.LiteralAnnotArg(constant @ from.Constant(_)) =>
+ LiteralAnnotArg(importConstant(constant))
+ case from.ArrayAnnotArg(args) =>
+ ArrayAnnotArg(args map importAnnotArg)
+ case from.ScalaSigBytes(bytes) =>
+ ScalaSigBytes(bytes)
+ case from.NestedAnnotArg(annInfo) =>
+ 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: override to cater for PackageScopes
+ def importScope(decls: from.Scope): Scope =
+ newScopeWith(decls.toList map importSymbol: _*)
+
+ 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 importTermName(name: from.TermName): TermName = importName(name).toTermName
+
+ 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.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.hasSymbol) importSymbol(tree.symbol) else NoSymbol
+ val mytpe = importType(tree.tpe)
+
+ mytree match {
+ case mytt: TypeTree =>
+ val tt = tree.asInstanceOf[from.TypeTree]
+ if (mytree.hasSymbol) mytt.symbol = mysym
+ if (tt.wasEmpty) mytt.defineType(mytpe) else mytt.setType(mytpe)
+ if (tt.original != null) mytt.setOriginal(importTree(tt.original))
+ case _ =>
+ if (mytree.hasSymbol) mytree.symbol = importSymbol(tree.symbol)
+ mytree.tpe = 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]
+ def importRefTree(tree: from.RefTree): RefTree = importTree(tree).asInstanceOf[RefTree]
+ def importIdent(tree: from.Ident): Ident = importTree(tree).asInstanceOf[Ident]
+ def importCaseDef(tree: from.CaseDef): CaseDef = importTree(tree).asInstanceOf[CaseDef]
+ def importConstant(constant: from.Constant): Constant = new Constant(constant.tag match {
+ case ClazzTag => importType(constant.value.asInstanceOf[from.Type])
+ case EnumTag => importSymbol(constant.value.asInstanceOf[from.Symbol])
+ case _ => constant.value
+ })
+ }
+} \ No newline at end of file