/* ____ ____ ____ ____ ______ *\ ** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** ** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** ** /_____/\____/\___/\____/____/ ** ** ** ** $Id$ \* */ package scalac.symtab; import ch.epfl.lamp.util.Position; import scalac.*; import scalac.util.*; import scalac.symtab.classfile.*; import Type.*; public class Definitions { /** the root module */ public final Symbol ROOT; public final Symbol ROOT_CLASS; public final Type ROOT_TYPE; /** the scala module */ public final Symbol SCALA; public final Symbol SCALA_CLASS; public final Type SCALA_TYPE; /** the java module */ public final Symbol JAVA; public final Symbol JAVA_CLASS; public final Type JAVA_TYPE; /** the java.lang module */ public final Symbol JAVALANG; public final Symbol JAVALANG_CLASS; public final Type JAVALANG_TYPE; /** the scala.runtime module */ public final Symbol SCALARUNTIME; public final Symbol SCALARUNTIME_CLASS; public final Type SCALARUNTIME_TYPE; /** the partial function class */ public final Symbol PARTIALFUNCTION_CLASS; /** the null value */ public final Symbol NULL; /** the scala.Any class */ public final Symbol ANY_CLASS; public final Type ANY_TYPE; /** some methods of the scala.Any class */ public final Symbol MATCH; public final Symbol IS; public final Symbol AS; public final Symbol EQEQ; public final Symbol BANGEQ; public final Symbol EQUALS; public final Symbol EQ; public final Symbol TOSTRING; public final Symbol HASHCODE; /** a method of class java.lang.Throwable */ public final Symbol THROW; /** the scala.AnyVal class */ public final Symbol ANYVAL_CLASS; public final Type ANYVAL_TYPE; /** the scala.AnyRef class */ public final Symbol ANYREF_CLASS; public final Type ANYREF_TYPE; /** the java.lang.Object class */ public final Symbol JAVA_OBJECT_CLASS; public final Type JAVA_OBJECT_TYPE; /** the scala.Object class */ public final Symbol OBJECT_CLASS; public final Type OBJECT_TYPE; /** the scala.All class */ public final Symbol ALL_CLASS; public final Type ALL_TYPE; /** the scala.AllRef class */ public final Symbol ALLREF_CLASS; public final Type ALLREF_TYPE; /** the primitive types */ public final Symbol BYTE_CLASS; public final Type BYTE_TYPE; public final Symbol SHORT_CLASS; public final Type SHORT_TYPE; public final Symbol CHAR_CLASS; public final Type CHAR_TYPE; public final Symbol INT_CLASS; public final Type INT_TYPE; public final Symbol LONG_CLASS; public final Type LONG_TYPE; public final Symbol FLOAT_CLASS; public final Type FLOAT_TYPE; public final Symbol DOUBLE_CLASS; public final Type DOUBLE_TYPE; public final Symbol BOOLEAN_CLASS; public final Type BOOLEAN_TYPE; public final Symbol UNIT_CLASS; public final Type UNIT_TYPE; /** the array class */ public final Symbol ARRAY_CLASS; /** types from java.lang */ public final Symbol JAVA_STRING_CLASS; public final Type JAVA_STRING_TYPE; public final Symbol JAVA_THROWABLE_CLASS; public final Type JAVA_THROWABLE_TYPE; /** types from scala */ public final Symbol STRING_CLASS; public final Type STRING_TYPE; public final Symbol SEQ_CLASS; /** string concatenation pseudo-methods of classes scala.Any and * java.lang.String */ //public final Symbol ANY_PLUS_STRING; public final Symbol STRING_PLUS_ANY; /** members of class Boolean */ private Symbol BARBAR; private Symbol AMPAMP; public Symbol BARBAR() { loadBooleanMembers(); return BARBAR; } public Symbol AMPAMP() { loadBooleanMembers(); return AMPAMP; } public Definitions(Global global) { // a hack to make definitions accessible earlier to other // components global.definitions = this; PackageParser pparser = new PackageParser(global); // this is the root value; all top-level functions, // modules etc. are a member of this value ROOT = TermSymbol.newJavaPackageModule( Names.EMPTY, Symbol.NONE, pparser); ROOT_CLASS = ROOT.moduleClass(); // this is a prefix for all types inside of the anonymous package ROOT_TYPE = ROOT_CLASS.thisType(); // the scala module SCALA = getModule(Names.scala); // the scala class SCALA_CLASS = SCALA.moduleClass(); // the scala package as a prefix SCALA_TYPE = Type.singleType(ROOT_TYPE, SCALA); // the java module JAVA = getModule(Names.java); // the java class JAVA_CLASS = JAVA.moduleClass(); // the java package as a prefix JAVA_TYPE = Type.singleType(ROOT_TYPE, JAVA); // the java.lang module JAVALANG = getModule(Names.java_lang); // the java.lang class JAVALANG_CLASS = JAVALANG.moduleClass(); // the java.lang package as a prefix JAVALANG_TYPE = Type.singleType(JAVA_TYPE, JAVALANG); // the scala.runtime module SCALARUNTIME = getModule(Names.scala_runtime); // the scala.runtime class SCALARUNTIME_CLASS = SCALARUNTIME.moduleClass(); // the scala.runtime package as a prefix SCALARUNTIME_TYPE = Type.singleType(SCALA_TYPE, SCALARUNTIME); // the scala.ANY classs ANY_CLASS = new ClassSymbol( Position.NOPOS, Names.Any.toTypeName(), SCALA_CLASS, Modifiers.JAVA); SCALA_CLASS.members().enter(ANY_CLASS); ANY_TYPE = ANY_CLASS.typeConstructor(); ANY_CLASS.setInfo(Type.compoundType(Type.EMPTY_ARRAY, new Scope(), ANY_CLASS)); ANY_CLASS.primaryConstructor().setInfo( Type.MethodType(Symbol.EMPTY_ARRAY, ANY_TYPE)); // the java.lang.OBJECT class JAVA_OBJECT_CLASS = getClass(Names.java_lang_Object); JAVA_OBJECT_TYPE = JAVA_OBJECT_CLASS.typeConstructor(); JAVA_OBJECT_CLASS.setInfo(pparser.classCompletion); // the scala.PartialFunction class PARTIALFUNCTION_CLASS = getClass(Names.scala_PartialFunction); // the scala.ANYREF class ANYREF_CLASS = new AliasTypeSymbol( Position.NOPOS, Names.AnyRef.toTypeName(), SCALA_CLASS, Modifiers.JAVA) .setInfo(JAVA_OBJECT_TYPE); SCALA_CLASS.members().enter(ANYREF_CLASS); ANYREF_TYPE = ANYREF_CLASS.typeConstructor().unalias(); ANYREF_CLASS.primaryConstructor().setInfo(Type.MethodType(Symbol.EMPTY_ARRAY, ANYREF_TYPE)); // the scala.OBJECT class OBJECT_CLASS = getClass(Names.scala_Object); OBJECT_TYPE = OBJECT_CLASS.typeConstructor(); // the scala.ANYVAL class ANYVAL_CLASS = getClass(Names.scala_AnyVal); ANYVAL_CLASS.flags |= Modifiers.SEALED; ANYVAL_TYPE = ANYVAL_CLASS.typeConstructor(); // the scala.ALL class ALL_CLASS = new ClassSymbol( Position.NOPOS, Names.All.toTypeName(), SCALA_CLASS, 0); SCALA_CLASS.members().enter(ALL_CLASS); ALL_TYPE = ALL_CLASS.typeConstructor(); ALL_CLASS.setInfo(Type.compoundType(new Type[]{ANY_TYPE}, new Scope(), ALL_CLASS)); ALL_CLASS.primaryConstructor().setInfo(Type.MethodType(Symbol.EMPTY_ARRAY, ALL_TYPE)); // the scala.ALLREF class ALLREF_CLASS = new ClassSymbol( Position.NOPOS, Names.AllRef.toTypeName(), SCALA_CLASS, 0); SCALA_CLASS.members().enter(ALLREF_CLASS); ALLREF_TYPE = ALLREF_CLASS.typeConstructor(); ALLREF_CLASS.setInfo(Type.compoundType(new Type[]{ANYREF_TYPE}, new Scope(), ALLREF_CLASS)); ALLREF_CLASS.primaryConstructor().setInfo(Type.MethodType(Symbol.EMPTY_ARRAY, ALLREF_TYPE)); // the primitive types DOUBLE_CLASS = getClass(Names.scala_Double); DOUBLE_TYPE = DOUBLE_CLASS.typeConstructor(); FLOAT_CLASS = getClass(Names.scala_Float); FLOAT_TYPE = FLOAT_CLASS.typeConstructor(); LONG_CLASS = getClass(Names.scala_Long); LONG_TYPE = LONG_CLASS.typeConstructor(); INT_CLASS = getClass(Names.scala_Int); INT_TYPE = INT_CLASS.typeConstructor(); CHAR_CLASS = getClass(Names.scala_Char); CHAR_TYPE = CHAR_CLASS.typeConstructor(); SHORT_CLASS = getClass(Names.scala_Short); SHORT_TYPE = SHORT_CLASS.typeConstructor(); BYTE_CLASS = getClass(Names.scala_Byte); BYTE_TYPE = BYTE_CLASS.typeConstructor(); BOOLEAN_CLASS = getClass(Names.scala_Boolean); BOOLEAN_TYPE = BOOLEAN_CLASS.typeConstructor(); UNIT_CLASS = getClass(Names.scala_Unit); UNIT_TYPE = UNIT_CLASS.typeConstructor(); // the array class ARRAY_CLASS = getClass(Names.scala_Array); // add members to java.lang.Throwable JAVA_THROWABLE_CLASS = getClass(Names.java_lang_Throwable); JAVA_THROWABLE_TYPE = JAVA_THROWABLE_CLASS.typeConstructor(); THROW = new TermSymbol( Position.NOPOS, Names.throw_, JAVA_THROWABLE_CLASS, Modifiers.FINAL); THROW.setInfo(Type.PolyType(Symbol.EMPTY_ARRAY, ALL_TYPE)); JAVA_THROWABLE_CLASS.members().enter(THROW); // add the java.lang.String class to the scala package JAVA_STRING_CLASS = getClass(Names.java_lang_String); JAVA_STRING_TYPE = JAVA_STRING_CLASS.typeConstructor(); STRING_CLASS = new AliasTypeSymbol( Position.NOPOS, Names.String.toTypeName(), SCALA_CLASS, 0) .setInfo(JAVA_STRING_TYPE); SCALA_CLASS.members().enter(STRING_CLASS); STRING_TYPE = STRING_CLASS.typeConstructor(); STRING_CLASS.primaryConstructor().setInfo(Type.MethodType(Symbol.EMPTY_ARRAY, STRING_TYPE)); SEQ_CLASS = getClass(Names.scala_Seq); /* ANY_PLUS_STRING = new TermSymbol( Position.NOPOS, Names.PLUS, ANY_CLASS, Modifiers.FINAL); ANY_PLUS_STRING.setInfo( Type.MethodType( new Symbol[]{newParameter(ANY_PLUS_STRING, STRING_TYPE)}, STRING_TYPE)); ANY_CLASS.members().enter(ANY_PLUS_STRING); */ STRING_PLUS_ANY = new TermSymbol( Position.NOPOS, Names.PLUS, JAVA_STRING_CLASS, Modifiers.FINAL); STRING_PLUS_ANY.setInfo( Type.MethodType( new Symbol[]{newParameter(STRING_PLUS_ANY, ANY_TYPE)}, STRING_TYPE)); JAVA_STRING_CLASS.members().enter(STRING_PLUS_ANY); // add members to class scala.Any MATCH = new TermSymbol( Position.NOPOS, Names.match, ANY_CLASS, Modifiers.FINAL); Symbol matchTyParam1 = newTypeParameter(MATCH, ANY_TYPE); Symbol matchTyParam2 = newTypeParameter(MATCH, ANY_TYPE); MATCH.setInfo( Type.PolyType( new Symbol[]{matchTyParam1, matchTyParam2}, Type.MethodType( new Symbol[]{ newParameter( MATCH, functionType( new Type[]{matchTyParam1.typeConstructor()}, matchTyParam2.typeConstructor()))}, matchTyParam2.typeConstructor()))); ANY_CLASS.members().enter(MATCH); AS = new TermSymbol( Position.NOPOS, Names.asInstanceOf, ANY_CLASS, Modifiers.FINAL); Symbol tvar = newTypeParameter(AS, ANY_TYPE); AS.setInfo(Type.PolyType(new Symbol[]{tvar}, tvar.type())); ANY_CLASS.members().enter(AS); IS = new TermSymbol( Position.NOPOS, Names.isInstanceOf, ANY_CLASS, Modifiers.FINAL); IS.setInfo(Type.PolyType(new Symbol[]{newTypeParameter(IS, ANY_TYPE)}, BOOLEAN_TYPE)); ANY_CLASS.members().enter(IS); EQEQ = new TermSymbol( Position.NOPOS, Names.EQEQ, ANY_CLASS, Modifiers.FINAL); EQEQ.setInfo(Type.MethodType(new Symbol[]{newParameter(EQEQ, ANY_TYPE)}, BOOLEAN_TYPE)); ANY_CLASS.members().enter(EQEQ); BANGEQ = new TermSymbol( Position.NOPOS, Names.BANGEQ, ANY_CLASS, Modifiers.FINAL); BANGEQ.setInfo(Type.MethodType(new Symbol[]{newParameter(BANGEQ, ANY_TYPE)}, BOOLEAN_TYPE)); ANY_CLASS.members().enter(BANGEQ); EQUALS = new TermSymbol( Position.NOPOS, Names.equals, ANY_CLASS, 0); EQUALS.setInfo(Type.MethodType(new Symbol[]{newParameter(EQUALS, JAVA_OBJECT_TYPE)}, BOOLEAN_TYPE)); ANY_CLASS.members().enter(EQUALS); EQ = new TermSymbol( Position.NOPOS, Names.eq, ANY_CLASS, 0); EQ.setInfo(Type.MethodType(new Symbol[]{newParameter(EQ, JAVA_OBJECT_TYPE)}, BOOLEAN_TYPE)); ANY_CLASS.members().enter(EQ); TOSTRING = new TermSymbol( Position.NOPOS, Names.toString, ANY_CLASS, 0); TOSTRING.setInfo(Type.MethodType(Symbol.EMPTY_ARRAY, STRING_TYPE)); ANY_CLASS.members().enter(TOSTRING); HASHCODE = new TermSymbol( Position.NOPOS, Names.hashCode, ANY_CLASS, 0); HASHCODE.setInfo(Type.MethodType(Symbol.EMPTY_ARRAY, INT_TYPE)); ANY_CLASS.members().enter(HASHCODE); // add a null value to the root scope NULL = new TermSymbol( Position.NOPOS, Names.null_, ROOT_CLASS, 0); NULL.setInfo(ALLREF_TYPE); ROOT.members().enter(NULL); } private Symbol newParameter(Symbol owner, Type tp) { return new TermSymbol(Position.NOPOS, Name.fromString("v"), owner, Modifiers.PARAM) .setInfo(tp); } private Symbol newTypeParameter(Symbol owner, Type bound) { return new AbsTypeSymbol( Position.NOPOS, Name.fromString("T").toTypeName(), owner, Modifiers.PARAM) .setInfo(bound); } public Symbol getModule(Name fullname) { Scope scope = ROOT_CLASS.members(); int i = 0; int j = fullname.pos((byte)'.', i); while (j < fullname.length()) { scope = scope.lookup(fullname.subName(i, j)).members(); i = j + 1; j = fullname.pos((byte)'.', i); } Symbol sym = scope.lookup(fullname.subName(i, fullname.length())); if (!sym.isModule()) { switch (sym.type()) { case OverloadedType(Symbol[] alts, Type[] alttypes): for (int k = 0; k < alts.length; k++) if ((sym = alts[k]).isModule()) break; } } assert sym.isModule() : "no module '" + fullname + "'"; return sym; } public Symbol getClass(Name fullname) { Scope scope = ROOT_CLASS.members(); int i = 0; int j = fullname.pos((byte)'.', i); while (j < fullname.length()) { scope = scope.lookup(fullname.subName(i, j)).members(); i = j + 1; j = fullname.pos((byte)'.', i); } Symbol sym = scope.lookup(fullname.subName(i, fullname.length()).toTypeName()); assert sym.kind != Kinds.NONE : "no class '" + fullname + "'"; return sym; } public Type getType(Name fullname) { return getClass(fullname).type(); } public Type getJavaType(Name fullname) { return getClass(fullname).typeConstructor(); } private void loadBooleanMembers() { if (BARBAR != null) return; Symbol booleanStatics = getModule(Names.scala_Boolean); BARBAR = BOOLEAN_TYPE.lookup(Names.BARBAR); AMPAMP = BOOLEAN_TYPE.lookup(Names.AMPAMP); } public Type arrayType(Type elemtpe) { return Type.appliedType(ARRAY_CLASS.typeConstructor(), new Type[]{elemtpe}); } public Type functionType(Type[] argtps, Type restp) { Type[] argtps1 = new Type[argtps.length + 1]; System.arraycopy(argtps, 0, argtps1, 0, argtps.length); argtps1[argtps.length] = restp; return Type.appliedType( getType(Name.fromString("scala.Function" + argtps.length)), argtps1); } public Type partialFunctionType(Type argtpe, Type restpe) { Type[] argtps1 = new Type[2]; argtps1[0] = argtpe; argtps1[1] = restpe; return Type.appliedType(PARTIALFUNCTION_CLASS.typeConstructor(), argtps1); } public Type seqType(Type argtpe) { return Type.appliedType(getType(Names.scala_Seq), new Type[]{argtpe}); } }