diff options
author | paltherr <paltherr@epfl.ch> | 2004-03-10 02:29:56 +0000 |
---|---|---|
committer | paltherr <paltherr@epfl.ch> | 2004-03-10 02:29:56 +0000 |
commit | 98bd45db839f0ec470d1fdbd42d5c748e428f4b5 (patch) | |
tree | 7cc9c1111515fa57b4a8917b87b61ae1cdf54282 /sources | |
parent | 70d535ae7b9e689b699a5327cdee747464874420 (diff) | |
download | scala-98bd45db839f0ec470d1fdbd42d5c748e428f4b5.tar.gz scala-98bd45db839f0ec470d1fdbd42d5c748e428f4b5.tar.bz2 scala-98bd45db839f0ec470d1fdbd42d5c748e428f4b5.zip |
- Added new factory methods in class Symbol
- Removed hack from ClassSymbol.dualClass
- Rewrote PackageParser and adapted other parsers and analyzer to use
the new factory method
- Replaced some unsound calls to Symbol.module by calls to Symbol.dualClass
Diffstat (limited to 'sources')
-rw-r--r-- | sources/scala/tools/scalac/typechecker/Analyzer.scala | 27 | ||||
-rw-r--r-- | sources/scalac/symtab/Symbol.java | 80 | ||||
-rw-r--r-- | sources/scalac/symtab/classfile/AttributeParser.java | 2 | ||||
-rw-r--r-- | sources/scalac/symtab/classfile/CLRClassParser.java | 10 | ||||
-rw-r--r-- | sources/scalac/symtab/classfile/CLRPackageParser.java | 13 | ||||
-rw-r--r-- | sources/scalac/symtab/classfile/ClassfileParser.java | 8 | ||||
-rw-r--r-- | sources/scalac/symtab/classfile/PackageParser.java | 218 | ||||
-rw-r--r-- | sources/scalac/symtab/classfile/UnPickle.java | 4 |
8 files changed, 216 insertions, 146 deletions
diff --git a/sources/scala/tools/scalac/typechecker/Analyzer.scala b/sources/scala/tools/scalac/typechecker/Analyzer.scala index e0a76fbf13..37ed261dd3 100644 --- a/sources/scala/tools/scalac/typechecker/Analyzer.scala +++ b/sources/scala/tools/scalac/typechecker/Analyzer.scala @@ -701,8 +701,7 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer( def packageSymbol(pos: int, base: Symbol, name: Name): Symbol = { var p: Symbol = base.members().lookup(name); if (p.kind == NONE) { - p = TermSymbol.newJavaPackageModule(name, base.moduleClass(), null); - base.members().enter(p); + p = base.moduleClass().newPackage(name); } else if (!p.isPackage()) { error(pos, "package and class with same name"); p = Symbol.ERROR; @@ -848,11 +847,27 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer( enterSym(tree, clazz) case Tree$ModuleDef(mods, name, _, _) => - val modul: TermSymbol = TermSymbol.define( - tree.pos, name, owner, mods, context.scope).makeModule(); + var modul: TermSymbol = TermSymbol.lookup( + tree.pos, name, owner, mods | MODUL | FINAL, context.scope); + if (modul == null) { + modul = new TermSymbol(tree.pos, name, owner, mods).makeModule(); + } else { + // The symbol has already been created by some symbol + // loader. It must be a real module. + assert(modul.moduleClass() != modul, Debug.show(modul)); + val clasz = modul.moduleClass(); + clasz.flags = clasz.flags & (~JAVA); + clasz.pos = tree.pos; + val constr = clasz.primaryConstructor(); + constr.flags = constr.flags & (~JAVA); + constr.pos = tree.pos; + } val clazz: Symbol = modul.moduleClass(); - if (!clazz.isInitialized()) - clazz.setInfo(new LazyTreeType(tree)); + if (!clazz.isInitialized()) { + val info = new LazyTreeType(tree); + clazz.setInfo(info); + modul.setInfo(info); + } enterSym(tree, modul) case Tree$ValDef(mods, name, _, _) => diff --git a/sources/scalac/symtab/Symbol.java b/sources/scalac/symtab/Symbol.java index eacfdf0310..4f565e1fc2 100644 --- a/sources/scalac/symtab/Symbol.java +++ b/sources/scalac/symtab/Symbol.java @@ -87,6 +87,36 @@ public abstract class Symbol implements Modifiers, Kinds { // Factories -------------------------------------------------------------- + /** Creates a new module owned by this symbol. */ + public final TermSymbol newModule(int pos, int flags, Name name) { + ClassSymbol clasz = newModuleClass(pos, flags, name.toTypeName()); + return (TermSymbol)clasz.module(); + } + + /** + * Creates a new package owned by this symbol, initializes it with + * an empty scope and adds it to this symbol's members. + */ + public final TermSymbol newPackage(Name name) { + TermSymbol peckage = newPackage(name, null); + members().enterNoHide(peckage); + return peckage; + } + + /** + * Creates a new package owned by this symbol, initializes it with + * the loader and enters it in the scope if it's non-null. + */ + public final TermSymbol newLoadedPackage(Name name, SymbolLoader loader, + Scope scope) + { + assert loader != null: Debug.show(this) + " - " + name; + TermSymbol peckage = newPackage(name, loader); + peckage.moduleClass().setInfo(loader); + if (scope != null) scope.enterNoHide(peckage); + return peckage; + } + /** Creates a new class owned by this symbol. */ public final ClassSymbol newClass(int pos, int flags, Name name) { return newClass(pos, flags, name, 0, NONE); @@ -97,6 +127,36 @@ public abstract class Symbol implements Modifiers, Kinds { return newModuleClass(pos, flags, name, 0, NONE); } + /** + * Creates a new class with a dual module class, both owned by + * this symbol, initializes them with the loader and enters the + * class and the module in the scope if it's non-null. + */ + public final ClassSymbol newLoadedClass(int flags, Name name, + SymbolLoader loader, Scope scope) + { + assert isPackageClass(): Debug.show(this); + assert loader != null: Debug.show(this) + " - " + name; + ClassSymbol clasz = newClass(pos, flags, name, 0, null); + clasz.setInfo(loader); + clasz.allConstructors().setInfo(loader); + clasz.dualClass().setInfo(loader); + clasz.dualClass().module().setInfo(loader); + if (scope != null) scope.enterNoHide(clasz); + if (scope != null) scope.enterNoHide(clasz.dualClass().module()); + return clasz; + } + + /** Creates a new package owned by this symbol. */ + final TermSymbol newPackage(Name name, Type info) { + assert isPackageClass(): Debug.show(this); + TermSymbol peckage = newModule(Position.NOPOS, JAVA | PACKAGE, name); + if (info == null) info = Type.compoundType( + Type.EMPTY_ARRAY, new Scope(), peckage.moduleClass()); + peckage.moduleClass().setInfo(info); + return peckage; + } + /** Creates a new class owned by this symbol. */ final ClassSymbol newClass(int pos, int flags, Name name, int attrs, Symbol dual) @@ -104,7 +164,7 @@ public abstract class Symbol implements Modifiers, Kinds { return new ClassSymbol(pos, name, this, flags, attrs, dual); } - /** Creates a new module-class owned by this symbol. */ + /** Creates a new module class owned by this symbol. */ final ClassSymbol newModuleClass(int pos, int flags, Name name, int attrs, Symbol dual) { @@ -116,7 +176,7 @@ public abstract class Symbol implements Modifiers, Kinds { return clasz; } - /** Creates a new compound class. */ + /** Creates a new compound class owned by this symbol. */ final ClassSymbol newCompoundClass(Type info) { int pos = Position.FIRSTPOS; Name name = Names.COMPOUND_NAME.toTypeName(); @@ -1359,6 +1419,12 @@ public class TermSymbol extends Symbol { public static TermSymbol define( int pos, Name name, Symbol owner, int flags, Scope scope) { + TermSymbol symbol = lookup(pos, name, owner, flags, scope); + if (symbol != null) return symbol; + return new TermSymbol(pos, name, owner, flags); + } + public static TermSymbol lookup( + int pos, Name name, Symbol owner, int flags, Scope scope) { Scope.Entry e = scope.lookupEntry(name); if (e.owner == scope && e.sym.isExternal() && e.sym.kind == VAL) { TermSymbol sym = (TermSymbol) e.sym; @@ -1381,7 +1447,7 @@ public class TermSymbol extends Symbol { sym.update(pos, flags); return sym; } else { - return new TermSymbol(pos, name, owner, flags); + return null; } } @@ -1865,13 +1931,7 @@ public class ClassSymbol extends TypeSymbol { /** Get dual class */ public Symbol dualClass() { - // !!! temporary hack, replace all this by: "return dual;" - if (isModuleClass()) { - Symbol symbol = owner().lookup(name.toTypeName()); - return symbol.isClassType() ? symbol : NONE; - } else { - return module.isNone() ? NONE : module.moduleClass(); - } + return dual; } /** Set module; only used internally from TermSymbol diff --git a/sources/scalac/symtab/classfile/AttributeParser.java b/sources/scalac/symtab/classfile/AttributeParser.java index 183e96785b..9205291748 100644 --- a/sources/scalac/symtab/classfile/AttributeParser.java +++ b/sources/scalac/symtab/classfile/AttributeParser.java @@ -122,7 +122,7 @@ public class AttributeParser implements ClassfileConstants { ((flags & 0x0009) == 0) || ((flags & 0x0001) == 0) || !outer.isModule() || - (outer != sym.module())) + (outer != sym.dualClass().module())) continue; AliasTypeSymbol alias = new AliasTypeSymbol(Position.NOPOS, name.toTypeName(), outer, 0); diff --git a/sources/scalac/symtab/classfile/CLRClassParser.java b/sources/scalac/symtab/classfile/CLRClassParser.java index 026755a73f..7136b1f90f 100644 --- a/sources/scalac/symtab/classfile/CLRClassParser.java +++ b/sources/scalac/symtab/classfile/CLRClassParser.java @@ -70,12 +70,12 @@ public class CLRClassParser extends SymbolLoader { scalac.symtab.Type classType = scalac.symtab.Type.compoundType(baseTypes, members, clazz); clazz.setInfo(classType); - Symbol staticsClass = clazz.module().moduleClass(); + Symbol staticsClass = clazz.dualClass(); if (staticsClass.isModuleClass()) { scalac.symtab.Type staticsInfo = scalac.symtab.Type.compoundType (scalac.symtab.Type.EMPTY_ARRAY, statics, staticsClass); staticsClass.setInfo(staticsInfo); - clazz.module().setInfo(scalac.symtab.Type.typeRef + staticsClass.module().setInfo(scalac.symtab.Type.typeRef (staticsClass.owner().thisType(), staticsClass, scalac.symtab.Type.EMPTY_ARRAY)); } @@ -94,14 +94,12 @@ public class CLRClassParser extends SymbolLoader { Name classname = Name.fromString(n).toTypeName(); Name aliasname = Name.fromString(ntype.Name).toTypeName(); // put the class at the level of its outermost class - ClassSymbol nclazz = new ClassSymbol(classname, clazz.owner(), this); + Symbol nclazz = clazz.owner().newLoadedClass(JAVA, classname, this, null); importer.map(nclazz, ntype); // create an alias in the module of the outer class AliasTypeSymbol alias = - new AliasTypeSymbol(Position.NOPOS, aliasname, clazz.module(), + new AliasTypeSymbol(Position.NOPOS, aliasname, staticsClass, translateAttributes(ntype)); - nclazz.allConstructors().setInfo(this); - nclazz.module().setInfo(this); // alias.setInfo(make.classType(nclazz)); alias.allConstructors() diff --git a/sources/scalac/symtab/classfile/CLRPackageParser.java b/sources/scalac/symtab/classfile/CLRPackageParser.java index 3d626e0f28..310ea7a2fd 100644 --- a/sources/scalac/symtab/classfile/CLRPackageParser.java +++ b/sources/scalac/symtab/classfile/CLRPackageParser.java @@ -260,14 +260,7 @@ public class CLRPackageParser extends SymbolLoader { Name n = Name.fromString(name); if (k < 0) { // it's a class - ClassSymbol clazz = new ClassSymbol(n.toTypeName(), p, completer); - clazz.allConstructors().setInfo(completer); - clazz.module().setInfo(completer); - members.enter(clazz); - Scope.Entry e = members.lookupEntry(clazz.module().name); - if (e != Scope.Entry.NONE) - members.unlink(e); - members.enter(clazz.module()); + Symbol clazz = p.newLoadedClass(JAVA, n.toTypeName(), completer, members); map(clazz, types[i]); } else { importCLRNamespace(name, p, members, pp); @@ -283,9 +276,7 @@ public class CLRPackageParser extends SymbolLoader { Name n = Name.fromString(namespace); if (members.lookup(n) == Symbol.NONE) { //System.out.println("importing namespace " + namespace); - TermSymbol module = TermSymbol.newJavaPackageModule(n, p, pp); - members.enter(module); - members.enter(module.moduleClass()); + p.newLoadedPackage(n, pp, members); } } diff --git a/sources/scalac/symtab/classfile/ClassfileParser.java b/sources/scalac/symtab/classfile/ClassfileParser.java index f966d331a2..3ee3f61b1e 100644 --- a/sources/scalac/symtab/classfile/ClassfileParser.java +++ b/sources/scalac/symtab/classfile/ClassfileParser.java @@ -102,11 +102,11 @@ public class ClassfileParser implements ClassfileConstants { Type classType = Type.compoundType(basetpes, locals, c); c.setInfo(classType); // set type of statics - Symbol staticsClass = c.module().moduleClass(); + Symbol staticsClass = c.dualClass(); if (staticsClass.isModuleClass()) { Type staticsInfo = Type.compoundType(Type.EMPTY_ARRAY, statics, staticsClass); staticsClass.setInfo(staticsInfo); - c.module().setInfo(Type.typeRef(staticsClass.owner().thisType(), + staticsClass.module().setInfo(Type.typeRef(staticsClass.owner().thisType(), staticsClass, Type.EMPTY_ARRAY)); } basetpes[0] = supertpe; @@ -193,7 +193,7 @@ public class ClassfileParser implements ClassfileConstants { mods |= Modifiers.MUTABLE; Symbol owner = c; if ((flags & JAVA_ACC_STATIC) != 0) - owner = c.module().moduleClass(); + owner = c.dualClass(); Symbol s = new TermSymbol(Position.NOPOS, name, owner, mods); s.setInfo(type); attrib.readAttributes(s, type, FIELD_ATTR); @@ -236,7 +236,7 @@ public class ClassfileParser implements ClassfileConstants { } else { Symbol s = new TermSymbol( Position.NOPOS, name, - ((flags & JAVA_ACC_STATIC) != 0) ? c.module().moduleClass() : c, + ((flags & JAVA_ACC_STATIC) != 0) ? c.dualClass() : c, sflags); setParamOwners(type, s); s.setInfo(type); diff --git a/sources/scalac/symtab/classfile/PackageParser.java b/sources/scalac/symtab/classfile/PackageParser.java index 00e4ae1da9..a805f0c1c2 100644 --- a/sources/scalac/symtab/classfile/PackageParser.java +++ b/sources/scalac/symtab/classfile/PackageParser.java @@ -2,135 +2,141 @@ ** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** ** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** ** /_____/\____/\___/\____/____/ ** -** ** -** $Id$ \* */ +// $Id$ + package scalac.symtab.classfile; -import ch.epfl.lamp.util.*; -import scalac.*; -import scalac.symtab.*; -import scalac.util.*; -import java.io.*; +import java.io.IOException; +import java.util.Iterator; import java.util.HashMap; +import java.util.HashSet; + +import ch.epfl.lamp.util.Position; +import scalac.Global; +import scalac.symtab.Scope; +import scalac.symtab.SourceCompleter; +import scalac.symtab.Symbol; +import scalac.symtab.SymbolLoader; +import scalac.symtab.Type; +import scalac.util.AbstractFile; +import scalac.util.Name; +import scalac.util.SourceRepresentation; + +/** + * This class implements a package member loader. It can be used to + * complete package class symbols. + */ public class PackageParser extends SymbolLoader { - /** the class parser - */ - public ClassParser classCompletion; - public SymblParser symblCompletion; // provisional + //######################################################################## + // Private Fields + + /** The JVM class file parser */ + private final ClassParser classCompletion; - protected final CLRPackageParser importer; + /** The CLR package parser */ + private final CLRPackageParser importer; + //######################################################################## + // Public Constructors + + /** Initializes this instance. */ public PackageParser(Global global) { super(global); this.classCompletion = new ClassParser(global); - this.symblCompletion = new SymblParser(global); // provisional - if (global.reporter.verbose) - System.out.println("classpath = " + global.classPath);//debug - importer = (global.target == global.TARGET_MSIL) + this.importer = (global.target == global.TARGET_MSIL) ? CLRPackageParser.create(global) : null; + if (global.reporter.verbose) + global.reporter.inform("classpath = " + global.classPath); } - /** complete package type symbol p by loading all package members - */ - protected String doComplete(Symbol p) { - Scope members = new Scope(); - String dirname = null; - HashMap/*<Symbol, AbstractFile>*/ symFile = new HashMap(); - if (!p.isRoot()) { - dirname = SourceRepresentation.externalizeFileName(p, "/"); - } - String[] base = global.classPath.components(); - for (int i = 0; i < base.length; i++) { - includeMembers( - AbstractFile.open(base[i], dirname), - p, members, symFile); - } - if (global.target == global.TARGET_MSIL) - importer.importCLRTypes(p, members, this); - p.setInfo(Type.compoundType(Type.EMPTY_ARRAY, members, p)); - return dirname == null ? "anonymous package" : "package '"+dirname+"'"; - } + //######################################################################## + // Protected Methods - private boolean isMostRecent(AbstractFile f, Symbol previous, HashMap symFile) { - if (previous == Symbol.NONE || previous.isPackage()) return true; - if (previous.pos != Position.NOPOS) return false; - AbstractFile pf = (AbstractFile) symFile.get(previous); - if (f.getName().endsWith(".scala")) { - if (pf.getName().endsWith(".scala")) return false; - if (!global.separate) return true; - } - if (f.getName().endsWith(".class")) { - if (pf.getName().endsWith(".class")) return false; - if (!global.separate) return false; - } - return f.lastModified() > pf.lastModified(); - } + /** Completes the package symbol by loading all its members. */ + protected String doComplete(Symbol peckage) { + boolean isRoot = peckage.isRoot(); + String dirname = isRoot ? null + : SourceRepresentation.externalizeFileName(peckage, "/"); - /** read directory of a classpath directory and include members - * in package/module scope - */ - protected void includeMembers(AbstractFile dir, Symbol p, Scope locals, - HashMap symFile) { - if (dir == null) - return; - boolean inclClasses = p != global.definitions.ROOT_CLASS; - String[] filenames = null; - try { - if ((filenames = dir.list()) == null) - return; - for (int j = 0; j < filenames.length; j++) { - String fname = filenames[j]; - AbstractFile f = dir.open(fname); - if (inclClasses && fname.endsWith(".class")) { - Name n = Name.fromString(fname.substring(0, fname.length() - 6)) - .toTypeName(); - if (isMostRecent(f, locals.lookup(n), symFile)) { - ClassSymbol clazz = new ClassSymbol(n, p, classCompletion); - // todo: needed? - clazz.allConstructors().setInfo(classCompletion); - clazz.module().setInfo(classCompletion); - // enter class - locals.enter(clazz); - // enter module - Scope.Entry e = locals.lookupEntry(clazz.module().name); - if (e != Scope.Entry.NONE) { - // we already have a package of the same name; delete it - locals.unlink(e); - } - locals.enter(clazz.module()); - symFile.put(clazz, f); + // collect JVM and source members + HashMap sources = new HashMap(); + HashMap classes = new HashMap(); + HashSet packages = new HashSet(); + String[] base = global.classPath.components(); + for (int i = 0; i < base.length; i++) { + AbstractFile dir = AbstractFile.open(base[i], dirname); + if (dir == null) continue; + try { + String[] filenames = dir.list(); + if (filenames == null) continue; + for (int j = 0; j < filenames.length; j++) { + String fname = filenames[j]; + if (fname.endsWith("/") && !fname.equals("META-INF/")) { + String name = fname.substring(0, fname.length() - 1); + packages.add(name); + continue; + } + if (!isRoot && fname.endsWith(".class")) { + String name = fname.substring(0, fname.length() - 6); + if (!classes.containsKey(name)) + classes.put(name, dir.open(fname)); + continue; } - } else if (inclClasses && fname.endsWith(".scala")) { - Name n = Name.fromString(fname.substring(0, fname.length() - 6)) - .toTypeName(); - if (isMostRecent(f, locals.lookup(n), symFile)) { - SourceCompleter completer = new SourceCompleter(global); - ClassSymbol clazz = new ClassSymbol(n, p, completer); - //todo: needed? - clazz.allConstructors().setInfo(completer); - clazz.module().setInfo(completer); - // enter class - locals.enter(clazz); - locals.enter(clazz.module()); - symFile.put(clazz, f); + if (!isRoot && fname.endsWith(".scala")) { + String name = fname.substring(0, fname.length() - 6); + if (!sources.containsKey(name)) + sources.put(name, dir.open(fname)); + continue; } - } else if (fname.endsWith("/") && !fname.equals("META-INF/")) { - Name n = Name.fromString(fname.substring(0, fname.length() - 1)); - if (locals.lookup(n) == Symbol.NONE) { - TermSymbol module = TermSymbol.newJavaPackageModule(n, p, this); - locals.enter(module); - //todo: moduleClass needs to be entered? - locals.enter(module.moduleClass()); - } } + } catch (IOException exception) { + if (global.debug) exception.printStackTrace(); + continue; } - } catch (IOException e) { + } + + // create JVM and source members + Scope members = new Scope(); + for (Iterator i = sources.entrySet().iterator(); i.hasNext(); ) { + HashMap.Entry entry = (HashMap.Entry)i.next(); + String name = (String)entry.getKey(); + AbstractFile sfile = (AbstractFile)entry.getValue(); + AbstractFile cfile = (AbstractFile)classes.remove(name); + if (global.separate && cfile != null) { + if (cfile.lastModified() > sfile.lastModified()) { + classes.put(name, cfile); + continue; + } + } + packages.remove(name); + Name classname = Name.fromString(name).toTypeName(); + SourceCompleter completer = new SourceCompleter(global); + peckage.newLoadedClass(0, classname, completer, members); + } + for (Iterator i = classes.entrySet().iterator(); i.hasNext(); ) { + HashMap.Entry entry = (HashMap.Entry)i.next(); + String name = (String)entry.getKey(); + AbstractFile cfile = (AbstractFile)entry.getValue(); + packages.remove(name); + Name classname = Name.fromString(name).toTypeName(); + peckage.newLoadedClass(JAVA, classname, classCompletion, members); + } + for (Iterator i = packages.iterator(); i.hasNext(); ) { + String name = (String)i.next(); + peckage.newLoadedPackage(Name.fromString(name), this, members); } - } + // collect and create CLR members + if (importer != null) importer.importCLRTypes(peckage, members, this); + + // initialize package + peckage.setInfo(Type.compoundType(Type.EMPTY_ARRAY, members, peckage)); + return dirname == null ? "anonymous package" : "package '"+dirname+"'"; + } + //######################################################################## } diff --git a/sources/scalac/symtab/classfile/UnPickle.java b/sources/scalac/symtab/classfile/UnPickle.java index 7efb9c318f..f87a411f47 100644 --- a/sources/scalac/symtab/classfile/UnPickle.java +++ b/sources/scalac/symtab/classfile/UnPickle.java @@ -39,10 +39,10 @@ public class UnPickle implements Kinds, Modifiers, EntryTags, TypeTags { global = Global.instance; if (root.isConstructor()) { this.classroot = root.constructorClass(); - this.moduleroot = classroot.module(); + this.moduleroot = classroot.dualClass().module(); } else if (root.isType()) { this.classroot = root; - this.moduleroot = classroot.module(); + this.moduleroot = classroot.dualClass().module(); } else { this.moduleroot = root; this.classroot = root.owner().lookup(root.name.toTypeName()); |