summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2007-05-29 14:17:05 +0000
committerMartin Odersky <odersky@gmail.com>2007-05-29 14:17:05 +0000
commit8397c7b73c2930229eae509e089550b0c3020ce2 (patch)
tree2d5101381353b7b2448708459339230a2a28c445
parent6018a932ce3ffc259914ee442f5ea3983439e0f1 (diff)
downloadscala-8397c7b73c2930229eae509e089550b0c3020ce2.tar.gz
scala-8397c7b73c2930229eae509e089550b0c3020ce2.tar.bz2
scala-8397c7b73c2930229eae509e089550b0c3020ce2.zip
fixed bugs 1143, 1136, 1102
-rw-r--r--src/compiler/scala/tools/nsc/CompilerCommand.scala1
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala4
-rw-r--r--src/compiler/scala/tools/nsc/Settings.scala1
-rw-r--r--src/compiler/scala/tools/nsc/ast/NodePrinters.scala41
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala6
-rw-r--r--src/compiler/scala/tools/nsc/symtab/AnnotationInfos.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Flags.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/StdNames.scala1
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Symbols.scala1
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala22
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala96
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala6
-rw-r--r--src/library/scala/List.scala5
13 files changed, 138 insertions, 50 deletions
diff --git a/src/compiler/scala/tools/nsc/CompilerCommand.scala b/src/compiler/scala/tools/nsc/CompilerCommand.scala
index 89302b0749..d246e05959 100644
--- a/src/compiler/scala/tools/nsc/CompilerCommand.scala
+++ b/src/compiler/scala/tools/nsc/CompilerCommand.scala
@@ -24,6 +24,7 @@ class CompilerCommand(arguments: List[String], val settings: Settings,
/** A message explaining usage and options */
def usageMsg: String = {
+ // todo: print -X and -javadoc options only on demand
val helpSyntaxColumnWidth: int =
Iterable.max(settings.allSettings map (. helpSyntax.length()))
def format(s: String): String = {
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index 31e4f162a3..9d76ab531c 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -497,8 +497,10 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
phase = globalPhase
globalPhase.run
if (settings.print contains globalPhase.name)
- if (globalPhase.id >= icodePhase.id) writeICode()
+ if (globalPhase.id >= icodePhase.id) writeICode()
+ else if (settings.Xshowtrees.value) nodePrinters.printAll()
else treePrinter.printAll()
+
if (settings.browse contains globalPhase.name) treeBrowser.browse(units)
informTime(globalPhase.description, startTime)
globalPhase = globalPhase.next
diff --git a/src/compiler/scala/tools/nsc/Settings.scala b/src/compiler/scala/tools/nsc/Settings.scala
index 848fc8a8f1..626c41cfd9 100644
--- a/src/compiler/scala/tools/nsc/Settings.scala
+++ b/src/compiler/scala/tools/nsc/Settings.scala
@@ -125,6 +125,7 @@ class Settings(error: String => unit) {
val Xdetach = BooleanSetting("-Xdetach", "Perform detaching of remote closures")
val Xshowcls = StringSetting ("-Xshowcls", "class", "Show class info", "")
val Xshowobj = StringSetting ("-Xshowobj", "object", "Show object info", "")
+ val Xshowtrees = BooleanSetting ("-Xshowtrees", "Show detailed trees when used in connection with -print:phase")
val Xlinearizer = ChoiceSetting ("-Xlinearizer", "Linearizer to use", List("normal", "dfs", "rpo", "dump"), "rpo")
val Xgenerics = BooleanSetting("-Xgenerics", "Use generic Java types")
val Xprintpos = BooleanSetting("-Xprintpos", "Print tree positions (as offsets)")
diff --git a/src/compiler/scala/tools/nsc/ast/NodePrinters.scala b/src/compiler/scala/tools/nsc/ast/NodePrinters.scala
index 31cc368ec8..24fd0971cd 100644
--- a/src/compiler/scala/tools/nsc/ast/NodePrinters.scala
+++ b/src/compiler/scala/tools/nsc/ast/NodePrinters.scala
@@ -232,8 +232,34 @@ abstract class NodePrinters {
traverse(tpt, level + 1, true)
traverse(rhs, level + 1, false)
printcln(")")
+ case PackageDef(name, stats) =>
+ println("PackageDef("+name+", ")
+ for (stat <- stats)
+ traverse(stat, level + 1, false)
+ printcln(")")
case _ =>
- printcln("***" + tree.getClass)
+ tree match {
+ case p: Product =>
+ if (p.productArity != 0) {
+ println(p.productPrefix+"(")
+ for (elem <- (0 until p.productArity) map p.productElement) {
+ def printElem(elem: Any, level: int): unit = elem match {
+ case t: Tree =>
+ traverse(t, level, false)
+ case xs: List[_] =>
+ print("List(")
+ for (x <- xs) printElem(x, level+1)
+ printcln(")")
+ case _ =>
+ println(elem.toString)
+ }
+ printElem(elem, level+1)
+ }
+ printcln(")")
+ } else printcln(p.productPrefix)
+ case _ =>
+ printcln("***" + tree.getClass)
+ }
}
}
buf setLength 0
@@ -241,4 +267,17 @@ abstract class NodePrinters {
buf.toString
}
}
+ def printUnit(unit: CompilationUnit) {
+ print("// Scala source: " + unit.source + "\n")
+ if (unit.body ne null) {
+ print(nodeToString(unit.body)); println()
+ } else {
+ print("<null>")
+ }
+ println()
+ }
+ def printAll() {
+ print("[[syntax trees at end of " + phase + "]]")
+ for (unit <- global.currentRun.units) printUnit(unit)
+ }
}
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index c938abb4bf..66168724b0 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -2239,6 +2239,8 @@ trait Parsers {
* |
*/
def templateStatSeq() = {
+ val savedImplicitParams = implicitParams
+ implicitParams = List()
var self: ValDef = emptyValDef
val stats = new ListBuffer[Tree]
if (isExprIntro) {
@@ -2266,6 +2268,7 @@ trait Parsers {
if (inToken != RBRACE && inToken != EOF) acceptStatSep()
}
checkNoImplicitParams()
+ implicitParams = savedImplicitParams
(self, stats.toList)
}
@@ -2305,6 +2308,8 @@ trait Parsers {
if (inToken == RBRACE || inToken == CASE)
stats += Literal(()).setPos(inCurrentPos)
}
+ val savedImplicitParams = implicitParams
+ implicitParams = List()
var last = false
while ((inToken != RBRACE) && (inToken != EOF) && (inToken != CASE) && !last) {
if (inToken == IMPORT) {
@@ -2324,6 +2329,7 @@ trait Parsers {
}
}
checkNoImplicitParams()
+ implicitParams = savedImplicitParams
stats.toList
}
diff --git a/src/compiler/scala/tools/nsc/symtab/AnnotationInfos.scala b/src/compiler/scala/tools/nsc/symtab/AnnotationInfos.scala
index 8b36ad819f..e1d72105ca 100644
--- a/src/compiler/scala/tools/nsc/symtab/AnnotationInfos.scala
+++ b/src/compiler/scala/tools/nsc/symtab/AnnotationInfos.scala
@@ -41,7 +41,7 @@ trait AnnotationInfos {
None
}
- private object symbolReifier extends SymbolReifier {
+ private val symbolReifier = new SymbolReifier {
val symbols: AnnotationInfos.this.type = AnnotationInfos.this
}
diff --git a/src/compiler/scala/tools/nsc/symtab/Flags.scala b/src/compiler/scala/tools/nsc/symtab/Flags.scala
index 4c5f227a21..83b538ee9d 100644
--- a/src/compiler/scala/tools/nsc/symtab/Flags.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Flags.scala
@@ -65,7 +65,7 @@ object Flags extends Enumeration {
final val LIFTED = 0x400000000L // class has been lifted out to package level
// local value has been lifted out to class level
// todo: make LIFTED = latePRIVATE?
- final val MIXEDIN = 0x800000000L // member has been mixed in
+ final val MIXEDIN = 0x800000000L // term member has been mixed in
final val EXPANDEDNAME = 0x1000000000L // name has been expanded with class suffix
final val IMPLCLASS = 0x2000000000L // symbol is an implementation class
diff --git a/src/compiler/scala/tools/nsc/symtab/StdNames.scala b/src/compiler/scala/tools/nsc/symtab/StdNames.scala
index fd1893054c..d6efdb32cb 100644
--- a/src/compiler/scala/tools/nsc/symtab/StdNames.scala
+++ b/src/compiler/scala/tools/nsc/symtab/StdNames.scala
@@ -302,6 +302,7 @@ trait StdNames {
val receive = newTermName("receive")
val report = newTermName("report")
val runtime = newTermName("runtime")
+ val sameElements = newTermName("sameElements")
val scala_ = newTermName("scala")
val send = newTermName("send")
val synchronized_ = newTermName("synchronized")
diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
index c1d2d222ea..81ba6b5b9e 100644
--- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
@@ -677,7 +677,6 @@ trait Symbols {
def thisType: Type = NoPrefix
/** Return every accessor of a primary constructor parameter in this case class
- * todo: limit to accessors for first constructor parameter section.
*/
final def caseFieldAccessors: List[Symbol] =
info.decls.toList filter (sym => !(sym hasFlag PRIVATE) && sym.hasFlag(CASEACCESSOR))
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index ac009e4c3e..80ba2c1df1 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -630,18 +630,19 @@ trait Infer {
false
}
- /** Is type `tpe1' a strictly better alternative than type `ftpe2'?
- *
- * @param tpe1 ...
- * @param tpe2 ...
- * @return ...
+ /** Is type `tpe1' a strictly better expression alternative than type `tpe2'?
*/
- def isStrictlyBetter(tpe1: Type, tpe2: Type) = {
+ def isStrictlyBetterExpr(tpe1: Type, tpe2: Type) = {
def isNullary(tpe: Type) = tpe.paramSectionCount == 0 || tpe.paramTypes.isEmpty
isNullary(tpe1) && !isNullary(tpe2) ||
- specializes(tpe1, tpe2) && !specializes(tpe2, tpe1)
+ isStrictlyBetter(tpe1, tpe2)
}
+ /** Is type `tpe1' a strictly better alternative than type `tpe2'?
+ */
+ def isStrictlyBetter(tpe1: Type, tpe2: Type) =
+ specializes(tpe1, tpe2) && !specializes(tpe2, tpe1)
+
/** error if arguments not within bounds. */
def checkBounds(pos: Position, pre: Type, owner: Symbol,
tparams: List[Symbol], targs: List[Type], prefix: String) = {
@@ -1132,7 +1133,7 @@ trait Infer {
val tp2 = pre.memberType(sym2)
(tp2 == ErrorType ||
!global.typer.infer.isCompatible(tp2, pt) && global.typer.infer.isCompatible(tp1, pt) ||
- isStrictlyBetter(tp1, tp2)) }
+ isStrictlyBetterExpr(tp1, tp2)) }
val best = ((NoSymbol: Symbol) /: alts1) ((best, alt) =>
if (improves(alt, best)) alt else best)
val competing = alts1 dropWhile (alt => best == alt || improves(best, alt))
@@ -1176,10 +1177,9 @@ trait Infer {
tryTwice {
if (settings.debug.value) log("infer method alt " + tree.symbol + " with alternatives " + (alts map pre.memberType) + ", argtpes = " + argtpes + ", pt = " + pt)
val applicable = alts filter (alt => isApplicable(undetparams, pre.memberType(alt), argtpes, pt))
- def improves(sym1: Symbol, sym2: Symbol) = (
+ def improves(sym1: Symbol, sym2: Symbol) =
sym2 == NoSymbol || sym2.isError ||
- specializes(pre.memberType(sym1), pre.memberType(sym2))
- )
+ isStrictlyBetter(pre.memberType(sym1), pre.memberType(sym2))
val best = ((NoSymbol: Symbol) /: applicable) ((best, alt) =>
if (improves(alt, best)) alt else best)
val competing = applicable dropWhile (alt => best == alt || improves(best, alt))
diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
index 1872642459..d91426867d 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
@@ -37,7 +37,9 @@ trait SyntheticMethods requires Analyzer {
* @param unit ...
* @return ...
*/
- def addSyntheticMethods(templ: Template, clazz: Symbol, unit: CompilationUnit): Template = {
+ def addSyntheticMethods(templ: Template, clazz: Symbol, context: Context): Template = {
+
+ val localTyper = newTyper(context)
def hasImplementation(name: Name): boolean = {
val sym = clazz.info.nonPrivateMember(name)
@@ -111,32 +113,66 @@ trait SyntheticMethods requires Analyzer {
Apply(gen.mkAttributedRef(target), This(clazz) :: (vparamss.head map Ident))))
}
+ /** The equality method for case classes and modules:
+ * def equals(that: Any) =
+ * (this eq that) ||
+ * (that match {
+ * case this.C(this.arg_1, ..., this.arg_n) => true
+ * case _ => false
+ * })
+ */
def equalsMethod: Tree = {
- val constrParamTypes = clazz.primaryConstructor.tpe.paramTypes
- val hasVarArgs = !constrParamTypes.isEmpty && constrParamTypes.last.symbol == RepeatedParamClass
- val target = getMember(ScalaRunTimeModule, if (hasVarArgs) nme._equalsWithVarArgs else nme._equals)
- val paramtypes =
- if (target.tpe.paramTypes.isEmpty) List()
- else target.tpe.paramTypes.tail
val method = syntheticMethod(
- nme.equals_, 0, MethodType(paramtypes, target.tpe.resultType))
- typed(DefDef(method, vparamss =>
- Apply(
- Select(
- Apply(
- Select(Ident(vparamss.head.head), Object_eq),
- List(This(clazz))),
- Boolean_or),
- List(
- Apply(
- Select(
- TypeApply(
- Select(Ident(vparamss.head.head), Any_isInstanceOf),
- List(TypeTree(clazz.tpe))),
- Boolean_and),
- List(
- Apply(gen.mkAttributedRef(target),
- This(clazz) :: (vparamss.head map Ident))))))));
+ nme.equals_, 0, MethodType(List(AnyClass.tpe), BooleanClass.tpe))
+ localTyper.typed {
+ DefDef(
+ method,
+ { vparamss =>
+ val that = Ident(vparamss.head.head)
+ val constrParamTypes = clazz.primaryConstructor.tpe.paramTypes
+ val hasVarArgs = !constrParamTypes.isEmpty && constrParamTypes.last.symbol == RepeatedParamClass
+ if (clazz.isStatic) {
+ val target = getMember(ScalaRunTimeModule, if (hasVarArgs) nme._equalsWithVarArgs else nme._equals)
+ Apply(
+ Select(
+ TypeApply(
+ Select(that, Any_isInstanceOf),
+ List(TypeTree(clazz.tpe))),
+ Boolean_and),
+ List(
+ Apply(gen.mkAttributedRef(target),
+ This(clazz) :: (vparamss.head map Ident))))
+ } else {
+ val (pat, guard) = {
+ val guards = new ListBuffer[Tree]
+ val params = for ((acc, cpt) <- clazz.caseFieldAccessors zip constrParamTypes) yield {
+ val name = context.unit.fresh.newName(acc.name+"$")
+ val isVarArg = cpt.symbol == RepeatedParamClass
+ guards += Apply(
+ Select(
+ Ident(name),
+ if (isVarArg) nme.sameElements else nme.equals_),
+ List(Ident(acc)))
+ Bind(name,
+ if (isVarArg) Star(Ident(nme.WILDCARD))
+ else Ident(nme.WILDCARD))
+ }
+ ( Apply(Ident(clazz.name.toTermName), params),
+ if (guards.isEmpty) EmptyTree
+ else guards reduceLeft { (g1: Tree, g2: Tree) =>
+ Apply(Select(g1, nme.AMPAMP), List(g2))
+ }
+ )
+ }
+ Match(
+ that,
+ List(
+ CaseDef(pat, guard, Literal(Constant(true))),
+ CaseDef(Ident(nme.WILDCARD), EmptyTree, Literal(Constant(false)))))
+ }
+ }
+ )
+ }
}
def isSerializable(clazz: Symbol): Boolean =
@@ -153,8 +189,8 @@ trait SyntheticMethods requires Analyzer {
def newAccessorMethod(tree: Tree): Tree = tree match {
case DefDef(_, _, _, _, _, rhs) =>
val newAcc = tree.symbol.cloneSymbol
- newAcc.name = unit.fresh.newName("" + tree.symbol.name + "$")
- newAcc.setFlag(SYNTHETIC).resetFlag(ACCESSOR | PARAMACCESSOR)
+ newAcc.name = context.unit.fresh.newName(tree.symbol.name + "$")
+ newAcc.setFlag(SYNTHETIC).resetFlag(ACCESSOR | PARAMACCESSOR | PRIVATE)
newAcc.owner.info.decls enter newAcc
val result = typed(DefDef(newAcc, vparamss => rhs.duplicate))
log("new accessor method " + result)
@@ -163,7 +199,7 @@ trait SyntheticMethods requires Analyzer {
def beanSetterOrGetter(sym: Symbol): Symbol =
if (!sym.name(0).isLetter) {
- unit.error(sym.pos, "attribute `BeanProperty' can be applied only to fields that start with a letter")
+ context.unit.error(sym.pos, "attribute `BeanProperty' can be applied only to fields that start with a letter")
NoSymbol
} else {
var name0 = sym.name
@@ -174,7 +210,7 @@ trait SyntheticMethods requires Analyzer {
val name1 = prefix + name0(0).toUpperCase + name0.subName(1, name0.length)
val sym1 = clazz.info.decl(name1)
if (sym1 != NoSymbol && sym1.tpe.paramTypes.length == arity) {
- unit.error(sym.pos, "a definition of `"+name1+"' already exists in " + clazz)
+ context.unit.error(sym.pos, "a definition of `"+name1+"' already exists in " + clazz)
NoSymbol
} else {
clazz.newMethod(sym.pos, name1)
@@ -251,7 +287,7 @@ trait SyntheticMethods requires Analyzer {
else if (sym.isSetter)
addBeanSetterMethod(sym)
else if (sym.isMethod || sym.isType)
- unit.error(sym.pos, "attribute `BeanProperty' is not applicable to " + sym)
+ context.unit.error(sym.pos, "attribute `BeanProperty' is not applicable to " + sym)
}
val synthetics = ts.toList
copy.Template(
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 30f693155d..7b6d84acb8 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -939,7 +939,7 @@ trait Typers requires Analyzer {
val tparams1 = List.mapConserve(cdef.tparams)(typedAbsTypeDef)
val impl1 = newTyper(context.make(cdef.impl, clazz, newTemplateScope(cdef.impl, clazz)))
.typedTemplate(cdef.impl, parentTypes(cdef.impl))
- val impl2 = addSyntheticMethods(impl1, clazz, context.unit)
+ val impl2 = addSyntheticMethods(impl1, clazz, context)
copy.ClassDef(cdef, cdef.mods, cdef.name, tparams1, impl2)
.setType(NoType)
}
@@ -954,7 +954,7 @@ trait Typers requires Analyzer {
val clazz = mdef.symbol.moduleClass
val impl1 = newTyper(context.make(mdef.impl, clazz, newTemplateScope(mdef.impl, clazz)))
.typedTemplate(mdef.impl, parentTypes(mdef.impl))
- val impl2 = addSyntheticMethods(impl1, clazz, context.unit)
+ val impl2 = addSyntheticMethods(impl1, clazz, context)
copy.ModuleDef(mdef, mdef.mods, mdef.name, impl2) setType NoType
}
@@ -2854,7 +2854,7 @@ trait Typers requires Analyzer {
def improves(info1: ImplicitInfo, info2: ImplicitInfo) =
(info2 == NoImplicitInfo) ||
(info1 != NoImplicitInfo) &&
- isStrictlyBetter(info1.tpe, info2.tpe)
+ isStrictlyBetterExpr(info1.tpe, info2.tpe)
val shadowed = new HashSet[Name](8)
def isApplicable(info: ImplicitInfo): boolean =
!containsError(info.tpe) &&
diff --git a/src/library/scala/List.scala b/src/library/scala/List.scala
index 2fc06ecb62..18be4e308b 100644
--- a/src/library/scala/List.scala
+++ b/src/library/scala/List.scala
@@ -309,7 +309,7 @@ object List {
* for all corresponding elements of the argument lists.
*
* @param p function to apply to each pair of elements.
- * @return <code>n == 0 || (p(a<sub>0</sub>,b<sub>0</sub>) &amp;&amp;
+ * @return <code>(p(a<sub>0</sub>,b<sub>0</sub>) &amp;&amp;
* ... &amp;&amp; p(a<sub>n</sub>,b<sub>n</sub>))]</code>
* if the lists are <code>[a<sub>0</sub>, ..., a<sub>k</sub>]</code>;
* <code>[b<sub>0</sub>, ..., b<sub>l</sub>]</code>
@@ -740,6 +740,9 @@ sealed abstract class List[+A] extends Seq[A] {
}
}
+// final def filterMap[B](f: PartialFunction[A, B]): List[B] =
+// this filter f.isDefinedAt map f
+
/** Removes all elements of the list which satisfy the predicate
* <code>p</code>. This is like <code>filter</code> with the
* predicate inversed.