diff options
-rw-r--r-- | doc/reference/reference.verb.tex | 50 | ||||
-rw-r--r-- | sources/scalac/ast/TreeInfo.java | 15 | ||||
-rw-r--r-- | sources/scalac/ast/parser/Parser.java | 30 | ||||
-rw-r--r-- | sources/scalac/symtab/Scope.java | 2 | ||||
-rw-r--r-- | sources/scalac/symtab/Symbol.java | 8 | ||||
-rw-r--r-- | sources/scalac/symtab/SymbolCloner.java | 5 | ||||
-rw-r--r-- | sources/scalac/symtab/classfile/Pickle.java | 7 | ||||
-rw-r--r-- | sources/scalac/symtab/classfile/UnPickle.java | 2 | ||||
-rw-r--r-- | sources/scalac/transformer/AddInterfacesPhase.java | 2 | ||||
-rw-r--r-- | sources/scalac/transformer/LambdaLift.java | 5 | ||||
-rw-r--r-- | sources/scalac/typechecker/Analyzer.java | 43 | ||||
-rw-r--r-- | sources/scalac/typechecker/Context.java | 4 | ||||
-rw-r--r-- | support/latex/scaladefs.sty | 2 | ||||
-rw-r--r-- | support/latex/scaladoc.sty | 21 |
14 files changed, 108 insertions, 88 deletions
diff --git a/doc/reference/reference.verb.tex b/doc/reference/reference.verb.tex index 0b1431cf83..dff170c2d7 100644 --- a/doc/reference/reference.verb.tex +++ b/doc/reference/reference.verb.tex @@ -2,7 +2,7 @@ \documentclass[11pt]{report} -\usepackage{fleqn,a4wide,modefs,math,prooftree,scaladefs,vquote} +\usepackage{fleqn,a4,modefs,math,prooftree,scaladefs,vquote} \newcommand{\ifqualified}[1]{} \newcommand{\iflet}[1]{} @@ -20,10 +20,11 @@ Martin Odersky \\ Philippe Altherr \\ Vincent Cremet \\ -Burak Emir \\ \\ -St\'ephane Micheloud +Burak Emir \\ +St\'ephane Micheloud \\ Nikolay Mihaylov \\ Michel Schinz \\ +Erik Stenman \\ Matthias Zenger \\ \ \\ @@ -3052,28 +3053,15 @@ methods can be implemented in different ways for different carrier types. As an example, an implementation of these methods for lists is given in \sref{cls-list}. -The translation scheme is by repeated applications of the following -rules, until all comprehensions have been eliminated. - -First, a definition: A pattern \verb@p@ is a {\em irrefutable} if \verb@p@ is a -variable pattern or a pattern \verb@scala.Tuple$\,n$(x$_1$, ..., x$_n$)@ where -\verb@x$_1$, ..., x$_n$@ are variable patterns. -In the following, we let \verb@p@ range over patterns, -let \verb@q@ range over refutable patterns, and -let \verb@e, f@ range over expressions. - -\begin{itemize} -\item -For a refutable pattern \verb@p@ with free variables -\verb@x$_1$, ..., x$_n$@, -the generator \verb@val p <- e@ is translated to: +The translation scheme is as follows. +In a first step, every generator \verb@val p <- e@, where \verb@p@ is not +a pattern variable, is replaced by \begin{verbatim} -val Scala.Tuple$\,n$(x$_1$, ..., x$_n$) <- - e\=.filter { case p => True case _ => False } - \>.map{ case p => Tuple$\,n$(x$_1$, ..., x$_n$) } . +val p <- e.filter { case p => true; case _ => false } \end{verbatim} -This yields a generator with an irrefutable pattern. - +Then, the following +rules are applied repeatedly until all comprehensions have been eliminated. +\begin{itemize} \item A generator \verb@q <- e@ followed by a filter \verb@f@ is translated to a single generator \verb@q <- e.filter(x$_1$, ..., x$_n$ => f)@ where @@ -3081,37 +3069,37 @@ a single generator \verb@q <- e.filter(x$_1$, ..., x$_n$ => f)@ where \item A for-comprehension -\verb@for (val q <- e) yield e'@ +\verb@for (val p <- e) yield e'@ is translated to -\verb@e.map { case q => e' }@. +\verb@e.map { case p => e' }@. \item A for-comprehension -\verb@for (val q <- e) do e'@ +\verb@for (val p <- e) do e'@ is translated to -\verb@e.foreach { case q => e' }@. +\verb@e.foreach { case p => e' }@. \item A for-comprehension \begin{verbatim} -for (val q <- e; val q' <- e' ...) yield e'' , +for (val p <- e; val p' <- e' ...) yield e'' , \end{verbatim} where \verb@...@ is a (possibly empty) sequence of generators or filters, is translated to \begin{verbatim} -e.flatmap { case q => for (val q' <- e' ...) yield e'' } . +e.flatmap { case p => for (val p' <- e' ...) yield e'' } . \end{verbatim} \item A for-comprehension \begin{verbatim} -for (val q <- e; val q' <- e' ...) do e'' . +for (val p <- e; val p' <- e' ...) do e'' . \end{verbatim} where \verb@...@ is a (possibly empty) sequence of generators or filters, is translated to \begin{verbatim} -e.foreach { case q => for (val q' <- e'...) do e'' } . +e.foreach { case p => for (val p' <- e'...) do e'' } . \end{verbatim} \end{itemize} diff --git a/sources/scalac/ast/TreeInfo.java b/sources/scalac/ast/TreeInfo.java index fc12935250..19b2341f44 100644 --- a/sources/scalac/ast/TreeInfo.java +++ b/sources/scalac/ast/TreeInfo.java @@ -127,6 +127,21 @@ public class TreeInfo { } } + /** Is tree a self constructor call? + */ + public static boolean isSelfConstrCall(Tree tree) { + switch (tree) { + case Ident(Name name): + return name == Names.CONSTRUCTOR; + case TypeApply(Tree constr, _): + return isSelfConstrCall(constr); + case Apply(Tree constr, _): + return isSelfConstrCall(constr); + default: + return false; + } + } + /** Is tree a variable pattern */ public static boolean isVarPattern(Tree pat) { diff --git a/sources/scalac/ast/parser/Parser.java b/sources/scalac/ast/parser/Parser.java index 3bcb1c4045..af165b22ea 100644 --- a/sources/scalac/ast/parser/Parser.java +++ b/sources/scalac/ast/parser/Parser.java @@ -284,20 +284,24 @@ public class Parser implements Tokens { //where Tree makeFor1(int pos, Name name, Tree pat, Tree rhs, Tree body) { - Tree cont; + return make.Apply( + pos, make.Select(pos, rhs, name), + new Tree[]{makeForCont(pos, pat, body)}); + } + Tree makeForCont(int pos, Tree pat, Tree body) { switch (pat) { case Ident(Name name1): - cont = make.Function(pos, - new Tree.ValDef[]{ - (ValDef) - make.ValDef(pat.pos, Modifiers.PARAM, name1, Tree.Empty, Tree.Empty)}, - body); - break; - default: - cont = make.Visitor(pos, new Tree.CaseDef[]{ - (CaseDef)make.CaseDef(pos, pat, Tree.Empty, body)}); + if (name1.isVariable()) + return make.Function( + pos, + new Tree.ValDef[]{ + (ValDef) make.ValDef( + pat.pos, Modifiers.PARAM, + name1, Tree.Empty, Tree.Empty)}, + body); } - return make.Apply(pos, make.Select(pos, rhs, name), new Tree[]{cont}); + return make.Visitor(pos, new Tree.CaseDef[]{ + (CaseDef)make.CaseDef(pos, pat, Tree.Empty, body)}); } Tree makeTry(int pos, Tree body, Tree catcher, Tree finalizer) { @@ -433,7 +437,7 @@ public class Parser implements Tokens { switch (fn) { case This(TypeNames.EMPTY): return make.Apply( - t.pos, make.Ident(t.pos, Names.this_.toTypeName()), args); + t.pos, make.Ident(t.pos, Names.CONSTRUCTOR), args); } } return syntaxError(t.pos, "class constructor expected", false); @@ -1729,7 +1733,7 @@ public class Parser implements Tokens { ValDef[][] vparams = new ValDef[][]{paramClause()}; accept(EQUALS); return make.DefDef( - pos, mods, Names.this_.toTypeName(), + pos, mods, Names.CONSTRUCTOR, Tree.AbsTypeDef_EMPTY_ARRAY, vparams, Tree.Empty, convertToSelfConstr(expr())); } else { diff --git a/sources/scalac/symtab/Scope.java b/sources/scalac/symtab/Scope.java index c9daf10c5a..d0a2bf5b9b 100644 --- a/sources/scalac/symtab/Scope.java +++ b/sources/scalac/symtab/Scope.java @@ -189,7 +189,7 @@ public class Scope { /** enter a symbol */ public Scope enter(Symbol sym) { - assert !sym.isConstructor(); + // assert !sym.isConstructor(); return enter(new Entry(sym, this)); } diff --git a/sources/scalac/symtab/Symbol.java b/sources/scalac/symtab/Symbol.java index 00161b7745..a98e44844d 100644 --- a/sources/scalac/symtab/Symbol.java +++ b/sources/scalac/symtab/Symbol.java @@ -60,8 +60,6 @@ public abstract class Symbol implements Modifiers, Kinds { /** Generic symbol constructor */ public Symbol(int kind, int pos, Name name, Symbol owner, int flags) { - assert (!isTerm() || !name.isTypeName()) && (!isType() || name.isTypeName()); - this.kind = kind; this.pos = pos; this.name = name; @@ -1023,6 +1021,7 @@ public class TermSymbol extends Symbol { /** Constructor */ public TermSymbol(int pos, Name name, Symbol owner, int flags) { super(VAL, pos, name, owner, flags); + assert !name.isTypeName() : this; } public static TermSymbol define( @@ -1039,7 +1038,7 @@ public class TermSymbol extends Symbol { public static TermSymbol newConstructor(Symbol clazz, int flags) { TermSymbol sym = new TermSymbol( - clazz.pos, clazz.name, clazz.owner(), flags | FINAL); + clazz.pos, Names.CONSTRUCTOR, clazz.owner(), flags | FINAL); sym.clazz = clazz; return sym; } @@ -1098,7 +1097,7 @@ public class TermSymbol extends Symbol { /** Is this symbol a constructor? */ public boolean isConstructor() { - return name.isTypeName(); + return name == Names.CONSTRUCTOR; } /** Return a fresh symbol with the same fields as this one. @@ -1155,6 +1154,7 @@ public abstract class TypeSymbol extends Symbol { /** Constructor */ public TypeSymbol(int kind, int pos, Name name, Symbol owner, int flags) { super(kind, pos, name, owner, flags); + assert name.isTypeName() : this; if (kind != TYPE) this.constructor = TermSymbol.newConstructor(this, flags & ~MODUL); } diff --git a/sources/scalac/symtab/SymbolCloner.java b/sources/scalac/symtab/SymbolCloner.java index c75958be40..8863cf24ff 100644 --- a/sources/scalac/symtab/SymbolCloner.java +++ b/sources/scalac/symtab/SymbolCloner.java @@ -85,7 +85,10 @@ public class SymbolCloner { assert !clones.containsKey(symbol) : Debug.show(symbol) + " -> " + Debug.show(clones.get(symbol)); Symbol clone = symbol.cloneSymbol(getOwnerFor(symbol)); - if (rename) clone.name = renamer.newName(symbol.name); + if (rename) { + assert !symbol.isConstructor(): symbol; + clone.name = renamer.newName(symbol.name); + } clones.put(symbol, clone); return clone; } diff --git a/sources/scalac/symtab/classfile/Pickle.java b/sources/scalac/symtab/classfile/Pickle.java index 58b2888d79..8cf0efd2de 100644 --- a/sources/scalac/symtab/classfile/Pickle.java +++ b/sources/scalac/symtab/classfile/Pickle.java @@ -80,8 +80,10 @@ public class Pickle implements Kinds, Modifiers, EntryTags { */ private boolean isLocal(Symbol sym) { return - sym.name.toTermName() == rootname && - sym.owner() == rootowner || + sym.name.toTermName() == rootname && sym.owner() == rootowner + || + sym.isConstructor() && isLocal(sym.primaryConstructorClass()) + || (sym.kind != NONE && isLocal(sym.owner())); } @@ -333,6 +335,7 @@ public class Pickle implements Kinds, Modifiers, EntryTags { } else { writeByte(EXTref); writeByte(0); // space for length + assert !sym.isConstructor() : sym; writeRef(sym.name); } if (sym.owner() != Global.instance.definitions.ROOT_CLASS) diff --git a/sources/scalac/symtab/classfile/UnPickle.java b/sources/scalac/symtab/classfile/UnPickle.java index 4e2eb566fb..2e333e5cd2 100644 --- a/sources/scalac/symtab/classfile/UnPickle.java +++ b/sources/scalac/symtab/classfile/UnPickle.java @@ -264,7 +264,7 @@ public class UnPickle implements Kinds, Modifiers, EntryTags { case VALsym: if (bp < end) { Symbol tsym = readSymbolRef(); - if (name.isTypeName()) { + if (name == Names.CONSTRUCTOR) { entries[n] = sym = tsym.primaryConstructor(); sym.flags = flags; } else { diff --git a/sources/scalac/transformer/AddInterfacesPhase.java b/sources/scalac/transformer/AddInterfacesPhase.java index 4df6c4bac7..c012f403c9 100644 --- a/sources/scalac/transformer/AddInterfacesPhase.java +++ b/sources/scalac/transformer/AddInterfacesPhase.java @@ -209,7 +209,7 @@ public class AddInterfacesPhase extends Phase { Symbol ifaceConstrSym = ifaceSym.primaryConstructor(); Symbol classConstrSym = classSym.primaryConstructor(); - classConstrSym.name = className(ifaceConstrSym.name); + // classConstrSym.name = className(ifaceConstrSym.name); Scope ifaceOwnerMembers = ifaceSym.owner().members(); ifaceOwnerMembers.enter(classSym); diff --git a/sources/scalac/transformer/LambdaLift.java b/sources/scalac/transformer/LambdaLift.java index 8651abb0c7..9384055c77 100644 --- a/sources/scalac/transformer/LambdaLift.java +++ b/sources/scalac/transformer/LambdaLift.java @@ -171,10 +171,7 @@ public class LambdaLift extends OwnerTransformer * If symbol is a class assign same name to its primary constructor. */ private void makeUnique(Symbol sym) { - Name newname = global.freshNameCreator.newName(sym.name); - sym.name = newname; - if (sym.kind == CLASS) - sym.primaryConstructor().name = newname.toTypeName(); + sym.name = global.freshNameCreator.newName(sym.name); } private Type.Map traverseTypeMap = new Type.Map() { diff --git a/sources/scalac/typechecker/Analyzer.java b/sources/scalac/typechecker/Analyzer.java index 7aeed9432d..da68b474b7 100644 --- a/sources/scalac/typechecker/Analyzer.java +++ b/sources/scalac/typechecker/Analyzer.java @@ -6,16 +6,12 @@ // $Id$ -// todo: (0) propagate target type in cast. // todo: eliminate Typed nodes. // todo: use SELECTOR flag to avoid access methods for privates // todo: use mangled name or drop. // todo: emit warnings for unchecked. // todo: synchronize on module instantiation. -// todo: implement EQ -// todo: for (Tuplen(...) <- ...) // todo: empty package -// todo: this for package? package scalac.typechecker; @@ -737,7 +733,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { case DefDef(int mods, Name name, _, _, _, _): Symbol sym; - if (name == Names.this_.toTypeName()) { + if (name == Names.CONSTRUCTOR) { Symbol clazz = context.enclClass.owner; if (!(context.tree instanceof Template) || clazz.isModuleClass() || @@ -746,7 +742,6 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { clazz.isPackage()) { error(tree.pos, "constructor definition not allowed here"); } - ((DefDef) tree).name = clazz.name; sym = context.enclClass.owner.addConstructor(); } else { sym = TermSymbol.define(tree.pos, name, owner, mods, context.scope); @@ -987,7 +982,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { Symbol[] tparamSyms; Symbol[][] vparamSyms; Type restype; - if (name.isTypeName()) { + if (name == Names.CONSTRUCTOR) { Context prevContext = context; Symbol clazz = context.enclClass.owner; context = context.enclClass.outer.outer; @@ -1804,8 +1799,8 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { case DefDef(_, Name name, Tree.AbsTypeDef[] tparams, Tree.ValDef[][] vparams, Tree tpe, Tree rhs): Context prevContext = context; - if (name.isTypeName()) { - Symbol clazz = context.enclClass.owner; + Symbol enclClass = context.enclClass.owner; + if (name == Names.CONSTRUCTOR) { context = context.enclClass.outer.outer; } pushContext(tree, sym, new Scope(context.scope)); @@ -1816,8 +1811,10 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { ? gen.mkType(tree.pos, sym.type().resultType()) : transform(tpe, TYPEmode); Tree rhs1 = rhs; - if (name.isTypeName()) + if (name == Names.CONSTRUCTOR) { + context.constructorClass = enclClass; rhs1 = transform(rhs, CONSTRmode, tpe1.type); + } else if (rhs != Tree.Empty) rhs1 = transform(rhs, EXPRmode, tpe1.type); context = prevContext; @@ -2106,6 +2103,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { mode = mode & ~SEQUENCEmode; Tree fn1; int argMode; + boolean selfcc = false; //todo: Should we pass in both cases a methodtype with // AnyType's for args as a prototype? if ((mode & EXPRmode) != 0) { @@ -2128,8 +2126,8 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { case TypeRef(Type pre, Symbol c, Type[] argtypes): if (c.kind == CLASS) { c.initialize(); - Tree fn0 = fn1; Symbol constr = c.allConstructors(); + Tree fn0 = fn1; fn1 = gen.mkRef(fn1.pos, pre, constr); switch (fn1) { case Select(Tree fn1qual, _): @@ -2151,6 +2149,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { tsym.typeParams(), fn1.type); } //System.out.println(TreeInfo.methSymbol(fn1) + ":" + tp + " --> " + fn1.type + " of " + fn1);//DEBUG + selfcc = TreeInfo.isSelfConstrCall(fn0); } else { error(tree.pos, tsym + " is not a class; cannot be instantiated"); @@ -2236,6 +2235,16 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { } } + // check that self constructors go backwards. + if (selfcc) { + Symbol constr = TreeInfo.methSymbol(fn1); + if (constr != null && constr.kind == VAL && + !(constr.type() instanceof Type.OverloadedType) && + constr.pos > tree.pos) + error(tree.pos, + "illegal forward reference to self constructor"); + } + switch (fn1.type) { case PolyType(Symbol[] tparams, Type restp): // if method is polymorphic, @@ -2307,13 +2316,11 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { tree, adapt(qual1, qualmode, Type.AnyType), name); case Ident(Name name): - if (name == Names.this_.toTypeName()) { - Tree tree1 = transform(make.Ident(tree.pos, pt.symbol().name)); - Symbol constr = tree1.symbol(); - if (constr != null && constr.kind == VAL && constr.pos > tree.pos) - error(tree.pos, - "illegal forward reference to self constructor"); - return tree1; + if (name == Names.CONSTRUCTOR) { + assert (mode & CONSTRmode) != 0 : tree; + return gen.Ident(tree.pos, context.constructorClass); + /* + */ } else if (((mode & (PATTERNmode | FUNmode)) == PATTERNmode) && name.isVariable()) { diff --git a/sources/scalac/typechecker/Context.java b/sources/scalac/typechecker/Context.java index 090f0e58fb..61bf0a8299 100644 --- a/sources/scalac/typechecker/Context.java +++ b/sources/scalac/typechecker/Context.java @@ -19,7 +19,8 @@ public class Context { Context outer; // The next outer context Context enclClass = this; // The next outer context whose tree // is a class template - int variance; // Variance relative to eclosing class. + int variance; // Variance relative to enclosing class. + Symbol constructorClass; // Class for auxiliary constructor public Context() {} @@ -36,6 +37,7 @@ public class Context { tree instanceof Tree.CompoundType) this.enclClass = this; else this.enclClass = outer.enclClass; this.variance = outer.variance; + this.constructorClass = outer.constructorClass; this.outer = outer; } diff --git a/support/latex/scaladefs.sty b/support/latex/scaladefs.sty index 578fcfa3fa..9fa86e130d 100644 --- a/support/latex/scaladefs.sty +++ b/support/latex/scaladefs.sty @@ -68,6 +68,6 @@ \newcommand{\EOL}{\la\mbox{EOL}\ra} \newcommand{\syntax}{{\bf Syntax:}} \newcommand{\todo}[1]{$\clubsuit$ {\bf #1} $\spadesuit$} -\newcommand{\Dollar}{\$}%$ +\newcommand{\Dollar}{\mbox{\$}}%$ \newcommand{\sref}[1]{\S\ref{#1}} \newcommand{\nyi}[1]{\footnote{#1 not yet implemented.}}
\ No newline at end of file diff --git a/support/latex/scaladoc.sty b/support/latex/scaladoc.sty index 6c45632aa1..2227ad1270 100644 --- a/support/latex/scaladoc.sty +++ b/support/latex/scaladoc.sty @@ -1,5 +1,5 @@ \usepackage{fourier} -\usepackage[scaled]{luximono} +\usepackage[scaled=0.8]{luximono} \usepackage{helvet} \usepackage{color} @@ -130,9 +130,7 @@ sensitive,% morecomment=[l]//,% morecomment=[s]{/*}{*/},% - morestring=[b]",% - morestring=[b]',% -}[keywords,comments,strings]% +}[keywords,comments]% % activate the language and predefine settings \lstset{ @@ -141,11 +139,11 @@ aboveskip=3mm,% belowskip=3mm,% fontadjust=true,% - columns=[c]flexible,% + columns=[c]fixed,% keepspaces=true,% - basewidth={0.5em, 0.425em},% + basewidth={0.58em, 0.53em},% tabsize=2,% - basicstyle=\small\renewcommand{\baselinestretch}{0.95}\ttfamily,% + basicstyle=\renewcommand{\baselinestretch}{0.95}\ttfamily,% commentstyle=\itshape,% keywordstyle=\bfseries,% mathescape=true,% @@ -167,7 +165,7 @@ keepspaces=true,% basewidth={0.5em, 0.425em},% tabsize=2,% - basicstyle=\small\renewcommand{\baselinestretch}{0.95}\ttfamily,% + basicstyle=\renewcommand{\baselinestretch}{0.95}\ttfamily,% commentstyle=\rm,% keywordstyle=\bfseries,% mathescape=true,% @@ -185,9 +183,12 @@ } % to define: caption, label \newcommand{\code}[1]{% - \lstinline[keywordstyle=,% + \lstinline[%keywordstyle=,% flexiblecolumns=true,% - basicstyle=\small\ttfamily]£#1£} + basicstyle=\ttfamily]£#1£} + + + \newcommand{\clearemptydoublepage}{\newpage{\pagestyle{empty}\cleardoublepage}} |