diff options
author | Martin Odersky <odersky@gmail.com> | 2005-02-21 17:19:28 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2005-02-21 17:19:28 +0000 |
commit | a50c72311952db8e6273a4048deee806db36110a (patch) | |
tree | 203bdce52f0552f79c904a0203cc4875be3d94eb | |
parent | 1b7d5dbc1f4a36b3099b5cb376c1dd6f8f747295 (diff) | |
download | scala-a50c72311952db8e6273a4048deee806db36110a.tar.gz scala-a50c72311952db8e6273a4048deee806db36110a.tar.bz2 scala-a50c72311952db8e6273a4048deee806db36110a.zip |
*** empty log message ***
18 files changed, 626 insertions, 476 deletions
diff --git a/sources/scala/List.scala b/sources/scala/List.scala index 5ce118412f..3808cb40d0 100644 --- a/sources/scala/List.scala +++ b/sources/scala/List.scala @@ -204,12 +204,24 @@ object List { * @param f function to apply to each pair of elements. * @return <code>[f(a0,b0), ..., f(an,bn)]</code> if the lists are * <code>[a0, ..., ak]</code>, <code>[b0, ..., bl]</code> and - * <code>m = min(k,l)</code> + * <code>n = min(k,l)</code> */ def map2[a,b,c](xs: List[a], ys: List[b])(f: (a, b) => c): List[c] = if (xs.isEmpty || ys.isEmpty) Nil else f(xs.head, ys.head) :: map2(xs.tail, ys.tail)(f); + /** Returns the list resulting from applying the given function <code>f</code> to + * corresponding elements of the argument lists. + * + * @param f function to apply to each pair of elements. + * @return <code>[f(a0,b0,c0), ..., f(an,bn,cn)]</code> if the lists are + * <code>[a0, ..., ak]</code>, <code>[b0, ..., bl]</code>, <code>[c0, ..., cm]</code> and + * <code>n = min(k,l,m)</code> + */ + def map3[a,b,c, d](xs: List[a], ys: List[b], zs: List[c])(f: (a, b, c) => d): List[d] = + if (xs.isEmpty || ys.isEmpty || zs.isEmpty) Nil + else f(xs.head, ys.head, zs.head) :: map3(xs.tail, ys.tail, zs.tail)(f); + /** Tests whether the given predicate <code>p</code> holds * for all corresponding elements of the argument lists. * diff --git a/sources/scala/tools/nsc/Global.scala b/sources/scala/tools/nsc/Global.scala index b87b9e26f9..a6c09fe855 100755 --- a/sources/scala/tools/nsc/Global.scala +++ b/sources/scala/tools/nsc/Global.scala @@ -17,10 +17,7 @@ import ast._; import ast.parser._; import typechecker._; -class Global(val settings: Settings, val reporter: Reporter) - extends SymbolTable - with Trees - with CompilationUnits { +class Global(val settings: Settings, val reporter: Reporter) extends SymbolTable with Trees with TreeCheckers with CompilationUnits { // sub-components -------------------------------------------------- @@ -48,6 +45,7 @@ class Global(val settings: Settings, val reporter: Reporter) def warning(msg: String) = reporter.warning(null, msg); def inform(msg: String) = reporter.info(null, msg, true); + def log(msg: String) = if (settings.log contains phase.name) inform("[log " + phase + "] " + msg); @@ -115,15 +113,10 @@ class Global(val settings: Settings, val reporter: Reporter) definitions.init; // needs firstPhase to be defined, that's why it is placed here. - object deSugarizePhase extends DeSugarizePhase(parserPhase) { - val global: Global.this.type = Global.this - } - object analyzer extends Analyzer { val global: Global.this.type = Global.this; } - - val namerPhase = new analyzer.NamerPhase(deSugarizePhase); + val namerPhase = new analyzer.NamerPhase(parserPhase); val typeCheckPhase = new analyzer.TypeCheckPhase(namerPhase); val terminalPhase = new StdPhase(typeCheckPhase) { @@ -159,11 +152,13 @@ class Global(val settings: Settings, val reporter: Reporter) reporter.resetCounters(); for (val source <- sources) addUnit(new CompilationUnit(source)); + phase = NoPhase.next; while (phase != terminalPhase && reporter.errors() == 0) { val startTime = System.currentTimeMillis(); if (!(settings.skip contains phase.name)) phase.run; if (settings.print contains phase.name) treePrinter.printAll(); + if (settings.check contains phase.name) checkTrees; informTime(phase.description, startTime); phase = if (settings.stop contains phase.name) terminalPhase else phase.next; } @@ -199,6 +194,10 @@ class Global(val settings: Settings, val reporter: Reporter) case ex: IOException => error(ex.getMessage()); } + def checkTrees: unit = + for (val unit <- units; val tree <- unit.body) + treeChecker.traverse(tree); + def showDef(name: Name, module: boolean): unit = { def getSym(name: Name, module: boolean): Symbol = { var i = name.length - 1; diff --git a/sources/scala/tools/nsc/StdPhase.scala b/sources/scala/tools/nsc/StdPhase.scala index 36bfaebf2c..7db984f563 100644 --- a/sources/scala/tools/nsc/StdPhase.scala +++ b/sources/scala/tools/nsc/StdPhase.scala @@ -7,8 +7,7 @@ package scala.tools.nsc; abstract class StdPhase(prev: Phase) extends Phase(prev) { val global: Global; - def run: unit = - for (val unit <- global.units) apply(unit); + def run: unit = for (val unit <- global.units) apply(unit); def apply(unit: global.CompilationUnit): unit; } diff --git a/sources/scala/tools/nsc/ast/TreeInfo.scala b/sources/scala/tools/nsc/ast/TreeInfo.scala index 7e703fbaf4..92e5c00cd4 100644 --- a/sources/scala/tools/nsc/ast/TreeInfo.scala +++ b/sources/scala/tools/nsc/ast/TreeInfo.scala @@ -114,7 +114,11 @@ abstract class TreeInfo { case _ => firstConstructor(stats.tail) } - /** Is name a variable name */ + /** Is name a left-associative operator? */ + def isLeftAssoc(operator: Name): boolean = + operator.length > 0 && operator(operator.length - 1) != ':'; + + /** Is name a variable name? */ def isVariableName(name: Name): boolean = { val first = name(0); (('a' <= first && first <= 'z') || first == '_') diff --git a/sources/scala/tools/nsc/ast/TreePrinters.scala b/sources/scala/tools/nsc/ast/TreePrinters.scala index ae61481f85..47c8af4cfb 100644 --- a/sources/scala/tools/nsc/ast/TreePrinters.scala +++ b/sources/scala/tools/nsc/ast/TreePrinters.scala @@ -70,12 +70,17 @@ abstract class TreePrinters { printOpt(">: ", lo); printOpt("<: ", hi); } + def printBlock(tree: Tree): unit = tree match { + case Block(_, _) | Visitor(_) => print(tree) + case _ => printColumn(List(tree), "{", ";", "}") + } + def symName(tree: Tree, name: Name): String = if (tree.symbol != null && tree.symbol != NoSymbol) tree.symbol.nameString else name.toString(); def printOpt(prefix: String, tree: Tree): unit = - if (tree != EmptyTree) { print(prefix); print(tree) } + if (!tree.isEmpty) { print(prefix); print(tree) } def printModifiers(flags: int): unit = { val s = flagsToString(flags); @@ -109,7 +114,7 @@ abstract class TreePrinters { printOpt(": ", tp); if ((mods & DEFERRED) == 0) { print(" = "); - if (rhs == EmptyTree) print("_") else print(rhs) + if (rhs.isEmpty) print("_") else print(rhs) } case DefDef(mods, name, tparams, vparams, tp, rhs) => @@ -126,22 +131,14 @@ abstract class TreePrinters { printTypeParams(tparams); printOpt(" = ", rhs); case LabelDef(name, params, rhs) => - print(symName(tree, name)); printRow(params, "(", ",", ")"); print(rhs); + print(symName(tree, name)); printRow(params, "(", ",", ")"); printBlock(rhs); case Import(expr, selectors) => - def printSelectors(ss: List[Pair[Name, Name]]): unit = ss match { - case List(Pair(nme.WILDCARD, _)) => print("_"); - case Pair(s1, s2) :: ss1 => - print(s1); - if (s1 != s2) print("=>" + s2); - if (!ss1.isEmpty) { - print(", "); printSelectors(ss1); - } - } - print("import "); print(expr); print(".{"); printSelectors(selectors); print("}"); - - case PatDef(mods, pat, rhs) => - print(flagsToString(mods) + " val "); print(pat); printOpt(" = ", rhs); + def selectorToString(s: Pair[Name, Name]): String = + if (s._1 == nme.WILDCARD || s._1 == s._2) s._1.toString() + else s._1.toString() + "=>" + s._2.toString(); + print("import "); print(expr); + print(selectors.map(selectorToString).mkString(".{", ", ", "}")) case Attributed(attr, definition) => print("["); print(attr); print("]"); println; print(definition); @@ -177,15 +174,10 @@ abstract class TreePrinters { case Assign(lhs, rhs) => print(lhs); print(" = "); print(rhs) - case For(enumerators, body, isForYield) => - printRow(enumerators, "for(", "; ", ") "); - if (isForYield) print("yield "); - print(body) - case If(cond, thenp, elsep) => print("if ("); print(cond); print(")"); indent; println; print(thenp); undent; - if (elsep != EmptyTree) { + if (!elsep.isEmpty) { println; print("else"); indent; println; print(elsep); undent } @@ -199,8 +191,9 @@ abstract class TreePrinters { print("return "); print(expr) case Try(block, catcher, finalizer) => - print("try "); print(block); print(" catch "); print(catcher); - print(" finally "); print(finalizer) + print("try "); printBlock(block); + printOpt(" catch ", catcher); + printOpt(" finally ", finalizer) case Throw(expr) => print("throw "); print(expr) @@ -239,6 +232,7 @@ abstract class TreePrinters { print(obj match { case null => "null" case s: String => "\"" + s + "\"" + case c: char => "\'" + c + "\'" case _ => obj.toString() }) @@ -251,9 +245,6 @@ abstract class TreePrinters { case SelectFromTypeTree(qualifier, selector) => print(qualifier); print("#"); print(symName(tree, selector)) - case FunctionTypeTree(argtpes, restpe) => - printRow(argtpes, "(", ", ", ") => "); print(restpe) - case IntersectionTypeTree(parents) => printRow(parents, " with ") @@ -263,7 +254,7 @@ abstract class TreePrinters { case AppliedTypeTree(tp, args) => print(tp); printRow(args, "[", ", ", "]") } - if (global.settings.printtypes.value && tree.isTerm && tree != EmptyTree) { + if (global.settings.printtypes.value && tree.isTerm && !tree.isEmpty) { print("{"); print(if (tree.tpe == null) "<null>" else tree.tpe.toString()); print("}") } } diff --git a/sources/scala/tools/nsc/ast/Trees.scala b/sources/scala/tools/nsc/ast/Trees.scala index 909c15d5b0..5178ad1dba 100644 --- a/sources/scala/tools/nsc/ast/Trees.scala +++ b/sources/scala/tools/nsc/ast/Trees.scala @@ -103,10 +103,6 @@ class Trees: Global { case class Import(expr: Tree, selectors: List[Pair[Name, Name]]) extends SymTree; - /** Pattern definition, eliminated by Analyzer */ - case class PatDef(mods: int, pat: Tree, rhs: Tree) - extends Tree; - /** Attribuetd definition */ case class Attributed(attribute: Tree, definition: Tree) extends Tree; @@ -156,10 +152,6 @@ class Trees: Global { case class If(cond: Tree, thenp: Tree, elsep: Tree) extends TermTree; - /** For comprehension */ - case class For(enumerators: List[Tree], body: Tree, isForYield: boolean) - extends TermTree; - /** Switch, introduced by refcheck */ case class Switch(test: Tree, tags: List[int], bodies: List[Tree], default: Tree) @@ -179,7 +171,7 @@ class Trees: Global { /** Object instantiation * @param init either a constructor or a template */ - case class New(init: Tree) + case class New(typeOrTempl: Tree) extends TermTree; /** Type annotation, eliminated by explicit outer */ @@ -222,7 +214,7 @@ class Trees: Global { /** General type term, introduced by RefCheck. */ case class EmptyTypeTree() extends TypeTree { - override def isEmpty = true; + override def isEmpty = tpe == null; } /** Singleton type, eliminated by RefCheck */ @@ -233,10 +225,6 @@ class Trees: Global { case class SelectFromTypeTree(qualifier: Tree, selector: Name) extends TypeTree with SymTree; - /** Function type, eliminated by RefCheck */ - case class FunctionTypeTree(argtpes: List[Tree], restpe: Tree) - extends TypeTree; - /** Intersection type, eliminated by RefCheck */ case class IntersectionTypeTree(parents: List[Tree]) extends TypeTree; @@ -253,33 +241,31 @@ class Trees: Global { case EmptyTree => case ClassDef(mods, name, tparams, tp, impl) => case PackageDef(name, stats) => - case ModuleDef(mods, name, tp, impl) => + case ModuleDef(mods, name, tp, impl) => (eliminated by refcheck) case ValDef(mods, name, tp, rhs) => case DefDef(mods, name, tparams, vparams, tp, rhs) => - case AbsTypeDef(mods, name, lo, hi) => - case AliasTypeDef(mods, name, tparams, rhs) => + case AbsTypeDef(mods, name, lo, hi) => (eliminated by erasure) + case AliasTypeDef(mods, name, tparams, rhs) => (eliminated by erasure) case LabelDef(name, params, rhs) => - case Import(expr, selectors) => - case PatDef(mods, pat, rhs) => - case Attributed(attribute, definition) => - case DocDef(comment, definition) => + case Import(expr, selectors) => (eliminated by typecheck) + case Attributed(attribute, definition) => (eliminated by typecheck) + case DocDef(comment, definition) => (eliminated by typecheck) case Template(parents, body) => case Block(stats, expr) => - case Visitor(cases) => - case CaseDef(pat, guard, body) => - case Sequence(trees) => - case Alternative(trees) => - case Bind(name, rhs) => - case Function(vparams, body) => + 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 Function(vparams, body) => (eliminated by typecheck) case Assign(lhs, rhs) => - case For(enumerators, body, isForYield) => case If(cond, thenp, elsep) => - case Switch(test, tags, bodies, default) => + case Switch(test, tags, bodies, default) => (introduced by refcheck, transmatch) case Return(expr) => case Try(block, catcher, finalizer) => case Throw(expr) => - case New(init) => - case Typed(expr, tp) => + case New(typeOrTempl) => + case Typed(expr, tp) => (eliminated by erasure) case TypeApply(fun, args) => case Apply(fun, args) => case Super(qual, mixin) => @@ -287,13 +273,12 @@ class Trees: Global { case Select(qualifier, selector) => case Ident(name) => case Literal(value) => - case EmptyTypeTree() => - case SingletonTypeTree(ref) => - case SelectFromTypeTree(qualifier, selector) => - case FunctionTypeTree(argtpes, restpe) => - case IntersectionTypeTree(parents) => - case RefinementTypeTree(base, decls) => - case AppliedTypeTree(tp, args) => + case EmptyTypeTree() => (eliminated by typecheck) + 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) */ trait TreeCopier { @@ -306,7 +291,6 @@ class Trees: Global { 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; def Import(tree: Tree, expr: Tree, selectors: List[Pair[Name, Name]]): Import; - def PatDef(tree: Tree, mods: int, pat: Tree, rhs: Tree): PatDef; def Attributed(tree: Tree, attribute: Tree, definition: Tree): Attributed; def DocDef(tree: Tree, comment: String, definition: Tree): DocDef; def Template(tree: Tree, parents: List[Tree], body: List[Tree]): Template; @@ -319,12 +303,11 @@ class Trees: Global { 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 For(tree: Tree, enumerators: List[Tree], body: Tree, isForYield: boolean): For; def Switch(tree: Tree, test: Tree, tags: List[int], bodies: List[Tree], default: Tree): Switch; def Return(tree: Tree, expr: Tree): Return; def Try(tree: Tree, block: Tree, catcher: Tree, finalizer: Tree): Try; def Throw(tree: Tree, expr: Tree): Throw; - def New(tree: Tree, init: Tree): New; + def New(tree: Tree, typeOrTempl: Tree): New; def Typed(tree: Tree, expr: Tree, tp: Tree): Typed; def TypeApply(tree: Tree, fun: Tree, args: List[Tree]): TypeApply; def Apply(tree: Tree, fun: Tree, args: List[Tree]): Apply; @@ -336,7 +319,6 @@ class Trees: Global { def EmptyTypeTree(tree: Tree): EmptyTypeTree; def SingletonTypeTree(tree: Tree, ref: Tree): SingletonTypeTree; def SelectFromTypeTree(tree: Tree, qualifier: Tree, selector: Name): SelectFromTypeTree; - def FunctionTypeTree(tree: Tree, argtpes: List[Tree], restpe: Tree): FunctionTypeTree; 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; @@ -361,8 +343,6 @@ class Trees: Global { { val t = new LabelDef(name, params, rhs); t.setPos(tree.pos); t } def Import(tree: Tree, expr: Tree, selectors: List[Pair[Name, Name]]) = { val t = new Import(expr, selectors); t.setPos(tree.pos); t } - def PatDef(tree: Tree, mods: int, pat: Tree, rhs: Tree) = - { val t = new PatDef(mods, pat, rhs); t.setPos(tree.pos); t } def Attributed(tree: Tree, attribute: Tree, definition: Tree) = { val t = new Attributed(attribute, definition); t.setPos(tree.pos); t } def DocDef(tree: Tree, comment: String, definition: Tree) = @@ -387,8 +367,6 @@ class Trees: Global { { 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 For(tree: Tree, enumerators: List[Tree], body: Tree, isForYield: boolean) = - { val t = new For(enumerators, body, isForYield); 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 Return(tree: Tree, expr: Tree) = @@ -397,8 +375,8 @@ class Trees: Global { { val t = new Try(block, catcher, 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, init: Tree) = - { val t = new New(init); 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 TypeApply(tree: Tree, fun: Tree, args: List[Tree]) = @@ -421,8 +399,6 @@ class Trees: Global { { 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 FunctionTypeTree(tree: Tree, argtpes: List[Tree], restpe: Tree) = - { val t = new FunctionTypeTree(argtpes, restpe); 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]) = @@ -478,11 +454,6 @@ class Trees: Global { if (expr0 == expr && selectors0 == selectors) => t case _ => copy.Import(tree, expr, selectors) } - def PatDef(tree: Tree, mods: int, pat: Tree, rhs: Tree) = tree match { - case t @ PatDef(mods0, pat0, rhs0) - if (mods0 == mods && pat0 == pat && rhs0 == rhs) => t - case _ => copy.PatDef(tree, mods, pat, rhs) - } def Attributed(tree: Tree, attribute: Tree, definition: Tree) = tree match { case t @ Attributed(attribute0, definition0) if (attribute0 == attribute && definition0 == definition) => t @@ -543,11 +514,6 @@ class Trees: Global { if (cond0 == cond && thenp0 == thenp && elsep0 == elsep) => t case _ => copy.If(tree, cond, thenp, elsep) } - def For(tree: Tree, enumerators: List[Tree], body: Tree, isForYield: boolean) = tree match { - case t @ For(enumerators0, body0, isForYield0) - if (enumerators0 == enumerators && body0 == body && isForYield0 == isForYield) => t - case _ => copy.For(tree, enumerators, body, isForYield) - } 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 @@ -568,10 +534,10 @@ class Trees: Global { if (expr0 == expr) => t case _ => copy.Throw(tree, expr) } - def New(tree: Tree, init: Tree) = tree match { - case t @ New(init0) - if (init0 == init) => t - case _ => copy.New(tree, init) + def New(tree: Tree, typeOrTempl: Tree) = tree match { + case t @ New(typeOrTempl0) + if (typeOrTempl0 == typeOrTempl) => t + case _ => copy.New(tree, typeOrTempl) } def Typed(tree: Tree, expr: Tree, tp: Tree) = tree match { case t @ Typed(expr0, tp0) @@ -627,11 +593,6 @@ class Trees: Global { if (qualifier0 == qualifier && selector0 == selector) => t case _ => copy.SelectFromTypeTree(tree, qualifier, selector) } - def FunctionTypeTree(tree: Tree, argtpes: List[Tree], restpe: Tree) = tree match { - case t @ FunctionTypeTree(argtpes0, restpe0) - if (argtpes0 == argtpes && restpe0 == restpe) => t - case _ => copy.FunctionTypeTree(tree, argtpes, restpe) - } def IntersectionTypeTree(tree: Tree, parents: List[Tree]) = tree match { case t @ IntersectionTypeTree(parents0) if (parents0 == parents) => t @@ -672,8 +633,6 @@ class Trees: Global { copy.LabelDef(tree, name, transformIdents(params), transform(rhs)) case Import(expr, selectors) => copy.Import(tree, transform(expr), selectors) - case PatDef(mods, pat, rhs) => - copy.PatDef(tree, mods, transform(pat), transform(rhs)) case Attributed(attribute, definition) => copy.Attributed(tree, transform(attribute), transform(definition)) case DocDef(comment, definition) => @@ -696,8 +655,6 @@ class Trees: Global { copy.Function(tree, transformValDefs(vparams), transform(body)) case Assign(lhs, rhs) => copy.Assign(tree, transform(lhs), transform(rhs)) - case For(enumerators, body: Tree, isForYield) => - copy.For(tree, transformTrees(enumerators), transform(body), isForYield) case If(cond, thenp, elsep) => copy.If(tree, transform(cond), transform(thenp), transform(elsep)) case Switch(test, tags, bodies, default) => @@ -708,8 +665,8 @@ class Trees: Global { copy.Try(tree, transform(block), transform(catcher), transform(finalizer)) case Throw(expr) => copy.Throw(tree, transform(expr)) - case New(init) => - copy.New(tree, transform(init)) + case New(typeOrTempl) => + copy.New(tree, transform(typeOrTempl)) case Typed(expr, tp) => copy.Typed(tree, transform(expr), transform(tp)) case TypeApply(fun, args) => @@ -732,8 +689,6 @@ class Trees: Global { copy.SingletonTypeTree(tree, transform(ref)) case SelectFromTypeTree(qualifier, selector) => copy.SelectFromTypeTree(tree, transform(qualifier), selector) - case FunctionTypeTree(argtpes, restpe) => - copy.FunctionTypeTree(tree, transformTrees(argtpes), transform(restpe)) case IntersectionTypeTree(parents) => copy.IntersectionTypeTree(tree, transformTrees(parents)) case RefinementTypeTree(base, decls) => @@ -778,8 +733,6 @@ class Trees: Global { traverseTrees(params); traverse(rhs) case Import(expr, selectors) => traverse(expr) - case PatDef(mods, pat, rhs) => - traverse(pat); traverse(rhs) case Attributed(attribute, definition) => traverse(attribute); traverse(definition) case DocDef(comment, definition) => @@ -802,8 +755,6 @@ class Trees: Global { traverseTrees(vparams); traverse(body) case Assign(lhs, rhs) => traverse(lhs); traverse(rhs) - case For(enumerators, body: Tree, isForYield) => - traverseTrees(enumerators); traverse(body) case If(cond, thenp, elsep) => traverse(cond); traverse(thenp); traverse(elsep) case Switch(test, tags, bodies, default) => @@ -814,8 +765,8 @@ class Trees: Global { traverse(block); traverse(catcher); traverse(finalizer) case Throw(expr) => traverse(expr) - case New(init) => - traverse(init) + case New(typeOrTempl) => + traverse(typeOrTempl) case Typed(expr, tp) => traverse(expr); traverse(tp) case TypeApply(fun, args) => @@ -828,8 +779,6 @@ class Trees: Global { traverse(ref) case SelectFromTypeTree(qualifier, selector) => traverse(qualifier) - case FunctionTypeTree(argtpes, restpe) => - traverseTrees(argtpes); traverse(restpe) case IntersectionTypeTree(parents) => traverseTrees(parents) case RefinementTypeTree(base, decls) => diff --git a/sources/scala/tools/nsc/ast/parser/Syntactic.scala b/sources/scala/tools/nsc/ast/parser/Syntactic.scala index 7ba1574072..b819d0e6e6 100755 --- a/sources/scala/tools/nsc/ast/parser/Syntactic.scala +++ b/sources/scala/tools/nsc/ast/parser/Syntactic.scala @@ -10,6 +10,34 @@ import scala.collection.mutable.ListBuffer; import symtab.Flags; import Tokens._; +/** Performs the following context-free rewritings: + * (1) Places all pattern variables in Bind nodes. In a pattern, for identifiers `x': + * x => x @ _ + * x:T => x @ (_ : T) + * + * (2) Removes pattern definitions (PatDef's) as follows: + * If pattern is a simple (typed) identifier: + * val x = e ==> val x = e + * val x: T = e ==> val x: T = e + * + * if there are no variables in pattern + * val p = e ==> e.match (case p => ()) + * + * if there is exactly one variable in pattern + * val x_1 = e.match (case p => (x_1)) + * + * if there is more than one variable in pattern + * val p = e ==> private synthetic val t$ = e.match (case p => (x_1, ..., x_N)) + * val x_1 = t$._1 + * ... + * val x_N = t$._N + * + * (3) Removes function types as follows: + * (argtpes) => restpe ==> scala.Function_n[argtpes, restpe] + * + * (4) Wraps naked case definitions in a match as follows: + * { cases } ==> (x => x.match {cases}), except when already argument to match + */ abstract class Syntactic: ParserPhase { import global._; @@ -27,6 +55,12 @@ abstract class Syntactic: ParserPhase { */ var loopNestingDepth = 0; + object treeBuilder extends TreeBuilder { + val global: Syntactic.this.global.type = Syntactic.this.global; + def freshName(): Name = unit.fresh.newName("x$"); + } + import treeBuilder._; + /** this is the general parse method */ def parse(): List[Tree] = { @@ -134,85 +168,14 @@ abstract class Syntactic: ParserPhase { /////// TREE CONSTRUCTION //////////////////////////////////////////////////// - def fresh(): Name = unit.fresh.newName("x"); - - /** Create a tree representing a packaging - */ - def makePackaging(pkg: Tree, stats: List[Tree]): Tree = - atPos(in.pos) { - pkg match { - case Ident(name) => - PackageDef(name, stats) - case Select(qual, name) => - makePackaging(qual, List(PackageDef(name, stats))) - } - } - - /** Create tree representing binary operation expression or pattern. - */ - def makeBinop(isExpr: boolean, left: Tree, op: Name, right: Tree): Tree = { - if (isExpr) { - if (isLeftAssoc(op)) { - Apply(Select(left, op.encode), List(right)) - } else { - val x: Name = fresh(); - Block( - List(ValDef(0, x, EmptyTypeTree(), left)), - Apply(Select(right, op.encode), List(Ident(x)))) - } - } else { - Apply(Ident(op.encode.toTypeName), List(left, right)) - } - } - def makeAlternative(ts: List[Tree]): Tree = { - def alternatives(t: Tree): List[Tree] = t match { - case Alternative(ts) => ts - case _ => List(t) - } - Alternative(for (val t <- ts; val a <- alternatives(t)) yield a) - } - - def makeSequence(ts: List[Tree]): Tree = { - def elements(t: Tree): List[Tree] = t match { - case Sequence(ts) => ts - case _ => List(t) - } - Sequence(for (val t <- ts; val e <- elements(t)) yield e) - } - def scalaDot(name: Name): Tree = Select(Ident(nme.scala), name); - def scalaRuntimeDot(name: Name): Tree = - Select(scalaDot(nme.runtime), name); - def ScalaRunTimeDot(name: Name): Tree = - Select(scalaRuntimeDot(nme.ScalaRunTime), name); - def scalaBooleanDot(name: Name): Tree = - Select(scalaDot(nme.Boolean), name); - def scalaAnyRefConstr(): Tree = - Apply(scalaDot(nme.AnyRef.toTypeName), List()); - def scalaObjectConstr(): Tree = - Apply(scalaDot(nme.ScalaObject.toTypeName), List()); - def caseClassConstr(): Tree = - Apply(scalaDot(nme.CaseClass.toTypeName), List()); - - def makeWhile(lname: Name, cond: Tree, body: Tree): Tree = { - val continu = Apply(Ident(lname), List()); - val rhs = If(cond, Block(List(body), continu), Literal(())); - LabelDef(lname, Nil, rhs) - } - - def makeDoWhile(lname: Name, body: Tree, cond: Tree): Tree = { - val continu = Apply(Ident(lname), List()); - val rhs = Block(List(body), If(cond, continu, Literal(()))); - LabelDef(lname, Nil, rhs) - } - - def makeBlock(stats: List[Tree]): Tree = { - if (stats.isEmpty) Literal(()) - else if (!stats.last.isTerm) Block(stats, Literal(())); - else if (stats.length == 1) stats(0) - else Block(stats.init, stats.last) - } + def scalaAnyRefConstr: Tree = + scalaDot(nme.AnyRef.toTypeName); + def scalaScalaObjectConstr: Tree = + scalaDot(nme.ScalaObject.toTypeName); + def caseClassConstr: Tree = + scalaDot(nme.CaseClass.toTypeName); /** Convert tree to formal parameter list */ @@ -265,7 +228,7 @@ abstract class Syntactic: ParserPhase { /** make closure from tree */ def makeClosure(tree: Tree): Tree = { - val pname = fresh(); + val pname = freshName(); def insertParam(tree: Tree): Tree = tree match { case Ident(name) => Select(Ident(pname), name) @@ -310,14 +273,11 @@ abstract class Syntactic: ParserPhase { } } - def isLeftAssoc(operator: Name): boolean = - operator.length > 0 && operator(operator.length - 1) != ':'; - def reduceStack(isExpr: boolean, base: List[OpInfo], top0: Tree, prec: int, leftAssoc: boolean): Tree = { var top = top0; if (opstack != base && precedence(opstack.head.operator) == prec && - isLeftAssoc(opstack.head.operator) != leftAssoc) { + treeInfo.isLeftAssoc(opstack.head.operator) != leftAssoc) { syntaxError( opstack.head.pos, "left- and right-associative operators with same precedence may not be mixed", @@ -514,14 +474,14 @@ abstract class Syntactic: ParserPhase { in.nextToken(); if (in.token == RPAREN) { in.nextToken(); - atPos(accept(ARROW)) { FunctionTypeTree(List(), typ()) } + atPos(accept(ARROW)) { makeFunctionTypeTree(List(), typ()) } } else { val t0 = typ(); if (in.token == COMMA) { in.nextToken(); val ts = new ListBuffer[Tree] + t0 ++ types(); accept(RPAREN); - atPos (accept(ARROW)) { FunctionTypeTree(ts.toList, typ()) } + atPos (accept(ARROW)) { makeFunctionTypeTree(ts.toList, typ()) } } else { accept(RPAREN); t0 } @@ -530,7 +490,7 @@ abstract class Syntactic: ParserPhase { type1() } if (in.token == ARROW) atPos(in.skipToken()) { - FunctionTypeTree(List(t), typ()) } + makeFunctionTypeTree(List(t), typ()) } else t } @@ -687,8 +647,8 @@ abstract class Syntactic: ParserPhase { val enums = enumerators(); accept(RPAREN); if (in.token == YIELD) { - in.nextToken(); For(enums, expr(), true) - } else For(enums, expr(), false) + in.nextToken(); makeForYield(enums, expr()) + } else makeFor(enums, expr()) } } else if (in.token == RETURN) { atPos(in.skipToken()) { @@ -745,7 +705,7 @@ abstract class Syntactic: ParserPhase { var top = prefixExpr(); while (in.token == IDENTIFIER) { top = reduceStack( - true, base, top, precedence(in.name), isLeftAssoc(in.name)); + true, base, top, precedence(in.name), treeInfo.isLeftAssoc(in.name)); opstack = OpInfo(top, in.name, in.pos) :: opstack; ident(); if (isExprIntro) { @@ -783,7 +743,7 @@ abstract class Syntactic: ParserPhase { * | StableRef * | `(' [Expr] `)' * | BlockExpr - * | new Template + * | new SimpleType [`(' [Exprs] `)'] {`with' SimpleType} [TemplateBody] * | SimpleExpr `.' Id * | SimpleExpr TypeArgs * | SimpleExpr ArgumentExprs @@ -822,9 +782,19 @@ abstract class Syntactic: ParserPhase { t = blockExpr() case NEW => t = atPos(in.skipToken()) { - val templ = template(); - New(if (templ.parents.length == 1 && templ.body.isEmpty) templ.parents.head - else templ) + val parents = new ListBuffer[Tree] + simpleType(); + var args: List[Tree] = List(); + if (in.token == LPAREN) args = argumentExprs(); + while (in.token == WITH) { + in.nextToken(); + 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)) } case _ => syntaxError("illegal start of simple expression", true); @@ -896,7 +866,7 @@ abstract class Syntactic: ParserPhase { val guard = if (in.token == IF) { in.nextToken(); postfixExpr() } else EmptyTree; - CaseDef(pat, guard, atPos(accept(ARROW))(block())) + makeCaseDef(pat, guard, atPos(accept(ARROW))(block())) } /** Enumerators ::= Generator {`;' Enumerator} @@ -916,7 +886,7 @@ abstract class Syntactic: ParserPhase { */ def generator(): Tree = atPos(accept(VAL)) { - PatDef(0, pattern1(false), { accept(LARROW); expr() }) + makeGenerator(pattern1(false), { accept(LARROW); expr() }) } //////// PATTERNS //////////////////////////////////////////////////////////// @@ -960,9 +930,12 @@ abstract class Syntactic: ParserPhase { atPos(in.pos) { Sequence(List()) } } else { val p = pattern2(seqOK); - if (in.token == COLON && treeInfo.isVarPattern(p)) - atPos(in.skipToken()) { Typed(p, type1()) } - else p + p match { + case Ident(name) if (treeInfo.isVariableName(name) && in.token == COLON) => + atPos(in.skipToken()) { Typed(p, type1()) } + case _ => + p + } } /* Pattern2 ::= varid [ @ Pattern3 ] @@ -997,31 +970,16 @@ abstract class Syntactic: ParserPhase { val base = opstack; var top = simplePattern(seqOK); if (seqOK && in.token == IDENTIFIER) { - if (in.name == STAR) { /* p* becomes z@( |(p,z)) */ - return atPos(in.skipToken()) { - val zname = fresh(); - Bind( - zname, - makeAlternative(List( - Sequence(List()), makeSequence(List(top, Ident(zname)))))) - } - } else if (in.name == PLUS) { /* p+ becomes z@(p,(z| )) */ - return atPos(in.skipToken()) { - val zname = fresh(); - Bind( - zname, - makeSequence(List( - top, makeAlternative(List(Ident(zname), Sequence(List())))))) - } - } else if (in.name == OPT) { /* p? becomes (p| ) */ - return atPos(in.skipToken()) { - makeAlternative(List(top, Sequence(List()))) - } - } + if (in.name == STAR) + return atPos(in.skipToken())(makeStar(top)) + else if (in.name == PLUS) + return atPos(in.skipToken())(makePlus(top)) + else if (in.name == OPT) + return atPos(in.skipToken())(makeOpt(top)) } while (in.token == IDENTIFIER && in.name != BAR) { top = reduceStack( - false, base, top, precedence(in.name), isLeftAssoc(in.name)); + false, base, top, precedence(in.name), treeInfo.isLeftAssoc(in.name)); opstack = OpInfo(top, in.name, in.pos) :: opstack; ident(); top = simplePattern(seqOK) @@ -1182,7 +1140,7 @@ abstract class Syntactic: ParserPhase { */ def paramType(): Tree = if (in.token == ARROW) - atPos(in.skipToken()) { FunctionTypeTree(List(), typ()) } + atPos(in.skipToken()) { makeFunctionTypeTree(List(), typ()) } else { val t = typ(); if (in.token == IDENTIFIER && in.name == STAR) { @@ -1369,24 +1327,19 @@ abstract class Syntactic: ParserPhase { newmods = newmods | Flags.DEFERRED; EmptyTree } - for (val p <- lhs.toList) yield { - atPos(p.pos) { - p match { - case Ident(name) => - ValDef(mods, name, tp.duplicate, rhs.duplicate) - case _ => - if (rhs == EmptyTree) { - syntaxError(p.pos, "cannot defer pattern definition", false); - errorPatternTree - } else { - PatDef( - mods, - if (tp == EmptyTree) p else Typed(p, tp), - rhs.duplicate) - } + def mkDefs(p: Tree): List[Tree] = { + val trees = + makePatDef(newmods, if (tp == EmptyTree) p else Typed(p, tp), rhs.duplicate) + map atPos(p.pos); + if (rhs == EmptyTree) { + trees match { + case List(ValDef(_, _, _, EmptyTree)) => + case _ => syntaxError(p.pos, "pattern definition may not be abstract", false); } } + trees } + for (val p <- lhs.toList; val d <- mkDefs(p)) yield d } /** VarDef ::= Id {`,' Id} [`:' Type] `=' Expr @@ -1525,22 +1478,26 @@ abstract class Syntactic: ParserPhase { lhs += Tuple4(in.skipToken(), ident().toTypeName, typeParamClauseOpt(true), - paramClauses(true)) + if ((mods & Flags.TRAIT) != 0) List() else paramClauses(true)) } while (in.token == COMMA); val thistpe = simpleTypedOpt(); - val Template(parents, body) = classTemplate((mods & Flags.CASE) != 0); + val Template(parents, body) = classTemplate(mods); for (val Tuple4(pos, name, tparams, vparamss) <- lhs.toList) yield atPos(pos) { - 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; - ClassDef(mods, name, tparams, thistpe.duplicate, - Template(parents, vparams ::: constr :: body)) + 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)) } } @@ -1552,7 +1509,7 @@ abstract class Syntactic: ParserPhase { lhs += Pair(in.skipToken(), ident()); } while (in.token == COMMA); val thistpe = simpleTypedOpt(); - val template = classTemplate((mods & Flags.CASE)!= 0); + val template = classTemplate(mods); for (val Pair(pos, name) <- lhs.toList) yield atPos(pos) { ModuleDef(mods, name, thistpe.duplicate, @@ -1560,46 +1517,36 @@ abstract class Syntactic: ParserPhase { } } - /** ClassTemplate ::= [`extends' Constr] {`with' Constr} [TemplateBody] + /** ClassTemplate ::= [`extends' SimpleType [`(' [Exprs] `)']] {`with' SimpleType} [TemplateBody] */ - def classTemplate(isCaseClass:boolean): Template = { + def classTemplate(mods: int): Template = atPos(in.pos) { - val parents = new ListBuffer[Tree]; - if (in.token == EXTENDS) { + val parents = new ListBuffer[Tree]; + var args: List[Tree] = List(); + if (in.token == EXTENDS) { in.nextToken(); - parents += constr() - } else { - parents += scalaAnyRefConstr() - } - parents += scalaObjectConstr(); - if (isCaseClass) parents += caseClassConstr(); - if (in.token == WITH) { - in.nextToken(); - template(parents) - } else if (in.token == LBRACE) { - Template(parents.toList, templateBody()) - } else { - if (!(in.token == SEMI || in.token == COMMA || in.token == RBRACE)) - syntaxError("`extends' or `{' expected", true); - Template(parents.toList, List()) - } + parents += simpleType(); + if (in.token == LPAREN) args = argumentExprs(); + } + parents += scalaScalaObjectConstr; + if ((mods & Flags.CASE)!= 0) parents += caseClassConstr; + while (in.token == WITH) { + in.nextToken(); parents += simpleType(); + } + val ps = parents.toList; + var body = + if (in.token == LBRACE) { + templateBody() + } else { + if (!(in.token == SEMI || in.token == COMMA || in.token == RBRACE)) + syntaxError("`extends' or `{' expected", true); + List() + } + if ((mods & Flags.TRAIT) == 0) body = makeSuperCall(args) :: body; + Template(ps, body) } - } ////////// TEMPLATES //////////////////////////////////////////////////////////// - /** Template ::= Constr {`with' Constr} [TemplateBody] - */ - def template(): Template = template(new ListBuffer[Tree]); - - def template(parents: ListBuffer[Tree]): Template = { - parents += constr(); - while (in.token == WITH) { - in.nextToken(); - parents += constr() - } - val stats = if (in.token == LBRACE) templateBody() else List(); - Template(parents.toList, stats) - } /** Constr ::= StableId [TypeArgs] [`(' [Exprs] `)'] */ @@ -1617,7 +1564,7 @@ abstract class Syntactic: ParserPhase { def templateBody(): List[Tree] = { accept(LBRACE); var body = templateStatSeq(); - if (body.length == 0) body = List(EmptyTree); + if (body.isEmpty) body = List(EmptyTree); accept(RBRACE); body } @@ -1800,4 +1747,6 @@ abstract class Syntactic: ParserPhase { } } + + // LocalWords: SOcos diff --git a/sources/scala/tools/nsc/symtab/Definitions.scala b/sources/scala/tools/nsc/symtab/Definitions.scala index 11e4a10684..ea570ae388 100755 --- a/sources/scala/tools/nsc/symtab/Definitions.scala +++ b/sources/scala/tools/nsc/symtab/Definitions.scala @@ -63,6 +63,16 @@ abstract class Definitions: SymbolTable { def TupleClass(i: int): Symbol = getClass("scala.Tuple" + i); def FunctionClass(i: int): Symbol = getClass("scala.Function" + i); + def tupleType(elems: List[Type]) = { + val sym = TupleClass(elems.length); + typeRef(sym.info.prefix, sym, elems) + } + + def functionType(formals: List[Type], restpe: Type) = { + val sym = FunctionClass(formals.length); + typeRef(sym.info.prefix, sym, formals ::: List(restpe)) + } + // members of class scala.Any var Any_== : Symbol = _; var Any_!= : Symbol = _; @@ -95,8 +105,9 @@ abstract class Definitions: SymbolTable { i = j + 1; j = fullname.pos('.', i) } - val result = sym.info.nonPrivateMember(fullname.subName(i, j).toTypeName) - .suchThat(.hasFlag(MODULE)); + val result = + if (module) sym.info.nonPrivateMember(fullname.subName(i, j)).suchThat(.hasFlag(MODULE)); + else sym.info.nonPrivateMember(fullname.subName(i, j).toTypeName); if (result == NoSymbol) throw new FatalError((if (module) "object " else "class ") + fullname + " not found."); result @@ -175,7 +186,16 @@ abstract class Definitions: SymbolTable { MatchErrorModule = getModule("scala.MatchError"); NilModule = getModule("scala.Nil"); ConsClass = getClass("scala.$colon$colon"); - RepeatedParamClass = newClass(ScalaPackageClass, nme.REPEATED_PARAM_CLASS_NAME, List(SeqClass.tpe)); + RepeatedParamClass = newClass(ScalaPackageClass, nme.REPEATED_PARAM_CLASS_NAME, List()); + { val tparam = newTypeParam(RepeatedParamClass, 0); + RepeatedParamClass.setInfo( + PolyType( + List(tparam), + ClassInfoType( + List(typeRef(SeqClass.tpe.prefix, SeqClass, List(tparam.typeConstructor))), + new Scope(), + RepeatedParamClass))) + } // members of class scala.Any Any_== = newMethod(AnyClass, "==") diff --git a/sources/scala/tools/nsc/symtab/Names.scala b/sources/scala/tools/nsc/symtab/Names.scala index f381d46da8..190bacc12b 100755 --- a/sources/scala/tools/nsc/symtab/Names.scala +++ b/sources/scala/tools/nsc/symtab/Names.scala @@ -234,7 +234,9 @@ class Names { } /** Replace $op_name by corresponding operator symbol */ - def decode: String = NameTransformer.decode(toString()) + def decode: String = + NameTransformer.decode(toString()) + + (if (isTypeName) "!" else "");//debug } private class TermName(index: int, len: int, hash: int) extends Name(index, len) { diff --git a/sources/scala/tools/nsc/symtab/StdNames.scala b/sources/scala/tools/nsc/symtab/StdNames.scala index f9897eac9d..5cbd8d0169 100755 --- a/sources/scala/tools/nsc/symtab/StdNames.scala +++ b/sources/scala/tools/nsc/symtab/StdNames.scala @@ -113,7 +113,7 @@ abstract class StdNames: SymbolTable { val report = newTermName("report"); val false_ = newTermName("false"); val filter = newTermName("filter"); - val flatmap = newTermName("flatMap"); + val flatMap = newTermName("flatMap"); val foreach = newTermName("foreach"); val getClass_ = newTermName("getClass"); val hasAsInstance = newTermName("hasAsInstance"); diff --git a/sources/scala/tools/nsc/symtab/Symbols.scala b/sources/scala/tools/nsc/symtab/Symbols.scala index cc4cfbe72c..6f4f89f899 100755 --- a/sources/scala/tools/nsc/symtab/Symbols.scala +++ b/sources/scala/tools/nsc/symtab/Symbols.scala @@ -325,11 +325,23 @@ abstract class Symbols: SymbolTable { if (hasFlag(OVERLOADED)) info.asInstanceOf[OverloadedType].alternatives else List(this); - def suchThat(cond: Symbol => boolean): Symbol = - if (hasFlag(OVERLOADED)) uniqueSymbolIn(alternatives.elements, cond) - else if (cond(this)) this + def filter(cond: Symbol => boolean): Symbol = + if (hasFlag(OVERLOADED)) { + val alts = alternatives; + val alts1 = alts filter cond; + if (alts1 eq alts) this + else if (alts1.isEmpty) NoSymbol + else if (alts1.tail.isEmpty) alts1.head + else owner.newOverloaded(info.prefix, alts1) + } else if (cond(this)) this else NoSymbol; + def suchThat(cond: Symbol => boolean): Symbol = { + val result = filter(cond); + assert(!result.hasFlag(OVERLOADED)); + result + } + // Cloneing ------------------------------------------------------------------- /** A clone of this symbol */ @@ -538,7 +550,7 @@ abstract class Symbols: SymbolTable { /** String representation of symbol's definition */ final def defString: String = - compose(List(flagsToString(flags & SOURCEFLAGS), + compose(List(flagsToString(rawflags & SOURCEFLAGS), keyString, varianceString + nameString, infoString(rawInfo))); @@ -647,16 +659,4 @@ abstract class Symbols: SymbolTable { /** A class for type histories */ private class TypeHistory(val start: Phase, val info: Type, val prev: TypeHistory); - - - /** Return unique element in list of symbols satisfying condition, - * or NoSymbol if no element satisfies condition, - * pre: at most one element satisfies condition. - */ - def uniqueSymbolIn(syms: Iterator[Symbol], cond: Symbol => boolean): Symbol = - if (syms.hasNext) { - val sym = syms.next; - if (cond(sym)) { assert(!syms.exists(cond)); sym } - else uniqueSymbolIn(syms, cond) - } else NoSymbol; } diff --git a/sources/scala/tools/nsc/symtab/Types.scala b/sources/scala/tools/nsc/symtab/Types.scala index 7f8688f3bc..38b061a39e 100755 --- a/sources/scala/tools/nsc/symtab/Types.scala +++ b/sources/scala/tools/nsc/symtab/Types.scala @@ -8,6 +8,24 @@ package scala.tools.nsc.symtab; import scala.tools.util.Position; import Flags._; +/* A standard type pattern match: + case ErrorType => + case WildcardType => + case NoType => + case NoPrefix => + case ThisType(_) => + case SingleType(pre, sym) => + case ConstantType(base, value) => + case TypeRef(pre, sym, args) => + case TypeBounds(lo, hi) => + case RefinedType(parents, defs) => + case ClassInfoType(parents, defs, clazz) => + case MethodType(paramtypes, result) => + case PolyType(tparams, result) => + case OverloadedType(pre, tparams, alts) => + case TypeVar(_, _) => +*/ + abstract class Types: SymbolTable { import definitions._; @@ -32,10 +50,8 @@ abstract class Types: SymbolTable { /** Map to a this type which is a subtype of this type. */ - def narrow: Type = { - val reftpe = refinedType(List(this), commonOwner(this), EmptyScope); - ThisType(reftpe.symbol); - } + def narrow: Type = + refinedType(List(this), commonOwner(this), EmptyScope).narrow; /** Map a constant type to its underlying base type, * identity for all other types */ @@ -83,7 +99,7 @@ abstract class Types: SymbolTable { def typeParams: List[Symbol] = List(); /** Is this type produced as a repair for an error? */ - def isError: boolean = this == ErrorType || symbol.isError; + def isError: boolean = symbol.isError; /** Does this type denote a stable reference (i.e. singleton type)? */ def isStable: boolean = false; @@ -212,8 +228,8 @@ abstract class Types: SymbolTable { def baseClasses: List[Symbol] = List(); - /** The index of given class symbol in the closure of this type, -1 - * of no base type with gien class symbol exists */ + /** The index of given class symbol in the closure of this type, + * or -1 if no base type with given class symbol exists */ def closurePos(sym: Symbol): int = { val cl = closure; var lo = 0; @@ -249,13 +265,15 @@ abstract class Types: SymbolTable { * by `owner'. Identity for all other types. */ def cloneInfo(owner: Symbol) = this; - /** The representation of this type used as a prefix */ + /** The string representation of this type used as a prefix */ def prefixString = toString() + "."; - /** Get type of `this' symbol corresponding to this class typeref, extend - * homomorphically to results of function types and poly types. - * Identity for all other types. */ - def instanceType = this; + /** The string representation of this type, with singletypes explained */ + def toLongString = { + val str = toString(); + if (str.endsWith(".type")) str + " (with underlying type " + widen + ")"; + else str + } /** Is this type completed (i.e. not a lazy type)? */ @@ -267,7 +285,7 @@ abstract class Types: SymbolTable { private def findDecl(name: Name, excludedFlags: int): Symbol = { var alts: List[Symbol] = List(); var sym: Symbol = NoSymbol; - var e = decls.lookupEntry(name); + var e: ScopeEntry = decls.lookupEntry(name); while (e != null) { if ((e.sym.rawflags & excludedFlags) == 0) { if (sym == NoSymbol) sym = e.sym @@ -283,6 +301,7 @@ abstract class Types: SymbolTable { } protected def findMember(name: Name, excludedFlags: int): Symbol = { + //System.out.println("find member " + name.decode + " in " + this.baseClasses);//DEBUG var members: Scope = null; var member: Symbol = NoSymbol; var excluded = excludedFlags | DEFERRED; @@ -357,6 +376,7 @@ abstract class Types: SymbolTable { /** An object representing an erroneous type */ case object ErrorType extends Type { // todo see whether we can do without + override def isError: boolean = true; override def decls: Scope = new ErrorScope(NoSymbol); override def findMember(name: Name, excludedFlags: int): Symbol = decls lookup name; override def baseType(clazz: Symbol): Type = this; @@ -432,17 +452,19 @@ abstract class Types: SymbolTable { private var validBaseClasses: Phase = null; override def closure: Array[Type] = { - if (validClosure != phase) { - validClosure = phase; - closureCache = null; + def computeClosure: Array[Type] = try { - closureCache = addClosure(symbol.tpe, glbArray(parents map (.closure))); + addClosure(symbol.tpe, glbArray(parents map (.closure))); } catch { case ex: MalformedClosure => throw new MalformedType( "the type intersection " + this + " is malformed" + "\n --- because ---\n" + ex.getMessage()) } + if (validClosure != phase) { + validClosure = phase; + closureCache = null; + closureCache = computeClosure; } if (closureCache == null) throw new TypeError("illegal cyclic reference involving " + symbol); @@ -457,7 +479,7 @@ abstract class Types: SymbolTable { val mixins = parents.tail; def isNew(limit: List[Type])(clazz: Symbol): boolean = { var ms = mixins; - while (!(ms eq limit) && !(ms.head.symbol isSubClass clazz)) ms = ms.tail; + while (!(ms eq limit) && ms.head.closurePos(clazz) < 0) ms = ms.tail; ms eq limit } var ms = mixins; @@ -467,7 +489,6 @@ abstract class Types: SymbolTable { } symbol :: bcs } - if (validBaseClasses != phase) { validBaseClasses = phase; baseClassCache = null; @@ -509,8 +530,7 @@ abstract class Types: SymbolTable { class PackageClassInfoType(decls: Scope, clazz: Symbol) extends ClassInfoType(List(), decls, clazz); /** A class representing a constant type */ - case class ConstantType(base: Type, value: Any) - extends SingletonType { + case class ConstantType(base: Type, value: Any) extends SingletonType { override def symbol: Symbol = base.symbol; override def singleDeref: Type = base; override def deconst: Type = base; @@ -523,10 +543,10 @@ abstract class Types: SymbolTable { abstract case class TypeRef(pre: Type, sym: Symbol, args: List[Type]) extends Type { assert(!sym.isAbstractType || pre.isStable || pre.isError); - private def transform(tp: Type): Type = + def transform(tp: Type): Type = tp.asSeenFrom(pre, sym.owner).subst(sym.typeParams, args); - private def transform(cl: Array[Type]): Array[Type] = { + def transform(cl: Array[Type]): Array[Type] = { val cl1 = new Array[Type](cl.length); var i = 0; while (i < cl.length) { cl1(i) = transform(cl(i)); i = i + 1 } @@ -556,15 +576,11 @@ abstract class Types: SymbolTable { else pre.memberInfo(sym).baseType(clazz); override def closure: Array[Type] = - if (sym.isAbstractType) addClosure(this, bounds.hi.closure) + if (sym.isAbstractType) addClosure(this, transform(bounds.hi).closure) else transform(sym.info.closure); override def baseClasses: List[Symbol] = sym.info.baseClasses; - override def instanceType: Type = - if (sym.thisSym != sym) transform(sym.typeOfThis) - else this; - override def erasure: Type = if (sym.isAbstractType || sym.isAliasType) sym.info.erasure else if (sym == ObjectClass || @@ -587,11 +603,6 @@ abstract class Types: SymbolTable { override def paramSectionCount: int = resultType.paramSectionCount + 1; - override def instanceType: Type = { - val res = resultType.instanceType; - if (res eq resultType) this else MethodType(paramTypes, res) - } - override def erasure = { val pts = List.transform(paramTypes)(.erasure); val res = resultType.erasure; @@ -602,25 +613,22 @@ abstract class Types: SymbolTable { override def toString(): String = paramTypes.mkString("(", ",", ")") + resultType; } + class ImplicitMethodType(pts: List[Type], rt: Type) extends MethodType(pts, rt); + /** A class representing a polymorphic type or, if tparams.length == 0, * a parameterless method type. */ - case class PolyType(override val typeParams: List[Symbol], override val resultType: Type) extends Type { + case class PolyType(override val typeParams: List[Symbol], override val resultType: Type) + extends Type { override def paramSectionCount: int = resultType.paramSectionCount; override def paramTypes: List[Type] = resultType.paramTypes; - override def instanceType: Type = { - val res = resultType.instanceType; - if (res eq resultType) this else PolyType(typeParams, res) - } - override def erasure = resultType.erasure; override def toString(): String = - (if (typeParams.isEmpty) "=> " else typeParams.mkString("[", ",", "]")) - + resultType; + (if (typeParams.isEmpty) "=> " else typeParams.mkString("[", ",", "]")) + resultType; override def cloneInfo(owner: Symbol) = { val tparams = typeParams map (.cloneSymbol(owner)); @@ -642,7 +650,10 @@ abstract class Types: SymbolTable { /** A class containing the alternatives and type prefix of an overloaded symbol */ - case class OverloadedType(pre: Type, val alternatives: List[Symbol]) extends Type; + case class OverloadedType(pre: Type, alternatives: List[Symbol]) extends Type { + override def prefix: Type = pre; + override def toString() = (alternatives map pre.memberType).mkString("", " <and> ", "") + } /** A class representing an as-yet unevaluated type. */ @@ -718,8 +729,7 @@ abstract class Types: SymbolTable { /** A creator for type applications */ def appliedType(tycon: Type, args: List[Type]): Type = tycon match { case TypeRef(pre, sym, args1) => - if (args eq args1) tycon - else typeRef(pre, sym, args) + if (args eq args1) tycon else typeRef(pre, sym, args) case ErrorType => tycon } @@ -745,7 +755,7 @@ abstract class Types: SymbolTable { /** Map this function over given type */ def mapOver(tp: Type): Type = tp match { - case ErrorType | WildcardType | NoType | NoPrefix | TypeVar(_, _) | ThisType(_) => + case ErrorType | WildcardType | NoType | NoPrefix | ThisType(_) => tp case SingleType(pre, sym) => val pre1 = this(pre); @@ -787,9 +797,16 @@ abstract class Types: SymbolTable { else MethodType(paramtypes1, result1) case PolyType(tparams, result) => val tparams1 = mapOver(tparams); - val result1 = this(result); + var result1 = this(result); if ((tparams1 eq tparams) && (result1 eq result)) tp - else PolyType(tparams1, result1) + else PolyType(tparams1, result1.substSym(tparams, tparams1)) + case OverloadedType(pre, alts) => + val pre1 = this(pre); + if (pre1 eq pre) tp + else OverloadedType(pre1, alts) + case TypeVar(_, constr) => + if (constr.inst != NoType) this(constr.inst) + else tp case _ => throw new Error("mapOver inapplicable for " + tp); } diff --git a/sources/scala/tools/nsc/symtab/classfile/UnPickle.scala b/sources/scala/tools/nsc/symtab/classfile/UnPickle.scala index 0a5ca5511c..e46b876b2f 100755 --- a/sources/scala/tools/nsc/symtab/classfile/UnPickle.scala +++ b/sources/scala/tools/nsc/symtab/classfile/UnPickle.scala @@ -24,7 +24,7 @@ abstract class UnPickle { private var bytes: Array[byte] = _; private var bp: int = _; private var index: Array[int] = _; - private var entries: Array[Any] = _; + private var entries: Array[AnyRef] = _; def parse(bytes: Array[byte], clazz: Symbol, module: Symbol): unit = { warning("cannot yet unpickle: " + clazz.fullNameString('.')); diff --git a/sources/scala/tools/nsc/typechecker/Analyzer.scala b/sources/scala/tools/nsc/typechecker/Analyzer.scala index fe01281247..5457b01ec4 100644 --- a/sources/scala/tools/nsc/typechecker/Analyzer.scala +++ b/sources/scala/tools/nsc/typechecker/Analyzer.scala @@ -9,9 +9,14 @@ import scala.tools.util.Position; /** The main attribution phase. */ -abstract class Analyzer extends Contexts with Namers with Typers with TypeCheckers { +abstract class Analyzer + extends Contexts + with Namers + with Typers + with TypeCheckers + with Infer + with Variances { val global: Global; - import global._; case class ImportType(tree: Import) extends Type; diff --git a/sources/scala/tools/nsc/typechecker/Contexts.scala b/sources/scala/tools/nsc/typechecker/Contexts.scala index 78112ad604..804b5ae29d 100755 --- a/sources/scala/tools/nsc/typechecker/Contexts.scala +++ b/sources/scala/tools/nsc/typechecker/Contexts.scala @@ -18,7 +18,7 @@ class Contexts: Analyzer { def addImport(pkg: Symbol): unit = { sc = sc.make(sc.tree, sc.owner, new Scope(sc.scope)); val impTree = Import(gen.mkGlobalRef(pkg), List(Pair(nme.WILDCARD, null))); - impTree.setSymbol(NoSymbol.newImport(Position.NOPOS)).setType(ImportType(impTree)); + impTree.setSymbol(NoSymbol.newImport(Position.NOPOS)).setType(this.ImportType(impTree)); sc.scope.enter(impTree.symbol) } if (!settings.noimports.value) { @@ -32,14 +32,15 @@ class Contexts: Analyzer { class Context { var unit: CompilationUnit = _; - var tree: Tree = _; // Tree associated with this context - var owner: Symbol = _; // The current owner - var scope: Scope = _; // The current scope - var outer: Context = _; // The next outer context - var enclClass: Context = this; // The next outer context whose tree - // is a class template - var variance: int = _; // Variance relative to enclosing class. - var constructorClass: Symbol = _; // Class for auxiliary constructor + var tree: Tree = _; // Tree associated with this context + var owner: Symbol = _; // The current owner + var scope: Scope = _; // The current scope + var outer: Context = _; // The next outer context + var enclClass: Context = this; // The next outer context whose tree + // is a class template + var variance: int = _; // Variance relative to enclosing class. + var undetparams: List[Symbol] = List(); // Undetermined type parameters + var constructorClass: Symbol = _; // Class for auxiliary constructor var depth: int = 0; val imports: List[Tree] = List(); diff --git a/sources/scala/tools/nsc/typechecker/TypeCheckers.scala b/sources/scala/tools/nsc/typechecker/TypeCheckers.scala index 01f0e26f03..43bd18ea60 100755 --- a/sources/scala/tools/nsc/typechecker/TypeCheckers.scala +++ b/sources/scala/tools/nsc/typechecker/TypeCheckers.scala @@ -21,10 +21,10 @@ trait TypeCheckers: Analyzer { class TypeChecker(context: Context) extends Transformer { - import global._; import context.unit; - def error(pos: int, msg: String) = unit.error(pos, msg); + val infer = new Inferencer(context); + import infer._; def reportTypeError(pos: int, ex: TypeError): unit = { if (settings.debug.value) ex.printStackTrace(); @@ -43,6 +43,33 @@ trait TypeCheckers: Analyzer { } } + /** Mode constants + */ + val NOmode = 0x000; + val EXPRmode = 0x001; // these 3 modes are mutually exclusive. + val PATTERNmode = 0x002; + val TYPEmode = 0x004; + + val FUNmode = 0x10; // orthogonal to above. When set + // we are looking for a method or constructor + + val POLYmode = 0x020; // orthogonal to above. When set + // expression types can be polymorphic. + + val QUALmode = 0x040; // orthogonal to above. When set + // expressions may be packages and + // Java statics modules. + + val SUPERmode = 0x080; // Goes with CONSTRmode. When set + // we are checking a superclass + // constructor invocation. + + val baseModes: int = EXPRmode | PATTERNmode; + + 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 + def reenterValueParams(tree: Tree): unit = tree match { case DefDef(_, _, _, vparamss, _, _) => for (val vparams <- vparamss; val vparam <- vparams) context.scope enter vparam.symbol @@ -54,23 +81,24 @@ trait TypeCheckers: Analyzer { def transformConstr(tree: Tree): Tree = tree; def transformExpr(tree: Tree): Tree = tree; def transformType(tree: Tree): Tree = tree; - - abstract class ResolveError extends TermSymbol(NoSymbol, Position.NOPOS, nme.EMPTY) { - setFlag(IS_ERROR); - def msg(qual: Tree, name: Name): String; - } - - object NotFoundError extends ResolveError { - def msg(qual: Tree, name: Name) = name.decode + " is not a member of " + qual; - } - - object NotAccessibleError extends TermSymbol(NoSymbol, Position.NOPOS, nme.EMPTY) { - def msg(qual: Tree, name: Name) = name.decode + " is not accessible in " + qual; - } + def transformSuperType(tree: Tree): Tree = tree; def transform(tree: Tree, mode: int, pt: Type): Tree = { - def stabilize(tree: Tree, pre: Type): Tree = tree; + /** 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 + 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 + } /** Attribute an identifier consisting of a simple name or an outer reference. * @param tree The tree representing the identifier. @@ -166,81 +194,260 @@ trait TypeCheckers: Analyzer { qual = importTree(impSym).expr.duplicate; pre = qual.tpe; } else { - error(tree.pos, "not found: " + name.decode); + error(tree.pos, "not found: " + decode(name)); sym = context.owner.newErrorSymbol(name); } } - val symtype = pre.memberType(sym); - if (symtype == NoType) error(tree.pos, "not found: " + name.decode); - if (qual == EmptyTree) stabilize(tree.setSymbol(sym).setType(symtype), pre) - else transform(Select(qual, name) setPos tree.pos, mode, pt) + stabilize(checkAccessible(tree, sym, pre, qual), pre); } - tree//for now - } - } -} -/* - def resolveSymbol(pos: int, qual: Tree, name: Name): Symbol = { - def chekFeasible(sym: Symbol): Symbol = { - - - var best: Symbol = notFoundError; - var multiple = false; - var alts = pre.lookupAll(name); - while (alts.hasNext) { - val alt = checkFeasible(alts.next); - if (!improves(best, alt)) { - multiple = !best.isError; - best = alt; - } - } - if (multiple) { - alts = pre.lookupAll(name); - while (alts.hasNext) { - val alt = checkFeasible(alts.next); - if (!improves(best, alt)) { - error(pos, - "ambiguous reference to overloaded definition,\n" + - "both " + sym1 + ": " + pre.memberType(sym1) + "\n" + - "and " + sym2 + ": " + pre.memberTyoe(sym2) + "\nmatch" + - context.resolveContext); - } - } - } - best match { - case err: ResolveError => error(pos, err.msg); - case _ => best - } - } + 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)) + } /** Attribute a selection where `tree' is `qual.name'. * `qual' is already attributed. */ def transformSelect(tree: Tree, qual0: Tree, name: Name): Tree = { - val qual = qual0; - var uninst: List[Symbol] = List(); - qual.tpe match { + val qual = qual0.tpe match { case PolyType(tparams, restpe) => - qual = mkTypeApply(qual, tparams, restype, tparams map (.tpe)); - uninst = tparams; + assert(context.undetparams.isEmpty); + applyPoly(qual, tparams, restpe); case _ => + qual0 } - val sym = resolveSymbol(qual, name); + val sym = qual.tpe.member(name); // if (sym == NoSymbol) try to insert view. - if (!uninst.isEmpty) { - def polymorphize(tp: Type): Type = tp match { - case PolyType(tparams, restpe) => PolyType(tparams, polymorphize(restpe)) - case _ => PolyType(uninst, tp) + 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); + } + + /** 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])); } - symtype = polymorphize(symtype); } - //System.out.println(qual.getType() + ".member: " + sym + ":" + symtype);//DEBUG - val tree1: Tree = tree match { - case Select(_, _) => copy.Select(tree, sym, qua); - case SelectFromType(_, _) => copy.SelectFromType(tree, sym, qual) + 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 + } + } + + + +/* tree + } + } +} +*/ + + 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 _ => } - mkStable(tree1.setType(symtype), qualtype) } + 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 e14628ab90..4c2f785af5 100755 --- a/sources/scala/tools/nsc/typechecker/Typers.scala +++ b/sources/scala/tools/nsc/typechecker/Typers.scala @@ -34,13 +34,6 @@ trait Typers: Analyzer { sym.setInfo(typechecker.transformType(tree).tpe) } - private def constrType(constr: Tree): Type = constr match { - case Apply(fn, args) => - val ctp = constrType(fn); - if (ctp.typeParams.isEmpty) ctp else typechecker.transformConstr(constr).tpe - case _ => typechecker.transformType(constr).tpe - } - private def deconstIfNotFinal(sym: Symbol, tpe: Type): Type = if (sym.isVariable || !sym.hasFlag(FINAL)) tpe.deconst else tpe; @@ -71,7 +64,11 @@ trait Typers: Analyzer { private def templateSig(clazz: Symbol, templ: Template): Type = { // determine parent types - val parents = templ.parents map constrType; + 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"); @@ -102,7 +99,6 @@ trait Typers: Analyzer { typechecker.checkNoEscape(tpt.pos, deconstIfNotFinal(meth, if (meth.name == nme.CONSTRUCTOR) context.enclClass.owner.tpe - else if (tpt.tpe != null) tpt.tpe else if (tpt.isEmpty) { tpt.tpe = typechecker.transformExpr(rhs).tpe; tpt.tpe } else typechecker.transformType(tpt).tpe)); def mkMethodType(vparams: List[Symbol], restpe: Type) = @@ -135,8 +131,7 @@ trait Typers: Analyzer { case ValDef(_, _, tpt, rhs) => deconstIfNotFinal(sym, - if (tpt.tpe != null) tpt.tpe - else if (tpt.isEmpty) + if (tpt.isEmpty) if (rhs.isEmpty) { unit.error(tpt.pos, "missing parameter type"); ErrorType diff --git a/sources/scala/tools/scalac/typechecker/Analyzer.scala b/sources/scala/tools/scalac/typechecker/Analyzer.scala index 405a8e6fac..cb351151b4 100644 --- a/sources/scala/tools/scalac/typechecker/Analyzer.scala +++ b/sources/scala/tools/scalac/typechecker/Analyzer.scala @@ -160,7 +160,7 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer( val baseModes = EXPRmode | PATTERNmode | CONSTRmode; - val SEQUENCEmode = 0x1000; // orthogonal to above. When set + 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 |