From e570d189e04924a7f2b59f4f859f642c43939a21 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 22 Jul 2003 09:27:52 +0000 Subject: *** empty log message *** --- config/list/compiler.lst | 1 + sources/scalac/CompilerCommand.java | 5 + sources/scalac/Global.java | 2 + sources/scalac/Unit.java | 3 +- sources/scalac/symtab/EntryTags.java | 35 +++- sources/scalac/symtab/Modifiers.java | 1 + sources/scalac/symtab/Symbol.java | 34 +++- sources/scalac/symtab/Type.java | 43 +++-- sources/scalac/symtab/classfile/ClassParser.java | 56 ++---- sources/scalac/symtab/classfile/PackageParser.java | 44 +++-- sources/scalac/symtab/classfile/Pickle.java | 178 ++++++++++++----- sources/scalac/symtab/classfile/SymblParser.java | 52 +++++ sources/scalac/symtab/classfile/UnPickle.java | 214 +++++++++++++-------- sources/scalac/transformer/LambdaLift.java | 4 +- sources/scalac/typechecker/Analyzer.java | 74 ++++--- sources/scalac/typechecker/Infer.java | 4 + sources/scalac/typechecker/RefCheck.java | 3 + sources/scalac/util/SourceRepresentation.java | 13 ++ test/files/pos/matthias4.scala | 4 +- test/files/run/Course-2002-07.scala | 2 +- test/pos/matthias4.scala | 4 +- 21 files changed, 539 insertions(+), 237 deletions(-) create mode 100644 sources/scalac/symtab/classfile/SymblParser.java diff --git a/config/list/compiler.lst b/config/list/compiler.lst index a652e2ad8f..216dcc01f0 100644 --- a/config/list/compiler.lst +++ b/config/list/compiler.lst @@ -65,6 +65,7 @@ symtab/classfile/JavaTypeCreator.java symtab/classfile/JavaTypeFactory.java symtab/classfile/PackageParser.java symtab/classfile/Signatures.java +symtab/classfile/SymblParser.java symtab/classfile/Pickle.java symtab/classfile/UnPickle.java diff --git a/sources/scalac/CompilerCommand.java b/sources/scalac/CompilerCommand.java index 535b5e92f1..94f04963e7 100644 --- a/sources/scalac/CompilerCommand.java +++ b/sources/scalac/CompilerCommand.java @@ -40,6 +40,7 @@ public class CompilerCommand extends CommandParser { public final BooleanOptionParser uniqid; public final BooleanOptionParser types; public final BooleanOptionParser prompt; + public final BooleanOptionParser separate; //public final OptimizeOptionParser optimize; public final StringOptionParser classpath; public final StringOptionParser sourcepath; @@ -105,6 +106,10 @@ public class CompilerCommand extends CommandParser { "prompt", "Display a prompt after each error (debugging option)", false), + this.separate = new BooleanOptionParser(this, + "separate", "read symbol files for separate compilation", + false), + //this.optimize = new OptimizeOptionParser(this, // "optimize", "optimize bytecode (-optimize:help for option list)", // null /* todo: uncomment: phases.OPTIMIZE */), diff --git a/sources/scalac/Global.java b/sources/scalac/Global.java index ce18aa3bbe..ad0eed1eb7 100644 --- a/sources/scalac/Global.java +++ b/sources/scalac/Global.java @@ -36,6 +36,7 @@ public class Global { */ public final boolean noimports; public final boolean nopredefs; + public final boolean separate; //public final boolean optimize; public final boolean debug; public final boolean explaintypes; @@ -147,6 +148,7 @@ public class Global { this.start(); // timestamp to compute the total time this.noimports = args.noimports.value; this.nopredefs = args.nopredefs.value; + this.separate = args.separate.value; //this.optimize = args.optimize.optimize; this.debug = args.debug.value; this.uniqid = args.uniqid.value; diff --git a/sources/scalac/Unit.java b/sources/scalac/Unit.java index 354fc1af55..1deb71317b 100644 --- a/sources/scalac/Unit.java +++ b/sources/scalac/Unit.java @@ -13,6 +13,7 @@ import ch.epfl.lamp.util.Position; import scalac.symtab.NameMangler; import scalac.ast.Tree; +import java.util.HashMap; /** A representation for a compilation unit in scala @@ -39,8 +40,8 @@ public class Unit { public Tree[] body; /** the generated symbol data; Symbol -> byte[] - public SymData symdata; */ + public HashMap/**/ symdata = new HashMap(); /** the name mangler */ diff --git a/sources/scalac/symtab/EntryTags.java b/sources/scalac/symtab/EntryTags.java index 1b695a213f..b8ae7c2d7a 100644 --- a/sources/scalac/symtab/EntryTags.java +++ b/sources/scalac/symtab/EntryTags.java @@ -10,6 +10,35 @@ package scalac.symtab; public interface EntryTags { +/*************************************************** + * Symbol table attribute format: + * Symtab = nentries_Nat {Entry} + * Entry = 1 TERMNAME len_Nat NameInfo + * | 2 CONSTRNAME len_Nat NameInfo + * | 3 TYPENAME len_Nat NameInfo + * | 4 NONEsym len_Nat + * | 5 TYPEsym len_Nat SymbolInfo lobound_Ref + * | 6 ALIASsym len_Nat SymbolInfo + * | 7 CLASSsym len_Nat SymbolInfo thistype_Ref constrsym_Ref + * | 8 VALsym len_Nat SymbolInfo [classsym_Ref] + * | 9 EXTsym len_Nat name_Ref [owner_Ref] + * | 10 EXTMODCLASSsym len_Nat name_Ref [owner_Ref] + * | 11 NOtpe len_Nat + * | 12 THIStpe len_Nat sym_Ref + * | 13 SINGLEtpe len_Nat type_Ref sym_Ref + * | 14 TYPEREFtpe len_Nat type_Ref sym_Ref {targ_Ref} + * | 15 COMPOUNDtpe len_Nat classsym_Ref {tpe_Ref} + * | 16 METHODtpe len_Nat tpe_Ref {tpe_Ref} + * | 17 POLYTtpe len_Nat tpe_Ref {sym_Ref} + * | 18 OVERLOADEDtpe len_Nat {sym_Ref} {tpe_Ref} + * | 21 FLAGGEDtype len_Nat flags_Nat tpe_Ref + * SymbolInfo = name_Ref owner_Ref flags_Nat info_Ref + * NameInfo = + * Ref = Nat + * + * len is remaining length after `len'. + */ + int TERMname = 1, CONSTRname = 2, TYPEname = 3, @@ -17,9 +46,9 @@ public interface EntryTags { TYPEsym = 5, ALIASsym = 6, CLASSsym = 7, - MODULEsym = 8, - VALsym = 9, - EXTsym = 10, + VALsym = 8, + EXTsym = 9, + EXTMODCLASSsym = 10, NOtpe = 11, THIStpe = 12, SINGLEtpe = 13, diff --git a/sources/scalac/symtab/Modifiers.java b/sources/scalac/symtab/Modifiers.java index 5948dc2157..9358a2d721 100644 --- a/sources/scalac/symtab/Modifiers.java +++ b/sources/scalac/symtab/Modifiers.java @@ -61,6 +61,7 @@ public interface Modifiers { int SOURCEFLAGS = 0x00000077 | DEF | REPEATED | MODUL | MUTABLE | PACKAGE | PARAM | TRAIT | COVARIANT | CONTRAVARIANT; // these modifiers can be set in source programs. int ACCESSFLAGS = PRIVATE | PROTECTED; int VARIANCES = COVARIANT | CONTRAVARIANT; + int OVERLOADFLAGS = DEFERRED | OVERRIDE | FINAL; public static class Helper { diff --git a/sources/scalac/symtab/Symbol.java b/sources/scalac/symtab/Symbol.java index b8edc68c3b..6867bfb576 100644 --- a/sources/scalac/symtab/Symbol.java +++ b/sources/scalac/symtab/Symbol.java @@ -226,6 +226,7 @@ public abstract class Symbol implements Modifiers, Kinds { } public final boolean isAbstractClass() { + preInitialize(); return (flags & ABSTRACTCLASS) != 0 && this != Global.instance.definitions.ARRAY_CLASS; } @@ -243,6 +244,7 @@ public abstract class Symbol implements Modifiers, Kinds { /** Does this symbol denote something loaded from a Java class? */ public final boolean isJava() { + preInitialize(); return (flags & JAVA) != 0; } @@ -276,11 +278,14 @@ public abstract class Symbol implements Modifiers, Kinds { /** Does this symbol denote a case class? */ public final boolean isCaseClass() { + preInitialize(); return kind == CLASS && (flags & CASE) != 0; } /** Does this symbol denote a uniform (i.e. parameterless) class? */ public final boolean isTrait() { + //preInitialize(); todo: enable, problem is that then we cannot print + // during unpickle return kind == CLASS && (flags & TRAIT) != 0; } @@ -292,6 +297,7 @@ public abstract class Symbol implements Modifiers, Kinds { /** Does this symbol denote an interface? */ public final boolean isInterface() { + preInitialize(); return (flags & INTERFACE) != 0; } @@ -302,11 +308,13 @@ public abstract class Symbol implements Modifiers, Kinds { /** Does this symbol denote a protected symbol? */ public final boolean isProtected() { + preInitialize(); return (flags & PROTECTED) != 0; } /** Does this symbol denote a private symbol? */ public final boolean isPrivate() { + preInitialize(); return (flags & PRIVATE) != 0; } @@ -402,8 +410,9 @@ public abstract class Symbol implements Modifiers, Kinds { /** Get the fully qualified name of this Symbol * (this is always a normal name, never a type name) */ + /** Get the fully qualified name of this Symbol */ public Name fullName() { - return name.toTermName(); + return name.toTermName(); } /** Get the mangled name of this Symbol @@ -541,6 +550,15 @@ public abstract class Symbol implements Modifiers, Kinds { return this; } + /** Make sure symbol is entered + */ + public final void preInitialize() { + //todo: clean up + if (infos.info instanceof ClassParser || + infos.info instanceof SourceCompleter) + infos.info.complete(this); + } + /** Get info; This is: * for a term symbol, its type * for a type variable, its bound @@ -825,11 +843,11 @@ public abstract class Symbol implements Modifiers, Kinds { assert this.name == that.name : Debug.show(this) + " <> " + Debug.show(that); assert this.owner == that.owner : Debug.show(this) + " != " + Debug.show(that); assert (this.flags & that.flags & JAVA) != 0 || - (this.flags & (SOURCEFLAGS | JAVA) & ~ACCESSFLAGS) == - (that.flags & (SOURCEFLAGS | JAVA) & ~ACCESSFLAGS) : Integer.toHexString(this.flags) + "@" + Debug.show(this) + " <> " + Integer.toHexString(that.flags) + "@" + Debug.show(that); + (this.flags & OVERLOADFLAGS) == (that.flags & OVERLOADFLAGS) + : Integer.toHexString(this.flags) + "@" + Debug.show(this) + " <> " + Integer.toHexString(that.flags) + "@" + Debug.show(that); TermSymbol overloaded = new TermSymbol( pos, name, owner, - ((this.flags | that.flags) & (SOURCEFLAGS | JAVA) & ~ACCESSFLAGS) | + ((this.flags | that.flags) & (JAVA | OVERLOADFLAGS)) | (this.flags & that.flags & ACCESSFLAGS)); overloaded.setInfo(new LazyOverloadedType(this, that)); return overloaded; @@ -1095,6 +1113,10 @@ public class TypeSymbol extends Symbol { return type(); } + public Symbol[] typeParams() { + return type().unalias().typeParams(); + } + public Type[] closure() { if (kind == ALIAS) return info().symbol().closure(); int id = currentPhaseId(); @@ -1219,6 +1241,10 @@ public class AbsTypeSymbol extends TypeSymbol { return other; } + public Symbol[] typeParams() { + return Symbol.EMPTY_ARRAY; + } + public Type loBound() { initialize(); return lobound == null ? Global.instance.definitions.ALL_TYPE : lobound; diff --git a/sources/scalac/symtab/Type.java b/sources/scalac/symtab/Type.java index 453e95a323..262d07ccd6 100644 --- a/sources/scalac/symtab/Type.java +++ b/sources/scalac/symtab/Type.java @@ -420,8 +420,11 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { return tparams; case MethodType(Symbol[] vparams, _): return Symbol.EMPTY_ARRAY; + case TypeRef(_, Symbol sym, Type[] args): + if (args.length == 0) return sym.typeParams(); + else return Symbol.EMPTY_ARRAY; default: - throw Debug.abort("illegal case", this); + return Symbol.EMPTY_ARRAY; } } @@ -1148,39 +1151,39 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { /** Substitute symbols `to' for occurrences of symbols `from' in this type. */ public Type subst(Symbol[] from, Symbol[] to) { - assert from.length == to.length - : this + ": " + from.length + " != " + to.length; - if (from.length != 0 && from != to) + if (to.length != 0 && from != to) {//!!! + assert from.length == to.length + : this + ": " + from.length + " != " + to.length; return new SubstSymMap(from, to).apply(this); - else return this; + } else return this; } /** Substitute symbols `to' for occurrences of symbols `from' in these types. */ public static Type[] subst(Type[] these, Symbol[] from, Symbol[] to) { - assert from.length == to.length; - if (these.length != 0 && from.length != 0 && from != to) + if (these.length != 0 && to.length != 0 && from != to) { + assert from.length == to.length; return new SubstSymMap(from, to).map(these); - else return these; + } else return these; } /** Substitute types `to' for occurrences of symbols `from' in this type. */ public Type subst(Symbol[] from, Type[] to) { - assert from.length == to.length - : this + ": " + Debug.show(from) + " <> " + ArrayApply.toString(to); - if (from.length != 0) + if (to.length != 0) { + assert from.length == to.length + : this + ": " + Debug.show(from) + " <> " + ArrayApply.toString(to); return new SubstTypeMap(from, to).apply(this); - else return this; + } else return this; } /** Substitute types `to' for occurrences of symbols `from' in these types. */ public static Type[] subst(Type[] these, Symbol[] from, Type[] to) { - assert from.length == to.length; - if (these.length != 0 && from.length != 0) + if (these.length != 0 && to.length != 0) { + assert from.length == to.length; return new SubstTypeMap(from, to).map(these); - else return these; + } else return these; } /** A map for substitutions of thistypes. @@ -2453,9 +2456,10 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { ^ (pre.hashCode() * 41) ^ (sym.hashCode() * (41*41)); case CompoundType(Type[] parts, Scope members): - return COMPOUNDtpe - ^ (hashCode(parts) * 41) - ^ (members.hashCode() * (41 * 41)); + return symbol().hashCode(); + //return COMPOUNDtpe + // ^ (hashCode(parts) * 41) + // ^ (members.hashCode() * (41 * 41)); case MethodType(Symbol[] vparams, Type result): int h = METHODtpe; for (int i = 0; i < vparams.length; i++) @@ -2532,7 +2536,8 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { case CompoundType(Type[] parts, Scope members): switch (that) { case CompoundType(Type[] parts1, Scope members1): - return parts.equals(parts1) && members.equals(members1); + return this.symbol() == that.symbol(); + //return parts.equals(parts1) && members.equals(members1); default: return false; } case MethodType(Symbol[] vparams, Type result): diff --git a/sources/scalac/symtab/classfile/ClassParser.java b/sources/scalac/symtab/classfile/ClassParser.java index 43c0eaff01..19eb931f3b 100644 --- a/sources/scalac/symtab/classfile/ClassParser.java +++ b/sources/scalac/symtab/classfile/ClassParser.java @@ -19,7 +19,7 @@ public class ClassParser extends Type.LazyType { /** the global compilation environment */ protected Global global; - private boolean completed = false; + protected boolean completed = false; public ClassParser(Global global) { this.global = global; @@ -28,44 +28,29 @@ public class ClassParser extends Type.LazyType { /** complete class symbol c by loading the class */ public void complete(Symbol c) { - if (completed) { - c.setInfo(Type.NoType); - } else { - //System.out.println("loading " + c);//DEBUG - try { - long msec = System.currentTimeMillis(); - String filename = externalizeFileName(c.fullName()) + ".class"; - AbstractFile f = global.classPath.openFile(filename); - if (f == null) - global.error("could not read class " + c); - else { - new ClassfileParser(global, new AbstractFileReader(f), c).parse(); - global.operation("loaded " + f.getPath() + " in " + - (System.currentTimeMillis() - msec) + "ms"); - //for (Definition e = c.locals().elems; e != null; e = e.sibling) - // if (e.def.kind == TYP) + //System.out.println("loading " + c);//DEBUG + try { + long msec = System.currentTimeMillis(); + String filename = SourceRepresentation.externalizeFileName( + c.fullName()) + ".class"; + AbstractFile f = global.classPath.openFile(filename); + if (f == null) + global.error("could not read class " + c); + else { + new ClassfileParser(global, new AbstractFileReader(f), c).parse(); + global.operation("loaded " + f.getPath() + " in " + + (System.currentTimeMillis() - msec) + "ms"); + //for (Definition e = c.locals().elems; e != null; e = e.sibling) + // if (e.def.kind == TYP) // e.def.complete(); - } - } catch (IOException e) { - e.printStackTrace(); - global.error("i/o error while loading " + c); - c.setInfo(Type.ErrorType); } + } catch (IOException e) { + e.printStackTrace(); + global.error("i/o error while loading " + c); + c.setInfo(Type.ErrorType); } } - /** return external representation of file name s, - * converting '.' to File.separatorChar - */ - public String externalizeFileName(Name n) { - if ((n == null) || (n.length() == 0)) - return "."; - byte[] ascii = n.toAscii(); - String s = SourceRepresentation.ascii2string( - ascii, 0, ascii.length); - return s.replace('.', File.separatorChar); - } - public Type.LazyType staticsParser(Symbol clazz) { return new StaticsParser(clazz); } @@ -100,7 +85,8 @@ public class ClassParser extends Type.LazyType { public void complete(Symbol c) { try { long msec = System.currentTimeMillis(); - String filename = externalizeFileName(alias.fullName()) + ".class"; + String filename = SourceRepresentation.externalizeFileName( + alias.fullName()) + ".class"; AbstractFile f = global.classPath.openFile(filename); if (f == null) global.error("could not read class " + c); diff --git a/sources/scalac/symtab/classfile/PackageParser.java b/sources/scalac/symtab/classfile/PackageParser.java index 9f14045723..80191c79ba 100644 --- a/sources/scalac/symtab/classfile/PackageParser.java +++ b/sources/scalac/symtab/classfile/PackageParser.java @@ -22,10 +22,14 @@ public class PackageParser extends Type.LazyType { /** the class parser */ public ClassParser classCompletion; + public SymblParser symblCompletion; // provisional public PackageParser(Global global) { this.global = global; this.classCompletion = new ClassParser(global); + this.symblCompletion = new SymblParser(global); // provisional + if (global.reporter.verbose) + System.out.println("classpath = " + global.classPath);//debug } /** complete package type symbol p by loading all package members @@ -38,7 +42,7 @@ public class PackageParser extends Type.LazyType { if (name.length() == 0) { // includeMembers(AbstractFile.open(null, "."), p, members, false); } else { - dirname = externalizeFileName(name); + dirname = SourceRepresentation.externalizeFileName(name); assert !dirname.startsWith("com") : p;//debug if (!dirname.endsWith("/")) dirname += "/"; @@ -95,11 +99,30 @@ public class PackageParser extends Type.LazyType { if (locals.lookup(n) == Symbol.NONE) { TermSymbol module = TermSymbol.newJavaPackageModule(n, p, this); locals.enter(module); + locals.enter(module.moduleClass()); } - } else if (fname.endsWith(".scala")) { + } else if (inclClasses && global.separate && fname.endsWith(".symbl")) { + //todo: compare dates between symbl and scala. Name n = Name.fromString(fname.substring(0, fname.length() - 6)) .toTypeName(); - //if (locals.lookup(n) == Symbol.NONE) { + Symbol sym = locals.lookup(n); + if (sym == Symbol.NONE || + sym.rawInfoAt(Symbol.FIRST_ID) instanceof ClassParser && + !(sym.rawInfoAt(Symbol.FIRST_ID) instanceof SymblParser)) { + ClassSymbol clazz = new ClassSymbol(n, p, symblCompletion); + clazz.constructor().setInfo(symblCompletion); + clazz.module().setInfo(symblCompletion); + locals.enter(clazz); + locals.enter(clazz.constructor()); + locals.enter(clazz.module()); + } + } else if (inclClasses && fname.endsWith(".scala")) { + Name n = Name.fromString(fname.substring(0, fname.length() - 6)) + .toTypeName(); + Symbol sym = locals.lookup(n); + if (sym == Symbol.NONE || + sym.rawInfoAt(Symbol.FIRST_ID) instanceof ClassParser && + !(sym.rawInfoAt(Symbol.FIRST_ID) instanceof SymblParser)) { SourceCompleter completer = new SourceCompleter(global, dir.getPath() + File.separatorChar + fname); ClassSymbol clazz = new ClassSymbol(n, p, completer); @@ -109,23 +132,10 @@ public class PackageParser extends Type.LazyType { locals.enter(clazz); locals.enter(clazz.constructor()); locals.enter(clazz.module()); - //} + } } } } catch (IOException e) { } } - - /** return external representation of file name s, - * converting '.' to File.separatorChar - */ - - public String externalizeFileName(Name n) { - if ((n == null) || (n.length() == 0)) - return "."; - byte[] ascii = n.toAscii(); - String s = SourceRepresentation.ascii2string( - ascii, 0, ascii.length); - return s.replace('.', File.separatorChar); - } } diff --git a/sources/scalac/symtab/classfile/Pickle.java b/sources/scalac/symtab/classfile/Pickle.java index bbd0ff7526..83d9851405 100644 --- a/sources/scalac/symtab/classfile/Pickle.java +++ b/sources/scalac/symtab/classfile/Pickle.java @@ -9,6 +9,7 @@ package scalac.symtab.classfile; import java.util.HashMap; +import java.io.*; import scalac.Global; import scalac.ApplicationError; import scalac.util.*; @@ -21,32 +22,85 @@ public class Pickle implements Kinds, Modifiers, EntryTags { final static boolean debug = false; /*************************************************** - * Symbol table attribute format: see UnPickle.java + * Symbol table attribute format: see EntryTags.java */ public byte[] bytes; private int bp; - private Symbol root; + private Name rootname; + private Symbol rootowner; private HashMap index; private Object[] entries; private int ep; - private Symbol root1; - private Symbol root2; /** Write symbol table info for root. * root must be either a module or a class. */ - Pickle(Symbol root) { - this.root = root; - this.root1 = root.moduleClass(); - this.root2 = root1.constructor(); + public Pickle() { index = new HashMap(); entries = new Object[256]; ep = 0; - putSymbol(root); + } + + /** Pickle all symbols descending from `root'. + */ + public void add(Symbol root) { + if (index.get(root) == null) { + this.rootname = root.name.toTermName(); + this.rootowner = root.owner(); + putSymbol(root); + } + } + + /** Finalize pickler with given fullname. + */ + public void finalize(Name fullname) { bytes = new byte[4096]; bp = 0; writeAttr(); + this.index = null; + this.entries = null; + writeFile(fullname); + } + + /** Create output file with given extension for given class. + */ + public File outputFile(Name fullname, String extension) { + if (Global.instance.outpath != null) { + return new File( + Global.instance.outpath, + SourceRepresentation.externalizeFileName(fullname) + extension); + } else { + String s = fullname.toString(); + int i = s.length(); + while (i > 0 && s.charAt(i - 1) != '.') i--; + return new File(s.substring(i) + extension); + } + } + + private void createPath(File f) { + try { + f.createNewFile(); + } catch (IOException ex) { + f.getParentFile().mkdirs(); + try { + f.createNewFile(); + } catch (IOException ex1) { + } + } + } + + private void writeFile(Name fullname) { + File outfile = outputFile(fullname, ".symbl"); + try { + createPath(outfile); + FileOutputStream out = new FileOutputStream(outfile); + out.write(bytes, 0, bp); + out.close(); + Global.instance.operation("wrote " + outfile); + } catch (IOException ex) { + System.err.println("error writing " + outfile); + } } /* ************************************************** @@ -57,7 +111,8 @@ public class Pickle implements Kinds, Modifiers, EntryTags { */ private boolean isLocal(Symbol sym) { return - sym == root || sym == root1 || sym == root2 || + sym.name.toTermName() == rootname && + sym.owner() == rootowner || (sym.kind != NONE && isLocal(sym.owner())); } @@ -88,37 +143,45 @@ public class Pickle implements Kinds, Modifiers, EntryTags { * another symbol. */ private void putSymbol(Symbol sym) { - if (putEntry(sym)) { - if (isLocal(sym)) { - putEntry(sym.name); - putSymbol(sym.owner()); - putType(sym.info()); - switch (sym.kind) { - case TYPE: - putType(sym.loBound()); - break; - case ALIAS: - break; - case CLASS: - putType(sym.typeOfThis()); - putSymbol(sym.constructor()); - for (Scope.SymbolIterator it = sym.members().iterator(); - it.hasNext();) - putSymbol(it.next()); - break; - case VAL: - if (sym.isPrimaryConstructor()) - putSymbol(sym.primaryConstructorClass()); - else if (sym.isModule()) - putSymbol(sym.moduleClass()); - break; - default: - throw new ApplicationError(); - } - } else if (sym.kind != NONE) { - putEntry(sym.name); - if (sym.owner() != Global.instance.definitions.ROOT_CLASS) + switch (sym.info()) { + case OverloadedType(Symbol[] alts, _): + for (int i = 0; i < alts.length; i++) + putSymbol(alts[i]); + break; + default: + if (putEntry(sym)) { + //System.out.println("put sym " + sym);//DEBUG + if (isLocal(sym)) { + putEntry(sym.name); putSymbol(sym.owner()); + putType(sym.info()); + switch (sym.kind) { + case TYPE: + putType(sym.loBound()); + break; + case ALIAS: + break; + case CLASS: + putType(sym.typeOfThis()); + putSymbol(sym.constructor()); + for (Scope.SymbolIterator it = sym.members().iterator(); + it.hasNext();) + putSymbol(it.next()); + break; + case VAL: + if (sym.isPrimaryConstructor()) + putSymbol(sym.primaryConstructorClass()); + else if (sym.isModule()) + putSymbol(sym.moduleClass()); + break; + default: + throw new ApplicationError(); + } + } else if (sym.kind != NONE) { + putEntry(sym.name); + if (sym.owner() != Global.instance.definitions.ROOT_CLASS) + putSymbol(sym.owner()); + } } } } @@ -148,13 +211,13 @@ public class Pickle implements Kinds, Modifiers, EntryTags { putTypes(args); break; case CompoundType(Type[] parents, Scope members): + putSymbol(tp.symbol()); putTypes(parents); - putSymbols(members.elements()); break; case MethodType(Symbol[] vparams, Type result): putType(result); for (int i = 0; i < vparams.length; i++) { - Type ptype= vparams[i].type(); + Type ptype = vparams[i].type(); putType(ptype); int pflags = vparams[i].flags; if ((pflags & (COVARIANT | CONTRAVARIANT | REPEATED | DEF)) != 0) @@ -166,8 +229,7 @@ public class Pickle implements Kinds, Modifiers, EntryTags { putSymbols(tparams); break; case OverloadedType(Symbol[] alts, Type[] alttypes): - putSymbols(alts); - putTypes(alttypes); + assert false : tp; break; default: throw new ApplicationError(); @@ -259,7 +321,22 @@ public class Pickle implements Kinds, Modifiers, EntryTags { */ private void writeSymbol(Symbol sym) { if (isLocal(sym)) { - writeByte(sym.kind); + switch (sym.kind) { + case TYPE: + writeByte(TYPEsym); + break; + case ALIAS: + writeByte(ALIASsym); + break; + case CLASS: + writeByte(CLASSsym); + break; + case VAL: + writeByte(VALsym); + break; + default: + throw new ApplicationError(); + } writeByte(0); // space for length writeRef(sym.name); writeRef(sym.owner()); @@ -281,14 +358,13 @@ public class Pickle implements Kinds, Modifiers, EntryTags { else if (sym.isModule()) writeRef(sym.moduleClass()); break; - default: - throw new ApplicationError(); } } else if (sym.kind == NONE) { - writeByte(NONE); + writeByte(NONEsym); writeByte(0); // space for length } else { - writeByte(EXTsym); + writeByte(((sym.flags & (MODUL | PACKAGE)) == MODUL) + ? EXTMODCLASSsym : EXTsym); writeByte(0); // space for length writeRef(sym.name); if (sym.owner() != Global.instance.definitions.ROOT_CLASS) @@ -329,8 +405,8 @@ public class Pickle implements Kinds, Modifiers, EntryTags { case CompoundType(Type[] parents, Scope members): writeByte(COMPOUNDtpe); writeByte(0); // space for length + writeRef(tp.symbol()); writeRefs(parents); - writeRefs(members.elements()); break; case MethodType(Symbol[] vparams, Type result): @@ -388,9 +464,9 @@ public class Pickle implements Kinds, Modifiers, EntryTags { for (int i = 0; i < ep; i++) { if (debug) System.out.print(i + "," + bp + ": "); writeEntry(entries[i]); + if (debug) System.out.print("(" + entries[i] + ")"); if (debug) System.out.println(); } - resizeTo(bp); } private static int encodeFlags(int flags) { diff --git a/sources/scalac/symtab/classfile/SymblParser.java b/sources/scalac/symtab/classfile/SymblParser.java new file mode 100644 index 0000000000..1c2ef25618 --- /dev/null +++ b/sources/scalac/symtab/classfile/SymblParser.java @@ -0,0 +1,52 @@ +/* ____ ____ ____ ____ ______ *\ +** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** +** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** +** /_____/\____/\___/\____/____/ ** +** ** +** $Id$ +\* */ + +package scalac.symtab.classfile; + +import scalac.*; +import scalac.symtab.*; +import scalac.util.*; +import java.io.*; + + +public class SymblParser extends ClassParser { + + /** the global compilation environment + */ + + public SymblParser(Global global) { + super(global); + } + /** complete class symbol c by loading the class + */ + public void complete(Symbol c) { + //System.out.println("loading " + c);//DEBUG + try { + long msec = System.currentTimeMillis(); + String filename = SourceRepresentation.externalizeFileName( + c.fullName()) + ".symbl"; + AbstractFile f = global.classPath.openFile(filename); + if (f == null) + global.error("could not read class " + c); + else { + byte[] data = f.read(); + new UnPickle(c, data, Name.fromString(filename)); + global.operation("loaded " + f.getPath() + " in " + + (System.currentTimeMillis() - msec) + "ms"); + //for (Definition e = c.locals().elems; e != null; e = e.sibling) + // if (e.def.kind == TYP) + // e.def.complete(); + } + } catch (IOException e) { + e.printStackTrace(); + global.error("i/o error while loading " + c); + c.setInfo(Type.ErrorType); + } + } +} + diff --git a/sources/scalac/symtab/classfile/UnPickle.java b/sources/scalac/symtab/classfile/UnPickle.java index 7c46a2d6e4..a0cc7eda31 100644 --- a/sources/scalac/symtab/classfile/UnPickle.java +++ b/sources/scalac/symtab/classfile/UnPickle.java @@ -19,34 +19,9 @@ import Type.*; public class UnPickle implements Kinds, Modifiers, EntryTags { /*************************************************** - * Symbol table attribute format: - * Symtab = nentries_Nat {Entry} - * Entry = TERMNAME len_Nat NameInfo - * | CONSTRNAME len_Nat NameInfo - * | TYPENAME len_Nat NameInfo - * | NONEsym len_Nat - * | TYPEsym len_Nat SymbolInfo lobound_Ref - * | ALIASsym len_Nat SymbolInfo - * | CLASSsym len_Nat SymbolInfo thistype_Ref constrsym_Ref - * | MODULEsym len_Nat SymbolInfo classsym_Ref - * | VALsym len_Nat SymbolInfo [classsym_Ref] - * | EXTsym len_Nat name_Ref [owner_Ref] - * | NOtpe len_Nat - * | THIStpe len_Nat sym_Ref - * | SINGLEtpe len_Nat type_Ref sym_Ref - * | TYPEREFtpe len_Nat type_Ref sym_Ref {targ_Ref} - * | COMPOUNDtpe len_Nat sym_Ref {tpe_Ref} {sym_Ref} - * | METHODtpe len_Nat tpe_Ref {tpe_Ref} - * | POLYTtpe len_Nat tpe_Ref {sym_Ref} - * | OVERLOADEDtpe len_Nat {sym_Ref} {tpe_Ref} - * | FLAGGEDtype len_Nat flags_Nat tpe_Ref - * SymbolInfo = name_Ref owner_Ref flags_Nat info_Ref - * NameInfo = - * Ref = Nat - * - * len is remaining length after `len'. + * Symbol table attribute format: see EntryTags.java */ - static final boolean debug = false; + static final boolean debug = true; Symbol classroot; Symbol moduleroot; @@ -56,12 +31,25 @@ public class UnPickle implements Kinds, Modifiers, EntryTags { int[] index; Object[] entries; int paramFlags; + Global global; UnPickle(Symbol root, byte[] data, Name sourceName) { + global = Global.instance; assert root.rawInfoAt(Symbol.FIRST_ID) instanceof LazyType; - //System.out.println("unpickle " + root);//DEBUG - this.classroot = root; - this.moduleroot = classroot.module(); + if (root.isConstructor()) { + this.classroot = root.primaryConstructorClass(); + this.moduleroot = classroot.module(); + } else if (root.isType()) { + this.classroot = root; + this.moduleroot = classroot.module(); + } else { + this.moduleroot = root; + this.classroot = root.owner().lookup(root.name.toTypeName()); + } + if (global.debug) + global.log( + "unpickle " + root + " " + classroot + " " + moduleroot + " " + + moduleroot.moduleClass() + moduleroot.moduleClass().constructor()); this.bytes = data; this.bp = 0; this.sourceName = sourceName; @@ -72,21 +60,28 @@ public class UnPickle implements Kinds, Modifiers, EntryTags { bp = readNat() + bp; } entries = new Object[index.length]; - if (debug) { + if (global.debug) { + global.log("length: " + index.length); for (int i = 0; i < index.length; i++) { System.out.print(i + "," + index[i] + ": "); bp = index[i]; - System.out.print(readByte() + " "); + int tag = readByte(); + System.out.print(tag + " "); int len = readNat(); System.out.print(len + " "); - for (int j = 0; j < len; j++) - System.out.print(readByte() + " "); + if (tag == TERMname || tag == TYPEname || tag == CONSTRname) + System.out.print( + SourceRepresentation.ascii2string(bytes, bp, len)); + else + for (int j = 0; j < len; j++) + System.out.print(readByte() + " "); System.out.println(); } } for (int i = 0; i < index.length; i++) { if (isSymbolEntry(i)) getSymbol(i); } + if (global.debug) global.log("unpickled " + root);//debug if (root.rawInfoAt(Symbol.FIRST_ID) instanceof LazyType) throw new BadSignature(this, "it does not define " + root); } @@ -99,14 +94,11 @@ public class UnPickle implements Kinds, Modifiers, EntryTags { else return Type.PolyType(tparams, restpe1); case MethodType(Symbol[] params, Type restpe): Symbol[] params1 = params; - for (int i = 0; i < params.length; i++) { - if (params[i].owner() != owner) { - if (params1 == params && params[i].owner() != Symbol.NONE) { - params1 = new Symbol[params.length]; - System.arraycopy(params, 0, params1, 0, i); - } - params1[i].setOwner(owner); - } + if (params.length > 0 && + params[0].owner() != owner && params[0].owner() != Symbol.NONE) { + params1 = new Symbol[params.length]; + for (int i = 0; i < params.length; i++) + params1[i] = params[i].cloneSymbol().setOwner(owner); } Type restpe1 = setOwner(restpe, owner); if (params1 == params && restpe1 == restpe) return tp; @@ -162,6 +154,30 @@ public class UnPickle implements Kinds, Modifiers, EntryTags { return getName(readNat()); } + String decode(Name name) { + if (name.isTypeName()) return "type " + NameTransformer.decode(name); + else if (name.isConstrName()) return "constructor " + NameTransformer.decode(name); + else return "value " + NameTransformer.decode(name); + } + + Symbol extRef(Symbol owner, Name name, boolean modclass) { + if (name.length() == 0 && owner == Symbol.NONE) { + return Global.instance.definitions.ROOT_CLASS; + } else if (modclass) { + assert name.isTypeName() : name; + Symbol module = extRef(owner, name.toTermName(), false); + switch (module.type()) { + case OverloadedType(Symbol[] alts, _): + for (int i = 0; i < alts.length; i++) + if (alts[i].isModule()) module = alts[i]; + } + assert module.isModule(); + return module.moduleClass(); + } else { + return owner.info().lookup(name); + } + } + Symbol getSymbol(int n) { if (entries[n] == null) { int savedBp = bp; @@ -175,6 +191,7 @@ public class UnPickle implements Kinds, Modifiers, EntryTags { entries[n] = sym = Symbol.NONE; break; case EXTsym: + case EXTMODCLASSsym: Name name = readNameRef(); if (bp == end) { owner = Global.instance.definitions.ROOT_CLASS; @@ -182,20 +199,20 @@ public class UnPickle implements Kinds, Modifiers, EntryTags { assert bp < end; owner = readSymbolRef(); } - if (name.length() == 0 && owner == Symbol.NONE) { - entries[n] = sym = Global.instance.definitions.ROOT_CLASS; - } else { - entries[n] = sym = owner.info().lookupNonPrivate(name); - } + entries[n] = sym = extRef(owner, name, tag == EXTMODCLASSsym); if (sym.kind == NONE) { + if (global.debug) + global.log(owner.info().members().toString());//debug throw new BadSignature(this, - "reference " + name + " of " + owner + + "reference " + decode(name) + " of " + owner + " refers to nonexisting symbol."); } break; default: assert isSymbolEntry(n) : n; Name name = readNameRef(); + if (global.debug) + global.log("reading " + name + " at " + n);//debug owner = readSymbolRef(); if (entries[n] == null) { int flags = readNat(); @@ -217,54 +234,84 @@ public class UnPickle implements Kinds, Modifiers, EntryTags { case CLASSsym: entries[n] = sym = new ClassSymbol( Position.NOPOS, name, owner, flags); - if (name == classroot.name && owner == classroot.owner()) { - sym.copyTo(classroot); - entries[n] = sym = classroot; + Symbol clr = ((flags & MODUL) == 0) ? classroot + : moduleroot.moduleClass(); + if (name == clr.name && owner == clr.owner()) { + if (global.debug) global.log("overwriting " + clr); + sym.copyTo(clr); + entries[n] = sym = clr; } sym.setInfo(getType(inforef)); sym.setTypeOfThis(readTypeRef()); Symbol constructor = readSymbolRef(); //will install itself! break; - case MODULEsym: - entries[n] = sym = TermSymbol.newModule( - Position.NOPOS, name, owner, flags, (ClassSymbol) readSymbolRef()); - if (name == moduleroot.name && owner == moduleroot.owner()) { - sym.copyTo(moduleroot); - entries[n] = sym = moduleroot; - } - sym.setInfo(getType(inforef)); - break; - case VALsym: + Symbol cf = Symbol.NONE; if (bp < end) { - assert name.isConstrName(); - Symbol clazz = readSymbolRef(); - entries[n] = sym = clazz.constructor(); - TermSymbol.newConstructor(clazz, flags).copyTo(sym); + ClassSymbol clazz = (ClassSymbol) readSymbolRef(); + if (name.isConstrName()) { + entries[n] = sym = clazz.constructor(); + if (global.debug) + global.log("overwriting " + sym);//debug + TermSymbol.newConstructor(clazz, flags).copyTo(sym); + if (clazz.isCaseClass()) { + cf = new TermSymbol( + Position.NOPOS, name.toTermName(), owner, flags | CASE); + if (name.toTypeName() == classroot.name && owner == moduleroot.owner()) { + if (global.debug) + global.log("overwriting " + moduleroot);//debug + cf.copyTo(moduleroot); + cf = moduleroot; + } else { + owner.info().members().enterOrOverload(cf); + } + } + } else { + assert (flags & MODUL) != 0 : name; + entries[n] = sym = TermSymbol.newModule( + Position.NOPOS, name, owner, flags, clazz); + if (name == moduleroot.name && owner == moduleroot.owner()) { + if (global.debug) + global.log("overwriting " + moduleroot);//debug + sym.copyTo(moduleroot); + entries[n] = sym = moduleroot; + } + } } else { entries[n] = sym = new TermSymbol( Position.NOPOS, name, owner, flags); } - sym.setInfo(setOwner(getType(inforef), sym)); + Type tp = getType(inforef); + sym.setInfo(setOwner(tp, sym)); + if (cf.kind != NONE) cf.setInfo(setOwner(tp, cf)); break; default: throw new BadSignature(this); } - if (owner.kind == CLASS && - !(sym == classroot || - sym.kind == CLASS && (sym.flags & MODUL) != 0 || - (sym.isPrimaryConstructor() && - (sym.primaryConstructorClass().flags & MODUL) != 0))) - owner.members().enter(sym); + if (owner.kind == CLASS && !noEnter(sym)) { + if (global.debug) + global.log("entering " + sym + ":" + sym.type() + " in " + owner);//debug + owner.info().members().enterOrOverload(sym); + } } } bp = savedBp; } return (Symbol) entries[n]; } + //where + private boolean noEnter(Symbol sym) { + return + sym == classroot || + sym == moduleroot || + sym.isModuleClass() || + sym.isPrimaryConstructor() && noEnter(sym.primaryConstructorClass()); + } + + Symbol readSymbolRef() { return getSymbol(readNat()); @@ -279,6 +326,7 @@ public class UnPickle implements Kinds, Modifiers, EntryTags { return new Symbol[nread]; } else { assert bp < end; + int bp0 = bp; int ref = readNat(); if (isSymbolEntry(ref)) { Symbol s = getSymbol(ref); @@ -286,6 +334,7 @@ public class UnPickle implements Kinds, Modifiers, EntryTags { ss[nread] = s; return ss; } else { + bp = bp0; return new Symbol[nread]; } } @@ -303,7 +352,9 @@ public class UnPickle implements Kinds, Modifiers, EntryTags { tpe = Type.NoType; break; case THIStpe: - tpe = Type.ThisType(readSymbolRef()); + Symbol sym = readSymbolRef(); + tpe = (sym.kind == NONE) ? Type.localThisType + : Type.ThisType(sym); break; case SINGLEtpe: tpe = Type.singleType(readTypeRef(), readSymbolRef()); @@ -315,8 +366,7 @@ public class UnPickle implements Kinds, Modifiers, EntryTags { case COMPOUNDtpe: Symbol clazz = readSymbolRef(); Type[] parents = readTypeRefs(end); - Scope members = new Scope(readSymbolRefs(end)); - tpe = Type.compoundType(parents, members, clazz); + tpe = Type.compoundType(parents, new Scope(), clazz); break; case METHODtpe: Type restype = readTypeRef(); @@ -339,15 +389,21 @@ public class UnPickle implements Kinds, Modifiers, EntryTags { tpe = Type.PolyType(readSymbolRefs(end), restype); break; case OVERLOADEDtpe: + int bp0 = bp; Symbol[] alts = readSymbolRefs(end); + int bp1 = bp; Type[] alttypes = readTypeRefs(end); + assert alts.length == alttypes.length + : alts.length + "!=" + alttypes.length + + " at " + bp0 + "/" + bp1 + "/" + bp; for (int i = 0; i < alts.length; i++) alttypes[i] = setOwner(alttypes[i], alts[i]); tpe = Type.OverloadedType(alts, alttypes); break; case FLAGGEDtpe: - paramFlags = getFlags(readNat()); - return readTypeRef(); + readNat(); // skip flags + tpe = readTypeRef(); + break; default: throw new BadSignature(this); } @@ -369,7 +425,8 @@ public class UnPickle implements Kinds, Modifiers, EntryTags { if (bp == end) { return new Type[nread]; } else { - assert bp < end; + assert bp < end : bp + ">" + end; + int bp0 = bp; int ref = readNat(); if (isTypeEntry(ref)) { Type t = getType(ref); @@ -377,6 +434,7 @@ public class UnPickle implements Kinds, Modifiers, EntryTags { ts[nread] = t; return ts; } else { + bp = bp0; return new Type[nread]; } } diff --git a/sources/scalac/transformer/LambdaLift.java b/sources/scalac/transformer/LambdaLift.java index 2b8a05135d..c18c466f9a 100644 --- a/sources/scalac/transformer/LambdaLift.java +++ b/sources/scalac/transformer/LambdaLift.java @@ -380,8 +380,8 @@ public class LambdaLift extends OwnerTransformer Tree rhs1 = transform(rhs, sym); if ((sym.flags & CAPTURED) != 0) { assert sym.isLocal(); - Type unboxedType = sym.typeAt(descr.nextPhase); - Type boxedType = descr.refType(unboxedType); + Type boxedType = sym.typeAt(descr.nextPhase); + Type unboxedType = boxedType.typeArgs()[0]; tpe1 = gen.mkType(tpe.pos, boxedType); rhs1 = gen.New( rhs.pos, diff --git a/sources/scalac/typechecker/Analyzer.java b/sources/scalac/typechecker/Analyzer.java index 8c427c3c84..bcb7dcb7b7 100644 --- a/sources/scalac/typechecker/Analyzer.java +++ b/sources/scalac/typechecker/Analyzer.java @@ -21,9 +21,9 @@ import scalac.util.*; import scalac.ast.*; import scalac.ast.printer.*; import scalac.symtab.*; -import scalac.symtab.classfile.UnPickle; +import scalac.symtab.classfile.*; import Tree.*; -import java.util.HashMap; +import java.util.*; /** The main attribution phase. */ @@ -111,16 +111,47 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { this.context = (Context)descr.contexts.remove(unit); assert this.context != null : "could not find context for " + unit; unit.body = transformStatSeq(unit.body, Symbol.NONE); - /** todo: check what this is for - if (global.target == global.TARGET_JAVA && unit.errors == 0) { - unit.symdata = new SymData(unit); + if (global.target != global.TARGET_INT && global.reporter.errors() == 0) { + genSymData(unit.symdata, unit.body); + finalizeSymData(unit.symdata); } - */ this.unit = null; this.context = null; global.operation("checked " + unit); } + public void genSymData(HashMap/**/ symdata, Tree[] stats) { + for (int i = 0; i < stats.length; i++) { + switch (stats[i]) { + case ClassDef(_, _, _, _, _, _): + case ModuleDef(_, _, _, _): + case ValDef(_, _, _, _): + Symbol sym = stats[i].symbol(); + Name fullname = sym.kind == VAL + ? Name.fromString(sym.owner().fullName() + "." + sym.name) + : sym.fullName(); + Pickle pickle = (Pickle) unit.symdata.get(fullname); + if (pickle == null) { + pickle = new Pickle(); + unit.symdata.put(fullname, pickle); + } + pickle.add(sym); + break; + case PackageDef(Tree packaged, Tree.Template templ): + genSymData(symdata, templ.body); + } + } + } + + public void finalizeSymData(HashMap/**/ symdata) { + for (Iterator it = symdata.entrySet().iterator(); it.hasNext();) { + Map.Entry entry = (Map.Entry) it.next(); + Name fullname = (Name) entry.getKey(); + Pickle pickle = (Pickle) entry.getValue(); + pickle.finalize(fullname); + } + } + /** Mode constants */ static final int NOmode = 0x000; @@ -612,14 +643,6 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { Symbol constr = tree.symbol().constructor(); Type constrtype = constr.type().instanceType(); constrtype = constrtype.cloneType(constr, sym); - /* todo: remove - switch (tree) { - case ClassDef(_, _, _, ValDef[][] vparams, _, _): - if (vparams.length == 0) { - constrtype = removeMethod(constrtype); - } - } - */ sym.setInfo(constrtype); } /* todo: remove @@ -924,6 +947,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { tparamSyms, vparamSyms, Type.TypeRef(sym.owner().thisType(), sym, Symbol.type(tparamSyms))); + //System.out.println("set info " + sym.constructor() + " to " + constrtype + " was " + sym.constructor().rawInfo());//DEBUG sym.constructor().setInfo(constrtype); // necessary so that we can access tparams sym.constructor().flags |= INITIALIZED; @@ -1001,6 +1025,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { owntype = rhs.type; popContext(); } + //checkNonCyclic(tree.pos, owntype); break; @@ -1014,7 +1039,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { tp.lookup(selectors[i]) == Symbol.NONE && tp.lookup(selectors[i].toTypeName()) == Symbol.NONE && tp.lookup(selectors[i].toConstrName()) == Symbol.NONE) - error(tree.pos, NameTransformer.decode(selectors[i]) + " is not a member of " + expr); + error(tree.pos, NameTransformer.decode(selectors[i]) + " is not a member of " + expr + " of type " + expr.type); } break; @@ -1041,6 +1066,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { * into symbol table. */ void defineTemplate(Tree.Template templ, Symbol clazz) { + //System.out.println("defining " + clazz);//debug // attribute parent constructors Tree[] constrs = transformConstrInvocations(templ.pos, templ.parents); Type[] parents = Tree.typeOf(constrs); @@ -1144,6 +1170,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { if ((mode & PATTERNmode) != 0) { if (tree.isType()) { Symbol clazz = tree.type.unalias().symbol(); + if (clazz.isCaseClass()) { // set type to instantiated case class constructor tree.type = clazz.constructor().type(); @@ -1241,7 +1268,6 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { // find applicable definition and assign to `sym' Symbol sym = Symbol.NONE; Type pre; - Type symtype; int stopPos = Integer.MIN_VALUE; Context nextcontext = context; @@ -1328,7 +1354,8 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { tree = make.Select(tree.pos, qual, name); checkAccessible(tree.pos, sym, qual); } - symtype = pre.memberType(sym); + Type symtype = (sym.isType() ? sym.typeConstructor() : sym.type()) + .asSeenFrom(pre, sym.owner()); if (symtype == Type.NoType) return error(tree.pos, "not found: " + decode(name)); if ((pt != null && pt.isStable() || (mode & QUALmode) != 0) && sym.isStable()) { @@ -1359,7 +1386,8 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { sym.flags |= ACCESSED; if (!TreeInfo.isSelf(qual, context.enclClass.owner)) sym.flags |= SELECTOR; - Type symtype = qual.type.memberType(sym); + Type symtype = (sym.isType() ? sym.typeConstructor() : sym.type()) + .asSeenFrom(qual.type, sym.owner()); if (symtype == Type.NoType) return error(tree.pos, "not found: " + decode(name)); //System.out.println(sym.name + ":" + symtype);//DEBUG @@ -1634,9 +1662,9 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { this.mode = savedMode; if ((mode & TYPEmode) != 0) { - // todo: generalize to type constructors? Symbol sym = tree1.symbol(); - if ((mode & FUNmode) == 0 && sym != null && sym.typeParams().length != 0) + if ((mode & FUNmode) == 0 && + sym != null && sym.typeParams().length != 0) return error(tree.pos, sym + " takes type parameters."); // else if (tree1.isType()) // return gen.mkType(tree1.pos, tree1.type); @@ -2223,11 +2251,13 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { Tree tpe1 = transform(tpe, TYPEmode | FUNmode); Tree[] args1 = transform(args, TYPEmode); Type[] argtypes = Tree.typeOf(args); + Symbol[] tparams = tpe1.type.symbol().typeParams(); + /* //todo: this needs to be refined. (same code in RefCheck.transform) - Symbol[] tparams = (Type.isSameAs(tpe1.type.typeArgs(), Symbol.type(tpe1.type.unalias().symbol().typeParams()))) - ? tpe1.type.unalias().symbol().typeParams() + ? : Symbol.EMPTY_ARRAY; + */ Type owntype = Type.ErrorType; if (tpe1.type != Type.ErrorType) { if (tparams.length == args.length) diff --git a/sources/scalac/typechecker/Infer.java b/sources/scalac/typechecker/Infer.java index e79fc21990..6690855ec6 100644 --- a/sources/scalac/typechecker/Infer.java +++ b/sources/scalac/typechecker/Infer.java @@ -261,6 +261,10 @@ public class Infer implements Modifiers, Kinds { return cut(variance(tparam, pre)); case CompoundType(Type[] parts, Scope members): return variance(tparam, parts) & variance(tparam, members.elements()); + case MethodType(Symbol[] params, Type restype): + return flip(variance(tparam, params)) & variance(tparam, restype); + case PolyType(Symbol[] tparams, Type restype): + return flip(variance(tparam, tparams)) & variance(tparam, restype); default: throw new ApplicationError(tp.toString()); } diff --git a/sources/scalac/typechecker/RefCheck.java b/sources/scalac/typechecker/RefCheck.java index bf5ca8d62f..9cd8575c6b 100644 --- a/sources/scalac/typechecker/RefCheck.java +++ b/sources/scalac/typechecker/RefCheck.java @@ -883,11 +883,14 @@ public class RefCheck extends Transformer implements Modifiers, Kinds { return super.transform(tree); case AppliedType(Tree tpe, Tree[] args): + Symbol[] tparams = tpe.type.symbol().typeParams(); + /* //todo: this needs to be refined. (same code in Analyzer.transform) Symbol[] tparams = (Type.isSameAs( tpe.type.typeArgs(), Symbol.type(tpe.type.unalias().symbol().typeParams()))) ? tpe.type.unalias().symbol().typeParams() : Symbol.EMPTY_ARRAY; + */ checkBounds(tree.pos, tparams, Tree.typeOf(args)); return elimTypeNode(super.transform(tree)); diff --git a/sources/scalac/util/SourceRepresentation.java b/sources/scalac/util/SourceRepresentation.java index 7c6ee44107..e5cb210090 100644 --- a/sources/scalac/util/SourceRepresentation.java +++ b/sources/scalac/util/SourceRepresentation.java @@ -8,6 +8,8 @@ package scalac.util; +import java.io.File; + public final class SourceRepresentation { public static int digit2int(byte ch, int base) { @@ -202,4 +204,15 @@ public final class SourceRepresentation { char[] s = {c}; return escape(new String(s)); } + + /** return external representation of file name s, + * converting '.' to File.separatorChar + */ + public static String externalizeFileName(Name n) { + if ((n == null) || (n.length() == 0)) + return "."; + byte[] ascii = n.toAscii(); + String s = ascii2string(ascii, 0, ascii.length); + return s.replace('.', File.separatorChar); + } } diff --git a/test/files/pos/matthias4.scala b/test/files/pos/matthias4.scala index 32200cccd1..bcda93746b 100644 --- a/test/files/pos/matthias4.scala +++ b/test/files/pos/matthias4.scala @@ -29,7 +29,7 @@ trait _a extends Object with _b { def setX(x: B.X): Unit; } } -abstract class a() extends Object with _a with _b { +abstract class a123() extends Object with _a with _b { val a: this.type = this; val A: A = new A(); class A() extends AObject { @@ -67,7 +67,7 @@ trait _m { abstract class m() extends Object with _m with _b { val m: this.type = this; val M: M = new M(); - class M() extends MObject with a() with Linker() { + class M() extends MObject with a123() with Linker() { def test() = { val x: B.X = B.getX(); A.setX(x); diff --git a/test/files/run/Course-2002-07.scala b/test/files/run/Course-2002-07.scala index 2a45805138..01a0e183b8 100644 --- a/test/files/run/Course-2002-07.scala +++ b/test/files/run/Course-2002-07.scala @@ -504,7 +504,7 @@ object MB { private def vars: List[String] = match { case Var(n) => List(n) case Mul(l,r) => l.vars ::: r.vars - case Pow(l,n) => { val vs = l.vars; List.range(0,n).flatMap(i => vs) } + case Pow(l,n) => { val vs = l.vars; Predef.List.range(0,n).flatMap(i => vs) } case _ => List() } diff --git a/test/pos/matthias4.scala b/test/pos/matthias4.scala index 32200cccd1..bcda93746b 100644 --- a/test/pos/matthias4.scala +++ b/test/pos/matthias4.scala @@ -29,7 +29,7 @@ trait _a extends Object with _b { def setX(x: B.X): Unit; } } -abstract class a() extends Object with _a with _b { +abstract class a123() extends Object with _a with _b { val a: this.type = this; val A: A = new A(); class A() extends AObject { @@ -67,7 +67,7 @@ trait _m { abstract class m() extends Object with _m with _b { val m: this.type = this; val M: M = new M(); - class M() extends MObject with a() with Linker() { + class M() extends MObject with a123() with Linker() { def test() = { val x: B.X = B.getX(); A.setX(x); -- cgit v1.2.3