summaryrefslogtreecommitdiff
path: root/sources/scala/tools/nsc/typechecker/Namers.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2005-02-16 13:15:42 +0000
committerMartin Odersky <odersky@gmail.com>2005-02-16 13:15:42 +0000
commit28c2394d012195e38308bcd6fd5049bcde635b4c (patch)
treeefc1ab19ecba057cf626af0d86e0aa85b985b941 /sources/scala/tools/nsc/typechecker/Namers.scala
parent431abf42bda2c97ff062594a8f1d15fd7776350c (diff)
downloadscala-28c2394d012195e38308bcd6fd5049bcde635b4c.tar.gz
scala-28c2394d012195e38308bcd6fd5049bcde635b4c.tar.bz2
scala-28c2394d012195e38308bcd6fd5049bcde635b4c.zip
*** empty log message ***
Diffstat (limited to 'sources/scala/tools/nsc/typechecker/Namers.scala')
-rwxr-xr-xsources/scala/tools/nsc/typechecker/Namers.scala166
1 files changed, 166 insertions, 0 deletions
diff --git a/sources/scala/tools/nsc/typechecker/Namers.scala b/sources/scala/tools/nsc/typechecker/Namers.scala
new file mode 100755
index 0000000000..1215c5ddfb
--- /dev/null
+++ b/sources/scala/tools/nsc/typechecker/Namers.scala
@@ -0,0 +1,166 @@
+/* NSC -- new scala compiler
+ * Copyright 2005 LAMP/EPFL
+ * @author Martin Odersky
+ */
+// $Id$
+package scala.tools.nsc.typechecker;
+
+import scala.tools.util.Position;
+import symtab.Flags._;
+
+/** Methods to create symbols and to enter them into scopes. */
+trait Namers: Analyzer {
+ import global._;
+
+ class NamerPhase(prev: Phase) extends StdPhase(prev) {
+ def name = "namer";
+ val global: Namers.this.global.type = Namers.this.global;
+ def apply(unit: CompilationUnit): unit =
+ new Namer(startContext.make(unit)).enterSyms(unit.body);
+ }
+
+ class Namer(context: Context) {
+
+ val typer = new Typer(context);
+
+ private def doubleDefError(pos: int, sym: Symbol): unit =
+ context.unit.error(pos,
+ sym.name.toString() + " is already defined as " +
+ (if ((sym.rawflags & CASE) != 0) "case class " + sym.name else sym.toString()));
+
+ private def updatePosFlags(sym: Symbol, pos: int, mods: int): Symbol = {
+ val sym1 = if (sym.isExternal && !sym.isPackage) sym
+ else { doubleDefError(pos, sym); sym.cloneSymbol }
+ sym1.pos = pos;
+ val oldflags = sym1.rawflags & (INITIALIZED | LOCKED);
+ val newflags = mods & ~(INITIALIZED | LOCKED);
+ sym1.rawflags = oldflags | newflags;
+ if (sym1.isModule)
+ updatePosFlags(sym1.moduleClass, pos, (mods & MODULE2CLASSFLAGS) | MODULE | FINAL);
+ sym1
+ }
+
+ private def enterInScope(pos: int, sym: Symbol): Symbol = {
+ if (!(sym.isMethod && sym.owner.isClass)) {
+ val prev = context.scope.lookupEntry(sym.name);
+ if (prev != null && prev.owner == context.scope && !prev.sym.isMethod)
+ doubleDefError(pos, prev.sym);
+ }
+ context.scope enter sym;
+ sym
+ }
+
+ private def enterPackageSymbol(pos: int, name: Name): Symbol = {
+ val p: Symbol = context.scope.lookup(name);
+ if (p.isPackage && context.scope == p.owner.info.decls) {
+ p.pos = pos; p.moduleClass.pos = pos; p
+ } else {
+ enterInScope(pos, context.owner.newPackage(pos, name))
+ }
+ }
+
+ private def enterClassSymbol(pos: int, mods: int, name: Name): Symbol = {
+ val c: Symbol = context.scope.lookup(name);
+ if (c.isType && context.scope == c.owner.info.decls) {
+ updatePosFlags(c, pos, mods)
+ } else {
+ enterInScope(pos, context.owner.newClass(pos, name).setFlag(mods))
+ }
+ }
+
+ private def enterModuleSymbol(pos: int, mods: int, name: Name): Symbol = {
+ val m: Symbol = context.scope.lookup(name);
+ if (m.isModule && context.scope == m.owner.info.decls) {
+ updatePosFlags(m, pos, mods)
+ } else {
+ val newm = context.owner.newModule(pos, name);
+ newm.setFlag(mods);
+ newm.moduleClass.setFlag(mods);
+ enterInScope(pos, newm)
+ }
+ }
+
+ private def enterCaseFactorySymbol(pos: int, mods: int, name: Name): Symbol = {
+ val m: Symbol = context.scope.lookup(name);
+ if (m.isModule && context.scope == m.owner.info.decls) {
+ updatePosFlags(m, pos, mods)
+ } else {
+ enterInScope(pos, context.owner.newMethod(pos, name).setFlag(mods))
+ }
+ }
+
+ def enterSyms(trees: List[Tree]): unit =
+ for (val tree <- trees) enterSym(tree);
+
+ def enterSym(tree: Tree): Symbol = {
+
+ def finishWith(tparams: List[AbsTypeDef]) = {
+ val ltype = typer.typeCompleter(tree);
+ def makeParam(tparam: AbsTypeDef): Symbol =
+ tree.symbol.newTypeParameter(tparam.pos, tparam.name);
+ tree.symbol.setInfo(
+ if (tparams.isEmpty) ltype
+ else new LazyPolyType(tparams map makeParam, ltype))
+ }
+ def finish = finishWith(List());
+
+ if (tree.symbol != null) tree.symbol
+ else {
+ val owner = context.owner;
+ tree match {
+ case PackageDef(name, stats) =>
+ tree.symbol = enterPackageSymbol(tree.pos, name);
+ val namer = new Namer(
+ context.make(tree, tree.symbol.moduleClass, tree.symbol.info.decls));
+ stats map namer.enterSym;
+ tree.symbol
+ case ClassDef(mods, name, tparams, _, _) =>
+ if ((mods & (CASE | ABSTRACT)) == CASE) { // enter case factory method.
+ tree.symbol = enterCaseFactorySymbol(
+ tree.pos, mods & ACCESSFLAGS | CASE, name.toTermName);
+ finishWith(tparams);
+ }
+ tree.symbol = enterClassSymbol(tree.pos, mods, name);
+ val constr = tree.symbol.newConstructor(tree.pos)
+ .setFlag(tree.symbol.rawflags & CONSTRFLAGS)
+ .setInfo(typer.typeCompleter(tree));
+ tree.symbol.info.decls enter constr;
+ finishWith(tparams)
+ case ModuleDef(mods, name, _, _) =>
+ tree.symbol = enterModuleSymbol(tree.pos, mods, name);
+ tree.symbol.moduleClass.setInfo(typer.typeCompleter(tree));
+ finish
+ case ValDef(mods, name, tp, rhs) =>
+ tree.symbol = enterInScope(tree.pos, owner.newValue(tree.pos, name).setFlag(mods));
+ finish
+ case DefDef(mods, nme.CONSTRUCTOR, tparams, vparams, tp, rhs) =>
+ if (!(owner.isClass && context.scope == owner.info.decls) ||
+ owner.isModuleClass || owner.isAnonymousClass || owner.isRefinementClass)
+ context.unit.error(tree.pos, "constructor definition not allowed here");
+ tree.symbol = enterInScope(tree.pos, owner.newConstructor(tree.pos))
+ .setFlag(mods | owner.rawflags & CONSTRFLAGS);
+ finishWith(tparams)
+ case DefDef(mods, name, tparams, _, _, _) =>
+ tree.symbol = enterInScope(tree.pos, owner.newMethod(tree.pos, name)).setFlag(mods);
+ finishWith(tparams)
+ case AbsTypeDef(mods, name, _, _) =>
+ tree.symbol = enterInScope(tree.pos, owner.newAbstractType(tree.pos, name));
+ finish
+ case AliasTypeDef(mods, name, tparams, _) =>
+ tree.symbol = enterInScope(tree.pos, owner.newAliasType(tree.pos, name));
+ finishWith(tparams)
+ case Attributed(_, defn) =>
+ enterSym(defn)
+ case DocDef(_, defn) =>
+ enterSym(defn)
+ case Import(expr, selectors) =>
+ tree.symbol = NoSymbol.newImport(tree.pos);
+ finish
+ case _ =>
+ NoSymbol
+ }
+ }
+ }
+ }
+}
+