summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sources/examples/fors.scala63
-rw-r--r--sources/examples/iterators.scala12
-rw-r--r--sources/examples/maps.scala152
-rw-r--r--sources/examples/parsers.scala53
-rw-r--r--sources/examples/parsers1.scala115
-rw-r--r--sources/examples/patterns.scala28
-rw-r--r--sources/examples/sort.scala27
-rw-r--r--sources/examples/sort1.scala12
-rw-r--r--sources/examples/sort2.scala12
-rw-r--r--sources/examples/typeinf.scala162
-rw-r--r--sources/scala/Iterator.scala2
-rw-r--r--sources/scala/List.scala10
-rw-r--r--sources/scala/Ord.scala8
-rw-r--r--sources/scala/PartialFunction.scala20
-rw-r--r--sources/scala/Predef.scala4
-rw-r--r--sources/scala/Stream.scala2
-rw-r--r--sources/scalac/ast/TreeGen.java4
-rw-r--r--sources/scalac/ast/parser/Parser.java27
-rw-r--r--sources/scalac/symtab/Definitions.java61
-rw-r--r--sources/scalac/symtab/Scope.java17
-rw-r--r--sources/scalac/symtab/Symbol.java132
-rw-r--r--sources/scalac/symtab/Type.java58
-rw-r--r--sources/scalac/symtab/classfile/AttributeParser.java2
-rw-r--r--sources/scalac/symtab/classfile/ClassfileParser.java2
-rw-r--r--sources/scalac/transformer/LambdaLiftPhase.java2
-rw-r--r--sources/scalac/typechecker/Analyzer.java143
-rw-r--r--sources/scalac/typechecker/DeSugarize.java87
-rw-r--r--sources/scalac/typechecker/RefCheck.java7
-rw-r--r--sources/scalac/util/Name.java4
-rw-r--r--sources/scalac/util/Names.java3
-rw-r--r--test/files/pos/List1.scala2
-rw-r--r--test/files/pos/lambda.scala2
-rw-r--r--test/pos/List1.scala2
-rw-r--r--test/pos/lambda.scala2
34 files changed, 1053 insertions, 186 deletions
diff --git a/sources/examples/fors.scala b/sources/examples/fors.scala
new file mode 100644
index 0000000000..55849f4010
--- /dev/null
+++ b/sources/examples/fors.scala
@@ -0,0 +1,63 @@
+module fors {
+
+ trait Person {
+ val name: String;
+ val age: Int;
+ }
+
+ def printOlderThan20(xs: Seq[Person]): Iterator[String] =
+ printOlderThan20(xs.elements);
+
+ def printOlderThan20(xs: Iterator[Person]): Iterator[String] =
+ for (val p <- xs; p.age > 20) yield p.name;
+
+ def divisors(n: Int): List[Int] =
+ for (val i <- List.range(1, n); n % i == 0) yield i;
+
+ def isPrime(n: Int) = divisors(n).length == 2;
+
+ def findNums(n: Int): Iterator[Pair[Int, Int]] =
+ for (val i <- Iterator.range(1, n);
+ val j <- Iterator.range(1, i-1);
+ isPrime(i+j)) yield Pair(i, j);
+
+ def sum(xs: List[Double]): Double =
+ (0.0 foldl_: xs) { (x, y) => x + y }
+
+ def scalProd(xs: List[Double], ys: List[Double]) =
+ sum(for(val Pair(x, y) <- xs zip ys) yield x * y);
+
+ type Lst = List[Any];
+
+ val books = List(
+ 'book('title("Structure and Interpretation of Computer Programs"),
+ 'author("Abelson, Harald"),
+ 'author("Sussman, Gerald J.")),
+ 'book('title("Principles of Compiler Design"),
+ 'author("Aho, Alfred"),
+ 'author("Ullman, Jeffrey")),
+ 'book('title("Programming in Modula-2"),
+ 'author("Wirth, Niklaus")));
+
+ def findAuthor(books: Lst) =
+ for (val 'book(book: Lst) <- books;
+ val 'title(title: String) <- book;
+ (title indexOf "Program") >= 0;
+ val 'author(author: String) <- book) yield author;
+
+ for (val 'book(b: Lst) <- books;
+ val 'author(author: String) <- b;
+ author startsWith "Ullman";
+ val 'title(title: String) <- b) yield title;
+
+ removeDuplicates(
+ for (val 'book(b1: Lst) <- books;
+ val 'book(b2: Lst) <- books;
+ b1 != b2;
+ val 'author(a1: String) <- b1;
+ val 'author(a2: String) <- b2;
+ a1 == a2) yield Pair(a1, a2));
+
+ def removeDuplicates[a](xs: List[a]): List[a] =
+ xs.head :: removeDuplicates(for (val x <- xs.tail; x != xs.head) yield x)
+}
diff --git a/sources/examples/iterators.scala b/sources/examples/iterators.scala
new file mode 100644
index 0000000000..8eae9fb026
--- /dev/null
+++ b/sources/examples/iterators.scala
@@ -0,0 +1,12 @@
+module iterators {
+
+ def printArray(xs: Array[Int]) =
+ Iterator.fromArray(xs) foreach (x => System.out.println(x));
+
+ def findGreater(xs: Array[Double], limit: Double) =
+ Iterator.fromArray(xs)
+ .zip(Iterator.from(0))
+ .filter{case Pair(x, i) => x > limit}
+ .map{case Pair(x, i) => i}
+
+}
diff --git a/sources/examples/maps.scala b/sources/examples/maps.scala
new file mode 100644
index 0000000000..3e75049765
--- /dev/null
+++ b/sources/examples/maps.scala
@@ -0,0 +1,152 @@
+module maps {
+
+ trait MapStruct[kt, vt] {
+ trait Map extends Function1[kt, vt] with {
+ def extend(key: kt, value: vt): Map;
+ def remove(key: kt): Map;
+ def domain: Stream[kt];
+ def range: Stream[vt];
+ }
+ type map <: Map;
+ val empty: map;
+ }
+
+ class AlgBinTree[kt <: Ord[kt], vt <: AnyRef]() extends MapStruct[kt, vt] {
+ type map = AlgMap;
+
+ val empty: AlgMap = Empty();
+
+ private case class
+ Empty() extends AlgMap {},
+ Node(key: kt, value: vt, l: map, r: map) extends AlgMap {}
+
+ trait AlgMap extends Map {
+ def apply(key: kt): vt = this match {
+ case Empty() => null
+ case Node(k, v, l, r) =>
+ if (key < k) l.apply(key)
+ else if (key > k) r.apply(key)
+ else v
+ }
+
+ def extend(key: kt, value: vt): map = this match {
+ case Empty()=> Node(key, value, empty, empty)
+ case Node(k, v, l, r) =>
+ if (key < k) Node(k, v, l.extend(key, value), r)
+ else if (key > k) Node(k, v, l, r.extend(key, value))
+ else Node(k, value, l, r)
+ }
+
+ def remove(key: kt): map = this match {
+ case Empty()=> empty
+ case Node(k, v, l, r) =>
+ if (key < k) Node(k, v, l.remove(key), r)
+ else if (key > k) Node(k, v, l, r.remove(key))
+ else if (l == empty) r
+ else if (r == empty) l
+ else {
+ val midKey = r.domain.head;
+ Node(midKey, r.apply(midKey), l, r.remove(midKey))
+ }
+ }
+
+ def domain: Stream[kt] = this match {
+ case Empty()=> Stream.empty
+ case Node(k, v, l, r) => l.domain append Stream.cons(k, r.domain)
+ }
+
+ def range: Stream[vt] = this match {
+ case Empty()=> Stream.empty
+ case Node(k, v, l, r) => l.range append Stream.cons(v, r.range)
+ }
+ }
+ }
+
+ class OOBinTree[kt <: Ord[kt], vt <: AnyRef]() extends MapStruct[kt, vt] {
+ type map = OOMap;
+
+ trait OOMap extends Map with {
+ def apply(key: kt): vt;
+ def extend(key: kt, value: vt): map;
+ def remove(key: kt): map;
+ def domain: Stream[kt];
+ def range: Stream[vt];
+ }
+ module empty extends OOMap with {
+ def apply(key: kt): vt = null;
+ def extend(key: kt, value: vt) = new Node(key, value, empty, empty);
+ def remove(key: kt) = empty;
+ def domain: Stream[kt] = Stream.empty;
+ def range: Stream[vt] = Stream.empty;
+ }
+ private class Node(k: kt, v: vt, l: map, r: map) extends OOMap with {
+ def apply(key: kt): vt =
+ if (key < k) l.apply(key)
+ else if (key > k) r.apply(key)
+ else v;
+ def extend(key: kt, value: vt): map =
+ if (key < k) new Node(k, v, l.extend(key, value), r)
+ else if (key > k) new Node(k, v, l, r.extend(key, value))
+ else new Node(k, value, l, r);
+ def remove(key: kt): map =
+ if (key < k) new Node(k, v, l.remove(key), r)
+ else if (key > k) new Node(k, v, l, r.remove(key))
+ else if (l == empty) r
+ else if (r == empty) l
+ else {
+ val midKey = r.domain.head;
+ new Node(midKey, r(midKey), l, r.remove(midKey))
+ }
+ def domain: Stream[kt] = l.domain append Stream.cons(k, r.domain);
+ def range: Stream[vt] = l.range append Stream.cons(v, r.range);
+ }
+ }
+
+ class MutBinTree[kt <: Ord[kt], vt <: AnyRef]() extends MapStruct[kt, vt] {
+ type map = MutMap;
+ class MutMap(key: kt, value: vt) extends Map with {
+ val k = key;
+ var v = value;
+ var l = empty, r = empty;
+
+ def apply(key: kt): vt =
+ if (this == empty) null
+ else if (key < k) l.apply(key)
+ else if (key > k) r.apply(key)
+ else v;
+
+ def extend(key: kt, value: vt): map =
+ if (this == empty) new MutMap(key, value)
+ else {
+ if (key < k) l = l.extend(key, value)
+ else if (key > k) r = r.extend(key, value)
+ else v = value;
+ this
+ }
+
+ def remove(key: kt): map =
+ if (this == empty) this
+ else if (key < k) { l = l.remove(key) ; this }
+ else if (key > k) { r = r.remove(key) ; this }
+ else if (l == empty) r
+ else if (r == empty) l
+ else {
+ var mid = r;
+ while (!(mid.l == empty)) { mid = mid.l }
+ mid.r = r.remove(mid.k);
+ mid.l = l;
+ mid
+ }
+ def domain: Stream[kt] =
+ if (this == empty) Stream.empty;
+ else l.domain append Stream.cons(k, r.domain);
+ def range: Stream[vt] =
+ if (this == empty) Stream.empty;
+ else l.range append Stream.cons(v, r.range);
+ }
+ val empty = new MutMap(null, null);
+ }
+}
+
+
+
diff --git a/sources/examples/parsers.scala b/sources/examples/parsers.scala
new file mode 100644
index 0000000000..43a386e8db
--- /dev/null
+++ b/sources/examples/parsers.scala
@@ -0,0 +1,53 @@
+package examples;
+
+module Parse {
+
+ type Result = Option[List[Char]];
+
+ trait Parser extends Function1[List[Char],Result] with {
+ def &&& (def p: Parser) = new Parser {
+ def apply(in: List[Char]) = Parser.this.apply(in) match {
+ case Some(in1) => p(in1)
+ case n => n
+ }
+ }
+
+ def ||| (def p: Parser) = new Parser {
+ def apply(in: List[Char]) = Parser.this.apply(in) match {
+ case None() => p(in)
+ case s => s
+ }
+ }
+ }
+
+ val empty = new Parser { def apply(in: List[Char]): Result = Some(in) }
+
+ def fail = new Parser { def apply(in: List[Char]): Result = None() }
+
+ def chrWith(p: Char => Boolean) = new Parser {
+ def apply(in: List[Char]): Result = in match {
+ case List() => None()
+ case (c :: in1) => if (p(c)) Some(in1) else None()
+ }
+ }
+
+ def chr(c: Char): Parser = chrWith(d => d == c);
+
+ def opt(p: Parser): Parser = p ||| empty;
+ def rep(p: Parser): Parser = opt(rep1(p));
+ def rep1(p: Parser): Parser = p &&& rep(p);
+}
+
+module ExprParser {
+ import Parse._;
+
+ def letter = chrWith(c => c.isLetter);
+ def digit = chrWith(c => c.isDigit);
+
+ def ident = letter &&& rep(letter ||| digit);
+ def number = digit &&& rep(digit);
+
+ def expr:Parser = expr1 &&& rep((chr('+') &&& expr1) ||| (chr('-') &&& expr1));
+ def expr1 = expr2 &&& rep((chr('*') &&& expr2) ||| (chr('/') &&& expr2));
+ def expr2 = ident ||| number ||| (chr('(') &&& expr &&& chr(')'));
+}
diff --git a/sources/examples/parsers1.scala b/sources/examples/parsers1.scala
new file mode 100644
index 0000000000..cf2d02d076
--- /dev/null
+++ b/sources/examples/parsers1.scala
@@ -0,0 +1,115 @@
+package examples;
+
+trait Tree {}
+case class Var(n: String) : Tree extends Tree {}
+case class Num(n: Int) : Tree extends Tree {}
+case class Binop(op: Char, l: Tree, r: Tree): Tree extends Tree {}
+
+module Parse {
+
+ type Result[b] = Option[Pair[b, List[Char]]];
+
+ trait Parser[p] extends Function1[List[Char], Result[p]] {
+
+ def apply(in: List[Char]): Result[p];
+
+ def filter(p: p => Boolean) = new Parser[p] {
+ def apply(in: List[Char]): Result[p] = Parser.this.apply(in) match {
+ case Some(Pair(x, in1)) => if (p(x)) Some(Pair(x, in1)) else None()
+ case n => n
+ }
+ }
+
+ def map[b](f: p => b) = new Parser[b] {
+ def apply(in: List[Char]): Result[b] = Parser.this.apply(in) match {
+ case Some(Pair(x, in1)) => Some(Pair(f(x), in1))
+ case None() => None()
+ }
+ }
+
+ def flatMap[b](f: p => Parser[b]) = new Parser[b] {
+ def apply(in: List[Char]): Result[b] = Parser.this.apply(in) match {
+ case Some(Pair(x, in1)) => f(x)(in1)
+ case None() => None()
+ }
+ }
+
+ def ||| (def p: Parser[p]) = new Parser[p] {
+ def apply(in: List[Char]): Result[p] = Parser.this.apply(in) match {
+ case None() => p(in)
+ case s => s
+ }
+ }
+
+ def &&& [b](def p: Parser[b]): Parser[b] =
+ for (val _ <- this; val result <- p) yield result;
+ }
+
+ def succeed[p](x: p) = new Parser[p] {
+ def apply(in: List[Char]) = Some(Pair(x, in))
+ }
+
+ def rep[a](p: Parser[a]): Parser[List[a]] =
+ rep1(p) ||| succeed(List());
+
+ def rep1[a](p: Parser[a]): Parser[List[a]] =
+ for (val x <- p; val xs <- rep(p)) yield x :: xs;
+
+ def opt[a](p: Parser[a]): Parser[Option[a]] =
+ (for (val x <- p) yield Some(x): Option[a]) ||| succeed(None(): Option[a]);
+}
+
+
+module ExprParser {
+ import Parse._;
+
+ def chrWith(p: Char => Boolean) = new Parser[Char] {
+ def apply(in: List[Char]): Result[Char] = in match {
+ case List() => None()
+ case (c :: in1) => if (p(c)) Some(Pair(c, in1)) else None()
+ }
+ }
+
+ def chr(c: Char): Parser[Char] = chrWith(d => d == c);
+
+ def letter: Parser[Char] = chrWith(c => c.isLetter);
+ def digit : Parser[Char] = chrWith(c => c.isDigit);
+
+ def ident: Parser[String] =
+ for (val c <- letter; val cs <- rep(letter ||| digit))
+ yield ((c :: cs) foldr "") {(c, s) => c+ s}
+
+ def number: Parser[Int] =
+ for (val d <- digit; val ds <- rep(digit))
+ yield ((d - '0') foldl_: ds) {(x, y) => x * 10 + (y - '0')};
+
+ def expr: Parser[Tree] =
+ for {
+ val e1 <- expr1;
+ val es <- rep (
+ for {
+ val op <- chr('+') ||| chr('-');
+ val e <- expr1
+ } yield (x: Tree => Binop(op, x, e))
+ )
+ } yield (e1 foldl_: es) {(x,f) => f(x)}
+
+ def expr1: Parser[Tree] =
+ for {
+ val e1 <- expr2;
+ val es <- rep (
+ for {
+ val op <- chr('*') ||| chr('/');
+ val e <- expr2
+ } yield (x: Tree => Binop(op, x, e))
+ )
+ } yield (e1 foldl_: es) {(x,f) => f(x)}
+
+ def expr2: Parser[Tree] =
+ (for { val n <- ident } yield Var(n))
+ ||| (for { val n <- number } yield Num(n))
+ ||| (for { val _ <- chr('('); val e <- expr; val _ <- chr(')') } yield e);
+
+ private def applyAll[a](fs: List[a => a], x: a) =
+ (x foldl_: fs) { (x, f) => f(x) }
+}
diff --git a/sources/examples/patterns.scala b/sources/examples/patterns.scala
new file mode 100644
index 0000000000..3e4d5a5826
--- /dev/null
+++ b/sources/examples/patterns.scala
@@ -0,0 +1,28 @@
+module patterns {
+
+ trait Tree {}
+ case class Branch(left: Tree, right: Tree) extends Tree {}
+ case class Leaf(x: Int) extends Tree {}
+
+ val tree1 = Branch(Branch(Leaf(1), Leaf(2)), Branch(Leaf(3), Leaf(4)));
+
+ def sumLeaves(t: Tree): Int = t match {
+ case Branch(l, r) => sumLeaves(l) + sumLeaves(r)
+ case Leaf(x) => x
+ }
+
+ def find[a,b](it: Iterator[Pair[a, b]], x: a): Option[b] = {
+ var result: Option[b] = None();
+ while (it.hasNext && result.isNone) {
+ val Pair(x1, y) = it.next;
+ if (x == x1) result = Some(y)
+ }
+ result
+ }
+
+ def printFinds[a](xs: List[Pair[a, String]], x: a) =
+ find(xs.elements, x) match {
+ case Some(y) => System.out.println(y)
+ case None() => System.out.println("no match")
+ }
+} \ No newline at end of file
diff --git a/sources/examples/sort.scala b/sources/examples/sort.scala
new file mode 100644
index 0000000000..36d91b72ae
--- /dev/null
+++ b/sources/examples/sort.scala
@@ -0,0 +1,27 @@
+module sorter {
+
+def sort(a: Array[Int]): Unit = {
+
+ def swap(i: Int, j: Int): Unit = {
+ val t = a(i); a(i) = a(j); a(j) = t;
+ }
+
+ def sort1(l: Int, r: Int): Unit = {
+ val pivot = a((l + r) / 2);
+ var i = l, j = r;
+ while (i <= j) {
+ while (a(i) < pivot) { i = i + 1 }
+ while (a(j) > pivot) { j = j - 1 }
+ if (i <= j) {
+ swap(i, j);
+ i = i + 1;
+ j = j - 1;
+ }
+ }
+ if (l < j) sort1(l, j);
+ if (j < r) sort1(i, r);
+ }
+
+ sort1(0, a.length - 1);
+}
+} \ No newline at end of file
diff --git a/sources/examples/sort1.scala b/sources/examples/sort1.scala
new file mode 100644
index 0000000000..f2722b23cc
--- /dev/null
+++ b/sources/examples/sort1.scala
@@ -0,0 +1,12 @@
+import scala._;
+
+module sorter {
+
+ def sort(a: List[Int]): List[Int] = {
+ val pivot = a at (a.length / 2);
+ sort(a.filter(x => x < pivot))
+ ::: a.filter(x => x == pivot)
+ ::: sort(a.filter(x => x > pivot))
+ }
+
+} \ No newline at end of file
diff --git a/sources/examples/sort2.scala b/sources/examples/sort2.scala
new file mode 100644
index 0000000000..a4e32a9cd4
--- /dev/null
+++ b/sources/examples/sort2.scala
@@ -0,0 +1,12 @@
+module sorter {
+
+def sort (a: List[Int]): List[Int] = {
+ val pivot = a at (a.length / 2);
+ def leqPivot(x: Int) = x <= pivot;
+ def gtPivot(x: Int) = x > pivot;
+ def eqPivot(x: Int) = x == pivot;
+ sort(a filter leqPivot)
+ ::: sort(a filter eqPivot)
+ ::: sort(a filter gtPivot)
+}
+} \ No newline at end of file
diff --git a/sources/examples/typeinf.scala b/sources/examples/typeinf.scala
new file mode 100644
index 0000000000..5ff6f03f50
--- /dev/null
+++ b/sources/examples/typeinf.scala
@@ -0,0 +1,162 @@
+package examples;
+
+trait Term {}
+case class Var(x: String) extends Term {}
+case class Lam(x: String, e: Term) extends Term {}
+case class App(f: Term, e: Term) extends Term {}
+case class Let(x: String, e: Term, f: Term) extends Term {}
+
+module types {
+ trait Type {}
+ case class Tyvar(a: String) extends Type {}
+ case class Arrow(t1: Type, t2: Type) extends Type {}
+ case class Tycon(k: String, ts: List[Type]) extends Type {}
+ private var n: Int = 0;
+ def newTyvar: Type = { n = n + 1 ; Tyvar("a" + n) }
+}
+import types._;
+
+case class ListSet[a](elems: List[a]) {
+
+ def contains(y: a): Boolean = elems match {
+ case List() => False
+ case x :: xs => (x == y) || (xs contains y)
+ }
+
+ def union(ys: ListSet[a]): ListSet[a] = elems match {
+ case List() => ys
+ case x :: xs =>
+ if (ys contains x) ListSet(xs) union ys
+ else ListSet(x :: (ListSet(xs) union ys).elems)
+ }
+
+ def diff(ys: ListSet[a]): ListSet[a] = elems match {
+ case List() => ListSet(List())
+ case x :: xs =>
+ if (ys contains x) ListSet(xs) diff ys
+ else ListSet(x :: (ListSet(xs) diff ys).elems)
+ }
+}
+
+module typeInfer {
+
+ trait Subst extends Function1[Type,Type] {
+ def lookup(x: Tyvar): Type;
+ def apply(t: Type): Type = t match {
+ case Tyvar(a) => val u = lookup(Tyvar(a)); if (t == u) t else apply(u);
+ case Arrow(t1, t2) => Arrow(apply(t1), apply(t2))
+ case Tycon(k, ts) => Tycon(k, ts map apply)
+ }
+ def extend(x: Tyvar, t: Type) = new Subst {
+ def lookup(y: Tyvar): Type = if (x == y) t else Subst.this.lookup(y);
+ }
+ }
+
+ val emptySubst = new Subst { def lookup(t: Tyvar): Type = t }
+
+ def tyvars(t: Type): ListSet[String] = t match {
+ case Tyvar(a) => new ListSet(List(a))
+ case Arrow(t1, t2) => tyvars(t1) union tyvars(t2)
+ case Tycon(k, ts) => tyvars(ts)
+ }
+ def tyvars(ts: TypeScheme): ListSet[String] = ts match {
+ case TypeScheme(vs, t) => tyvars(t) diff new ListSet(vs)
+ }
+ def tyvars(ts: List[Type]): ListSet[String] = ts match {
+ case List() => new ListSet[String](List())
+ case t :: ts1 => tyvars(t) union tyvars(ts1)
+ }
+ def tyvars(env: Env): ListSet[String] = env match {
+ case List() => new ListSet[String](List())
+ case Pair(x, t) :: env1 => tyvars(t) union tyvars(env1)
+ }
+
+ case class TypeScheme(vs: List[String], t: Type) {
+ def newInstance: Type =
+ (emptySubst foldl_: vs) { (s, a) => s.extend(Tyvar(a), newTyvar) } (t);
+ }
+
+ type Env = List[Pair[String, TypeScheme]];
+
+ def lookup(env: Env, x: String): TypeScheme = env match {
+ case List() => null
+ case Pair(y, t) :: env1 => if (x == y) t else lookup(env1, x)
+ }
+
+ def gen(env: Env, t: Type): TypeScheme =
+ TypeScheme((tyvars(t) diff tyvars(env)).elems, t);
+
+ def mgu(t: Type, u: Type)(s: Subst): Subst = Pair(s(t), s(u)) match {
+ case Pair(Tyvar( a), Tyvar(b)) if (a == b) =>
+ s
+ case Pair(Tyvar(a), _) =>
+ if (tyvars(u) contains a) error("unification failure: occurs check")
+ else s.extend(Tyvar(a), u)
+ case Pair(_, Tyvar(a)) =>
+ mgu(u, t)(s)
+ case Pair(Arrow(t1, t2), Arrow(u1, u2)) =>
+ mgu(t1, u1)(mgu(t2, u2)(s))
+ case Pair(Tycon(k1, ts), Tycon(k2, us)) if (k1 == k2) =>
+ (s foldl_: ((ts zip us) map {case Pair(t,u) => mgu(t,u)})) { (s, f) => f(s) }
+ case _ => error("unification failure");
+ }
+
+ def tp(env: Env, e: Term, t: Type)(s: Subst): Subst = e match {
+ case Var(x) => {
+ val u = lookup(env, x);
+ if (u == null) error("undefined: x");
+ else mgu(u.newInstance, t)(s)
+ }
+ case Lam(x, e1) => {
+ val a = newTyvar, b = newTyvar;
+ val s1 = mgu(t, Arrow(a, b))(s);
+ val env1 = Pair(x, TypeScheme(List(), a)) :: env;
+ tp(env1, e1, b)(s1)
+ }
+ case App(e1, e2) => {
+ val a = newTyvar;
+ val s1 = tp(env, e1, Arrow(a, t))(s);
+ tp(env, e2, a)(s1)
+ }
+ case Let(x, e1, e2) => {
+ val a = newTyvar;
+ val s1 = tp(env, e1, a)(s);
+ tp(Pair(x, gen(env, s1(a))) :: env, e2, t)(s1)
+ }
+ }
+
+ def typeOf(env: Env, e: Term): Type = {
+ val a = newTyvar;
+ tp(env, e, a)(emptySubst)(a)
+ }
+}
+
+module predefined {
+ val booleanType = Tycon("Boolean", List());
+ val intType = Tycon("Int", List());
+ def listType(t: Type) = Tycon("List", List(t));
+
+ private def gen(t: Type): typeInfer.TypeScheme = typeInfer.gen(List(), t);
+ private val a = newTyvar;
+ val env = List(
+ Pair("true", gen(booleanType)),
+ Pair("false", gen(booleanType)),
+ Pair("if", gen(Arrow(booleanType, Arrow(a, Arrow(a, a))))),
+ Pair("zero", gen(intType)),
+ Pair("succ", gen(Arrow(intType, intType))),
+ Pair("nil", gen(listType(a))),
+ Pair("cons", gen(Arrow(a, Arrow(listType(a), listType(a))))),
+ Pair("isEmpty", gen(Arrow(listType(a), booleanType))),
+ Pair("head", gen(Arrow(listType(a), a))),
+ Pair("tail", gen(Arrow(listType(a), listType(a)))),
+ Pair("fix", gen(Arrow(Arrow(a, a), a)))
+ )
+}
+
+module test {
+
+ def showType(e: Term) = typeInfer.typeOf(predefined.env, e);
+
+ showType(Lam("x", App(App(Var("cons"), Var("x")), Var("nil"))));
+
+} \ No newline at end of file
diff --git a/sources/scala/Iterator.scala b/sources/scala/Iterator.scala
index 90a1b0cbca..1f2fafc942 100644
--- a/sources/scala/Iterator.scala
+++ b/sources/scala/Iterator.scala
@@ -25,7 +25,7 @@ trait Iterator[a] {
}
def filter(p: a => Boolean): Iterator[a] = new BufferedIterator[a] {
- private val source: BufferedIterator[a] =
+ private val source =
Iterator.this.buffered;
private def skip: Unit =
while (source.hasNext && !p(source.head)) { source.next; () }
diff --git a/sources/scala/List.scala b/sources/scala/List.scala
index a36ab98813..34f7d7cf3d 100644
--- a/sources/scala/List.scala
+++ b/sources/scala/List.scala
@@ -176,13 +176,13 @@ trait List[a] extends Seq[a] {
* operator <code>op</code>, from left to right, and starting with
* the value <code>z</code>. Similar to <code>fold</code> but with
* a different order of the arguments, allowing to use nice constructions like
- * <code>(z :_foldl l) { ... }</code>.
+ * <code>(z foldl_: l) { ... }</code>.
* @return <code>op(... (op(op(z,a0),a1) ...), an)</code> if the list
* is <code>[a0, a1, ..., an]</code>.
*/
- def :_foldl[b](z: b)(f: (b, a) => b): b = match {
+ def foldl_:[b](z: b)(f: (b, a) => b): b = match {
case Nil() => z
- case x :: xs => (xs.:_foldl[b](f(z, x)))(f)
+ case x :: xs => (xs.foldl_:[b](f(z, x)))(f)
}
def foldr[b](z: b)(f: (a, b) => b): b = match {
@@ -192,7 +192,7 @@ trait List[a] extends Seq[a] {
def foldl1(f: (a, a) => a): a = this match {
case Nil() => error("foldl1 of empty list")
- case x :: xs => (x :_foldl xs)(f)
+ case x :: xs => (x foldl_: xs)(f)
}
def foldr1(f: (a, a) => a): a = match {
@@ -218,7 +218,7 @@ trait List[a] extends Seq[a] {
* @return the elements of this list in reverse order.
*/
def reverse: List[a] = {
- ((Nil(): List[a]) :_foldl this)((xs: List[a], x: a) => x :: xs)
+ ((Nil(): List[a]) foldl_: this)((xs: List[a], x: a) => x :: xs)
}
/** Prints on standard output a raw textual representation of this list.
diff --git a/sources/scala/Ord.scala b/sources/scala/Ord.scala
new file mode 100644
index 0000000000..5cf7b6cd91
--- /dev/null
+++ b/sources/scala/Ord.scala
@@ -0,0 +1,8 @@
+package scala;
+
+trait Ord[t <: Ord[t]]: t {
+ def < (that: t): Boolean;
+ def <=(that: t): Boolean = this < that || this == that;
+ def > (that: t): Boolean = that < this;
+ def >=(that: t): Boolean = that <= this;
+} \ No newline at end of file
diff --git a/sources/scala/PartialFunction.scala b/sources/scala/PartialFunction.scala
new file mode 100644
index 0000000000..90a731ebaf
--- /dev/null
+++ b/sources/scala/PartialFunction.scala
@@ -0,0 +1,20 @@
+// DO NOT EDIT. Automatically generated file!
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala {
+ class PartialFunction[A, B] {
+
+ def apply(x: A): B;
+
+ def isDefinedAt(x: A): scala.Boolean;
+
+ }
+
+}
diff --git a/sources/scala/Predef.scala b/sources/scala/Predef.scala
index aa05688fc9..bde0ab3b05 100644
--- a/sources/scala/Predef.scala
+++ b/sources/scala/Predef.scala
@@ -38,10 +38,10 @@ package scala {
}
}
- type Pair[a, b] = Tuple2[a, b];
+ type Pair = Tuple2;
def Pair[a, b](x: a, y: b) = Tuple2(x, y);
- type Triple[a, b, c] = Tuple3[a, b, c];
+ type Triple = Tuple3;
def Triple[a, b, c](x: a, y: b, z: c) = Tuple3(x, y, z);
}
}
diff --git a/sources/scala/Stream.scala b/sources/scala/Stream.scala
index 5c631cfd7b..bb82cbb6d2 100644
--- a/sources/scala/Stream.scala
+++ b/sources/scala/Stream.scala
@@ -144,5 +144,3 @@ module Stream {
else empty;
}
}
-
-case class Foo()
diff --git a/sources/scalac/ast/TreeGen.java b/sources/scalac/ast/TreeGen.java
index d29903f14e..1eb59ca0e0 100644
--- a/sources/scalac/ast/TreeGen.java
+++ b/sources/scalac/ast/TreeGen.java
@@ -534,9 +534,7 @@ public class TreeGen implements Kinds, Modifiers {
pos, Names.ANON_CLASS_NAME.toTypeName(), owner, 0);
clazz.setInfo(Type.compoundType(new Type[]{f0t}, new Scope(), clazz));
clazz.constructor().setInfo(
- Type.MethodType(
- Symbol.EMPTY_ARRAY,
- Type.TypeRef(owner.thisType(), clazz, Type.EMPTY_ARRAY)));
+ Type.MethodType(Symbol.EMPTY_ARRAY, clazz.typeConstructor()));
Symbol applyMeth = new TermSymbol(pos, Names.apply, clazz, FINAL)
.setInfo(Type.MethodType(Symbol.EMPTY_ARRAY, tp));
diff --git a/sources/scalac/ast/parser/Parser.java b/sources/scalac/ast/parser/Parser.java
index 7455080054..8243d73411 100644
--- a/sources/scalac/ast/parser/Parser.java
+++ b/sources/scalac/ast/parser/Parser.java
@@ -168,7 +168,7 @@ public class Parser implements Tokens {
*/
Tree makeBinop(boolean isExpr, int pos, Tree left, Name op, Tree right) {
if (isExpr) {
- if (op.leftAssoc()) {
+ if (op.isLeftAssoc()) {
return make.Apply(pos,
make.Select(pos, left, NameTransformer.encode(op)),
new Tree[]{right});
@@ -339,7 +339,7 @@ public class Parser implements Tokens {
int prec, boolean leftAssoc) {
if (sp != base &&
operators[sp-1].precedence() == prec &&
- operators[sp-1].leftAssoc() != leftAssoc) {
+ operators[sp-1].isLeftAssoc() != leftAssoc) {
syntaxError(
positions[sp-1],
"left- and right-associative operators with same precedence may not be mixed",
@@ -666,9 +666,16 @@ public class Parser implements Tokens {
return make.If(pos, cond, thenp, elsep) ;
} else if (s.token == FOR) {
s.nextToken();
- accept(LPAREN);
- Tree[] enums = enumerators();
- accept(RPAREN);
+ Tree[] enums;
+ if (s.token == LBRACE) {
+ accept(LBRACE);
+ enums = enumerators();
+ accept(RBRACE);
+ } else {
+ accept(LPAREN);
+ enums = enumerators();
+ accept(RPAREN);
+ }
if (s.token == DO) {
return makeFor(s.skipToken(), enums, Names.foreach, Names.foreach, expr());
} else if (s.token == YIELD) {
@@ -712,7 +719,7 @@ public class Parser implements Tokens {
Tree top = prefixExpr();
while (s.token == IDENTIFIER) {
top = reduceStack(
- true, base, top, s.name.precedence(), s.name.leftAssoc());
+ true, base, top, s.name.precedence(), s.name.isLeftAssoc());
push(top, s.pos, s.name);
ident();
if (isExprIntro()) {
@@ -972,7 +979,7 @@ public class Parser implements Tokens {
}
while (s.token == IDENTIFIER) {
top = reduceStack(
- false, base, top, s.name.precedence(), s.name.leftAssoc());
+ false, base, top, s.name.precedence(), s.name.isLeftAssoc());
push(top, s.pos, s.name);
ident();
top = simplePattern();
@@ -1439,7 +1446,7 @@ public class Parser implements Tokens {
tparams, vparams, restype, Tree.Empty);
}
- /** TypeDef ::= Id [TypeParamClause] `=' Type
+ /** TypeDef ::= Id `=' Type
* TypeSig ::= Id [`<:' Type]
*/
Tree typeDefOrSig(int mods) {
@@ -1449,10 +1456,6 @@ public class Parser implements Tokens {
s.nextToken();
return make.TypeDef(pos, mods | Modifiers.DEFERRED, name,
Tree.ExtTypeDef.EMPTY_ARRAY, type());
- } else if (s.token == LBRACKET) {
- TypeDef[] tparams = typeParamClauseOpt();
- accept(EQUALS);
- return make.TypeDef(pos, mods, name, tparams, type());
} else if (s.token == EQUALS) {
s.nextToken();
return make.TypeDef(pos, mods, name,
diff --git a/sources/scalac/symtab/Definitions.java b/sources/scalac/symtab/Definitions.java
index f9e5a6f0ec..a842885d31 100644
--- a/sources/scalac/symtab/Definitions.java
+++ b/sources/scalac/symtab/Definitions.java
@@ -45,6 +45,10 @@ public class Definitions {
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;
@@ -191,61 +195,61 @@ public class Definitions {
ANY_CLASS = new ClassSymbol(
Position.NOPOS, Names.Any.toTypeName(), SCALA_CLASS, Modifiers.JAVA);
SCALA_CLASS.members().enter(ANY_CLASS);
- ANY_TYPE = monoType(ANY_CLASS);
+ ANY_TYPE = ANY_CLASS.typeConstructor();
ANY_CLASS.setInfo(Type.compoundType(Type.EMPTY_ARRAY, new Scope(), ANY_CLASS));
ANY_CLASS.constructor().setInfo(
Type.PolyType(Symbol.EMPTY_ARRAY, ANY_TYPE));
// the java.lang.OBJECT class
JAVA_OBJECT_CLASS = getClass(Names.java_lang_Object);
- JAVA_OBJECT_TYPE = monoType(JAVA_OBJECT_CLASS);
+ 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 TypeSymbol(
Kinds.ALIAS, Position.NOPOS, Names.AnyRef.toTypeName(),
SCALA_CLASS, Modifiers.JAVA)
.setInfo(JAVA_OBJECT_TYPE);
- ANYREF_CLASS.constructor().setInfo(
- Type.PolyType(Symbol.EMPTY_ARRAY, Type.NoType));
-
- ANYREF_TYPE = monoType(ANYREF_CLASS);
+ ANYREF_TYPE = ANYREF_CLASS.typeConstructor();
SCALA.members().enter(ANYREF_CLASS);
// the scala.OBJECT class
OBJECT_CLASS = getClass(Names.scala_Object);
- OBJECT_TYPE = monoType(OBJECT_CLASS);
+ OBJECT_TYPE = OBJECT_CLASS.typeConstructor();
// the scala.ANYVAL class
ANYVAL_CLASS = getClass(Names.scala_AnyVal);
- ANYVAL_TYPE = monoType(ANYVAL_CLASS);
+ ANYVAL_TYPE = ANYVAL_CLASS.typeConstructor();
// the primitive types
DOUBLE_CLASS = getClass(Names.scala_Double);
- DOUBLE_TYPE = monoType(DOUBLE_CLASS);
+ DOUBLE_TYPE = DOUBLE_CLASS.typeConstructor();
FLOAT_CLASS = getClass(Names.scala_Float);
- FLOAT_TYPE = monoType(FLOAT_CLASS);
+ FLOAT_TYPE = FLOAT_CLASS.typeConstructor();
LONG_CLASS = getClass(Names.scala_Long);
- LONG_TYPE = monoType(LONG_CLASS);
+ LONG_TYPE = LONG_CLASS.typeConstructor();
INT_CLASS = getClass(Names.scala_Int);
- INT_TYPE = monoType(INT_CLASS);
+ INT_TYPE = INT_CLASS.typeConstructor();
CHAR_CLASS = getClass(Names.scala_Char);
- CHAR_TYPE = monoType(CHAR_CLASS);
+ CHAR_TYPE = CHAR_CLASS.typeConstructor();
SHORT_CLASS = getClass(Names.scala_Short);
- SHORT_TYPE = monoType(SHORT_CLASS);
+ SHORT_TYPE = SHORT_CLASS.typeConstructor();
BYTE_CLASS = getClass(Names.scala_Byte);
- BYTE_TYPE = monoType(BYTE_CLASS);
+ BYTE_TYPE = BYTE_CLASS.typeConstructor();
BOOLEAN_CLASS = getClass(Names.scala_Boolean);
- BOOLEAN_TYPE = monoType(BOOLEAN_CLASS);
+ BOOLEAN_TYPE = BOOLEAN_CLASS.typeConstructor();
UNIT_CLASS = getClass(Names.scala_Unit);
- UNIT_TYPE = monoType(UNIT_CLASS);
+ 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 = monoType(JAVA_THROWABLE_CLASS);
+ JAVA_THROWABLE_TYPE = JAVA_THROWABLE_CLASS.typeConstructor();
THROW = new TermSymbol(
Position.NOPOS, Names.throw_, JAVA_THROWABLE_CLASS, Modifiers.FINAL);
Symbol tvar = newTypeParameter(THROW, ANY_TYPE);
@@ -254,13 +258,11 @@ public class Definitions {
// add the java.lang.String class to the scala package
JAVA_STRING_CLASS = getClass(Names.java_lang_String);
- JAVA_STRING_TYPE = monoType(JAVA_STRING_CLASS);
+ JAVA_STRING_TYPE = JAVA_STRING_CLASS.typeConstructor();
STRING_CLASS = new TypeSymbol(
Kinds.ALIAS, Position.NOPOS, Names.String.toTypeName(), SCALA_CLASS, 0)
.setInfo(JAVA_STRING_TYPE);
- STRING_CLASS.constructor().setInfo(
- Type.PolyType(Symbol.EMPTY_ARRAY, Type.NoType));
- STRING_TYPE = monoType(STRING_CLASS);
+ STRING_TYPE = STRING_CLASS.typeConstructor();
SCALA.members().enter(STRING_CLASS);
SEQ_CLASS = getClass(Names.scala_Seq);
@@ -384,12 +386,8 @@ public class Definitions {
return getClass(fullname).type();
}
- public Type monoType(Symbol c) {
- return Type.TypeRef(c.owner().thisType(), c, Type.EMPTY_ARRAY);
- }
-
public Type getJavaType(Name fullname) {
- return monoType(getClass(fullname));
+ return getClass(fullname).typeConstructor();
}
private void loadBooleanMembers() {
@@ -402,7 +400,7 @@ public class Definitions {
}
public Type arrayType(Type elemtpe) {
- return Type.appliedType(monoType(ARRAY_CLASS), new Type[]{elemtpe});
+ return Type.appliedType(ARRAY_CLASS.typeConstructor(), new Type[]{elemtpe});
}
public Type functionType(Type[] argtps, Type restp) {
@@ -414,6 +412,13 @@ public class Definitions {
argtps1);
}
+ public Type partialFunctionType(Type argtpe, Type restpe) {
+ Type[] argtps1 = new Type[2];
+ argtps1[0] = argtpe;
+ argtps1[1] = Type.covarType(restpe);
+ return Type.appliedType(PARTIALFUNCTION_CLASS.typeConstructor(), argtps1);
+ }
+
public Type seqType(Type argtpe) {
return Type.appliedType(getType(Names.scala_Seq), new Type[]{argtpe});
}
diff --git a/sources/scalac/symtab/Scope.java b/sources/scalac/symtab/Scope.java
index 3bd22f51ed..f1fa915c55 100644
--- a/sources/scalac/symtab/Scope.java
+++ b/sources/scalac/symtab/Scope.java
@@ -210,19 +210,22 @@ public class Scope {
/** remove entry
*/
public void unlink(Entry e) {
- Entry e1 = hashtable[e.sym.name.index & HASHMASK];
- if (e1 == e) {
- hashtable[e.sym.name.index & HASHMASK] = e.tail;
- } else {
- while (e1.tail != e) e1 = e1.tail;
- }
if (elems == e) {
elems = e.next;
} else {
- e1 = elems;
+ Entry e1 = elems;
while (e1.next != e) e1 = e1.next;
e1.next = e.next;
}
+ if (hashtable != null) {
+ Entry e1 = hashtable[e.sym.name.index & HASHMASK];
+ if (e1 == e) {
+ hashtable[e.sym.name.index & HASHMASK] = e.tail;
+ } else {
+ while (e1.tail != e) e1 = e1.tail;
+ e1.tail = e.tail;
+ }
+ }
elemsCache = null;
}
diff --git a/sources/scalac/symtab/Symbol.java b/sources/scalac/symtab/Symbol.java
index b8e1821daa..20ab5b3366 100644
--- a/sources/scalac/symtab/Symbol.java
+++ b/sources/scalac/symtab/Symbol.java
@@ -113,9 +113,16 @@ public abstract class Symbol implements Modifiers, Kinds {
return this;
}
- /** Set type -- this is an alias for setInfo(Type info) */
+ /** Set type -- this is an alias for setInfo(Type info)
+ */
public Symbol setType(Type info) { return setInfo(info); }
+ /** Set type of `this' in current class
+ */
+ public Symbol setTypeOfThis(Type tp) {
+ throw new ApplicationError(this + ".setTypeOfThis");
+ }
+
public Symbol updateInfo(Type info) {
// Global.instance.currentPhase.setInfo(this, info);
if (infos.limit <= Global.instance.currentPhase.id) {
@@ -481,9 +488,11 @@ public abstract class Symbol implements Modifiers, Kinds {
int nextid = infos.limit;
assert infos != TypeIntervalList.EMPTY : this;
if (nextid < id) {
+ PhaseDescriptor curphase = Global.instance.currentPhase;
do {
+ Global.instance.currentPhase = Global.instance.phases[nextid];
Type newInfo =
- Global.instance.phases[nextid].transformInfo(this, infos.info);
+ Global.instance.currentPhase.transformInfo(this, infos.info);
if (newInfo != infos.info) {
infos = new TypeIntervalList(infos);
infos.info = newInfo;
@@ -491,6 +500,7 @@ public abstract class Symbol implements Modifiers, Kinds {
nextid++;
infos.limit = nextid;
} while (nextid < id);
+ Global.instance.currentPhase = curphase;
return infos.info;
} else {
TypeIntervalList infos1 = infos;
@@ -528,14 +538,25 @@ public abstract class Symbol implements Modifiers, Kinds {
return tps;
}
+ /** The type constructor of a symbol is:
+ * For a type symbol, the type corresponding to the symbol itself, excluding
+ * parameters.
+ * Not applicable for term symbols.
+ */
+ public Type typeConstructor() {
+ throw new ApplicationError("typeConstructor inapplicable for " + this);
+ }
+
/** Get this.type corresponding to this symbol
*/
public Type thisType() {
return Type.localThisType;
}
+ /** Get type of `this' in current class.
+ */
public Type typeOfThis() {
- return Type.localThisType;
+ return type();
}
/** A total ordering between symbols that refines the class
@@ -857,10 +878,10 @@ public class TermSymbol extends Symbol {
TermSymbol sym = new TermSymbol(pos, name, owner, flags | MODUL | FINAL);
Symbol clazz = new ClassSymbol(
pos, name.toTypeName(), owner, flags | MODUL | FINAL, sym);
- Type clazztype = Type.TypeRef(owner.thisType(), clazz, Type.EMPTY_ARRAY);
- clazz.constructor().setInfo(Type.MethodType(Symbol.EMPTY_ARRAY, clazztype));
+ clazz.constructor().setInfo(
+ Type.MethodType(Symbol.EMPTY_ARRAY, clazz.typeConstructor()));
sym.clazz = clazz;
- sym.setInfo(clazztype);
+ sym.setInfo(clazz.typeConstructor());
return sym;
}
@@ -910,6 +931,10 @@ public class TermSymbol extends Symbol {
return other;
}
+ public Symbol[] typeParams() {
+ return type().typeParams();
+ }
+
public Symbol primaryConstructorClass() {
return isConstructor() && clazz != null ? clazz : this;
}
@@ -927,56 +952,42 @@ public class TypeSymbol extends Symbol {
*/
private ClosureIntervalList closures = ClosureIntervalList.EMPTY;
- /** The symbol's type template */
- private Type template;
-
- /** The primary constructor of this type */
- public final Symbol constructor;
+ /** A cache for type constructors
+ */
+ private Type tycon = null;
/** Constructor */
public TypeSymbol(int kind, int pos, Name name, Symbol owner, int flags) {
super(kind, pos, name, owner, flags);
- this.constructor = TermSymbol.newConstructor(this, flags);
- if (kind == TYPE) { // provide a constructor type
- this.constructor().setInfo(
- Type.PolyType(Symbol.EMPTY_ARRAY, Type.NoType));
- }
}
+
/** Return a fresh symbol with the same fields as this one.
*/
public Symbol cloneSymbol() {
if (Global.instance.debug) System.out.println("cloning " + this + this.locationString());
TypeSymbol other = new TypeSymbol(kind, pos, name, owner(), flags);
other.setInfo(info());
- other.constructor.setInfo(constructor.info());
return other;
}
- /** Get self type */
+ /** Get type constructor */
+ public Type typeConstructor() {
+ if (tycon == null)
+ tycon = Type.TypeRef(owner().thisType(), this, Type.EMPTY_ARRAY);
+ return tycon;
+ }
+
+ /** Get type */
public Type type() {
- if (template == null || template.typeArgs().length != typeParams().length) {
- template = Type.TypeRef(
- owner().thisType(), this, type(typeParams()));
- }
- return template;
+ return typeConstructor();
}
- //todo: needed?
+ /** Get type at phase id */
public Type typeAt(int id) {
return type();
}
- /** Get type parameters */
- public Symbol[] typeParams() {
- return constructor.info().typeParams();
- }
-
- /** Get primary constructor */
- public Symbol constructor() {
- return constructor;
- }
-
public Type[] closure() {
if (kind == ALIAS) return info().symbol().closure();
int id = Global.instance.currentPhase.id;
@@ -1069,6 +1080,12 @@ public class ClassSymbol extends TypeSymbol {
/** The mangled class name */
private Name mangled;
+ /** The symbol's type template */
+ private Type template;
+
+ /** The primary constructor of this type */
+ public final Symbol constructor;
+
/** The module belonging to the class. This means:
* For Java classes, its statics parts.
* For module classes, the corresponding module.
@@ -1076,10 +1093,19 @@ public class ClassSymbol extends TypeSymbol {
*/
private Symbol module = NONE;
+ /** The given type of self, or NoType, if no explicit type was given.
+ */
+ private Symbol thisSym = this;
+
+ /** A cache for this.thisType()
+ */
+ private Type thistp = Type.ThisType(this);
+
/** Principal Constructor for module classes and classes with static members.
*/
public ClassSymbol(int pos, Name name, Symbol owner, int flags) {
super(CLASS, pos, name, owner, flags);
+ this.constructor = TermSymbol.newConstructor(this, flags);
this.mangled = name;
}
@@ -1103,6 +1129,7 @@ public class ClassSymbol extends TypeSymbol {
*/
public ClassSymbol(Name name, Symbol owner, ClassParser parser) {
super(CLASS, Position.NOPOS, name, owner, JAVA);
+ this.constructor = TermSymbol.newConstructor(this, flags);
this.module = TermSymbol.newCompanionModule(this, JAVA, parser.staticsParser(this));
this.mangled = name;
this.setInfo(parser);
@@ -1116,9 +1143,17 @@ public class ClassSymbol extends TypeSymbol {
other.constructor.setInfo(constructor.info());
other.mangled = mangled;
other.module = module;
+ other.thisSym = thisSym;
return other;
}
+ /** copy all fields to `sym'
+ */
+ public void copyTo(Symbol sym) {
+ super.copyTo(sym);
+ if (thisSym != this) sym.setTypeOfThis(typeOfThis());
+ }
+
/** Get module */
public Symbol module() {
return module;
@@ -1153,12 +1188,39 @@ public class ClassSymbol extends TypeSymbol {
}
}
- private Type thistp = Type.ThisType(this);
+ /** Get type parameters */
+ public Symbol[] typeParams() {
+ return constructor.info().typeParams();
+ }
+
+ /** Get type */
+ public Type type() {
+ if (template == null || template.typeArgs().length != typeParams().length) {
+ template = Type.TypeRef(
+ owner().thisType(), this, type(typeParams()));
+ }
+ return template;
+ }
public Type thisType() {
return thistp;
}
+ public Type typeOfThis() {
+ return thisSym.type();
+ }
+
+ public Symbol setTypeOfThis(Type tp) {
+ thisSym = new TermSymbol(this.pos, Names.this_, this, SYNTHETIC);
+ thisSym.setInfo(tp);
+ return this;
+ }
+
+ /** Get primary constructor */
+ public Symbol constructor() {
+ return constructor;
+ }
+
/** Return the next enclosing class */
public Symbol enclClass() {
return this;
diff --git a/sources/scalac/symtab/Type.java b/sources/scalac/symtab/Type.java
index 7e94662d9a..3a95a2805d 100644
--- a/sources/scalac/symtab/Type.java
+++ b/sources/scalac/symtab/Type.java
@@ -186,7 +186,7 @@ public class Type implements Modifiers, Kinds, TypeTags {
public Type widen() {
switch (this) {
case ThisType(Symbol sym):
- return sym.type();
+ return sym.typeOfThis();
case SingleType(Type pre, Symbol sym):
// overridden in ExtSingleType
throw new ApplicationError();
@@ -249,6 +249,30 @@ public class Type implements Modifiers, Kinds, TypeTags {
}
}
+ /** Get type of `this' symbol corresponding to this type, extend
+ * homomorphically to function types and method types.
+ */
+ public Type instanceType() {
+ switch (unalias()) {
+ case TypeRef(Type pre, Symbol sym, Type[] args):
+ Type tp1 = sym.typeOfThis();
+ if (tp1 != sym.type())
+ return tp1.asSeenFrom(pre, sym.owner()).subst(sym.typeParams(), args);
+ break;
+ case MethodType(Symbol[] params, Type restp):
+ Type restp1 = restp.instanceType();
+ if (restp1 != restp)
+ return MethodType(params, restp1);
+ break;
+ case PolyType(Symbol[] tparams, Type restp):
+ Type restp1 = restp.instanceType();
+ if (restp1 != restp)
+ return PolyType(tparams, restp1);
+ break;
+ }
+ return this;
+ }
+
/** Remove all aliases
*/
public Type unalias() {
@@ -261,9 +285,7 @@ public class Type implements Modifiers, Kinds, TypeTags {
if (n == 20) throw new Type.Error("recursive type alias: " + this);
switch (this) {
case TypeRef(Type pre, Symbol sym, Type[] args):
- if (sym.kind == ALIAS) {
- return pre.memberInfo(sym).subst(sym.typeParams(), args).unalias(n + 1);
- }
+ if (sym.kind == ALIAS) return pre.memberInfo(sym).unalias(n + 1);
break;
case TypeVar(Type origin, Constraint constr):
if (constr.inst != NoType) return constr.inst.unalias(n + 1);
@@ -303,8 +325,8 @@ public class Type implements Modifiers, Kinds, TypeTags {
case PolyType(Symbol[] tparams, _):
return tparams;
case TypeRef(_, Symbol sym, _):
- if (sym.kind == CLASS || sym.kind == ALIAS) return sym.typeParams();
- break;
+ if (sym.kind == CLASS) return sym.typeParams();
+ else return sym.info().typeParams();
}
return Symbol.EMPTY_ARRAY;
}
@@ -433,7 +455,7 @@ public class Type implements Modifiers, Kinds, TypeTags {
public boolean isFunctionType() {
switch (this) {
case TypeRef(Type pre, Symbol sym, Type[] args):
- if (sym.fullName().startsWith(Names.Function)) {
+ if (sym.fullName().startsWith(Names.scala_Function)) {
for (int i = 0; i < args.length - 1; i++)
if (args[i].isCovarType()) return false;
return args.length > 0 && args[args.length - 1].isCovarType();
@@ -693,11 +715,8 @@ public class Type implements Modifiers, Kinds, TypeTags {
case TypeRef(Type pre, Symbol sym, Type[] args):
if (sym == clazz)
return this;
- else if (sym.kind == TYPE)
+ else if (sym.kind == TYPE || sym.kind == ALIAS)
return pre.memberInfo(sym).baseType(clazz);
- else if (sym.kind == ALIAS)
- return pre.memberInfo(sym).baseType(clazz)
- .subst(sym.typeParams(), args);
else if (clazz.isCompoundSym())
return NoType;
else
@@ -811,14 +830,15 @@ public class Type implements Modifiers, Kinds, TypeTags {
switch (pre.baseType(ownclass)) {
case TypeRef(_, Symbol basesym, Type[] baseargs):
Symbol[] baseparams = basesym.typeParams();
- for (int i = 0; i < baseparams.length; i++)
- if (sym == baseparams[i]) return baseargs[i];//???
+ for (int i = 0; i < baseparams.length; i++) {
+ if (sym == baseparams[i]) return baseargs[i];
+ }
break;
case ErrorType:
return ErrorType;
}
throw new ApplicationError(
- this + " cannot be instantiated from " + pre);
+ this + " in " + ownclass + " cannot be instantiated from " + pre);
} else {
return toInstance(
pre.baseType(clazz).prefix(), clazz.owner());
@@ -1115,8 +1135,8 @@ public class Type implements Modifiers, Kinds, TypeTags {
*/
public boolean containsSome(Symbol[] syms) {
for (int i = 0; i < syms.length; i++)
- if (contains(syms[i])) return false;
- return true;
+ if (contains(syms[i])) return true;
+ return false;
}
// Comparisons ------------------------------------------------------------------
@@ -1789,6 +1809,7 @@ public class Type implements Modifiers, Kinds, TypeTags {
e = e.next) {
Name name = e.sym.name;
if ((e.sym.flags & PRIVATE) == 0 && lubType.lookup(name) == e.sym) {
+ //todo: not memberType?
Type symType = lubThisType.memberInfo(e.sym);
int j = 0;
while (j < tps.length) {
@@ -2025,6 +2046,11 @@ public class Type implements Modifiers, Kinds, TypeTags {
System.arraycopy(args, 0, params, 0, params.length);
return ArrayApply.toString(params, "(", ",", ") => ") +
args[params.length].dropVariance();
+ } else if (sym.isAnonymousClass()) {
+ return "<template: " +
+ ArrayApply.toString(
+ pre.memberInfo(sym).parents(), "", "", " with ") +
+ "{...}>";
}
}
Type pre1 = (Global.instance.debug) ? pre : pre.expandModuleThis();
diff --git a/sources/scalac/symtab/classfile/AttributeParser.java b/sources/scalac/symtab/classfile/AttributeParser.java
index 0ed09b44d0..a9e0790889 100644
--- a/sources/scalac/symtab/classfile/AttributeParser.java
+++ b/sources/scalac/symtab/classfile/AttributeParser.java
@@ -322,7 +322,7 @@ public class AttributeParser implements ClassfileConstants {
types.toArray(args);
return Type.TypeRef(clazz.owner().thisType(), clazz, args);
} else {
- return parser.defs.monoType(clazz);
+ return clazz.typeConstructor();
}
}
diff --git a/sources/scalac/symtab/classfile/ClassfileParser.java b/sources/scalac/symtab/classfile/ClassfileParser.java
index 686b832459..61b7c88691 100644
--- a/sources/scalac/symtab/classfile/ClassfileParser.java
+++ b/sources/scalac/symtab/classfile/ClassfileParser.java
@@ -53,7 +53,7 @@ public class ClassfileParser implements ClassfileConstants {
this.global = global;
this.in = in;
this.c = c;
- this.ctype = Type.TypeRef(c.owner().thisType(), c, Type.EMPTY_ARRAY);
+ this.ctype = c.typeConstructor();
this.make = new JavaTypeCreator(global);
this.sigs = new Signatures(global, make);
this.pool = new ConstantPool(in, sigs);
diff --git a/sources/scalac/transformer/LambdaLiftPhase.java b/sources/scalac/transformer/LambdaLiftPhase.java
index 4b86c37acf..1960175ae8 100644
--- a/sources/scalac/transformer/LambdaLiftPhase.java
+++ b/sources/scalac/transformer/LambdaLiftPhase.java
@@ -64,7 +64,7 @@ public class LambdaLiftPhase extends PhaseDescriptor implements Kinds, Modifiers
case TypeRef(Type pre, Symbol sym, Type[] targs):
switch (pre) {
case ThisType(_):
- if (sym.constructor().isUpdated(nextPhase)) {
+ if (sym.kind == CLASS && sym.constructor().isUpdated(nextPhase)) {
Symbol[] tparams =
sym.constructor().infoAt(nextPhase).typeParams();
int i = tparams.length;
diff --git a/sources/scalac/typechecker/Analyzer.java b/sources/scalac/typechecker/Analyzer.java
index 232ba4a0c9..dd8a65ff22 100644
--- a/sources/scalac/typechecker/Analyzer.java
+++ b/sources/scalac/typechecker/Analyzer.java
@@ -27,6 +27,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
private final DeSugarize desugarize;
private final AnalyzerPhase descr;
final Infer infer;
+ final Transformer duplicator;
public Analyzer(Global global, AnalyzerPhase descr) {
super(global, descr);
@@ -34,6 +35,8 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
this.descr = descr;
this.infer = new Infer(this);
this.desugarize = new DeSugarize(this, global);
+ this.duplicator = new Transformer(
+ global, descr, make, new StrictTreeFactory(make));
}
/** Phase variables, used and set in transformers;
@@ -152,19 +155,6 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
return fn.type == Type.ErrorType ? Type.ErrorType : Type.NoType;
}
- private Tree deepCopy(Tree tree) {
- switch (tree) {
- case Ident(Name name):
- return make.Ident(tree.pos, name)
- .setSymbol(tree.symbol()).setType(tree.type);
- case Select(Tree qual, Name name):
- return make.Select(tree.pos, deepCopy(qual), name)
- .setSymbol(tree.symbol()).setType(tree.type);
- default:
- return tree;
- }
- }
-
static Name value2TypeName(Object value) {
if (value instanceof Character) return Name.fromString("scala.Char");
else if (value instanceof Integer) return Name.fromString("scala.Int");
@@ -293,15 +283,19 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
* - final classes are only inherited by classes which are
* nested within definition of base class, or that occur within same
* statement sequence.
+ * - self-type of current class is a subtype of self-type of each parent class.
*/
- void validateParentClasses(Tree[] constrs, Type[] parents) {
+ void validateParentClasses(Tree[] constrs, Type[] parents, Type selfType) {
if (parents.length == 0 || !checkClassType(constrs[0].pos, parents[0])) return;
- for (int i = 1; i < parents.length; i++) {
+ for (int i = 0; i < parents.length; i++) {
if (!checkClassType(constrs[i].pos, parents[i])) return;
- Type[] grandparents = parents[i].parents();
- if (grandparents.length > 0 && !parents[0].isSubType(grandparents[0]))
- error(constrs[i].pos, "illegal inheritance;\n " + parents[0] +
- " does not conform to " + parents[i] + "'s supertype");
+ if (1 <= i) {
+ Type[] grandparents = parents[i].parents();
+ if (grandparents.length > 0 &&
+ !parents[0].isSubType(grandparents[0]))
+ error(constrs[i].pos, "illegal inheritance;\n " + parents[0] +
+ " does not conform to " + parents[i] + "'s supertype");
+ }
Symbol bsym = parents[i].symbol();
if ((bsym.flags & FINAL) != 0) {
// are we in same scope as base type definition?
@@ -316,6 +310,11 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
}
}
}
+ if (!selfType.isSubType(parents[i].instanceType())) {
+ error(constrs[i].pos, "illegal inheritance;\n self-type " +
+ selfType + " does not conform to " + parents[i] +
+ "'s selftype " + parents[i].instanceType());
+ }
}
}
@@ -444,7 +443,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
try {
return checkNoEscapeMap.apply(tp);
} catch (Type.Error ex) {
- error(pos, tp + "///" + ex.msg);
+ error(pos, ex.msg);
return Type.ErrorType;
}
}
@@ -496,6 +495,12 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
return error(tree, "stable identifier required");
}
+ /** Check that (abstract) type can be instantiated.
+ */
+ void checkInstantiatable(int pos, Type tp) {
+ error(pos, tp.symbol() + " is abstract; cannot be instantiated");
+ }
+
/** Check all members of class `clazz' for overriding conditions.
*/
void checkAllOverrides(Symbol clazz) {
@@ -628,7 +633,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
if (clazz.isLocalClass()) unit.mangler.setMangledName(clazz);
enterSym(tree, clazz.constructor());
- if ((mods & CASE) != 0) {
+ if ((mods & (ABSTRACTCLASS | CASE)) == CASE) {
// enter case constructor method.
enterInScope(
new TermSymbol(
@@ -652,10 +657,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
case TypeDef(int mods, Name name, _, _):
int kind = (mods & (DEFERRED | PARAM)) != 0 ? TYPE : ALIAS;
- TypeSymbol tsym = new TypeSymbol(kind, tree.pos, name, owner, mods);
- if (kind == ALIAS)
- tsym.constructor().setInfo(new LazyTreeType(tree));
- return enterSym(tree, tsym);
+ return enterSym(tree, new TypeSymbol(kind, tree.pos, name, owner, mods));
case Import(Tree expr, Name[] selectors):
return enterImport(tree,
@@ -700,7 +702,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
if (other.isPreloaded()) {
// symbol was preloaded from package;
// need to overwrite definition.
- if (global.debug) System.out.println("overwriting " + other);//debug
+ if (global.debug) System.out.println(sym + " overwrites " + other);//debug
sym.copyTo(other);
if (sym.isModule()) {
sym.moduleClass().copyTo(
@@ -742,11 +744,11 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
/** Define symbol associated with `tree' using given `context'.
*/
- void defineSym(Tree tree, Unit unit, Infer infer, Context context) {
+ void defineSym(Tree tree, Unit unit, Infer infer, Context curcontext) {
Unit savedUnit = this.unit;
this.unit = unit;
Context savedContext = this.context;
- this.context = context;
+ this.context = curcontext;
int savedMode = this.mode;
this.mode = EXPRmode;
Type savedPt = this.pt;
@@ -756,7 +758,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
if (global.debug) System.out.println("defining " + sym);//debug
Type owntype;
switch (tree) {
- case ClassDef(int mods, Name name, Tree.TypeDef[] tparams, Tree.ValDef[][] vparams, _, Tree.Template templ):
+ case ClassDef(int mods, Name name, Tree.TypeDef[] tparams, Tree.ValDef[][] vparams, Tree tpe, Tree.Template templ):
assert (mods & LOCKED) == 0 || sym.isAnonymousClass(): sym; // to catch repeated evaluations
((ClassDef) tree).mods |= LOCKED;
@@ -766,6 +768,10 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
pushContext(tree, sym.constructor(), new Scope(context.scope));
Symbol[] tparamSyms = enterParams(tparams);
Symbol[][] vparamSyms = enterParams(vparams);
+ for (int i = 0; i < vparamSyms.length; i++)
+ for (int j = 0; j < vparamSyms[i].length; j++)
+ context.scope.unlink(
+ context.scope.lookupEntry(vparamSyms[i][j].name));
Type constrtype = makeMethodType(
tparamSyms,
vparamSyms,
@@ -773,7 +779,10 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
sym.constructor().setInfo(constrtype);
// necessary so that we can access tparams
sym.constructor().flags |= INITIALIZED;
+ if (tpe != Tree.Empty)
+ sym.setTypeOfThis(transform(tpe, TYPEmode).type);
+ reenterParams(vparams);
defineTemplate(templ, sym);
owntype = templ.type;
popContext();
@@ -812,31 +821,31 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
case DefDef(int mods, Name name, Tree.TypeDef[] tparams, Tree.ValDef[][] vparams, Tree tpe, Tree rhs):
pushContext(tree, sym, new Scope(context.scope));
Symbol[] tparamSyms = enterParams(tparams);
+ Type restpe = null;
+ if (tpe != Tree.Empty) {
+ restpe = transform(tpe, TYPEmode).type;
+ }
Symbol[][] vparamSyms = enterParams(vparams);
- Type restpe;
if (tpe == Tree.Empty) {
int rhsmode = name.isConstrName() ? CONSTRmode : EXPRmode;
((DefDef) tree).rhs = rhs = transform(rhs, rhsmode);
restpe = rhs.type.widen();
- } else {
- restpe = transform(tpe, TYPEmode).type;
}
popContext();
owntype = makeMethodType(tparamSyms, vparamSyms, restpe);
break;
case TypeDef(int mods, Name name, Tree.TypeDef[] tparams, Tree rhs):
+ //todo: alwyas have context.owner as owner.
if (sym.kind == TYPE) {
pushContext(rhs, context.owner, context.scope);
- this.context.delayArgs = true;
+ context.delayArgs = true;
owntype = transform(rhs, TYPEmode).type;
owntype.symbol().initialize();//to detect cycles
popContext();
} else { // sym.kind == ALIAS
pushContext(tree, sym, new Scope(context.scope));
- Symbol[] tparamSyms = enterParams(tparams);
- sym.constructor().setInfo(Type.PolyType(tparamSyms, Type.NoType));
- owntype = transform(rhs, TYPEmode).type;
+ owntype = transform(rhs, TYPEmode | FUNmode).type;
popContext();
}
break;
@@ -921,8 +930,9 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
/** Re-enter type parameters in current scope.
*/
void reenterParams(Tree[] params) {
- for (int i = 0; i < params.length; i++)
+ for (int i = 0; i < params.length; i++) {
context.scope.enter(params[i].symbol());
+ }
}
/** Re-enter value parameters in current scope.
@@ -1014,7 +1024,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
}
sym = sym1;
sym.flags |= (ACCESSED | SELECTOR);
- Tree qual = checkStable(deepCopy(lastimports.importPrefix()));
+ Tree qual = checkStable(duplicator.transform(lastimports.importPrefix()));
pre = qual.type;
//new TextTreePrinter().print(name + " => ").print(lastimports.tree).print("." + name).println().end();//DEBUG
tree = make.Select(tree.pos, qual, name);
@@ -1048,7 +1058,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
} else {
sym.flags |= (ACCESSED | SELECTOR);
Type symtype = qual.type.memberType(sym);
- //System.out.println(sym.name + ":" + symtype);//debug
+ //System.out.println(sym.name + ":" + symtype);//DEBUG
if (uninst.length != 0) {
switch (symtype) {
case PolyType(Symbol[] tparams, Type restype):
@@ -1156,7 +1166,8 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
Tree[] parents1 = transformConstrInvocations(
templ.pos, templ.parents, false, Type.AnyType);
if (owner.kind != ERROR) {
- validateParentClasses(templ.parents, owner.info().parents());
+ validateParentClasses(
+ templ.parents, owner.info().parents(), owner.typeOfThis());
validateBaseTypes(owner);
}
pushContext(templ, owner, owner.members());
@@ -1358,12 +1369,12 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
* Insert `apply' function if needed.
*/
Tree transform(Tree tree, int mode, Type pt) {
- //new TextTreePrinter().print("transforming ").print(tree).println().end();//DEBUG
int savedMode = this.mode;
Type savedPt = this.pt;
this.mode = mode;
this.pt = pt;
Tree tree1 = adapt(transform(tree), mode, pt);
+
this.mode = savedMode;
this.pt = savedPt;
return tree1;
@@ -1562,11 +1573,16 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
case ClassDef(int mods, Name name, Tree.TypeDef[] tparams, Tree.ValDef[][] vparams, Tree tpe, Tree.Template templ):
pushContext(tree, sym.constructor(), new Scope(context.scope));
reenterParams(tparams);
- reenterParams(vparams);
Tree.TypeDef[] tparams1 = transform(tparams);
- Tree.ValDef[][] vparams1 = transform(vparams);
Tree tpe1 = transform(tpe);
+ reenterParams(vparams);
+ Tree.ValDef[][] vparams1 = transform(vparams);
Tree.Template templ1 = transformTemplate(templ, sym);
+ if ((sym.flags & ABSTRACTCLASS) == 0 &&
+ !sym.type().isSubType(sym.typeOfThis()))
+ error(sym.pos, sym +
+ " needs to be abstract; it does not conform to its self-type " +
+ sym.typeOfThis());
popContext();
return copy.ClassDef(tree, mods, name, tparams1, vparams1, tpe1, templ1)
.setType(definitions.UNIT_TYPE);
@@ -1592,10 +1608,10 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
case DefDef(int mods, Name name, Tree.TypeDef[] tparams, Tree.ValDef[][] vparams, Tree tpe, Tree rhs):
pushContext(tree, sym, new Scope(context.scope));
reenterParams(tparams);
- reenterParams(vparams);
Tree.TypeDef[] tparams1 = transform(tparams);
- Tree.ValDef[][] vparams1 = transform(vparams);
Tree tpe1 = transform(tpe, TYPEmode);
+ reenterParams(vparams);
+ Tree.ValDef[][] vparams1 = transform(vparams);
Tree rhs1 = rhs;
if (tpe1 == Tree.Empty) {
tpe1 = gen.mkType(rhs1.pos, rhs1.type.widen());
@@ -1612,7 +1628,9 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
pushContext(tree, sym, new Scope(context.scope));
reenterParams(tparams);
Tree.TypeDef[] tparams1 = transform(tparams);
- Tree rhs1 = transform(rhs, TYPEmode);
+ int mode = TYPEmode;
+ if (sym.kind == ALIAS) mode |= FUNmode;
+ Tree rhs1 = transform(rhs, mode);
popContext();
return copy.TypeDef(tree, mods, name, tparams1, rhs1)
.setType(definitions.UNIT_TYPE);
@@ -1642,6 +1660,12 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
.setType(tp);
case Visitor(Tree.CaseDef[] cases):
+ if (infer.isFullyDefined(pt)) {
+ Type pt1 = pt.baseType(definitions.PARTIALFUNCTION_CLASS);
+ if (pt1.symbol() == definitions.PARTIALFUNCTION_CLASS)
+ return transform(
+ desugarize.partialFunction(tree, pt1.typeArgs()));
+ }
return transform(desugarize.Visitor(tree));
case Assign(Apply(Tree funarray, Tree[] vparam), Tree rhs):
@@ -1685,13 +1709,10 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
copy.Template(templ, new Tree[]{parent1}, body)
.setType(parent1.type).setSymbol(Symbol.NONE);
Type owntype = parent1.type;
- if ((owntype.symbol().constructor().flags &
- ABSTRACTCLASS) != 0) {
- error(tree.pos, owntype.symbol() +
- " is abstract; cannot be instantiated");
- }
+ if ((owntype.symbol().constructor().flags & ABSTRACTCLASS) != 0)
+ checkInstantiatable(tree.pos, owntype);
return copy.New(tree, templ1)
- .setType(owntype);
+ .setType(owntype.instanceType());
} else {
pushContext(tree, context.owner, new Scope(context.scope));
Tree cd = make.ClassDef(
@@ -1718,7 +1739,9 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
while (it.hasNext()) {
Symbol sym1 = it.next();
Symbol basesym1 = base.lookupNonPrivate(sym1.name);
- if (basesym1.kind != NONE && !basesym1.info().isSameAs(sym1.info()))
+ if (basesym1.kind != NONE &&
+ !base.symbol().thisType().memberType(basesym1)
+ .isSameAs(sym1.type()))
refinement.enter(sym1);
}
if (refinement.elems == Scope.Entry.NONE &&
@@ -1806,14 +1829,15 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
Symbol fsym = TreeInfo.methSymbol(tree1);
if ((mode & (EXPRmode | FUNmode)) == EXPRmode &&
fsym != null && (fsym.flags & CASE) != 0) {
- Symbol constr = fsym.type().resultType().symbol().constructor();
+ Symbol constr = fsym.owner().info()
+ .lookup(fsym.name.toTypeName()).constructor();
Template templ = make.Template(
tree1.pos,
new Tree[]{desugarize.toConstructor(tree1, constr)},
Tree.EMPTY_ARRAY);
templ.setSymbol(Symbol.NONE).setType(tree1.type);
return adapt(
- make.New(tree1.pos, templ).setType(tree1.type), mode, pt);
+ make.New(tree1.pos, templ).setType(tree1.type.instanceType()), mode, pt);
} else {
return tree1;
}
@@ -1919,8 +1943,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
Tree tpe1 = transform(tpe, TYPEmode | FUNmode);
Tree[] args1 = transform(args, TYPEmode);
Type[] argtypes = Tree.typeOf(args);
- Symbol clazz = tpe1.type.unalias().symbol();
- Symbol[] tparams = clazz.typeParams();
+ Symbol[] tparams = tpe1.type.typeParams();
if (tpe1.type != Type.ErrorType) {
if (tparams.length != args.length) {
if (tparams.length == 0)
@@ -1968,7 +1991,8 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
}
}
}
- return error(tree, ex.msg);
+ throw ex;//debug
+ //return error(tree, ex.msg);
}
}
@@ -2005,6 +2029,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
this.c = context;
}
public void complete(Symbol sym) {
+ //System.out.println("completing " + sym);//debug
//if (sym.isConstructor()) sym.constructorClass().initialize();
//else if (sym.isModule()) sym.moduleClass().initialize();
defineSym(tree, u, i, c);
@@ -2019,7 +2044,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
super(tree);
}
public void complete(Symbol sym) {
- sym.setInfo(tree.symbol().constructor().type());
+ sym.setInfo(tree.symbol().constructor().type().instanceType());
}
}
}
diff --git a/sources/scalac/typechecker/DeSugarize.java b/sources/scalac/typechecker/DeSugarize.java
index 15c5713293..cc6654232f 100644
--- a/sources/scalac/typechecker/DeSugarize.java
+++ b/sources/scalac/typechecker/DeSugarize.java
@@ -5,7 +5,6 @@
** **
** $Id$
\* */
-
package scalac.typechecker;
import java.io.*;
@@ -49,6 +48,10 @@ public class DeSugarize implements Kinds, Modifiers {
*/
protected final FreshNameCreator freshNameCreator;
+ /** the tree duplicator
+ */
+ final Transformer duplicator;
+
/** the constructor
*/
public DeSugarize(Analyzer analyzer, Global global) {
@@ -58,9 +61,9 @@ public class DeSugarize implements Kinds, Modifiers {
this.gen = analyzer.gen;
this.infer = analyzer.infer;
this.freshNameCreator = global.freshNameCreator;
+ this.duplicator = analyzer.duplicator;
}
-
// Auxiliary definitions and functions -------------------------------------------
/** introduce fresh variable of the form "deS$56"
@@ -217,7 +220,83 @@ public class DeSugarize implements Kinds, Modifiers {
global.definitions.functionType(targs1, targs[targs1.length]));
print(tree, "postfun", result);
return result;
- } else return tree;
+ } else {
+ print(tree, "postfun", tree);
+ return tree;
+ }
+ }
+
+ /** Cases, Argtpe, Restpe ==>
+ * (new scala.PartialFunction[Argtpe, Restpe] {
+ * def apply(x: Argtpe): Restpe = x match {Cases}
+ * def isDefinedAt(x: Argtpe): scala.Boolean = x match {Cases'}
+ * }: scala.PartialFunction[Argtpe, +Restpe])
+ * WHERE
+ * case P1 if G1 => E1, ..., Pn if Gn => En) = Cases
+ * Cases' = case P1 if G1 => True, ..., Pn if Gn => True, _ => False
+ * Argtpe = targs[0]
+ * Restpe = targs[1]
+ */
+ public Tree partialFunction(Tree tree, Type[] targs) {
+ Type argtpe = targs[0];
+ Type restpe = targs[1].dropVariance();
+ Tree constr = make.TypeApply(tree.pos,
+ make.Select(tree.pos,
+ make.Ident(tree.pos, Names.scala),
+ Names.PartialFunction.toConstrName()),
+ new Tree[]{gen.mkType(tree.pos, argtpe), gen.mkType(tree.pos, restpe)});
+ Name x = getvar();
+ ValDef param = (ValDef) make.ValDef(
+ tree.pos, PARAM, x, gen.mkType(tree.pos, argtpe), Tree.Empty);
+ ValDef[][] vparams = new ValDef[][]{new ValDef[]{param}};
+ Tree body = make.Apply(tree.pos,
+ make.Select(tree.pos,
+ make.Ident(tree.pos, x), Names.match), new Tree[]{tree});
+ Tree applyDef = make.DefDef(
+ tree.pos, 0, Names.apply, Tree.ExtTypeDef.EMPTY_ARRAY, vparams,
+ gen.mkType(tree.pos, restpe), body);
+ Tree tree1 = isDefinedAtVisitor(tree);
+ Tree body1 = make.Apply(tree.pos,
+ make.Select(tree.pos,
+ make.Ident(tree.pos, x), Names.match), new Tree[]{tree1});
+ Tree isDefinedAtDef = make.DefDef(
+ tree.pos, 0, Names.isDefinedAt, Tree.ExtTypeDef.EMPTY_ARRAY,
+ duplicator.transform(vparams),
+ gen.mkType(tree.pos, global.definitions.BOOLEAN_TYPE), body1);
+ Tree newTree = make.New(tree.pos,
+ make.Template(
+ tree.pos, new Tree[]{constr}, new Tree[]{applyDef, isDefinedAtDef}));
+ Tree result = make.Typed(tree.pos,
+ tree,
+ gen.mkType(tree.pos,
+ global.definitions.partialFunctionType(targs[0], targs[1])));
+ print(tree, "partialfun", result);
+ return result;
+ }
+
+ private Tree isDefinedAtVisitor(Tree tree) {
+ switch (tree) {
+ case Visitor(CaseDef[] cases):
+ CaseDef[] cases1 = new CaseDef[cases.length + 1];
+ for (int i = 0; i < cases.length; i++) {
+ switch (cases[i]) {
+ case CaseDef(Tree pat, Tree guard, _):
+ cases1[i] = (CaseDef) make.CaseDef(cases[i].pos,
+ duplicator.transform(pat),
+ duplicator.transform(guard),
+ make.Select(tree.pos,
+ make.Ident(tree.pos, Names.scala), Names.True));
+ }
+ }
+ cases1[cases.length] = (CaseDef) make.CaseDef(tree.pos,
+ make.Ident(tree.pos, Names.WILDCARD),
+ Tree.Empty,
+ make.Select(tree.pos,
+ make.Ident(tree.pos, Names.scala), Names.False));
+ return make.Visitor(tree.pos, cases1);
+ default:
+ throw new ApplicationError("visitor expected", tree);
+ }
}
/** match => this.match
@@ -247,7 +326,7 @@ public class DeSugarize implements Kinds, Modifiers {
case Visitor(CaseDef[] cases):
Name x = getvar();
ValDef param = (ValDef) make.ValDef(
- tree.pos, 0, x, Tree.Empty, Tree.Empty);
+ tree.pos, PARAM, x, Tree.Empty, Tree.Empty);
Tree xuse = make.Ident(tree.pos, x);
// x.match {cases}
Tree body = make.Apply(tree.pos,
diff --git a/sources/scalac/typechecker/RefCheck.java b/sources/scalac/typechecker/RefCheck.java
index b45a9d3a2f..753c81986b 100644
--- a/sources/scalac/typechecker/RefCheck.java
+++ b/sources/scalac/typechecker/RefCheck.java
@@ -97,7 +97,7 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
case ValDef(_, _, _, _):
sym = stat.symbol();
}
- if (sym != null) {
+ if (sym != null && sym.isLocal()) {
scopes[level].enter(sym);
symIndex.put(sym, new Integer(index));
}
@@ -163,7 +163,7 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
Symbol sym = tree.symbol();
resultTree = transform(tree);
//todo: handle variables
- if (index <= maxindex[level]) {
+ if (sym.isLocal() && index <= maxindex[level]) {
if (Global.instance.debug)
System.out.println(refsym[level] + ":" + refsym[level].type());
unit.error(
@@ -189,7 +189,8 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
return copy.Block(tree, stats1);
case Ident(Name name):
Scope.Entry e = scopes[level].lookupEntry(name);
- if (tree.symbol() == e.sym) {
+ Symbol sym = tree.symbol();
+ if (sym.isLocal() && sym == e.sym) {
int i = level;
while (scopes[i] != e.owner) i--;
int symindex = ((Integer) symIndex.get(tree.symbol())).intValue();
diff --git a/sources/scalac/util/Name.java b/sources/scalac/util/Name.java
index 0c04fe2dcb..2522cb59f8 100644
--- a/sources/scalac/util/Name.java
+++ b/sources/scalac/util/Name.java
@@ -385,7 +385,7 @@ public final class Name {
/** is this operator left associative
*/
- public boolean leftAssoc() {
- return names[index] != ':';
+ public boolean isLeftAssoc() {
+ return names[index + len -1] != ':';
}
}
diff --git a/sources/scalac/util/Names.java b/sources/scalac/util/Names.java
index ac41d1192b..54b0509f23 100644
--- a/sources/scalac/util/Names.java
+++ b/sources/scalac/util/Names.java
@@ -44,6 +44,7 @@ public class Names {
public static final Name Long = Name.fromString("Long");
public static final Name Nil = Name.fromString("Nil");
public static final Name Object = Name.fromString("Object");
+ public static final Name PartialFunction = Name.fromString("PartialFunction");
public static final Name Predef = Name.fromString("Predef");
public static final Name Seq = Name.fromString("Seq");
public static final Name Short = Name.fromString("Short");
@@ -61,6 +62,7 @@ public class Names {
public static final Name foreach = Name.fromString("foreach");
public static final Name hashCode = Name.fromString("hashCode");
public static final Name is = Name.fromString("is");
+ public static final Name isDefinedAt = Name.fromString("isDefinedAt");
public static final Name java = Name.fromString("java");
public static final Name java_lang = Name.fromString("java.lang");
public static final Name java_lang_Object = Name.fromString("java.lang.Object");
@@ -89,6 +91,7 @@ public class Names {
public static final Name scala_Long = Name.fromString("scala.Long");
public static final Name scala_Nil = Name.fromString("scala.Nil");
public static final Name scala_Object = Name.fromString("scala.Object");
+ public static final Name scala_PartialFunction = Name.fromString("scala.PartialFunction");
public static final Name scala_Predef = Name.fromString("scala.Predef");
public static final Name scala_Ref = Name.fromString("scala.Ref");
public static final Name scala_Seq = Name.fromString("scala.Seq");
diff --git a/test/files/pos/List1.scala b/test/files/pos/List1.scala
index a52c95b1c8..0e2ad848c9 100644
--- a/test/files/pos/List1.scala
+++ b/test/files/pos/List1.scala
@@ -8,7 +8,7 @@ module lists {
}
def Nil[a] = new List[a] {
- def isEmpty = True;
+ def isEmpty: True.type = True;
def head = error[a]("head of Nil");
def tail = error[List[a]]("tail of Nil");
}
diff --git a/test/files/pos/lambda.scala b/test/files/pos/lambda.scala
index 7e687df4ef..0c85672ac1 100644
--- a/test/files/pos/lambda.scala
+++ b/test/files/pos/lambda.scala
@@ -4,5 +4,5 @@ module test {
def twice[a](f: a => a): a => a = x: a => f(f(x));
- def main = apply@[Int,Int](twice@[Int](x: Int => x))(1);
+ def main = apply[Int,Int](twice@[Int](x: Int => x))(1);
} \ No newline at end of file
diff --git a/test/pos/List1.scala b/test/pos/List1.scala
index a52c95b1c8..0e2ad848c9 100644
--- a/test/pos/List1.scala
+++ b/test/pos/List1.scala
@@ -8,7 +8,7 @@ module lists {
}
def Nil[a] = new List[a] {
- def isEmpty = True;
+ def isEmpty: True.type = True;
def head = error[a]("head of Nil");
def tail = error[List[a]]("tail of Nil");
}
diff --git a/test/pos/lambda.scala b/test/pos/lambda.scala
index 7e687df4ef..0c85672ac1 100644
--- a/test/pos/lambda.scala
+++ b/test/pos/lambda.scala
@@ -4,5 +4,5 @@ module test {
def twice[a](f: a => a): a => a = x: a => f(f(x));
- def main = apply@[Int,Int](twice@[Int](x: Int => x))(1);
+ def main = apply[Int,Int](twice@[Int](x: Int => x))(1);
} \ No newline at end of file