From 6749e5dd658522cb63600021a9ee5a86f911cfeb Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 3 Mar 2003 14:33:53 +0000 Subject: *** empty log message *** --- sources/examples/fors.scala | 63 ++++++++ sources/examples/iterators.scala | 12 ++ sources/examples/maps.scala | 152 +++++++++++++++++++ sources/examples/parsers.scala | 53 +++++++ sources/examples/parsers1.scala | 115 +++++++++++++++ sources/examples/patterns.scala | 28 ++++ sources/examples/sort.scala | 27 ++++ sources/examples/sort1.scala | 12 ++ sources/examples/sort2.scala | 12 ++ sources/examples/typeinf.scala | 162 +++++++++++++++++++++ sources/scala/Iterator.scala | 2 +- sources/scala/List.scala | 10 +- sources/scala/Ord.scala | 8 + sources/scala/PartialFunction.scala | 20 +++ sources/scala/Predef.scala | 4 +- sources/scala/Stream.scala | 2 - sources/scalac/ast/TreeGen.java | 4 +- sources/scalac/ast/parser/Parser.java | 27 ++-- sources/scalac/symtab/Definitions.java | 61 ++++---- sources/scalac/symtab/Scope.java | 17 ++- sources/scalac/symtab/Symbol.java | 132 ++++++++++++----- sources/scalac/symtab/Type.java | 58 ++++++-- .../scalac/symtab/classfile/AttributeParser.java | 2 +- .../scalac/symtab/classfile/ClassfileParser.java | 2 +- sources/scalac/transformer/LambdaLiftPhase.java | 2 +- sources/scalac/typechecker/Analyzer.java | 143 ++++++++++-------- sources/scalac/typechecker/DeSugarize.java | 87 ++++++++++- sources/scalac/typechecker/RefCheck.java | 7 +- sources/scalac/util/Name.java | 4 +- sources/scalac/util/Names.java | 3 + test/files/pos/List1.scala | 2 +- test/files/pos/lambda.scala | 2 +- test/pos/List1.scala | 2 +- test/pos/lambda.scala | 2 +- 34 files changed, 1053 insertions(+), 186 deletions(-) create mode 100644 sources/examples/fors.scala create mode 100644 sources/examples/iterators.scala create mode 100644 sources/examples/maps.scala create mode 100644 sources/examples/parsers.scala create mode 100644 sources/examples/parsers1.scala create mode 100644 sources/examples/patterns.scala create mode 100644 sources/examples/sort.scala create mode 100644 sources/examples/sort1.scala create mode 100644 sources/examples/sort2.scala create mode 100644 sources/examples/typeinf.scala create mode 100644 sources/scala/Ord.scala create mode 100644 sources/scala/PartialFunction.scala 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 op, from left to right, and starting with * the value z. Similar to fold but with * a different order of the arguments, allowing to use nice constructions like - * (z :_foldl l) { ... }. + * (z foldl_: l) { ... }. * @return op(... (op(op(z,a0),a1) ...), an) if the list * is [a0, a1, ..., an]. */ - 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 ""; } } 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 -- cgit v1.2.3