summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2003-10-24 18:15:34 +0000
committerMartin Odersky <odersky@gmail.com>2003-10-24 18:15:34 +0000
commitc3dd593e0d28458e838008c3a8311c9994f3f8a2 (patch)
tree2490ce19deb2b3ecbf30724fa11d3ff7fe3f155f
parent71d2d7d9787f1be2927a9c66dd8e78e9a9b285ea (diff)
downloadscala-c3dd593e0d28458e838008c3a8311c9994f3f8a2.tar.gz
scala-c3dd593e0d28458e838008c3a8311c9994f3f8a2.tar.bz2
scala-c3dd593e0d28458e838008c3a8311c9994f3f8a2.zip
*** empty log message ***
-rw-r--r--doc/reference/ScalaReference.tex62
-rw-r--r--sources/scalac/symtab/Type.java9
-rw-r--r--sources/scalac/transformer/AddInterfaces.java8
-rw-r--r--sources/scalac/typechecker/Analyzer.java61
-rw-r--r--sources/scalac/typechecker/Infer.java6
-rw-r--r--sources/scalac/typechecker/RefCheck.java2
6 files changed, 102 insertions, 46 deletions
diff --git a/doc/reference/ScalaReference.tex b/doc/reference/ScalaReference.tex
index 6abb8a3596..d7298ca763 100644
--- a/doc/reference/ScalaReference.tex
+++ b/doc/reference/ScalaReference.tex
@@ -91,7 +91,7 @@ Unicode encodings \lstinline@`\uXXXX'@ are also as in Java.
\section{Identifiers}
\syntax\begin{lstlisting}
-op ::= special {special} [`_' [id]]
+op ::= special {special}
varid ::= lower {letter $|$ digit} [`_' [id]]
id ::= upper {letter $|$ digit} [`_' [id]]
| varid
@@ -101,11 +101,11 @@ id ::= upper {letter $|$ digit} [`_' [id]]
There are two ways to form an identifier. First, an identifier can
start with a letter which can be followed by an arbitrary sequence of
letters and digits. Second, an identifier can be start with a special
-character followed by an arbitrary sequence of special characters.
-In both cases, the identifier prefix may be immediately followed
-by an underscore `\lstinline@_@' character and another string of characters
-that by themselves make up an identifier. As usual, a longest match
-rule applies. For instance, the string
+character followed by an arbitrary sequence of special characters. In
+the first case, the identifier prefix may be immediately followed by
+an underscore `\lstinline@_@' character and another string of
+characters that by themselves make up an identifier. As usual, a
+longest match rule applies. For instance, the string
\begin{lstlisting}
big_bob++=z3
@@ -155,7 +155,7 @@ statement.
The tokens which cannot legally start a statement
are the following delimiters and reserved words:
\begin{lstlisting}
-else extends with yield do
+catch else extends finally with yield
, . ; : = => <- <: >: # @ ) ] }
\end{lstlisting}
@@ -607,7 +607,8 @@ The base classes of an aliased type are the base classes of its alias.
\item
The base classes of an abstract type are the base classes of its upper bound.
\item
-The base classes of a parameterized type ~\lstinline@$C$[$T_1 \commadots T_n$]@~ are the base classes
+The base classes of a parameterized type
+~\lstinline@$C$[$T_1 \commadots T_n$]@~ are the base classes
of type $C$, where every occurrence of a type parameter $a_i$
of $C$ has been replaced by the corresponding parameter type $T_i$.
\item
@@ -618,6 +619,14 @@ The base classes of a compound type
~\lstinline@$T_1$ with $\ldots$ with $T_n$ with {$R\,$}@~ is the concatenation of the
base classes of all $T_i$'s, except that later base classes replace
earlier base classes which are instances of the same class.
+\item
+The base classes of a type selection \lstinline@$S$#$T$@ are
+determined as follows. If $T$ is an alias or abstract type, the
+previous clauses apply. Otherwise, $T$ must be a (possibly
+parameterized) class type, which is defined in some class $B$. Then
+the base classes of \lstinline@$S$#$T$@ are the base classes of $T$
+seen as members of $B$ from the prefix type $S$.
+
\end{itemize}
2. The notion of a type $T$
@@ -1049,7 +1058,7 @@ definition also introduce a getter function $x$ which returns the
value currently assigned to the variable, as well as a setter function
\lstinline@$x$_=@ which changes the value currently assigned to the variable.
The functions have the same signatures as for a variable declaration.
-The getter and setter functions, are then members of the template
+The getter and setter functions are then members of the template
instead of the variable accessed by them.
\example The following example shows how {\em properties} can be
@@ -2801,16 +2810,17 @@ the expression is the value of $e$ converted to type $T$.
| SimpleExpr ArgumentExpr `=' Expr
\end{lstlisting}
-An assignment to a simple variable ~\lstinline@$x$ = $e$@~ is interpreted
-depending on whether $x$ is defined in a block or in a
-template. If $x$ is a variable defined in a block, then the
-assignment changes the current value of $x$ to be the result of
-evaluating the expression $e$. The type of $e$ is expected
-to conform to the type of $x$. If $x$ is a member
-of a template, the assignment ~\lstinline@$x$ = $e$@~ is interpreted as the
-invocation ~\lstinline@$x$_=($e\,$)@~ of the setter function for variable $x$
-(\sref{sec:vardef}). Analogously, an assignment ~\lstinline@$f$.$x$ = $e$@~ to a
-field $x$ is interpreted as the invocation ~\lstinline@$f$.$x$_=($e\,$)@.
+The interpretation of assignment to a simple variable ~\lstinline@$x$
+= $e$@~ depends on the definition of $x$. If $x$ denotes a mutable
+variable, then the assignment changes the current value of $x$ to be
+the result of evaluating the expression $e$. The type of $e$ is
+expected to conform to the type of $x$. If $x$ is a parameterless
+function defined in some a template, and the same template contains a
+setter function \lstinline@$x$_=@ as member, then the assignment
+~\lstinline@$x$ = $e$@~ is interpreted as the invocation
+~\lstinline@$x$_=($e\,$)@~ of that setter function. Analogously, an
+assignment ~\lstinline@$f$.$x$ = $e$@~ to a parameterless function $x$
+is interpreted as the invocation ~\lstinline@$f$.$x$_=($e\,$)@.
An assignment ~\lstinline@$f$($\args\,$) = $e$@~ with a function application to the
left of the ``\lstinline@=@' operator is interpreted as
@@ -3608,7 +3618,7 @@ abstract class Any {
def asInstanceOf[a]: a = match {
case x: a => x
case _ => if (this eq null) this
- else else new ClassCastException().throw
+ else throw new ClassCastException()
}
/** Pattern match */
@@ -3619,6 +3629,16 @@ class AnyRef extends Any;
class Object extends AnyRef;
\end{lstlisting}
+The type cast operation \verb@asInstanceOf@ has a special meaning (not
+expressed in the code above) when its type parameter is a numeric
+type. For any type \lstinline@T <: Double@, and any numeric value
+\verb@v@ \lstinline@v.asInstanceIf[T]@ converts \code{v} to type
+\code{T} using the rules of Java's numeric type cast operation. The
+conversion might truncate the numeric value (as when going from
+\code{Long} to \code{Int} or from \code{Int} to \code{Byte}) or it
+might lose precision (as when going from \code{Double} to \code{Float}
+or when converting between \code{Long} and \code{Float}).
+
\section{Value Classes}
\label{sec:cls-value}
@@ -4109,7 +4129,7 @@ form.
digit ::= `0' | $\ldots$ | `9'
special ::= $\mbox{\rm\em ``all other characters except parentheses ([{}]) and periods''}$
- op ::= special {special} [`_' [id]]
+ op ::= special {special}
varid ::= lower {letter | digit} [`_' [id]]
id ::= upper {letter | digit} [`_' [id]]
| varid
diff --git a/sources/scalac/symtab/Type.java b/sources/scalac/symtab/Type.java
index 9af1ea5244..578aeb3451 100644
--- a/sources/scalac/symtab/Type.java
+++ b/sources/scalac/symtab/Type.java
@@ -1139,6 +1139,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
}
Type toPrefix(Symbol sym, Type pre, Symbol clazz) {
+ //System.out.println(this + ".toPrefix(" + sym + "," + pre + "," + clazz + ")");//DEBUG
if (pre == NoType || clazz.kind != CLASS)
return this;
else if (sym.isSubClass(clazz) &&
@@ -1795,6 +1796,14 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
if (alttypes[i].isSubType(that)) return true;
}
break;
+
+ case CompoundType(Type[] parts, Scope members):
+ int i = 0;
+ while (i < parts.length) {
+ if (parts[i].isSubType(that)) return true;
+ i++;
+ }
+ break;
}
switch (that) {
diff --git a/sources/scalac/transformer/AddInterfaces.java b/sources/scalac/transformer/AddInterfaces.java
index 497b7a4feb..46650b7a2a 100644
--- a/sources/scalac/transformer/AddInterfaces.java
+++ b/sources/scalac/transformer/AddInterfaces.java
@@ -240,7 +240,13 @@ class AddInterfaces extends Transformer {
case New(Template templ): {
Tree.New newTree = (Tree.New)super.transform(tree);
- Symbol ifaceSym = newTree.type.unalias().symbol();
+ Type tp = newTree.type;
+ switch (tp) {
+ case CompoundType(Type[] parts, _): tp = parts[0];
+ // gross hack to prevent crashing when selftypes are compound;
+ // should be fixed!
+ }
+ Symbol ifaceSym = tp.unalias().symbol();
if (phase.needInterface(ifaceSym)) {
Map clsMap = new HashMap();
Symbol classSym = phase.getClassSymbol(ifaceSym);
diff --git a/sources/scalac/typechecker/Analyzer.java b/sources/scalac/typechecker/Analyzer.java
index 595f1e462c..9797825f8e 100644
--- a/sources/scalac/typechecker/Analyzer.java
+++ b/sources/scalac/typechecker/Analyzer.java
@@ -606,6 +606,14 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
else throw new ApplicationError();
}
+ private boolean isSetterMethod(Symbol sym) {
+ return sym != null &&
+ !sym.isLocal() &&
+ !sym.isStable() &&
+ sym.type() instanceof Type.PolyType &&
+ sym.typeParams().length == 0;
+ }
+
// Contexts -------------------------------------------------------------------
/** Push new context associated with given tree, owner, and scope on stack.
@@ -661,11 +669,13 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
/** A lazy type for self types
*/
class LazySelfType extends LazyTreeType {
- LazySelfType(Tree tree) {
+ Symbol clazz;
+ LazySelfType(Symbol clazz, Tree tree) {
super(tree);
+ this.clazz = clazz;
}
public void complete(Symbol sym) {
- defineSelfType(sym, tree, u, c);
+ defineSelfType(sym, clazz, tree, u, c);
}
}
@@ -1004,7 +1014,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
sym.primaryConstructor().flags |= INITIALIZED;
if (tpe != Tree.Empty)
- sym.setTypeOfThis(new LazySelfType(tpe));
+ sym.setTypeOfThis(new LazySelfType(sym, tpe));
defineTemplate(templ, sym, new Scope());
owntype = templ.type;
@@ -1017,7 +1027,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
clazz.setInfo(templ.type);
((ModuleDef) tree).tpe = tpe = transform(tpe, TYPEmode);
if (tpe != Tree.Empty)
- clazz.setTypeOfThis(new LazySelfType(tpe));
+ clazz.setTypeOfThis(new LazySelfType(sym, tpe));
owntype = (tpe == Tree.Empty) ? clazz.type() : tpe.type;
break;
@@ -1171,13 +1181,17 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
/** 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) {
+ void defineSelfType(Symbol sym, Symbol clazz, 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);
+ Type selftype = transform(tree, TYPEmode).type;
+
+ sym.setInfo(
+ Type.compoundType(
+ new Type[]{selftype, clazz.type()}, Scope.EMPTY));
this.unit = savedUnit;
this.context= savedContext;
@@ -1352,18 +1366,20 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
owntype.isSubType(pt))) {
switch (tree) {
case Literal(Object value):
- if (value instanceof Integer) {
- int n = ((Integer) value).intValue();
- if (pt.symbol() == definitions.BYTE_CLASS &&
- -128 <= n && n <= 127)
- return copy.Literal(tree, new Byte((byte) n)).setType(pt);
- else if (pt.symbol() == definitions.SHORT_CLASS &&
- -32768 <= n && n <= 32767)
- return copy.Literal(tree, new Short((short) n)).setType(pt);
- else if (pt.symbol() == definitions.CHAR_CLASS &&
- 0 <= n && n <= 65535)
- return copy.Literal(tree, new Character((char) n)).setType(pt);
- }
+ int n = Integer.MAX_VALUE;
+ if (value instanceof Integer)
+ n = ((Integer) value).intValue();
+ else if (value instanceof Character)
+ n = ((Character) value).charValue();
+ if (pt.symbol() == definitions.BYTE_CLASS &&
+ -128 <= n && n <= 127)
+ return copy.Literal(tree, new Byte((byte) n)).setType(pt);
+ else if (pt.symbol() == definitions.SHORT_CLASS &&
+ -32768 <= n && n <= 32767)
+ return copy.Literal(tree, new Short((short) n)).setType(pt);
+ else if (pt.symbol() == definitions.CHAR_CLASS &&
+ 0 <= n && n <= 65535)
+ return copy.Literal(tree, new Character((char) n)).setType(pt);
}
typeError(tree.pos, owntype, pt);
Type.explainTypes(owntype, pt);
@@ -2039,14 +2055,15 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
case Assign(Tree lhs, Tree rhs):
Tree lhs1 = transform(lhs, EXPRmode);
Symbol varsym = lhs1.symbol();
- if (varsym != null && (varsym.flags & ACCESSOR) != 0) {
+ if (isSetterMethod(varsym)) {
+ // todo: change this to require setters in same template
return transform(desugarize.Assign(tree.pos, lhs, rhs));
- } else if (varsym == null || (varsym.flags & MUTABLE) == 0) {
- return error(tree.pos, "assignment to non-variable");
- } else {
+ } else if (varsym != null && (varsym.flags & MUTABLE) != 0) {
Tree rhs1 = transform(rhs, EXPRmode, lhs1.type);
return copy.Assign(tree, lhs1, rhs1)
.setType(definitions.UNIT_TYPE);
+ } else {
+ return error(tree.pos, "assignment to non-variable");
}
case If(Tree cond, Tree thenp, Tree elsep):
diff --git a/sources/scalac/typechecker/Infer.java b/sources/scalac/typechecker/Infer.java
index befd1d151c..b23890f0d0 100644
--- a/sources/scalac/typechecker/Infer.java
+++ b/sources/scalac/typechecker/Infer.java
@@ -958,7 +958,9 @@ public class Infer implements Modifiers, Kinds {
* If several applicable alternatives exist, take the
* most specialized one, or throw an error if no
* most specialized applicable alternative exists.
- * If no alternative matches, leave `tree' unchanged.
+ * If no alternative matches, leave `tree' unchanged,
+ * try to select method with pt = AnyType.
+ * If pt is AnyType, leave tree unchanged.
*/
public void methodAlternative(Tree tree, Symbol[] alts, Type[] alttypes,
Type[] argtypes, Type pt)
@@ -988,6 +990,8 @@ public class Infer implements Modifiers, Kinds {
}
}
tree.setSymbol(alts[best]).setType(alttypes[best]);
+ } else if (pt != Type.AnyType) {
+ methodAlternative(tree, alts, alttypes, argtypes, Type.AnyType);
}
}
diff --git a/sources/scalac/typechecker/RefCheck.java b/sources/scalac/typechecker/RefCheck.java
index d6ff53bb84..1f4b75ed09 100644
--- a/sources/scalac/typechecker/RefCheck.java
+++ b/sources/scalac/typechecker/RefCheck.java
@@ -92,7 +92,7 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
sym.overriddenSymbol(parents[0]).kind == NONE) {
unit.error(sym.pos,
sym + " does not override a superclass member in " +
- parents[0]);
+ parents);
}
}
}