diff options
Diffstat (limited to 'sources')
34 files changed, 414 insertions, 254 deletions
diff --git a/sources/examples/auction.scala b/sources/examples/auction.scala index e553752342..102892b4c6 100644 --- a/sources/examples/auction.scala +++ b/sources/examples/auction.scala @@ -11,18 +11,17 @@ case class trait AuctionReply; case class Status(asked: Int, expiration: Date), // asked sum, expiration date - BestOffer(), // yours is the best offer + BestOffer, // yours is the best offer BeatenOffer(maxBid: Int), // offer beaten by maxBid AuctionConcluded(seller: Actor, client: Actor), // auction concluded - AuctionFailed(), // failed with no bids - AuctionOver() extends AuctionReply; // bidding is closed + AuctionFailed, // failed with no bids + AuctionOver extends AuctionReply; // bidding is closed -class Auction(seller: Actor, minBid: Int, closing: Date) extends Actor() { +class Auction(seller: Actor, minBid: Int, closing: Date) extends Actor { val timeToShutdown = 36000000; // msec val bidIncrement = 10; - override def run() = execute; - def execute = { + override def run() = { var maxBid = minBid - bidIncrement; var maxBidder: Actor = _; var running = true; @@ -33,7 +32,7 @@ class Auction(seller: Actor, minBid: Int, closing: Date) extends Actor() { if (maxBid >= minBid) maxBidder send BeatenOffer(bid); maxBid = bid; maxBidder = client; - client send BestOffer(); + client send BestOffer; } else { client send BeatenOffer(maxBid); } @@ -41,17 +40,17 @@ class Auction(seller: Actor, minBid: Int, closing: Date) extends Actor() { case Inquire(client) => client send Status(maxBid, closing); - case TIMEOUT() => + case TIMEOUT => if (maxBid >= minBid) { val reply = AuctionConcluded(seller, maxBidder); maxBidder send reply; seller send reply; } else { - seller send AuctionFailed(); + seller send AuctionFailed; } receiveWithin(timeToShutdown) { - case Offer(_, client) => client send AuctionOver() - case TIMEOUT() => running = false; + case Offer(_, client) => client send AuctionOver + case TIMEOUT => running = false; } } } diff --git a/sources/scala/$colon$colon.scala b/sources/scala/$colon$colon.scala index 61afd1313b..cb1bf098cc 100644 --- a/sources/scala/$colon$colon.scala +++ b/sources/scala/$colon$colon.scala @@ -7,6 +7,5 @@ package scala { def isEmpty = false; def head = hd; def tail = tl; - override def toString(): String = mkString("[", ",", "]"); } } diff --git a/sources/scala/Interpreter.scala b/sources/scala/Interpreter.scala index a6b3f4a4c3..c904c77c33 100644 --- a/sources/scala/Interpreter.scala +++ b/sources/scala/Interpreter.scala @@ -10,7 +10,7 @@ package scala; -module Interpreter { +object Interpreter { def initialize: Boolean = true; diff --git a/sources/scala/Iterator.scala b/sources/scala/Iterator.scala index 57a97ac441..25a1c81308 100644 --- a/sources/scala/Iterator.scala +++ b/sources/scala/Iterator.scala @@ -68,7 +68,7 @@ trait Iterator[a] { } } -module Iterator { +object Iterator { def empty[a] = new Iterator[a] { def hasNext = false; diff --git a/sources/scala/List.scala b/sources/scala/List.scala index 2d6464955c..a079ce4fcc 100644 --- a/sources/scala/List.scala +++ b/sources/scala/List.scala @@ -275,6 +275,8 @@ trait List[a] extends Seq[a] { else if (tail.isEmpty) head.toString() + end else head.toString().concat(sep).concat(tail.mkString("", sep, end))); + override def toString() = mkString("[", ",", "]"); + /** Return a list formed from this list and the specified list * <code>that</code> by associating each element of the former with * the element at the same position in the latter. @@ -343,7 +345,7 @@ trait List[a] extends Seq[a] { } } -module List { +object List { def range(from: Int, end: Int): List[Int] = if (from >= end) scala.Predef.List() diff --git a/sources/scala/Nil.scala b/sources/scala/Nil.scala index 82460f5de3..09f9bf0bc8 100644 --- a/sources/scala/Nil.scala +++ b/sources/scala/Nil.scala @@ -7,7 +7,6 @@ package scala { def isEmpty = true; def head: c = error("head of empty list"); def tail: List[c] = error("tail of empty list"); - override def toString(): String = "[]"; } } diff --git a/sources/scala/Predef.scala b/sources/scala/Predef.scala index 62561fab89..ee28828191 100644 --- a/sources/scala/Predef.scala +++ b/sources/scala/Predef.scala @@ -1,6 +1,6 @@ package scala; -module Predef { +object Predef { type byte = scala.Byte; type short = scala.Short; diff --git a/sources/scala/Stream.scala b/sources/scala/Stream.scala index 701499a487..984f3f362e 100644 --- a/sources/scala/Stream.scala +++ b/sources/scala/Stream.scala @@ -116,7 +116,7 @@ trait Stream[a] { } } -module Stream { +object Stream { def empty[c]: Stream[c] = new Stream[c] { def isEmpty = true; diff --git a/sources/scala/concurrent/Actor.scala b/sources/scala/concurrent/Actor.scala index f6a1447f0e..9c1c5c2a57 100644 --- a/sources/scala/concurrent/Actor.scala +++ b/sources/scala/concurrent/Actor.scala @@ -1,10 +1,10 @@ package scala.concurrent; -abstract class Actor() extends Thread() { +abstract class Actor extends Thread { type Message = AnyRef; - private val mb = new MailBox(); + private val mb = new MailBox; def send(msg: Message): Unit = mb.send(msg); @@ -12,4 +12,9 @@ abstract class Actor() extends Thread() { mb.receive(f); def receiveWithin[a](msec: Long)(f: PartialFunction[Message, a]): a = mb.receiveWithin(msec)(f); -}
\ No newline at end of file +} + + + + + diff --git a/sources/scala/concurrent/Channel.scala b/sources/scala/concurrent/Channel.scala index b58cf15862..fee66786ab 100644 --- a/sources/scala/concurrent/Channel.scala +++ b/sources/scala/concurrent/Channel.scala @@ -1,12 +1,12 @@ package scala.concurrent; -class Channel[a]() extends Monitor() { - private var written: LinkedList[a] = new LinkedList(); +class Channel[a] extends Monitor { + private var written: LinkedList[a] = new LinkedList; private var lastWritten = written; private var nreaders = 0; def write(x: a) = synchronized { - lastWritten.next = new LinkedList(); + lastWritten.next = new LinkedList; lastWritten = lastWritten.next; if (nreaders > 0) notify(); } diff --git a/sources/scala/concurrent/Lock.scala b/sources/scala/concurrent/Lock.scala index 9581151ea7..48431ff110 100644 --- a/sources/scala/concurrent/Lock.scala +++ b/sources/scala/concurrent/Lock.scala @@ -1,6 +1,6 @@ package scala.concurrent; -class Lock() extends Monitor() { +class Lock extends Monitor { var available = true; def acquire = { if (!available) wait(); diff --git a/sources/scala/concurrent/MailBox.scala b/sources/scala/concurrent/MailBox.scala index 62a102781e..576d203d89 100644 --- a/sources/scala/concurrent/MailBox.scala +++ b/sources/scala/concurrent/MailBox.scala @@ -1,10 +1,10 @@ package scala.concurrent; -class MailBox() extends Monitor() { +class MailBox extends Monitor { type Message = AnyRef; - private abstract class Receiver() extends Monitor() { + private abstract class Receiver extends Monitor { type t; val receiver: PartialFunction[Message, t]; var msg: Message = _; @@ -18,9 +18,9 @@ class MailBox() extends Monitor() { } } - private val sent = new LinkedList[Message](); + private val sent = new LinkedList[Message]; private var lastSent = sent; - private var receivers = new LinkedList[Receiver](); + private var receivers = new LinkedList[Receiver]; private var lastReceiver = receivers; def send(msg: Message): Unit = synchronized { @@ -48,13 +48,13 @@ class MailBox() extends Monitor() { } def receive[a](f: PartialFunction[Message, a]): a = { - val r = new Receiver() { type t = a; val receiver = f } + val r = new Receiver { type t = a; val receiver = f } scanSentMsgs(r); r.receive() } def receiveWithin[a](msec: Long)(f: PartialFunction[Message, a]): a = { - val r = new Receiver() { type t = a; val receiver = f } + val r = new Receiver { type t = a; val receiver = f } scanSentMsgs(r); r.receiveWithin(msec) } diff --git a/sources/scala/concurrent/SyncChannel.scala b/sources/scala/concurrent/SyncChannel.scala index 7184ff7c61..7f0680487d 100644 --- a/sources/scala/concurrent/SyncChannel.scala +++ b/sources/scala/concurrent/SyncChannel.scala @@ -1,6 +1,6 @@ package scala.concurrent; -class SyncChannel[a]() extends Monitor() { +class SyncChannel[a] extends Monitor { private var data: a = _; private var reading = false; private var writing = false; diff --git a/sources/scala/concurrent/SyncVar.scala b/sources/scala/concurrent/SyncVar.scala index 4bb550be30..4c1c6864bd 100644 --- a/sources/scala/concurrent/SyncVar.scala +++ b/sources/scala/concurrent/SyncVar.scala @@ -1,6 +1,6 @@ package scala.concurrent; -class SyncVar[a]() extends Monitor() { +class SyncVar[a] extends Monitor { private var isDefined: Boolean = false; private var value: a = _; def get = synchronized { diff --git a/sources/scala/concurrent/TIMEOUT.scala b/sources/scala/concurrent/TIMEOUT.scala index 5c26cf8611..189ae0632f 100644 --- a/sources/scala/concurrent/TIMEOUT.scala +++ b/sources/scala/concurrent/TIMEOUT.scala @@ -1,3 +1,3 @@ package scala.concurrent; -case class TIMEOUT(); +case class TIMEOUT; diff --git a/sources/scala/concurrent/ops.scala b/sources/scala/concurrent/ops.scala index 8b52975ef1..f0bc73f953 100644 --- a/sources/scala/concurrent/ops.scala +++ b/sources/scala/concurrent/ops.scala @@ -3,18 +3,18 @@ package scala.concurrent; module ops { def spawn(def p: Unit) = { - val t = new Thread() { override def run() = p; } + val t = new Thread { override def run() = p; } t.run() } def future[a](def p: a): () => a = { - val result = new SyncVar[a](); + val result = new SyncVar[a]; spawn { result set p } () => result.get } def par[a, b](def xp: a, def yp: b): Pair[a, b] = { - val y = new SyncVar[b](); + val y = new SyncVar[b]; spawn { y set yp } Pair(xp, y.get) } diff --git a/sources/scalac/ast/Tree.java b/sources/scalac/ast/Tree.java index 0c28016253..a3cc94cf3e 100644 --- a/sources/scalac/ast/Tree.java +++ b/sources/scalac/ast/Tree.java @@ -146,7 +146,7 @@ public class Tree { /** * Import declaration * - introduced by: parser - * - eliminated by: !!! ? + * - eliminated by: analyzer */ public case Import(Tree expr, Name[] selectors) { if (!expr.isTerm()) @@ -204,8 +204,8 @@ public class Tree { /** * Tuple of expressions (comma separated expressions) - * - introduced by: !!! ? - * - eliminated by: !!! ? + * - introduced by: uncurry + * - eliminated by: lambdalift */ public case Tuple(Tree[] trees) { if (trees != null) { @@ -219,14 +219,14 @@ public class Tree { /** * Visitor (a sequence of cases) * - introduced by: parser - * - eliminated by: !!! ? + * - eliminated by: transmatch */ public case Visitor(CaseDef[] cases); /** * Anonymous function * - introduced by: parser - * - eliminated by: !!! ? + * - eliminated by: analyzer */ public case Function(ValDef[] vparams, Tree body) { @@ -237,7 +237,7 @@ public class Tree { /** * Assignment * - introduced by: parser - * - eliminated by: !!! ? + * - eliminated by: - */ public case Assign(Tree lhs, Tree rhs) { @@ -283,7 +283,7 @@ public class Tree { /** * Type application * - introduced by: parser - * - eliminated by: !!! ? + * - eliminated by: erasure */ public case TypeApply(Tree fun, Tree[] args) { @@ -422,7 +422,7 @@ public class Tree { /** * Applied type * - introduced by: parser - * - eliminated by: Analyzer + * - eliminated by: analyzer */ public case AppliedType(Tree tpe, Tree[] args) { assert tpe.isType() : this; @@ -492,6 +492,17 @@ public class Tree { } } + /** Returns true if this tree is empty or error. */ + public boolean isMissing() { + switch(this) { + case Bad(): + case Empty: + return true; + default: + return false; + } + } + //######################################################################## // Public Methods - tree type diff --git a/sources/scalac/ast/TreeGen.java b/sources/scalac/ast/TreeGen.java index 0c9c47eb88..ecb4705de5 100644 --- a/sources/scalac/ast/TreeGen.java +++ b/sources/scalac/ast/TreeGen.java @@ -165,13 +165,7 @@ public class TreeGen implements Kinds, Modifiers { Tree ref = mkRef(pos, pre, sym.constructor()); Tree constr = (args.length == 0) ? ref : TypeApply(ref, mkTypes(sym.pos, args)); - switch (parentType) { - case MethodType(Symbol[] params, Type restpe): - assert params.length == 0 : parentType; - return Apply(constr, Tree.EMPTY_ARRAY); - default: - return constr; - } + return Apply(constr, Tree.EMPTY_ARRAY); default: throw global.fail("invalid parent type", parentType); } @@ -357,9 +351,17 @@ public class TreeGen implements Kinds, Modifiers { return TypeApply(fn.pos, fn, args); } + public Tree If(int pos, Tree cond, Tree thenpart, Tree elsepart) { + return + make.If(pos, cond, thenpart, elsepart).setType(thenpart.type); + } + + public Tree If(Tree cond, Tree thenpart, Tree elsepart) { + return If(cond.pos, cond, thenpart, elsepart); + } + /** Build and applied type node with given function * and argument trees. - */ public Tree AppliedType(int pos, Tree fn, Tree[] args) { return make.AppliedType(pos, fn, args) .setType(Type.appliedType(fn.type, Tree.typeOf(args))); @@ -368,6 +370,7 @@ public class TreeGen implements Kinds, Modifiers { public Tree AppliedType(Tree fn, Tree[] args) { return AppliedType(fn.pos, fn, args); } + */ /** Build and attribute select node of given symbol. * It is assumed that the prefix is not empty. diff --git a/sources/scalac/ast/TreeInfo.java b/sources/scalac/ast/TreeInfo.java index d07627724f..17ca034316 100644 --- a/sources/scalac/ast/TreeInfo.java +++ b/sources/scalac/ast/TreeInfo.java @@ -115,6 +115,8 @@ public class TreeInfo { tree.symbol() != null && tree.symbol().isPrimaryConstructor(); case TypeApply(Tree constr, _): return isPureConstr(constr); + case Apply(Tree fn, Tree[] args): + return args.length == 0 && isPureConstr(fn); default: return false; } diff --git a/sources/scalac/ast/parser/Parser.java b/sources/scalac/ast/parser/Parser.java index f525398b3c..771979fcda 100644 --- a/sources/scalac/ast/parser/Parser.java +++ b/sources/scalac/ast/parser/Parser.java @@ -124,7 +124,7 @@ public class Parser implements Tokens { boolean isDefIntro() { switch (s.token) { case VAL: case VAR: case DEF: case CONSTR: case TYPE: - case MODULE: case CLASS: case CASECLASS: case TRAIT: + case OBJECT: case CASEOBJECT: case CLASS: case CASECLASS: case TRAIT: return true; default: return false; @@ -193,6 +193,15 @@ public class Parser implements Tokens { return make.Select(pos, make.Ident(pos, Names.scala), name); } + Tree scalaBooleanDot(int pos, Name name) { + return make.Select(pos, scalaDot(pos, Names.Boolean), name); + } + + Tree scalaObjectConstr(int pos) { + return make.Apply( + pos, scalaDot(pos, Names.Object.toConstrName()), Tree.EMPTY_ARRAY); + } + /** Create tree for for-comprehension <for (enums) do body> or * <for (enums) yield body> where mapName and flatmapName are chosen * corresponding to whether this is a for-do or a for-yield. @@ -310,6 +319,17 @@ public class Parser implements Tokens { } } + /** Complete unapplied constructor with `()' arguments + */ + Tree applyConstr(Tree t) { + switch (t) { + case Apply(_, _): + return t; + default: + return make.Apply(t.pos, t, Tree.EMPTY_ARRAY); + } + } + /////// OPERAND/OPERATOR STACK ///////////////////////////////////////////////// Tree[] operands = new Tree[8]; @@ -383,6 +403,9 @@ public class Parser implements Tokens { t = make.This(s.skipToken(), Tree.Empty); if (!thisOK || s.token == DOT) t = selectors(accept(DOT), t, typeOK); + } else if (s.token == SUPER) { + t = make.Super(s.skipToken(), Tree.Empty); + t = selectors(accept(DOT), t, typeOK); } else { t = make.Ident(s.pos, ident()); if (s.token == DOT) { @@ -413,7 +436,7 @@ public class Parser implements Tokens { } } - /** StableId ::= [[Ident `.'] this `.'] {Id `.'} Id + /** StableId ::= [[Ident `.'] this `.' | super] {Id `.'} Id */ Tree stableId() { return stableRef(false, false); @@ -498,6 +521,17 @@ public class Parser implements Tokens { } } + /** SimpleTypedOpt ::= [`:' Type] + */ + Tree simpleTypedOpt() { + if (s.token == COLON) { + s.nextToken(); + return simpleType(); + } else { + return Tree.Empty; + } + } + /** Types ::= Type {`,' Type} */ Tree[] types() { @@ -894,7 +928,8 @@ public class Parser implements Tokens { switch (res) { case Block(Tree[] stats): if (stats.length > 0) - stats[stats.length - 1] = convertToConstr(stats[stats.length - 1]); + stats[stats.length - 1] = applyConstr( + convertToConstr(stats[stats.length - 1])); else syntaxError(res.pos, "class constructor expected", false); } @@ -1337,9 +1372,7 @@ public class Parser implements Tokens { } /** TopDef ::= ([case] class | trait) ClassDef {`,' ClassDef} - * | module ModuleDef {`,' ModuleDef} - * LocalTopDef ::= class ClassDef {`,' ClassDef}//todo: keep? - * | module ModuleDef {`,' ModuleDef} + * | [case] object ModuleDef {`,' ModuleDef} */ Tree[] topDef(int mods) { TreeList ts = new TreeList(); @@ -1354,7 +1387,8 @@ public class Parser implements Tokens { ts.append(classDef(mods)); } while (s.token == COMMA); return ts.toArray(); - case MODULE: + case OBJECT: + case CASEOBJECT: do { s.nextToken(); ts.append(moduleDef(mods)); @@ -1441,10 +1475,7 @@ public class Parser implements Tokens { TypeDef[] tparams = typeParamClauseOpt(); ValDef[][] vparams = new ValDef[][]{paramClause()}; Tree restype = typedOpt(); - if (s.token == LBRACE) - return make.DefDef(pos, mods, name, tparams, vparams, - restype, blockConstr()); - else if (s.token == EQUALS || restype == Tree.Empty) { + if (s.token == EQUALS || restype == Tree.Empty) { accept(EQUALS); return make.DefDef(pos, mods, name, tparams, vparams, restype, (s.token == LBRACE) ? blockConstr() : constr()); @@ -1474,24 +1505,23 @@ public class Parser implements Tokens { } } - /** ClassDef ::= Id [TypeParamClause] [`:' Type] ClassTemplate + /** ClassDef ::= Id [TypeParamClause] [`:' SimpleType] ClassTemplate */ Tree classDef(int mods) { int pos = s.pos; Name name = ident(); TypeDef[] tparams = typeParamClauseOpt(); - ValDef[][] params; - if (s.token == LPAREN) params = new ValDef[][]{paramClause()}; - else params = Tree.ExtValDef.EMPTY_ARRAY_ARRAY; + ValDef[][] params = (s.token == LPAREN) ? new ValDef[][]{paramClause()} + : Tree.ExtValDef.EMPTY_ARRAY_ARRAY; return make.ClassDef(pos, mods, name.toTypeName(), tparams, params, - typedOpt(), classTemplate()); + simpleTypedOpt(), classTemplate()); } - /** ModuleDef ::= Id [`:' Type] ClassTemplate + /** ModuleDef ::= Id [`:' SimpleType] ClassTemplate */ Tree moduleDef(int mods) { return make.ModuleDef( - s.pos, mods, ident(), typedOpt(), classTemplate()); + s.pos, mods, ident(), simpleTypedOpt(), classTemplate()); } /** ClassTemplate ::= [`extends' Constr] {`with' Constr} [TemplateBody] @@ -1504,21 +1534,16 @@ public class Parser implements Tokens { } else if (s.token == WITH) { s.nextToken(); TreeList parents = new TreeList(); - parents.append(scalaDot(pos, Names.Object.toConstrName())); + parents.append(scalaObjectConstr(pos)); return template(parents); } else if (s.token == LBRACE) { - return (Template)make.Template(pos, - new Tree[]{scalaDot(pos, Names.Object.toConstrName())}, - templateBody()); - } else if (s.token == SEMI || s.token == COMMA || s.token == RBRACE) { - return (Template)make.Template(pos, - new Tree[]{scalaDot(pos, Names.Object.toConstrName())}, - Tree.EMPTY_ARRAY); + return (Template)make.Template( + pos, new Tree[]{scalaObjectConstr(pos)}, templateBody()); } else { - syntaxError("`extends' or `{' expected", true); - return (Template)make.Template(pos, - new Tree[]{scalaDot(pos, Names.Object.toConstrName())}, - Tree.EMPTY_ARRAY); + if (!(s.token == SEMI || s.token == COMMA || s.token == RBRACE)) + syntaxError("`extends' or `{' expected", true); + return (Template)make.Template( + pos, new Tree[]{scalaObjectConstr(pos)}, Tree.EMPTY_ARRAY); } } @@ -1550,7 +1575,7 @@ public class Parser implements Tokens { t = make.TypeApply(s.pos, t, typeArgs()); if (s.token == LPAREN) t = make.Apply(s.pos, t, argumentExprs()); - return t; + return applyConstr(t); } /** TemplateBody ::= `{' [TemplateStat {`;' TemplateStat}] `}' @@ -1601,11 +1626,12 @@ public class Parser implements Tokens { } else if (s.token == CLASS || s.token == CASECLASS || s.token == TRAIT || - s.token == MODULE || + s.token == OBJECT || + s.token == CASEOBJECT || isModifier()) { stats.append(topDef(modifiers())); } else if (s.token != SEMI) { - syntaxError("illegal start of class or module definition", true); + syntaxError("illegal start of class or object definition", true); } if (s.token != RBRACE && s.token != EOF) accept(SEMI); } @@ -1658,7 +1684,7 @@ public class Parser implements Tokens { /** BlockStatSeq ::= { BlockStat `;' } [Expr] * BlockStat ::= Import * | Def - * | LocalClassModifiers LocalTopDef + * | LocalClassModifiers TopDef * | Expr * | */ diff --git a/sources/scalac/ast/parser/Scanner.java b/sources/scalac/ast/parser/Scanner.java index 82eef0d408..5cfe8292a6 100644 --- a/sources/scalac/ast/parser/Scanner.java +++ b/sources/scalac/ast/parser/Scanner.java @@ -138,6 +138,8 @@ public class Scanner extends TokenData { fetchToken(); if (token == CLASS) { token = CASECLASS; + } else if (token == OBJECT) { + token = CASEOBJECT; } else { next.copyFrom(this); this.copyFrom(prev); @@ -479,8 +481,10 @@ public class Scanner extends TokenData { void treatIdent(int start, int end) { name = Name.fromAscii(buf, start, end - start); - if (name.index <= maxKey) + if (name.index <= maxKey) { token = key[name.index]; + if (token == OBJECT1) token = OBJECT; //todo: elim + } else token = IDENTIFIER; } @@ -716,6 +720,8 @@ public class Scanner extends TokenData { return "','"; case CASECLASS: return "case class"; + case CASEOBJECT: + return "case object"; default: try { return "'" + tokenName[token].toString() + "'"; @@ -796,7 +802,8 @@ public class Scanner extends TokenData { enterKeyword("def", DEF); enterKeyword("type", TYPE); enterKeyword("extends", EXTENDS); - enterKeyword("module", MODULE); + enterKeyword("object", OBJECT); + enterKeyword("module", OBJECT1); enterKeyword("class",CLASS); enterKeyword("constr",CONSTR); enterKeyword("import", IMPORT); diff --git a/sources/scalac/ast/parser/Tokens.java b/sources/scalac/ast/parser/Tokens.java index 10503ddd48..c4499522df 100644 --- a/sources/scalac/ast/parser/Tokens.java +++ b/sources/scalac/ast/parser/Tokens.java @@ -37,19 +37,20 @@ public interface Tokens { SUPER = 27, CASE = 28, CASECLASS = 29, - VAL = 30, - ABSTRACT = 31, - FINAL = 32, - PRIVATE = 33, - PROTECTED = 34, - OVERRIDE = 35, - VAR = 36, - DEF = 37, - TYPE = 38, - EXTENDS = 39, - TRUE = 40, - FALSE = 41, - MODULE = 43, + CASEOBJECT = 30, + VAL = 31, + ABSTRACT = 32, + FINAL = 33, + PRIVATE = 34, + PROTECTED = 35, + OVERRIDE = 36, + VAR = 37, + DEF = 38, + TYPE = 39, + EXTENDS = 40, + TRUE = 41, + FALSE = 42, + OBJECT = 43, CLASS = 44, CONSTR = 45, IMPORT = 46, @@ -60,6 +61,8 @@ public interface Tokens { DO = 51, TRAIT = 52, + OBJECT1 = 53, // todo: elim + /* special symbols */ COMMA = 61, SEMI = 62, diff --git a/sources/scalac/ast/printer/TextTreePrinter.java b/sources/scalac/ast/printer/TextTreePrinter.java index adbad7c3ad..0d4ff6022f 100644 --- a/sources/scalac/ast/printer/TextTreePrinter.java +++ b/sources/scalac/ast/printer/TextTreePrinter.java @@ -150,7 +150,7 @@ public class TextTreePrinter implements TreePrinter { protected static final Text KW_IMPORT = Text.Keyword("import"); protected static final Text KW_INTERFACE = Text.Keyword("interface"); protected static final Text KW_LET = Text.Keyword("let"); - protected static final Text KW_MODULE = Text.Keyword("module"); + protected static final Text KW_OBJECT = Text.Keyword("object"); protected static final Text KW_NEW = Text.Keyword("new"); protected static final Text KW_NULL = Text.Keyword("null"); protected static final Text KW_OUTER = Text.Keyword("outer"); @@ -171,8 +171,8 @@ public class TextTreePrinter implements TreePrinter { protected static final Text TXT_ERROR = Text.Simple("<error>"); protected static final Text TXT_UNKNOWN = Text.Simple("<unknown>"); protected static final Text TXT_NULL = Text.Simple("<null>"); - protected static final Text TXT_MODULE_COMMENT - = Text.Simple("/*module*/ "); + protected static final Text TXT_OBJECT_COMMENT + = Text.Simple("/*object*/ "); protected static final Text TXT_EMPTY = Text.Simple("<empty>"); protected static final Text TXT_QUOTE = Text.Simple("\""); @@ -192,10 +192,6 @@ public class TextTreePrinter implements TreePrinter { protected static final Text TXT_LEFT_BRACKET = Text.Simple("["); protected static final Text TXT_RIGHT_BRACKET = Text.Simple("]"); - protected static final Text TXT_WITH_BLOCK_BEGIN = - Text.Sequence(new Text[] { - Text.Space, KW_WITH, Text.Space, TXT_LEFT_BRACE, Text.Newline - }); protected static final Text TXT_WITH_SP = Text.Sequence(new Text[]{ Text.Space, KW_WITH, Text.Space }); protected static final Text TXT_BLOCK_BEGIN = @@ -271,7 +267,7 @@ public class TextTreePrinter implements TreePrinter { Tree tpe, Tree.Template impl): printModifiers(mods); - print(KW_MODULE); + print(KW_OBJECT); print(Text.Space); printSymbolDefinition(tree.symbol(), name); printOpt(TXT_COLON, tpe, false); @@ -282,7 +278,7 @@ public class TextTreePrinter implements TreePrinter { printModifiers(mods); if ((mods & Modifiers.MUTABLE) != 0) print(KW_VAR); else { - if ((mods & Modifiers.MODUL) != 0) print(TXT_MODULE_COMMENT); + if ((mods & Modifiers.MODUL) != 0) print(TXT_OBJECT_COMMENT); print(KW_VAL); } print(Text.Space); @@ -506,7 +502,7 @@ public class TextTreePrinter implements TreePrinter { case CompoundType(Tree[] baseTypes, Tree[] refinements): printArray(baseTypes, Text.None, Text.None, TXT_WITH_SP); - printArray(refinements, TXT_WITH_BLOCK_BEGIN, TXT_BLOCK_END, Text.Newline); + printArray(refinements, TXT_BLOCK_BEGIN, TXT_BLOCK_END, Text.Newline); break; case AppliedType(Tree tpe, Tree[] args): @@ -649,8 +645,10 @@ public class TextTreePrinter implements TreePrinter { printArray(templ.parents, Text.None, Text.None, TXT_WITH_SP); } - if (templ.body.length > 0) - printArray(templ.body, TXT_WITH_BLOCK_BEGIN, TXT_BLOCK_END, TXT_BLOCK_SEP); + if (templ.body.length > 0) { + print(Text.Space); + printArray(templ.body, TXT_BLOCK_BEGIN, TXT_BLOCK_END, TXT_BLOCK_SEP); + } } protected void printParams(Tree.TypeDef[] tparams) { diff --git a/sources/scalac/symtab/Definitions.java b/sources/scalac/symtab/Definitions.java index de31e34a06..3fe8cc7dee 100644 --- a/sources/scalac/symtab/Definitions.java +++ b/sources/scalac/symtab/Definitions.java @@ -194,7 +194,7 @@ public class Definitions { ANY_TYPE = ANY_CLASS.typeConstructor(); ANY_CLASS.setInfo(Type.compoundType(Type.EMPTY_ARRAY, new Scope(), ANY_CLASS)); ANY_CLASS.constructor().setInfo( - Type.PolyType(Symbol.EMPTY_ARRAY, ANY_TYPE)); + Type.MethodType(Symbol.EMPTY_ARRAY, ANY_TYPE)); // the java.lang.OBJECT class JAVA_OBJECT_CLASS = getClass(Names.java_lang_Object); diff --git a/sources/scalac/symtab/Modifiers.java b/sources/scalac/symtab/Modifiers.java index cbfafae068..8d161ce117 100644 --- a/sources/scalac/symtab/Modifiers.java +++ b/sources/scalac/symtab/Modifiers.java @@ -55,7 +55,7 @@ public interface Modifiers { int SNDTIME = 0x40000000; //debug // masks - int SOURCEFLAGS = 0x00000077 | PARAM | TRAIT; // these modifiers can be set in source programs. + int SOURCEFLAGS = 0x00000077 | DEF | REPEATED | MODUL | MUTABLE | PACKAGE | PARAM | TRAIT; // these modifiers can be set in source programs. int ACCESSFLAGS = PRIVATE | PROTECTED; public static class Helper { diff --git a/sources/scalac/symtab/Symbol.java b/sources/scalac/symtab/Symbol.java index b76b8c2869..7ecbfe543a 100644 --- a/sources/scalac/symtab/Symbol.java +++ b/sources/scalac/symtab/Symbol.java @@ -104,6 +104,14 @@ public abstract class Symbol implements Modifiers, Kinds { } public Symbol setInfo(Type info, int limit) { + assert !isConstructor() + || info instanceof Type.LazyType + || info == Type.ErrorType + || info instanceof Type.MethodType + || info instanceof Type.OverloadedType + || info instanceof Type.PolyType && + ((Type.PolyType)info).result instanceof Type.MethodType + : "illegal type for " + this + ": " + info; if ((flags & (INITIALIZED | LOCKED)) != (INITIALIZED | LOCKED)) { if (infos == TypeIntervalList.EMPTY) infos = new TypeIntervalList(TypeIntervalList.EMPTY); @@ -748,7 +756,7 @@ public abstract class Symbol implements Modifiers, Kinds { if ((flags & TRAIT) != 0) return "trait"; else if ((flags & MODUL) != 0 && Global.instance.debug) - return "module class"; + return "object class"; else return "class"; case TYPE: @@ -756,7 +764,7 @@ public abstract class Symbol implements Modifiers, Kinds { return "type"; case VAL: if (isVariable()) return "variable"; - else if (isModule()) return "module"; + else if (isModule()) return "object"; else if (isConstructor()) return "constructor"; else if (isInitializedMethod() && (Global.instance.debug || (flags & STABLE) == 0) ) @@ -775,7 +783,7 @@ public abstract class Symbol implements Modifiers, Kinds { case ALIAS: return "type"; case VAL: if (isVariable()) return "var"; - else if (isModule()) return "module"; + else if (isModule()) return "object"; else if (isInitializedMethod()) return "def"; else return "val"; default: return ""; diff --git a/sources/scalac/symtab/Type.java b/sources/scalac/symtab/Type.java index 571e12061a..d579ea9685 100644 --- a/sources/scalac/symtab/Type.java +++ b/sources/scalac/symtab/Type.java @@ -26,7 +26,9 @@ public class Type implements Modifiers, Kinds, TypeTags { public case ThisType(Symbol sym); - public case TypeRef(Type pre, Symbol sym, Type[] args); + public case TypeRef(Type pre, Symbol sym, Type[] args) { + assert pre.isLegalPrefix() || pre == ErrorType : pre + "#" + sym; + } public case SingleType(Type pre, Symbol sym) { assert this instanceof ExtSingleType; @@ -80,11 +82,12 @@ public class Type implements Modifiers, Kinds, TypeTags { public static final Type[] NO_ARRAY = new Type[0]; public static SingleType singleType(Type pre, Symbol sym) { - if (pre.isStable() || pre == ErrorType) + if (pre.isStable() || pre == ErrorType) { return new ExtSingleType(pre, sym); - else + } else { throw new Type.Error( - "malformed type: " + pre + "." + sym.nameString() + ".type"); + "malformed type: " + pre + "#" + sym.nameString() + ".type"); + } } public static TypeRef appliedType(Type tycon, Type[] args) { @@ -116,7 +119,7 @@ public class Type implements Modifiers, Kinds, TypeTags { SYNTHETIC | ABSTRACTCLASS); res.tsym.setInfo(res); res.tsym.constructor().setInfo( - Type.PolyType(Symbol.EMPTY_ARRAY, Type.NoType)); + Type.MethodType(Symbol.EMPTY_ARRAY, Type.NoType)); return res; } @@ -127,7 +130,7 @@ public class Type implements Modifiers, Kinds, TypeTags { return pre.memberInfo(sym); else // todo: handle Java-style inner classes throw new Type.Error( - "malformed type: " + pre + "." + sym.nameString()); + "malformed type: " + pre + "#" + sym.nameString()); } static class ExtSingleType extends SingleType { @@ -634,7 +637,7 @@ public class Type implements Modifiers, Kinds, TypeTags { Type pre1 = apply(pre); Type[] args1 = map(args); if (pre1 == pre && args1 == args) return tp; - else return TypeRef(pre1, sym, args1); + else return typeRef(pre1, sym, args1); case SingleType(Type pre, Symbol sym): Type pre1 = apply(pre); if (pre1 == pre) return tp; @@ -866,7 +869,7 @@ public class Type implements Modifiers, Kinds, TypeTags { Type[] args1 = map(args); typeArg = prevTypeArg; if (prefix1 == prefix && args1 == args) return t; - else return TypeRef(prefix1, sym1, args1); + else return typeRef(prefix1, sym1, args1); } case SingleType(Type prefix, Symbol sym): @@ -1075,7 +1078,7 @@ public class Type implements Modifiers, Kinds, TypeTags { protected Type replacement(int i, Type fromtp) { switch (fromtp) { case TypeRef(Type pre, Symbol sym, Type[] args): - return TypeRef(pre, to[i], args); + return typeRef(pre, to[i], args); case SingleType(Type pre, Symbol sym): return singleType(pre, to[i]); default: @@ -1822,7 +1825,7 @@ public class Type implements Modifiers, Kinds, TypeTags { if (args[j] == NoType) args[j] = CovarType(lub(argss[j])); } - return TypeRef(pre, sym, args); + return typeRef(pre, sym, args); } /** The frontier of a closure C is the minimal set of types such that @@ -2050,7 +2053,7 @@ public class Type implements Modifiers, Kinds, TypeTags { Type this1 = unbox(); if (this1 != this) return this1; else if (args.length == 0) return this; - else return TypeRef(pre, sym, Type.EMPTY_ARRAY); + else return typeRef(pre, sym, Type.EMPTY_ARRAY); } default: throw new ApplicationError(); @@ -2104,6 +2107,7 @@ public class Type implements Modifiers, Kinds, TypeTags { case ThisType(Symbol sym): if (sym.isRoot()) return "<root>.this.type"; else if (this == localThisType) return "<local>.this.type"; + else if (sym.isAnonymousClass()) return "this.type"; else { Type this1 = (Global.instance.debug) ? this : expandModuleThis(); if (this1 == this) return sym.nameString() + ".this.type"; @@ -2195,7 +2199,7 @@ public class Type implements Modifiers, Kinds, TypeTags { else if (spre.endsWith(".type")) return spre.substring(0, spre.length() - 4); else - return spre + "@"; + return spre + "#"; } } diff --git a/sources/scalac/symtab/classfile/AttributeParser.java b/sources/scalac/symtab/classfile/AttributeParser.java index 8cc8e296d0..a6ae0a9083 100644 --- a/sources/scalac/symtab/classfile/AttributeParser.java +++ b/sources/scalac/symtab/classfile/AttributeParser.java @@ -253,7 +253,9 @@ public class AttributeParser implements ClassfileConstants { if ((parser.c.flags & Modifiers.INTERFACE) != 0) { parser.c.constructor().setInfo( - Type.PolyType(smbls, constrtype), parser.phaseId); + Type.PolyType( + smbls, Type.MethodType(Symbol.EMPTY_ARRAY, constrtype)), + parser.phaseId); //System.out.println("info = " + parser.c.constructor().info());//DEBUG } Symbol[] constrs; @@ -269,13 +271,9 @@ public class AttributeParser implements ClassfileConstants { switch (constrs[i].rawInfo()) { case MethodType(Symbol[] vparams, _): constrs[i].setInfo( - Type.PolyType(smbls, - Type.MethodType( - vparams, constrtype)), parser.phaseId); - break; - case PolyType(_, _): - constrs[i].setInfo( - Type.PolyType(smbls, constrtype), parser.phaseId); + Type.PolyType( + smbls, Type.MethodType(vparams, constrtype)), + parser.phaseId); break; } //System.out.println("*** constructor " + e.sym + ": " + e.sym.info());//DEBUG diff --git a/sources/scalac/symtab/classfile/ClassfileParser.java b/sources/scalac/symtab/classfile/ClassfileParser.java index 69d95f79f0..a0d69c4bed 100644 --- a/sources/scalac/symtab/classfile/ClassfileParser.java +++ b/sources/scalac/symtab/classfile/ClassfileParser.java @@ -117,10 +117,9 @@ public class ClassfileParser implements ClassfileConstants { assert constrs.length == 1; c.constructor().setInfo(constrs[0].info(), phaseId); } else { - Type constrtype = ((c.flags & Modifiers.INTERFACE) != 0) - ? Type.PolyType(Symbol.EMPTY_ARRAY, ctype) - : Type.MethodType(new Symbol[]{Symbol.NONE}, ctype); - c.constructor().setInfo(constrtype, phaseId); + Symbol[] cparams = ((c.flags & Modifiers.INTERFACE) != 0) ? Symbol.EMPTY_ARRAY + : new Symbol[]{Symbol.NONE}; + c.constructor().setInfo(Type.MethodType(cparams, ctype), phaseId); } attrib.readAttributes(c, classType, CLASS_ATTR); //System.out.println("dynamic class: " + c); @@ -214,10 +213,7 @@ public class ClassfileParser implements ClassfileConstants { } switch (type) { case MethodType(Symbol[] vparams, _): - if (c == defs.OBJECT_CLASS) - type = Type.PolyType(Symbol.EMPTY_ARRAY, ctype); - else - type = Type.MethodType(vparams, ctype); + type = Type.MethodType(vparams, ctype); break; default: throw new ApplicationError(); diff --git a/sources/scalac/transformer/AddConstructors.java b/sources/scalac/transformer/AddConstructors.java index 6e69d191c3..14ee843677 100644 --- a/sources/scalac/transformer/AddConstructors.java +++ b/sources/scalac/transformer/AddConstructors.java @@ -139,7 +139,9 @@ public class AddConstructors extends Transformer { getConstructor(fun.symbol())); constrBody.add(gen.Apply(superConstr, transform(args))); break; - default: assert false; + default: + new scalac.ast.printer.TextTreePrinter().print(baseClasses[0]).println().end(); + assert false; } } diff --git a/sources/scalac/transformer/ExpandMixins.java b/sources/scalac/transformer/ExpandMixins.java index 19984b4b61..9ce484ab12 100644 --- a/sources/scalac/transformer/ExpandMixins.java +++ b/sources/scalac/transformer/ExpandMixins.java @@ -345,9 +345,10 @@ public class ExpandMixins extends Transformer { case Apply(Select(Tree qualifier, Name selector), Tree[] args): { Tree fun = ((Tree.Apply)newTree).fun; Symbol funOwnerSym = fun.symbol().owner(); - Symbol qualSym = qualifier.type.symbol(); + Symbol qualSym = qualifier.type.symbol().moduleClass(); if (! (qualifier instanceof Tree.Super || qualSym.isSubClass(funOwnerSym))) { + global.log("inserting cast from " + qualSym + " to " + funOwnerSym);//debug Type ownerTp = funOwnerSym.type(); Tree castQualifier = gen.Apply(gen.TypeApply(gen.Select(qualifier, defs.AS), diff --git a/sources/scalac/typechecker/Analyzer.java b/sources/scalac/typechecker/Analyzer.java index da24b2ea86..ee545ac7d3 100644 --- a/sources/scalac/typechecker/Analyzer.java +++ b/sources/scalac/typechecker/Analyzer.java @@ -85,7 +85,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { if (sym.pos == Position.NOPOS) { sym.setInfo(Type.ErrorType); String kind; - if (sym.name.isTermName()) kind = "module or method "; + if (sym.name.isTermName()) kind = "object or method "; else if (sym.name.isTypeName()) kind = "class "; else kind = "constructor "; throw new Type.Error("file " + unit.source + " does not define public " + @@ -213,7 +213,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { String decode(Name name) { if (name.isTypeName()) return "type " + name; else if (name.isConstrName()) return "constructor " + name; - else return name.toString(); + else return "value " + name.toString(); } /** Is `sym' accessible as a member of tree `site' in current context? @@ -318,6 +318,8 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { if ((bsym.flags & INTERFACE) != 0) error(constrs[0].pos, "superclass may not be a Java interface"); } else { + if ((bsym.flags & (JAVA | INTERFACE)) == JAVA) + error(constrs[i].pos, "Java class may not be used as mixin"); Type[] grandparents = parents[i].parents(); if (grandparents.length > 0 && !parents[0].isSubType(grandparents[0])) @@ -421,17 +423,6 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { } } - /** Check that found type conforms to required one. - */ - Type checkType(int pos, Type found, Type required) { - if (found.isSubType(required)) return found; - else { - typeError(pos, found, required); - explainTypes(found, required); - return Type.ErrorType; - } - } - /** Check that type is eta-expandable (i.e. no `def' parameters) */ void checkEtaExpandable(int pos, Type tp) { @@ -545,14 +536,21 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { Tree checkStable(Tree tree) { if (TreeInfo.isPureExpr(tree) || tree.type == Type.ErrorType) return tree; //new TextTreePrinter().print(tree).end();//DEBUG - //System.out.println(" " + tree.type);//DEBUG + //System.out.println(" " + tree.symbol() + ":" + tree.type);//DEBUG return error(tree.pos, "stable identifier required"); } - /** Check that (abstract) type can be instantiated. + /** Check that class can be instantiated. */ void checkInstantiatable(int pos, Type tp) { - error(pos, tp.symbol() + " is abstract; cannot be instantiated"); + Symbol clazz = tp.symbol(); + if (clazz.kind == CLASS) { + if ((clazz.flags & ABSTRACTCLASS) != 0) + error(pos, clazz + " is abstract, so it cannot be instantiated"); + else if (!tp.isSubType(tp.instanceType())) + error(pos, tp + " does not conform to its self-type " + + tp.instanceType() + ", so it cannot be instantiated"); + } } /** Check all members of class `clazz' for overriding conditions. @@ -851,9 +849,9 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { // Definining Symbols ------------------------------------------------------- - /** Define symbol associated with `tree' using given `context'. + /** Define symbol associated with `tree' using given `unit' and `context'. */ - void defineSym(Tree tree, Unit unit, Infer infer, Context curcontext) { + void defineSym(Tree tree, Unit unit, Context curcontext) { Unit savedUnit = this.unit; this.unit = unit; Context savedContext = this.context; @@ -878,6 +876,8 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { pushContext(tree, sym.constructor(), new Scope(context.scope)); Symbol[] tparamSyms = enterParams(tparams); Symbol[][] vparamSyms = enterParams(vparams); + if (vparamSyms.length == 0) + vparamSyms = new Symbol[][]{Symbol.EMPTY_ARRAY}; if ((mods & CASE) != 0 && vparams.length > 0) templ.body = desugarize.addCaseElements(templ.body, vparams[0]); @@ -891,7 +891,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { sym.constructor().flags |= INITIALIZED; if (tpe != Tree.Empty) - sym.setTypeOfThis(transform(tpe, TYPEmode).type); + sym.setTypeOfThis(new LazySelfType(tpe)); defineTemplate(templ, sym); owntype = templ.type; @@ -1001,7 +1001,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { void defineTemplate(Tree.Template templ, Symbol clazz) { // attribute parent constructors Tree[] constrs = transformConstrInvocations( - templ.pos, templ.parents, true, Type.AnyType); + templ.pos, templ.parents, true); Type[] parents = new Type[constrs.length]; for (int i = 0; i < parents.length; i++) @@ -1068,6 +1068,21 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { reenterParams(vparams[i]); } + /** Define self type of class or module `sym' + * associated with `tree' using given `unit' and `context'. + */ + void defineSelfType(Symbol sym, Tree tree, Unit unit, Context curcontext) { + Unit savedUnit = this.unit; + this.unit = unit; + Context savedContext = this.context; + this.context = curcontext; + + sym.setInfo(transform(tree, TYPEmode).type); + + this.unit = savedUnit; + this.context= savedContext; + } + // Attribution and Transform ------------------------------------------------- /** Attribute an identifier consisting of a simple name or an outer reference. @@ -1284,12 +1299,11 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { /** Attribute a sequence of constructor invocations. */ - Tree[] transformConstrInvocations(int pos, Tree[] constrs, - boolean delayArgs, Type pt) { + Tree[] transformConstrInvocations(int pos, Tree[] constrs, boolean delayArgs) { for (int i = 0; i < constrs.length; i++) { pushContext(constrs[i], context.owner, context.scope); context.delayArgs = delayArgs; - constrs[i] = transform(constrs[i], CONSTRmode, pt); + constrs[i] = transform(constrs[i], CONSTRmode, Type.AnyType); Symbol f = TreeInfo.methSymbol(constrs[i]); if (f != null) { Symbol c = f.primaryConstructorClass(); @@ -1306,7 +1320,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { if (global.debug) global.log("transforming " + owner);//debug //System.out.println(owner.info());//DEBUG Tree[] parents1 = transformConstrInvocations( - templ.pos, templ.parents, false, Type.AnyType); + templ.pos, templ.parents, false); if (owner.kind != ERROR) { validateParentClasses( templ.parents, owner.info().parents(), owner.typeOfThis()); @@ -1636,7 +1650,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { " does not conform to sequence " + clazz); } } else if (tree.type != Type.ErrorType) { - error(tree.pos, tree.symbol() + + error(tree.pos, tree.type.symbol() + " is neither a case class constructor nor a sequence class constructor"); } } @@ -1648,20 +1662,26 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { // check that other idents or selects are stable. switch (tree) { case Ident(Name name): - if (sym != null && isNullaryMethod(sym) && (sym.flags & CASE) != 0) { - ((Ident)tree).name = name.toTypeName(); - return transform(tree, mode, pt); - } else { + if (sym != null && isNullaryMethod(sym) && (sym.flags & CASE) != 0) + return transform( + make.Apply( + tree.pos, + copy.Ident(tree, name.toTypeName()), + Tree.EMPTY_ARRAY), + mode, pt); + else checkStable(tree); - } break; - case Select(_, Name selector): - if (sym != null && isNullaryMethod(sym) && (sym.flags & CASE) != 0) { - ((Select)tree).selector = selector.toTypeName(); - return transform(tree, mode, pt); - } else { + case Select(Tree qual, Name name): + if (sym != null && isNullaryMethod(sym) && (sym.flags & CASE) != 0) + return transform( + make.Apply( + tree.pos, + copy.Select(tree, qual, name.toTypeName()), + Tree.EMPTY_ARRAY), + mode, pt); + else checkStable(tree); - } } } } else if ((mode & EXPRmode) != 0) { @@ -1700,9 +1720,14 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { } } - if (!(tree.type instanceof Type.PolyType)) - tree.type = checkType(tree.pos, tree.type, pt); - + Type owntype = tree.type; + if ((mode & (CONSTRmode | FUNmode)) == (CONSTRmode)) + owntype = owntype.instanceType(); + if (!(owntype instanceof Type.PolyType || owntype.isSubType(pt))) { + typeError(tree.pos, owntype, pt); + explainTypes(owntype, pt); + tree.type = Type.ErrorType; + } return tree; } //where @@ -1757,6 +1782,8 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { Symbol sym = tree1.symbol(); if ((mode & FUNmode) == 0 && sym != null && sym.typeParams().length != 0) return error(tree.pos, sym + " takes type parameters."); +// else if (tree1.isType()) +// return gen.mkType(tree1.pos, tree1.type); else return tree1; } @@ -1807,12 +1834,6 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { Tree.ValDef[][] vparams1 = transform(vparams); Tree tpe1 = transform(tpe); Tree.Template templ1 = transformTemplate(templ, sym); - - if ((sym.flags & ABSTRACTCLASS) == 0 && - !sym.type().isSubType(sym.typeOfThis())) - error(sym.pos, sym + - " needs to be abstract; it does not conform to its self-type " + - sym.typeOfThis()); popContext(); return copy.ClassDef(tree, mods, name, tparams1, vparams1, tpe1, templ1) .setType(definitions.UNIT_TYPE); @@ -1954,8 +1975,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { copy.Template(templ, new Tree[]{parent1}, body) .setType(parent1.type).setSymbol(Symbol.NONE); Type owntype = parent1.type; - if ((owntype.symbol().constructor().flags & ABSTRACTCLASS) != 0) - checkInstantiatable(tree.pos, owntype); + checkInstantiatable(tree.pos, owntype); return copy.New(tree, templ1) .setType(owntype.instanceType()); } else { @@ -2078,7 +2098,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { switch (enclClazz.info()) { case CompoundType(Type[] parents, _): return copy.Super(tree, tpe1) - .setType(Type.compoundType(parents, Scope.EMPTY)); + .setType(Type.compoundType(parents, Scope.EMPTY).symbol().thisType()); case ErrorType: return tree.setType(Type.ErrorType); default: @@ -2086,7 +2106,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { } } else { return error(tree.pos, - "super can be used only in a class, module, or template"); + "super can be used only in a class, object, or template"); } case This(Tree qual): @@ -2099,16 +2119,16 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { } else { return error( tree.pos, tree + - " can be used only in a class, module, or template"); + " can be used only in a class, object, or template"); } } else { Tree qual1 = transform(qual, TYPEmode | FUNmode); - clazz = qual1.symbol(); + clazz = qual1.type.symbol(); if (clazz.kind == CLASS) { Context clazzContext = context.outerContext(clazz); if (clazzContext != Context.NONE) { if (!(qual1 instanceof Tree.Ident)) - qual1 = gen.Ident(tree.pos, qual1.symbol()); + qual1 = gen.Ident(tree.pos, clazz); tree1 = copy.This(tree, qual1); } else { return error(qual.pos, @@ -2245,20 +2265,18 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { class LazyTreeType extends Type.LazyType { Tree tree; Unit u; - Infer i; Context c; LazyTreeType(Tree tree) { this.tree = tree; this.u = unit; - this.i = infer; this.c = context; } public void complete(Symbol sym) { //System.out.println("completing " + sym);//DEBUG //if (sym.isConstructor()) sym.constructorClass().initialize(); //else if (sym.isModule()) sym.moduleClass().initialize(); - defineSym(tree, u, i, c); + defineSym(tree, u, c); } } @@ -2270,7 +2288,35 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { super(tree); } public void complete(Symbol sym) { - sym.setInfo(tree.symbol().constructor().type().instanceType()); + Type constrtype = tree.symbol().constructor().type().instanceType(); + switch (tree) { + case ClassDef(_, _, _, ValDef[][] vparams, _, _): + if (vparams.length == 0) { + constrtype = removeMethod(constrtype); + } + } + sym.setInfo(constrtype); + } + private Type removeMethod(Type tp) { + switch (tp) { + case MethodType(_, Type restp): + return restp; + case PolyType(Symbol[] tparams, Type restp): + return Type.PolyType(tparams, removeMethod(restp)); + default: + return tp; + } + } + } + + /** A lazy type for self types + */ + class LazySelfType extends LazyTreeType { + LazySelfType(Tree tree) { + super(tree); + } + public void complete(Symbol sym) { + defineSelfType(sym, tree, u, c); } } } diff --git a/sources/scalac/typechecker/DeSugarize.java b/sources/scalac/typechecker/DeSugarize.java index ae7dd9b970..91faf4adb6 100644 --- a/sources/scalac/typechecker/DeSugarize.java +++ b/sources/scalac/typechecker/DeSugarize.java @@ -164,7 +164,7 @@ public class DeSugarize implements Kinds, Modifiers { } /** (x_1: T_1, ..., x_n: T_N) => e ==> - * new scala.Function[T_1, ..., T_N, T] with { + * new new scala.Object() with scala.Function[T_1, ..., T_N, T]() { * def apply(x_1: T_1, ..., x_N: T_N): T = e * } * where T = `restpe' @@ -182,14 +182,23 @@ public class DeSugarize implements Kinds, Modifiers { for (int i = 0; i < length; i++) argtpes[i] = vparams[i].tpe; argtpes[vparams.length] = restpe; - Tree objConstr = make.Select(tree.pos, - make.Ident(tree.pos, Names.scala), - Names.Object.toConstrName()); - Tree constr = make.TypeApply(tree.pos, - make.Select(tree.pos, - make.Ident(tree.pos, Names.scala), - Name.fromString("Function" + length).toConstrName()), - argtpes); + Tree objConstr = make.Apply( + tree.pos, + make.Select( + tree.pos, + make.Ident(tree.pos, Names.scala), + Names.Object.toConstrName()), + Tree.EMPTY_ARRAY); + Tree constr = make.Apply( + tree.pos, + make.TypeApply( + tree.pos, + make.Select( + tree.pos, + make.Ident(tree.pos, Names.scala), + Name.fromString("Function" + length).toConstrName()), + argtpes), + Tree.EMPTY_ARRAY); Tree applyDef = make.DefDef( tree.pos, 0, Names.apply, @@ -225,7 +234,7 @@ public class DeSugarize implements Kinds, Modifiers { } /** Cases, Argtpe, Restpe ==> - * (new scala.PartialFunction[Argtpe, Restpe] { + * (new scala.PartialFunction[Argtpe, Restpe]() { * def apply(x: Argtpe): Restpe = x match {Cases} * def isDefinedAt(x: Argtpe): scala.Boolean = x match {Cases'} * }: scala.PartialFunction[Argtpe, +Restpe]) @@ -236,12 +245,18 @@ public class DeSugarize implements Kinds, Modifiers { * Restpe = targs[1] */ public Tree partialFunction(Tree tree, Type pattpe, Type restpe) { - Tree constr = make.TypeApply(tree.pos, - make.Select(tree.pos, - make.Ident(tree.pos, Names.scala), - Names.PartialFunction.toConstrName()), - new Tree[]{gen.mkType(tree.pos, pattpe), - gen.mkType(tree.pos, restpe)}); + Tree constr = + make.Apply( + tree.pos, + make.TypeApply( + tree.pos, + make.Select( + tree.pos, + make.Ident(tree.pos, Names.scala), + Names.PartialFunction.toConstrName()), + new Tree[]{gen.mkType(tree.pos, pattpe), + gen.mkType(tree.pos, restpe)}), + Tree.EMPTY_ARRAY); Name x = getvar(); ValDef param = (ValDef) make.ValDef( tree.pos, PARAM, x, gen.mkType(tree.pos, pattpe), Tree.Empty); @@ -547,9 +562,17 @@ public class DeSugarize implements Kinds, Modifiers { public Tree toConstructor(Tree tree, Symbol constr) { switch (tree) { case Apply(Tree fn, Tree[] args): - return copy.Apply(tree, toConstructor(fn, constr), args); + return toConstructor1(tree, constr); + default: + return make.Apply(tree.pos, toConstructor1(tree, constr), Tree.EMPTY_ARRAY); + } + } + private Tree toConstructor1(Tree tree, Symbol constr) { + switch (tree) { + case Apply(Tree fn, Tree[] args): + return copy.Apply(tree, toConstructor1(fn, constr), args); case TypeApply(Tree fn, Tree[] args): - return copy.TypeApply(tree, toConstructor(fn, constr), args); + return copy.TypeApply(tree, toConstructor1(fn, constr), args); case Ident(Name name): return copy.Ident(tree, constr.name).setSymbol(constr); case Select(Tree qual, Name name): diff --git a/sources/scalac/typechecker/RefCheck.java b/sources/scalac/typechecker/RefCheck.java index af02095030..74ab754ae0 100644 --- a/sources/scalac/typechecker/RefCheck.java +++ b/sources/scalac/typechecker/RefCheck.java @@ -3,16 +3,6 @@ ** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** ** /_____/\____/\___/\____/____/ ** \* */ - -// $Id$ - -// todo: Any cannot be inherited. -// todo: check that only stable defs override stable defs -// todo: admit vardefs w/o rhs -// ClassTemplate ::= [extends Constr {with Constr}] -// [with `(' TemplateStatSeq `)'] -// todo: pretty printer prints wrong precedence for `new' (-> lambdalift.scala). - package scalac.typechecker; import java.util.HashMap; @@ -126,6 +116,18 @@ public class RefCheck extends Transformer implements Modifiers, Kinds { return stats; } + public Tree nullTree(int pos, Type tp) { + return gen.TypeApply( + gen.Ident(pos, global.definitions.NULL), + new Tree[]{gen.mkType(pos, tp)}); + } + + private boolean isGlobalModule(Symbol sym) { + return + sym.isModule() && + (sym.owner().isPackage() || isGlobalModule(sym.owner().module())); + } + /** The main checking functions */ public Tree[] transformStat(Tree tree, int index) { @@ -133,38 +135,55 @@ public class RefCheck extends Transformer implements Modifiers, Kinds { switch (tree) { case ModuleDef(int mods, Name name, Tree tpe, Tree.Template templ): Symbol sym = tree.symbol(); - // local modules are not yet supported but the interpreter - // accepts modules at the console level - if (sym.isLocal()) unit.error("local modules are not yet supported"); - - Tree[] result = new Tree[2]; - result[0] = make.ClassDef( + Tree cdef = make.ClassDef( tree.pos, mods | FINAL | MODUL, name.toTypeName(), - new Tree.TypeDef[0], - new Tree.ValDef[][]{{}}, + Tree.ExtTypeDef.EMPTY_ARRAY, + Tree.ExtValDef.EMPTY_ARRAY_ARRAY, Tree.Empty, templ) .setSymbol(sym.moduleClass()).setType(tree.type); - result[1] = make.ValDef( + Tree alloc = gen.New( tree.pos, - mods | MODUL, - name, - (tpe == Tree.Empty) ? gen.mkType(tree.pos, sym.type()) : tpe, - gen.New( - tree.pos, - sym.type().prefix(), - sym.moduleClass(), - Tree.EMPTY_ARRAY)) - .setSymbol(sym).setType(tree.type); + sym.type().prefix(), + sym.moduleClass(), + Tree.EMPTY_ARRAY); + Tree[] result; + if (isGlobalModule(sym)) { + Tree vdef = gen.ValDef(sym, alloc); + result = new Tree[]{cdef, vdef}; + } else { + // var m$: T = null[T]; + Name varname = Name.fromString(name + "$"); + Symbol mvar = new TermSymbol( + tree.pos, varname, sym.owner(), PRIVATE | MUTABLE | SYNTHETIC) + .setInfo(sym.type()); + Tree vdef = gen.ValDef(mvar, nullTree(tree.pos, sym.type())); + + // { if (m$ == null[T]) m$ = new m$class; m$ } + Tree body = gen.Block(new Tree[]{ + gen.If( + gen.Apply( + gen.Select(gen.mkRef(tree.pos, mvar), global.definitions.EQEQ), + new Tree[]{nullTree(tree.pos, sym.type())}), + gen.Assign(gen.mkRef(tree.pos, mvar), alloc), + gen.Block(tree.pos, Tree.EMPTY_ARRAY)), + gen.mkRef(tree.pos, mvar)}); + + // def m: T = { if (m$ == null[T]) m$ = new m$class; m$ } + sym.updateInfo(Type.PolyType(Symbol.EMPTY_ARRAY, sym.type())); + sym.flags |= STABLE; + Tree ddef = gen.DefDef(sym, body); + result = new Tree[]{cdef, vdef, ddef}; + } return transform(result); case ValDef(int mods, Name name, Tree tpe, Tree rhs): Symbol sym = tree.symbol(); resultTree = transform(tree); //todo: handle variables - if (sym.isLocal() && index <= maxindex[level]) { + if (sym.isLocal() && !sym.isModule() && index <= maxindex[level]) { if (Global.instance.debug) System.out.println(refsym[level] + ":" + refsym[level].type()); unit.error( @@ -180,6 +199,7 @@ public class RefCheck extends Transformer implements Modifiers, Kinds { } public Tree transform(Tree tree) { + Tree tree1; switch (tree) { case Template(Tree[] bases, Tree[] body): Tree[] bases1 = transform(bases); @@ -188,6 +208,10 @@ public class RefCheck extends Transformer implements Modifiers, Kinds { case Block(Tree[] stats): Tree[] stats1 = transformStats(stats); return copy.Block(tree, stats1); + case This(_): + return tree; + case PackageDef(Tree pkg, Template packaged): + return copy.PackageDef(tree, pkg, super.transform(packaged)); case Ident(Name name): Scope.Entry e = scopes[level].lookupEntry(name); Symbol sym = tree.symbol(); @@ -202,10 +226,14 @@ public class RefCheck extends Transformer implements Modifiers, Kinds { maxindex[i] = symindex; } } - return tree; + tree1 = tree; + break; default: - return super.transform(tree); + tree1 = super.transform(tree); } + if (tree1.isType() && !tree1.isMissing()) + tree1 = gen.mkType(tree1.pos, tree1.type); + return tree1; } } |