diff options
author | Martin Odersky <odersky@gmail.com> | 2005-03-02 14:56:32 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2005-03-02 14:56:32 +0000 |
commit | 9acfa7693d146fc2ea6fdad61c74907354910ea8 (patch) | |
tree | e0832025736b165bd7e087b3bab41d4fb0046fe0 | |
parent | f8c47c369ed0254ea3bda3366b9902b1a3dd5ba2 (diff) | |
download | scala-9acfa7693d146fc2ea6fdad61c74907354910ea8.tar.gz scala-9acfa7693d146fc2ea6fdad61c74907354910ea8.tar.bz2 scala-9acfa7693d146fc2ea6fdad61c74907354910ea8.zip |
*** empty log message ***
19 files changed, 1226 insertions, 743 deletions
diff --git a/sources/scala/List.scala b/sources/scala/List.scala index 3808cb40d0..a774787e51 100644 --- a/sources/scala/List.scala +++ b/sources/scala/List.scala @@ -188,16 +188,6 @@ object List { sb.toString() } - /** Like (xs map f), but returns xs unchanged if function `f' maps all elements to themselves - */ - def transform[a](xs: List[a])(f: a => a): List[a] = xs match { - case Nil => Nil - case head :: tail => - val head1 = f(head); - val tail1 = transform(tail)(f); - if (head1 == head && (tail1 eq tail)) xs else head1 :: tail1 - } - /** Returns the list resulting from applying the given function <code>f</code> to * corresponding elements of the argument lists. * @@ -520,6 +510,16 @@ sealed trait List[+a] extends Seq[a] { case head :: tail => f(head) :: (tail map f) } + /** Like xs map f, but returns xs unchanged if function `f' maps all elements to themselves + */ + def mapConserve[b >: a](f: a => b): List[b] = match { + case Nil => Nil + case head :: tail => + val head1 = f(head); + val tail1 = tail mapConserve f; + if (head1 == head && (tail1 eq tail)) this else head1 :: tail1 + } + /** Apply a function to all the elements of the list, and return the * reversed list of results. This is equivalent to a call to <code>map</code> * followed by a call to <code>reverse</code>, but more efficient. diff --git a/sources/scala/tools/nsc/Global.scala b/sources/scala/tools/nsc/Global.scala index a6c09fe855..061373b189 100755 --- a/sources/scala/tools/nsc/Global.scala +++ b/sources/scala/tools/nsc/Global.scala @@ -34,6 +34,15 @@ class Global(val settings: Settings, val reporter: Reporter) extends SymbolTable val global: Global.this.type = Global.this } + object constfold extends ConstantFolder { + val global: Global.this.type = Global.this + } + + val copy = new LazyTreeCopier(); + + type AttrInfo = Pair[Type, List[Any]]; + val attributes = new HashMap[Symbol, List[AttrInfo]]; + // reporting ------------------------------------------------------- def informTime(msg: String, start: long) = { @@ -213,6 +222,6 @@ class Global(val settings: Settings, val reporter: Reporter) extends SymbolTable } val sym = getSym(name, module); System.err.println("" + sym.name + ":" + - (if (module) sym.moduleClass.info else sym.info)) + (if (module) sym.tpe.symbol.info else sym.info)) } } diff --git a/sources/scala/tools/nsc/ast/TreeInfo.scala b/sources/scala/tools/nsc/ast/TreeInfo.scala index 92e5c00cd4..03cb490d28 100644 --- a/sources/scala/tools/nsc/ast/TreeInfo.scala +++ b/sources/scala/tools/nsc/ast/TreeInfo.scala @@ -18,7 +18,7 @@ abstract class TreeInfo { def isOwnerDefinition(tree: Tree): boolean = tree match { case PackageDef(_, _) | ClassDef(_, _, _, _, _) - | ModuleDef(_, _, _, _) + | ModuleDef(_, _, _) | DefDef(_, _, _, _, _, _) | Import(_, _) => true case _ => false @@ -39,7 +39,7 @@ abstract class TreeInfo { def isPureDef(tree: Tree): boolean = tree match { case EmptyTree | ClassDef(_, _, _, _, _) - | ModuleDef(_, _, _, _) + | ModuleDef(_, _, _) | AbsTypeDef(_, _, _, _) | AliasTypeDef(_, _, _, _) | Import(_, _) @@ -108,9 +108,9 @@ abstract class TreeInfo { case _ => false } - /** The first constructor in a list of statements */ + /** The longest statement suffix that starts with a constructor */ def firstConstructor(stats: List[Tree]): Tree = stats.head match { - case DefDef(_, nme.CONSTRUCTOR, _, _, _, _) => stats.head + case constr @ DefDef(_, nme.CONSTRUCTOR, _, _, _, _) => constr case _ => firstConstructor(stats.tail) } @@ -133,6 +133,14 @@ abstract class TreeInfo { case _ => false } + /** Is this pattern node a sequence-valued pattern? */ + def isSequenceValued(tree: Tree): boolean = tree match { + case Bind(_, body) => isSequenceValued(body) + case Sequence(_) => true + case Alternative(ts) => ts exists isSequenceValued + case _ => false + } + /** The method symbol of an application node, or NoSymbol, if none exists. */ def methSymbol(tree: Tree): Symbol = { diff --git a/sources/scala/tools/nsc/ast/TreePrinters.scala b/sources/scala/tools/nsc/ast/TreePrinters.scala index 47c8af4cfb..64ff2f66f2 100644 --- a/sources/scala/tools/nsc/ast/TreePrinters.scala +++ b/sources/scala/tools/nsc/ast/TreePrinters.scala @@ -71,7 +71,7 @@ abstract class TreePrinters { } def printBlock(tree: Tree): unit = tree match { - case Block(_, _) | Visitor(_) => print(tree) + case Block(_, _) => print(tree) case _ => printColumn(List(tree), "{", ";", "}") } @@ -103,9 +103,9 @@ abstract class TreePrinters { case PackageDef(packaged, stats) => print("package "); print(packaged); printColumn(stats, " {", ";", "}") - case ModuleDef(mods, name, tpe, impl) => + case ModuleDef(mods, name, impl) => printModifiers(mods); print("object " + symName(tree, name)); - printOpt(": ", tpe); print(" extends "); print(impl); + print(" extends "); print(impl); case ValDef(mods, name, tp, rhs) => printModifiers(mods); @@ -152,8 +152,8 @@ abstract class TreePrinters { case Block(stats, expr) => printColumn(stats ::: List(expr), "{", ";", "}") - case Visitor(cases) => - printColumn(cases, "{", "", "}"); + case Match(selector, cases) => + print(selector); printColumn(cases, " match {", "", "}") case CaseDef(pat, guard, body) => print("case "); print(pat); printOpt(" if ", guard); @@ -181,18 +181,12 @@ abstract class TreePrinters { println; print("else"); indent; println; print(elsep); undent } - case Switch(expr, tags, bodies, defaultBody) => - print("<switch> ("); print(expr); print(") {"); indent; - printSeq(tags zip bodies) - {case Pair(tag, body) => print("case " + tag + " => "); print(body)} {println} - print("<default> => "); print(defaultBody); print(" }"); undent - case Return(expr) => print("return "); print(expr) - case Try(block, catcher, finalizer) => + case Try(block, catches, finalizer) => print("try "); printBlock(block); - printOpt(" catch ", catcher); + if (!catches.isEmpty) printColumn(catches, " catch {", "", "}"); printOpt(" finally ", finalizer) case Throw(expr) => @@ -236,7 +230,7 @@ abstract class TreePrinters { case _ => obj.toString() }) - case EmptyTypeTree() => + case TypeTree() => print(tree.tpe.toString()); case SingletonTypeTree(ref) => @@ -245,11 +239,9 @@ abstract class TreePrinters { case SelectFromTypeTree(qualifier, selector) => print(qualifier); print("#"); print(symName(tree, selector)) - case IntersectionTypeTree(parents) => - printRow(parents, " with ") - - case RefinementTypeTree(base, decls) => - print(base); printColumn(decls, "{", ";", "}") + case CompoundTypeTree(parents, decls) => + printRow(parents, " with "); + if (!decls.isEmpty) printColumn(decls, "{", ";", "}") case AppliedTypeTree(tp, args) => print(tp); printRow(args, "[", ", ", "]") diff --git a/sources/scala/tools/nsc/ast/Trees.scala b/sources/scala/tools/nsc/ast/Trees.scala index 5178ad1dba..16be82347e 100644 --- a/sources/scala/tools/nsc/ast/Trees.scala +++ b/sources/scala/tools/nsc/ast/Trees.scala @@ -16,13 +16,13 @@ class Trees: Global { var pos: int = Position.NOPOS; var tpe: Type = _; - def setPos(p: int): Tree = { pos = p; this } - def setType(tp: Type): Tree = { tpe = tp; this } + def setPos(p: int): this.type = { pos = p; this } + def setType(tp: Type): this.type = { tpe = tp; this } def symbol: Symbol = null; def symbol_=(sym: Symbol): unit = throw new Error("symbol_= inapplicable for " + this); - def setSymbol(sym: Symbol): Tree = { symbol = sym; this } + def setSymbol(sym: Symbol): this.type = { symbol = sym; this } def hasSymbol = false; def isDef = false; @@ -37,6 +37,11 @@ class Trees: Global { buffer.toString() } + override def equals(that: Any): boolean = that match { + case t: Tree => this eq t + case _ => false + } + def duplicate: Tree = new Transformer(new StrictTreeCopier) transform this; } @@ -54,7 +59,7 @@ class Trees: Global { override def isTerm = true; } - abstract class TypeTree extends Tree { + abstract class TypTree extends Tree { override def isType = true; } @@ -64,25 +69,25 @@ class Trees: Global { override def isEmpty = true; } - /** Class definition */ - case class ClassDef(mods: int, name: Name, tparams: List[AbsTypeDef], tp: Tree, impl: Template) - extends DefTree; - /** Package clause */ case class PackageDef(name: Name, stats: List[Tree]) extends DefTree; + /** Class definition */ + case class ClassDef(mods: int, name: Name, tparams: List[AbsTypeDef], tpt: Tree, impl: Template) + extends DefTree; + /** Singleton object definition */ - case class ModuleDef(mods: int, name: Name, tp: Tree, impl: Template) + case class ModuleDef(mods: int, name: Name, impl: Template) extends DefTree; /** Value definition */ - case class ValDef(mods: int, name: Name, tp: Tree, rhs: Tree) + case class ValDef(mods: int, name: Name, tpt: Tree, rhs: Tree) extends DefTree; /** Method definition */ case class DefDef(mods: int, name: Name, tparams: List[AbsTypeDef], - vparams: List[List[ValDef]], tp: Tree, rhs: Tree) + vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree) extends DefTree; /** Abstract type or type parameter */ @@ -119,10 +124,6 @@ class Trees: Global { case class Block(stats: List[Tree], expr: Tree) extends TermTree; - /** Visitor (a sequence of cases), eliminated by TransMatch */ - case class Visitor(cases: List[CaseDef]) - extends TermTree; - /** Case clause in a pattern match, eliminated by TransMatch */ case class CaseDef(pat: Tree, guard: Tree, body: Tree) extends Tree; @@ -137,7 +138,7 @@ class Trees: Global { extends TermTree; /** Bind of a variable to a rhs pattern, eliminated by TransMatch */ - case class Bind(name: Name, rhs: Tree) + case class Bind(name: Name, body: Tree) extends TermTree; /** Anonymous function, eliminated by analyzer */ @@ -152,16 +153,14 @@ class Trees: Global { case class If(cond: Tree, thenp: Tree, elsep: Tree) extends TermTree; - /** Switch, introduced by refcheck */ - case class Switch(test: Tree, tags: List[int], bodies: List[Tree], - default: Tree) - extends TermTree; + /** Pattern matching expression */ + case class Match(selector: Tree, cases: List[CaseDef]) extends TermTree; /** Return expression */ case class Return(expr: Tree) - extends TermTree; + extends SymTree; - case class Try(block: Tree, catcher: Tree, finalizer: Tree) + case class Try(block: Tree, catches: List[CaseDef], finalizer: Tree) extends TermTree; /** Throw expression */ @@ -175,7 +174,7 @@ class Trees: Global { extends TermTree; /** Type annotation, eliminated by explicit outer */ - case class Typed(expr: Tree, tp: Tree) + case class Typed(expr: Tree, tpt: Tree) extends TermTree; /** Type application */ @@ -213,37 +212,33 @@ class Trees: Global { extends TermTree; /** General type term, introduced by RefCheck. */ - case class EmptyTypeTree() extends TypeTree { + case class TypeTree() extends TypTree { override def isEmpty = tpe == null; } /** Singleton type, eliminated by RefCheck */ case class SingletonTypeTree(ref: Tree) - extends TypeTree; + extends TypTree; /** Type selection, eliminated by RefCheck */ case class SelectFromTypeTree(qualifier: Tree, selector: Name) - extends TypeTree with SymTree; + extends TypTree with SymTree; /** Intersection type, eliminated by RefCheck */ - case class IntersectionTypeTree(parents: List[Tree]) - extends TypeTree; - - /** Refinement type, eliminated by RefCheck */ - case class RefinementTypeTree(base: Tree, decls: List[Tree]) - extends TypeTree; + case class CompoundTypeTree(parents: List[Tree], decls: List[Tree]) + extends TypTree; /** Applied type, eliminated by RefCheck */ - case class AppliedTypeTree(tp: Tree, args: List[Tree]) - extends TypeTree; + case class AppliedTypeTree(tpt: Tree, args: List[Tree]) + extends TypTree; /* A standard pattern match case EmptyTree => - case ClassDef(mods, name, tparams, tp, impl) => case PackageDef(name, stats) => - case ModuleDef(mods, name, tp, impl) => (eliminated by refcheck) - case ValDef(mods, name, tp, rhs) => - case DefDef(mods, name, tparams, vparams, tp, rhs) => + case ClassDef(mods, name, tparams, tpt, impl) => + case ModuleDef(mods, name, impl) => (eliminated by refcheck) + case ValDef(mods, name, tpt, rhs) => + case DefDef(mods, name, tparams, vparamss, tpt, rhs) => case AbsTypeDef(mods, name, lo, hi) => (eliminated by erasure) case AliasTypeDef(mods, name, tparams, rhs) => (eliminated by erasure) case LabelDef(name, params, rhs) => @@ -252,20 +247,19 @@ class Trees: Global { case DocDef(comment, definition) => (eliminated by typecheck) case Template(parents, body) => case Block(stats, expr) => - case Visitor(cases) => (eliminated by transmatch) case CaseDef(pat, guard, body) => (eliminated by transmatch) case Sequence(trees) => (eliminated by transmatch) case Alternative(trees) => (eliminated by transmatch) - case Bind(name, rhs) => (eliminated by transmatch) + case Bind(name, body) => (eliminated by transmatch) case Function(vparams, body) => (eliminated by typecheck) case Assign(lhs, rhs) => case If(cond, thenp, elsep) => - case Switch(test, tags, bodies, default) => (introduced by refcheck, transmatch) + case Match(selector, cases) => case Return(expr) => - case Try(block, catcher, finalizer) => + case Try(block, catches, finalizer) => case Throw(expr) => - case New(typeOrTempl) => - case Typed(expr, tp) => (eliminated by erasure) + case New(tpt) => + case Typed(expr, tpt) => (eliminated by erasure) case TypeApply(fun, args) => case Apply(fun, args) => case Super(qual, mixin) => @@ -273,20 +267,19 @@ class Trees: Global { case Select(qualifier, selector) => case Ident(name) => case Literal(value) => - case EmptyTypeTree() => (eliminated by typecheck) + case TypeTree() => case SingletonTypeTree(ref) => (eliminated by typecheck) case SelectFromTypeTree(qualifier, selector) => (eliminated by typecheck) - case IntersectionTypeTree(parents) => (eliminated by typecheck) - case RefinementTypeTree(base, decls) => (eliminated by typecheck) - case AppliedTypeTree(tp, args) => (eliminated by typecheck) + case CompoundTypeTree(parents, decls) => (eliminated by typecheck) + case AppliedTypeTree(tpt, args) => (eliminated by typecheck) */ trait TreeCopier { - def ClassDef(tree: Tree, mods: int, name: Name, tparams: List[AbsTypeDef], tp: Tree, impl: Template): ClassDef; + def ClassDef(tree: Tree, mods: int, name: Name, tparams: List[AbsTypeDef], tpt: Tree, impl: Template): ClassDef; def PackageDef(tree: Tree, name: Name, stats: List[Tree]): PackageDef; - def ModuleDef(tree: Tree, mods: int, name: Name, tp: Tree, impl: Template): ModuleDef; - def ValDef(tree: Tree, mods: int, name: Name, tp: Tree, rhs: Tree): ValDef; - def DefDef(tree: Tree, mods: int, name: Name, tparams: List[AbsTypeDef], vparams: List[List[ValDef]], tp: Tree, rhs: Tree): DefDef; + def ModuleDef(tree: Tree, mods: int, name: Name, impl: Template): ModuleDef; + def ValDef(tree: Tree, mods: int, name: Name, tpt: Tree, rhs: Tree): ValDef; + def DefDef(tree: Tree, mods: int, name: Name, tparams: List[AbsTypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree): DefDef; def AbsTypeDef(tree: Tree, mods: int, name: Name, lo: Tree, hi: Tree): AbsTypeDef; def AliasTypeDef(tree: Tree, mods: int, name: Name, tparams: List[AbsTypeDef], rhs: Tree): AliasTypeDef; def LabelDef(tree: Tree, name: Name, params: List[Ident], rhs: Tree): LabelDef; @@ -295,20 +288,19 @@ class Trees: Global { def DocDef(tree: Tree, comment: String, definition: Tree): DocDef; def Template(tree: Tree, parents: List[Tree], body: List[Tree]): Template; def Block(tree: Tree, stats: List[Tree], expr: Tree): Block; - def Visitor(tree: Tree, cases: List[CaseDef]): Visitor; def CaseDef(tree: Tree, pat: Tree, guard: Tree, body: Tree): CaseDef; def Sequence(tree: Tree, trees: List[Tree]): Sequence; def Alternative(tree: Tree, trees: List[Tree]): Alternative; - def Bind(tree: Tree, name: Name, rhs: Tree): Bind; + def Bind(tree: Tree, name: Name, body: Tree): Bind; def Function(tree: Tree, vparams: List[ValDef], body: Tree): Function; def Assign(tree: Tree, lhs: Tree, rhs: Tree): Assign; def If(tree: Tree, cond: Tree, thenp: Tree, elsep: Tree): If; - def Switch(tree: Tree, test: Tree, tags: List[int], bodies: List[Tree], default: Tree): Switch; + def Match(tree: Tree, selector: Tree, cases: List[CaseDef]): Match; def Return(tree: Tree, expr: Tree): Return; - def Try(tree: Tree, block: Tree, catcher: Tree, finalizer: Tree): Try; + def Try(tree: Tree, block: Tree, catches: List[CaseDef], finalizer: Tree): Try; def Throw(tree: Tree, expr: Tree): Throw; - def New(tree: Tree, typeOrTempl: Tree): New; - def Typed(tree: Tree, expr: Tree, tp: Tree): Typed; + def New(tree: Tree, tpt: Tree): New; + def Typed(tree: Tree, expr: Tree, tpt: Tree): Typed; def TypeApply(tree: Tree, fun: Tree, args: List[Tree]): TypeApply; def Apply(tree: Tree, fun: Tree, args: List[Tree]): Apply; def Super(tree: Tree, qual: Name, mixin: Name): Super; @@ -316,25 +308,24 @@ class Trees: Global { def Select(tree: Tree, qualifier: Tree, selector: Name): Select; def Ident(tree: Tree, name: Name): Ident; def Literal(tree: Tree, value: Any): Literal; - def EmptyTypeTree(tree: Tree): EmptyTypeTree; + def TypeTree(tree: Tree): TypeTree; def SingletonTypeTree(tree: Tree, ref: Tree): SingletonTypeTree; def SelectFromTypeTree(tree: Tree, qualifier: Tree, selector: Name): SelectFromTypeTree; - def IntersectionTypeTree(tree: Tree, parents: List[Tree]): IntersectionTypeTree; - def RefinementTypeTree(tree: Tree, base: Tree, decls: List[Tree]): RefinementTypeTree; - def AppliedTypeTree(tree: Tree, tp: Tree, args: List[Tree]): AppliedTypeTree; + def CompoundTypeTree(tree: Tree, parents: List[Tree], decls: List[Tree]): CompoundTypeTree; + def AppliedTypeTree(tree: Tree, tpt: Tree, args: List[Tree]): AppliedTypeTree; } class StrictTreeCopier extends TreeCopier { - def ClassDef(tree: Tree, mods: int, name: Name, tparams: List[AbsTypeDef], tp: Tree, impl: Template) = - { val t = new ClassDef(mods, name, tparams, tp, impl); t.setPos(tree.pos); t } + def ClassDef(tree: Tree, mods: int, name: Name, tparams: List[AbsTypeDef], tpt: Tree, impl: Template) = + { new ClassDef(mods, name, tparams, tpt, impl).setPos(tree.pos) } def PackageDef(tree: Tree, name: Name, stats: List[Tree]) = { val t = new PackageDef(name, stats); t.setPos(tree.pos); t } - def ModuleDef(tree: Tree, mods: int, name: Name, tp: Tree, impl: Template) = - { val t = new ModuleDef(mods, name, tp, impl); t.setPos(tree.pos); t } - def ValDef(tree: Tree, mods: int, name: Name, tp: Tree, rhs: Tree) = - { val t = new ValDef(mods, name, tp, rhs); t.setPos(tree.pos); t } - def DefDef(tree: Tree, mods: int, name: Name, tparams: List[AbsTypeDef], vparams: List[List[ValDef]], tp: Tree, rhs: Tree) = - { val t = new DefDef(mods, name, tparams, vparams, tp, rhs); t.setPos(tree.pos); t } + def ModuleDef(tree: Tree, mods: int, name: Name, impl: Template) = + { val t = new ModuleDef(mods, name, impl); t.setPos(tree.pos); t } + def ValDef(tree: Tree, mods: int, name: Name, tpt: Tree, rhs: Tree) = + { val t = new ValDef(mods, name, tpt, rhs); t.setPos(tree.pos); t } + def DefDef(tree: Tree, mods: int, name: Name, tparams: List[AbsTypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree) = + { val t = new DefDef(mods, name, tparams, vparamss, tpt, rhs); t.setPos(tree.pos); t } def AbsTypeDef(tree: Tree, mods: int, name: Name, lo: Tree, hi: Tree) = { val t = new AbsTypeDef(mods, name, lo, hi); t.setPos(tree.pos); t } def AliasTypeDef(tree: Tree, mods: int, name: Name, tparams: List[AbsTypeDef], rhs: Tree) = @@ -351,34 +342,32 @@ class Trees: Global { { val t = new Template(parents, body); t.setPos(tree.pos); t } def Block(tree: Tree, stats: List[Tree], expr: Tree) = { val t = new Block(stats, expr); t.setPos(tree.pos); t } - def Visitor(tree: Tree, cases: List[CaseDef]) = - { val t = new Visitor(cases); t.setPos(tree.pos); t } def CaseDef(tree: Tree, pat: Tree, guard: Tree, body: Tree) = { val t = new CaseDef(pat, guard, body); t.setPos(tree.pos); t } def Sequence(tree: Tree, trees: List[Tree]) = { val t = new Sequence(trees); t.setPos(tree.pos); t } def Alternative(tree: Tree, trees: List[Tree]) = { val t = new Alternative(trees); t.setPos(tree.pos); t } - def Bind(tree: Tree, name: Name, rhs: Tree) = - { val t = new Bind(name, rhs); t.setPos(tree.pos); t } + def Bind(tree: Tree, name: Name, body: Tree) = + { val t = new Bind(name, body); t.setPos(tree.pos); t } def Function(tree: Tree, vparams: List[ValDef], body: Tree) = { val t = new Function(vparams, body); t.setPos(tree.pos); t } def Assign(tree: Tree, lhs: Tree, rhs: Tree) = { val t = new Assign(lhs, rhs); t.setPos(tree.pos); t } def If(tree: Tree, cond: Tree, thenp: Tree, elsep: Tree) = { val t = new If(cond, thenp, elsep); t.setPos(tree.pos); t } - def Switch(tree: Tree, test: Tree, tags: List[int], bodies: List[Tree], default: Tree) = - { val t = new Switch(test, tags, bodies, default); t.setPos(tree.pos); t } + def Match(tree: Tree, selector: Tree, cases: List[CaseDef]) = + { val t = new Match(selector, cases); t.setPos(tree.pos); t } def Return(tree: Tree, expr: Tree) = { val t = new Return(expr); t.setPos(tree.pos); t } - def Try(tree: Tree, block: Tree, catcher: Tree, finalizer: Tree) = - { val t = new Try(block, catcher, finalizer); t.setPos(tree.pos); t } + def Try(tree: Tree, block: Tree, catches: List[CaseDef], finalizer: Tree) = + { val t = new Try(block, catches, finalizer); t.setPos(tree.pos); t } def Throw(tree: Tree, expr: Tree) = { val t = new Throw(expr); t.setPos(tree.pos); t } - def New(tree: Tree, typeOrTempl: Tree) = - { val t = new New(typeOrTempl); t.setPos(tree.pos); t } - def Typed(tree: Tree, expr: Tree, tp: Tree) = - { val t = new Typed(expr, tp); t.setPos(tree.pos); t } + def New(tree: Tree, tpt: Tree) = + { val t = new New(tpt); t.setPos(tree.pos); t } + def Typed(tree: Tree, expr: Tree, tpt: Tree) = + { val t = new Typed(expr, tpt); t.setPos(tree.pos); t } def TypeApply(tree: Tree, fun: Tree, args: List[Tree]) = { val t = new TypeApply(fun, args); t.setPos(tree.pos); t } def Apply(tree: Tree, fun: Tree, args: List[Tree]) = @@ -393,185 +382,178 @@ class Trees: Global { { val t = new Ident(name); t.setPos(tree.pos); t } def Literal(tree: Tree, value: Any) = { val t = new Literal(value); t.setPos(tree.pos); t } - def EmptyTypeTree(tree: Tree) = - { val t = new EmptyTypeTree(); t.setPos(tree.pos); t } + def TypeTree(tree: Tree) = + { val t = new TypeTree(); t.setPos(tree.pos); t } def SingletonTypeTree(tree: Tree, ref: Tree) = { val t = new SingletonTypeTree(ref); t.setPos(tree.pos); t } def SelectFromTypeTree(tree: Tree, qualifier: Tree, selector: Name) = { val t = new SelectFromTypeTree(qualifier, selector); t.setPos(tree.pos); t } - def IntersectionTypeTree(tree: Tree, parents: List[Tree]) = - { val t = new IntersectionTypeTree(parents); t.setPos(tree.pos); t } - def RefinementTypeTree(tree: Tree, base: Tree, decls: List[Tree]) = - { val t = new RefinementTypeTree(base, decls); t.setPos(tree.pos); t } - def AppliedTypeTree(tree: Tree, tp: Tree, args: List[Tree]) = - { val t = new AppliedTypeTree(tp, args); t.setPos(tree.pos); t } + def CompoundTypeTree(tree: Tree, parents: List[Tree], decls: List[Tree]) = + { val t = new CompoundTypeTree(parents, decls); t.setPos(tree.pos); t } + def AppliedTypeTree(tree: Tree, tpt: Tree, args: List[Tree]) = + { val t = new AppliedTypeTree(tpt, args); t.setPos(tree.pos); t } } class LazyTreeCopier(copy: TreeCopier) extends TreeCopier { def this() = this(new StrictTreeCopier); - def ClassDef(tree: Tree, mods: int, name: Name, tparams: List[AbsTypeDef], tp: Tree, impl: Template) = tree match { - case t @ ClassDef(mods0, name0, tparams0, tp0, impl0) - if (mods0 == mods && name0 == name && tparams0 == tparams && tp0 == tp && impl0 == impl) => t - case _ => copy.ClassDef(tree, mods, name, tparams, tp, impl) + def ClassDef(tree: Tree, mods: int, name: Name, tparams: List[AbsTypeDef], tpt: Tree, impl: Template) = tree match { + case t @ ClassDef(mods0, name0, tparams0, tpt0, impl0) + if (mods0 == mods && (name0 == name) && (tparams0 == tparams) && (tpt0 == tpt) && (impl0 == impl)) => t + case _ => copy.ClassDef(tree, mods, name, tparams, tpt, impl) } def PackageDef(tree: Tree, name: Name, stats: List[Tree]) = tree match { case t @ PackageDef(name0, stats0) - if (name0 == name && stats0 == stats) => t + if ((name0 == name) && (stats0 == stats)) => t case _ => copy.PackageDef(tree, name, stats) } - def ModuleDef(tree: Tree, mods: int, name: Name, tp: Tree, impl: Template) = tree match { - case t @ ModuleDef(mods0, name0, tp0, impl0) - if (mods0 == mods && name0 == name && tp0 == tp && impl0 == impl) => t - case _ => copy.ModuleDef(tree, mods, name, tp, impl) + def ModuleDef(tree: Tree, mods: int, name: Name, impl: Template) = tree match { + case t @ ModuleDef(mods0, name0, impl0) + if (mods0 == mods && (name0 == name) && (impl0 == impl)) => t + case _ => copy.ModuleDef(tree, mods, name, impl) } - def ValDef(tree: Tree, mods: int, name: Name, tp: Tree, rhs: Tree) = tree match { - case t @ ValDef(mods0, name0, tp0, rhs0) - if (mods0 == mods && name0 == name && tp0 == tp && rhs0 == rhs) => t - case _ => copy.ValDef(tree, mods, name, tp, rhs) + def ValDef(tree: Tree, mods: int, name: Name, tpt: Tree, rhs: Tree) = tree match { + case t @ ValDef(mods0, name0, tpt0, rhs0) + if (mods0 == mods && (name0 == name) && (tpt0 == tpt) && (rhs0 == rhs)) => t + case _ => copy.ValDef(tree, mods, name, tpt, rhs) } - def DefDef(tree: Tree, mods: int, name: Name, tparams: List[AbsTypeDef], vparams: List[List[ValDef]], tp: Tree, rhs: Tree) = tree match { - case t @ DefDef(mods0, name0, tparams0, vparams0, tp0, rhs0) - if (mods0 == mods && name0 == name && tparams0 == tparams && vparams0 == vparams && tp0 == tp && rhs == rhs0) => t - case _ => copy.DefDef(tree, mods, name, tparams, vparams, tp, rhs) + def DefDef(tree: Tree, mods: int, name: Name, tparams: List[AbsTypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree) = tree match { + case t @ DefDef(mods0, name0, tparams0, vparamss0, tpt0, rhs0) + if (mods0 == mods && (name0 == name) && (tparams0 == tparams) && (vparamss0 == vparamss) && (tpt0 == tpt) && (rhs == rhs0)) => t + case _ => copy.DefDef(tree, mods, name, tparams, vparamss, tpt, rhs) } def AbsTypeDef(tree: Tree, mods: int, name: Name, lo: Tree, hi: Tree) = tree match { case t @ AbsTypeDef(mods0, name0, lo0, hi0) - if (mods0 == mods && name0 == name && lo0 == lo && hi0 == hi) => t + if (mods0 == mods && (name0 == name) && (lo0 == lo) && (hi0 == hi)) => t case _ => copy.AbsTypeDef(tree, mods, name, lo, hi) } def AliasTypeDef(tree: Tree, mods: int, name: Name, tparams: List[AbsTypeDef], rhs: Tree) = tree match { case t @ AliasTypeDef(mods0, name0, tparams0, rhs0) - if (mods0 == mods && name0 == name && tparams0 == tparams && rhs0 == rhs) => t + if (mods0 == mods && (name0 == name) && (tparams0 == tparams) && (rhs0 == rhs)) => t case _ => copy.AliasTypeDef(tree, mods, name, tparams, rhs) } def LabelDef(tree: Tree, name: Name, params: List[Ident], rhs: Tree) = tree match { case t @ LabelDef(name0, params0, rhs0) - if (name0 == name && params0 == params && rhs0 == rhs) => t + if ((name0 == name) && (params0 == params) && (rhs0 == rhs)) => t case _ => copy.LabelDef(tree, name, params, rhs) } def Import(tree: Tree, expr: Tree, selectors: List[Pair[Name, Name]]) = tree match { case t @ Import(expr0, selectors0) - if (expr0 == expr && selectors0 == selectors) => t + if ((expr0 == expr) && (selectors0 == selectors)) => t case _ => copy.Import(tree, expr, selectors) } def Attributed(tree: Tree, attribute: Tree, definition: Tree) = tree match { case t @ Attributed(attribute0, definition0) - if (attribute0 == attribute && definition0 == definition) => t + if ((attribute0 == attribute) && (definition0 == definition)) => t case _ => copy.Attributed(tree, attribute, definition) } def DocDef(tree: Tree, comment: String, definition: Tree) = tree match { case t @ DocDef(comment0, definition0) - if (comment0 == comment && definition0 == definition) => t + if ((comment0 == comment) && (definition0 == definition)) => t case _ => copy.DocDef(tree, comment, definition) } def Template(tree: Tree, parents: List[Tree], body: List[Tree]) = tree match { case t @ Template(parents0, body0) - if (parents0 == parents && body0 == body) => t + if ((parents0 == parents) && (body0 == body)) => t case _ => copy.Template(tree, parents, body) } def Block(tree: Tree, stats: List[Tree], expr: Tree) = tree match { case t @ Block(stats0, expr0) - if (stats0 == stats && expr0 == expr) => t + if ((stats0 == stats) && (expr0 == expr)) => t case _ => copy.Block(tree, stats, expr) } - def Visitor(tree: Tree, cases: List[CaseDef]) = tree match { - case t @ Visitor(cases0) - if (cases == cases0) => t - case _ => copy.Visitor(tree, cases) - } def CaseDef(tree: Tree, pat: Tree, guard: Tree, body: Tree) = tree match { case t @ CaseDef(pat0, guard0, body0) - if (pat0 == pat && guard0 == guard && body0 == body) => t + if ((pat0 == pat) && (guard0 == guard) && (body0 == body)) => t case _ => copy.CaseDef(tree, pat, guard, body) } def Sequence(tree: Tree, trees: List[Tree]) = tree match { case t @ Sequence(trees0) - if (trees0 == trees) => t + if ((trees0 == trees)) => t case _ => copy.Sequence(tree, trees) } def Alternative(tree: Tree, trees: List[Tree]) = tree match { case t @ Alternative(trees0) - if (trees0 == trees) => t + if ((trees0 == trees)) => t case _ => copy.Alternative(tree, trees) } - def Bind(tree: Tree, name: Name, rhs: Tree) = tree match { - case t @ Bind(name0, rhs0) - if (name0 == name && rhs0 == rhs) => t - case _ => copy.Bind(tree, name, rhs) + def Bind(tree: Tree, name: Name, body: Tree) = tree match { + case t @ Bind(name0, body0) + if ((name0 == name) && (body0 == body)) => t + case _ => copy.Bind(tree, name, body) } def Function(tree: Tree, vparams: List[ValDef], body: Tree) = tree match { case t @ Function(vparams0, body0) - if (vparams0 == vparams && body0 == body) => t + if ((vparams0 == vparams) && (body0 == body)) => t case _ => copy.Function(tree, vparams, body) } def Assign(tree: Tree, lhs: Tree, rhs: Tree) = tree match { case t @ Assign(lhs0, rhs0) - if (lhs0 == lhs && rhs0 == rhs) => t + if ((lhs0 == lhs) && (rhs0 == rhs)) => t case _ => copy.Assign(tree, lhs, rhs) } def If(tree: Tree, cond: Tree, thenp: Tree, elsep: Tree) = tree match { case t @ If(cond0, thenp0, elsep0) - if (cond0 == cond && thenp0 == thenp && elsep0 == elsep) => t + if ((cond0 == cond) && (thenp0 == thenp) && (elsep0 == elsep)) => t case _ => copy.If(tree, cond, thenp, elsep) } - def Switch(tree: Tree, test: Tree, tags: List[int], bodies: List[Tree], default: Tree) = tree match { - case t @ Switch(test0, tags0, bodies0, default0) - if (test0 == test && tags0 == tags && bodies0 == bodies && default0 == default) => t - case _ => copy.Switch(tree, test, tags, bodies, default) + def Match(tree: Tree, selector: Tree, cases: List[CaseDef]) = tree match { + case t @ Match(selector0, cases0) + if ((selector0 == selector) && (cases0 == cases)) => t + case _ => copy.Match(tree, selector, cases) } def Return(tree: Tree, expr: Tree) = tree match { case t @ Return(expr0) - if (expr0 == expr) => t + if ((expr0 == expr)) => t case _ => copy.Return(tree, expr) } - def Try(tree: Tree, block: Tree, catcher: Tree, finalizer: Tree) = tree match { - case t @ Try(block0, catcher0, finalizer0) - if (block0 == block && catcher0 == catcher && finalizer0 == finalizer) => t - case _ => copy.Try(tree, block, catcher, finalizer) + def Try(tree: Tree, block: Tree, catches: List[CaseDef], finalizer: Tree) = tree match { + case t @ Try(block0, catches0, finalizer0) + if ((block0 == block) && (catches0 == catches) && (finalizer0 == finalizer)) => t + case _ => copy.Try(tree, block, catches, finalizer) } def Throw(tree: Tree, expr: Tree) = tree match { case t @ Throw(expr0) - if (expr0 == expr) => t + if ((expr0 == expr)) => t case _ => copy.Throw(tree, expr) } - def New(tree: Tree, typeOrTempl: Tree) = tree match { - case t @ New(typeOrTempl0) - if (typeOrTempl0 == typeOrTempl) => t - case _ => copy.New(tree, typeOrTempl) + def New(tree: Tree, tpt: Tree) = tree match { + case t @ New(tpt0) + if ((tpt0 == tpt)) => t + case _ => copy.New(tree, tpt) } - def Typed(tree: Tree, expr: Tree, tp: Tree) = tree match { - case t @ Typed(expr0, tp0) - if (expr0 == expr && tp0 == tp) => t - case _ => copy.Typed(tree, expr, tp) + def Typed(tree: Tree, expr: Tree, tpt: Tree) = tree match { + case t @ Typed(expr0, tpt0) + if ((expr0 == expr) && (tpt0 == tpt)) => t + case _ => copy.Typed(tree, expr, tpt) } def TypeApply(tree: Tree, fun: Tree, args: List[Tree]) = tree match { case t @ TypeApply(fun0, args0) - if (fun0 == fun && args0 == args) => t + if ((fun0 == fun) && (args0 == args)) => t case _ => copy.TypeApply(tree, fun, args) } def Apply(tree: Tree, fun: Tree, args: List[Tree]) = tree match { case t @ Apply(fun0, args0) - if (fun0 == fun && args0 == args) => t + if ((fun0 == fun) && (args0 == args)) => t case _ => copy.Apply(tree, fun, args) } def Super(tree: Tree, qual: Name, mixin: Name) = tree match { case t @ Super(qual0, mixin0) - if (qual0 == qual && mixin0 == mixin) => t + if ((qual0 == qual) && (mixin0 == mixin)) => t case _ => copy.Super(tree, qual, mixin) } def This(tree: Tree, qual: Name) = tree match { case t @ This(qual0) - if (qual0 == qual) => t + if ((qual0 == qual)) => t case _ => copy.This(tree, qual) } def Select(tree: Tree, qualifier: Tree, selector: Name) = tree match { case t @ Select(qualifier0, selector0) - if (qualifier0 == qualifier && selector0 == selector) => t + if ((qualifier0 == qualifier) && (selector0 == selector)) => t case _ => copy.Select(tree, qualifier, selector) } def Ident(tree: Tree, name: Name) = tree match { case t @ Ident(name0) - if (name0 == name) => t + if ((name0 == name)) => t case _ => copy.Ident(tree, name) } def Literal(tree: Tree, value: Any) = tree match { @@ -579,34 +561,29 @@ class Trees: Global { if (value0 == value) => t case _ => copy.Literal(tree, value) } - def EmptyTypeTree(tree: Tree) = tree match { - case t @ EmptyTypeTree() => t - case _ => copy.EmptyTypeTree(tree) + def TypeTree(tree: Tree) = tree match { + case t @ TypeTree() => t + case _ => copy.TypeTree(tree) } def SingletonTypeTree(tree: Tree, ref: Tree) = tree match { case t @ SingletonTypeTree(ref0) - if (ref0 == ref) => t + if ((ref0 == ref)) => t case _ => copy.SingletonTypeTree(tree, ref) } def SelectFromTypeTree(tree: Tree, qualifier: Tree, selector: Name) = tree match { case t @ SelectFromTypeTree(qualifier0, selector0) - if (qualifier0 == qualifier && selector0 == selector) => t + if ((qualifier0 == qualifier) && (selector0 == selector)) => t case _ => copy.SelectFromTypeTree(tree, qualifier, selector) } - def IntersectionTypeTree(tree: Tree, parents: List[Tree]) = tree match { - case t @ IntersectionTypeTree(parents0) - if (parents0 == parents) => t - case _ => copy.IntersectionTypeTree(tree, parents) - } - def RefinementTypeTree(tree: Tree, base: Tree, decls: List[Tree]) = tree match { - case t @ RefinementTypeTree(base0, decls0) - if (base0 == base && decls0 == decls) => t - case _ => copy.RefinementTypeTree(tree, base, decls) + def CompoundTypeTree(tree: Tree, parents: List[Tree], decls: List[Tree]) = tree match { + case t @ CompoundTypeTree(parents0, decls0) + if ((parents0 == parents) && (decls0 == decls)) => t + case _ => copy.CompoundTypeTree(tree, parents, decls) } - def AppliedTypeTree(tree: Tree, tp: Tree, args: List[Tree]) = tree match { - case t @ AppliedTypeTree(tp0, args0) - if (tp0 == tp && args0 == args) => t - case _ => copy.AppliedTypeTree(tree, tp, args) + def AppliedTypeTree(tree: Tree, tpt: Tree, args: List[Tree]) = tree match { + case t @ AppliedTypeTree(tpt0, args0) + if ((tpt0 == tpt) && (args0 == args)) => t + case _ => copy.AppliedTypeTree(tree, tpt, args) } } @@ -615,16 +592,16 @@ class Trees: Global { def transform(tree: Tree): Tree = tree match { case EmptyTree => tree - case ClassDef(mods, name, tparams, tp, impl) => - copy.ClassDef(tree, mods, name, transformAbsTypeDefs(tparams), transform(tp), transformTemplate(impl)) + case ClassDef(mods, name, tparams, tpt, impl) => + copy.ClassDef(tree, mods, name, transformAbsTypeDefs(tparams), transform(tpt), transformTemplate(impl)) case PackageDef(name, stats) => copy.PackageDef(tree, name, transformTrees(stats)) - case ModuleDef(mods, name, tp, impl) => - copy.ModuleDef(tree, mods, name, transform(tp), transformTemplate(impl)) - case ValDef(mods, name, tp, rhs) => - copy.ValDef(tree, mods, name, transform(tp), transform(rhs)) - case DefDef(mods, name, tparams, vparams, tp, rhs) => - copy.DefDef(tree, mods, name, transformAbsTypeDefs(tparams), transformValDefss(vparams), transform(tp), transform(rhs)) + case ModuleDef(mods, name, impl) => + copy.ModuleDef(tree, mods, name, transformTemplate(impl)) + case ValDef(mods, name, tpt, rhs) => + copy.ValDef(tree, mods, name, transform(tpt), transform(rhs)) + case DefDef(mods, name, tparams, vparamss, tpt, rhs) => + copy.DefDef(tree, mods, name, transformAbsTypeDefs(tparams), transformValDefss(vparamss), transform(tpt), transform(rhs)) case AbsTypeDef(mods, name, lo, hi) => copy.AbsTypeDef(tree, mods, name, transform(lo), transform(hi)) case AliasTypeDef(mods, name, tparams, rhs) => @@ -641,34 +618,32 @@ class Trees: Global { copy.Template(tree, transformTrees(parents), transformTrees(body)) case Block(stats, expr) => copy.Block(tree, transformTrees(stats), transform(expr)) - case Visitor(cases) => - copy.Visitor(tree, transformCaseDefs(cases)) case CaseDef(pat, guard, body) => copy.CaseDef(tree, transform(pat), transform(guard), transform(body)) case Sequence(trees) => copy.Sequence(tree, transformTrees(trees)) case Alternative(trees) => copy.Alternative(tree, transformTrees(trees)) - case Bind(name, rhs) => - copy.Bind(tree, name, transform(rhs)) + case Bind(name, body) => + copy.Bind(tree, name, transform(body)) case Function(vparams, body) => copy.Function(tree, transformValDefs(vparams), transform(body)) case Assign(lhs, rhs) => copy.Assign(tree, transform(lhs), transform(rhs)) case If(cond, thenp, elsep) => copy.If(tree, transform(cond), transform(thenp), transform(elsep)) - case Switch(test, tags, bodies, default) => - copy.Switch(tree, transform(test), tags, transformTrees(bodies), transform(default)) + case Match(selector, cases) => + copy.Match(tree, transform(selector), transformCaseDefs(cases)) case Return(expr) => copy.Return(tree, transform(expr)) - case Try(block, catcher, finalizer) => - copy.Try(tree, transform(block), transform(catcher), transform(finalizer)) + case Try(block, catches, finalizer) => + copy.Try(tree, transform(block), transformCaseDefs(catches), transform(finalizer)) case Throw(expr) => copy.Throw(tree, transform(expr)) - case New(typeOrTempl) => - copy.New(tree, transform(typeOrTempl)) - case Typed(expr, tp) => - copy.Typed(tree, transform(expr), transform(tp)) + case New(tpt) => + copy.New(tree, transform(tpt)) + case Typed(expr, tpt) => + copy.Typed(tree, transform(expr), transform(tpt)) case TypeApply(fun, args) => copy.TypeApply(tree, transform(fun), transformTrees(args)) case Apply(fun, args) => @@ -683,48 +658,46 @@ class Trees: Global { copy.Ident(tree, name) case Literal(value) => copy.Literal(tree, value) - case EmptyTypeTree() => - copy.EmptyTypeTree(tree) + case TypeTree() => + copy.TypeTree(tree) case SingletonTypeTree(ref) => copy.SingletonTypeTree(tree, transform(ref)) case SelectFromTypeTree(qualifier, selector) => copy.SelectFromTypeTree(tree, transform(qualifier), selector) - case IntersectionTypeTree(parents) => - copy.IntersectionTypeTree(tree, transformTrees(parents)) - case RefinementTypeTree(base, decls) => - copy.RefinementTypeTree(tree, transform(base), transformTrees(decls)) - case AppliedTypeTree(tp, args) => - copy.AppliedTypeTree(tree, transform(tp), transformTrees(args)) + case CompoundTypeTree(parents, decls) => + copy.CompoundTypeTree(tree, transformTrees(parents), transformTrees(decls)) + case AppliedTypeTree(tpt, args) => + copy.AppliedTypeTree(tree, transform(tpt), transformTrees(args)) } def transformTrees(trees: List[Tree]): List[Tree] = - List.transform(trees)(tree => transform(tree)); + trees mapConserve (tree => transform(tree)); def transformTemplate(tree: Template): Template = transform(tree: Tree).asInstanceOf[Template]; def transformAbsTypeDefs(trees: List[AbsTypeDef]): List[AbsTypeDef] = - List.transform(trees)(tree => transform(tree).asInstanceOf[AbsTypeDef]); + trees mapConserve (tree => transform(tree).asInstanceOf[AbsTypeDef]); def transformValDefs(trees: List[ValDef]): List[ValDef] = - List.transform(trees)(tree => transform(tree).asInstanceOf[ValDef]); + trees mapConserve (tree => transform(tree).asInstanceOf[ValDef]); def transformValDefss(treess: List[List[ValDef]]): List[List[ValDef]] = - List.transform(treess)(tree => transformValDefs(tree)); + treess mapConserve (tree => transformValDefs(tree)); def transformCaseDefs(trees: List[CaseDef]): List[CaseDef] = - List.transform(trees)(tree => transform(tree).asInstanceOf[CaseDef]); + trees mapConserve (tree => transform(tree).asInstanceOf[CaseDef]); def transformIdents(trees: List[Ident]): List[Ident] = - List.transform(trees)(tree => transform(tree).asInstanceOf[Ident]); + trees mapConserve (tree => transform(tree).asInstanceOf[Ident]); } class Traverser { def traverse(tree: Tree): unit = tree match { - case ClassDef(mods, name, tparams, tp, impl) => - traverseTrees(tparams); traverse(tp); traverse(impl) + case ClassDef(mods, name, tparams, tpt, impl) => + traverseTrees(tparams); traverse(tpt); traverse(impl) case PackageDef(name, stats) => traverseTrees(stats) - case ModuleDef(mods, name, tp, impl) => - traverse(tp); traverse(impl) - case ValDef(mods, name, tp, rhs) => - traverse(tp); traverse(rhs) - case DefDef(mods, name, tparams, vparams, tp, rhs) => - traverseTrees(tparams); traverseTreess(vparams); traverse(tp); traverse(rhs) + case ModuleDef(mods, name, impl) => + traverse(impl) + case ValDef(mods, name, tpt, rhs) => + traverse(tpt); traverse(rhs) + case DefDef(mods, name, tparams, vparamss, tpt, rhs) => + traverseTrees(tparams); traverseTreess(vparamss); traverse(tpt); traverse(rhs) case AbsTypeDef(mods, name, lo, hi) => traverse(lo); traverse(hi); case AliasTypeDef(mods, name, tparams, rhs) => @@ -741,34 +714,32 @@ class Trees: Global { traverseTrees(parents); traverseTrees(body) case Block(stats, expr) => traverseTrees(stats); traverse(expr) - case Visitor(cases) => - traverseTrees(cases) case CaseDef(pat, guard, body) => traverse(pat); traverse(guard); traverse(body) case Sequence(trees) => traverseTrees(trees) case Alternative(trees) => traverseTrees(trees) - case Bind(name, rhs) => - traverse(rhs) + case Bind(name, body) => + traverse(body) case Function(vparams, body) => traverseTrees(vparams); traverse(body) case Assign(lhs, rhs) => traverse(lhs); traverse(rhs) case If(cond, thenp, elsep) => traverse(cond); traverse(thenp); traverse(elsep) - case Switch(test, tags, bodies, default) => - traverse(test); traverseTrees(bodies); traverse(default) + case Match(selector, cases) => + traverse(selector); traverseTrees(cases) case Return(expr) => traverse(expr) - case Try(block, catcher, finalizer) => - traverse(block); traverse(catcher); traverse(finalizer) + case Try(block, catches, finalizer) => + traverse(block); traverseTrees(catches); traverse(finalizer) case Throw(expr) => traverse(expr) - case New(typeOrTempl) => - traverse(typeOrTempl) - case Typed(expr, tp) => - traverse(expr); traverse(tp) + case New(tpt) => + traverse(tpt) + case Typed(expr, tpt) => + traverse(expr); traverse(tpt) case TypeApply(fun, args) => traverse(fun); traverseTrees(args) case Apply(fun, args) => @@ -779,13 +750,11 @@ class Trees: Global { traverse(ref) case SelectFromTypeTree(qualifier, selector) => traverse(qualifier) - case IntersectionTypeTree(parents) => - traverseTrees(parents) - case RefinementTypeTree(base, decls) => - traverse(base); traverseTrees(decls) - case AppliedTypeTree(tp, args) => - traverse(tp); traverseTrees(args) - case EmptyTree | Super(_, _) | This(_) | Ident(_) | Literal(_) | EmptyTypeTree() => + case CompoundTypeTree(parents, decls) => + traverseTrees(parents); traverseTrees(decls) + case AppliedTypeTree(tpt, args) => + traverse(tpt); traverseTrees(args) + case EmptyTree | Super(_, _) | This(_) | Ident(_) | Literal(_) | TypeTree() => {} } diff --git a/sources/scala/tools/nsc/ast/parser/Lexical.scala b/sources/scala/tools/nsc/ast/parser/Lexical.scala index d7ab47f91a..318ae77395 100644 --- a/sources/scala/tools/nsc/ast/parser/Lexical.scala +++ b/sources/scala/tools/nsc/ast/parser/Lexical.scala @@ -729,6 +729,7 @@ abstract class Lexical: ParserPhase { enterKeyword("for", FOR); enterKeyword("if", IF); enterKeyword("import", IMPORT); + enterKeyword("match", MATCH); enterKeyword("new", NEW); enterKeyword("null", NULL); enterKeyword("object", OBJECT); diff --git a/sources/scala/tools/nsc/ast/parser/Syntactic.scala b/sources/scala/tools/nsc/ast/parser/Syntactic.scala index b819d0e6e6..9f9e34d48e 100755 --- a/sources/scala/tools/nsc/ast/parser/Syntactic.scala +++ b/sources/scala/tools/nsc/ast/parser/Syntactic.scala @@ -57,10 +57,12 @@ abstract class Syntactic: ParserPhase { object treeBuilder extends TreeBuilder { val global: Syntactic.this.global.type = Syntactic.this.global; - def freshName(): Name = unit.fresh.newName("x$"); + def freshName(prefix: String): Name = unit.fresh.newName(prefix); } import treeBuilder._; + + /** this is the general parse method */ def parse(): List[Tree] = { @@ -119,7 +121,7 @@ abstract class Syntactic: ParserPhase { pos } - def errorTypeTree = EmptyTypeTree().setType(ErrorType).setPos(in.pos); + def errorTypeTree = TypeTree().setType(ErrorType).setPos(in.pos); def errorTermTree = Literal(null).setPos(in.pos); def errorPatternTree = Ident(nme.WILDCARD).setPos(in.pos); @@ -180,7 +182,7 @@ abstract class Syntactic: ParserPhase { /** Convert tree to formal parameter list */ def convertToParams(t: Tree): List[ValDef] = t match { - case Function(params, EmptyTypeTree()) => + case Function(params, TypeTree()) => params case Ident(_) | Typed(Ident(_), _) => List(convertToParam(t)); @@ -197,7 +199,7 @@ abstract class Syntactic: ParserPhase { atPos(tree.pos) { tree match { case Ident(name) => - ValDef(Flags.PARAM, name, EmptyTypeTree(), EmptyTree) + ValDef(Flags.PARAM, name, TypeTree(), EmptyTree) case Typed(Ident(name), tpe) => ValDef(Flags.PARAM, name, tpe, EmptyTree) case _ => @@ -219,16 +221,9 @@ abstract class Syntactic: ParserPhase { errorTypeTree } - /** Complete unapplied constructor with `()' arguments - */ - def applyConstr(t: Tree): Tree = t match { - case Apply(_, _) => t - case _ => Apply(t, List()) setPos t.pos - } - /** make closure from tree */ def makeClosure(tree: Tree): Tree = { - val pname = freshName(); + val pname: Name = unit.fresh.newName("x$"); def insertParam(tree: Tree): Tree = tree match { case Ident(name) => Select(Ident(pname), name) @@ -243,7 +238,7 @@ abstract class Syntactic: ParserPhase { errorTermTree } Function( - List(ValDef(Flags.PARAM, pname, EmptyTypeTree(), EmptyTree)), + List(ValDef(Flags.PARAM, pname, TypeTree(), EmptyTree)), insertParam(tree)) } @@ -445,13 +440,13 @@ abstract class Syntactic: ParserPhase { */ def typedOpt(): Tree = if (in.token == COLON) { in.nextToken(); typ() } - else EmptyTypeTree(); + else TypeTree(); /** SimpleTypedOpt ::= [`:' SimpleType] */ def simpleTypedOpt(): Tree = if (in.token == COLON) { in.nextToken(); simpleType() } - else EmptyTypeTree(); + else TypeTree(); /** Types ::= Type {`,' Type} */ @@ -498,17 +493,14 @@ abstract class Syntactic: ParserPhase { */ def type1(): Tree = { val pos = in.pos; - var t = simpleType(); - if (in.token == WITH) { - val ts = new ListBuffer[Tree] + t; - while (in.token == WITH) { - in.nextToken(); ts += simpleType() - } - t = atPos(pos) { IntersectionTypeTree(ts.toList) } + var ts = new ListBuffer[Tree] + simpleType(); + while (in.token == WITH) { + in.nextToken(); ts += simpleType() + } + atPos(pos) { + if (in.token == LBRACE) CompoundTypeTree(ts.toList, refinement()) + else makeIntersectionTypeTree(ts.toList) } - if (in.token == LBRACE) - t = atPos(pos) { RefinementTypeTree(t, refinement()) } - t } /** SimpleType ::= SimpleType TypeArgs @@ -578,7 +570,7 @@ abstract class Syntactic: ParserPhase { * ResultExpr ::= Bindings `=>' Block * | Expr1 * Expr1 ::= (' Expr `)' Expr [[`;'] else Expr] - * | try `{' block `}' [catch Expr] [finally Expr] + * | try `{' block `}' [catch `{' caseClauses `}'] [finally Expr] * | while `(' Expr `)' Expr * | do Expr [`;'] while `(' Expr `)' * | for `(' Enumerators `)' (do | yield) Expr @@ -588,6 +580,7 @@ abstract class Syntactic: ParserPhase { * | SimpleExpr ArgumentExprs `=' Expr * | `.' SimpleExpr * | PostfixExpr [`:' Type1] + * | PostfixExpr match `{' caseClauses `}' * Bindings ::= Id [`:' Type1] * | `(' [Binding {`,' Binding}] `)' * Binding ::= Id [`:' Type] @@ -611,13 +604,18 @@ abstract class Syntactic: ParserPhase { accept(LBRACE); val body = block(); accept(RBRACE); - val catcher = - if (in.token == CATCH) { in.nextToken(); expr() } - else EmptyTree; + val catches = + if (in.token == CATCH) { + in.nextToken(); + accept(LBRACE); + val cases = caseClauses(); + accept(RBRACE); + cases + } else List(); val finalizer = if (in.token == FINALLY) { in.nextToken(); expr() } else EmptyTree; - Try(body, catcher, finalizer) + Try(body, catches, finalizer) } } else if (in.token == WHILE) { val lname: Name = "label$" + loopNestingDepth; @@ -668,7 +666,7 @@ abstract class Syntactic: ParserPhase { if (in.token == EQUALS) { t match { case Ident(_) | Select(_, _) | Apply(_, _) => - t = atPos(in.skipToken()) { Assign(t, expr()) } + t = atPos(in.skipToken()) { makeAssign(t, expr()) } case _ => } } else if (in.token == COLON) { @@ -686,7 +684,14 @@ abstract class Syntactic: ParserPhase { } else { t = atPos(pos) { Typed(t, type1()) } } - } + } else if (in.token == MATCH) { + t = atPos(in.skipToken()) { + accept(LBRACE); + val cases = caseClauses(); + accept(RBRACE); + Match(t, cases): Tree + } + } if (in.token == ARROW) { t = atPos(in.skipToken()) { Function(convertToParams(t), if (isInBlock) block() else expr()) @@ -769,7 +774,7 @@ abstract class Syntactic: ParserPhase { accept(RPAREN); if (in.token == ARROW) { t = atPos(pos) { - Function(ts.toList map convertToParam, EmptyTypeTree()) + Function(ts.toList map convertToParam, TypeTree()) } } else { syntaxError(commapos, "`)' expected", false); @@ -790,11 +795,7 @@ abstract class Syntactic: ParserPhase { parents += simpleType() } val stats = if (in.token == LBRACE) templateBody() else List(); - val ps = parents.toList; - if (ps.length == 1 && stats.isEmpty) - Apply(Select(New(ps.head), nme.CONSTRUCTOR), args) - else - New(Template(ps, makeSuperCall(args) :: stats)) + makeNew(parents.toList, stats, args) } case _ => syntaxError("illegal start of simple expression", true); @@ -834,22 +835,13 @@ abstract class Syntactic: ParserPhase { } } - /** BlockExpr ::= `{' CaseClause {CaseClause} `}' - * | `{' Block `}' + /** BlockExpr ::= `{' CaseClauses | Block `}' */ def blockExpr(): Tree = { - val res = - atPos(accept(LBRACE)) { - if (in.token == CASE) { - var stats: List[CaseDef] = List(); - do { - stats = caseClause() :: stats; - } while (in.token == CASE); - Visitor(stats.reverse) - } else { - block() - } - } + val res = atPos(accept(LBRACE)) { + if (in.token == CASE) makeVisitor(caseClauses()) + else block() + } accept(RBRACE); res } @@ -858,6 +850,15 @@ abstract class Syntactic: ParserPhase { */ def block(): Tree = makeBlock(blockStatSeq(new ListBuffer[Tree])); + /** CaseClauses ::= CaseClause {CaseClause} + */ + def caseClauses(): List[CaseDef] = { + val ts = new ListBuffer[CaseDef]; + do { ts += caseClause(); + } while (in.token == CASE); + ts.toList + } + /** caseClause : =>= case Pattern [if PostfixExpr] `=>' Block */ def caseClause(): CaseDef = @@ -1381,7 +1382,7 @@ abstract class Syntactic: ParserPhase { val vparams = List(paramClause(false)); accept(EQUALS); DefDef( - mods, nme.CONSTRUCTOR, List(), vparams, EmptyTypeTree(), constrExpr()) + mods, nme.CONSTRUCTOR, List(), vparams, TypeTree(), constrExpr()) }) else { var newmods = mods; @@ -1481,39 +1482,27 @@ abstract class Syntactic: ParserPhase { if ((mods & Flags.TRAIT) != 0) List() else paramClauses(true)) } while (in.token == COMMA); val thistpe = simpleTypedOpt(); - val Template(parents, body) = classTemplate(mods); + val template = classTemplate(mods); for (val Tuple4(pos, name, tparams, vparamss) <- lhs.toList) yield atPos(pos) { - val body1 = - if ((mods & Flags.TRAIT) != 0) body - else { - val vparamss1 = vparamss map (.map (vd => - ValDef(Flags.PARAM, vd.name, vd.tp.duplicate, EmptyTree))); - val constr: Tree = DefDef( - mods & Flags.CONSTRFLAGS | Flags.SYNTHETIC, nme.CONSTRUCTOR, List(), - if (vparamss1.isEmpty) List(List()) else vparamss1, - EmptyTypeTree(), EmptyTree); - val vparams: List[Tree] = - for (val vparams <- vparamss; val vparam <- vparams) yield vparam; - vparams ::: constr :: body - } - ClassDef(mods, name, tparams, thistpe.duplicate, Template(parents, body1)) + val template1 = if ((mods & Flags.TRAIT) != 0) template + else addConstructor(mods, vparamss, template); + ClassDef(mods, name, tparams, thistpe.duplicate, template1.duplicate.asInstanceOf[Template]) } } - /** ObjectDef ::= Id { , Id } [`:' SimpleType] ClassTemplate + /** ObjectDef ::= Id { , Id } ClassTemplate */ def objectDef(mods: int): List[Tree] = { val lhs = new ListBuffer[Pair[Int, Name]]; do { lhs += Pair(in.skipToken(), ident()); } while (in.token == COMMA); - val thistpe = simpleTypedOpt(); val template = classTemplate(mods); for (val Pair(pos, name) <- lhs.toList) yield atPos(pos) { - ModuleDef(mods, name, thistpe.duplicate, - template.duplicate.asInstanceOf[Template]) + val template1 = addConstructor(mods, List(), template); + ModuleDef(mods, name, template1.duplicate.asInstanceOf[Template]) } } @@ -1548,17 +1537,6 @@ abstract class Syntactic: ParserPhase { ////////// TEMPLATES //////////////////////////////////////////////////////////// - /** Constr ::= StableId [TypeArgs] [`(' [Exprs] `)'] - */ - def constr(): Tree = { - var t: Tree = convertToTypeId(stableId()); - if (in.token == LBRACKET) - t = AppliedTypeTree(t, typeArgs()) setPos in.pos; - if (in.token == LPAREN) - t = Apply(t, argumentExprs()) setPos in.pos; - applyConstr(t) - } - /** TemplateBody ::= `{' [TemplateStat {`;' TemplateStat}] `}' */ def templateBody(): List[Tree] = { @@ -1649,22 +1627,31 @@ abstract class Syntactic: ParserPhase { /** AttributeClauses ::= {AttributeClause} * AttributeClause ::= `[' Attribute {`,' Attribute} `]' - * Attribute ::= Constr */ def attributeClauses(): List[Tree] = { var attrs = new ListBuffer[Tree]; while (in.token == LBRACKET) { in.nextToken(); - attrs += constr(); + attrs += attribute(); while (in.token == COMMA) { in.nextToken(); - attrs += constr() + attrs += attribute() } accept(RBRACKET); } attrs.toList } + /** Attribute ::= StableId [TypeArgs] [`(' [Exprs] `)'] + */ + def attribute(): Tree = { + var t: Tree = convertToTypeId(stableId()); + if (in.token == LBRACKET) + t = atPos(in.pos)(AppliedTypeTree(t, typeArgs())); + val args = if (in.token == LPAREN) argumentExprs() else List(); + makeNew(List(t), List(), args) + } + def joinAttributes(attrs: List[Tree], defs: List[Tree]): List[Tree] = defs map (defn => (attrs :\ defn) ((attr, tree) => Attributed(attr, tree) setPos attr.pos)); diff --git a/sources/scala/tools/nsc/ast/parser/Tokens.scala b/sources/scala/tools/nsc/ast/parser/Tokens.scala index 8b26a259ca..1908ee70f1 100644 --- a/sources/scala/tools/nsc/ast/parser/Tokens.scala +++ b/sources/scala/tools/nsc/ast/parser/Tokens.scala @@ -64,6 +64,7 @@ object Tokens { val FINALLY = 55; val WHILE = 56; val RETURN = 57; + val MATCH = 58; /** special symbols */ val COMMA = 61; diff --git a/sources/scala/tools/nsc/symtab/Definitions.scala b/sources/scala/tools/nsc/symtab/Definitions.scala index ea570ae388..ae927fd6c1 100755 --- a/sources/scala/tools/nsc/symtab/Definitions.scala +++ b/sources/scala/tools/nsc/symtab/Definitions.scala @@ -73,6 +73,9 @@ abstract class Definitions: SymbolTable { typeRef(sym.info.prefix, sym, formals ::: List(restpe)) } + def seqType(arg: Type) = + typeRef(SeqClass.info.prefix, SeqClass, List(arg)); + // members of class scala.Any var Any_== : Symbol = _; var Any_!= : Symbol = _; @@ -81,7 +84,6 @@ abstract class Definitions: SymbolTable { var Any_toString : Symbol = _; var Any_isInstanceOf: Symbol = _; var Any_asInstanceOf: Symbol = _; - var Any_match : Symbol = _; // members of class java.lang.{Object, String} var Object_eq : Symbol = _; @@ -145,7 +147,7 @@ abstract class Definitions: SymbolTable { JavaPackage = getModule("java"); JavaLangPackage = getModule("java.lang"); ScalaPackage = getModule("scala"); - ScalaPackageClass = ScalaPackage.moduleClass; + ScalaPackageClass = ScalaPackage.tpe.symbol; AnyClass = newClass(ScalaPackageClass, "Any", List()); AnyValClass = getClass("scala.AnyVal"); @@ -220,15 +222,6 @@ abstract class Definitions: SymbolTable { { val tparam = newTypeParam(Any_asInstanceOf, 0); Any_asInstanceOf.setInfo(PolyType(List(tparam), tparam.typeConstructor)); } - Any_match = newMethod(AnyClass, "match") - .setFlag(FINAL); - { val tparam0 = newTypeParam(Any_match, 0); - val tparam1 = newTypeParam(Any_match, 1); - Any_match.setInfo( - PolyType( - List(tparam0, tparam1), - MethodType(List(tparam0.typeConstructor), tparam1.typeConstructor))); - } // members of class java.lang.{Object, String} Object_eq = newMethod(ObjectClass, "eq") diff --git a/sources/scala/tools/nsc/symtab/Flags.scala b/sources/scala/tools/nsc/symtab/Flags.scala index cfa93b8709..1df4f985f3 100644 --- a/sources/scala/tools/nsc/symtab/Flags.scala +++ b/sources/scala/tools/nsc/symtab/Flags.scala @@ -39,14 +39,14 @@ object Flags { val SYNTHETIC = 0x00100000; // symbol is compiler-generated val STABLE = 0x00200000; // functions that are assumed to be stable // (typically, access methods for valdefs) - val INITIALIZED = 0x00300000; // symbol's definition is complete - val LOCKED = 0x00400000; // temporary flag to catch cyclic dependencies + val INITIALIZED = 0x00400000; // symbol's definition is complete + val LOCKED = 0x00800000; // temporary flag to catch cyclic dependencies val ACCESSED = 0x01000000; // symbol was accessed at least once val SELECTOR = 0x02000000; // symbol was used as selector in Select - val CAPTURED = 0x04000000; // variables is accessed from nested function. Set by LambdaLift - val ACCESSOR = 0x08000000; // function is an access function for a value or variable + val CAPTURED = 0x04000000; // variable is accessed from nested function. Set by LambdaLift + val ACCESSOR = 0x08000000; // a value or variable accessor val ACCESS_METHOD = 0x10000000; // function is an access function for a method in some // outer class; set by ExplicitOuter @@ -60,9 +60,9 @@ object Flags { val IS_ERROR = 0x200000000l; // symbol is an error symbol val OVERLOADED = 0x400000000l; // symbol is overloaded - val TRANS_FLAG = 0x1000000000l; // transient flag guaranteed to be reset after each phase. - val LIFTED = TRANS_FLAG; // transient flag for lambdalift - val INCONSTRUCTOR = TRANS_FLAG; // transient flag for analyzer + val TRANS_FLAG = 0x1000000000l; // transient flag guaranteed to be reset after each phase. + val LIFTED = TRANS_FLAG; // transient flag for lambdalift + val INCONSTRUCTOR = TRANS_FLAG; // transient flag for analyzer // masks val SOURCEFLAGS = 0x00077777; // these modifiers can be set in source programs. diff --git a/sources/scala/tools/nsc/symtab/StdNames.scala b/sources/scala/tools/nsc/symtab/StdNames.scala index 5cbd8d0169..1da9ebc888 100755 --- a/sources/scala/tools/nsc/symtab/StdNames.scala +++ b/sources/scala/tools/nsc/symtab/StdNames.scala @@ -126,7 +126,6 @@ abstract class StdNames: SymbolTable { val java = newTermName("java"); val lang = newTermName("lang"); val length = newTermName("length"); - val _match = newTermName("match"); val map = newTermName("map"); val n = newTermName("n"); val nobinding = newTermName("nobinding"); diff --git a/sources/scala/tools/nsc/symtab/Symbols.scala b/sources/scala/tools/nsc/symtab/Symbols.scala index 6f4f89f899..80137e3f91 100755 --- a/sources/scala/tools/nsc/symtab/Symbols.scala +++ b/sources/scala/tools/nsc/symtab/Symbols.scala @@ -90,9 +90,11 @@ abstract class Symbols: SymbolTable { final def isValue = isTerm && !(isModule && ((rawflags & (PACKAGE | JAVA)) != 0)); final def isVariable = isTerm && (rawflags & MUTABLE) != 0; + final def isGetter = isTerm && (rawflags & ACCESSOR) != 0 && !name.endsWith(nme._EQ); + final def isSetter = isTerm && (rawflags & ACCESSOR) != 0 && name.endsWith(nme._EQ); final def isValueParameter = isTerm && (rawflags & PARAM) != 0; final def isLocalDummy = isTerm && (name startsWith nme.LOCAL_PREFIX); - final def isMethod = isTerm && (rawflags & METHOD) != 0; + final def isMethod = isTerm && (rawflags & (METHOD | STABLE)) == METHOD; final def isLabel = isTerm && (rawflags & LABEL) != 0; final def isConstructor = isTerm && name == nme.CONSTRUCTOR; final def isModule = isTerm && (rawflags & MODULE) != 0; @@ -130,6 +132,9 @@ abstract class Symbols: SymbolTable { isTerm && ( hasFlag(PRIVATE) || isLocal || owner.isClass && owner.hasFlag(FINAL | MODULE)); + /** Is this symbol a sealed class?*/ + final def isSealed: boolean = + isClass && (hasFlag(SEALED) || isSubClass(AnyValClass) || isSubClass(ArrayClass)); /** Is this symbol locally defined? I.e. not a member of a class or module */ final def isLocal: boolean = owner.isTerm || hasFlag(LOCAL); @@ -158,18 +163,13 @@ abstract class Symbols: SymbolTable { final def flags = { initialize; rawflags & phase.flagMask } - final def setFlag(mask: long): Symbol = { - rawflags = rawflags | mask; this - } - final def resetFlag(mask: long): Symbol = { - rawflags = rawflags & ~mask; this - } + final def setFlag(mask: long): this.type = { rawflags = rawflags | mask; this } + final def resetFlag(mask: long): this.type = { rawflags = rawflags & ~mask; this } final def getFlag(mask: long): long = (if ((mask & ~CREATIONFLAGS) == 0) rawflags else flags) & mask; final def hasFlag(mask: long): boolean = ((if ((mask & ~CREATIONFLAGS) == 0) rawflags else flags) & mask) != 0; - final def resetFlags = - rawflags = rawflags & SOURCEFLAGS; + final def resetFlags: unit = { rawflags = rawflags & SOURCEFLAGS } // Info and Type ------------------------------------------------------------------- @@ -210,7 +210,7 @@ abstract class Symbols: SymbolTable { } /** Set initial info. */ - def setInfo(info: Type): Symbol = { + def setInfo(info: Type): this.type = { infos = new TypeHistory(phase, info, null); limit = phase; assert(info != null, "setInfo(null) for " + name + " at phase " + phase);//debug @@ -383,7 +383,7 @@ abstract class Symbols: SymbolTable { /** Return every accessor of a primary constructor parameter in this case class */ final def caseFieldAccessors: List[Symbol] = { assert(isClass && hasFlag(CASE)); - info.decls.toList.filter(sym => sym.isMethod && sym.hasFlag(PARAMACCESSOR)) + info.decls.toList.filter(sym => !sym.hasFlag(PARAM) && sym.hasFlag(PARAMACCESSOR)) } /** The symbol accessed by this accessor function. @@ -416,7 +416,7 @@ abstract class Symbols: SymbolTable { /** The module corresponding to this module class (note that this * is not updated when a module is cloned). */ - def sourceModule: Symbol = NoSymbol; + //def sourceModule: Symbol = NoSymbol; /** The module class corresponding to this module. */ @@ -506,7 +506,7 @@ abstract class Symbols: SymbolTable { final def locationString: String = if (owner.isClass && (!owner.isAnonymousClass && !owner.isRefinementClass || settings.debug.value)) - " in " + (if (owner.isModuleClass) owner.sourceModule else owner) + " in " + (if (owner.isModuleClass) "object " + owner.nameString else owner) else ""; /** String representation of symbol's definition following its name */ @@ -639,13 +639,13 @@ abstract class Symbols: SymbolTable { class ModuleClassSymbol(module: ModuleSymbol) extends ClassSymbol(module.owner, module.pos, module.name.toTypeName) { setFlag(module.getFlag(MODULE2CLASSFLAGS) | MODULE | FINAL); - override def sourceModule = module; + //override def sourceModule = module; } /** An object repreesenting a missing symbol */ object NoSymbol extends Symbol(null, Position.NOPOS, nme.NOSYMBOL) { super.setInfo(NoType); - override def setInfo(info: Type): Symbol = { assert(info == NoType); this } + override def setInfo(info: Type): this.type = { assert(info == NoType); this } override def enclClass: Symbol = this; override def enclMethod: Symbol = this; override def owner: Symbol = throw new Error(); diff --git a/sources/scala/tools/nsc/symtab/Types.scala b/sources/scala/tools/nsc/symtab/Types.scala index 38b061a39e..9d8c8f90f0 100755 --- a/sources/scala/tools/nsc/symtab/Types.scala +++ b/sources/scala/tools/nsc/symtab/Types.scala @@ -48,6 +48,10 @@ abstract class Types: SymbolTable { * identity for all other types */ def widen: Type = this; + /** The type of `this' of a class type or reference type + */ + def typeOfThis = symbol.typeOfThis; + /** Map to a this type which is a subtype of this type. */ def narrow: Type = @@ -561,6 +565,8 @@ abstract class Types: SymbolTable { override def parents: List[Type] = sym.info.parents map transform; + override def typeOfThis = transform(sym.typeOfThis); + override def prefix: Type = pre; override def typeArgs: List[Type] = args; @@ -604,7 +610,7 @@ abstract class Types: SymbolTable { override def paramSectionCount: int = resultType.paramSectionCount + 1; override def erasure = { - val pts = List.transform(paramTypes)(.erasure); + val pts = paramTypes mapConserve (.erasure); val res = resultType.erasure; if ((pts eq paramTypes) && (res eq resultType)) this else MethodType(pts, res) @@ -767,7 +773,7 @@ abstract class Types: SymbolTable { else ConstantType(base1, value) case TypeRef(pre, sym, args) => val pre1 = this(pre); - val args1 = List.transform(args)(this); + val args1 = args mapConserve this; if ((pre1 eq pre) && (args1 eq args)) tp else typeRef(pre1, sym, args1) case TypeBounds(lo, hi) => @@ -776,7 +782,7 @@ abstract class Types: SymbolTable { if ((lo1 eq lo) && (hi1 eq hi)) tp else TypeBounds(lo1, hi1) case RefinedType(parents, refinement) => - val parents1 = List.transform(parents)(this); + val parents1 = parents mapConserve this; val refinement1 = mapOver(refinement); if ((parents1 eq parents) && (refinement1 eq refinement)) tp else { @@ -791,7 +797,7 @@ abstract class Types: SymbolTable { result } case MethodType(paramtypes, result) => - val paramtypes1 = List.transform(paramtypes)(this); + val paramtypes1 = paramtypes mapConserve this; val result1 = this(result); if ((paramtypes1 eq paramtypes) && (result1 eq result)) tp else MethodType(paramtypes1, result1) @@ -822,7 +828,7 @@ abstract class Types: SymbolTable { /** Map this function over given list of symbols */ private def mapOver(syms: List[Symbol]): List[Symbol] = { val infos = syms map (.info); - val infos1 = List.transform(infos)(this); + val infos1 = infos mapConserve this; if (infos1 eq infos) syms else { val syms1 = syms map (.cloneSymbol); @@ -1414,7 +1420,7 @@ abstract class Types: SymbolTable { * of thistype or prefixless typerefs/singletype occurrences in given list of types */ private def commonOwner(tps: List[Type]): Symbol = { commonOwnerMap.init; - List.transform(tps)(commonOwnerMap); + tps mapConserve commonOwnerMap; commonOwnerMap.result } diff --git a/sources/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/sources/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index 3531115583..2379d09400 100755 --- a/sources/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/sources/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -18,7 +18,7 @@ abstract class ClassfileParser { private var in: AbstractFileReader = _; // the class file private var clazz: Symbol = _; // the class symbol containing dynamic members - private var statics: Symbol = _; // the module class symbol containing static members + private var staticModule: Symbol = _; // the module symbol containing static members private var instanceDefs: Scope = _; // the scope of all instance definitions private var staticDefs: Scope = _; // the scope of all static definitions private var pool: ConstantPool = _; // the classfile's constant pool @@ -40,10 +40,10 @@ abstract class ClassfileParser { this.in = new AbstractFileReader(file); if (root.isModule) { this.clazz = root.linkedClass; - this.statics = root.moduleClass + this.staticModule = root } else { this.clazz = root; - this.statics = root.linkedModule.moduleClass; + this.staticModule = root.linkedModule } this.isScala = false; this.hasMeta = false; @@ -59,6 +59,8 @@ abstract class ClassfileParser { busy = false } + private def statics: Symbol = staticModule.moduleClass; + private def parseHeader: unit = { val magic = in.nextInt(); if (magic != JAVA_MAGIC) @@ -239,7 +241,7 @@ abstract class ClassfileParser { clazz.setInfo(classInfo); statics.setInfo(staticInfo); } - statics.sourceModule.setInfo(statics.tpe); + staticModule.setInfo(statics.tpe); in.bp = curbp; val fieldCount = in.nextChar(); for (val i <- Iterator.range(0, fieldCount)) parseField(); diff --git a/sources/scala/tools/nsc/typechecker/Analyzer.scala b/sources/scala/tools/nsc/typechecker/Analyzer.scala index 5457b01ec4..1e5e2c17c8 100644 --- a/sources/scala/tools/nsc/typechecker/Analyzer.scala +++ b/sources/scala/tools/nsc/typechecker/Analyzer.scala @@ -15,7 +15,8 @@ abstract class Analyzer with Typers with TypeCheckers with Infer - with Variances { + with Variances + with EtaExpansion { val global: Global; import global._; diff --git a/sources/scala/tools/nsc/typechecker/Contexts.scala b/sources/scala/tools/nsc/typechecker/Contexts.scala index 804b5ae29d..bbc965c468 100755 --- a/sources/scala/tools/nsc/typechecker/Contexts.scala +++ b/sources/scala/tools/nsc/typechecker/Contexts.scala @@ -51,7 +51,7 @@ class Contexts: Analyzer { c.owner = owner; c.scope = scope; c.enclClass = if ((tree.isInstanceOf[Template] || - tree.isInstanceOf[IntersectionTypeTree]) && + tree.isInstanceOf[CompoundTypeTree]) && tree != this.tree) c else this.enclClass; c.variance = this.variance; diff --git a/sources/scala/tools/nsc/typechecker/Namers.scala b/sources/scala/tools/nsc/typechecker/Namers.scala index 1215c5ddfb..1ed2f26947 100755 --- a/sources/scala/tools/nsc/typechecker/Namers.scala +++ b/sources/scala/tools/nsc/typechecker/Namers.scala @@ -40,11 +40,11 @@ trait Namers: Analyzer { sym1 } - private def enterInScope(pos: int, sym: Symbol): Symbol = { + def enterInScope(sym: Symbol): Symbol = { if (!(sym.isMethod && sym.owner.isClass)) { val prev = context.scope.lookupEntry(sym.name); if (prev != null && prev.owner == context.scope && !prev.sym.isMethod) - doubleDefError(pos, prev.sym); + doubleDefError(sym.pos, prev.sym); } context.scope enter sym; sym @@ -55,7 +55,7 @@ trait Namers: Analyzer { if (p.isPackage && context.scope == p.owner.info.decls) { p.pos = pos; p.moduleClass.pos = pos; p } else { - enterInScope(pos, context.owner.newPackage(pos, name)) + enterInScope(context.owner.newPackage(pos, name)) } } @@ -64,7 +64,7 @@ trait Namers: Analyzer { if (c.isType && context.scope == c.owner.info.decls) { updatePosFlags(c, pos, mods) } else { - enterInScope(pos, context.owner.newClass(pos, name).setFlag(mods)) + enterInScope(context.owner.newClass(pos, name).setFlag(mods)) } } @@ -76,7 +76,7 @@ trait Namers: Analyzer { val newm = context.owner.newModule(pos, name); newm.setFlag(mods); newm.moduleClass.setFlag(mods); - enterInScope(pos, newm) + enterInScope(newm) } } @@ -85,7 +85,7 @@ trait Namers: Analyzer { if (m.isModule && context.scope == m.owner.info.decls) { updatePosFlags(m, pos, mods) } else { - enterInScope(pos, context.owner.newMethod(pos, name).setFlag(mods)) + enterInScope(context.owner.newMethod(pos, name).setFlag(mods)) } } @@ -113,7 +113,7 @@ trait Namers: Analyzer { val namer = new Namer( context.make(tree, tree.symbol.moduleClass, tree.symbol.info.decls)); stats map namer.enterSym; - tree.symbol + tree.symbol case ClassDef(mods, name, tparams, _, _) => if ((mods & (CASE | ABSTRACT)) == CASE) { // enter case factory method. tree.symbol = enterCaseFactorySymbol( @@ -126,28 +126,48 @@ trait Namers: Analyzer { .setInfo(typer.typeCompleter(tree)); tree.symbol.info.decls enter constr; finishWith(tparams) - case ModuleDef(mods, name, _, _) => + case ModuleDef(mods, name, _) => tree.symbol = enterModuleSymbol(tree.pos, mods, name); tree.symbol.moduleClass.setInfo(typer.typeCompleter(tree)); finish case ValDef(mods, name, tp, rhs) => - tree.symbol = enterInScope(tree.pos, owner.newValue(tree.pos, name).setFlag(mods)); - finish + if (context.owner.isClass & (mods & PRIVATE) == 0) { + val accmods = ACCESSOR | (if ((mods & MUTABLE) != 0) mods & ~MUTABLE + else mods | STABLE); + val getter = owner.newMethod(tree.pos, name) + .setFlag(accmods).setInfo(typer.getterTypeCompleter(tree)); + enterInScope(getter); + if ((mods & MUTABLE) != 0) { + val setter = owner.newMethod(tree.pos, name) + .setFlag(accmods).setInfo(typer.setterTypeCompleter(tree)); + enterInScope(setter) + } + tree.symbol = + if ((mods & DEFERRED) == 0) + owner.newValue(tree.pos, name) + .setFlag(mods | PRIVATE | LOCAL).setInfo(typer.typeCompleter(tree)) + else getter; + tree.symbol + } else { + tree.symbol = + enterInScope(owner.newValue(tree.pos, name).setFlag(mods)); + finish + } case DefDef(mods, nme.CONSTRUCTOR, tparams, vparams, tp, rhs) => if (!(owner.isClass && context.scope == owner.info.decls) || owner.isModuleClass || owner.isAnonymousClass || owner.isRefinementClass) context.unit.error(tree.pos, "constructor definition not allowed here"); - tree.symbol = enterInScope(tree.pos, owner.newConstructor(tree.pos)) + tree.symbol = enterInScope(owner.newConstructor(tree.pos)) .setFlag(mods | owner.rawflags & CONSTRFLAGS); finishWith(tparams) case DefDef(mods, name, tparams, _, _, _) => - tree.symbol = enterInScope(tree.pos, owner.newMethod(tree.pos, name)).setFlag(mods); + tree.symbol = enterInScope(owner.newMethod(tree.pos, name)).setFlag(mods); finishWith(tparams) case AbsTypeDef(mods, name, _, _) => - tree.symbol = enterInScope(tree.pos, owner.newAbstractType(tree.pos, name)); + tree.symbol = enterInScope(owner.newAbstractType(tree.pos, name)); finish case AliasTypeDef(mods, name, tparams, _) => - tree.symbol = enterInScope(tree.pos, owner.newAliasType(tree.pos, name)); + tree.symbol = enterInScope(owner.newAliasType(tree.pos, name)); finishWith(tparams) case Attributed(_, defn) => enterSym(defn) @@ -157,7 +177,7 @@ trait Namers: Analyzer { tree.symbol = NoSymbol.newImport(tree.pos); finish case _ => - NoSymbol + tree.symbol } } } diff --git a/sources/scala/tools/nsc/typechecker/TypeCheckers.scala b/sources/scala/tools/nsc/typechecker/TypeCheckers.scala index 43bd18ea60..6a31477d2b 100755 --- a/sources/scala/tools/nsc/typechecker/TypeCheckers.scala +++ b/sources/scala/tools/nsc/typechecker/TypeCheckers.scala @@ -5,35 +5,65 @@ // $Id$ package scala.tools.nsc.typechecker; +import collection.mutable.ListBuffer; +import symtab.Flags._; import scala.tools.util.Position; /** Methods to create symbols and to enter them into scopes. */ trait TypeCheckers: Analyzer { - import symtab.Flags._; import global._; + import definitions._; + import posAssigner.atPos; class TypeCheckPhase(prev: Phase) extends StdPhase(prev) { def name = "typechecker"; val global: TypeCheckers.this.global.type = TypeCheckers.this.global; def apply(unit: CompilationUnit): unit = - unit.body = new TypeChecker(startContext.make(unit)).transformTrees(unit.body); + new TypeChecker(startContext.make(unit)).transformStats(unit.body, NoSymbol) } - class TypeChecker(context: Context) extends Transformer { + class TypeChecker(context: Context) { import context.unit; val infer = new Inferencer(context); import infer._; + object namer extends Namer(context); + + /** Mode constants + */ + private val NOmode = 0x000; + private val EXPRmode = 0x001; // these 3 modes are mutually exclusive. + private val PATTERNmode = 0x002; + private val TYPEmode = 0x004; + + private val INCONSTRmode = 0x008; // orthogonal to above. When set we are + // in the body of a constructor + + private val FUNmode = 0x10; // orthogonal to above. When set + // we are looking for a method or constructor + + private val POLYmode = 0x020; // orthogonal to above. When set + // expression types can be polymorphic. + + private val QUALmode = 0x040; // orthogonal to above. When set + // expressions may be packages and + // Java statics modules. + + private val stickyModes: int = EXPRmode | PATTERNmode | TYPEmode | INCONSTRmode; + + /** Report a type error. + * @param pos The position where to report the error + * @param ex The exception that caused the error */ def reportTypeError(pos: int, ex: TypeError): unit = { if (settings.debug.value) ex.printStackTrace(); ex match { case CyclicReference(sym, info: TypeCompleter) => info.tree match { - case ValDef(_, _, EmptyTypeTree(), _) => + case ValDef(_, _, tpt, _) if (tpt.tpe == null) => error(pos, "recursive " + sym + " needs type") - case DefDef(_, _, _, _, EmptyTypeTree(), _) => + case DefDef(_, _, _, _, tpt, _) if (tpt.tpe == null) => error(pos, "recursive " + sym + " needs result type") case _ => error(pos, ex.getMessage()) @@ -43,61 +73,495 @@ trait TypeCheckers: Analyzer { } } - /** Mode constants - */ - val NOmode = 0x000; - val EXPRmode = 0x001; // these 3 modes are mutually exclusive. - val PATTERNmode = 0x002; - val TYPEmode = 0x004; + /** Check that tree is a stable expression. + */ + def checkStable(tree: Tree): Tree = + if (treeInfo.isPureExpr(tree) || tree.tpe.isError) tree; + else errorTree(tree, "stable identifier required, but " + tree + " found."); + + /** Check that type of given tree does not contain local or private components + */ + private object checkNoEscape extends TypeMap { + private var owner: Symbol = _; + private var badSymbol: Symbol = _; + def apply[T <: Tree](owner: Symbol, tree: T): T = { + this.owner = owner; + badSymbol = NoSymbol; + apply(tree.tpe); + if (badSymbol == NoSymbol) tree + else { + error(tree.pos, + (if (badSymbol.hasFlag(PRIVATE)) "private " else "") + badSymbol + + " escapes its defining scope as part of type " + tree.tpe); + setError(tree) + } + } + override def apply(t: Type): Type = { + def checkNoEscape(sym: Symbol): unit = { + val e = context.scope.lookupEntry(sym.name); + if (e.sym == sym && e.owner == context.scope && !e.sym.isTypeParameter) { + badSymbol = e.sym + } else if (sym.hasFlag(PRIVATE)) { + var o = owner; + while (o != NoSymbol && o != sym.owner && !o.isLocal && !o.hasFlag(PRIVATE)) + o = o.owner; + if (o == sym.owner) badSymbol = sym + } + } + if (badSymbol == NoSymbol) + t match { + case TypeRef(NoPrefix, sym, args) => checkNoEscape(sym) + case SingleType(NoPrefix, sym) => checkNoEscape(sym) + case _ => + } + mapOver(t) + } + } + + def reenterValueParams(vparamss: List[List[ValDef]]): unit = + for (val vparams <- vparamss; val vparam <- vparams) context.scope enter vparam.symbol; - val FUNmode = 0x10; // orthogonal to above. When set - // we are looking for a method or constructor + def reenterTypeParams(tparams: List[AbsTypeDef]): unit = + for (val tparam <- tparams) context.scope enter tparam.symbol; - val POLYmode = 0x020; // orthogonal to above. When set - // expression types can be polymorphic. + def attrInfo(attr: Tree): AttrInfo = attr match { + case Apply(Select(New(tpt), nme.CONSTRUCTOR), args) => + Pair(tpt.tpe, args map { + case Literal(value) => + value + case arg => + error(arg.pos, "attribute argument needs to be a constant; found: " + arg); + }) + } + + private def literalType(value: Any): Type = + if (value.isInstanceOf[unit]) UnitClass.tpe + else if (value.isInstanceOf[boolean]) BooleanClass.tpe + else if (value.isInstanceOf[char]) CharClass.tpe + else if (value.isInstanceOf[int]) IntClass.tpe + else if (value.isInstanceOf[long]) LongClass.tpe + else if (value.isInstanceOf[float]) FloatClass.tpe + else if (value.isInstanceOf[double]) DoubleClass.tpe + else if (value.isInstanceOf[String]) StringClass.tpe + else if (value == null) AllRefClass.tpe + else throw new FatalError("unexpected literal value: " + value); + + /** Perform the following adaptations of expression, pattern or type `tree' wrt to + * given mode `mode' and given prototype `pt': + * (1) Resolve overloading, unless mode contains FUNmode + * (2) Apply parameterless functions + * (3) Apply polymorphic types to fresh instances of their type parameters and + * store these instances in context.undetparams. + * (4) When in mode EXPRmode but not FUNmode, convert unapplied methods to functions + * However, if function is `match' or a constructor, issue an error. + * (5) Convert a class type that serves as a constructor in a pattern as follows: + * (5.1) If this type refers to a case class, set tree's type to the unique + * instance of its primary constructor that is a subtype of the expected type. + * (5.2) Otherwise, if this type is a subtype of scala.Seq[A], set trees' type + * to a method type from a repeated parameter sequence type A* to the expected type. + * (6) Convert all other types to TypeTree nodes. + * (7) When in TYPEmode nut not FUNmode, check that types are fully parameterized + * (8) When in both EXPRmode and FUNmode, add apply method calls to values of object type. + * (9) If there are undetermined type variables and not POLYmode, infer expression instance + * Then, if tree's type is not a subtype of expected type, try the following adaptations: + * (10) If the expected type is byte, short or char, and the expression + * is an integer fitting in the range of that type, convert it to that type. + * (11) Widen numeric literals to their expected type, if necessary + * (12) When in mode EXPRmode, convert E to { E; () } if expected type is Scala.unit. + * (13) When in mode EXPRmode, apply a view + * If all this fails, error + */ + private def adapt(tree: Tree, mode: int, pt: Type): Tree = tree.tpe match { + case OverloadedType(pre, alts) if ((mode & FUNmode) == 0) => // (1) + inferExprAlternative(tree, pt); + adapt(tree, mode, pt) + case PolyType(List(), restpe) => // (2) + transform(constfold(tree.setType(restpe)), mode, pt); + case PolyType(tparams, restpe) => // (3) + val tparams1 = tparams map (.cloneSymbol); + val tree1 = if (tree.isType) tree + else TypeApply(tree, tparams1 map (tparam => + TypeTree() setPos tparam.pos setType tparam.tpe) + context.undetparams = context.undetparams ::: tparams1; + adapt(tree1 setType restpe.substSym(tparams, tparams1), mode, pt) + case MethodType(_, _) if ((mode & (EXPRmode | FUNmode)) == EXPRmode && + isCompatible(tree.tpe, pt)) => // (4) + val meth = treeInfo.methSymbol(tree); + if (meth.isConstructor) errorTree(tree, "missing arguments for " + meth) + else transform(etaExpand(tree, tree.tpe), mode, pt) + case _ => + if (tree.isType) { + val clazz = tree.tpe.symbol; + if ((mode & PATTERNmode) != 0) { // (5) + if (clazz.hasFlag(CASE)) { // (5.1) + val tparams = context.undetparams; + context.undetparams = List(); + inferConstructorInstance( + TypeTree() setPos tree.pos + setType1 tree.tpe.prefix.memberType(clazz.primaryConstructor), + tparams, pt); + tree + } else if (clazz.isSubClass(SeqClass)) { // (5.2) + pt.baseType(clazz).baseType(SeqClass) match { + case TypeRef(pre, seqClass, args) => + tree.setType(MethodType(List(typeRef(pre, RepeatedParamClass, args)), pt)) + case NoType => + errorTree(tree, "expected pattern type " + pt + + " does not conform to sequence " + clazz) + } + } else errorTree(tree, + clazz.toString() + " is neither a case class nor a sequence class") + } else if ((mode & FUNmode) == 0 && !context.undetparams.isEmpty) { // (7) + context.undetparams = List(); + errorTree(tree, "" + clazz + " takes type parameters"); + } else tree match { // (6) + case TypeTree() => tree + case _ => TypeTree() setPos tree.pos setType tree.tpe + } + } else if ((mode & (EXPRmode | FUNmode)) == (EXPRmode | FUNmode) && + tree.tpe.member(nme.apply).filter( + m => m.tpe.paramSectionCount > 0) != NoSymbol) { // (8) + transform(Select(tree, nme.apply), mode, pt) + } else if (!context.undetparams.isEmpty & (mode & POLYmode) == 0) { // (9) + val tparams = context.undetparams; + context.undetparams = List(); + inferExprInstance(tree, tparams, pt); + tree + } else if (tree.tpe <:< pt) { + tree + } else { + def adaptError: Tree = { + typeError(tree.pos, tree.tpe, pt); + explainTypes(tree.tpe, pt); + setError(tree) + } + val tree1 = constfold(tree, pt); // (10) (11) + if (tree1 != tree)) transform(tree1, mode, pt) + else if ((mode & EXPRmode) != 0) + if (pt.symbol == UnitClass) // (12) + transform(Block(List(tree), Literal(())), mode, pt) + else { // (13) + val vmeth = bestView(tree.tpe, pt); + if (vmeth != NoSymbol) + transform(Apply(Ident(vmeth.name), List(tree)), mode, pt) + else adaptError + } + else adaptError + } + } - val QUALmode = 0x040; // orthogonal to above. When set - // expressions may be packages and - // Java statics modules. + def completeSuperType(supertpt: Tree, tparams: List[Symbol], vparamss: List[List[ValDef]], superargs: List[Tree]): Type = { + reenterValueParams(vparamss); + context.undetparams = tparams; + transformExpr(atPos(supertpt.pos)(Apply(Select(New(supertpt), nme.CONSTRUCTOR), superargs))) + .tpe + } - val SUPERmode = 0x080; // Goes with CONSTRmode. When set - // we are checking a superclass - // constructor invocation. + def parentTypes(templ: Template): List[Tree] = + if (templ.parents.isEmpty) List() + else { + var supertpt = transform(templ.parents.head, TYPEmode | FUNmode, WildcardType); + val tparams = context.undetparams; + context.undetparams = List(); + if (!tparams.isEmpty) { + val constr @ DefDef(_, _, _, vparamss, _, Apply(_, superargs)) = + treeInfo.firstConstructor(templ.body); + supertpt = TypeTree() + setPos supertpt.pos + setType new TypeChecker(context.makeNewScope(constr, constr.symbol)) + .completeSuperType(supertpt, tparams, vparamss, superargs map (.duplicate)); + } + checkNoEscape(context.owner, supertpt) :: + (templ.parents.tail mapConserve (tpt => transformType(tpt, context.owner))) + } - val baseModes: int = EXPRmode | PATTERNmode; + /** Check that + * - all parents are class types, + * - first parent cluss is not a trait; following classes are traits, + * - fnal classes are not inherited, + * - sealed 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. + * - no two parents define same symbol. + */ + def validateParentClasses(parents: List[Tree], selfType: Type): unit = { + var c = context; + do { c = c.outer } while (c.tree.owner == context.owner); + val defscope = c.scope; + + def validateParentClass(parent: Tree, isFirst: boolean): unit = { + val psym = parent.tpe.symbol; + if (!psym.isClass && !parent.tpe.isError) error(parent.pos, "class type expected"); + else if (isFirst == psym.hasFlag(TRAIT)) + error(parent.pos, "" + psym + + (if (isFirst) " is a trait; cannot be used as superclass" + else " is not a trait; cannot be used as mixin")) + else if (psym.hasFlag(FINAL)) + error(parent.pos, "illegal inheritance from final class"); + else if (psym.isSealed) { + // are we in same scope as base type definition? + val e = defscope.lookupEntry(psym.name); + if (!(e.sym == psym && e.owner == defscope)) { + // we are not within same statement sequence + var c = context; + while (c != NoContext && c.owner != psym) c = c.outer.enclClass; + if (c == NoContext) error(parent.pos, "illegal inheritance from sealed class") + } + } + if (!(selfType <:< parent.tpe.typeOfThis)) { + error(parent.pos, "illegal inheritance;\n self-type " + + selfType + " does not conform to " + parent + + "'s selftype " + parent.tpe.typeOfThis) + } + if (parents exists (p => p != parent && p.tpe.symbol == psym && !psym.isError)) + error(parent.pos, "" + psym + " is inherited twice") + } - val SEQUENCEmode = 0x1000; // only for PATTERNmode, otherwise orthogonal to above. When set - // we turn "x" into "x@_" - // and allow args to be of type Seq( a) instead of a + if (!parents.isEmpty) { + validateParentClass(parents.head, true); + for (val p <- parents.tail) validateParentClass(p, false); + } + } - def reenterValueParams(tree: Tree): unit = tree match { - case DefDef(_, _, _, vparamss, _, _) => - for (val vparams <- vparamss; val vparam <- vparams) context.scope enter vparam.symbol + def transformClassDef(cdef: ClassDef): Tree = { + val clazz = cdef.symbol; + reenterTypeParams(cdef.tparams); + val tparams1 = cdef.tparams mapConserve transformAbsTypeDef; + val tpt1 = transformType(cdef.tpt, clazz.thisSym); + val impl1 = new TypeChecker(context.make(cdef.impl, clazz, clazz.info.decls)) + .transformTemplate(cdef.impl); + copy.ClassDef(cdef, cdef.mods, cdef.name, tparams1, tpt1, impl1) setType NoType } - def checkStable(tree: Tree): Tree = tree; - def checkNoEscape(pos: int, tpe: Type): Type = tpe; + def transformModuleDef(mdef: ModuleDef): Tree = { + val clazz = mdef.symbol.moduleClass; + val impl1 = new TypeChecker(context.make(mdef.impl, clazz, clazz.info.decls)) + .transformTemplate(mdef.impl); + copy.ModuleDef(mdef, mdef.mods, mdef.name, impl1) setType NoType + } - def transformConstr(tree: Tree): Tree = tree; - def transformExpr(tree: Tree): Tree = tree; - def transformType(tree: Tree): Tree = tree; - def transformSuperType(tree: Tree): Tree = tree; + def transformTemplate(templ: Template): Template = { + templ setSymbol context.owner.newLocalDummy(templ.pos); + val parents1 = parentTypes(templ); + validateParentClasses(parents1, context.owner.thisType); + val body1 = transformStats(templ.body, templ.symbol); + copy.Template(templ, parents1, body1) setType context.owner.tpe + } - def transform(tree: Tree, mode: int, pt: Type): Tree = { + def transformValDef(vdef: ValDef): ValDef = { + val sym = vdef.symbol; + val tpt1 = transformType(vdef.tpt, sym); + val rhs1 = + if (vdef.rhs.isEmpty) vdef.rhs + else new TypeChecker(context.make(vdef, sym)).transform(vdef.rhs, EXPRmode, tpt1.tpe); + copy.ValDef(vdef, vdef.mods, vdef.name, tpt1, rhs1) setType NoType + } - /** Turn tree type into stable type if possible and required by context. */ - def stabilize(tree: Tree, pre: Type): Tree = tree.tpe match { - case ConstantType(base, value) => - Literal(value) setPos tree.pos setType tree.tpe - case PolyType(List(), restp @ ConstantType(base, value)) => - Literal(value) setPos tree.pos setType restp + def transformDefDef(ddef: DefDef): DefDef = { + val meth = ddef.symbol; + reenterTypeParams(ddef.tparams); + reenterValueParams(ddef.vparamss); + val tparams1 = ddef.tparams mapConserve transformAbsTypeDef; + val vparamss1 = ddef.vparamss mapConserve (.mapConserve(transformValDef)); + val tpt1 = transformType(ddef.tpt, meth); + val rhs1 = + if (ddef.name == nme.CONSTRUCTOR) { + context.enclClass.owner.setFlag(INCONSTRUCTOR); + val result = transform(ddef.rhs, EXPRmode | INCONSTRmode, UnitClass.tpe); + context.enclClass.owner.resetFlag(INCONSTRUCTOR); + result + } else { + transform(ddef.rhs, EXPRmode, tpt1.tpe); + } + copy.DefDef(ddef, ddef.mods, ddef.name, tparams1, vparamss1, tpt1, rhs1) setType NoType + } + + def transformAbsTypeDef(tdef: AbsTypeDef): AbsTypeDef = { + val lo1 = transformType(tdef.lo, tdef.symbol); + val hi1 = transformType(tdef.hi, tdef.symbol); + copy.AbsTypeDef(tdef, tdef.mods, tdef.name, lo1, hi1) setType NoType + } + + def transformAliasTypeDef(tdef: AliasTypeDef): AliasTypeDef = { + reenterTypeParams(tdef.tparams); + val tparams1 = tdef.tparams mapConserve transformAbsTypeDef; + val rhs1 = transformType(tdef.rhs, tdef.symbol); + copy.AliasTypeDef(tdef, tdef.mods, tdef.name, tparams1, rhs1) setType NoType + } + + def transformLabelDef(ldef: LabelDef): LabelDef = { + val lsym = namer.enterInScope( + context.owner.newLabel(ldef.pos, ldef.name) setInfo MethodType(List(), UnitClass.tpe)); + val rhs1 = transform(ldef.rhs, EXPRmode, UnitClass.tpe); + copy.LabelDef(ldef, ldef.name, ldef.params, rhs1) setType UnitClass.tpe + } + + def transformBlock(block: Block, mode: int, pt: Type): Block = { + namer.enterSyms(block.stats); + val stats1 = + if ((mode & INCONSTRmode) != 0) { + val constrCall = transform(block.stats.head, mode, WildcardType); + context.enclClass.owner.resetFlag(INCONSTRUCTOR); + constrCall :: block.stats.tail mapConserve transformExpr + } else { + block.stats mapConserve transformExpr + } + val expr1 = transform(block.expr, mode & ~(FUNmode | QUALmode), pt); + checkNoEscape(NoSymbol, copy.Block(block, stats1, expr1) setType expr1.tpe.deconst) + } + + def transformCase(cdef: CaseDef, pattpe: Type, pt: Type): CaseDef = { + val pat1: Tree = transform(cdef.pat, PATTERNmode, pattpe); + val guard1: Tree = if (cdef.guard == EmptyTree) EmptyTree + else transform(cdef.guard, EXPRmode, BooleanClass.tpe); + val body1: Tree = transform(cdef.body, EXPRmode, pt); + copy.CaseDef(cdef, pat1, guard1, body1) setType body1.tpe + } + + def transformFunction(fun: Function, mode: int, pt: Type): Function = { + val Triple(clazz, argpts, respt) = pt match { + case TypeRef(_, sym, argtps) + if (sym == FunctionClass(fun.vparams.length) || + sym == PartialFunctionClass && fun.body.isInstanceOf[Match]) => + Triple(sym, argtps.init, argtps.last) case _ => - if (tree.symbol.hasFlag(OVERLOADED) && (mode & FUNmode) == 0) - inferExprAlternative(tree, pt); - if (tree.symbol.isStable && pre.isStable && - (pt.isStable || (mode & QUALmode) != 0 || tree.symbol.isModule)) - tree.tpe = singleType(pre, tree.symbol); - tree + Triple(FunctionClass(fun.vparams.length), fun.vparams map (x => NoType), WildcardType) + } + val vparamSyms = List.map2(fun.vparams, argpts) { (vparam, argpt) => + vparam match { + case ValDef(_, _, tpt, _) => + if (tpt.isEmpty) + tpt.tpe = + if (argpt == NoType) { + error(vparam.pos, "missing parameter type"); + ErrorType + } else argpt + } + namer.enterSym(vparam) + } + val vparams1 = fun.vparams mapConserve transformValDef; + val body1 = transform(fun.body, EXPRmode, respt); + copy.Function(fun, vparams1, body1) + setType typeRef(clazz.info.prefix, clazz, (vparamSyms map (.tpe)) ::: List(body1.tpe)) + } + + def transformRefinement(stats: List[Tree]): List[Tree] = { + for (val stat <- stats) namer.enterSym(stat) setFlag OVERRIDE; + transformStats(stats, NoSymbol); + } + + def transformStats(stats: List[Tree], exprOwner: Symbol): List[Tree] = + stats mapConserve { stat => + if (context.owner.isRefinementClass && !treeInfo.isDeclaration(stat)) + errorTree(stat, "only declarations allowed here"); + (if (stat.isDef) TypeChecker.this + else new TypeChecker(context.make(stat, exprOwner))).transformExpr(stat) + } + + private def transform1(tree: Tree, mode: int, pt: Type): Tree = { + + def transformCases(cases: List[CaseDef], pattp: Type): List[CaseDef] = { + val tc1 = new TypeChecker(context.makeNewScope(tree, context.owner)); + cases mapConserve (cdef => tc1.transformCase(cdef, pattp, pt)) + } + + def transformApply(fn: Tree, args: List[Tree]): Tree = { + // if function is overloaded, filter all alternatives that match + // number of arguments and expected result type. + if (fn.hasSymbol && fn.symbol.hasFlag(OVERLOADED)) { + val argtypes = args map (arg => AllClass.tpe); + val pre = fn.symbol.info.prefix; + val sym = fn.symbol filter (alt => + isApplicable(context.undetparams, pre.memberType(alt), argtypes, pt)); + fn.symbol = sym; + fn.tpe = pre.memberType(sym) + } + fn.tpe match { + case OverloadedType(pre, alts) => + val args1 = args mapConserve (arg => + transform(arg, mode & stickyModes, WildcardType)); + inferMethodAlternative(fn, context.undetparams, args1 map (.tpe.deconst), pt); + transformApply(fn, args1); + case MethodType(formals0, restpe) => + val formals = formalTypes(formals0, args.length); + if (formals.length != args.length) { + errorTree(tree, "wrong number of arguments for " + treeSymTypeMsg(fn)) + } else { + val tparams = context.undetparams; + context.undetparams = List(); + if (!tparams.isEmpty) { // note: this case cannot arise for patterns + val lenientTargs = protoTypeArgs(tparams, formals, restpe, pt); + val strictTargs = List.map2(lenientTargs, tparams)((targ, tparam) => + if (targ == WildcardType) tparam.tpe else targ); + def transformArg(tree: Tree, formal: Type): Tree = { + val lenientPt = formal.subst(tparams, lenientTargs); + val tree1 = transform(tree, mode & stickyModes | POLYmode, lenientPt); + val argtparams = context.undetparams; + context.undetparams = List(); + if (!argtparams.isEmpty) { + val strictPt = formal.subst(tparams, strictTargs); + inferArgumentInstance(tree1, argtparams, strictPt, lenientPt); + } + tree1 + } + val args1 = List.map2(args, formals)(transformArg); + if (args1 exists (.tpe.isError)) setError(tree) + else { + val undetparams = inferMethodInstance(fn, tparams, args1, pt); + val result = transformApply(fn, args1); + context.undetparams = undetparams; + result + } + } else { + val args1 = List.map2(args, formals) ((arg, formal) => + transform(arg, mode & stickyModes, formal)); + val tree1 = copy.Apply(tree, fn, args1).setType(restpe); + val tree2 = constfold(tree1); + if (tree1 == tree2) tree2 else transform(tree2, mode, pt) + } + } + case ErrorType => + setError(tree) + } + } + + /** The qualifying class of a this or super with prefix `qual' */ + def qualifyingClass(qual: Name): Symbol = { + if (qual == nme.EMPTY.toTypeName) { + val clazz = context.enclClass.owner; + if (!clazz.isPackageClass) clazz + else { + error(tree.pos, "" + tree + " can be used only in a class, object, or template"); + NoSymbol + } + } else { + var c = context; + while (c != NoContext && !(c.owner.isClass && c.owner.name == qual)) + c = c.outer.enclClass; + if (c != NoContext) c.owner + else { + error(tree.pos, "" + qual + " is not an enclosing class"); + NoSymbol + } + } + } + + /** Attribute a selection where `tree' is `qual.name'. + * `qual' is already attributed. + */ + def transformSelect(qual: Tree, name: Name): Tree = { + val sym = qual.tpe.member(name); + if (sym == NoSymbol && qual.isTerm) { + val vmeth = bestView(tree.tpe, name); + if (vmeth != NoSymbol) + return transform(Select(Apply(Ident(vmeth.name), List(qual)), name), mode, pt) + } + val pre = qual match { + case Super(_, _) => context.enclClass.owner.thisType + case _ => qual.tpe + } + stabilize(checkAccessible(tree, sym, pre, qual), pre); } /** Attribute an identifier consisting of a simple name or an outer reference. @@ -201,253 +665,281 @@ trait TypeCheckers: Analyzer { stabilize(checkAccessible(tree, sym, pre, qual), pre); } - def applyPoly(tree: Tree, tparams: List[Symbol], restpe: Type): Tree = { - val tparams1 = tparams map (.cloneSymbol); - val targs = context.undetparams map (tparam => EmptyTypeTree().setType(tparam.tpe)); - context.undetparams = context.undetparams ::: tparams1; - (if (qual0.isType) AppliedTypeTree(tree, targs) else TypeApply(tree, targs)) - .setType(restpe.subst(tparams, tparams1)) + /** Post-process an identifier or selection node, performing the following: + * (1) Turn trees of constant type into literals + * (2) Check that non-function pattern expressions are stable + * (3) Check that packages and static modules are not used as values + * (4) Turn tree type into stable type if possible and required by context. */ + def stabilize(tree: Tree, pre: Type): Tree = tree.tpe match { + case ConstantType(base, value) => // (1) + Literal(value) setPos tree.pos setType tree.tpe + case PolyType(List(), restp @ ConstantType(base, value)) => // (1) + Literal(value) setPos tree.pos setType restp + case _ => + if (tree.symbol.hasFlag(OVERLOADED) && (mode & FUNmode) == 0) + inferExprAlternative(tree, pt); + if ((mode & (PATTERNmode | FUNmode)) == PATTERNmode && tree.isTerm) // (2) + checkStable(tree) + else if ((mode & (EXPRmode | QUALmode)) == EXPRmode && !tree.symbol.isValue) // (3) + errorTree(tree, tree.symbol.toString() + " is not a value"); + else if (tree.symbol.isStable && pre.isStable && + (pt.isStable || (mode & QUALmode) != 0 || tree.symbol.isModule)) // (4) + tree.setType(singleType(pre, tree.symbol)) + else + tree } - /** Attribute a selection where `tree' is `qual.name'. - * `qual' is already attributed. - */ - def transformSelect(tree: Tree, qual0: Tree, name: Name): Tree = { - val qual = qual0.tpe match { - case PolyType(tparams, restpe) => - assert(context.undetparams.isEmpty); - applyPoly(qual, tparams, restpe); - case _ => - qual0 - } - val sym = qual.tpe.member(name); - // if (sym == NoSymbol) try to insert view. - val pre = qual match { - case Super(_, _) => context.enclClass.owner.thisType - case _ => qual.tpe - } - val tree1 = tree match { - case Select(_, name) => copy.Select(tree, qual, name); - case SelectFromTypeTree(_, name) => copy.SelectFromTypeTree(tree, qual, name) - } - stabilize(checkAccessible(tree1, sym, pre, qual), pre); + // begin transform1 + val sym: Symbol = tree.symbol; + if (sym != null) sym.initialize; + if (settings.debug.value && tree.isDef) global.log("transforming definition of " + sym); + tree match { + case PackageDef(name, stats) => + val stats1 = new TypeChecker(context.make(tree, sym.moduleClass, sym.info.decls)) + .transformStats(stats, NoSymbol); + copy.PackageDef(tree, name, stats1) setType NoType + + case cdef @ ClassDef(_, _, _, _, _) => + new TypeChecker(context.makeNewScope(tree, sym)).transformClassDef(cdef) + + case mdef @ ModuleDef(_, _, _) => + transformModuleDef(mdef) + + case vdef @ ValDef(_, _, _, _) => + transformValDef(vdef) + + case ddef @ DefDef(_, _, _, _, _, _) => + new TypeChecker(context.makeNewScope(tree, sym)).transformDefDef(ddef) + + case tdef @ AbsTypeDef(_, _, _, _) => + transformAbsTypeDef(tdef) + + case tdef @ AliasTypeDef(_, _, _, _) => + new TypeChecker(context.makeNewScope(tree, sym)).transformAliasTypeDef(tdef) + + case ldef @ LabelDef(_, List(), _) => + new TypeChecker(context.makeNewScope(tree, context.owner)).transformLabelDef(ldef) + + case Import(_, _) => + EmptyTree + + case Attributed(attr, defn) => + val attr1 = transform(attr, EXPRmode, AttributeClass.tpe); + val defn1 = transform(defn, mode, pt); + val existing = attributes.get(defn1.symbol) match { + case None => List() + case Some(attrs) => attrs + } + attributes(defn1.symbol) = attrInfo(attr1) :: existing; + defn1 + + case DocDef(comment, defn) => + transform(defn, mode, pt); + + case block @ Block(_, _) => + new TypeChecker(context.makeNewScope(tree, context.owner)) + .transformBlock(block, mode, pt) + + case Sequence(elems) => + copy.Sequence(tree, elems mapConserve (elem => transform(elem, mode, pt))) setType pt + + case Alternative(alts) => + copy.Alternative(tree, alts mapConserve (alt => transform(alt, mode, pt))) setType pt + + case Bind(name, body) => + val body1 = transform(body, mode, pt); + val vble = context.owner.newValue(tree.pos, name).setInfo( + if (treeInfo.isSequenceValued(body)) seqType(pt) else pt); + namer.enterInScope(vble); + copy.Bind(tree, name, body1) setSymbol vble setType pt + + case fun @ Function(_, _) => + new TypeChecker(context.makeNewScope(tree, context.owner)) + .transformFunction(fun, mode, pt) + + case Assign(lhs, rhs) => + def isGetter(sym: Symbol) = sym.info match { + case PolyType(List(), _) => !sym.isStable + case _ => false + } + val lhs1 = transformExpr(lhs); + val varsym = lhs1.symbol; + if (varsym != null && isGetter(varsym)) { + lhs1 match { + case Select(qual, name) => + transform(Apply(Select(qual, name.toString() + "_="), List(rhs)), mode, pt) + } + } else if (varsym != null && varsym.isVariable) { + val rhs1 = transform(rhs, EXPRmode, lhs.tpe); + copy.Assign(tree, lhs1, rhs1) setType UnitClass.tpe; + } else { + if (!lhs.tpe.isError) error(tree.pos, "assignment to non-variable "); + setError(tree) + } + + case If(cond, thenp, elsep) => + val cond1 = transform(cond, EXPRmode, BooleanClass.tpe); + if (elsep.isEmpty) { + val thenp1 = transform(thenp, EXPRmode, UnitClass.tpe); + copy.If(tree, cond1, thenp1, elsep) setType UnitClass.tpe + } else { + val thenp1 = transform(thenp, EXPRmode, pt); + val elsep1 = transform(thenp, EXPRmode, pt); + copy.If(tree, cond1, thenp1, elsep1) setType lub(List(thenp1.tpe, elsep1.tpe)); + } + + case Match(selector, cases) => + val selector1 = transformExpr(selector); + val cases1 = transformCases(cases, selector1.tpe); + copy.Match(tree, selector1, cases1) setType lub(cases1 map (.tpe)) + + case Return(expr) => + if ((context.owner.rawflags & INITIALIZED) == 0) { + errorTree(tree, "method with return needs result type") + } else { + val enclFun = context.owner.enclMethod; + if (!enclFun.isMethod || enclFun.isConstructor) { + errorTree(tree, "return outside method definition") + } else { + val expr1: Tree = transform(expr, EXPRmode, enclFun.tpe.resultType); + copy.Return(tree, expr1) setSymbol enclFun setType AllClass.tpe; + } + } + + case Try(block, catches, finalizer) => + val block1 = transform(block, EXPRmode, pt); + val catches1 = transformCases(catches, ThrowableClass.tpe); + val finalizer1 = if (finalizer.isEmpty) finalizer + else transform(finalizer, EXPRmode, UnitClass.tpe); + copy.Try(tree, block1, catches1, finalizer1) + setType lub(block1.tpe :: (catches1 map (.tpe))) + + case Throw(expr) => + val expr1 = transform(expr, EXPRmode, ThrowableClass.tpe); + copy.Throw(tree, expr1) setType AllClass.tpe + + case New(tpt: Tree) => + val tpt1 = transform(tpt, TYPEmode, WildcardType); + copy.New(tree, tpt1).setType(tpt.tpe) + + case Typed(expr, tpt @ Ident(nme.WILDCARD_STAR)) => + val expr1 = transform(expr, mode & stickyModes, seqType(pt)); + expr1.tpe.baseType(SeqClass) match { + case TypeRef(_, _, List(elemtp)) => + copy.Typed(tree, expr1, tpt setType elemtp) setType elemtp + case _ => + setError(tree) + } + case Typed(expr, tpt) => + val tpt1 = transform(tpt, TYPEmode, WildcardType); + val expr1 = transform(expr, mode & stickyModes, tpt1.tpe); + copy.Typed(tree, expr1, tpt1) + + case TypeApply(fun, args) => + val fun1 = transform(fun, mode & stickyModes | FUNmode, WildcardType); + inferPolyAlternative(fun1, args.length); + val args1 = args mapConserve (arg => transform(arg, TYPEmode, WildcardType)); + val targs = args1 map (.tpe); + if (fun1.tpe.isError || (targs exists (.isError))) + setError(tree) + else fun1.tpe match { + case PolyType(tparams, restpe) => + checkBounds(tree.pos, tparams, targs, ""); + copy.TypeApply(tree, fun1, args1) setType restpe.subst(tparams, targs) + } + + case Apply(fn, args) => + val fnpt = if ((mode & PATTERNmode) != 0) pt else WildcardType; + transformApply(transform(fn, mode | FUNmode | POLYmode, fnpt), args) + + case Super(qual, mix) => + val clazz = qualifyingClass(qual); + if (clazz == NoSymbol) + setError(tree) + else + tree setSymbol clazz + setType ( + if (mix == nme.EMPTY.toTypeName) { + intersectionType(clazz.info.parents) + } else { + val ps = clazz.info.parents dropWhile (p => p.symbol.name != mix); + if (ps.isEmpty) { + error(tree.pos, "" + mix + " does not name a mixin base class of " + clazz); + ErrorType + } else ps.head + }) + + case This(qual) => + val clazz = qualifyingClass(qual); + if (clazz == NoSymbol) setError(tree) + else { + tree.setSymbol(clazz); + tree.setType( + if (pt.isStable || (mode & QUALmode) != 0) clazz.thisType + else clazz.typeOfThis) + } + + case Select(qual, name) => + val qual1 = transform(qual, EXPRmode | QUALmode | POLYmode, WildcardType); + if (name.isTypeName) checkStable(qual1); + transformSelect(qual1, name); + + case Ident(name) => + transformIdent(name) + + case Literal(value) => + tree.setType(literalType(value)) + + case SingletonTypeTree(ref) => + val ref1 = checkStable(transform(ref, EXPRmode | QUALmode, AnyRefClass.tpe)); + tree setType ref1.tpe.resultType; + + case SelectFromTypeTree(qual, selector) => + tree setType transformSelect(transform(qual, TYPEmode, WildcardType), selector).tpe + + case CompoundTypeTree(parents, refinements) => + tree setType { + val parents1 = parents mapConserve (parent => transform(parent, TYPEmode, WildcardType)); + if (parents1 exists (.tpe.isError)) ErrorType + else { + val decls = new Scope(); + val self = refinedType(parents1 map (.tpe), context.enclClass.owner, decls); + new TypeChecker(context.make(tree, self.symbol, decls)) + .transformRefinement(refinements); + self + } + } + + case AppliedTypeTree(tpt, args) => + val tpt1 = transform(tpt, mode | FUNmode, WildcardType); + val args1 = args mapConserve (arg => transform(arg, TYPEmode, WildcardType)); + val tparams = context.undetparams; + context.undetparams = List(); + if (tpt1.tpe.isError) + setError(tree) + else if (tparams.length == args1.length) + tree setType appliedType(tpt1.tpe, args1 map (.tpe)) + else if (tparams.length == 0) + errorTree(tree, "" + tpt1.tpe + " does not take type parameters") + else + errorTree(tree, "wrong number of type arguments for " + tpt1.tpe) } - - /** Attribute an argument list. - * @param pos Position for error reporting - * @param meth The symbol of the called method, or `null' if none exists. - * @param tparams The type parameters that need to be instantiated - * @param methtype The method's type w/o type parameters - * @param argMode The argument mode (either EXPRmode or PATTERNmode) - * @param args The actual arguments - * @param pt The proto-resulttype. - * @return The vector of instantiated argument types, or null if error. - */ - def transformArgs(pos: int, meth: Symbol, tparams: Array[Symbol], methtype: Type, argMode: int, args: Array[Tree], pt: Type): Array[Tree] = { - val argtypes = new Array[Type](args.length); - methtype match { - case Type$MethodType(params, restp) => - val formals = infer.formalTypes(params, args.length); - if (formals.length != args.length) { - error(pos, "wrong number of arguments for " + - (if (meth == null) "<function>" else meth) + - ArrayApply.toString(formals.asInstanceOf[Array[Object]], "(", ",", ")")); - return null; - } - if (tparams.isEmpty) { - List.map2(args, formals) ((arg, formal) => transform(arg, argMode, formal)) - } else { - val targs = protoTypeArgs(tparams, params, restp, pt); - val argpts = formals map (.subst(tparams, targs)); - val args1 = List.map2(args, argpts)((arg, argpt) => - transform(arg, argMode | POLYmode, argpt)); - // targs1: same as targs except that every WildcardType is mapped to - // formal parameter type. - val targs1 = List.map2(targs, tparams)((targ, tparam) => - if (targ == WildcardType) tparam.tpe else targ); - - - { var i = 0; while (i < args.length) { - argtypes(i) = args(i).getType().deconst(); - argtypes(i) match { - case Type$PolyType(tparams1, restype1) => - argtypes(i) = infer.argumentTypeInstance( - tparams1, restype1, - formals(i).subst(tparams, targs1), - argpts(i)); - case _ => - } - i = i + 1 - }} - } - // desugarizing ident patterns - if (params.length > 0 && (params(params.length-1).flags & REPEATED) != 0) { - if ((mode & PATTERNmode) != 0) { - def desug_allIdentPatterns(trees: Array[Tree], currentOwner: Symbol): unit = { - var i = 0; while (i < trees.length) { - trees(i) match { - case Tree.Ident(name) => - if (name != Names.PATTERN_WILDCARD) { - val vble: Symbol = context.scope.lookup(name); - trees(i) = desugarize.IdentPattern(trees(i)).setSymbol(vble) - .setType(vble.getType()); - } else { - trees(i) = gen.Ident(trees(i).pos, definitions.PATTERN_WILDCARD); - } - case _ => - } - i = i + 1 - } - } - desug_allIdentPatterns(args, context.owner); - } else { - assert(args.length != params.length || - !(args(params.length-1).isInstanceOf[Tree.Sequence])); - } - } - argtypes; - - case Type$PolyType(tparams1, restp) => - var tparams2: Array[Symbol] = tparams1; - if (tparams.length != 0) { - tparams2 = new Array[Symbol](tparams.length + tparams1.length); - System.arraycopy(tparams, 0, tparams2, 0, tparams.length); - System.arraycopy(tparams1, 0, tparams2, tparams.length, tparams1.length); - } - transformArgs(pos, meth, tparams2, - infer.skipViewParams(tparams2, restp), argMode, args, pt) - - case Type.ErrorType => - var i = 0; while (i < args.length) { - args(i) = transform(args(i), argMode, Type.ErrorType); - argtypes(i) = args(i).getType().deconst(); - i = i + 1 - } - argtypes - - case Type.OverloadedType(alts, alttypes) if (alts.length == 1) => - transformArgs(pos, alts(0), tparams, alttypes(0), argMode, args, pt) - - case _ => - var i = 0; while (i < args.length) { - args(i) = transform(args(i), argMode, Type.AnyType); - argtypes(i) = args(i).getType().deconst(); - i = i + 1 - } - argtypes } - } + def transform(tree: Tree, mode: int, pt: Type): Tree = + try { + if (tree.tpe != null) tree else adapt(transform1(tree, mode, pt), mode, pt) + } catch { + case ex: TypeError => + reportTypeError(tree.pos, ex); + setError(tree) + } + def transformExpr(tree: Tree): Tree = + transform(tree, EXPRmode, WildcardType); -/* tree - } + def transformType(tree: Tree, owner: Symbol) = + checkNoEscape(owner, transform(tree, TYPEmode, WildcardType)); } } -*/ - - def transformApply(tree: Tree, fn: Tree, args: List[Tree]): Tree = { - var fn1 = - if ((mode & PATTERNmode) != 0) transform(fn, mode | FUNmode & ~SEQUENCEmode, pt) - else transform(fn, mode | FUNmode, WildcardType); - - // if function is overloaded filter all alternatives that match - // number of arguments and expected result type. - if (fn1.hasSymbol && fn1.symbol.hasFlag(OVERLOADED)) { - val sym1 = fn1.symbol filter (alt => - isApplicable(fn1.symbol.info.prefix.memberType(alt), argtypes, pt)); - fn1.setSymbol(sym1).setType(fn1.symbol.info.prefix.memberType(sym1)); - } - - // handle the case of application of match to a visitor specially - args match { - case List(Visitor(_)) if (treeInfo.methSymbol(fn1) == Any_match) => - return transformMatch(fn1, args.head); - case _ => - } - } - - def transformApply(fn: Tree, args: List[Tree]): Tree = { - fn.tpe match { - case OverloadedType(pre, alts) => - val args1 = args map (arg => transform(arg, argMode, WildcardType)); - inferMethodAlternative(fn, args1 map (.tpe.deconst), pt); - transformApply(fn, args1); - case PolyType(tparams, restpe) => - transformApply(applyPoly(fn, tparams, restpe)); - case MethodType(formals0, restpe) => - val formals = formalTypes(formals, args.length); - if (formals.length != args.length) { - error(pos, "wrong number of arguments for " + treeSymTypeMsg(fn1)); - setError(tree) - } - val tparams = context.undetparams; - if (tparams.isEmpty) { - val args1 = List.map2(args, formals) ((arg, formal) => - transform(arg, argMode, formal)); - - } else { - val targs = protoTypeArgs(tparams, formals, restp, pt); - val argpts = formals map (.subst(tparams, targs)); - val args1 = List.map2(args, argpts1)((arg, argpt) => - transform(arg, argMode | POLYmode, argpt)); - // targs1: same as targs except that every WildcardType is mapped to - // formal parameter type. - val targs1 = List.map2(targs, tparams)((targ, tparam) => - if (targ == WildcardType) tparam.tpe else targ); - val argpts1 = formals map (.subst(tparams, targs1)); - val argtpes = List.map3(args, argpts, argpts1)(inferArgumentTypeInstance); - inferMethodInstance(fn, argtpes, pt); - transformApply(fn, args1) - } - - - - val tparams1 = tparams map (.cloneSymbol); - val restpe1 = restpe.substSym(tparams, tparams1); - - - copy.Apply(tree, fn1, args1).setType(???) - case MethodType(formals, restpe) => - transformMonoApply(fn1, formals, restpe, args) - - - - // type arguments with formals as prototypes if they exist. - val argtypes = transformArgs(tree.pos, fn1.symbol, fn1.tpe, - mode & (PATTERNmode | EXPRmode), args, pt); - if (argtypes == null || argtypes exists (.isError)) return setError(tree); - - var args1 = null; - // resolve overloading - - - - pt); - case _ => - } - - // infer method instance - - - val pattp: Type = matchQualType(fn1); - if (pattp.isError()) { - return setError(tree) - } else if (pattp != Type.NoType) { - if (infer.isFullyDefined(pattp) && - !(fn1.getType().isInstanceOf[Type$PolyType] && - pattp.containsSome(fn1.getType().typeParams()))) { - val fn2: Tree = desugarize.postMatch(fn1, context.enclClass.owner); - val arg1: Tree = transformVisitor(args(0), pattp, pt); - return copy.Apply(tree, fn2, NewArray.Tree(arg1)) - .setType(arg1.getType()); - } else { - error(tree.pos, "expected pattern type of cases could not be determined"); - return errorTermTree(tree) - } - } - } - - -*/ diff --git a/sources/scala/tools/nsc/typechecker/Typers.scala b/sources/scala/tools/nsc/typechecker/Typers.scala index 4c2f785af5..12cfb8a66a 100755 --- a/sources/scala/tools/nsc/typechecker/Typers.scala +++ b/sources/scala/tools/nsc/typechecker/Typers.scala @@ -22,21 +22,41 @@ trait Typers: Analyzer { def typeCompleter(tree: Tree) = new TypeCompleter(tree) { override def complete(sym: Symbol): unit = { - if (settings.debug.value) log("defining " + sym); - sym.setInfo(typeSig(tree)); + if (settings.debug.value) log("defining " + sym); + sym.setInfo(typeSig(tree)); + if (settings.debug.value) log("defined " + sym); + validate(sym); + } + } + + def getterTypeCompleter(tree: Tree) = new TypeCompleter(tree) { + override def complete(sym: Symbol): unit = { + if (settings.debug.value) log("defining " + sym); + sym.setInfo(PolyType(List(), typeSig(tree))); + if (settings.debug.value) log("defined " + sym); + validate(sym); + } + } + + def setterTypeCompleter(tree: Tree) = new TypeCompleter(tree) { + override def complete(sym: Symbol): unit = { + if (settings.debug.value) log("defining " + sym); + sym.setInfo(MethodType(List(typeSig(tree)), definitions.UnitClass.tpe)); if (settings.debug.value) log("defined " + sym); validate(sym); } } def selfTypeCompleter(tree: Tree) = new TypeCompleter(tree) { - override def complete(sym: Symbol): unit = - sym.setInfo(typechecker.transformType(tree).tpe) + override def complete(sym: Symbol): unit = { + sym.setInfo(typechecker.transformType(tree, sym).tpe); + } } private def deconstIfNotFinal(sym: Symbol, tpe: Type): Type = if (sym.isVariable || !sym.hasFlag(FINAL)) tpe.deconst else tpe; + private def enterTypeParams(owner: Symbol, tparams: List[AbsTypeDef]): List[Symbol] = { List.map2(owner.typeParams, tparams) { (tpsym, tptree) => tptree.symbol = tpsym; context.scope enter tpsym; tpsym } @@ -62,45 +82,29 @@ trait Typers: Analyzer { case _ => tpe }); - private def templateSig(clazz: Symbol, templ: Template): Type = { - // determine parent types - val parents = - if (templ.parents.isEmpty) List() - else - typechecker.transformSuperType(templ.parents.head).tpe :: - (templ.parents.tail map (p => typechecker.transformType(p).tpe)); - if (!parents.isEmpty && parents.head.symbol.hasFlag(INTERFACE) - && parents.head.symbol.hasFlag(JAVA)) - unit.error(templ.parents.head.pos, "cannot extend a Java interface"); - - // enter all members + private def templateSig(templ: Template): Type = { + val clazz = context.owner; + val parents = typechecker.parentTypes(templ) map (.tpe); val decls = new Scope(); new Namer(context.make(templ, clazz, decls)).enterSyms(templ.body); ClassInfoType(parents, decls, clazz) } - private def classSig(clazz: Symbol, - tparams: List[AbsTypeDef], - tpt: Tree, impl: Template): Type = { + private def classSig(tparams: List[AbsTypeDef], tpt: Tree, impl: Template): Type = { + val clazz = context.owner; val tparamSyms = enterTypeParams(clazz, tparams); if (!tpt.isEmpty) clazz.typeOfThis = selfTypeCompleter(tpt); - val constrTree = treeInfo.firstConstructor(impl.body); - val constr = new Namer(context).enterSym(constrTree).initialize; - typechecker.reenterValueParams(constrTree); - makePolyType(tparamSyms, templateSig(clazz, impl)) + makePolyType(tparamSyms, templateSig(impl)) } - private def methodSig(meth: Symbol, - tparams: List[AbsTypeDef], vparamss: List[List[ValDef]], - tpt: Tree, rhs: Tree): Type = { + private def methodSig(tparams: List[AbsTypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree): Type = { + val meth = context.owner; val tparamSyms = enterTypeParams(meth, tparams); val vparamSymss = enterValueParams(meth, vparamss); - val restype = - typechecker.checkNoEscape(tpt.pos, - deconstIfNotFinal(meth, - if (meth.name == nme.CONSTRUCTOR) context.enclClass.owner.tpe - else if (tpt.isEmpty) { tpt.tpe = typechecker.transformExpr(rhs).tpe; tpt.tpe } - else typechecker.transformType(tpt).tpe)); + val restype = deconstIfNotFinal(meth, + if (meth.name == nme.CONSTRUCTOR) context.enclClass.owner.tpe + else if (tpt.isEmpty) { tpt.tpe = typechecker.transformExpr(rhs).tpe; tpt.tpe } + else typechecker.transformType(tpt, meth).tpe); def mkMethodType(vparams: List[Symbol], restpe: Type) = MethodType(vparams map (.tpe), restpe); makePolyType( @@ -110,24 +114,22 @@ trait Typers: Analyzer { } private def aliasTypeSig(tpsym: Symbol, tparams: List[AbsTypeDef], rhs: Tree): Type = - makePolyType(enterTypeParams(tpsym, tparams), typechecker.transformType(rhs).tpe); + makePolyType(enterTypeParams(tpsym, tparams), typechecker.transformType(rhs, tpsym).tpe); private def typeSig(tree: Tree): Type = try { val sym: Symbol = tree.symbol; tree match { case ClassDef(_, _, tparams, tpt, impl) => - new Typer(context.makeNewScope(tree, sym)).classSig(sym, tparams, tpt, impl) + new Typer(context.makeNewScope(tree, sym)).classSig(tparams, tpt, impl) - case ModuleDef(_, _, tpt, impl) => + case ModuleDef(_, _, impl) => val clazz = sym.moduleClass; - clazz.setInfo(new Typer(context.make(tree, clazz)).templateSig(clazz, impl)); - if (tpt.isEmpty) { tpt.tpe = clazz.tpe; tpt.tpe } - else typechecker.transformType(tpt).tpe + clazz.setInfo(new Typer(context.make(tree, clazz)).templateSig(impl)); + clazz.tpe case DefDef(_, _, tparams, vparamss, tpt, rhs) => - new Typer(context.makeNewScope(tree, sym)) - .methodSig(sym, tparams, vparamss, tpt, rhs) + new Typer(context.makeNewScope(tree, sym)).methodSig(tparams, vparamss, tpt, rhs) case ValDef(_, _, tpt, rhs) => deconstIfNotFinal(sym, @@ -140,13 +142,14 @@ trait Typers: Analyzer { .transformExpr(rhs).tpe; tpt.tpe } - else typechecker.transformType(tpt).tpe) + else typechecker.transformType(tpt, sym).tpe) case AliasTypeDef(_, _, tparams, rhs) => new Typer(context.makeNewScope(tree, sym)).aliasTypeSig(sym, tparams, rhs) case AbsTypeDef(_, _, lo, hi) => - TypeBounds(typechecker.transformType(lo).tpe, typechecker.transformType(hi).tpe); + TypeBounds(typechecker.transformType(lo, sym).tpe, + typechecker.transformType(hi, sym).tpe); case imptree @ Import(expr, selectors) => val expr1 = typechecker.transformExpr(expr); |