diff options
author | Martin Odersky <odersky@gmail.com> | 2003-02-13 14:41:36 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2003-02-13 14:41:36 +0000 |
commit | 4177daab2f54bdb20c71f623296a8bb32616fd12 (patch) | |
tree | 23f08b43f3758e825d5965b336030603a65bbcf7 /sources/scalac/symtab/classfile/AttributeParser.java | |
parent | 33d6e170c97ca7b2f991896a0729941a7240b6d6 (diff) | |
download | scala-4177daab2f54bdb20c71f623296a8bb32616fd12.tar.gz scala-4177daab2f54bdb20c71f623296a8bb32616fd12.tar.bz2 scala-4177daab2f54bdb20c71f623296a8bb32616fd12.zip |
Initial version.
Diffstat (limited to 'sources/scalac/symtab/classfile/AttributeParser.java')
-rw-r--r-- | sources/scalac/symtab/classfile/AttributeParser.java | 439 |
1 files changed, 439 insertions, 0 deletions
diff --git a/sources/scalac/symtab/classfile/AttributeParser.java b/sources/scalac/symtab/classfile/AttributeParser.java new file mode 100644 index 0000000000..0ed09b44d0 --- /dev/null +++ b/sources/scalac/symtab/classfile/AttributeParser.java @@ -0,0 +1,439 @@ +/* ____ ____ ____ ____ ______ *\ +** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** +** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** +** /_____/\____/\___/\____/____/ ** +** ** +** $Id$ +\* */ + +package scalac.symtab.classfile; + +import scalac.*; +import scalac.symtab.*; +import scalac.util.*; +import java.util.*; + +public class AttributeParser implements ClassfileConstants { + + /** the classfile input buffer + */ + protected AbstractFileReader in; + + /** the constant pool + */ + protected ConstantPool pool; + + protected ClassfileParser parser; + + /** constructor + */ + public AttributeParser(AbstractFileReader in, ConstantPool pool, ClassfileParser parser) { + this.in = in; + this.pool = pool; + this.parser = parser; + } + + public int nameToId(Name name) { + if (name == SOURCEFILE_N) + return SOURCEFILE_ATTR; + if (name == SYNTHETIC_N) + return SYNTHETIC_ATTR; + if (name == DEPRECATED_N) + return DEPRECATED_ATTR; + if (name == CODE_N) + return CODE_ATTR; + if (name == EXCEPTIONS_N) + return EXCEPTIONS_ATTR; + if (name == CONSTANT_VALUE_N) + return CONSTANT_VALUE_ATTR; + if (name == LINE_NUM_TABLE_N) + return LINE_NUM_TABLE_ATTR; + if (name == LOCAL_VAR_TABLE_N) + return LOCAL_VAR_TABLE_ATTR; + if (name == INNERCLASSES_N) + return INNERCLASSES_ATTR; + if (name == META_N) + return META_ATTR; + if (name == SCALA_N) + return SCALA_ATTR; + return BAD_ATTR; + } + + 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()); + int attr = nameToId(attrName); + int attrLen = in.nextInt(); + if ((attrs & attr) == 0) { + //System.out.println("# skipping " + attrName + " of " + def); + in.skip(attrLen); + } else { + //System.out.println("# reading " + attrName + " of " + def); + readAttribute(def, type, attr, attrLen); + } + } + return def; + } + + public void readAttribute(Symbol sym, Type type, int attr, int attrLen) { + switch (attr) { + // class attributes + case SCALA_ATTR: + in.skip(attrLen); + /* not yet + Name sourcefile = (Name)pool.readPool(in.nextChar()); + new UnPickle( + (JavaClassSymbol) sym, in.nextBytes(attrLen - 2), sourcefile); + */ + return; + + case SOURCEFILE_ATTR: + // ((ClassDef)def).sourcefile = (Name)reader.readPool(in.nextChar()); + in.skip(attrLen); + return; + + case INNERCLASSES_ATTR: + /* int n = in.nextChar(); + for (int i = 0; i < n; i++) { + Symbol inner = (Symbol)pool.readPool(in.nextChar()); + Symbol outer = (Symbol)pool.readPool(in.nextChar()); + Name name = (Name)pool.readPool(in.nextChar()); + int flags = in.nextChar(); + if (name != null) { + inner.owner(outer); + inner.mangled(name); + inner.flags = flags; + } + } */ + in.skip(attrLen); + return; + + // method attributes + case CODE_ATTR: + in.skip(attrLen); + return; + + case EXCEPTIONS_ATTR: + //int nexceptions = in.nextChar(); + //Type[] thrown = new Type[nexceptions]; + //for (int j = 0; j < nexceptions; j++) + // thrown[j] = make.classType(reader.readClassName(in.nextChar())); + //((MethodType)def.type).thrown = thrown; + in.skip(attrLen); + return; + + case LINE_NUM_TABLE_ATTR: + in.skip(attrLen); + return; + + case LOCAL_VAR_TABLE_ATTR: + in.skip(attrLen); + return; + + // general attributes + case SYNTHETIC_ATTR: + sym.flags |= Modifiers.SYNTHETIC; + return; + + case DEPRECATED_ATTR: + sym.flags |= Modifiers.DEPRECATED; + return; + + case CONSTANT_VALUE_ATTR: + // Type ctype = (Type)reader.readPool(in.nextChar()); + // def.type = types.coerce(ctype, def.type); + in.skip(attrLen); + return; + + case META_ATTR: + //System.out.println("parsing meta data for " + sym); + String meta = pool.readPool(in.nextChar()).toString().trim(); + sym.setInfo(new MetaParser(meta, tvars, sym, type).parse(), parser.phaseId); + + return; + } + throw new RuntimeException("unknown classfile attribute"); + } + + Scope tvars = new Scope(); + + class MetaParser { + + Symbol owner; + StringTokenizer scanner; + Type defaultType; + String token; + Scope tvars; + Scope locals; + + MetaParser(String meta, Scope tvars, Symbol owner, Type defaultType) { + //System.out.println("meta = " + meta); + this.scanner = new StringTokenizer(meta, "()[], \t<;", true); + this.defaultType = defaultType; + this.owner = owner; + this.tvars = tvars; + } + + private Symbol getTVar(String name) { + return getTVar(name, parser.c.constructor()); + } + + private Symbol getTVar(String name, Symbol owner) { + if (name.startsWith("?")) { + if (locals != null) { + Symbol s = locals.lookup(Name.fromString(name).toTypeName()); + if (s != Symbol.NONE) + return s; + } + Symbol s = tvars.lookup(Name.fromString(name).toTypeName()); + if (s == Symbol.NONE) { + s = new TypeSymbol(Kinds.TYPE, + Position.NOPOS, + Name.fromString(token).toTypeName(), + owner, + Modifiers.PARAM); + s.setInfo(parser.defs.ANY_TYPE, parser.phaseId); + tvars.enter(s); + } + return s; + } else + return Symbol.NONE; + } + + private String nextToken() { + do { + token = scanner.nextToken().trim(); + } while (token.length() == 0); + return token; + } + + protected Type parse() { + if (scanner.hasMoreTokens()) { + nextToken(); + if (!scanner.hasMoreTokens()) + return defaultType; + if ("class".equals(token)) + return parseMetaClass(); + if ("method".equals(token)) + return parseMetaMethod(); + if ("field".equals(token)) + return parseMetaField(); + if ("constr".equals(token)) + return parseConstrField(); + } + return defaultType; + } + + protected Type parseMetaClass() { + nextToken(); + //System.out.println("parse meta class " + token);//DEBUG + if ("[".equals(token)) { + try { + Vector syms = new Vector(); + do { + nextToken(); + assert token.startsWith("?"); + Symbol s = getTVar(token); + if (s == Symbol.NONE) + return defaultType; + nextToken(); + //System.out.println("new var " + s + ", " + token);//DEBUG + if (token.equals("<")) { + nextToken(); + s.setInfo(parseType(), parser.phaseId); + } + syms.add(s); + } while (token.equals(",")); + assert "]".equals(token); + nextToken(); + Symbol[] smbls = (Symbol[])syms.toArray(new Symbol[syms.size()]); + //System.out.println("*** " + syms);//DEBUG + Type constrtype = Type.appliedType( + parser.ctype, Symbol.type(smbls)); + + if ((parser.c.flags & Modifiers.INTERFACE) != 0) { + parser.c.constructor().setInfo( + Type.PolyType(smbls, constrtype), parser.phaseId); + //System.out.println("info = " + parser.c.constructor().info());//DEBUG + } + Symbol[] constrs; + switch (parser.c.constructor().rawInfo()) { + case OverloadedType(Symbol[] alts, _): + constrs = alts; + break; + default: + constrs = new Symbol[]{parser.c.constructor()}; + } + for (int i = 0; i < constrs.length; i++) { + //System.out.println("info = " + e.sym.info()); + switch (constrs[i].rawInfo()) { + case MethodType(Symbol[] vparams, _): + constrs[i].setInfo( + Type.PolyType(smbls, + Type.MethodType( + vparams, constrtype)), parser.phaseId); + break; + case PolyType(_, _): + constrs[i].setInfo( + Type.PolyType(smbls, constrtype), parser.phaseId); + break; + } + //System.out.println("*** constructor " + e.sym + ": " + e.sym.info());//DEBUG + } + } catch (NoSuchElementException e) { + } + } + Type res = defaultType; + if ("extends".equals(token)) { + Vector basetpes = new Vector(); + do { + nextToken(); + basetpes.add(parseType()); + } while (token.equals("with")); + switch (defaultType) { + case CompoundType(_, Scope scope): + res = Type.compoundType( + (Type[])basetpes.toArray(new Type[basetpes.size()]), + scope, + defaultType.symbol()); + } + } + assert ";".equals(token); + return res; + } + + protected Type parseType() { + String name = token; + Symbol s = getTVar(name); + nextToken(); + if (s != Symbol.NONE) + return s.type(); + Symbol clazz = parser.defs.getClass(Name.fromString(name)); + if (token.equals("[")) { + Vector types = new Vector(); + do { + nextToken(); + types.add(parseType()); + } while (token.equals(",")); + assert "]".equals(token); + nextToken(); + Type[] args = new Type[types.size()]; + types.toArray(args); + return Type.TypeRef(clazz.owner().thisType(), clazz, args); + } else { + return parser.defs.monoType(clazz); + } + } + + protected Type parseMetaMethod() { + locals = new Scope(); + try { + nextToken(); + Symbol[] smbls = null; + //System.out.println("parse meta method " + token); + if ("[".equals(token)) { + Vector syms = new Vector(); + do { + nextToken(); + if ("]".equals(token)) + break; + assert token.startsWith("?"); + Symbol s = getTVar(token, owner); + if (s == Symbol.NONE) + return defaultType; + nextToken(); + //System.out.println("new var " + s + ", " + token); + if (token.equals("<")) { + nextToken(); + s.setInfo(parseType(), parser.phaseId); + } + syms.add(s); + } while (token.equals(",")); + assert "]".equals(token); + nextToken(); + smbls = (Symbol[])syms.toArray(new Symbol[syms.size()]); + } + if ("(".equals(token)) { + int i = 0; + Vector params = new Vector(); + do { + nextToken(); + if (")".equals(token)) + break; + params.add(new TermSymbol( + Position.NOPOS, + Name.fromString("x" + (i++)), + owner, + Modifiers.PARAM).setInfo(parseType(), parser.phaseId)); + //System.out.println(" + " + token); + } while (token.equals(",")); + assert ")".equals(token); + nextToken(); + //System.out.println("+++ method " + token); + Type restpe = parseType(); + assert ";".equals(token); + if (smbls == null) + return Type.MethodType( + (Symbol[])params.toArray(new Symbol[params.size()]), + restpe); + else + return Type.PolyType( + smbls, + Type.MethodType( + (Symbol[])params.toArray(new Symbol[params.size()]), + restpe)); + } else { + Type res = parseType(); + assert ";".equals(token); + if (smbls == null) + return Type.PolyType(Symbol.EMPTY_ARRAY, res); + else + return Type.PolyType(smbls, res); + } + } catch (NoSuchElementException e) { + return defaultType; + } finally { + locals = null; + } + } + + protected Type parseMetaField() { + nextToken(); + return parseType(); + } + + protected Type parseConstrField() { + try { + nextToken(); + //System.out.println("+++ constr " + token); + if ("(".equals(token)) { + int i = 0; + Vector params = new Vector(); + do { + nextToken(); + if (")".equals(token)) + break; + params.add(new TermSymbol( + Position.NOPOS, + Name.fromString("x" + (i++)), + owner, + Modifiers.PARAM).setInfo(parseType(), parser.phaseId)); + //System.out.println(" + " + token); + } while (token.equals(",")); + assert ")".equals(token); + nextToken(); + assert ";".equals(token); + return Type.MethodType( + (Symbol[])params.toArray(new Symbol[params.size()]), + parser.ctype); + } else { + assert ";".equals(token); + return Type.PolyType(Symbol.EMPTY_ARRAY, parser.ctype); + } + } catch (NoSuchElementException e) { + return defaultType; + } + } + } +} |