summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/reference/ReferencePart.tex12
-rw-r--r--sources/scala/List.scala45
-rw-r--r--sources/scala/tools/scalac/ast/parser/Parser.scala35
-rw-r--r--sources/scala/tools/scalac/typechecker/Analyzer.scala11
-rw-r--r--sources/scala/tools/scalac/typechecker/DeSugarize.scala2
-rw-r--r--sources/scalac/symtab/ClosureHistory.java4
-rw-r--r--sources/scalac/symtab/Type.java28
-rw-r--r--test/files/dis/List.check4
-rw-r--r--test/files/neg/bug72.check2
-rw-r--r--test/files/pos/context.scala42
10 files changed, 172 insertions, 13 deletions
diff --git a/doc/reference/ReferencePart.tex b/doc/reference/ReferencePart.tex
index 362f4045a8..e1728fa95a 100644
--- a/doc/reference/ReferencePart.tex
+++ b/doc/reference/ReferencePart.tex
@@ -4385,11 +4385,8 @@ following definitions.
package scala;
abstract class Any {
- /** Reference equality */
- final def eq(that: Any): boolean = $\ldots$
-
- /** Defined equality */
- def equals(that: Any): boolean = this eq that;
+ /** Defined equality; abstract here */
+ def equals(that: Any): boolean;
/** Semantic equality between values of same type */
final def == (that: Any): boolean = this equals that
@@ -4420,7 +4417,10 @@ abstract class Any {
def match[a, b](cases: a => b): b = cases(this);
}
final class AnyVal extends Any;
-class AnyRef extends Any;
+class AnyRef extends Any {
+ def equals(that: Any): boolean = this eq that;
+ final def eq(that: Any): boolean = $\ldots$; // reference equality
+}
trait ScalaObject extends AnyRef;
\end{lstlisting}
diff --git a/sources/scala/List.scala b/sources/scala/List.scala
index 00b3bcf446..ec05522eda 100644
--- a/sources/scala/List.scala
+++ b/sources/scala/List.scala
@@ -180,6 +180,49 @@ object List {
sb.toString()
}
+ /** 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), ..., f(an,bn)]</code> if the lists are
+ * <code>[a0, ..., ak]</code>, <code>[b0, ..., bl]</code> and
+ * <code>m = 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);
+
+ /** Tests whether the given predicate <code>p</code> holds
+ * for all corresponding elements of the argument lists.
+ *
+ * @param p function to apply to each pair of elements.
+ * @return <code>n == 0 || (p(a0,b0) && ... && p(an,bn))]</code> if the lists are
+ * <code>[a0, ..., ak]</code>, <code>[b0, ..., bl]</code> and
+ * <code>m = min(k,l)</code>
+ */
+ def forall2[a,b](xs: List[a], ys: List[b], f: (a, b) => boolean): boolean =
+ if (xs.isEmpty || ys.isEmpty) true
+ else f(xs.head, ys.head) && forall2(xs.tail, ys.tail, f);
+
+ /** Tests whether the given predicate <code>p</code> holds
+ * for some corresponding elements of the argument lists.
+ *
+ * @param p function to apply to each pair of elements.
+ * @return <code>n != 0 && (p(a0,b0) || ... || p(an,bn))]</code> if the lists are
+ * <code>[a0, ..., ak]</code>, <code>[b0, ..., bl]</code> and
+ * <code>m = min(k,l)</code>
+ */
+ def exists2[a,b](xs: List[a], ys: List[b], f: (a, b) => boolean): boolean =
+ if (xs.isEmpty || ys.isEmpty) false
+ else f(xs.head, ys.head) || exists2(xs.tail, ys.tail, f);
+
+ /** Transposes a list of lists.
+ * pre: All element lists have the same length.
+ */
+ def transpose[a](xss: List[List[a]]): List[List[a]] =
+ if (xss.head.isEmpty) List()
+ else (xss map (xs => xs.head)) :: transpose(xss map (xs => xs.tail));
+
/** Lists with ordered elements are ordered
*/
def view[a <% Ordered[a]](x: List[a]): Ordered[List[a]] = new Ordered[List[a]] {
@@ -445,7 +488,7 @@ sealed trait List[+a] extends Seq[a] {
def map[b](f: a => b): List[b] = match {
case Nil => Nil
case head :: tail => f(head) :: (tail map f)
- };
+ }
/** Apply a function to all the elements of the list, and return the
* reversed list of results. This is equivalent to a call to <code>map</code>
diff --git a/sources/scala/tools/scalac/ast/parser/Parser.scala b/sources/scala/tools/scalac/ast/parser/Parser.scala
index 3aa0ac6cb2..2ce0ec1c3a 100644
--- a/sources/scala/tools/scalac/ast/parser/Parser.scala
+++ b/sources/scala/tools/scalac/ast/parser/Parser.scala
@@ -239,6 +239,7 @@ class Parser(unit: CompilationUnit) {
NewArray.Tree(left, right));
}
+
def scalaDot(pos: int, name: Name): Tree =
make.Select(pos, make.Ident(pos, Names.scala), name);
@@ -433,6 +434,29 @@ class Parser(unit: CompilationUnit) {
make.Apply(t.pos, t, Tree.EMPTY_ARRAY)
}
+ /** make closure from tree */
+ def makeClosure(pos: int, tree: Tree): Tree = {
+ val pname = fresh();
+ def insertParam(tree: Tree): Tree = tree match {
+ case Tree$Ident(name) =>
+ make.Select(tree.pos, make.Ident(pos, pname), name)
+ case Tree$Select(qual, name) =>
+ make.Select(tree.pos, insertParam(qual), name)
+ case Tree$Apply(fn, args) =>
+ make.Apply(tree.pos, insertParam(fn), args)
+ case Tree$TypeApply(fn, args) =>
+ make.TypeApply(tree.pos, insertParam(fn), args)
+ case _ =>
+ syntaxError(pos, "cannot concert to closure", false);
+ gen.mkZeroLit(s.pos)
+ }
+ make.Function(
+ pos,
+ NewArray.ValDef(
+ make.ValDef(pos, Modifiers.PARAM, pname, Tree.Empty, Tree.Empty)),
+ insertParam(tree))
+ }
+
/////// OPERAND/OPERATOR STACK /////////////////////////////////////////////////
var operands = new Array[Tree](8);
@@ -818,6 +842,7 @@ class Parser(unit: CompilationUnit) {
* | return [Expr]
* | [SimpleExpr `.'] Id `=' Expr
* | SimpleExpr ArgumentExprs `=' Expr
+ * | `.' SimpleExpr
* | PostfixExpr [`:' Type1]
* Bindings ::= Id [`:' Type1]
* | `(' [Binding {`,' Binding}] `)'
@@ -890,6 +915,14 @@ class Parser(unit: CompilationUnit) {
} else if (s.token == THROW) {
val pos = s.skipToken();
make.Throw(pos, expr())
+ } else if (s.token == DOT) {
+ val pos = s.skipToken();
+ if (s.token == IDENTIFIER)
+ makeClosure(pos, simpleExpr())
+ else {
+ syntaxError("identifier expected", true);
+ gen.mkZeroLit(pos);
+ }
} else {
var t = postfixExpr();
if (s.token == EQUALS) {
@@ -927,7 +960,7 @@ class Parser(unit: CompilationUnit) {
}
}
- /** PostfixExpr ::= InfixExpr [Id]
+ /** PostfixExpr ::= [`.'] InfixExpr [Id]
* InfixExpr ::= PrefixExpr
* | InfixExpr Id InfixExpr
*/
diff --git a/sources/scala/tools/scalac/typechecker/Analyzer.scala b/sources/scala/tools/scalac/typechecker/Analyzer.scala
index 46692e3508..1478b89045 100644
--- a/sources/scala/tools/scalac/typechecker/Analyzer.scala
+++ b/sources/scala/tools/scalac/typechecker/Analyzer.scala
@@ -1330,6 +1330,8 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
clazz.getType()
else if (selftype.isSubType(clazz.getType()))
selftype
+ else if (selftype.isSingletonType() && selftype.singleDeref().symbol().isSubClass(clazz))
+ selftype
else
selftype match {
case Type$CompoundType(parts, members) =>
@@ -1342,6 +1344,7 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
Type.compoundTypeWithOwner(
clazz.owner().enclClass(), NewArray.Type(selftype, clazz.getType()), Scope.EMPTY);
}
+ if (global.debug) global.log("assigning self type " + selftype1);
sym.setInfo(selftype1);
this.unit = savedUnit;
@@ -1367,7 +1370,9 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
}
case _ =>
}
- if ((pt != null && pt.isStable() || (mode & QUALmode) != 0) &&
+ if ((pt != null && pt.isStable() ||
+ (mode & QUALmode) != 0 ||
+ tree.getType().symbol().isModuleClass()) &&
(pre != null) && pre.isStable()) {
var sym: Symbol = tree.symbol();
tree.getType() match {
@@ -1566,7 +1571,7 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
}
var owntype: Type = tree.getType();
- if ((mode & (CONSTRmode | FUNmode)) == (CONSTRmode)) {
+ if ((mode & (CONSTRmode | FUNmode)) == (CONSTRmode) && pt != Type.AnyType) {
owntype = owntype.instanceType();
// this works as for superclass constructor calls the expected
// type `pt' is always AnyType (see transformConstrInvocations).
@@ -1917,7 +1922,7 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
transformConstrInvocationArgs(parents);
if (!owner.isError()) {
validateParentClasses(
- parents, owner.info().parents(), owner.typeOfThis());
+ parents, owner.info().parents(), owner.thisType());
}
val prevContext = pushContext(templ, owner, owner.members());
/*
diff --git a/sources/scala/tools/scalac/typechecker/DeSugarize.scala b/sources/scala/tools/scalac/typechecker/DeSugarize.scala
index 7e178e3000..99ec52fb2b 100644
--- a/sources/scala/tools/scalac/typechecker/DeSugarize.scala
+++ b/sources/scala/tools/scalac/typechecker/DeSugarize.scala
@@ -591,7 +591,7 @@ class DeSugarize(make: TreeFactory, copy: TreeCopier, gen: TreeGen, infer: scala
* It is assumed that all symbols are term symbols ==> make.Ident().
*/
def toIdents(symbols: Array[Symbol]): Array[Tree] = {
- val idents = new Array[Tree$Ident](symbols.length);
+ val idents = new Array[Tree](symbols.length);
for (val i <- Iterator.range(0, symbols.length)) {
idents(i) = make.Ident(symbols(i).pos, symbols(i).name);
}
diff --git a/sources/scalac/symtab/ClosureHistory.java b/sources/scalac/symtab/ClosureHistory.java
index 514e093f29..0f5073cd89 100644
--- a/sources/scalac/symtab/ClosureHistory.java
+++ b/sources/scalac/symtab/ClosureHistory.java
@@ -66,6 +66,10 @@ public class ClosureHistory extends History {
for (int i = 0; i < parents.length; i++)
addParents(table, parents[i]);
return;
+ case SingleType(_, _):
+ case ThisType(_):
+ addParents(table, type.singleDeref());
+ return;
default:
throw Debug.abort("illegal case", type);
}
diff --git a/sources/scalac/symtab/Type.java b/sources/scalac/symtab/Type.java
index f0ebe88b1e..8b7510a597 100644
--- a/sources/scalac/symtab/Type.java
+++ b/sources/scalac/symtab/Type.java
@@ -698,6 +698,15 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
}
}
+ /** Is this type a s thistype or singletype?
+ */
+ public boolean isSingletonType() {
+ switch (this) {
+ case ThisType(_): case SingleType(_, _): return true;
+ default: return false;
+ }
+ }
+
/** Is this type a reference to an object type?
* todo: replace by this.isSubType(global.definitions.ANY_TYPE())?
*/
@@ -2155,6 +2164,12 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
&& sym == sym1.moduleClass()
&& sym.owner().thisType().isSameAs(pre1)
||
+ this.singleDeref().isSingletonType() &&
+ this.singleDeref().isSameAs(that)
+ ||
+ that.singleDeref().isSingletonType() &&
+ this.isSameAs(that.singleDeref())
+ ||
deAlias(that) != that &&
this.isSameAs(deAlias(that));
}
@@ -2165,6 +2180,12 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
case SingleType(Type pre1, Symbol sym1):
return sym == sym1 && pre.isSameAs(pre1)
||
+ this.singleDeref().isSingletonType() &&
+ this.singleDeref().isSameAs(that)
+ ||
+ that.singleDeref().isSingletonType() &&
+ this.isSameAs(that.singleDeref())
+ ||
(deAlias(this) != this || deAlias(that) != that) &&
deAlias(this).isSameAs(deAlias(that));
case ThisType(Symbol sym1):
@@ -2172,6 +2193,12 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
&& sym.moduleClass() == sym1
&& pre.isSameAs(sym1.owner().thisType())
||
+ this.singleDeref().isSingletonType() &&
+ this.singleDeref().isSameAs(that)
+ ||
+ that.singleDeref().isSingletonType() &&
+ this.isSameAs(that.singleDeref())
+ ||
deAlias(this) != this &&
deAlias(this).isSameAs(that);
default:
@@ -2280,6 +2307,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
return false;
}
//where
+
Type deAlias(Type tp) {
switch (tp) {
case SingleType(_, _):
diff --git a/test/files/dis/List.check b/test/files/dis/List.check
index 65f447d305..f80406d4ee 100644
--- a/test/files/dis/List.check
+++ b/test/files/dis/List.check
@@ -60,5 +60,9 @@ object List extends scala.AnyRef with scala.ScalaObject {
final def fromString(java.lang.String, scala.Char): scala.List[java.lang.String];
final def fromString(java.lang.String): scala.List[scala.Char];
final def toString(scala.List[scala.Char]): java.lang.String;
+ final def map2[a, b, c](scala.List[a], scala.List[b], (a, b) => c): scala.List[c];
+ final def forall2[a, b](scala.List[a], scala.List[b], (a, b) => scala.Boolean): scala.Boolean;
+ final def exists2[a, b](scala.List[a], scala.List[b], (a, b) => scala.Boolean): scala.Boolean;
+ final def transpose[a](scala.List[scala.List[a]]): scala.List[scala.List[a]];
final def view[a <% scala.Ordered[a]](a => scala.Ordered[a])(scala.List[a]): scala.Ordered[scala.List[a]]
}
diff --git a/test/files/neg/bug72.check b/test/files/neg/bug72.check
index 0b427069f2..eea821046d 100644
--- a/test/files/neg/bug72.check
+++ b/test/files/neg/bug72.check
@@ -1,4 +1,4 @@
-bug72.scala:5: object Set of type scala.collection.mutable.Set cannot be applied to (java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String) with expected result type scala.collection.mutable.Set[java.lang.String]
+bug72.scala:5: object Set of type scala.collection.mutable.Set.type cannot be applied to (java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String) with expected result type scala.collection.mutable.Set[java.lang.String]
val weekDays : Set[String] = Set("Mon", "Tue", "Wed", "Thu", "Fri");
^
one error found
diff --git a/test/files/pos/context.scala b/test/files/pos/context.scala
new file mode 100644
index 0000000000..5706918ef9
--- /dev/null
+++ b/test/files/pos/context.scala
@@ -0,0 +1,42 @@
+class Context {
+ object symswrap extends SymsWrapper {
+ val context: Context.this.type = Context.this
+ }
+ object typswrap extends TypsWrapper {
+ val context: Context.this.type = Context.this
+ }
+ object syms extends symswrap.Syms;
+ object typs extends typswrap.Typs;
+}
+
+abstract class SymsWrapper {
+ val context: Context;
+ import context._;
+
+ class Syms: context.syms.type {
+ abstract class Sym: context.syms.Sym {
+ def typ: typs.Typ;
+ def sym: Sym = typ.sym;
+ }
+ }
+}
+
+abstract class TypsWrapper {
+ val context: Context;
+ import context._;
+
+ class Typs: context.typs.type {
+ abstract class Typ {
+ def sym: syms.Sym;
+ def typ: Typ = sym.typ;
+ }
+ }
+}
+
+============================================================
+
+class Context {
+
+
+}
+