summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2004-07-15 16:20:37 +0000
committerMartin Odersky <odersky@gmail.com>2004-07-15 16:20:37 +0000
commit83f49b9bebb04a55a45722594e717d95468924ac (patch)
tree056e5855759dfffb38d280cc886631344466476c
parent5c1a325f05a3c14623dbcbf643dfa0dc6f8bc81e (diff)
downloadscala-83f49b9bebb04a55a45722594e717d95468924ac.tar.gz
scala-83f49b9bebb04a55a45722594e717d95468924ac.tar.bz2
scala-83f49b9bebb04a55a45722594e717d95468924ac.zip
*** empty log message ***
-rw-r--r--config/list/compiler.lst8
-rw-r--r--config/list/library.lst5
-rw-r--r--doc/reference/ReferencePart.tex17
-rw-r--r--sources/examples/monads/callccInterpreter.scala84
-rw-r--r--sources/examples/monads/directInterpreter.scala55
-rw-r--r--sources/examples/monads/errorInterpreter.scala85
-rw-r--r--sources/examples/monads/simpleInterpreter.scala74
-rw-r--r--sources/meta/scalac/ast/Tree.java7
-rw-r--r--sources/scala/Attribute.scala13
-rw-r--r--sources/scala/SerialVersionUID.scala12
-rw-r--r--sources/scala/Serializable.scala12
-rw-r--r--sources/scala/tools/scalac/ast/parser/Parser.scala40
-rw-r--r--sources/scala/tools/scalac/ast/parser/Scanner.scala8
-rw-r--r--sources/scala/tools/scalac/ast/printer/TextTreePrinter.scala7
-rw-r--r--sources/scala/tools/scalac/typechecker/Analyzer.scala45
-rw-r--r--sources/scala/transient.scala12
-rw-r--r--sources/scala/volatile.scala12
-rw-r--r--sources/scalac/Global.java4
-rw-r--r--sources/scalac/symtab/Definitions.java6
-rw-r--r--sources/scalac/symtab/classfile/ClassfileParser.java4
-rw-r--r--sources/scalac/symtab/classfile/UnPickle.java11
-rw-r--r--test/files/pos/bug287.scala12
-rw-r--r--test/files/pos/bug342.scala9
23 files changed, 523 insertions, 19 deletions
diff --git a/config/list/compiler.lst b/config/list/compiler.lst
index 2a9922180f..b340896ff3 100644
--- a/config/list/compiler.lst
+++ b/config/list/compiler.lst
@@ -113,8 +113,8 @@ transformer/MakeBoxingExplicitPhase.java
transformer/OwnerTransformer.java
transformer/TailCallPhase.java
transformer/TypesAsValuesPhase.java
-transformer/UnCurry.java
-transformer/UnCurryPhase.java
+# transformer/UnCurry.java
+# transformer/UnCurryPhase.java
transformer/matching/AlgebraicMatcher.java
transformer/matching/Autom2Scala.java
@@ -143,8 +143,8 @@ transformer/matching/WordAutomInScala.java
typechecker/AnalyzerPhase.java
typechecker/Infer.java
-typechecker/RefCheck.java
-typechecker/RefCheckPhase.java
+# typechecker/RefCheck.java
+# typechecker/RefCheckPhase.java
util/AbstractFileReader.java
util/ArrayApply.java
diff --git a/config/list/library.lst b/config/list/library.lst
index 2200a49e59..9a3855d91f 100644
--- a/config/list/library.lst
+++ b/config/list/library.lst
@@ -5,6 +5,7 @@
AnyVal.java
Array.java
+Attribute.scala
Boolean.java
BufferedIterator.scala
Byte.java
@@ -44,6 +45,8 @@ Ref.java
ScalaObject.java
Seq.scala
SeqProxy.scala
+Serializable.scala
+SerialVersionUID.scala
Short.java
Some.scala
Stream.scala
@@ -59,6 +62,8 @@ Tuple8.scala
Tuple9.scala
Type.java
Unit.java
+transient.scala
+volatile.scala
collection/Map.scala
collection/MapProxy.scala
diff --git a/doc/reference/ReferencePart.tex b/doc/reference/ReferencePart.tex
index 79b4cdf146..8cb834a026 100644
--- a/doc/reference/ReferencePart.tex
+++ b/doc/reference/ReferencePart.tex
@@ -57,19 +57,20 @@ which are in none of the sets above, mathematical symbols(Sm) and other symbols(
\syntax\begin{lstlisting}
op ::= special {special}
-varid ::= lower {letter $|$ digit} [`_' {digit} [id]]
-id ::= upper {letter $|$ digit} [`_' {digit} [id]]
+varid ::= lower idrest
+id ::= upper idrest
| varid
| op
| ```string chars`''
+idrest ::= {letter $|$ digit} {'_' (op | idrest)}
\end{lstlisting}
There are three ways to form an identifier. First, an identifier can
start with a letter which can be followed by an arbitrary sequence of
-letters and digits. This may be followed by an underscore
-`\lstinline@_@' character and another string of characters that by
-themselves make up an identifier. Second, an identifier can start
-with a special character followed by an arbitrary sequence of special
+letters and digits. This may be followed by underscore `\lstinline@_@'
+characters and other string composed of either letters and digits or
+of special characeters. Second, an identifier can start with a
+special character followed by an arbitrary sequence of special
characters. Finally, an identifier may also be formed by an arbitrary
string between back-quotes (host systems may impose some restrictions
on which strings are legal for identifiers). As usual, a longest
@@ -767,8 +768,8 @@ transitive relation that satisfies the following conditions.
$(T'_1 \commadots T'_n) U'$.
\item If, assuming
$L'_1 \conforms a_1 \conforms U'_1 \commadots L'_n \conforms a_n \conforms U'_n$
-one has $L'_i \equiv L'_i$ and $U_i \equiv U'_i$
-for $i = 1 \commadots n$, as well as $T \conforms T'$ then the polymorphic type
+one has $L_i \conforms L'_i$ and $U'_i \conforms U_i$
+for $i = 1 \commadots n$, as well as $T \conforms T'$, then the polymorphic type
$[a_1 >: L_1 <: U_1 \commadots a_n >: L_n <: U_n] T$ conforms to the polymorphic type
$[a_1 >: L'_1 <: U'_1 \commadots a_n >: L'_n <: U'_n] T'$.
\item
diff --git a/sources/examples/monads/callccInterpreter.scala b/sources/examples/monads/callccInterpreter.scala
new file mode 100644
index 0000000000..934fce1a9e
--- /dev/null
+++ b/sources/examples/monads/callccInterpreter.scala
@@ -0,0 +1,84 @@
+object callccInterpreter {
+
+ type Answer = Value;
+
+ case class M[A](in: (A => Answer) => Answer) {
+ def bind[B](k: A => M[B]) = M[B](c => in (a => k(a) in c));
+ def map[B](f: A => B): M[B] = bind(x => unitM(f(x)));
+ def flatMap[B](f: A => M[B]): M[B] = bind(f);
+ }
+
+ def unitM[A](a: A) = M[A](c => c(a));
+
+ def showM(m: M[Value]): String = (m in id).toString();
+
+ def callCC[A](h: (A => M[A]) => M[A]) =
+ M[A](c => h(a => M[A](d => c(a))) in c);
+
+ type Name = String;
+
+ trait Term;
+ case class Var(x: Name) extends Term;
+ case class Con(n: int) extends Term;
+ case class Add(l: Term, r: Term) extends Term;
+ case class Lam(x: Name, body: Term) extends Term;
+ case class App(fun: Term, arg: Term) extends Term;
+ case class Ccc(x: Name, t: Term) extends Term;
+
+ trait Value;
+ case object Wrong extends Value {
+ override def toString() = "wrong"
+ }
+ case class Num(n: int) extends Value {
+ override def toString() = n.toString();
+ }
+ case class Fun(f: Value => M[Value]) extends Value {
+ override def toString() = "<function>"
+ }
+
+ type Environment = List[Pair[Name, Value]];
+
+ def lookup(x: Name, e: Environment): M[Value] = e match {
+ case List() => unitM(Wrong)
+ case Pair(y, b) :: e1 => if (x == y) unitM(b) else lookup(x, e1)
+ }
+
+ def add(a: Value, b: Value): M[Value] = Pair(a, b) match {
+ case Pair(Num(m), Num(n)) => unitM(Num(m + n))
+ case _ => unitM(Wrong)
+ }
+
+ def apply(a: Value, b: Value): M[Value] = a match {
+ case Fun(k) => k(b)
+ case _ => unitM(Wrong)
+ }
+
+ def interp(t: Term, e: Environment): M[Value] = t match {
+ case Var(x) => lookup(x, e)
+ case Con(n) => unitM(Num(n))
+ case Add(l, r) => for (val a <- interp(l, e);
+ val b <- interp(r, e);
+ val c <- add(a, b))
+ yield c
+ case Lam(x, t) => unitM(Fun(a => interp(t, Pair(x, a) :: e)))
+ case App(f, t) => for (val a <- interp(f, e);
+ val b <- interp(t, e);
+ val c <- apply(a, b))
+ yield c
+ case Ccc(x, t) => callCC(k => interp(t, Pair(x, Fun(k)) :: e))
+ }
+
+ def test(t: Term): String =
+ showM(interp(t, List()));
+
+ val term0 = App(Lam("x", Add(Var("x"), Var("x"))), Add(Con(10), Con(11)));
+ val term1 = App(Con(1), Con(2));
+ val term2 = Add(Con(1), Ccc("k", Add(Con(2), App(Var("k"), Con(4)))));
+
+ def main(args: Array[String]) = {
+ System.out.println(test(term0));
+ System.out.println(test(term1));
+ System.out.println(test(term2));
+ }
+}
+
diff --git a/sources/examples/monads/directInterpreter.scala b/sources/examples/monads/directInterpreter.scala
new file mode 100644
index 0000000000..0e2aae4a7b
--- /dev/null
+++ b/sources/examples/monads/directInterpreter.scala
@@ -0,0 +1,55 @@
+object directInterpreter {
+
+ type Name = String;
+
+ trait Term;
+ case class Var(x: Name) extends Term;
+ case class Con(n: int) extends Term;
+ case class Add(l: Term, r: Term) extends Term;
+ case class Lam(x: Name, body: Term) extends Term;
+ case class App(fun: Term, arg: Term) extends Term;
+
+ trait Value;
+ case object Wrong extends Value;
+ case class Num(n: int) extends Value;
+ case class Fun(f: Value => Value)extends Value;
+
+ def showval(v: Value): String = v match {
+ case Wrong => "<wrong>"
+ case Num(n) => n.toString()
+ case Fun(f) => "<function>"
+ }
+
+ type Environment = List[Pair[Name, Value]];
+
+ def lookup(x: Name, e: Environment): Value = e match {
+ case List() => Wrong
+ case Pair(y, b) :: e1 => if (x == y) b else lookup(x, e1)
+ }
+
+ def add(a: Value, b: Value): Value = Pair(a, b) match {
+ case Pair(Num(m), Num(n)) => Num(m + n)
+ case _ => Wrong
+ }
+
+ def apply(a: Value, b: Value) = a match {
+ case Fun(k) => k(b)
+ case _ => Wrong
+ }
+
+ def interp(t: Term, e: Environment): Value = t match {
+ case Var(x) => lookup(x, e)
+ case Con(n) => Num(n)
+ case Add(l, r) => add(interp(l, e), interp(r, e))
+ case Lam(x, t) => Fun(a => interp(t, Pair(x, a) :: e))
+ case App(f, t) => apply(interp(f, e), interp(t, e))
+ }
+
+ def test(t: Term): String =
+ showval(interp(t, List()));
+
+ val term0 = App(Lam("x", Add(Var("x"), Var("x"))), Add(Con(10), Con(11)));
+
+ def main(args: Array[String]) =
+ System.out.println(test(term0));
+}
diff --git a/sources/examples/monads/errorInterpreter.scala b/sources/examples/monads/errorInterpreter.scala
new file mode 100644
index 0000000000..d797f01a4d
--- /dev/null
+++ b/sources/examples/monads/errorInterpreter.scala
@@ -0,0 +1,85 @@
+object errorInterpreter {
+
+ trait M[A] {
+ def show: String;
+ def bind[B](k: A => M[B]);
+ def map[B](f: A => B): M[B] = bind(x => unitM(f(x)));
+ def flatMap[B](f: A => M[B]): M[B] = bind(f);
+ }
+
+ def unitM[A](a: A): M[A] = new Suc(a);
+ def errorM[A](msg: String): M[A] = new Err(msg);
+
+ def showM(m: M[Value]): String = m.show;
+
+ class Suc[A](x: T) extends M[A] {
+ def bind[A](k: A => M[B]): M[B] = k(x);
+ def show: String = "Success: " + x;
+ }
+ class Err[T](msg: String) extends M[T] {
+ def bind[A](k: A => M[B]): M[B] = new Err(msg);
+ def show: String = "Error: " + msg;
+ }
+
+ type Name = String;
+
+ trait Term;
+ case class Var(x: Name) extends Term;
+ case class Con(n: int) extends Term;
+ case class Add(l: Term, r: Term) extends Term;
+ case class Lam(x: Name, body: Term) extends Term;
+ case class App(fun: Term, arg: Term) extends Term;
+
+ trait Value;
+ case object Wrong extends Value {
+ override def toString() = "wrong"
+ }
+ case class Num(n: int) extends Value {
+ override def toString() = n.toString();
+ }
+ case class Fun(f: Value => M[Value]) extends Value {
+ override def toString() = "<function>"
+ }
+
+ type Environment = List[Pair[Name, Value]];
+
+ def lookup(x: Name, e: Environment): M[Value] = e match {
+ case List() => errorM("unbound variable: " + x);
+ case Pair(y, b) :: e1 => if (x == y) unitM(b) else lookup(x, e1)
+ }
+
+ def add(a: Value, b: Value): M[Value] = Pair(a, b) match {
+ case Pair(Num(m), Num(n)) => unitM(Num(m + n))
+ case _ => errorM("should be numbers: " + a + "," + b)
+ }
+
+ def apply(a: Value, b: Value): M[Value] = a match {
+ case Fun(k) => k(b)
+ case _ => errorM("should be function: " + a);
+ }
+
+ def interp(t: Term, e: Environment): M[Value] = t match {
+ case Var(x) => lookup(x, e)
+ case Con(n) => unitM(Num(n))
+ case Add(l, r) => for (val a <- interp(l, e);
+ val b <- interp(r, e);
+ val c <- add(a, b))
+ yield c
+ case Lam(x, t) => unitM(Fun(a => interp(t, Pair(x, a) :: e)))
+ case App(f, t) => for (val a <- interp(f, e);
+ val b <- interp(t, e);
+ val c <- apply(a, b))
+ yield c
+ }
+
+ def test(t: Term): String =
+ showM(interp(t, List()));
+
+ val term0 = App(Lam("x", Add(Var("x"), Var("x"))), Add(Con(10), Con(11)));
+ val term1 = App(Con(1), Con(2));
+
+ def main(args: Array[String]) = {
+ System.out.println(test(term0));
+ System.out.println(test(term1));
+ }
+}
diff --git a/sources/examples/monads/simpleInterpreter.scala b/sources/examples/monads/simpleInterpreter.scala
new file mode 100644
index 0000000000..07da5f40ab
--- /dev/null
+++ b/sources/examples/monads/simpleInterpreter.scala
@@ -0,0 +1,74 @@
+object simpleInterpreter {
+
+ case class M[A](value: A) {
+ def bind[B](k: A => M[B]): M[B] = k(value);
+ def map[B](f: A => B): M[B] = bind(x => unitM(f(x)));
+ def flatMap[B](f: A => M[B]): M[B] = bind(f);
+ }
+
+ def unitM[A](a: A): M[A] = M(a);
+
+ def showM(m: M[Value]): String = m.value.toString();
+
+ type Name = String;
+
+ trait Term;
+ case class Var(x: Name) extends Term;
+ case class Con(n: int) extends Term;
+ case class Add(l: Term, r: Term) extends Term;
+ case class Lam(x: Name, body: Term) extends Term;
+ case class App(fun: Term, arg: Term) extends Term;
+
+ trait Value;
+ case object Wrong extends Value {
+ override def toString() = "wrong"
+ }
+ case class Num(n: int) extends Value {
+ override def toString() = n.toString();
+ }
+ case class Fun(f: Value => M[Value]) extends Value {
+ override def toString() = "<function>"
+ }
+
+ type Environment = List[Pair[Name, Value]];
+
+ def lookup(x: Name, e: Environment): M[Value] = e match {
+ case List() => unitM(Wrong)
+ case Pair(y, b) :: e1 => if (x == y) unitM(b) else lookup(x, e1)
+ }
+
+ def add(a: Value, b: Value): M[Value] = Pair(a, b) match {
+ case Pair(Num(m), Num(n)) => unitM(Num(m + n))
+ case _ => unitM(Wrong)
+ }
+
+ def apply(a: Value, b: Value): M[Value] = a match {
+ case Fun(k) => k(b)
+ case _ => unitM(Wrong)
+ }
+
+ def interp(t: Term, e: Environment): M[Value] = t match {
+ case Var(x) => lookup(x, e)
+ case Con(n) => unitM(Num(n))
+ case Add(l, r) => for (val a <- interp(l, e);
+ val b <- interp(r, e);
+ val c <- add(a, b))
+ yield c
+ case Lam(x, t) => unitM(Fun(a => interp(t, Pair(x, a) :: e)))
+ case App(f, t) => for (val a <- interp(f, e);
+ val b <- interp(t, e);
+ val c <- apply(a, b))
+ yield c
+ }
+
+ def test(t: Term): String =
+ showM(interp(t, List()));
+
+ val term0 = App(Lam("x", Add(Var("x"), Var("x"))), Add(Con(10), Con(11)));
+ val term1 = App(Con(1), Con(2));
+
+ def main(args: Array[String]) = {
+ System.out.println(test(term0));
+ System.out.println(test(term1));
+ }
+}
diff --git a/sources/meta/scalac/ast/Tree.java b/sources/meta/scalac/ast/Tree.java
index bb59069140..492461bc59 100644
--- a/sources/meta/scalac/ast/Tree.java
+++ b/sources/meta/scalac/ast/Tree.java
@@ -71,6 +71,7 @@ public class Tree {
public final TreeNode
n_Empty = node("Empty" , Any , NoSym),
+ n_Attributed = node("Attributed" , None, NoSym),
n_DocDef = node("DocDef" , None, NoSym),
n_ClassDef = node("ClassDef" , None, DefSym),
n_PackageDef = node("PackageDef" , None, NoSym),
@@ -127,6 +128,12 @@ public class Tree {
setRange(Phase.PARSER, Phase.UNKNOWN).
noFields();
+ n_Attributed.
+ setDescription("Attributed definition").
+ setRange(Phase.PARSER, Phase.ANALYZER).
+ addField(t_Tree, "attribute").
+ addField(t_Tree, "definition");
+
n_DocDef.
setDescription("Documented definition").
setRange(Phase.PARSER, Phase.ANALYZER).
diff --git a/sources/scala/Attribute.scala b/sources/scala/Attribute.scala
new file mode 100644
index 0000000000..afd8c02b36
--- /dev/null
+++ b/sources/scala/Attribute.scala
@@ -0,0 +1,13 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id: Attribute.scala
+*/
+package scala;
+
+/** A base class for attributes
+*/
+class Attribute {}
diff --git a/sources/scala/SerialVersionUID.scala b/sources/scala/SerialVersionUID.scala
new file mode 100644
index 0000000000..dab477a7b0
--- /dev/null
+++ b/sources/scala/SerialVersionUID.scala
@@ -0,0 +1,12 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id: Attribute.scala
+*/
+package scala;
+
+case class SerialVersionUID(uid: long) extends Attribute {}
+
diff --git a/sources/scala/Serializable.scala b/sources/scala/Serializable.scala
new file mode 100644
index 0000000000..d123a82f12
--- /dev/null
+++ b/sources/scala/Serializable.scala
@@ -0,0 +1,12 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id: Attribute.scala
+*/
+package scala;
+
+class Serializable extends Attribute {}
+
diff --git a/sources/scala/tools/scalac/ast/parser/Parser.scala b/sources/scala/tools/scalac/ast/parser/Parser.scala
index 60111dd803..4cf476ac82 100644
--- a/sources/scala/tools/scalac/ast/parser/Parser.scala
+++ b/sources/scala/tools/scalac/ast/parser/Parser.scala
@@ -157,7 +157,7 @@ class Parser(unit: CompilationUnit) {
false;
}
-/////// COMMENT COLLECTION ///////////////////////////////////////////////////
+/////// COMMENT AND ATTRIBUTE COLLECTION //////////////////////////////////////
/** Stack of comments
*/
@@ -2006,8 +2006,12 @@ class Parser(unit: CompilationUnit) {
s.token == TRAIT ||
s.token == OBJECT ||
s.token == CASEOBJECT ||
+ s.token == LBRACKET ||
isModifier()) {
- stats.append(joinComment(clsDef(modifiers())));
+ stats.append(
+ joinAttributes(
+ attributes(),
+ joinComment(clsDef(modifiers()))));
} else if (s.token != SEMI) {
syntaxError("illegal start of class or object definition", true);
}
@@ -2030,8 +2034,11 @@ class Parser(unit: CompilationUnit) {
stats.append(importClause());
} else if (isExprIntro()) {
stats.append(expr());
- } else if (isDefIntro() || isModifier()) {
- stats.append(joinComment(defOrDcl(modifiers())));
+ } else if (isDefIntro() || isModifier() || s.token == LBRACKET) {
+ stats.append(
+ joinAttributes(
+ attributes(),
+ joinComment(defOrDcl(modifiers()))))
} else if (s.token != SEMI) {
syntaxError("illegal start of definition", true);
}
@@ -2040,6 +2047,31 @@ class Parser(unit: CompilationUnit) {
stats.toArray()
}
+ def attributes(): List[Tree] = {
+ var attrs: List[Tree] = List();
+ while (s.token == LBRACKET) {
+ s.nextToken();
+ attrs = constr() :: attrs;
+ while (s.token == COMMA) {
+ s.nextToken();
+ attrs = constr() :: attrs;
+ }
+ accept(RBRACKET);
+ }
+ attrs
+ }
+
+ def joinAttributes(attrs: List[Tree], defs: Array[Tree]): Array[Tree] = attrs match {
+ case List() =>
+ defs
+ case attr :: attrs1 =>
+ var i = 0; while (i < defs.length) {
+ defs(i) = make.Attributed(attr.pos, attr, defs(i));
+ i = i + 1;
+ }
+ joinAttributes(attrs1, defs)
+ }
+
/** RefineStatSeq ::= RefineStat {`;' RefineStat}
* RefineStat ::= Dcl
* | type TypeDef
diff --git a/sources/scala/tools/scalac/ast/parser/Scanner.scala b/sources/scala/tools/scalac/ast/parser/Scanner.scala
index bbb0e148d9..007403b169 100644
--- a/sources/scala/tools/scalac/ast/parser/Scanner.scala
+++ b/sources/scala/tools/scalac/ast/parser/Scanner.scala
@@ -628,8 +628,12 @@ class Scanner(_unit: CompilationUnit) extends TokenData {
def treatIdent = {
name = Name.fromString( cbuf.toString() );
- token = name2token( name );
- cbuf.setLength( 0 );;
+/* not yet!
+ if (name.length() > 1 && name.charAt(name.length() - 1) == '_')
+ syntaxError("identifier may not end in a '_'");
+*/
+ token = name2token(name);
+ cbuf.setLength(0);
}
/** generate an error at the given position
diff --git a/sources/scala/tools/scalac/ast/printer/TextTreePrinter.scala b/sources/scala/tools/scalac/ast/printer/TextTreePrinter.scala
index 6d1982c948..bc590cbfdd 100644
--- a/sources/scala/tools/scalac/ast/printer/TextTreePrinter.scala
+++ b/sources/scala/tools/scalac/ast/printer/TextTreePrinter.scala
@@ -226,6 +226,13 @@ class TextTreePrinter(writer: PrintWriter) with TreePrinter {
case Tree.Empty =>
print(TXT_EMPTY);
+ case Tree$Attributed(attr, definition) =>
+ print(TXT_LEFT_BRACKET);
+ print(attr);
+ print(TXT_RIGHT_BRACKET);
+ printNewLine();
+ print(definition);
+
case Tree$DocDef(comment, definition) =>
print(comment);
printNewLine();
diff --git a/sources/scala/tools/scalac/typechecker/Analyzer.scala b/sources/scala/tools/scalac/typechecker/Analyzer.scala
index 81ef8f414f..4a62d8cdef 100644
--- a/sources/scala/tools/scalac/typechecker/Analyzer.scala
+++ b/sources/scala/tools/scalac/typechecker/Analyzer.scala
@@ -57,6 +57,8 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
var unit: CompilationUnit = _;
+ type AttrInfo = Pair/*<Symbol, Array[AConstant]>*/;
+
override def apply(units: Array[CompilationUnit]): unit = {
var i = 0; while (i < units.length) {
enterUnit(units(i));
@@ -839,6 +841,7 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
}
def outerEnterSym(tree: Tree): Symbol = enterSym(tree);
+
/** If `tree' is a definition, create a symbol for it with a lazily
* constructed type, and enter into current scope.
*/
@@ -899,6 +902,9 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
throw new ApplicationError();
}
+ case Tree$Attributed(attr, definition) =>
+ outerEnterSym(definition);
+
case Tree$DocDef(comment, definition) =>
val sym = outerEnterSym(definition);
global.mapSymbolComment.put(sym, new Pair(comment, unit));
@@ -1581,6 +1587,13 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
if (pt.symbol() == definitions.UNIT_CLASS) {
return gen.mkUnitBlock(tree);
} else if (infer.isCompatible(tree.getType(), pt)) {
+ tree match {
+ case Tree$Literal(value) =>
+ val value1 = constfold.cast(value, pt);
+ if (value1 != null)
+ return adapt(gen.Literal(tree.pos, value1), mode, pt);
+ case _ =>
+ }
val v = infer.bestView(tree.getType(), pt, Names.EMPTY);
if (v != null) return applyView(v, tree, mode, pt);
// todo: remove
@@ -2153,6 +2166,38 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
case Tree.Empty =>
tree.setType(Type.NoType)
+ case Tree$Attributed(attr, definition) =>
+
+ def attrInfo(attr: Tree): AttrInfo = attr match {
+ case Tree$Ident(_) | Tree$Select(_, _) =>
+ new Pair(attr.symbol(), new Array[AConstant](0))
+ case Tree$Apply(fn, args) =>
+ new Pair(attrInfo(fn).fst, attrArgInfos(args))
+ case _ =>
+ unit.error(attr.pos, "malformed attribute");
+ new Pair(Symbol.NONE.newErrorClass(errorName(attr).toTypeName()),
+ new Array[AConstant](0))
+ }
+
+ def attrArgInfos(args: Array[Tree]): Array[AConstant] = {
+ val infos = new Array[AConstant](args.length);
+ var i = 0; while (i < args.length) {
+ args(i) match {
+ case Tree$Literal(value) => infos(i) = value;
+ case _ => unit.error(args(i).pos,
+ "attribute argument needs to be a constant; found: " + args(i) + " " + args(i).getClass());
+ }
+ i = i + 1
+ }
+ infos
+ }
+
+ val attr1 = transform(attr, CONSTRmode, definitions.ATTRIBUTE_TYPE());
+ var attrs = global.mapSymbolAttr.get(sym).asInstanceOf[List[AttrInfo]];
+ if (attrs == null) attrs = List();
+ global.mapSymbolAttr.put(sym, attrInfo(attr1) :: attrs);
+ transform(definition)
+
case Tree$DocDef(comment, definition) =>
transform(definition)
diff --git a/sources/scala/transient.scala b/sources/scala/transient.scala
new file mode 100644
index 0000000000..3b25a6f390
--- /dev/null
+++ b/sources/scala/transient.scala
@@ -0,0 +1,12 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id: Attribute.scala
+*/
+package scala;
+
+class transient extends Attribute {}
+
diff --git a/sources/scala/volatile.scala b/sources/scala/volatile.scala
new file mode 100644
index 0000000000..54e62f103e
--- /dev/null
+++ b/sources/scala/volatile.scala
@@ -0,0 +1,12 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id: Attribute.scala
+*/
+package scala;
+
+class volatile extends Attribute {}
+
diff --git a/sources/scalac/Global.java b/sources/scalac/Global.java
index e164dec350..66d8d76506 100644
--- a/sources/scalac/Global.java
+++ b/sources/scalac/Global.java
@@ -119,6 +119,10 @@ public abstract class Global {
*/
public final Map/*<Symbol, String>*/ mapSymbolComment = new HashMap();
+ /** attributes of symbols
+ */
+ public final Map/*<Symbol, Pair<Symbol, AConstant[]>>*/ mapSymbolAttr = new HashMap();
+
/** views associated with (upper-bounded) type parameters
*/
public final Map/*<Symbol, Symbol>*/ viewOfTypeParam = new HashMap();
diff --git a/sources/scalac/symtab/Definitions.java b/sources/scalac/symtab/Definitions.java
index 9f4ff9cbe0..17fa1a5802 100644
--- a/sources/scalac/symtab/Definitions.java
+++ b/sources/scalac/symtab/Definitions.java
@@ -116,6 +116,7 @@ public class Definitions {
public final Symbol DOUBLE_CLASS;
public final Type DOUBLE_TYPE() {return DOUBLE_CLASS.staticType();}
+
//########################################################################
// Public Fields & Methods - Scala reference classes
@@ -123,6 +124,10 @@ public class Definitions {
public final Symbol SCALAOBJECT_CLASS;
public final Type SCALAOBJECT_TYPE() {return SCALAOBJECT_CLASS.staticType();}
+ /** The scala.Attribute class */
+ public final Symbol ATTRIBUTE_CLASS;
+ public final Type ATTRIBUTE_TYPE() {return ATTRIBUTE_CLASS.staticType();}
+
/** The scala.Ref class */
public final Symbol REF_CLASS;
public final Type REF_TYPE(Type element) {
@@ -660,6 +665,7 @@ public class Definitions {
// the scala reference classes
SCALAOBJECT_CLASS = getClass("scala.ScalaObject");
+ ATTRIBUTE_CLASS = getClass("scala.Attribute");
REF_CLASS = getClass("scala.Ref");
for (int i = 1; i < TUPLE_COUNT; i++) {
TUPLE_CLASS[i] = getClass("scala.Tuple" + i);
diff --git a/sources/scalac/symtab/classfile/ClassfileParser.java b/sources/scalac/symtab/classfile/ClassfileParser.java
index 073df39e90..f7186b886d 100644
--- a/sources/scalac/symtab/classfile/ClassfileParser.java
+++ b/sources/scalac/symtab/classfile/ClassfileParser.java
@@ -147,7 +147,9 @@ public class ClassfileParser implements ClassfileConstants {
int savedFlags = c.flags;
c.flags |= Modifiers.INITIALIZED;
// hack to make memberType in addInheritedOverloaded work
- addInheritedOverloaded();
+ if (global.currentPhase.id <= global.PHASE.REFCHECK.id() &&
+ !c.name.toString().endsWith("$class"))
+ addInheritedOverloaded();
//if (global.debug) {
// Symbol[] elems = c.members().elements();
diff --git a/sources/scalac/symtab/classfile/UnPickle.java b/sources/scalac/symtab/classfile/UnPickle.java
index fe11fced85..aa88139ad2 100644
--- a/sources/scalac/symtab/classfile/UnPickle.java
+++ b/sources/scalac/symtab/classfile/UnPickle.java
@@ -154,6 +154,17 @@ public class UnPickle implements Kinds, Modifiers, EntryTags, TypeTags {
else return "value " + NameTransformer.decode(name);
}
+ /*
+ void enterSymbol(Symbol sym) {
+ Symbol owner = sym.owner();
+ if (owner.kind == CLASS &&
+ !sym.isConstructor() && !sym.isModuleClass()) {
+ Scope scope = owner.info().members();
+ scope.enterOrOverload(sym);
+ }
+ }
+ */
+
void enterSymbol(Symbol sym) {
/*
if (global.debug) {
diff --git a/test/files/pos/bug287.scala b/test/files/pos/bug287.scala
new file mode 100644
index 0000000000..81a01951b2
--- /dev/null
+++ b/test/files/pos/bug287.scala
@@ -0,0 +1,12 @@
+object testBuf {
+ class mystream extends java.io.BufferedOutputStream(new java.io.FileOutputStream("/dev/null")) {
+ def w( x:String ):Unit = {
+ val foo = new Array[byte](2);
+
+ // write( byte[] ) is defined in FilterOutputStream, the superclass of BufferedOutputStream
+ super.write( foo ); // error
+
+ super.write( foo, 0, foo.length ); // this works however
+ }
+ }
+}
diff --git a/test/files/pos/bug342.scala b/test/files/pos/bug342.scala
new file mode 100644
index 0000000000..f7e318e0a8
--- /dev/null
+++ b/test/files/pos/bug342.scala
@@ -0,0 +1,9 @@
+object Main with Application {
+
+//object Foo extends Enumeration { // 1: OK !
+ object Foo extends Enumeration(0, "Bar") { // 2
+ val Bar = Value
+ }
+ import Foo._;
+ Console.println(Bar)
+}