From 3ec2af254866c60389b3fd304c14d1137b9cf4c8 Mon Sep 17 00:00:00 2001 From: paltherr Date: Wed, 14 Apr 2004 13:31:35 +0000 Subject: - Replaced Symbol.module by Symbol.sourceModule - Made Symbol.linkedModule and Symbol.linkedClass a bit less ambiguous - Added documentation to Symbol.sourceModule and Symbol.linkedModule - Added classes ConstructorSymbol, ModuleSymbol ModuleClassSymbol - Added classes LinkedModuleSymbol and LinkedClassSymbol - Changed the argument order in symbol constructors to be the same as in the symbol factories - Changed Pickle to use sourceModule instead of HashTable - Replaced notion of main class by notion of root symbol in SymbolLoader - Fixed UnPickle to work with any root symbol --- .../scala/tools/scalac/typechecker/Analyzer.scala | 3 - sources/scala/tools/scaladoc/HTMLGenerator.java | 4 +- sources/scala/tools/scaladoc/ScalaSearch.java | 2 +- sources/scalac/symtab/SourceCompleter.java | 2 +- sources/scalac/symtab/Symbol.java | 363 +++++++++++++-------- sources/scalac/symtab/SymbolLoader.java | 113 ++++--- sources/scalac/symtab/SymbolTablePrinter.java | 5 +- .../scalac/symtab/classfile/CLRClassParser.java | 10 +- .../scalac/symtab/classfile/CLRPackageParser.java | 4 +- sources/scalac/symtab/classfile/ClassParser.java | 6 +- sources/scalac/symtab/classfile/PackageParser.java | 5 +- sources/scalac/symtab/classfile/Pickle.java | 15 +- sources/scalac/symtab/classfile/SymblParser.java | 4 +- sources/scalac/symtab/classfile/UnPickle.java | 30 +- 14 files changed, 347 insertions(+), 219 deletions(-) diff --git a/sources/scala/tools/scalac/typechecker/Analyzer.scala b/sources/scala/tools/scalac/typechecker/Analyzer.scala index 3c0d37861c..68594cbb81 100644 --- a/sources/scala/tools/scalac/typechecker/Analyzer.scala +++ b/sources/scala/tools/scalac/typechecker/Analyzer.scala @@ -677,9 +677,6 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer( def moduleSymbol(pos: int, name: Name, owner: Symbol, flags: int, scope: Scope): Symbol = { val symbol = termSymbolOrNone(scope, pos, name, flags | MODUL | FINAL); if (symbol.isNone()) owner.newModule(pos, flags, name) else { - // The symbol has already been created by some symbol - // loader. It must be a real module (or package). - assert(symbol.moduleClass() != symbol, Debug.show(symbol)); val clasz = symbol.moduleClass(); updateFlagsAndPos(clasz, pos, clasz.flags & ~(JAVA | PACKAGE)); val constr = clasz.primaryConstructor(); diff --git a/sources/scala/tools/scaladoc/HTMLGenerator.java b/sources/scala/tools/scaladoc/HTMLGenerator.java index 3ff44c6939..6978ba92a0 100644 --- a/sources/scala/tools/scaladoc/HTMLGenerator.java +++ b/sources/scala/tools/scaladoc/HTMLGenerator.java @@ -978,7 +978,7 @@ public abstract class HTMLGenerator { Symbol[] owners = (Symbol[]) grouped.fst; Map/**/ group = (Map) grouped.snd; for (int i = 0; i < owners.length; i++) { - if (owners[i] != sym.moduleClass()) { + if (owners[i] != (sym.isModule() ? sym.moduleClass() : sym)) { page.printlnOTag("table", ATTRS_MEMBER).indent(); // owner @@ -1053,7 +1053,7 @@ public abstract class HTMLGenerator { } // parents - Type[] parts = symbol.moduleClass().parents(); + Type[] parts = (symbol.isModule() ? symbol.moduleClass() : symbol).parents(); page.printlnCTag("dt"); for (int i = 0; i < parts.length; i++) { page.printOTag("dd"); diff --git a/sources/scala/tools/scaladoc/ScalaSearch.java b/sources/scala/tools/scaladoc/ScalaSearch.java index b697e9c862..96f3d5e174 100644 --- a/sources/scala/tools/scaladoc/ScalaSearch.java +++ b/sources/scala/tools/scaladoc/ScalaSearch.java @@ -376,7 +376,7 @@ public class ScalaSearch { final Map subs = new HashMap(); foreach(root, new SymFun() { public void apply(Symbol sym) { if (sym.isClass() || sym.isModule()) { - Type[] parents = sym.moduleClass().parents(); + Type[] parents = (sym.isModule() ? sym.moduleClass(): sym).parents(); for (int i = 0; i < parents.length; i++) { Symbol parentSymbol = parents[i].symbol(); List subList = (List) subs.get(parentSymbol); diff --git a/sources/scalac/symtab/SourceCompleter.java b/sources/scalac/symtab/SourceCompleter.java index fa6157ea14..73596724bd 100644 --- a/sources/scalac/symtab/SourceCompleter.java +++ b/sources/scalac/symtab/SourceCompleter.java @@ -37,7 +37,7 @@ public class SourceCompleter extends SymbolLoader { // Protected Methods /** Completes the specified symbol by reading the source file. */ - protected String doComplete(Symbol clasz) throws IOException { + protected String doComplete(Symbol root) throws IOException { global.compileLate(global.getSourceFile(file), false); return "source file '" + file + "'"; } diff --git a/sources/scalac/symtab/Symbol.java b/sources/scalac/symtab/Symbol.java index defa4b18af..1b32899c69 100644 --- a/sources/scalac/symtab/Symbol.java +++ b/sources/scalac/symtab/Symbol.java @@ -78,7 +78,7 @@ public abstract class Symbol implements Modifiers, Kinds { // Constructors ----------------------------------------------------------- /** Generic symbol constructor */ - public Symbol(int kind, int pos, Name name, Symbol owner, int flags, int attrs) { + public Symbol(int kind, Symbol owner, int pos, int flags, Name name, int attrs) { this.kind = kind; this.pos = pos; this.name = name; @@ -98,7 +98,7 @@ public abstract class Symbol implements Modifiers, Kinds { /** Creates a new constructor of this symbol. */ public final Symbol newConstructor(int pos, int flags) { assert isType(): Debug.show(this); - return new TermSymbol(pos, Names.CONSTRUCTOR, owner(), flags, 0, this); + return new ConstructorSymbol(this, pos, flags); } /** Creates a new method owned by this symbol. */ @@ -184,7 +184,7 @@ public abstract class Symbol implements Modifiers, Kinds { /** Creates a new module owned by this symbol. */ public final Symbol newModule(int pos, int flags, Name name) { - return newTerm(pos, flags | MODUL | FINAL | STABLE, name, 0); + return new ModuleSymbol(this, pos, flags, name); } /** @@ -220,12 +220,12 @@ public abstract class Symbol implements Modifiers, Kinds { /** Creates a new type alias owned by this symbol. */ public final Symbol newTypeAlias(int pos, int flags, Name name) { - return new AliasTypeSymbol(pos, name, this, flags, 0); + return new AliasTypeSymbol(this, pos, flags, name, 0); } /** Creates a new abstract type owned by this symbol. */ public final Symbol newAbstractType(int pos, int flags, Name name) { - return new AbsTypeSymbol(pos, name, this, flags, 0); + return new AbsTypeSymbol(this, pos, flags, name, 0); } /** Creates a new type parameter owned by this symbol. */ @@ -276,7 +276,7 @@ public abstract class Symbol implements Modifiers, Kinds { { assert isPackageClass(): Debug.show(this); assert loader != null: Debug.show(this) + " - " + name; - ClassSymbol clasz = new LinkedClassSymbol(name, this, flags); + ClassSymbol clasz = new LinkedClassSymbol(this, flags, name); clasz.setInfo(loader); clasz.allConstructors().setInfo(loader); clasz.linkedModule().setInfo(loader); @@ -300,7 +300,7 @@ public abstract class Symbol implements Modifiers, Kinds { /** Creates a new term owned by this symbol. */ final Symbol newTerm(int pos, int flags, Name name, int attrs) { - return new TermSymbol(pos, name, this, flags, attrs, null); + return new TermSymbol(this, pos, flags, name, attrs); } /** Creates a new package owned by this symbol. */ @@ -315,7 +315,7 @@ public abstract class Symbol implements Modifiers, Kinds { /** Creates a new class owned by this symbol. */ final ClassSymbol newClass(int pos, int flags, Name name, int attrs) { - return new ClassSymbol(pos, name, this, flags, attrs); + return new ClassSymbol(this, pos, flags, name, attrs); } /** Creates a new compound class owned by this symbol. */ @@ -434,7 +434,6 @@ public abstract class Symbol implements Modifiers, Kinds { || info instanceof Type.OverloadedType || info instanceof Type.PolyType : "illegal type for " + this + ": " + info; - // !!! if (phase.prev != null) phase = phase.prev; infos = new TypeIntervalList(null, info, phase); if (info instanceof Type.LazyType) flags &= ~INITIALIZED; else flags |= INITIALIZED; @@ -447,7 +446,7 @@ public abstract class Symbol implements Modifiers, Kinds { * "nextInfo". It will not be transformed by the current phase. */ public final Symbol updateInfo(Type info) { - return updateInfoAt_(info, Global.instance.currentPhase.next); + return updateInfoAt(info, Global.instance.currentPhase.next); } /** @@ -456,7 +455,7 @@ public abstract class Symbol implements Modifiers, Kinds { * which is also the first phase that will transform this * information. */ - private final Symbol updateInfoAt_(Type info, Phase phase) { + private final Symbol updateInfoAt(Type info, Phase phase) { assert info != null: Debug.show(this); assert phase != null: Debug.show(this); assert infos != null: Debug.show(this); @@ -889,23 +888,64 @@ public abstract class Symbol implements Modifiers, Kinds { return NONE; } - /** Get module associated with class */ - public Symbol module() { - return NONE; - } - /** - * Returns the linked class if there is one and NONE otherwise. + * Returns the class linked to this module or null if there is no + * such class. The returned value remains the same for the whole + * life of the symbol. + * + * See method "linkedModule" to learn more about linked modules + * and classes. */ - public Symbol linkedClass() { - return NONE; + public ClassSymbol linkedClass() { + assert isModule(): "not a module: " + Debug.show(this); + return null; } /** - * Returns the linked module if there is one and NONE otherwise. - */ - public Symbol linkedModule() { - return NONE; + * Returns the module linked to this class or null if there is no + * such module. The returned value remains the same for the whole + * life of the symbol. + * + * Linked modules and classes are intended to be used by the + * symbol table loader. They are needed because it is impossible + * to know from the name of a class or source file if it defines a + * class or a module. For that reason a class and a module (each + * linked to the other) are created for each of those files. Once + * the file is read the class, the module or both are initialized + * depending on what the file defines. + * + * It is guaranteed that if a class "c" has a linked module then + * "c.linkedModule().linkedClasss() == c" and that if a module "m" + * has a linked class then "m.linkedClasss().linkedModule() == m". + * + * The linked module of a Java class, is the module that contains + * the static members of that class. A Java class has always a + * linked module. + * + * The linked module of a Scala class, is the module with the same + * name declared in the same scope. A Scala class may or may not + * have a linked module. However, this does not depend on the + * presence or absence of a module with the same name but on how + * the class is created. Therefore a Scala class may have no + * linked module even though there exists a module with the same + * name in the same scope. A Scala class may also have a linked + * module even though there exists no module with the same name in + * the same scope. In the latter case, the linked would be + * initialized to NoType (which prevents accesses to it). + * + * There is a last catch about linked modules. It may happen that + * the symbol returned by "linkedModule" is not a module (and that + * method "linkedClass" works on a non-module symbol). At creation + * time, linked modules are always modules, but at initialization + * time, it may be discovered that the module is in fact a case + * class factory method. In that case, the module is downgraded to + * a non-module term. This implies that from then on calls to its + * method "moduleClass" will fail, but the links defined by the + * methods "linkedModule" and "linkedClass" remain unchanged. + */ + public ModuleSymbol linkedModule() { + assert isClassType(): "not a class: " + Debug.show(this); + return null; } /** Get owner */ @@ -957,11 +997,50 @@ public abstract class Symbol implements Modifiers, Kinds { return this; } - /* If this is a module, return its class. - * Otherwise return the symbol itself. + /** + * Returns the class of this module. This method may be invoked + * only on module symbols. It returns always a non-null module + * class symbol whose identity never changes. */ - public Symbol moduleClass() { - return this; + public ModuleClassSymbol moduleClass() { + throw Debug.abort("not a module", this); + } + + /** + * Returns the source module of this module class. This method may + * be invoked only on module class symbols. It returns always a + * non-null module symbol whose identity never changes. + * + * This method should be used with great care. If possible, one + * should always use moduleClass instead. For example, one should + * write "m.moduleClass()==c" rather than "m==c.sourceModule()". + * + * This method is problematic because the module - module-class + * relation is not a one - one relation. There might be more than + * one module that share the same module class. In that case, the + * source module of the module class is the module that created + * the class. This implies that "m.moduleClass().sourceModule()" + * may be different of "m". However, its is guaranteed that + * "c.sourceModule().moduleClass()" always returns "c". + * + * Phases like "AddInterfaces" and "ExpandMixins" are two examples + * of phases that create additional modules referring the same + * module class. + * + * Even if a module class is related to only one module, the use + * of this method may still be dangerous. The problem is that + * modules and module classes are not always as related as one + * might expect. For example, modules declared in a function are + * lifted out of the function by phase "LambdaLift". During this + * process, the module value is transformed into a module method + * with a "Ref" argument. If the "sourceModule" method is used to + * replace references to module classes by references to their + * source modules and this is done it naively with the class of a + * lifted module, it will yield wrong code because the the "Ref" + * argument will be missing. + */ + public ModuleSymbol sourceModule() { + throw Debug.abort("not a module class", this); } /** if type is a (possibly lazy) overloaded type, return its alternatves @@ -1138,7 +1217,6 @@ public abstract class Symbol implements Modifiers, Kinds { return infos.info; } else { TypeIntervalList infos = this.infos; - // !!! && infos.prev != null while (phase.id < infos.start.id && infos.prev != null) infos = infos.prev; return infos.info; @@ -1262,7 +1340,9 @@ public abstract class Symbol implements Modifiers, Kinds { if (global.PHASE.EXPLICITOUTER.id() < global.currentPhase.id) return Type.NoPrefix; if (isRoot()) return thisType(); - return Type.singleType(owner.staticPrefix(), module()); + assert sourceModule().owner() == owner(): Debug.show(this); + assert sourceModule().type().isObjectType(): Debug.show(this); + return Type.singleType(owner.staticPrefix(), sourceModule()); } /** The type constructor of a symbol is: @@ -1396,8 +1476,10 @@ public abstract class Symbol implements Modifiers, Kinds { if (owner.kind == CLASS && !owner.isAnonymousClass() && !owner.isCompoundSym() || Global.instance.debug) - return " in " + + return " in " + owner; + /* (owner.isModuleClass() ? ((ClassSymbol) owner).module() : owner); + */ else return ""; } @@ -1563,34 +1645,14 @@ public abstract class Symbol implements Modifiers, Kinds { */ class TermSymbol extends Symbol { - /** - * The module class if this is a module, the constructed class if - * this is a constructor and null otherwise - */ - private final Symbol clasz; - /** Constructor */ - TermSymbol(int pos, Name name, Symbol owner, int flags, int attrs, Symbol clasz) { - super(VAL, pos, name, owner, flags, attrs); - this.clasz = clasz == null && isModule() ? newModuleClass() : clasz; - if (isModule()) setType(this.clasz.typeConstructor()); + TermSymbol(Symbol owner, int pos, int flags, Name name, int attrs) { + super(VAL, owner, pos, flags, name, attrs); assert name.isTermName(): Debug.show(this); - assert (isModule() || isConstructor()) == (this.clasz != null): this; } - /** Creates the module class associated to this module. */ - ClassSymbol newModuleClass() { - return new ClassSymbol(this); - } - - /** Is this symbol an instance initializer? */ public boolean isInitializer() { - return clasz == null && name == Names.INITIALIZER; - } - - /** Is this symbol a constructor? */ - public boolean isConstructor() { - return clasz != null && name == Names.CONSTRUCTOR; + return name == Names.INITIALIZER; } public Symbol[] typeParams() { @@ -1601,45 +1663,97 @@ class TermSymbol extends Symbol { return type().valueParams(); } + protected Symbol cloneSymbolImpl(Symbol owner, int attrs) { + return new TermSymbol(owner, pos, flags, name, attrs); + } + +} + +/** A class for constructor symbols */ +final class ConstructorSymbol extends TermSymbol { + + /** The constructed class */ + private final Symbol clasz; + + /** Initializes this instance. */ + ConstructorSymbol(Symbol clasz, int pos, int flags) { + super(clasz.owner(), pos, flags, Names.CONSTRUCTOR, 0); + this.clasz = clasz; + } + + public boolean isInitializer() { + return false; + } + + public boolean isConstructor() { + return true; + } + public Symbol constructorClass() { - return isConstructor() ? clasz : this; + return clasz; + } + + protected final Symbol cloneSymbolImpl(Symbol owner, int attrs) { + throw Debug.abort("illegal clone of constructor", this); } - public Symbol moduleClass() { - return isModule() ? clasz : this; +} + +/** A class for module symbols */ +public class ModuleSymbol extends TermSymbol { + + /** The module class */ + private final ModuleClassSymbol clasz; + + /** Initializes this instance. */ + private ModuleSymbol(Symbol owner, int pos, int flags, Name name, + int attrs, ModuleClassSymbol clasz) + { + super(owner, pos, flags | MODUL | FINAL | STABLE, name, attrs); + this.clasz = clasz != null ? clasz : new ModuleClassSymbol(this); + setType(Type.typeRef(owner().thisType(), this.clasz,Type.EMPTY_ARRAY)); + } + + /** Initializes this instance. */ + ModuleSymbol(Symbol owner, int pos, int flags, Name name) { + this(owner, pos, flags, name, 0, null); + } + + public ModuleClassSymbol moduleClass() { + // test may fail because loaded modules may be downgraded to + // case class factory methods (see Symbol#linkedModule()) + + assert isModule(): Debug.show(this); + return clasz; } protected final Symbol cloneSymbolImpl(Symbol owner, int attrs) { - assert !isPrimaryConstructor() : Debug.show(this); - return new TermSymbol(pos, name, owner, flags, attrs, clasz); + return new ModuleSymbol(owner, pos, flags, name, attrs, clasz); } } -final class LinkedModuleSymbol extends TermSymbol { +/** + * A class for linked module symbols + * + * @see Symbol#linkedModule() + */ +final class LinkedModuleSymbol extends ModuleSymbol { /** The linked class */ private final LinkedClassSymbol clasz; - /** Inistializes this instance. */ + /** Initializes this instance. */ LinkedModuleSymbol(LinkedClassSymbol clasz) { - super(clasz.pos, clasz.name.toTermName(), clasz.owner(), - (clasz.flags & JAVA) | MODUL | FINAL | STABLE, 0, null); + super(clasz.owner(), clasz.pos, clasz.flags & JAVA, + clasz.name.toTermName()); this.clasz = clasz; } - final ClassSymbol newModuleClass() { - return new LinkedModuleClassSymbol(this); - } - - public Symbol linkedClass() { + public ClassSymbol linkedClass() { return clasz; } - public Symbol linkedModule() { - return this; - } - } /** A base class for all type symbols. @@ -1658,8 +1772,8 @@ abstract class TypeSymbol extends Symbol { private Symbol constructor; /** Constructor */ - public TypeSymbol(int kind, int pos, Name name, Symbol owner, int flags, int attrs) { - super(kind, pos, name, owner, flags, attrs); + public TypeSymbol(int kind, Symbol owner, int pos, int flags, Name name, int attrs) { + super(kind, owner, pos, flags, name, attrs); this.closures = new ClosureHistory(); assert name.isTypeName() : this; this.constructor = newConstructor(pos, flags & CONSTRFLAGS); @@ -1785,12 +1899,12 @@ abstract class TypeSymbol extends Symbol { final class AliasTypeSymbol extends TypeSymbol { /** Initializes this instance. */ - AliasTypeSymbol(int pos, Name name, Symbol owner, int flags, int attrs) { - super(ALIAS, pos, name, owner, flags, attrs); + AliasTypeSymbol(Symbol owner, int pos, int flags, Name name, int attrs) { + super(ALIAS, owner, pos, flags, name, attrs); } protected TypeSymbol cloneTypeSymbolImpl(Symbol owner, int attrs) { - return new AliasTypeSymbol(pos, name, owner, flags, attrs); + return new AliasTypeSymbol(owner, pos, flags, name, attrs); } } @@ -1801,8 +1915,8 @@ final class AbsTypeSymbol extends TypeSymbol { private Type vubound = null; /** Initializes this instance. */ - AbsTypeSymbol(int pos, Name name, Symbol owner, int flags, int attrs) { - super(TYPE, pos, name, owner, flags, attrs); + AbsTypeSymbol(Symbol owner, int pos, int flags, Name name, int attrs) { + super(TYPE, owner, pos, flags, name, attrs); allConstructors().setInfo(Type.MethodType(EMPTY_ARRAY, Type.typeRef(owner.thisType(), this, Type.EMPTY_ARRAY))); } @@ -1828,7 +1942,7 @@ final class AbsTypeSymbol extends TypeSymbol { } protected TypeSymbol cloneTypeSymbolImpl(Symbol owner, int attrs) { - TypeSymbol clone = new AbsTypeSymbol(pos, name, owner, flags, attrs); + TypeSymbol clone = new AbsTypeSymbol(owner, pos, flags, name, attrs); clone.setLoBound(loBound()); clone.setVuBound(vuBound()); return clone; @@ -1839,9 +1953,6 @@ final class AbsTypeSymbol extends TypeSymbol { /** A class for class symbols. */ public class ClassSymbol extends TypeSymbol { - /** The module belonging to the class or NONE. */ - private final Symbol module; - /** The given type of self, or NoType, if no explicit type was given. */ private Symbol thisSym = this; @@ -1855,29 +1966,12 @@ public class ClassSymbol extends TypeSymbol { private final Symbol rebindSym; /** Initializes this instance. */ - private ClassSymbol(int pos, Name name, Symbol owner, int flags, int attrs, Symbol module) { - super(CLASS, pos, name, owner, flags, attrs); + ClassSymbol(Symbol owner, int pos, int flags, Name name, int attrs) { + super(CLASS, owner, pos, flags, name, attrs); this.rebindSym = owner.newTypeAlias(pos, 0, Names.ALIAS(this)); Type rebindType = new ClassAliasLazyType(); this.rebindSym.setInfo(rebindType); this.rebindSym.primaryConstructor().setInfo(rebindType); - this.module = module; - assert isModuleClass() == !module.isNone(): Debug.show(this); - } - - /** Initializes this instance. */ - ClassSymbol(int pos, Name name, Symbol owner, int flags, int attrs) { - this(pos, name, owner, flags, attrs, Symbol.NONE); - } - - /** Initializes this instance. */ - ClassSymbol(TermSymbol module) { - this(module.pos, module.name.toTypeName(), module.owner(), - (module.flags & MODULE2CLASSFLAGS) | MODUL | FINAL, 0, - module); - primaryConstructor().flags |= PRIVATE; - primaryConstructor().setInfo( - Type.MethodType(Symbol.EMPTY_ARRAY, typeConstructor())); } private class ClassAliasLazyType extends Type.LazyType { @@ -1902,7 +1996,7 @@ public class ClassSymbol extends TypeSymbol { Symbol owner = Symbol.NONE; int flags = JAVA | PACKAGE | FINAL; int attrs = IS_ROOT; - Symbol clasz = new ClassSymbol(pos, name, owner, flags, attrs, NONE); + Symbol clasz = new ClassSymbol(owner, pos, flags, name, attrs); clasz.setInfo(global.getRootLoader()); clasz.primaryConstructor().setInfo( Type.MethodType(Symbol.EMPTY_ARRAY, clasz.typeConstructor())); @@ -1915,12 +2009,6 @@ public class ClassSymbol extends TypeSymbol { return newTerm(pos, SYNTHETIC, Names.this_, IS_THISTYPE); } - /** Get module */ - public Symbol module() { - assert !isRoot(): this + ".module()"; - return module; - } - public Type thisType() { Global global = Global.instance; if (global.currentPhase.id > global.PHASE.ERASURE.id()) return type(); @@ -1973,65 +2061,74 @@ public class ClassSymbol extends TypeSymbol { public void reset(Type completer) { super.reset(completer); - module().reset(completer); thisSym = this; } - protected TypeSymbol cloneTypeSymbolImpl(Symbol owner, int attrs) { + protected final TypeSymbol cloneTypeSymbolImpl(Symbol owner, int attrs) { assert !isModuleClass(): Debug.show(this); - ClassSymbol clone = new ClassSymbol(pos, name, owner,flags,attrs,NONE); + ClassSymbol clone = new ClassSymbol(owner, pos, flags, name, attrs); if (thisSym != this) clone.setTypeOfThis(typeOfThis()); return clone; } } -final class LinkedClassSymbol extends ClassSymbol { +/** + * A class for module class symbols + * + * @see Symbol#sourceModule() + */ +public final class ModuleClassSymbol extends ClassSymbol { - /** The linked module */ - private final LinkedModuleSymbol module; + /** The source module */ + private final ModuleSymbol module; /** Initializes this instance. */ - LinkedClassSymbol(Name name, Symbol owner, int flags) { - super(Position.NOPOS, name, owner, flags, 0); - this.module = new LinkedModuleSymbol(this); - } - - public Symbol linkedClass() { - return this; + ModuleClassSymbol(ModuleSymbol module) { + super(module.owner(), module.pos, + (module.flags & MODULE2CLASSFLAGS) | MODUL | FINAL, + module.name.toTypeName(), 0); + primaryConstructor().flags |= PRIVATE; + primaryConstructor().setInfo( + Type.MethodType(Symbol.EMPTY_ARRAY, typeConstructor())); + this.module = module; } - public Symbol linkedModule() { + public ModuleSymbol sourceModule() { return module; } } -final class LinkedModuleClassSymbol extends ClassSymbol { +/** + * A class for linked class symbols + * + * @see Symbol#linkedModule() + */ +final class LinkedClassSymbol extends ClassSymbol { - /** Initializes this instance. */ - LinkedModuleClassSymbol(LinkedModuleSymbol module) { - super(module); - } + /** The linked module */ + private final LinkedModuleSymbol module; - public Symbol linkedClass() { - return linkedModule().linkedClass(); + /** Initializes this instance. */ + LinkedClassSymbol(Symbol owner, int flags, Name name) { + super(owner, Position.NOPOS, flags, name, 0); + this.module = new LinkedModuleSymbol(this); } - public Symbol linkedModule() { - return module(); + public ModuleSymbol linkedModule() { + return module; } } - /** The class of Symbol.NONE */ final class NoSymbol extends Symbol { /** Constructor */ public NoSymbol() { - super(Kinds.NONE, Position.NOPOS, Names.NOSYMBOL, null, 0, 0); + super(Kinds.NONE, null, Position.NOPOS, 0, Names.NOSYMBOL, 0); super.setInfo(Type.NoType); } diff --git a/sources/scalac/symtab/SymbolLoader.java b/sources/scalac/symtab/SymbolLoader.java index 3a4c1464eb..d02829f191 100644 --- a/sources/scalac/symtab/SymbolLoader.java +++ b/sources/scalac/symtab/SymbolLoader.java @@ -40,36 +40,37 @@ public abstract class SymbolLoader extends Type.LazyType { // Public Methods /** - * Completes the symbol. More precisely, it completes all related - * symbols of the main class of the symbol. It is guaranteed that - * after this method call all these symbols are initialized (or at - * least that their info does not contain this lazy type). + * Completes the specified symbol. More precisely, it completes + * all symbols related to the root symbol of the specified + * symbol. It is guaranteed that after this method call all these + * symbols are initialized (or at least that their info does no + * longer contain this lazy type). * - * The main class of a symbol is: - * - the main class of the constructed class, if it's a + * The root symbol of a symbol is: + * - the root symbol of the constructed class, if it's a * constructor, - * - the main class of the module class, if it's a module, - * - the linked class, if it's a linked module class, - * - itself if it's a non-linked class or a non-module class, + * - the root symbol of the source module, if it's a module class, + * - the linked class, if it's a module with a linked class, + * - itself if it's a class or a module with no linked class, * - undefined otherwise. * - * The related symbols of a class include: - * - the class itself, - * - its constructor (symbol returned by allConstructors()), - * - its linked module, if it has one, - * - the related symbols of its linked module class, if it has one + * The symbols related to a symbol include: + * - the symbol itself, + * - its constructor (allConstructors()), if it's a class, + * - the symbols related to its linked module, if there is one. + * - the symbols related to its module class, if it's a module, */ public final void complete(Symbol symbol) { - Symbol clasz = getMainClass(symbol); + Symbol root = getRootSymbol(symbol); try { long start = System.currentTimeMillis(); Phase phase = global.currentPhase; global.currentPhase = global.PHASE.ANALYZER.phase(); - String source = doComplete(clasz); + String source = doComplete(root); global.currentPhase = phase; long end = System.currentTimeMillis(); global.operation("loaded " + source + " in " + (end-start) + "ms"); - checkValidity(clasz, source); + checkValidity(root, source); } catch (IOException exception) { if (global.debug) exception.printStackTrace(); String error = "error while loading " + symbol; @@ -77,7 +78,7 @@ public abstract class SymbolLoader extends Type.LazyType { error = message != null ? error + ", " + message : "i/o " + error; global.error(error); } - initializeAll(clasz); + initializeRoot(root); } //######################################################################## @@ -86,56 +87,78 @@ public abstract class SymbolLoader extends Type.LazyType { /** * Performs the actual loading and returns the name of the * external source. It is guaranteed that the argument of this - * method is always a main class (see also method complete). + * method is always a root symbol + * + * @see complete(Symbol) */ - protected abstract String doComplete(Symbol clasz) throws IOException; + protected abstract String doComplete(Symbol root) throws IOException; //######################################################################## // Private Methods - /** Returns the main class of the symbol (see method complete). */ - private Symbol getMainClass(Symbol symbol) { + /** + * Returns the root symbol of the specified symbol. + * + * @see complete(Symbol) + */ + private Symbol getRootSymbol(Symbol symbol) { if (symbol.isConstructor()) - return getMainClass(symbol.constructorClass()); - if (symbol.isModule()) - return getMainClass(symbol.moduleClass()); - if (symbol.isModuleClass() && !symbol.linkedClass().isNone()) + return getRootSymbol(symbol.constructorClass()); + if (symbol.isModuleClass()) + return getRootSymbol(symbol.sourceModule()); + if (symbol.isModule() && symbol.linkedClass() != null) return symbol.linkedClass(); - assert symbol.isClassType(): Debug.show(symbol); + assert symbol.isClassType() || symbol.isModule(): Debug.show(symbol); return symbol; } /** - * Checks that at least the class or its dual class have been - * initialized and signals an error otherwise. + * Checks that at least the specified root symbol or its linked + * module, if any, has been initialized and signals an error + * otherwise. + * + * @see complete(Symbol) */ - private void checkValidity(Symbol clasz, String source) { - if (clasz.rawInfo() != this) return; + private void checkValidity(Symbol root, String source) { + if (root.rawInfo() != this) return; String what; - if (clasz.linkedClass().isNone()) { - what = "does not define " + clasz.linkedModule(); + if (!root.isClassType() || root.linkedModule() == null) { + what = "does not define " + root; } else { - if (clasz.linkedModule().moduleClass().rawInfo() != this) return; - what = "defines neither " + clasz + " nor " + clasz.linkedModule(); + if (root.linkedModule().moduleClass().rawInfo() != this) return; + what = "defines neither " + root + " nor " + root.linkedModule(); } global.error(source + " " + what); } /** - * Initializes all related symbols of the class whose info is this - * instance (see also method complete). + * Initializes all symbols related to the specified root symbol + * and whose info is this instance. + * + * @see complete(Symbol) + */ + private void initializeRoot(Symbol root) { + if (root.isClassType()) { + initializeClass(root); + if (root.linkedModule() != null) + initializeRoot(root.linkedModule()); + } else { + initializeSymbol(root); + if (root.isModule()) initializeClass(root.moduleClass()); + } + } + + /** + * Initializes the specified class and its constructor if their + * info is this instance. */ - private void initializeAll(Symbol clasz) { - initializeOne(clasz); - initializeOne(clasz.allConstructors()); - if (clasz.isModuleClass()) initializeOne(clasz.linkedModule()); - Symbol module = clasz.linkedModule(); - if (!module.isNone() && module.moduleClass() != clasz) - initializeAll(module.moduleClass()); + private void initializeClass(Symbol clasz) { + initializeSymbol(clasz); + initializeSymbol(clasz.allConstructors()); } /** Initializes the symbol if its info is this instance. */ - private void initializeOne(Symbol symbol) { + private void initializeSymbol(Symbol symbol) { if (symbol.rawInfo() != this) return; symbol.setInfo(symbol.isModule() ? Type.NoType : Type.ErrorType); if (symbol.isConstructor()) symbol.flags |= Modifiers.PRIVATE; diff --git a/sources/scalac/symtab/SymbolTablePrinter.java b/sources/scalac/symtab/SymbolTablePrinter.java index d70d62d3c2..89fe42d869 100644 --- a/sources/scalac/symtab/SymbolTablePrinter.java +++ b/sources/scalac/symtab/SymbolTablePrinter.java @@ -407,7 +407,10 @@ public class SymbolTablePrinter { case ThisType(Symbol clasz): if (global.debug || !clasz.isModuleClass()) return type; Type prefix = getTypeToPrintForType(clasz.owner().thisType()); - return Type.singleType(prefix, clasz.module()); + Symbol module = clasz.sourceModule(); + if (module.owner() != clasz.owner()) return type; + if (!module.type().isObjectType()) return type; + return Type.singleType(prefix, module); case SingleType(_, Symbol sym): if (global.debug) return type; if (sym.isSynthetic()) return type.widen(); diff --git a/sources/scalac/symtab/classfile/CLRClassParser.java b/sources/scalac/symtab/classfile/CLRClassParser.java index 7c7f2f1376..9de9d17629 100644 --- a/sources/scalac/symtab/classfile/CLRClassParser.java +++ b/sources/scalac/symtab/classfile/CLRClassParser.java @@ -39,10 +39,14 @@ public class CLRClassParser extends SymbolLoader { private static Name[] ENUM_BIT_LOG_NAMES = new Name[] { Names.OR, Names.AND, Names.XOR }; - protected String doComplete(Symbol clazz) { - try { return doComplete0(clazz); } + protected String doComplete(Symbol root) { + assert root.isClassType(): Debug.show(root); + try { return doComplete0(root); } catch (Throwable e) { - System.err.println("\nWhile processing " + Debug.show(clazz)); + // !!! doComplete may throw an IOException which is then + // caught by SymbolLoader and reported to the user as + // normal error message + System.err.println("\nWhile processing " + Debug.show(root)); e.printStackTrace(); System.exit(1); return null; // !!! diff --git a/sources/scalac/symtab/classfile/CLRPackageParser.java b/sources/scalac/symtab/classfile/CLRPackageParser.java index 10e6d4acd6..90fd0fcc47 100644 --- a/sources/scalac/symtab/classfile/CLRPackageParser.java +++ b/sources/scalac/symtab/classfile/CLRPackageParser.java @@ -221,7 +221,9 @@ public class CLRPackageParser extends SymbolLoader { //########################################################################## // main functionality - protected String doComplete(Symbol p) { + protected String doComplete(Symbol root) { + assert root.isRoot() || root.isPackage(): Debug.show(root); + Symbol p = root.isRoot() ? root : root.moduleClass(); Scope members = new Scope(); importCLRTypes(p, members); p.setInfo(scalac.symtab.Type.compoundType diff --git a/sources/scalac/symtab/classfile/ClassParser.java b/sources/scalac/symtab/classfile/ClassParser.java index f920a5ef79..5284d9cfed 100644 --- a/sources/scalac/symtab/classfile/ClassParser.java +++ b/sources/scalac/symtab/classfile/ClassParser.java @@ -15,6 +15,7 @@ import scala.tools.util.AbstractFile; import scalac.Global; import scalac.symtab.Symbol; import scalac.symtab.SymbolLoader; +import scalac.util.Debug; /** This class implements a SymbolLoader that reads a class file. */ public class ClassParser extends SymbolLoader { @@ -38,8 +39,9 @@ public class ClassParser extends SymbolLoader { // Protected Methods /** Completes the specified symbol by reading the class file. */ - protected String doComplete(Symbol clasz) throws IOException { - ClassfileParser.parse(global, file, clasz); + protected String doComplete(Symbol root) throws IOException { + assert root.isClassType(): Debug.show(root); + ClassfileParser.parse(global, file, root); return "class file '" + file + "'"; } diff --git a/sources/scalac/symtab/classfile/PackageParser.java b/sources/scalac/symtab/classfile/PackageParser.java index 13882f7714..07d196312c 100644 --- a/sources/scalac/symtab/classfile/PackageParser.java +++ b/sources/scalac/symtab/classfile/PackageParser.java @@ -21,6 +21,7 @@ import scalac.symtab.Symbol; import scalac.symtab.SymbolLoader; import scalac.symtab.Type; import scalac.util.Name; +import scalac.util.Debug; /** * This class implements a package member loader. It can be used to @@ -47,7 +48,9 @@ public class PackageParser extends SymbolLoader { // Protected Methods /** Completes the package symbol by loading all its members. */ - protected String doComplete(Symbol peckage) { + protected String doComplete(Symbol root) { + assert root.isRoot() || root.isPackage(): Debug.show(root); + Symbol peckage = root.isRoot() ? root : root.moduleClass(); // collect JVM and source members boolean isRoot = peckage.isRoot(); HashMap sources = new HashMap(); diff --git a/sources/scalac/symtab/classfile/Pickle.java b/sources/scalac/symtab/classfile/Pickle.java index bd2f1f0ef2..6891093e75 100644 --- a/sources/scalac/symtab/classfile/Pickle.java +++ b/sources/scalac/symtab/classfile/Pickle.java @@ -34,7 +34,6 @@ public class Pickle implements Kinds, Modifiers, EntryTags { private HashMap index; private Object[] entries; private int ep; - private final HashMap modules; // maps module-classes to modules /** Write symbol table info for root. * root must be either a module or a class. @@ -43,7 +42,6 @@ public class Pickle implements Kinds, Modifiers, EntryTags { index = new HashMap(); entries = new Object[256]; ep = 0; - modules = new HashMap(); } /** Pickle all symbols descending from `root'. @@ -132,6 +130,7 @@ public class Pickle implements Kinds, Modifiers, EntryTags { break; case CLASS: putType(sym.info()); + if (sym.isModuleClass()) putSymbol(sym.sourceModule()); putType(sym.typeOfThis()); putSymbol(sym.allConstructors()); for (Scope.SymbolIterator it = sym.members().iterator(); @@ -143,12 +142,8 @@ public class Pickle implements Kinds, Modifiers, EntryTags { if (sym.isConstructor() && sym == sym.constructorClass().allConstructors()) putSymbol(sym.constructorClass()); - else if (sym.isModule()) { - Symbol clasz = sym.moduleClass(); + else if (sym.isModule()) putSymbol(sym.moduleClass()); - assert !modules.containsKey(clasz): Debug.show(sym); - modules.put(clasz, sym); - } break; default: throw new ApplicationError(); @@ -358,11 +353,7 @@ public class Pickle implements Kinds, Modifiers, EntryTags { break; case CLASS: writeRef(sym.info()); - if (sym.isModuleClass()) { - Symbol module = (Symbol)modules.remove(sym); - assert module != null: Debug.show(sym); - writeRef(module); - } + if (sym.isModuleClass()) writeRef(sym.sourceModule()); writeRef(sym.typeOfThis()); writeRef(sym.allConstructors()); break; diff --git a/sources/scalac/symtab/classfile/SymblParser.java b/sources/scalac/symtab/classfile/SymblParser.java index 56873215e8..5c948d9176 100644 --- a/sources/scalac/symtab/classfile/SymblParser.java +++ b/sources/scalac/symtab/classfile/SymblParser.java @@ -38,8 +38,8 @@ public class SymblParser extends SymbolLoader { // Protected Methods /** Completes the specified symbol by reading the symbol file. */ - public String doComplete(Symbol clasz) throws IOException { - UnPickle.parse(global, file, clasz); + public String doComplete(Symbol root) throws IOException { + UnPickle.parse(global, file, root); return "symbol file '" + file + "'"; } diff --git a/sources/scalac/symtab/classfile/UnPickle.java b/sources/scalac/symtab/classfile/UnPickle.java index 61c62dc63f..9579458394 100644 --- a/sources/scalac/symtab/classfile/UnPickle.java +++ b/sources/scalac/symtab/classfile/UnPickle.java @@ -38,6 +38,11 @@ public class UnPickle implements Kinds, Modifiers, EntryTags, TypeTags { } } + /** + * The root symbol must be either a module or a non-module + * class. The unpickler initializes it. If it has a linked module + * or class, it will also be initialized. + */ public static void parse(Global global, byte[] data, Symbol root) throws BadSignature { @@ -55,17 +60,16 @@ public class UnPickle implements Kinds, Modifiers, EntryTags, TypeTags { private UnPickle(Global global, byte[] data, Symbol root) { this.global = global; - this.classroot = root.linkedClass(); - this.moduleroot = root.linkedModule(); - assert !classroot.isNone(): Debug.show(root); - assert !moduleroot.isNone(): Debug.show(root); - if (root != moduleroot && moduleroot.isModule()) { + this.classroot = root.isModule() ? root.linkedClass() : root; + this.moduleroot = root.isClassType() ? root.linkedModule() : root; + assert classroot == null || classroot.isClassType(): Debug.show(root); + assert moduleroot == null || moduleroot.isModule(): Debug.show(root); + if (root != moduleroot && moduleroot != null) { moduleroot.moduleClass().setInfo(Type.NoType); } - if (global.debug) - global.log( - "unpickle " + root + " " + classroot + " " + moduleroot + " " + - moduleroot.moduleClass() + " " + moduleroot.moduleClass().primaryConstructor()); + if (global.debug) global.log( + "unpickle " + root + " " + classroot + " " + moduleroot + + (moduleroot != null ? " " + moduleroot.moduleClass() : "")); this.bytes = data; this.bp = 0; index = new int[readNat()]; @@ -84,7 +88,9 @@ public class UnPickle implements Kinds, Modifiers, EntryTags, TypeTags { if (global.debug) global.log("unpickled " + root + ":" + root.rawInfo());//debug if (!root.isInitialized()) throw new BadSignature(this, "it does not define " + root); - if (moduleroot.isModule() && moduleroot.moduleClass().type() == Type.NoType) { + // the isModule test is needed because moduleroot may become + // the case class factory method of classroot + if (moduleroot != null && moduleroot.isModule() && moduleroot.moduleClass().type() == Type.NoType) { moduleroot.setInfo(Type.NoType); } } @@ -259,7 +265,7 @@ public class UnPickle implements Kinds, Modifiers, EntryTags, TypeTags { Symbol modulesym = readSymbolRef(); entries[n] = sym = modulesym.moduleClass(); sym.flags = flags; - } else if (name == classroot.name && owner == classroot.owner()) { + } else if (classroot != null && name == classroot.name && owner == classroot.owner()) { if (global.debug) global.log("overwriting " + classroot); entries[n] = sym = classroot; @@ -275,7 +281,7 @@ public class UnPickle implements Kinds, Modifiers, EntryTags, TypeTags { break; case VALsym: - if (name == moduleroot.name && owner == moduleroot.owner()) { + if (moduleroot != null && name == moduleroot.name && owner == moduleroot.owner()) { if (global.debug) global.log("overwriting " + moduleroot); entries[n] = sym = moduleroot; -- cgit v1.2.3