summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpaltherr <paltherr@epfl.ch>2004-03-13 22:19:42 +0000
committerpaltherr <paltherr@epfl.ch>2004-03-13 22:19:42 +0000
commit7155dffc81e96cb3f77e086d77593a511c6d80e3 (patch)
treed685c929a637dce3b82279b5abd1758a31c8f426
parentf108d5429fbf1515c0820a327becd5fbd06180f9 (diff)
downloadscala-7155dffc81e96cb3f77e086d77593a511c6d80e3.tar.gz
scala-7155dffc81e96cb3f77e086d77593a511c6d80e3.tar.bz2
scala-7155dffc81e96cb3f77e086d77593a511c6d80e3.zip
- Rewrote Signatures and ConstantPool to avoid ...
- Rewrote Signatures and ConstantPool to avoid creation of unnecessary names
-rw-r--r--sources/scalac/symtab/classfile/AttributeParser.java61
-rw-r--r--sources/scalac/symtab/classfile/CLRClassParser.java26
-rw-r--r--sources/scalac/symtab/classfile/ClassParser.java2
-rw-r--r--sources/scalac/symtab/classfile/ClassfileParser.java88
-rw-r--r--sources/scalac/symtab/classfile/ConstantPool.java336
-rw-r--r--sources/scalac/symtab/classfile/JavaTypeCreator.java26
-rw-r--r--sources/scalac/symtab/classfile/JavaTypeFactory.java4
-rw-r--r--sources/scalac/symtab/classfile/Signatures.java231
8 files changed, 420 insertions, 354 deletions
diff --git a/sources/scalac/symtab/classfile/AttributeParser.java b/sources/scalac/symtab/classfile/AttributeParser.java
index 5306201edd..1eafb04eea 100644
--- a/sources/scalac/symtab/classfile/AttributeParser.java
+++ b/sources/scalac/symtab/classfile/AttributeParser.java
@@ -75,7 +75,7 @@ public class AttributeParser implements ClassfileConstants {
public Symbol readAttributes(Symbol def, Type type, int attrs) {
char nattr = in.nextChar();
for (int i = 0; i < nattr; i++) {
- Name attrName = (Name)pool.readPool(in.nextChar());
+ Name attrName = pool.getName(in.nextChar());
int attr = nameToId(attrName);
int attrLen = in.nextInt();
if ((attrs & attr) == 0) {
@@ -101,31 +101,21 @@ public class AttributeParser implements ClassfileConstants {
int n = in.nextChar();
//System.out.println(sym + " has " + n + " innerclass entries");
for (int i = 0; i < n; i++) {
- Name name = (Name)pool.readPool(in.nextChar());
- if (name == null) {
- in.nextChar();
- in.nextChar();
- in.nextChar();
- continue;
- }
- Symbol inner = parser.global.definitions.getClass(name);
- name = (Name)pool.readPool(in.nextChar());
- if (name == null) {
- in.nextChar();
- in.nextChar();
- continue;
- }
- Symbol outer = parser.global.definitions.getModule(name, false);
- name = (Name)pool.readPool(in.nextChar());
+ int inner = in.nextChar();
+ if (inner == 0) { in.skip(6); return; }
+ int outer = in.nextChar();
+ if (outer == 0) { in.skip(4); return; }
+ int name = in.nextChar();
+ if (name == 0) { in.skip(2); return; }
int flags = in.nextChar();
- if ((name == null) ||
- ((flags & 0x0009) == 0) ||
- ((flags & 0x0001) == 0) ||
- !outer.isModule() ||
- (outer != sym.dualClass().module()))
- continue;
- Symbol alias = outer.newTypeAlias(Position.NOPOS,
- 0, name.toTypeName(), parser.make.classType(inner));
+ if ((flags & JAVA_ACC_STATIC) == 0) return;
+ if ((flags & (JAVA_ACC_PUBLIC | JAVA_ACC_PROTECTED)) == 0) return;
+ if (pool.getClass(outer) != sym) return;
+ Symbol alias = sym.dualClass().newTypeAlias(
+ Position.NOPOS,
+ 0,
+ pool.getName(name).toTypeName(),
+ parser.make.classType(pool.getClass(inner)));
parser.statics.enterNoHide(alias);
}
//in.skip(attrLen);
@@ -159,13 +149,26 @@ public class AttributeParser implements ClassfileConstants {
sym.flags |= Modifiers.DEPRECATED;
return;
case CONSTANT_VALUE_ATTR:
- Object constVal = pool.readPool(in.nextChar());
- //System.out.println(sym.owner() + "." + sym + ": " + constVal + " of type " + constantType(type, constVal));
- sym.setInfo(parser.make.constantType(type, constVal));
+ AConstant constant = pool.getConstantValue(in.nextChar());
+ switch (constant) {
+ case INT(int value):
+ Definitions definitions = parser.global.definitions;
+ Symbol base = sym.getType().symbol();
+ if (base == definitions.INT_CLASS) break;
+ if (base == definitions.CHAR_CLASS)
+ constant = AConstant.CHAR((char)value);
+ else if (base == definitions.SHORT_CLASS)
+ constant = AConstant.SHORT((short)value);
+ else if (base == definitions.BYTE_CLASS)
+ constant = AConstant.BYTE((byte)value);
+ else
+ constant = AConstant.BOOLEAN(value != 0);
+ }
+ sym.setInfo(parser.make.constantType(constant));
return;
case META_ATTR:
//System.out.println("parsing meta data for " + sym);
- String meta = pool.readPool(in.nextChar()).toString().trim();
+ String meta = pool.getString(in.nextChar()).trim();
sym.setInfo(
new MetaParser(meta, tvars, sym, type).parse());
return;
diff --git a/sources/scalac/symtab/classfile/CLRClassParser.java b/sources/scalac/symtab/classfile/CLRClassParser.java
index ac9d630228..dc01413900 100644
--- a/sources/scalac/symtab/classfile/CLRClassParser.java
+++ b/sources/scalac/symtab/classfile/CLRClassParser.java
@@ -9,6 +9,7 @@
package scalac.symtab.classfile;
import scalac.Global;
+import scalac.atree.AConstant;
import scalac.symtab.Symbol;
import scalac.symtab.SymbolLoader;
import scalac.symtab.TermSymbol;
@@ -108,7 +109,8 @@ public class CLRClassParser extends SymbolLoader {
Name name = Name.fromString(fields[i].Name);
scalac.symtab.Type fieldType = getCLRType(fields[i].FieldType);
if (fields[i].IsLiteral())
- fieldType = make.constantType(fieldType, fields[i].getValue());
+ fieldType = make.constantType(
+ getConstant(fieldType.symbol(), fields[i].getValue()));
Symbol owner = fields[i].IsStatic() ? staticsClass : clazz;
Symbol field = new TermSymbol(Position.NOPOS, name, owner, mods);
field.setInfo(fieldType);
@@ -293,6 +295,28 @@ public class CLRClassParser extends SymbolLoader {
return s != null ? make.classType(s) : getClassType(type);
}
+ public AConstant getConstant(Symbol base, Object value) {
+ if (base == global.definitions.BOOLEAN_CLASS)
+ return AConstant.BOOLEAN(((Number)value).intValue() != 0);
+ if (base == global.definitions.BYTE_CLASS)
+ return AConstant.BYTE(((Number)value).byteValue());
+ if (base == global.definitions.SHORT_CLASS)
+ return AConstant.SHORT(((Number)value).shortValue());
+ if (base == global.definitions.CHAR_CLASS)
+ return AConstant.CHAR((char)((Number)value).intValue());
+ if (base == global.definitions.INT_CLASS)
+ return AConstant.INT(((Number)value).intValue());
+ if (base == global.definitions.LONG_CLASS)
+ return AConstant.LONG(((Number)value).longValue());
+ if (base == global.definitions.FLOAT_CLASS)
+ return AConstant.FLOAT(((Number)value).floatValue());
+ if (base == global.definitions.DOUBLE_CLASS)
+ return AConstant.DOUBLE(((Number)value).doubleValue());
+ if (base == global.definitions.STRING_CLASS)
+ return AConstant.STRING((String)value);
+ throw Debug.abort("illegal value", Debug.show(value, " - ", base));
+ }
+
protected static int translateAttributes(Type type) {
int mods = Modifiers.JAVA;
if (type.IsNotPublic() || type.IsNestedPrivate()
diff --git a/sources/scalac/symtab/classfile/ClassParser.java b/sources/scalac/symtab/classfile/ClassParser.java
index 7066a2cde4..4c40a6016c 100644
--- a/sources/scalac/symtab/classfile/ClassParser.java
+++ b/sources/scalac/symtab/classfile/ClassParser.java
@@ -23,7 +23,7 @@ public class ClassParser extends SymbolLoader {
protected String doComplete(Symbol clasz) throws IOException {
AbstractFile file = global.classPath.openFile(
SourceRepresentation.externalizeFileName(clasz, ".class"));
- new ClassfileParser(global,new AbstractFileReader(file),clasz).parse();
+ ClassfileParser.parse(global, new AbstractFileReader(file), clasz);
return "class file '" + file.getPath() + "'";
}
diff --git a/sources/scalac/symtab/classfile/ClassfileParser.java b/sources/scalac/symtab/classfile/ClassfileParser.java
index 5f3f2f8a57..4495e8ca74 100644
--- a/sources/scalac/symtab/classfile/ClassfileParser.java
+++ b/sources/scalac/symtab/classfile/ClassfileParser.java
@@ -40,34 +40,34 @@ public class ClassfileParser implements ClassfileConstants {
| META_ATTR
| SIG_ATTR;
- protected Global global;
- protected AbstractFileReader in;
- protected Symbol c;
- protected Type ctype;
- protected Scope locals;
- protected Scope statics;
- protected JavaTypeFactory make;
- protected Signatures sigs;
- protected ConstantPool pool;
- protected AttributeParser attrib;
-
-
- public ClassfileParser(Global global, AbstractFileReader in, Symbol c) {
+ protected final Global global;
+ protected final AbstractFileReader in;
+ protected final Symbol c;
+ protected final Type ctype;
+ protected final JavaTypeFactory make;
+ protected final ConstantPool pool;
+ protected final AttributeParser attrib;
+ protected final Scope locals;
+ protected final Scope statics;
+
+
+ private ClassfileParser(Global global, AbstractFileReader in, Symbol c, JavaTypeFactory make, ConstantPool pool) {
this.global = global;
this.in = in;
this.c = c;
- this.make = new JavaTypeCreator(global.definitions);
this.ctype = make.classType(c);
- this.sigs = new Signatures(global, make);
- this.pool = new ConstantPool(in, sigs);
+ this.make = make;
+ this.pool = pool;
this.attrib = new AttributeParser(in, pool, this);
+ this.locals = new Scope();
+ this.statics = new Scope();
}
/** parse the classfile and throw IO exception if there is an
* error in the classfile structure
*/
- public void parse() throws IOException {
+ public static void parse(Global global, AbstractFileReader in, Symbol c) throws IOException {
try {
int magic = in.nextInt();
if (magic != JAVA_MAGIC)
@@ -84,20 +84,29 @@ public class ClassfileParser implements ClassfileConstants {
+ majorVersion + "." + minorVersion
+ ", should be less than "
+ JAVA_MAJOR_VERSION + "." + JAVA_MINOR_VERSION);
- pool.indexPool();
+ JavaTypeFactory make = new JavaTypeCreator(global.definitions);
+ Signatures sigs = new Signatures(global, make, in);
+ ConstantPool pool = new ConstantPool(in, sigs);
int flags = in.nextChar();
- Name name = readClassName(in.nextChar());
- if (c != global.definitions.getClass(name))
+ Symbol clasz = pool.getClass(in.nextChar());
+ if (c != clasz)
throw new IOException("class file '" + in.path + "' "
- + "contains wrong class " + name);
+ + "contains wrong class " + clasz.staticType());
+ new ClassfileParser(global, in, c, make, pool).parse(flags);
+ } catch (RuntimeException e) {
+ if (global.debug) e.printStackTrace();
+ throw new IOException("class file '" + in.path + "' is broken");
+ }
+ }
+
+ protected void parse(int flags) {
+ {
// todo: correct flag transition
c.flags = transFlags(flags);
if ((c.flags & Modifiers.DEFERRED) != 0)
c.flags = c.flags & ~Modifiers.DEFERRED | Modifiers.ABSTRACT;
Type supertpe = readClassType(in.nextChar());
Type[] basetpes = new Type[in.nextChar() + 1];
- this.locals = new Scope();
- this.statics = new Scope();
// set info of class
Type classInfo = Type.compoundType(basetpes, locals, c);
c.setInfo(classInfo);
@@ -129,9 +138,6 @@ public class ClassfileParser implements ClassfileConstants {
//System.out.println("statics class: " + staticsClass);
//System.out.println("module: " + c.module());
//System.out.println("modules class: " + c.module().type().symbol());
- } catch (RuntimeException e) {
- if (global.debug) e.printStackTrace();
- throw new IOException("class file '" + in.path + "' is broken");
}
}
@@ -156,37 +162,18 @@ public class ClassfileParser implements ClassfileConstants {
return res | Modifiers.JAVA;
}
- /** read a class name
- */
- protected Name readClassName(int i) {
- return (Name)pool.readPool(i);
- }
-
/** read a class name and return the corresponding class type
*/
protected Type readClassType(int i) {
- if (i == 0)
- return make.anyType();
- Type res = make.classType((Name)pool.readPool(i));
- if (res == Type.ErrorType)
- global.error("unknown class reference " + pool.readPool(i));
- return res;
- }
-
- /** read a signature and return it as a type
- */
- protected Type readType(int i) {
- Name sig = pool.readExternal(i);
- byte[] ascii = SourceRepresentation.string2ascii(sig.toString());
- return sigs.sigToType(ascii, 0, ascii.length);
+ return i == 0 ? make.anyType() : make.classType(pool.getClass(i));
}
/** read a field
*/
protected void parseField() {
int flags = in.nextChar();
- Name name = (Name)pool.readPool(in.nextChar());
- Type type = readType(in.nextChar());
+ Name name = pool.getName(in.nextChar());
+ Type type = pool.getFieldType(in.nextChar());
int mods = transFlags(flags);
if ((flags & JAVA_ACC_FINAL) == 0)
mods |= Modifiers.MUTABLE;
@@ -206,8 +193,8 @@ public class ClassfileParser implements ClassfileConstants {
int sflags = transFlags(flags);
if ((flags & JAVA_ACC_BRIDGE) != 0)
sflags |= Modifiers.BRIDGE;
- Name name = (Name)pool.readPool(in.nextChar());
- Type type = readType(in.nextChar());
+ Name name = pool.getName(in.nextChar());
+ Type type = pool.getMethodType(in.nextChar());
if (CONSTR_N.equals(name)) {
Symbol s = c.newConstructor(Position.NOPOS, sflags);
// kick out package visible or private constructors
@@ -232,6 +219,7 @@ public class ClassfileParser implements ClassfileConstants {
setParamOwners(type, constr);
constr.setInfo(type);
attrib.readAttributes(constr, type, METH_ATTR);
+
//System.out.println(c + " " + c.allConstructors() + ":" + c.allConstructors().info());//debug
//System.out.println("-- enter " + s);
} else {
diff --git a/sources/scalac/symtab/classfile/ConstantPool.java b/sources/scalac/symtab/classfile/ConstantPool.java
index 8d80446342..09108d950a 100644
--- a/sources/scalac/symtab/classfile/ConstantPool.java
+++ b/sources/scalac/symtab/classfile/ConstantPool.java
@@ -2,184 +2,216 @@
** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
** /_____/\____/\___/\____/____/ **
-** **
-** $Id$
\* */
+// $Id$
+
package scalac.symtab.classfile;
-import scalac.*;
-import scalac.symtab.*;
-import scalac.util.*;
+import scalac.atree.AConstant;
+import scalac.symtab.Symbol;
+import scalac.symtab.Type;
+import scalac.util.AbstractFileReader;
+import scalac.util.Debug;
+import scalac.util.Name;
+import scalac.util.SourceRepresentation;
+/** This class implements the parsing of class file constant pools. */
public class ConstantPool implements ClassfileConstants {
- AbstractFileReader in;
- Signatures sigparser;
+ //########################################################################
+ // Private Fields
- /** the objects of the constant pool
- */
- protected Object[] poolObj;
+ /** The input file */
+ private final AbstractFileReader in;
- /** for every constant pool entry, an index into in.buf where the
- * defining section of the entry is found
- */
- protected int[] poolIdx;
+ /** The signature parser */
+ private final Signatures parser;
- /** constructor
- */
- protected ConstantPool(AbstractFileReader in, Signatures sigparser) {
- this.in = in;
- this.sigparser = sigparser;
- }
-
- /** index all constant pool entries, writing their start
- * addresses into poolIdx
- */
- public void indexPool() {
- poolIdx = new int[in.nextChar()];
- poolObj = new Object[poolIdx.length];
- int i = 1;
- while (i < poolIdx.length) {
- poolIdx[i++] = in.bp;
- byte tag = in.nextByte();
- switch (tag) {
- case CONSTANT_UTF8:
- case CONSTANT_UNICODE: {
- int len = in.nextChar();
- in.skip(len);
- break;
- }
- case CONSTANT_CLASS:
- case CONSTANT_STRING:
- in.skip(2);
- break;
- case CONSTANT_FIELDREF:
- case CONSTANT_METHODREF:
- case CONSTANT_INTFMETHODREF:
- case CONSTANT_NAMEANDTYPE:
- case CONSTANT_INTEGER:
- case CONSTANT_FLOAT:
- in.skip(4);
- break;
- case CONSTANT_LONG:
- case CONSTANT_DOUBLE:
- in.skip(8);
- i++;
- break;
- default:
- throw new RuntimeException("bad constant pool tag: " + tag +
- " at " + (in.bp - 1));
- }
- }
- }
+ /** The start addresses of all constants */
+ private final int[] starts;
+
+ /** The values of the constants (or null if not yet read) */
+ private final Object[] values;
- /** if name is an array type or class signature, return the
- * corresponding type; otherwise return a class definition with given name
- */
- protected Object classOrType(Name name) {
- if ((name.charAt(0) == '[') || (name.charAt(name.length() - 1) == ';')) {
- byte[] ascii = SourceRepresentation.string2ascii(name.toString());
- return sigparser.sigToType(ascii, 0, ascii.length);
- } else
- return name;
- }
-
- /** read constant pool entry at start address i, use poolObj as a cache.
- */
- public Object readPool(int i) {
- if (poolObj[i] != null)
- return poolObj[i];
- int index = poolIdx[i];
- if (index == 0)
- return null;
- switch (in.byteAt(index)) {
+ //########################################################################
+ // Public Constructors
+
+ /** Initializes this instance by reading constant pool in file. */
+ public ConstantPool(AbstractFileReader in, Signatures parser) {
+ this.in = in;
+ this.parser = parser;
+ this.starts = new int[in.nextChar()];
+ this.values = new Object[starts.length];
+ for (int index = 1; index < starts.length; ) {
+ starts[index++] = in.bp;
+ switch (in.nextByte()) {
case CONSTANT_UTF8:
- poolObj[i] = Name.fromAscii(in.buf, index + 3, in.getChar(index + 1));
- break;
case CONSTANT_UNICODE:
- throw new RuntimeException("can't read unicode strings in classfiles");
+ in.skip(in.nextChar());
+ continue;
case CONSTANT_CLASS:
- poolObj[i] = classOrType(readExternal(in.getChar(index + 1)));
- break;
- case CONSTANT_FIELDREF: {
- //Symbol owner = (Symbol)readPool(in.getChar(index + 1));
- //NameAndType nt = (NameAndType)readPool(in.getChar(index + 3));
- //poolObj[i] = new TermSymbol(Kinds.VAR, Position.NOPOS, nt.name, owner, 0)
- // .type(sigparser.sigToType(Name.names, nt.sig.index, nt.sig.length()));
- throw new RuntimeException("can't read constant_fieldrefs in classfiles");
- }
+ case CONSTANT_STRING:
+ in.skip(2);
+ continue;
+ case CONSTANT_FIELDREF:
case CONSTANT_METHODREF:
- case CONSTANT_INTFMETHODREF: {
- //Symbol owner = (Symbol)readPool(in.getChar(index + 1));
- //NameAndType nt = (NameAndType)readPool(in.getChar(index + 3));
- //poolObj[i] = new TermSymbol(Kinds.FUN, Position.NOPOS, nt.name, owner, 0)
- // .type(sigparser.sigToType(Name.names, nt.sig.index, nt.sig.length()));
- throw new RuntimeException("can't read constant_methodrefs in classfiles");
- }
+ case CONSTANT_INTFMETHODREF:
case CONSTANT_NAMEANDTYPE:
- poolObj[i] = new NameAndType((Name)readPool(in.getChar(index + 1)),
- readExternal(in.getChar(index + 3)));
- break;
- case CONSTANT_STRING:
- poolObj[i] = ((Name)readPool(in.getChar(index + 1))).toString();
- break;
case CONSTANT_INTEGER:
- poolObj[i] = new Integer(in.getInt(index + 1));
- break;
case CONSTANT_FLOAT:
- poolObj[i] = new Float(in.getFloat(index + 1));
- break;
+ in.skip(4);
+ continue;
case CONSTANT_LONG:
- poolObj[i] = new Long(in.getLong(index + 1));
- break;
case CONSTANT_DOUBLE:
- poolObj[i] = new Double(in.getDouble(index + 1));
- break;
+ in.skip(8);
+ index++;
+ continue;
default:
- throw new RuntimeException("bad constant pool tag: " + in.byteAt(index));
- }
- return poolObj[i];
- }
-
- /** return internal representation of buf[offset..offset+len-1],
- * converting '/' to '.'
- */
- public byte[] internalize(byte[] buf, int offset, int len) {
- byte[] translated = new byte[len];
- for (int j = 0; j < len; j++) {
- byte b = buf[offset + j];
- if (b == '/')
- translated[j] = '.';
- else
- translated[j] = b;
- }
- return translated;
- }
-
- /** read a constant pool string and convert to internal representation.
- */
- public Name readExternal(int i) {
- if (poolObj[i] == null) {
- int index = poolIdx[i];
- if (in.byteAt(index) == CONSTANT_UTF8) {
- int len = in.getChar(index + 1);
- byte[] translated = internalize(in.buf, index + 3, len);
- poolObj[i] = Name.fromAscii(translated, 0, len);
+ throw errorBadTag(in.bp - 1);
}
}
- return (Name)poolObj[i];
}
- /** the name and type signature of a method or field
- */
- public static final class NameAndType {
- public Name name;
- public Name sig;
+ //########################################################################
+ // Public Methods
+
+ /** Returns the string at given index. */
+ public String getString(int index) {
+ if (index <= 0 || starts.length <= index) throw errorBadIndex(index);
+ if (values[index] instanceof String) return (String)values[index];
+ if (values[index] instanceof Name) return values[index].toString();
+ String value = readString(starts[index]);
+ values[index] = value;
+ return value;
+ }
+
+ /** Returns the name at given index. */
+ public Name getName(int index) {
+ if (index <= 0 || starts.length <= index) throw errorBadIndex(index);
+ if (values[index] instanceof Name) return (Name)values[index];
+ Name value = readName(starts[index]);
+ values[index] = value;
+ return value;
+ }
- public NameAndType(Name name, Name sig) {
- this.name = name;
- this.sig = sig;
+ /** Returns the class at given index. */
+ public Symbol getClass(int index) {
+ if (index <= 0 || starts.length <= index) throw errorBadIndex(index);
+ if (values[index] instanceof Symbol) return (Symbol)values[index];
+ Symbol value = readClass(starts[index]);
+ values[index] = value;
+ return value;
+ }
+
+ /** Returns the field type at given index. */
+ public Type getFieldType(int index) {
+ if (index <= 0 || starts.length <= index) throw errorBadIndex(index);
+ if (values[index] instanceof Type) return (Type)values[index];
+ Type value = readFieldType(starts[index]);
+ values[index] = value;
+ return value;
+ }
+
+ /** Returns the method type at given index. */
+ public Type getMethodType(int index) {
+ if (index <= 0 || starts.length <= index) throw errorBadIndex(index);
+ if (values[index] instanceof Type) return clone((Type)values[index]);
+ Type value = readMethodType(starts[index]);
+ values[index] = value;
+ return value;
+ }
+
+ /** Returns the constant value at given index. */
+ public AConstant getConstantValue(int index) {
+ if (index <= 0 || starts.length <= index) throw errorBadIndex(index);
+ if (values[index] != null) return (AConstant)values[index];
+ AConstant value = readConstantValue(starts[index]);
+ values[index] = value;
+ return value;
+ }
+
+ //########################################################################
+ // Private Fields
+
+ /** Reads the string at given address. */
+ private String readString(int address) {
+ if (in.byteAt(address) != CONSTANT_UTF8) throw errorBadTag(address);
+ return parser.at(address).getSignature();
+ }
+
+ /** Reads the name at given address. */
+ private Name readName(int address) {
+ return Name.fromString(readString(address));
+ }
+
+ /** Reads the class at given address. */
+ private Symbol readClass(int address) {
+ if (in.byteAt(address) != CONSTANT_CLASS) throw errorBadTag(address);
+ int index = in.getChar(address + 1);
+ if (index <= 0 || starts.length <= index) throw errorBadIndex(index);
+ address = starts[index];
+ if (in.byteAt(address) != CONSTANT_UTF8) throw errorBadTag(address);
+ return parser.at(address).readClassName();
+ }
+
+ /** Reads the field type at given address. */
+ private Type readFieldType(int address) {
+ if (in.byteAt(address) != CONSTANT_UTF8) throw errorBadTag(address);
+ return parser.at(address).readValueType();
+ }
+
+ /** Reads the method type at given address. */
+ private Type readMethodType(int address) {
+ if (in.byteAt(address) != CONSTANT_UTF8) throw errorBadTag(address);
+ return parser.at(address).readMethodType();
+ }
+
+ /** Reads the constant value at given address. */
+ private AConstant readConstantValue(int address) {
+ switch (in.byteAt(address)) {
+ case CONSTANT_STRING:
+ return AConstant.STRING(getString(in.getChar(address + 1)));
+ case CONSTANT_INTEGER:
+ return AConstant.INT(in.getInt(address + 1));
+ case CONSTANT_FLOAT:
+ return AConstant.FLOAT(in.getFloat(address + 1));
+ case CONSTANT_LONG:
+ return AConstant.LONG(in.getLong(address + 1));
+ case CONSTANT_DOUBLE:
+ return AConstant.DOUBLE(in.getDouble(address + 1));
+ default:
+ throw errorBadTag(address);
+ }
+ }
+
+ /** Returns the type with all its parameters symbols cloned. */
+ private Type clone(Type type) {
+ switch (type) {
+ case MethodType(Symbol[] params, Type result):
+ Symbol[] clones = new Symbol[params.length];
+ for (int i = 0; i < clones.length; i++)
+ clones[i] = params[i].cloneSymbol(Symbol.NONE);
+ return Type.MethodType(clones, result);
+ case ErrorType:
+ return type;
+ default:
+ throw Debug.abort("illegal case", type);
}
}
+
+ /** Throws an exception signaling a bad constant index. */
+ private RuntimeException errorBadIndex(int index) {
+ String error = "bad constant pool index: " + index;
+ throw new RuntimeException(error);
+ }
+
+ /** Throws an exception signaling a bad tag at given address. */
+ private RuntimeException errorBadTag(int address) {
+ int tag = in.byteAt(address);
+ String error = "bad constant pool tag " + tag + " at byte " + address;
+ throw new RuntimeException(error);
+ }
+
+ //########################################################################
}
diff --git a/sources/scalac/symtab/classfile/JavaTypeCreator.java b/sources/scalac/symtab/classfile/JavaTypeCreator.java
index d5128efcb3..01e4bf05ba 100644
--- a/sources/scalac/symtab/classfile/JavaTypeCreator.java
+++ b/sources/scalac/symtab/classfile/JavaTypeCreator.java
@@ -133,30 +133,8 @@ public class JavaTypeCreator implements JavaTypeFactory {
/** return the constant type for the given constant.
*/
- public Type constantType(Type base, Object value) {
- return Type.constantType(constantValue(base, value));
- }
-
- private AConstant constantValue(Type base, Object value) {
- if (base.symbol() == definitions.BOOLEAN_CLASS)
- return AConstant.BOOLEAN(((Number)value).intValue() != 0);
- if (base.symbol() == definitions.BYTE_CLASS)
- return AConstant.BYTE(((Number)value).byteValue());
- if (base.symbol() == definitions.SHORT_CLASS)
- return AConstant.SHORT(((Number)value).shortValue());
- if (base.symbol() == definitions.CHAR_CLASS)
- return AConstant.CHAR((char)((Number)value).intValue());
- if (base.symbol() == definitions.INT_CLASS)
- return AConstant.INT(((Number)value).intValue());
- if (base.symbol() == definitions.LONG_CLASS)
- return AConstant.LONG(((Number)value).longValue());
- if (base.symbol() == definitions.FLOAT_CLASS)
- return AConstant.FLOAT(((Number)value).floatValue());
- if (base.symbol() == definitions.DOUBLE_CLASS)
- return AConstant.DOUBLE(((Number)value).doubleValue());
- if (base.symbol() == definitions.STRING_CLASS)
- return AConstant.STRING((String)value);
- throw Debug.abort("illegal value", value + " - " + base);
+ public Type constantType(AConstant value) {
+ return Type.constantType(value);
}
/** return the type of a given constant.
diff --git a/sources/scalac/symtab/classfile/JavaTypeFactory.java b/sources/scalac/symtab/classfile/JavaTypeFactory.java
index 5b89ebf231..62ead89e1d 100644
--- a/sources/scalac/symtab/classfile/JavaTypeFactory.java
+++ b/sources/scalac/symtab/classfile/JavaTypeFactory.java
@@ -8,6 +8,7 @@
package scalac.symtab.classfile;
+import scalac.atree.AConstant;
import scalac.symtab.Symbol;
import scalac.symtab.Type;
import scalac.util.Name;
@@ -30,6 +31,5 @@ public interface JavaTypeFactory {
Type arrayType(Type elemtpe);
Type methodType(Type[] argtpes, Type restpe, Type[] thrown);
Type packageType(Name packagename);
- Type constantType(Type base, Object value);
- Type typeOfValue(Object value); // not in use, shall we remove it?
+ Type constantType(AConstant value);
}
diff --git a/sources/scalac/symtab/classfile/Signatures.java b/sources/scalac/symtab/classfile/Signatures.java
index 9676882aed..3aad3593d4 100644
--- a/sources/scalac/symtab/classfile/Signatures.java
+++ b/sources/scalac/symtab/classfile/Signatures.java
@@ -2,121 +2,162 @@
** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
** /_____/\____/\___/\____/____/ **
-** **
-** $Id$
\* */
+// $Id$
+
package scalac.symtab.classfile;
-import scalac.*;
-import scalac.symtab.*;
-import scalac.util.*;
-import java.util.*;
-import Type.*;
+import ch.epfl.lamp.util.Position;
+import scalac.Global;
+import scalac.symtab.Symbol;
+import scalac.symtab.Type;
+import scalac.util.AbstractFileReader;
+import scalac.util.Name;
+import scalac.util.SourceRepresentation;
+/** This class implements the parsing of class file signatures. */
public class Signatures {
- /** signature constants
- */
- Name BYTE_SIG = Name.fromString("B");
- Name SHORT_SIG = Name.fromString("S");
- Name CHAR_SIG = Name.fromString("C");
- Name INT_SIG = Name.fromString("I");
- Name LONG_SIG = Name.fromString("J");
- Name FLOAT_SIG = Name.fromString("F");
- Name DOUBLE_SIG = Name.fromString("D");
- Name BOOLEAN_SIG = Name.fromString("Z");
- Name VOID_SIG = Name.fromString("V");
- Name CLASS_SIG = Name.fromString("L");
- Name ARRAY_SIG = Name.fromString("[");
- Name ARGBEGIN_SIG = Name.fromString("(");
- Name ARGEND_SIG = Name.fromString(")");
-
- Global global;
- JavaTypeFactory make;
-
-
- public Signatures(Global global, JavaTypeFactory make) {
- this.make = make;
+ //########################################################################
+ // Private Fields
+
+ /** The global environment */
+ private final Global global;
+
+ /** The Java type factory */
+ private final JavaTypeFactory make;
+
+ /** The input file */
+ private final AbstractFileReader in;
+
+ /** The address of the first byte of the current signature */
+ private int first;
+
+ /** The address of the last byte of the current signature */
+ private int last;
+
+ /** The current address (first <= current <= last) */
+ private int current;
+
+ //########################################################################
+ // Public Constructors
+
+ /** Initializes this instance. */
+ public Signatures(Global global, JavaTypeFactory make,
+ AbstractFileReader in)
+ {
this.global = global;
+ this.make = make;
+ this.in = in;
}
- /** the type represented by signature[offset..].
+ //########################################################################
+ // Public Methods
+
+ /**
+ * Sets the address of the next signature to read. The address
+ * must point to the first byte of a CONSTANT_Utf8_info.
*/
- protected byte[] signature;
- protected int sigp;
- protected int limit;
-
- public Type sigToType(byte[] sig, int offset, int len) {
- signature = sig;
- sigp = offset;
- limit = offset + len;
- return sigToType();
+ public Signatures at(int address) {
+ first = address + 3;
+ last = first + in.getChar(address + 1) - 1;
+ current = first;
+ return this;
}
- protected Type sigToType() {
- switch (signature[sigp]) {
- case 'B':
- sigp++;
- return make.byteType();
- case 'C':
- sigp++;
- return make.charType();
- case 'D':
- sigp++;
- return make.doubleType();
- case 'F':
- sigp++;
- return make.floatType();
- case 'I':
- sigp++;
- return make.intType();
- case 'J':
- sigp++;
- return make.longType();
- case 'L':
- sigp++;
- int start = sigp;
- while (signature[sigp] != ';')
- sigp++;
- return make.classType(Name.fromAscii(signature, start, (sigp++) - start));
- case 'S':
- sigp++;
- return make.shortType();
- case 'V':
- sigp++;
- return make.voidType();
- case 'Z':
- sigp++;
- return make.booleanType();
- case '[':
- sigp++;
- while (('0' <= signature[sigp]) && (signature[sigp] <= '9'))
- sigp++;
- return make.arrayType(sigToType());
- case '(':
- return make.methodType(sigToTypes(')'), sigToType(), Type.EMPTY_ARRAY);
- default:
- global.error("bad signature: " +
- SourceRepresentation.ascii2string(signature, sigp, 1));
- return Type.ErrorType;
+ /** Returns the current signature. */
+ public String getSignature() {
+ return SourceRepresentation.ascii2string(in.buf, first, last-first+1);
+ }
+
+ /** Reads the class signature at current address. */
+ public Symbol readClassName() {
+ Symbol owner = global.definitions.ROOT_CLASS;
+ int start = current;
+ for (; current <= last; current++) {
+ int b = in.byteAt(current);
+ if (b == ';') break;
+ if (b != '/') continue;
+ Name name = Name.fromAscii(in.buf, start, current - start);
+ Symbol module = owner.members().lookup(name);
+ if (!module.isModule()) {
+ Symbol symbol = owner.newModule(Position.NOPOS, 0, name);
+ symbol.moduleClass().setInfo(Type.ErrorType);
+ error("could not find module " + symbol.staticType());
+ if (module.isNone()) owner.members().enterNoHide(symbol);
+ module = symbol;
+ }
+ owner = module.moduleClass();
+ start = current + 1;
+ }
+ Name name = Name.fromAscii(in.buf, start, current-start).toTypeName();
+ Symbol clasz = owner.members().lookup(name);
+ if (!clasz.isClass()) {
+ Symbol symbol = owner.newClass(Position.NOPOS, 0, name);
+ symbol.setInfo(Type.ErrorType);
+ symbol.allConstructors().setInfo(Type.ErrorType);
+ error("could not find class " + symbol.staticType());
+ if (clasz.isNone()) owner.members().enterNoHide(symbol);
+ clasz = symbol;
+ }
+ current++;
+ return clasz;
+ }
+
+ /** Reads the value type signature at current address. */
+ public Type readValueType() {
+ switch (in.byteAt(current++)) {
+ case 'V': return make.voidType();
+ case 'Z': return make.booleanType();
+ case 'B': return make.byteType();
+ case 'S': return make.shortType();
+ case 'C': return make.charType();
+ case 'I': return make.intType();
+ case 'J': return make.longType();
+ case 'F': return make.floatType();
+ case 'D': return make.doubleType();
+ case 'L': return make.classType(readClassName());
+ case '[': return make.arrayType(readValueType());
+ default : return errorBadTypeTag(current - 1);
}
}
- protected Type[] sigToTypes(char terminator) {
- sigp++;
- return sigToTypes(terminator, 0);
+ /** Reads the method type signature at current address. */
+ public Type readMethodType() {
+ if (in.byteAt(current++) != '(') return errorBadTypeTag(current - 1);
+ Type[] parameters = readParamterTypes(0);
+ Type result = readValueType();
+ return make.methodType(parameters, result, Type.EMPTY_ARRAY);
}
- protected Type[] sigToTypes(char terminator, int i) {
- if (signature[sigp] == terminator) {
- sigp++;
+ //########################################################################
+ // Private Methods
+
+ /** Reads the parameter types at current address. */
+ private Type[] readParamterTypes(int i) {
+ if (in.byteAt(current) == ')') {
+ current++;
return new Type[i];
} else {
- Type t = sigToType();
- Type[] vec = sigToTypes(terminator, i+1);
- vec[i] = t;
- return vec;
+ Type type = readValueType();
+ Type[] types = readParamterTypes(i + 1);
+ types[i] = type;
+ return types;
}
}
+
+ /** Signals a bad tag at given address. Return ErrorType. */
+ private Type errorBadTypeTag(int address) {
+ char tag = (char)in.byteAt(address);
+ error("bad tag '" + tag + "' in signature '" + getSignature() + "'");
+ return Type.ErrorType;
+ }
+
+ /** Signals the given error. */
+ private void error(String error) {
+ global.error("class file '" + in.path + "': " + error);
+ }
+
+ //########################################################################
}