diff options
author | Martin Odersky <odersky@gmail.com> | 2004-01-05 11:38:11 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2004-01-05 11:38:11 +0000 |
commit | 0adfc8d42abed2b4019a866672c497eb5d67e5b9 (patch) | |
tree | 11c3b94a1d6df352d313d0496275cd0dc7db23df /sources | |
parent | 3b1253891b888c191e9b96d566b3eb304213eeee (diff) | |
download | scala-0adfc8d42abed2b4019a866672c497eb5d67e5b9.tar.gz scala-0adfc8d42abed2b4019a866672c497eb5d67e5b9.tar.bz2 scala-0adfc8d42abed2b4019a866672c497eb5d67e5b9.zip |
*** empty log message ***
Diffstat (limited to 'sources')
-rw-r--r-- | sources/examples/parsers.scala | 90 | ||||
-rw-r--r-- | sources/examples/parsers1.scala | 143 | ||||
-rw-r--r-- | sources/examples/typeinf.scala | 250 | ||||
-rw-r--r-- | sources/scala/Iterator.scala | 2 | ||||
-rw-r--r-- | sources/scala/tools/scalac/typechecker/Analyzer.scala | 78 | ||||
-rw-r--r-- | sources/scala/tools/scalac/typechecker/Context.scala | 5 | ||||
-rw-r--r-- | sources/scala/tools/scalac/typechecker/DeSugarize.scala | 2 | ||||
-rw-r--r-- | sources/scalac/symtab/SourceCompleter.java | 5 | ||||
-rw-r--r-- | sources/scalac/symtab/Symbol.java | 3 | ||||
-rw-r--r-- | sources/scalac/symtab/Type.java | 20 | ||||
-rw-r--r-- | sources/scalac/typechecker/RefCheck.java | 4 |
11 files changed, 362 insertions, 240 deletions
diff --git a/sources/examples/parsers.scala b/sources/examples/parsers.scala index efe90fc306..3112e0346d 100644 --- a/sources/examples/parsers.scala +++ b/sources/examples/parsers.scala @@ -1,53 +1,79 @@ package examples; +abstract class Parsers[intype] { -module Parse { + abstract class Parser { - type Result = Option[List[Char]]; + type Result = Option[intype]; - trait Parser with Function1[List[Char],Result] { - 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 apply(in: intype): Result; + + /*** p &&& q applies first p, and if that succeeds, then q + */ + def &&& (def q: Parser) = new Parser { + def apply(in: intype): Result = Parser.this.apply(in) match { + case None => None + case Some(in1) => q(in1) } } - def ||| (def p: Parser) = new Parser { - def apply(in: List[Char]) = Parser.this.apply(in) match { - case None() => p(in) + /*** p ||| q applies first p, and, if that fails, then q. + */ + def ||| (def q: Parser) = new Parser { + def apply(in: intype): Result = Parser.this.apply(in) match { + case None => q(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() - } + val empty = new Parser { + def apply(in: intype): Result = Some(in) } - def chr(c: Char): Parser = chrWith(d => d == c); + val fail = new Parser { + def apply(in: intype): Result = None + } - def opt(p: Parser): Parser = p ||| empty; - def rep(p: Parser): Parser = opt(rep1(p)); - def rep1(p: Parser): Parser = p &&& rep(p); + def opt(p: Parser): Parser = p ||| empty; // p? = (p | <empty>) + def rep(p: Parser): Parser = opt(rep1(p)); // p* = [p+] + def rep1(p: Parser): Parser = p &&& rep(p); // p+ = p p* } -module ExprParser { - import Parse._; +abstract class ListParsers[intype] extends Parsers[intype] { + + def chr(p: char => boolean): Parser; - def letter = chrWith(c => c.isLetter); - def digit = chrWith(c => c.isDigit); + def chr(c: char): Parser = chr(d: char => d == c); - def ident = letter &&& rep(letter ||| digit); - def number = digit &&& rep(digit); + def letter : Parser = chr(Character.isLetter); + def digit : Parser = chr(Character.isDigit); - def expr:Parser = expr1 &&& rep((chr('+') &&& expr1) ||| (chr('-') &&& expr1)); - def expr1 = expr2 &&& rep((chr('*') &&& expr2) ||| (chr('/') &&& expr2)); - def expr2 = ident ||| number ||| (chr('(') &&& expr &&& chr(')')); + def ident : Parser = letter &&& rep(letter ||| digit); + def number : Parser = digit &&& rep(digit); + def list : Parser = chr('(') &&& listElems &&& chr(')'); + def listElems : Parser = expr &&& (chr(',') &&& listElems ||| empty); + def expr : Parser = ident ||| number ||| list; +} + +class ParseString(s: String) extends Parsers[int] { + val input = 0; + def chr(p: char => boolean) = new Parser { + def apply(in: int): Parser#Result = + if (in < s.length() && p(s charAt in)) Some(in + 1); + else None; + } +} + +object Test { + + def main(args: Array[String]): unit = + if (args.length == 1) { + val ps = new ListParsers[int] with ParseString(args(0)); + ps.exprs(input) match { + case Some(n) => + System.out.println("parsed: " + args(0).substring(0, n)); + case None => + System.out.println("nothing parsed"); + } + } else System.out.println("usage: java examples.Test <expr-string>"); } diff --git a/sources/examples/parsers1.scala b/sources/examples/parsers1.scala index bbd0a0dbe0..06e8ed0fe0 100644 --- a/sources/examples/parsers1.scala +++ b/sources/examples/parsers1.scala @@ -1,52 +1,49 @@ 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 {} +abstract class Parsers { -module Parse { + type input; - trait Parser[p] { + trait Parser[a] { - type Result = Option[Pair[p, List[Char]]]; + type Result = Option[Pair[a, input]]; - def apply(in: List[Char]): Result; + def apply(in: input): Result; - def filter(p: p => Boolean) = new Parser[p] { - def apply(in: List[Char]): Result = Parser.this.apply(in) match { - case Some(Pair(x, in1)) => if (p(x)) Some(Pair(x, in1)) else None() - case n => n + def filter(pred: a => boolean) = new Parser[a] { + def apply(in: input): Result = Parser.this.apply(in) match { + case None => None + case Some(Pair(x, in1)) => if (pred(x)) Some(Pair(x, in1)) else None } } - def map[b](f: p => b) = new Parser[b] { - def apply(in: List[Char]): Result = Parser.this.apply(in) match { + def map[b](f: a => b) = new Parser[b] { + def apply(in: input): Result = Parser.this.apply(in) match { + case None => None 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 = Parser.this.apply(in) match { - case Some(Pair(x, in1)) => f(x)(in1) - case None() => None() + def flatMap[b](f: a => Parser[b]) = new Parser[b] { + def apply(in: input): Result = Parser.this.apply(in) match { + case None => None + case Some(Pair(x, in1)) => f(x).apply(in1) } } - def ||| (def p: Parser[p]) = new Parser[p] { - def apply(in: List[Char]): Result = Parser.this.apply(in) match { - case None() => p(in) + def ||| (def p: Parser[a]) = new Parser[a] { + def apply(in: input): Result = 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; + for (val _ <- this; val x <- p) yield x; } - def succeed[p](x: p) = new Parser[p] { - def apply(in: List[Char]) = Some(Pair(x, in)) + def succeed[a](x: a) = new Parser[a] { + def apply(in: input) = Some(Pair(x, in)) } def rep[a](p: Parser[a]): Parser[List[a]] = @@ -56,60 +53,58 @@ module Parse { 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]); + (for (val x <- p) yield List(x)) ||| List(); } +abstract class ExprParsers extends Parsers { -module ExprParser { - import Parse._; + def any: Parser[char]; - def chrWith(p: Char => Boolean) = new Parser[Char] { - def apply(in: List[Char]): Result = in match { - case List() => None() - case (c :: in1) => if (p(c)) Some(Pair(c, in1)) else None() - } - } + def chr(ch: char) = + for (val c <- any; c == ch) yield c; - 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 chr(p: char => boolean) = + for (val c <- any; p(c)) yield c; 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) } + for ( + val c: char <- chr(Character.isLetter); + val cs: List[char] <- rep(chr(Character.isLetterOrDigit)) + ) yield (c :: cs).mkString("", "", ""); + + def number: Parser[int] = + for ( + val d: char <- chr(Character.isDigit); + val ds: List[char] <- rep(chr(Character.isDigit)) + ) yield ((d - '0') /: ds) ((x, digit) => x * 10 + digit - '0'); + + def list: Parser[List[Tree]] = + for ( + val _ <- chr('('); + val es <- listElems ||| succeed(List()); + val _ <- chr(')') + ) yield es; + + def listElems: Parser[List[Any]] = + for ( + val x <- expr; + val xs <- chr(',') &&& listElems ||| succeed(List()) + ) yield x :: xs; + + def expr: Parser[Any] = + list ||| ident ||| number; + } + +object Test { + def main(args: Array[String]) = + System.out.println( + if (args.length == 1) + new ExprParserFamily(args(0)).expr(0) match { + case Some(Pair(tree, _)) => tree.toString(); + case None => "Syntax error" + } + else "usage: java examples.Test <expr-string>" + ); +} + diff --git a/sources/examples/typeinf.scala b/sources/examples/typeinf.scala index 0a3a96819e..77976be656 100644 --- a/sources/examples/typeinf.scala +++ b/sources/examples/typeinf.scala @@ -1,49 +1,41 @@ 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 {} - -object 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) - } +case class Var(x: String) extends Term { + override def toString() = x +} +case class Lam(x: String, e: Term) extends Term { + override def toString() = "(\\" + x + "." + e + ")" +} +case class App(f: Term, e: Term) extends Term { + override def toString() = "(" + f + " " + e + ")" +} +case class Let(x: String, e: Term, f: Term) extends Term { + override def toString() = "let " + x + " = " + e + " in " + f; +} - 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) - } +sealed trait Type {} +case class Tyvar(a: String) extends Type { + override def toString() = a +} +case class Arrow(t1: Type, t2: Type) extends Type { + override def toString() = "(" + t1 + "->" + t2 + ")" +} +case class Tycon(k: String, ts: List[Type]) extends Type { + override def toString() = + k + (if (ts.isEmpty) "" else ts.mkString("[", ",", "]")) } object typeInfer { + private var n: Int = 0; + def newTyvar(): Type = { n = n + 1 ; Tyvar("a" + n) } + trait Subst with 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 tv @ Tyvar(a) => val u = lookup(tv); 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) } @@ -54,26 +46,9 @@ object typeInfer { 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) { + case class TypeScheme(tyvars: List[Tyvar], tpe: Type) { def newInstance: Type = - vs.foldLeft(emptySubst) { (s, a) => s.extend(Tyvar(a), newTyvar) } (t); + (emptySubst /: tyvars) ((s, tv) => s.extend(tv, newTyvar())) (tpe); } type Env = List[Pair[String, TypeScheme]]; @@ -84,50 +59,66 @@ object typeInfer { } def gen(env: Env, t: Type): TypeScheme = - TypeScheme((tyvars(t) diff tyvars(env)).elems, t); + TypeScheme(tyvars(t) diff tyvars(env), 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) => + def tyvars(t: Type): List[Tyvar] = t match { + case tv @ Tyvar(a) => List(tv) + case Arrow(t1, t2) => tyvars(t1) union tyvars(t2) + case Tycon(k, ts) => (List[Tyvar]() /: ts) ((tvs, t) => tvs union tyvars(t)); + } + + def tyvars(ts: TypeScheme): List[Tyvar] = + tyvars(ts.tpe) diff ts.tyvars; + + def tyvars(env: Env): List[Tyvar] = + (List[Tyvar]() /: env) ((tvs, nt) => tvs union tyvars(nt._2)); + + 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), _) if !(tyvars(u) contains a) => + s.extend(Tyvar(a), u) case Pair(_, Tyvar(a)) => - mgu(u, t)(s) + mgu(u, t, s) case Pair(Arrow(t1, t2), Arrow(u1, u2)) => - mgu(t1, u1)(mgu(t2, u2)(s)) + mgu(t1, u1, mgu(t2, u2, s)) case Pair(Tycon(k1, ts), Tycon(k2, us)) if (k1 == k2) => - ((ts zip us) map {case Pair(t,u) => mgu(t,u)}).foldLeft(s) { (s, f) => f(s) } - case _ => error("unification failure"); + (s /: (ts zip us)) ((s, tu) => mgu(tu._1, tu._2, s)) + case _ => throw new TypeError("cannot unify " + s(t) + " with " + s(u)) } - 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) + case class TypeError(s: String) extends Exception(s) {} + + def tp(env: Env, e: Term, t: Type, s: Subst): Subst = { + current = e; + e match { + case Var(x) => + val u = lookup(env, x); + if (u == null) throw new TypeError("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) } } + var current: Term = null; def typeOf(env: Env, e: Term): Type = { - val a = newTyvar; - tp(env, e, a)(emptySubst)(a) + val a = newTyvar(); + tp(env, e, a, emptySubst)(a) } } @@ -137,7 +128,7 @@ object predefined { def listType(t: Type) = Tycon("List", List(t)); private def gen(t: Type): typeInfer.TypeScheme = typeInfer.gen(List(), t); - private val a = newTyvar; + private val a = typeInfer.newTyvar(); val env = List( /* Pair("true", gen(booleanType)), @@ -155,11 +146,86 @@ object predefined { ) } -object test with Executable { +abstract class MiniMLParsers[intype] extends CharParsers[intype] { + + /** whitespace */ + def whitespace = rep{chr(' ') ||| chr('\t') ||| chr('\n')}; + + /** A given character, possible preceded by whitespace */ + def wschr(ch: char) = whitespace &&& chr(ch); + + /** identifiers or keywords */ + def id: Parser[String] = + for ( + val c: char <- rep(chr(' ')) &&& chr(Character.isLetter); + val cs: List[char] <- rep(chr(Character.isLetterOrDigit)) + ) yield (c :: cs).mkString("", "", ""); + + /** Non-keyword identifiers */ + def ident: Parser[String] = + for (val s <- id; s != "let" && s != "in") yield s; + + /** term = '\' ident '.' term | term1 {term1} | let ident "=" term in term */ + def term: Parser[Term] = + ( for ( + val _ <- wschr('\\'); + val x <- ident; + val _ <- wschr('.'); + val t <- term) + yield Lam(x, t): Term ) + ||| + ( for ( + val letid <- id; letid == "let"; + val x <- ident; + val _ <- wschr('='); + val t <- term; + val inid <- id; inid == "in"; + val c <- term) + yield Let(x, t, c) ) + ||| + ( for ( + val t <- term1; + val ts <- rep(term1)) + yield (t /: ts)((f, arg) => App(f, arg)) ); + + /** term1 = ident | '(' term ')' */ + def term1: Parser[Term] = + ( for (val s <- ident) + yield Var(s): Term ) + ||| + ( for ( + val _ <- wschr('('); + val t <- term; + val _ <- wschr(')')) + yield t ); + + /** all = term ';' */ + def all: Parser[Term] = + for ( + val t <- term; + val _ <- wschr(';')) + yield t; +} + +object testInfer { -// def showType(e: Term) = typeInfer.typeOf(predefined.env, e); - def showType(e: Term) = typeInfer.typeOf(Nil, e); + def showType(e: Term): String = + try { + typeInfer.typeOf(predefined.env, e).toString(); + } catch { + case typeInfer.TypeError(msg) => + "\n cannot type: " + typeInfer.current + + "\n reason: " + msg; + } - Console.println( - showType(Lam("x", App(App(Var("cons"), Var("x")), Var("nil"))))); + def main(args: Array[String]): unit = { + val ps = new MiniMLParsers[int] with ParseString(args(0)); + ps.all(ps.input) match { + case Some(Pair(term, _)) => + System.out.println("" + term + ": " + showType(term)); + case None => + System.out.println("syntax error"); + } + } } + diff --git a/sources/scala/Iterator.scala b/sources/scala/Iterator.scala index 301abf9f17..0f02c1cd05 100644 --- a/sources/scala/Iterator.scala +++ b/sources/scala/Iterator.scala @@ -34,7 +34,7 @@ object Iterator { else error("next on empty iterator"); } - def range(lo: Int, end: Int) = new BufferedIterator[Int] { + def range(lo: Int, end: Int) = new Iterator[Int] { private var i = lo; def hasNext: Boolean = i < end; diff --git a/sources/scala/tools/scalac/typechecker/Analyzer.scala b/sources/scala/tools/scalac/typechecker/Analyzer.scala index 0ac50a4358..1a723516d2 100644 --- a/sources/scala/tools/scalac/typechecker/Analyzer.scala +++ b/sources/scala/tools/scalac/typechecker/Analyzer.scala @@ -36,7 +36,7 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer( import Kinds._; val definitions = global.definitions; - val infer = new Infer(this); + val infer = new scala.tools.scalac.typechecker.Infer(this); val desugarize = new DeSugarize(make, copy, gen, infer, global); val constfold = new ConstantFolder(this); @@ -370,7 +370,7 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer( bsym.isSubClass(definitions.ARRAY_CLASS)) { // are we in same scope as base type definition? val e: Scope$Entry = context.scope.lookupEntry(bsym.name); - if (e.sym != bsym || e.owner != context.scope) { + if (e.sym != bsym) { // we are not within same statement sequence var c: Context = context; while (c != Context.NONE && c.owner != bsym) @@ -1172,18 +1172,25 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer( this.context = curcontext; val selftype: Type = transform(tree, TYPEmode).getType(); - selftype match { - case Type$CompoundType(parts, members) => - val parts1 = new Array[Type](parts.length + 1); - System.arraycopy(parts, 0, parts1, 0, parts.length); - parts1(parts.length) = clazz.getType(); - sym.setInfo(Type.compoundType(parts1, members)); + //todo: can we really make a compound type with class + val selftype1: Type = + if (clazz.getType().isSubType(selftype)) + clazz.getType() + else if (selftype.isSubType(clazz.getType())) + selftype + else + selftype match { + case Type$CompoundType(parts, members) => + val parts1 = new Array[Type](parts.length + 1); + System.arraycopy(parts, 0, parts1, 0, parts.length); + parts1(parts.length) = clazz.getType(); + Type.compoundType(parts1, members); - case _ => - sym.setInfo( - Type.compoundType( - NewArray.Type(selftype, clazz.getType()), Scope.EMPTY)); - } + case _ => + Type.compoundType( + NewArray.Type(selftype, clazz.getType()), Scope.EMPTY); + } + sym.setInfo(selftype1); this.unit = savedUnit; this.context= savedContext; @@ -1272,7 +1279,9 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer( case Type$MethodType(_, _) => // convert unapplied methods to functions. - if ((mode & (EXPRmode | FUNmode)) == EXPRmode && infer.isCompatible(tree.getType(), pt)) { + if ((mode & (EXPRmode | FUNmode)) == EXPRmode && + (infer.isCompatible(tree.getType(), pt) || + pt.symbol() == definitions.UNIT_CLASS)) { checkEtaExpandable(tree.pos, tree.getType()); return transform(desugarize.etaExpand(tree, tree.getType()), mode, pt); } else if ((mode & (CONSTRmode | FUNmode)) == CONSTRmode) { @@ -1396,16 +1405,16 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer( if ((mode & EXPRmode) != 0) { if (pt.symbol() == definitions.UNIT_CLASS) { return gen.Block(NewArray.Tree(tree, gen.mkUnitLit(tree.pos))); - } else { + } else if (infer.isCompatible(tree.getType(), pt)) { val coerceMeth: Symbol = tree.getType().lookup(Names.coerce); if (coerceMeth != Symbol.NONE) { val coerceType: Type = checkAccessible( tree.pos, coerceMeth, tree.getType().memberType(coerceMeth), tree, tree.getType()); val tree1 = make.Select(tree.pos, tree, Names.coerce) - .setSymbol(coerceMeth) - .setType(coerceType); - return adapt(tree1, mode, pt); + .setSymbol(coerceMeth) + .setType(coerceType); + return adapt(tree1, mode, pt); } } } @@ -1539,13 +1548,16 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer( error(tree.pos, decode(name) + " is not a member of " + qual.getType().widen()); } else { + val qualtype = + if (qual.isInstanceOf[Tree$Super]) context.enclClass.owner.thisType() + else qual.getType(); var symtype: Type = (if (sym.isType()) sym.typeConstructor() else sym.getType()) - .asSeenFrom(qual.getType(), sym.owner()); + .asSeenFrom(qualtype, sym.owner()); if (symtype == Type.NoType) return error(tree.pos, "not found: " + decode(name)); else - symtype = checkAccessible(tree.pos, sym, symtype, qual, qual.getType()); + symtype = checkAccessible(tree.pos, sym, symtype, qual, qualtype); //System.out.println(sym.name + ":" + symtype);//DEBUG if (uninst.length != 0) { symtype match { @@ -1562,7 +1574,7 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer( case Tree$SelectFromType(_, _) => copy.SelectFromType(tree, sym, qual) } - mkStable(tree1.setType(symtype), qual.getType(), mode, pt) + mkStable(tree1.setType(symtype), qualtype, mode, pt) } } @@ -1679,8 +1691,30 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer( validateParentClasses(parents, owner.info().parents(), owner.typeOfThis()); } pushContext(templ, owner, owner.members()); + /* + val params: Scope = new Scope(); + def computeParams(t: Type): unit = t match { + case Type$PolyType(tparams, t1) => + var i = 0; while (i < tparams.length) { + params.enter(tparams(i)); + i = i + 1; + } + computeParams(t1); + case Type$MethodType(vparams, _) => + var i = 0; while (i < vparams.length) { + params.enter(vparams(i)); + i = i + 1; + } + case _ => + } + computeParams(owner.primaryConstructor().getType()); + pushContext(templ, owner.primaryConstructor(), params); + */ templ.setSymbol(TermSymbol.newLocalDummy(owner)); val body1 = transformStatSeq(templ.body, templ.symbol()); + /* + popContext(); + */ popContext(); if (owner.isTrait()) { var i = 0; while (i < parents.length) { @@ -2059,7 +2093,7 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer( if (stats1.length > 0) { stats1(stats1.length - 1) = transform(stats1(stats1.length - 1), curmode & ~FUNmode, pt); - checkNoEscape(tree.pos, stats1(stats1.length - 1).getType()) + checkNoEscape(tree.pos, stats1(stats1.length - 1).getType().deconst()) } else { definitions.UNIT_TYPE() } diff --git a/sources/scala/tools/scalac/typechecker/Context.scala b/sources/scala/tools/scalac/typechecker/Context.scala index c8b885fe7b..81089e0b26 100644 --- a/sources/scala/tools/scalac/typechecker/Context.scala +++ b/sources/scala/tools/scalac/typechecker/Context.scala @@ -32,8 +32,9 @@ class Context { this.owner = owner; this.scope = scope; this.imports = outer.imports; - this.enclClass = if (tree.isInstanceOf[Tree$Template] || - tree.isInstanceOf[Tree$CompoundType]) this + this.enclClass = if ((tree.isInstanceOf[Tree$Template] || + tree.isInstanceOf[Tree$CompoundType]) && + tree != outer.tree) this else outer.enclClass; this.variance = outer.variance; this.constructorClass = outer.constructorClass; diff --git a/sources/scala/tools/scalac/typechecker/DeSugarize.scala b/sources/scala/tools/scalac/typechecker/DeSugarize.scala index 8bb4d75c9b..37ba3cef27 100644 --- a/sources/scala/tools/scalac/typechecker/DeSugarize.scala +++ b/sources/scala/tools/scalac/typechecker/DeSugarize.scala @@ -27,7 +27,7 @@ package scala.tools.scalac.typechecker { * @author Martin Odersky * @version 2.0 */ -class DeSugarize(make: TreeFactory, copy: TreeCopier, gen: TreeGen, infer: Infer, global: scalac_Global) { +class DeSugarize(make: TreeFactory, copy: TreeCopier, gen: TreeGen, infer: scala.tools.scalac.typechecker.Infer, global: scalac_Global) { import Kinds._, Modifiers._; diff --git a/sources/scalac/symtab/SourceCompleter.java b/sources/scalac/symtab/SourceCompleter.java index 7aeda28d05..02d739249b 100644 --- a/sources/scalac/symtab/SourceCompleter.java +++ b/sources/scalac/symtab/SourceCompleter.java @@ -56,7 +56,10 @@ public class SourceCompleter extends Type.LazyType { (System.currentTimeMillis() - msec) + "ms"); } catch (IOException e) { if (global.debug) e.printStackTrace(); - global.error("i/o error while loading " + c); + if (mixinOnly) + global.error("source file for " + c + " not found; it is needed because class is used as a mixin"); + else + global.error("i/o error while loading " + c + ": " + e); c.setInfo(Type.ErrorType); } completed = true; diff --git a/sources/scalac/symtab/Symbol.java b/sources/scalac/symtab/Symbol.java index 37f885bf60..f7430a8402 100644 --- a/sources/scalac/symtab/Symbol.java +++ b/sources/scalac/symtab/Symbol.java @@ -282,6 +282,7 @@ public abstract class Symbol implements Modifiers, Kinds { /** Does this symbol denote a stable value? */ public final boolean isStable() { return kind == VAL && + ((flags & DEF) == 0) && ((flags & STABLE) != 0 || (flags & MUTABLE) == 0 && type().isObjectType()); } @@ -1596,8 +1597,6 @@ public abstract class TypeSymbol extends Symbol { closures = new ClosureIntervalList(closures, Symbol.type(closureClasses), phase.prev == null ? phase : phase.prev); //System.out.println("closure(" + this + ") = " + ArrayApply.toString(closures.closure));//DEBUG - - adjustType(type()); //System.out.println("closure(" + this + ") = " + ArrayApply.toString(closures.closure));//DEBUG Global.instance.currentPhase = current; diff --git a/sources/scalac/symtab/Type.java b/sources/scalac/symtab/Type.java index d7670a4aed..93918f0c54 100644 --- a/sources/scalac/symtab/Type.java +++ b/sources/scalac/symtab/Type.java @@ -827,14 +827,6 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { * inherited members of this type; return Symbol.NONE if not found. */ public Symbol lookupNonPrivate(Name name) { - return lookupNonPrivate(name, 0); - } - - /** Same as before, but with additional parameter `start'. - * If start == 0, lookup in all basetypes of a compound type. - * If start == 1, lookup only in mixin classes. - */ - private Symbol lookupNonPrivate(Name name, int start) { switch (this) { case ErrorType: return Symbol.ERROR; @@ -843,7 +835,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { case ConstantType(_, _): return singleDeref().lookupNonPrivate(name); case TypeRef(_, Symbol sym, _): - return sym.info().lookupNonPrivate(name, start); + return sym.info().lookupNonPrivate(name); case CompoundType(Type[] parts, Scope members): Symbol sym = members.lookup(name); if (sym.kind != NONE && (sym.flags & PRIVATE) == 0) @@ -853,12 +845,14 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { // take precedence over abstract ones. int i = parts.length; sym = Symbol.NONE; - while (i > start && (sym.kind == NONE || (sym.flags & DEFERRED) != 0)) { + while (i > 0 && (sym.kind == NONE || (sym.flags & DEFERRED) != 0)) { i--; - Symbol sym1 = parts[i].lookupNonPrivate(name, i == 0 ? 0 : 1); + Symbol sym1 = parts[i].lookupNonPrivate(name); if (sym1.kind != NONE && (sym1.flags & PRIVATE) == 0 && - (sym.kind == NONE || (sym1.flags & DEFERRED) == 0)) + (sym.kind == NONE || + (sym1.flags & DEFERRED) == 0 || + sym1.owner().isSubClass(sym.owner()))) sym = sym1; } return sym; @@ -1198,7 +1192,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { * or `sym' itself if none exists. */ public Symbol rebind(Symbol sym) { - if ((sym.flags & (PRIVATE | MODUL)) == 0) { + if (sym.kind != CLASS && (sym.flags & (PRIVATE | MODUL)) == 0) { Symbol sym1 = lookupNonPrivate(sym.name); if (sym1.kind != NONE) { if ((sym1.flags & LOCKED) != 0) diff --git a/sources/scalac/typechecker/RefCheck.java b/sources/scalac/typechecker/RefCheck.java index 0b9d308e2b..afe0e0df7a 100644 --- a/sources/scalac/typechecker/RefCheck.java +++ b/sources/scalac/typechecker/RefCheck.java @@ -100,6 +100,8 @@ public class RefCheck extends Transformer implements Modifiers, Kinds { } void checkOverride(int pos, Symbol clazz, Symbol other) { + if (other.kind == CLASS) + return; // todo: see if we can sustain this Symbol member = other; if ((other.flags & PRIVATE) == 0) { Symbol member1 = clazz.info().lookup(other.name); @@ -222,8 +224,10 @@ public class RefCheck extends Transformer implements Modifiers, Kinds { overrideError(pos, member, other, "has weaker access privileges; it should not be protected"); } else if ((other.flags & FINAL) != 0) { overrideError(pos, member, other, "cannot override final member"); +/* } else if (other.kind == CLASS) { overrideError(pos, member, other, "cannot override a class"); +*/ } else if ((other.flags & DEFERRED) == 0 && ((member.flags & OVERRIDE) == 0)) { overrideError(pos, member, other, "needs `override' modifier"); } else if (other.isAbstractOverride() && |