summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/reference/reference.verb.tex50
-rw-r--r--sources/scalac/ast/TreeInfo.java15
-rw-r--r--sources/scalac/ast/parser/Parser.java30
-rw-r--r--sources/scalac/symtab/Scope.java2
-rw-r--r--sources/scalac/symtab/Symbol.java8
-rw-r--r--sources/scalac/symtab/SymbolCloner.java5
-rw-r--r--sources/scalac/symtab/classfile/Pickle.java7
-rw-r--r--sources/scalac/symtab/classfile/UnPickle.java2
-rw-r--r--sources/scalac/transformer/AddInterfacesPhase.java2
-rw-r--r--sources/scalac/transformer/LambdaLift.java5
-rw-r--r--sources/scalac/typechecker/Analyzer.java43
-rw-r--r--sources/scalac/typechecker/Context.java4
-rw-r--r--support/latex/scaladefs.sty2
-rw-r--r--support/latex/scaladoc.sty21
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}}