summaryrefslogtreecommitdiff
path: root/sources
diff options
context:
space:
mode:
authorburaq <buraq@epfl.ch>2004-05-18 10:42:03 +0000
committerburaq <buraq@epfl.ch>2004-05-18 10:42:03 +0000
commit00048f2901012137789f0af5ff5d733a581fc90e (patch)
tree8750463a865285bd54d2a0842a0e7331f026176e /sources
parent7432218075b602548bb109fac463077ddc50befd (diff)
downloadscala-00048f2901012137789f0af5ff5d733a581fc90e.tar.gz
scala-00048f2901012137789f0af5ff5d733a581fc90e.tar.bz2
scala-00048f2901012137789f0af5ff5d733a581fc90e.zip
case classes implement trait scala.CaseClass
Diffstat (limited to 'sources')
-rw-r--r--sources/meta/scalac/ast/Tree.java2
-rw-r--r--sources/scala/CaseClass.scala26
-rw-r--r--sources/scala/tools/scalac/ast/parser/Parser.scala13
-rw-r--r--sources/scala/tools/scalac/typechecker/DeSugarize.scala2
-rw-r--r--sources/scalac/typechecker/RefCheck.java41
-rw-r--r--sources/scalac/util/Names.java4
6 files changed, 81 insertions, 7 deletions
diff --git a/sources/meta/scalac/ast/Tree.java b/sources/meta/scalac/ast/Tree.java
index 8df7d2221d..bb59069140 100644
--- a/sources/meta/scalac/ast/Tree.java
+++ b/sources/meta/scalac/ast/Tree.java
@@ -276,7 +276,7 @@ public class Tree {
n_Switch.
setDescription("Switch").
- setRange(Phase.TRANSMATCH, Phase.END).
+ setRange(Phase.REFCHECK, Phase.END).
addField(t_TermTree, "test").
addField(t_ints, "tags").
addField(t_TermTrees, "bodies").
diff --git a/sources/scala/CaseClass.scala b/sources/scala/CaseClass.scala
new file mode 100644
index 0000000000..2e6306138b
--- /dev/null
+++ b/sources/scala/CaseClass.scala
@@ -0,0 +1,26 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala;
+
+/** defines an access function for instances of case classes.
+ *
+ * @author Burak Emir
+ */
+trait CaseClass {
+
+ /** for a case class A(x1,...,xk), returns x_i for 1<= i <= k, null otherwise
+ */
+ def selectElement(n:int):Any = null;
+
+ /** for a case class A(x1,...,xk), returns k
+ */
+ def numberOfElements(): int = 0;
+
+}
diff --git a/sources/scala/tools/scalac/ast/parser/Parser.scala b/sources/scala/tools/scalac/ast/parser/Parser.scala
index 09e07f7312..6f4df2bd00 100644
--- a/sources/scala/tools/scalac/ast/parser/Parser.scala
+++ b/sources/scala/tools/scalac/ast/parser/Parser.scala
@@ -257,6 +257,10 @@ class Parser(unit: Unit) {
make.Apply(
pos, scalaDot(pos, Names.ScalaObject.toTypeName()), Tree.EMPTY_ARRAY);
+ def caseClassConstr(pos: int): Tree =
+ make.Apply(
+ pos, scalaDot(pos, Names.CaseClass.toTypeName()), Tree.EMPTY_ARRAY);
+
/** Create tree for for-comprehension <for (enums) do body> or
* <for (enums) yield body> where mapName and flatmapName are chosen
* corresponding to whether this is a for-do or a for-yield.
@@ -1859,7 +1863,7 @@ class Parser(unit: Unit) {
paramClauseOpt()));
} while (s.token == COMMA);
val thistpe = simpleTypedOpt();
- val template = classTemplate();
+ val template = classTemplate( mods );
val ts = new myTreeList();
lhs foreach { case Tuple4(p, n, tp, vp) =>
ts.append(
@@ -1879,7 +1883,7 @@ class Parser(unit: Unit) {
lhs.append(Pair(s.pos, ident()));
} while (s.token == COMMA);
val thistpe = simpleTypedOpt();
- val template = classTemplate();
+ val template = classTemplate( mods );
val ts = new myTreeList();
lhs foreach { case Pair(p, n) =>
ts.append(
@@ -1892,7 +1896,7 @@ class Parser(unit: Unit) {
/** ClassTemplate ::= [`extends' Constr] {`with' Constr} [TemplateBody]
*/
- def classTemplate(): Tree$Template = {
+ def classTemplate( mods:int ): Tree$Template = {
val pos = s.pos;
val parents = new myTreeList();
if (s.token == EXTENDS) {
@@ -1902,6 +1906,9 @@ class Parser(unit: Unit) {
parents.append(scalaAnyRefConstr(pos));
}
parents.append(scalaObjectConstr(pos));
+ if( (mods & Modifiers.CASE) != 0 ) {
+ parents.append(caseClassConstr(pos));
+ }
if (s.token == WITH) {
s.nextToken();
template(parents)
diff --git a/sources/scala/tools/scalac/typechecker/DeSugarize.scala b/sources/scala/tools/scalac/typechecker/DeSugarize.scala
index ae21fac622..11cd558573 100644
--- a/sources/scala/tools/scalac/typechecker/DeSugarize.scala
+++ b/sources/scala/tools/scalac/typechecker/DeSugarize.scala
@@ -609,7 +609,7 @@ class DeSugarize(make: TreeFactory, copy: TreeCopier, gen: TreeGen, infer: scala
.setSymbol(vparam.symbol())));
}
- /** add case constructor, defintiions value and access functions.
+ /** add case constructor, definitions value and access functions.
*/
def addCaseElements(body: Array[Tree], vparams: Array[Tree$ValDef]): Array[Tree] = {
val stats: TreeList = new TreeList();
diff --git a/sources/scalac/typechecker/RefCheck.java b/sources/scalac/typechecker/RefCheck.java
index a96a21fd0a..455bcd3f15 100644
--- a/sources/scalac/typechecker/RefCheck.java
+++ b/sources/scalac/typechecker/RefCheck.java
@@ -29,8 +29,9 @@ import Tree.*;
* It preforms the following transformations.
*
* - Local modules are replaced by variables and classes
- * - toString, equals, and hashCode methods are added to case classes, unless
- * they are defined in the class or a baseclass different from java.lang.Object
+ * - equals, and hashCode, selectElement and toString methods are added to
+ * case classes, unless they are defined in the class or a baseclass
+ * different from java.lang.Object
* - Calls to case factory methods are replaced by new's.
* - Type nodes are replaced by TypeTerm nodes.
* - Eliminate constant definitions
@@ -687,6 +688,39 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
return gen.DefDef(toStringSym, body);
}
+ private Tree selectElementMethod( ClassSymbol clazz ) {
+ Symbol seSym = clazz.newMethod( clazz.pos, OVERRIDE, Names.selectElement );
+ Symbol seParam = seSym.newVParam(
+ clazz.pos, 0, Names.n, defs.INT_TYPE());
+ seSym.setInfo(
+ Type.MethodType( new Symbol[]{ seParam }, defs.ANY_TYPE() ));
+ clazz.info().members().enter( seSym );
+ Tree[] fields = caseFields( clazz );
+ Tree body;
+ if( fields.length > 0) { // switch< n >
+ int tags[] = new int[ fields.length ];
+ int i = 0; while( i < fields.length ) { tags[i] = ++i; };
+ body = gen.Switch( gen.mkLocalRef( clazz.pos, seParam ),
+ tags,
+ fields,
+ gen.mkNullLit( clazz.pos ),
+ defs.ANY_TYPE() );
+ }
+ else
+ body = gen.mkNullLit( clazz.pos );
+ return gen.DefDef(seSym, body);
+ }
+
+ private Tree numberOfElementsMethod( ClassSymbol clazz ) {
+ Symbol seSym = clazz.newMethod( clazz.pos, OVERRIDE, Names.numberOfElements );
+ seSym.setInfo(
+ Type.MethodType( Symbol.EMPTY_ARRAY, defs.INT_TYPE() ));
+ clazz.info().members().enter( seSym );
+ Tree[] fields = caseFields( clazz );
+ return gen.DefDef(seSym, gen.mkIntLit( clazz.pos, fields.length ));
+ }
+
+
private Tree equalsMethod(ClassSymbol clazz) {
Symbol equalsSym = clazz.newMethod(clazz.pos, OVERRIDE, Names.equals);
Symbol equalsParam = equalsSym.newVParam(
@@ -823,6 +857,9 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
ts.append(equalsMethod(clazz));
if (!hasImplementation(clazz, Names.hashCode))
ts.append(hashCodeMethod(clazz));
+
+ ts.append(selectElementMethod(clazz));
+ ts.append(numberOfElementsMethod(clazz));
ts.append(tagMethod(clazz));
if (ts.length() > 0) {
Tree[] stats1 = new Tree[stats.length + ts.length()];
diff --git a/sources/scalac/util/Names.java b/sources/scalac/util/Names.java
index 87858f395c..619ddf5b07 100644
--- a/sources/scalac/util/Names.java
+++ b/sources/scalac/util/Names.java
@@ -106,6 +106,7 @@ public class Names {
public static final Name AnyRef = Name.fromString("AnyRef");
public static final Name Array = Name.fromString("Array");
public static final Name Byte = Name.fromString("Byte");
+ public static final Name CaseClass = Name.fromString("CaseClass");
public static final Name Catch = Name.fromString("Catch");
public static final Name Char = Name.fromString("Char");
public static final Name Boolean = Name.fromString("Boolean");
@@ -164,9 +165,11 @@ public class Names {
public static final Name length = Name.fromString("length");
public static final Name match = Name.fromString("match");
public static final Name map = Name.fromString("map");
+ public static final Name n = Name.fromString("n");
public static final Name nobinding = Name.fromString("nobinding");
public static final Name next = Name.fromString("next");
public static final Name newArray = Name.fromString("newArray");
+ public static final Name numberOfElements = Name.fromString("numberOfElements");
public static final Name null_ = Name.fromString("null");
public static final Name predef = Name.fromString("predef");
public static final Name print = Name.fromString("print");
@@ -176,6 +179,7 @@ public class Names {
public static final Name synchronized_ = Name.fromString("synchronized");
public static final Name eq = Name.fromString("eq");
public static final Name equals = Name.fromString("equals");
+ public static final Name selectElement = Name.fromString("selectElement");
public static final Name tail = Name.fromString("tail");
public static final Name toString = Name.fromString("toString");
public static final Name that = Name.fromString("that");