summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2007-10-26 17:26:45 +0000
committerMartin Odersky <odersky@gmail.com>2007-10-26 17:26:45 +0000
commite97eb8f50e2ae30c3a651b7f975282659a57e817 (patch)
tree5835476f458a667bc24576b1e550ec6f760f00ef /src
parent74c60ffa67853c170e4f23e500c0380a2118c8b4 (diff)
downloadscala-e97eb8f50e2ae30c3a651b7f975282659a57e817.tar.gz
scala-e97eb8f50e2ae30c3a651b7f975282659a57e817.tar.bz2
scala-e97eb8f50e2ae30c3a651b7f975282659a57e817.zip
fixed tickets 152, 123.
spreadsheet demo crash. Made Lists more tail recursive. toString in Sets and Maps now says just Set(...) or Map(...) without revealing the implementation.
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala4
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala20
-rw-r--r--src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala36
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala3
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala51
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala18
-rw-r--r--src/library/scala/List.scala34
-rw-r--r--src/library/scala/Responder.scala2
-rw-r--r--src/library/scala/collection/Map.scala4
-rw-r--r--src/library/scala/collection/Set.scala4
-rw-r--r--src/library/scala/util/parsing/combinator1/lexical/StdLexical.scala8
11 files changed, 108 insertions, 76 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
index c969dc2f52..53d02d4569 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
@@ -161,7 +161,9 @@ abstract class Pickler extends SubComponent {
case TypeBounds(lo, hi) =>
putType(lo); putType(hi)
case RefinedType(parents, decls) =>
- putSymbol(tp.typeSymbol); putTypes(parents); putSymbols(decls.toList)
+ val rclazz = tp.typeSymbol
+ assert(decls.elements forall (_.owner == rclazz))
+ putSymbol(rclazz); putTypes(parents); putSymbols(decls.toList)
case ClassInfoType(parents, decls, clazz) =>
putSymbol(clazz); putTypes(parents); putSymbols(decls.toList)
case MethodType(formals, restpe) =>
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala
index c8fbe40009..ce4c99ec25 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala
@@ -25,9 +25,13 @@ abstract class UnPickler {
val global: Global
import global._
- /**
- * @param bytes bytearray from which we unpickle
- * @param filename filename associated with bytearray, only used for error messages
+ /** Unpickle symbol table information descending from a class and/or module root
+ * from an array of bytes.
+ * @param bytes bytearray from which we unpickle
+ * @param offset offset from which unpickling starts
+ * @param classroot the top-level class which is unpickled, or NoSymbol if unapplicable
+ * @param moduleroot the top-level module which is unpickled, or NoSymbol if unapplicable
+ * @param filename filename associated with bytearray, only used for error messages
*/
def unpickle(bytes: Array[Byte], offset: Int, classRoot: Symbol, moduleRoot: Symbol, filename: String) {
try {
@@ -44,8 +48,14 @@ abstract class UnPickler {
private class UnPickle(bytes: Array[Byte], offset: Int, classRoot: Symbol, moduleRoot: Symbol) extends PickleBuffer(bytes, offset, -1) {
if (settings.debug.value) global.log("unpickle " + classRoot + " and " + moduleRoot)
checkVersion()
+
+ /** A map from entry numbers to array offsets */
private val index = createIndex
+
+ /** A map from entry numbers to symbols, types, or annotations */
private val entries = new Array[AnyRef](index.length)
+
+ /** A map from symbols to their associated `decls' scopes */
private val symScopes = new HashMap[Symbol, Scope]
for (i <- 0 until index.length) {
@@ -55,7 +65,7 @@ abstract class UnPickler {
if (settings.debug.value) global.log("unpickled " + classRoot + ":" + classRoot.rawInfo + ", " + moduleRoot + ":" + moduleRoot.rawInfo);//debug
- private def checkVersion() = {
+ private def checkVersion() {
val major = readNat()
val minor = readNat()
if (major != MajorVersion || minor > MinorVersion)
@@ -65,7 +75,7 @@ abstract class UnPickler {
"\n found: " + major + "." + minor)
}
- /** The scope associated with given symbol */
+ /** The `decls' scope associated with given symbol */
private def symScope(sym: Symbol)(f : => Scope) = symScopes.get(sym) match {
case None => val s = f; symScopes(sym) = s; s
case Some(s) => s
diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
index cd48899c17..55c8023ed3 100644
--- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
+++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
@@ -415,23 +415,24 @@ abstract class ExplicitOuter extends InfoTransform with TransMatcher with Patter
//assert(nselector.tpe =:= selector.tpe)
//val ncases = transformCaseDefs(cases)
- def makeGuardDef(vs:SymList, guard:Tree) = {
- import symtab.Flags._
- val gdname = cunit.fresh.newName("gd")
- val fmls = new ListBuffer[Type]
- val method = currentOwner.newMethod(mch.pos, gdname) setFlag (SYNTHETIC)
- var vs1 = vs; while (vs1 ne Nil) {
- fmls += vs1.head.tpe
- vs1 = vs1.tail
+ def makeGuardDef(vs:SymList, guard:Tree) = {
+ import symtab.Flags._
+ val gdname = cunit.fresh.newName("gd")
+ val fmls = new ListBuffer[Type]
+ val method = currentOwner.newMethod(mch.pos, gdname) setFlag (SYNTHETIC)
+ var vs1 = vs; while (vs1 ne Nil) {
+ fmls += vs1.head.tpe
+ vs1 = vs1.tail
+ }
+ val tpe = new MethodType(fmls.toList, definitions.BooleanClass.tpe)
+ method setInfo tpe
+ localTyper.
+ typed {
+ DefDef(method,
+ {vparamss =>
+ new ChangeOwnerTraverser(currentOwner, method).traverse(guard);
+ new TreeSymSubstituter(vs, vparamss.head).traverse(guard);guard})}
}
- val tpe = new MethodType(fmls.toList, definitions.BooleanClass.tpe)
- method setInfo tpe
- localTyper.
- typed { DefDef(method,
- {vparamss =>
- new ChangeOwnerTraverser(currentOwner, method).traverse(guard);
- new TreeSymSubstituter(vs, vparamss.head).traverse(guard);guard})}
- }
val nguard = new ListBuffer[Tree]
val ncases = new ListBuffer[CaseDef]
@@ -468,10 +469,13 @@ abstract class ExplicitOuter extends InfoTransform with TransMatcher with Patter
//Console.println("TransMatcher selector.tpe ="+selector.tpe+")")
//Console.println("TransMatcher resultType ="+resultType+")")
+ //println("handle pattern = "+nselector+"/"+ncases.toList+"/"+currentOwner+"/"+tree.tpe)
val t_untyped = handlePattern(nselector, ncases.toList, checkExhaustive, currentOwner, transform)
+ //println("t_untyped = "+t_untyped)
try {
//Console.println("t_untyped "+t_untyped.toString())
val t = atPos(tree.pos) { localTyper.typed(t_untyped, resultType) }
+ //println("t_typed = "+t)
//t = transform(t)
//val t = atPos(tree.pos) { typed(t_untyped, resultType) }
diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
index 5427debfd0..4133a914b0 100644
--- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala
+++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
@@ -46,7 +46,7 @@ abstract class UnCurry extends InfoTransform with TypingTransformers {
//@MAT: uncurry and uncurryType fully expand type aliases in their input and output
// note: don't normalize higher-kined types -- @M TODO: maybe split those uses of normalize?
// OTOH, should be a problem as calls to normalize only occur on types with kind * in principle (in well-typed programs)
- private def expandAlias(tp: Type): Type = if(!tp.isHigherKinded) tp.normalize else tp
+ private def expandAlias(tp: Type): Type = if (!tp.isHigherKinded) tp.normalize else tp
private val uncurry: TypeMap = new TypeMap {
def apply(tp0: Type): Type = {val tp=expandAlias(tp0); tp match {
@@ -310,6 +310,7 @@ abstract class UnCurry extends InfoTransform with TypingTransformers {
Typed(
New(TypeTree(anonClass.tpe), List(List())),
TypeTree(fun.tpe)))
+
}
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index 695cb60f5e..df34651883 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -316,41 +316,38 @@ abstract class RefChecks extends InfoTransform {
val seenTypes = new Array[Type](clazz.info.closure.length)
var seenCaseClass = if (clazz hasFlag CASE) clazz else NoSymbol
- def validateTypes(tps: List[Type], includeSuper: Boolean) {
- if (!tps.isEmpty) {
- for (val tp <- tps.tail.reverse) validateType(tp, false);
- if (includeSuper) validateType(tps.head, true);
- }
- }
-
- def validateType(tp: Type, includeSuper: Boolean) {
+ /** validate all base types of a class in reverse linear order. */
+ def validateType(tp: Type) {
val baseClass = tp.typeSymbol
if (baseClass.isClass) {
val index = clazz.info.closurePos(baseClass)
if (index >= 0) {
- if ((seenTypes(index) ne null) && !(seenTypes(index) <:< tp))
- unit.error(clazz.pos, "illegal inheritance;\n " + clazz +
- " inherits different type instances of " + baseClass +
- ":\n" + tp + " and " + seenTypes(index));
- seenTypes(index) = tp;
- // check that case classes do not inherit from case classes
- if (baseClass hasFlag CASE) {
- if (seenCaseClass != NoSymbol && seenCaseClass != baseClass)
- unit.error(clazz.pos, "implementation restriction: case " +
- seenCaseClass + " and case " + baseClass +
- " cannot be combined in one object");
- seenCaseClass = baseClass
+ if (seenTypes(index) ne null) {
+ if (!(seenTypes(index) <:< tp)) {
+ unit.error(clazz.pos, "illegal inheritance;\n " + clazz +
+ " inherits different type instances of " + baseClass +
+ ":\n" + tp + " and " + seenTypes(index));
+ }
+ } else {
+ seenTypes(index) = tp
+ // check that case classes do not inherit from case classes
+ if (baseClass hasFlag CASE) {
+ if (seenCaseClass != NoSymbol && seenCaseClass != baseClass)
+ unit.error(clazz.pos, "implementation restriction: case " +
+ seenCaseClass + " and case " + baseClass +
+ " cannot be combined in one object");
+ seenCaseClass = baseClass
+ }
+ // check that inner classes do not inherit from Annotation
+ if (baseClass == ClassfileAnnotationClass)
+ if (!clazz.owner.isPackageClass)
+ unit.error(clazz.pos, "inner classes cannot be classfile annotations")
}
- // check that inner classes do not inherit from Annotation
- if (baseClass == ClassfileAnnotationClass)
- if (!clazz.owner.isPackageClass)
- unit.error(clazz.pos, "inner classes cannot be classfile annotations")
+ tp.parents foreach validateType
}
- validateTypes(tp.parents, includeSuper)
}
}
-
- validateTypes(clazz.info.parents, true)
+ validateType(clazz.tpe)
}
// Variance Checking --------------------------------------------------------
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 9737cc906b..ecba9bb44f 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -1336,7 +1336,7 @@ trait Typers { self: Analyzer =>
val thistp = tp.typeSymbol.thisType
for (sym <- clazz.info.decls.toList) {
if (sym.isPublic && !sym.isClass && !sym.isConstructor)
- addMember(thistp, tp, sym)
+ addMember(thistp, tp, sym.cloneSymbol(tp.typeSymbol).setInfo(sym.info))
}
tp
}
@@ -2801,19 +2801,9 @@ trait Typers { self: Analyzer =>
case UnApply(fun, args) =>
val fun1 = typed(fun)
- var tpes = fun.symbol.name match {
- case nme.unapply => unapplyTypeListFromReturnType (fun.tpe)
- case nme.unapplySeq => unapplyTypeListFromReturnTypeSeq(fun.tpe)
- }
- var as = args; while(as ne Nil) { // bq: typing a pattern never changes the tree
- typedPattern(as.head, tpes.head match {
- case TypeRef(_,sym,targs) if sym eq definitions.RepeatedParamClass => targs.head
- case tpe => tpe
- })
- as = as.tail; tpes = tpes.tail
- }
- //val args1 = List.mapConserve(args)(typedPattern(_, WildcardType))
- copy.UnApply(tree, fun1, args) setType pt
+ val tpes = formalTypes(unapplyTypeList(fun.symbol, fun1.tpe), args.length)
+ val args1 = List.map2(args, tpes)(typedPattern(_, _))
+ copy.UnApply(tree, fun1, args1) setType pt
case ArrayValue(elemtpt, elems) =>
typedArrayValue(elemtpt, elems)
diff --git a/src/library/scala/List.scala b/src/library/scala/List.scala
index 38028b7385..537f649a8a 100644
--- a/src/library/scala/List.scala
+++ b/src/library/scala/List.scala
@@ -456,9 +456,14 @@ sealed abstract class List[+A] extends Seq[A] {
* @param prefix the prefix to reverse and then prepend
* @return the concatenation of the reversed prefix and the current list.
*/
- def reverse_:::[B >: A](prefix: List[B]): List[B] = prefix match {
- case Nil => this
- case head :: tail => (head :: this).reverse_:::(tail)
+ def reverse_:::[B >: A](prefix: List[B]): List[B] = {
+ var these: List[B] = this
+ var pres = prefix
+ while (!pres.isEmpty) {
+ these = pres.head :: these
+ pres = pres.tail
+ }
+ these
}
/** Returns the number of elements in the list.
@@ -540,8 +545,15 @@ sealed abstract class List[+A] extends Seq[A] {
*/
override def last: A =
if (isEmpty) throw new Predef.NoSuchElementException("Nil.last")
- else if (tail.isEmpty) head
- else tail.last
+ else {
+ var cur = this
+ var next = this.tail
+ while (!next.isEmpty) {
+ cur = next
+ next = next.tail
+ }
+ cur.head
+ }
/** Returns the <code>n</code> first elements of this list, or else the whole
* list, if it has less than <code>n</code> elements.
@@ -580,9 +592,15 @@ sealed abstract class List[+A] extends Seq[A] {
* @param n the number of elements to drop.
* @return the list without its <code>n</code> first elements.
*/
- override def drop(n: Int): List[A] =
- if (isEmpty || n <= 0) this
- else (tail drop (n-1))
+ override def drop(n: Int): List[A] = {
+ var these = this
+ var count = n
+ while (!these.isEmpty && count > 0) {
+ these = these.tail
+ count -= 1
+ }
+ these
+ }
/** Returns the rightmost <code>n</code> elements from this list.
*
diff --git a/src/library/scala/Responder.scala b/src/library/scala/Responder.scala
index 9aade29aa1..fd7e5f1b35 100644
--- a/src/library/scala/Responder.scala
+++ b/src/library/scala/Responder.scala
@@ -12,6 +12,7 @@ package scala
/** This object contains utility methods to build responders.
*
+ * @author Martin Odersky
* @author Burak Emir
* @version 1.0
*
@@ -60,6 +61,7 @@ object Responder {
* Scala while giving the impression that programs in these DSLs are
* written in direct style.
*
+ * @author Martin Odersky
* @author Burak Emir
* @version 1.0
*/
diff --git a/src/library/scala/collection/Map.scala b/src/library/scala/collection/Map.scala
index 015bda5f21..fafdf8e175 100644
--- a/src/library/scala/collection/Map.scala
+++ b/src/library/scala/collection/Map.scala
@@ -191,4 +191,8 @@ trait Map[A, +B] extends PartialFunction[A, B] with Collection[(A, B)] {
override def contains(key : A) = Map.this.contains(key)
override def get(key : A) = Map.this.get(key).map(f)
}
+
+ /** Defines the prefix of this object's <code>toString</code> representation.
+ */
+ override protected def stringPrefix : String = "Map"
}
diff --git a/src/library/scala/collection/Set.scala b/src/library/scala/collection/Set.scala
index 4f412712d6..aac1342a37 100644
--- a/src/library/scala/collection/Set.scala
+++ b/src/library/scala/collection/Set.scala
@@ -124,4 +124,8 @@ trait Set[A] extends (A => Boolean) with Collection[A] {
copyToArray(result, 0)
result
}
+
+ /** Defines the prefix of this object's <code>toString</code> representation.
+ */
+ override protected def stringPrefix : String = "Set"
}
diff --git a/src/library/scala/util/parsing/combinator1/lexical/StdLexical.scala b/src/library/scala/util/parsing/combinator1/lexical/StdLexical.scala
index fc04116692..e278869f7a 100644
--- a/src/library/scala/util/parsing/combinator1/lexical/StdLexical.scala
+++ b/src/library/scala/util/parsing/combinator1/lexical/StdLexical.scala
@@ -37,9 +37,9 @@ class StdLexical extends Lexical with StdTokens {
def token: Parser[Token] =
( letter ~ rep( letter | digit ) ^^ { case first ~ rest => processIdent(first :: rest mkString "") }
| digit ~ rep( digit ) ^^ { case first ~ rest => NumericLit(first :: rest mkString "") }
- | '\'' ~ rep( chrExcept('\'', '\n', EofCh) ) ~ '\'' ^^ { case _ ~ chars ~ _ => StringLit(chars mkString "") }
- | '\"' ~ rep( chrExcept('\"', '\n', EofCh) ) ~ '\"' ^^ { case _ ~ chars ~ _ => StringLit(chars mkString "") }
- | EofCh ^^ const(EOF)
+ | '\'' ~ rep( chrExcept('\'', '\n', EofCh) ) ~ '\'' ^^ { case '\'' ~ chars ~ '\'' => StringLit(chars mkString "") }
+ | '\"' ~ rep( chrExcept('\"', '\n', EofCh) ) ~ '\"' ^^ { case '\"' ~ chars ~ '\"' => StringLit(chars mkString "") }
+ | EofCh ^^^ EOF
| '\'' ~> failure("unclosed string literal")
| '\"' ~> failure("unclosed string literal")
| delim
@@ -70,7 +70,7 @@ class StdLexical extends Lexical with StdTokens {
private var _delim: Parser[Token] = null
protected def delim: Parser[Token] = {
- if(_delim eq null) { // construct parser for delimiters by |'ing together the parsers for the individual delimiters,
+ if (_delim eq null) { // construct parser for delimiters by |'ing together the parsers for the individual delimiters,
// starting with the longest one (hence the sort + reverse) -- otherwise a delimiter D will never be matched if
// there is another delimiter that is a prefix of D
def parseDelim(s: String): Parser[Token] = accept(s.toList) ^^ { x => Keyword(s) }