summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormihaylov <mihaylov@epfl.ch>2005-05-29 23:06:35 +0000
committermihaylov <mihaylov@epfl.ch>2005-05-29 23:06:35 +0000
commit08d6815870d309e1ce924a99f17f50c6e46f89cd (patch)
treeb02781adb87721405c94615ac91c57aa88c922c3
parenta50fb39267918c2ff500143e2c622445edacdffa (diff)
downloadscala-08d6815870d309e1ce924a99f17f50c6e46f89cd.tar.gz
scala-08d6815870d309e1ce924a99f17f50c6e46f89cd.tar.bz2
scala-08d6815870d309e1ce924a99f17f50c6e46f89cd.zip
Initial support for attributes - only works for...
Initial support for attributes - only works for the scala.serializable attribute
-rw-r--r--config/list/scalac.lst1
-rw-r--r--sources/scala/tools/scalac/typechecker/Analyzer.scala17
-rwxr-xr-xsources/scala/tools/scalac/typechecker/RefCheck.scala18
-rw-r--r--sources/scalac/Global.java28
-rw-r--r--sources/scalac/atree/AConstant.java2
-rw-r--r--sources/scalac/backend/jvm/GenJVM.java9
-rw-r--r--sources/scalac/symtab/AttributeInfo.java39
-rw-r--r--sources/scalac/symtab/Definitions.java16
-rw-r--r--sources/scalac/transformer/AddInterfacesPhase.java6
9 files changed, 113 insertions, 23 deletions
diff --git a/config/list/scalac.lst b/config/list/scalac.lst
index b0f49ed7c2..747c1c2937 100644
--- a/config/list/scalac.lst
+++ b/config/list/scalac.lst
@@ -78,6 +78,7 @@
../../../scalac/symtab/classfile/Pickle.java
../../../scalac/symtab/classfile/UnPickle.java
+../../../scalac/symtab/AttributeInfo.java
../../../scalac/symtab/ClosureHistory.java
../../../scalac/symtab/Definitions.java
../../../scalac/symtab/EntryTags.java
diff --git a/sources/scala/tools/scalac/typechecker/Analyzer.scala b/sources/scala/tools/scalac/typechecker/Analyzer.scala
index facaafc7ee..9abd60ef20 100644
--- a/sources/scala/tools/scalac/typechecker/Analyzer.scala
+++ b/sources/scala/tools/scalac/typechecker/Analyzer.scala
@@ -56,8 +56,6 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
var unit: CompilationUnit = _;
- type AttrInfo = Pair/*<Symbol, Array[AConstant]>*/ ;
-
def enterUnit(unit: CompilationUnit): unit =
enter(
new Context(
@@ -2163,15 +2161,15 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
case Tree.Attributed(attr, definition) =>
- def attrInfo(attr: Tree): AttrInfo = attr match {
+ def attrInfo(attr: Tree): Tuple2[Symbol, Array[AConstant]] = attr match {
case Tree.Ident(_) | Tree.Select(_, _) =>
- new Pair(attr.symbol(), new Array[AConstant](0))
+ Tuple2(attr.symbol(), AConstant.EMPTY_ARRAY)
case Tree.Apply(fn, args) =>
- new Pair(attrInfo(fn).fst, attrArgInfos(args))
+ Tuple2(attrInfo(fn)._1, attrArgInfos(args))
case _ =>
unit.error(attr.pos, "malformed attribute");
- new Pair(Symbol.NONE.newErrorClass(errorName(attr).toTypeName()),
- new Array[AConstant](0))
+ Tuple2(Symbol.NONE.newErrorClass(errorName(attr).toTypeName()),
+ AConstant.EMPTY_ARRAY)
}
def attrArgInfos(args: Array[Tree]): Array[AConstant] = {
@@ -2190,9 +2188,8 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
val attr1 = transform(attr, CONSTRmode, definitions.ATTRIBUTE_TYPE());
val res = transform(definition);
val defsym = res.symbol();
- var attrs = global.mapSymbolAttr.get(defsym).asInstanceOf[List[AttrInfo]];
- if (attrs == null) attrs = List();
- global.mapSymbolAttr.put(defsym, attrInfo(attr1) :: attrs);
+ val attrpair = attrInfo(attr1);
+ global.addAttribute(defsym, attrpair._1, attrpair._2);
res
case Tree.DocDef(comment, definition) =>
diff --git a/sources/scala/tools/scalac/typechecker/RefCheck.scala b/sources/scala/tools/scalac/typechecker/RefCheck.scala
index 42e208fe8e..8bee62c5ed 100755
--- a/sources/scala/tools/scalac/typechecker/RefCheck.scala
+++ b/sources/scala/tools/scalac/typechecker/RefCheck.scala
@@ -877,6 +877,7 @@ class RefCheck(globl: scalac.Global) extends Transformer(globl) {
private def addSyntheticMethods(templ: Template, clazz: ClassSymbol): Template = {
val ts = new TreeList();
if (clazz.isCaseClass()) {
+ global.addAttribute(clazz, defs.SCALA_SERIALIZABLE_CONSTR);
if (!hasImplementation(clazz, Names.toString)) {
ts.append(toStringMethod(clazz));
}
@@ -900,12 +901,17 @@ class RefCheck(globl: scalac.Global) extends Transformer(globl) {
if (global.target != Global.TARGET_MSIL)
ts.append(getTypeMethod(clazz));
}
- if (clazz.isModuleClass() && clazz.isSubClass(defs.SERIALIZABLE_CLASS)) {
- // If you serialize a singleton and then deserialize it twice,
- // you will have two instances of your singleton, unless you implement
- // the readResolve() method (see http://www.javaworld.com/javaworld/
- // jw-04-2003/jw-0425-designpatterns_p.html)
- ts.append(readResolveMethod(clazz));
+ if (clazz.isModuleClass()) {
+ val attrs = global.getAttributes(clazz);
+ val serializable = attrs != null &&
+ attrs.getAttrArguments(defs.SCALA_SERIALIZABLE_CONSTR) != null;
+ if (serializable) {
+ // If you serialize a singleton and then deserialize it twice,
+ // you will have two instances of your singleton, unless you implement
+ // the readResolve() method (see http://www.javaworld.com/javaworld/
+ // jw-04-2003/jw-0425-designpatterns_p.html)
+ ts.append(readResolveMethod(clazz));
+ }
}
copy.Template(
templ, templ.parents,
diff --git a/sources/scalac/Global.java b/sources/scalac/Global.java
index 6c2b9ac200..6f6bb899a3 100644
--- a/sources/scalac/Global.java
+++ b/sources/scalac/Global.java
@@ -35,6 +35,7 @@ import scala.tools.util.ReporterTimer;
import scalac.ast.*;
import scalac.ast.parser.*;
import scalac.ast.printer.TreePrinter;
+import scalac.atree.AConstant;
import scalac.atree.ATreePrinter;
import scalac.backend.Primitives;
// !!! <<< Interpreter stuff
@@ -121,7 +122,7 @@ public abstract class Global {
/** attributes of symbols
*/
- public final Map/*<Symbol, Pair<Symbol, AConstant[]>>*/ mapSymbolAttr = new HashMap();
+ protected final Map/*<Symbol, AttributeInfo>*/ mapSymbolAttr = new HashMap();
/** views associated with (upper-bounded) type parameters
*/
@@ -416,6 +417,31 @@ public abstract class Global {
}
}
+ public void addAttribute(Symbol sym, Symbol aSym, AConstant[] params) {
+ AttributeInfo attr = getAttributes(sym);
+ attr = new AttributeInfo(aSym, params, attr);
+ //mapSymbolAttr.put(sym, attr);
+ setAttribute(sym, attr);
+ }
+
+ public void addAttribute(Symbol sym, Symbol aSym) {
+ addAttribute(sym, aSym, AConstant.EMPTY_ARRAY);
+ }
+
+ public void setAttribute(Symbol sym, AttributeInfo attr) {
+ mapSymbolAttr.put(sym, attr);
+ if (sym.isModule() && !sym.isModuleClass())
+ mapSymbolAttr.put(sym.moduleClass(), attr);
+ }
+
+ public AttributeInfo getAttributes(Symbol sym) {
+ return (AttributeInfo)mapSymbolAttr.get(sym);
+ }
+
+ public AttributeInfo removeAttributes(Symbol sym) {
+ return (AttributeInfo)mapSymbolAttr.remove(sym);
+ }
+
public abstract void dump(CompilationUnit[] units);
void print(CompilationUnit[] units) {
diff --git a/sources/scalac/atree/AConstant.java b/sources/scalac/atree/AConstant.java
index 2dcc80bbaf..12c58d5889 100644
--- a/sources/scalac/atree/AConstant.java
+++ b/sources/scalac/atree/AConstant.java
@@ -14,6 +14,8 @@ import scalac.symtab.Symbol;
/** This class represents a constant. */
public class AConstant {
+ public static final AConstant[] EMPTY_ARRAY = new AConstant[0];
+
//########################################################################
// Public Cases
diff --git a/sources/scalac/backend/jvm/GenJVM.java b/sources/scalac/backend/jvm/GenJVM.java
index 5095a3b024..5753ca9c4d 100644
--- a/sources/scalac/backend/jvm/GenJVM.java
+++ b/sources/scalac/backend/jvm/GenJVM.java
@@ -1624,6 +1624,10 @@ public class GenJVM {
protected Context enterClass(Context ctx, Symbol cSym) {
String javaName = javaName(cSym);
+ AttributeInfo attrs = global.getAttributes(cSym);
+ boolean serializable = attrs != null
+ && attrs.getAttrArguments(defs.SCALA_SERIALIZABLE_CONSTR) != null;
+
scalac.symtab.Type[] baseTps = cSym.info().parents();
assert baseTps.length > 0 : Debug.show(cSym);
@@ -1636,12 +1640,15 @@ public class GenJVM {
offset = 1;
superClassName = javaName(baseTps[0].symbol());
}
- String[] interfaceNames = new String[baseTps.length - offset];
+ String[] interfaceNames = new String[baseTps.length - offset
+ + (serializable ? 1 : 0)];
for (int i = offset; i < baseTps.length; ++i) {
Symbol baseSym = baseTps[i].symbol();
assert baseSym.isInterface() : cSym + " implements " + baseSym;
interfaceNames[i - offset] = javaName(baseSym);
}
+ if (serializable)
+ interfaceNames[interfaceNames.length - 1] = "java.io.Serializable";
JClass cls = fjbgContext.JClass(javaModifiers(cSym)
& ~JAccessFlags.ACC_STATIC
diff --git a/sources/scalac/symtab/AttributeInfo.java b/sources/scalac/symtab/AttributeInfo.java
new file mode 100644
index 0000000000..8269cc74a6
--- /dev/null
+++ b/sources/scalac/symtab/AttributeInfo.java
@@ -0,0 +1,39 @@
+package scalac.symtab;
+
+import scalac.atree.AConstant;
+import scalac.util.Debug;
+
+public class AttributeInfo {
+
+ public final Symbol constr;
+ public final AConstant[] args;
+ public final AttributeInfo next;
+
+ public AttributeInfo(Symbol constr, AConstant[] args, AttributeInfo next) {
+ this.constr = constr;
+ this.args = args;
+ this.next = next;
+ assert constr.isConstructor() : Debug.show(constr);
+ }
+
+ public AConstant[] getAttrArguments(Symbol sym) {
+ for (AttributeInfo attr = this; attr != null; attr = attr.next)
+ if (attr.constr == sym)
+ return attr.args;
+ return null;
+ }
+
+ public String toString() {
+ StringBuffer str = new StringBuffer();
+ for (AttributeInfo attr = this; attr != null; attr = attr.next) {
+ str.append('['); str.append(Debug.show(attr.constr.constructorClass()));
+ str.append('(');
+ for (int i = 0; i < attr.args.length; i++) {
+ if (i > 0) str.append(", ");
+ str.append(attr.args[i]);
+ }
+ str.append(")]\n");
+ }
+ return str.toString();
+ }
+}
diff --git a/sources/scalac/symtab/Definitions.java b/sources/scalac/symtab/Definitions.java
index 11b49d1f57..a80ceeff52 100644
--- a/sources/scalac/symtab/Definitions.java
+++ b/sources/scalac/symtab/Definitions.java
@@ -77,10 +77,6 @@ public class Definitions {
public final Symbol THROWABLE_CLASS;
public final Type THROWABLE_TYPE() {return THROWABLE_CLASS.staticType();}
- /** The java.io.Serializable class */
- public final Symbol SERIALIZABLE_CLASS;
- public final Type SERIALIZABLE_TYPE() {return SERIALIZABLE_CLASS.staticType();}
-
//########################################################################
// Public Fields & Methods - Scala value classes
@@ -254,6 +250,12 @@ public class Definitions {
public final Symbol MATCHERROR;
//########################################################################
+ // attributes
+
+ public final Symbol SCALA_SERIALIZABLE_CONSTR;
+ public final Symbol SCALA_SERIAL_VERSION_UID_CONSTR;
+
+ //########################################################################
// Public Fields & Methods - Scala primitive types
/** Returns the primitive type void. */
@@ -789,7 +791,6 @@ public class Definitions {
STRING_CLASS = getClass(forMSIL ? "System.String" : "java.lang.String");
THROWABLE_CLASS =
getClass(forMSIL ? "System.Exception" : "java.lang.Throwable");
- SERIALIZABLE_CLASS = getClass("java.io.Serializable");
// the scala value classes
UNIT_CLASS = getClass("scala.Unit");
@@ -833,6 +834,11 @@ public class Definitions {
CONSOLE = getModule("scala.Console");
MATCHERROR = getModule("scala.MatchError");
+ SCALA_SERIALIZABLE_CONSTR = getClass("scala.serializable")
+ .primaryConstructor();
+ SCALA_SERIAL_VERSION_UID_CONSTR = getClass("scala.SerialVersionUID")
+ .primaryConstructor();
+
// initialize generated classes and aliases
initClass(ANY_CLASS, Type.EMPTY_ARRAY);
initAlias(ANYREF_CLASS, OBJECT_TYPE());
diff --git a/sources/scalac/transformer/AddInterfacesPhase.java b/sources/scalac/transformer/AddInterfacesPhase.java
index aa2eb23ebb..60c8ef441d 100644
--- a/sources/scalac/transformer/AddInterfacesPhase.java
+++ b/sources/scalac/transformer/AddInterfacesPhase.java
@@ -256,6 +256,12 @@ public class AddInterfacesPhase extends Phase {
classSym));
ifaceToClass.put(ifaceSym, classSym);
classToIFace.put(classSym, ifaceSym);
+
+ // move attributes to the implementing class
+ AttributeInfo attr = global.removeAttributes(ifaceSym);
+ if (attr != null) {
+ global.setAttribute(classSym, attr);
+ }
}
return classSym;
}