diff options
author | Eugene Burmako <xeno.by@gmail.com> | 2012-06-08 02:36:10 +0200 |
---|---|---|
committer | Eugene Burmako <xeno.by@gmail.com> | 2012-06-08 15:32:28 +0200 |
commit | 0b2f1bcf75d31c59b25e19eebcb80f39c155365b (patch) | |
tree | 8d9dfc50ef01ca48c068b232af7e67a723325388 /src/reflect/scala/reflect/internal/Importers.scala | |
parent | 13213e3df0384b1fd815c0798758a22284572cdb (diff) | |
download | scala-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.scala | 451 |
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 |