From 4a1a36b3441d1a1b1013941f73ce83f4837f874b Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 23 Aug 2004 14:58:37 +0000 Subject: *** empty log message *** --- doc/reference/ReferencePart.tex | 12 +++--- sources/scala/List.scala | 45 +++++++++++++++++++++- sources/scala/tools/scalac/ast/parser/Parser.scala | 35 ++++++++++++++++- .../scala/tools/scalac/typechecker/Analyzer.scala | 11 ++++-- .../tools/scalac/typechecker/DeSugarize.scala | 2 +- sources/scalac/symtab/ClosureHistory.java | 4 ++ sources/scalac/symtab/Type.java | 28 ++++++++++++++ test/files/dis/List.check | 4 ++ test/files/neg/bug72.check | 2 +- test/files/pos/context.scala | 42 ++++++++++++++++++++ 10 files changed, 172 insertions(+), 13 deletions(-) create mode 100644 test/files/pos/context.scala 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 f to + * corresponding elements of the argument lists. + * + * @param f function to apply to each pair of elements. + * @return [f(a0,b0), ..., f(an,bn)] if the lists are + * [a0, ..., ak], [b0, ..., bl] and + * m = min(k,l) + */ + 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 p holds + * for all corresponding elements of the argument lists. + * + * @param p function to apply to each pair of elements. + * @return n == 0 || (p(a0,b0) && ... && p(an,bn))] if the lists are + * [a0, ..., ak], [b0, ..., bl] and + * m = min(k,l) + */ + 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 p holds + * for some corresponding elements of the argument lists. + * + * @param p function to apply to each pair of elements. + * @return n != 0 && (p(a0,b0) || ... || p(an,bn))] if the lists are + * [a0, ..., ak], [b0, ..., bl] and + * m = min(k,l) + */ + 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 map 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)); } @@ -2164,6 +2179,12 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { switch (that) { 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)); @@ -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 { + + +} + -- cgit v1.2.3