*** empty log message ***
git-svn-id: http://lampsvn.epfl.ch/svn-repos/scala/scala/trunk@3244 5e8d7ff9-d8ef-0310-90f0-a4852d11357a
This commit is contained in:
parent
3b72eb5544
commit
9fb513dafd
|
@ -201,20 +201,19 @@ Of course, a compiler is free (if it is moderately smart, even expected)
|
||||||
to recognize the special case of calling the \code{+} method over
|
to recognize the special case of calling the \code{+} method over
|
||||||
integer arguments and to generate efficient inline code for it.
|
integer arguments and to generate efficient inline code for it.
|
||||||
|
|
||||||
Control constructs such as \code{while} are also not primitive but are
|
For efficiency and better error diagnostics the \code{while} loop is a
|
||||||
predefined functions in the standard Scala library. Here is the
|
primitive construct in Scala. But in principle, it could have just as
|
||||||
definition of \code{while} in Scala.
|
well been a predefined function. Here is a possible implementation of it:
|
||||||
\begin{lstlisting}
|
\begin{lstlisting}
|
||||||
def while (def p: boolean) (def s: unit): unit =
|
def While (def p: boolean) (def s: unit): unit =
|
||||||
if (p) { s ; while(p)(s) }
|
if (p) { s ; While(p)(s) }
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
The \code{while} function takes as first parameter a test function,
|
The \code{While} function takes as first parameter a test function,
|
||||||
which takes no parameters and yields a boolean value. As second
|
which takes no parameters and yields a boolean value. As second
|
||||||
parameter it takes a command function which also takes no parameters
|
parameter it takes a command function which also takes no parameters
|
||||||
and yields a trivial result. \code{while} invokes the command function
|
and yields a trivial result. \code{While} invokes the command function
|
||||||
as long as the test function yields true. Again, compilers are free to
|
as long as the test function yields true.
|
||||||
pick specialized implementations of \code{while} that have the same
|
|
||||||
behavior as the invocation of the function given above.
|
|
||||||
|
|
||||||
\chapter{Programming with Actors and Messages}
|
\chapter{Programming with Actors and Messages}
|
||||||
\label{chap:example-auction}
|
\label{chap:example-auction}
|
||||||
|
@ -260,7 +259,7 @@ are defined in Figure~\ref{fig:simple-auction-msgs}.
|
||||||
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 timeToShutdown = 36000000; // msec
|
||||||
val bidIncrement = 10;
|
val bidIncrement = 10;
|
||||||
def run() = {
|
override def run() = {
|
||||||
var maxBid = minBid - bidIncrement;
|
var maxBid = minBid - bidIncrement;
|
||||||
var maxBidder: Actor = _;
|
var maxBidder: Actor = _;
|
||||||
var running = true;
|
var running = true;
|
||||||
|
@ -6546,7 +6545,7 @@ messages. A {\em message} in this context is an arbitrary object.
|
||||||
There is a special message \code{TIMEOUT} which is used to signal a
|
There is a special message \code{TIMEOUT} which is used to signal a
|
||||||
time-out.
|
time-out.
|
||||||
\begin{lstlisting}
|
\begin{lstlisting}
|
||||||
case class TIMEOUT;
|
case object TIMEOUT;
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
Mailboxes implement the following signature.
|
Mailboxes implement the following signature.
|
||||||
\begin{lstlisting}
|
\begin{lstlisting}
|
||||||
|
@ -6737,7 +6736,7 @@ class Auction(seller: Process, minBid: int, closing: Date)
|
||||||
val delta = 10 // bid increment
|
val delta = 10 // bid increment
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
\begin{lstlisting}
|
\begin{lstlisting}
|
||||||
def run = {
|
override def run = {
|
||||||
var askedBid = minBid
|
var askedBid = minBid
|
||||||
var maxBidder: Process = null
|
var maxBidder: Process = null
|
||||||
while (true) {
|
while (true) {
|
||||||
|
@ -6850,7 +6849,7 @@ class Bidder (auction: Process, minBid: int, maxBid: int)
|
||||||
}
|
}
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
\begin{lstlisting}
|
\begin{lstlisting}
|
||||||
def run = {
|
override def run = {
|
||||||
getAuctionStatus
|
getAuctionStatus
|
||||||
if (nextBid != Unknown) bid
|
if (nextBid != Unknown) bid
|
||||||
}
|
}
|
||||||
|
|
|
@ -762,12 +762,12 @@ transitive relation that satisfies the following conditions.
|
||||||
binding of $x$ in $T$ subsuming it, then $T$ conforms to the
|
binding of $x$ in $T$ subsuming it, then $T$ conforms to the
|
||||||
compound type ~\lstinline@$T_1$ with $\ldots$ with $T_n$ {$R\,$}@.
|
compound type ~\lstinline@$T_1$ with $\ldots$ with $T_n$ {$R\,$}@.
|
||||||
\item If
|
\item If
|
||||||
$T'_i$ conforms to $T_i$ for $i = 1 \commadots n$ and $U$ conforms to $U'$
|
$T_i \equiv T'_i$ for $i = 1 \commadots n$ and $U$ conforms to $U'$
|
||||||
then the method type $(T_1 \commadots T_n) U$ conforms to
|
then the method type $(T_1 \commadots T_n) U$ conforms to
|
||||||
$(T'_1 \commadots T'_n) U'$.
|
$(T'_1 \commadots T'_n) U'$.
|
||||||
\item If, assuming
|
\item If, assuming
|
||||||
$L'_1 \conforms a_1 \conforms U'_1 \commadots L'_n \conforms a_n \conforms U'_n$
|
$L'_1 \conforms a_1 \conforms U'_1 \commadots L'_n \conforms a_n \conforms U'_n$
|
||||||
one has $L_i \conforms L'_i$ and $U'_i \conforms U_i$
|
one has $L'_i \equiv L'_i$ and $U_i \equiv U'_i$
|
||||||
for $i = 1 \commadots n$, as well as $T \conforms T'$ then the polymorphic type
|
for $i = 1 \commadots n$, as well as $T \conforms T'$ then the polymorphic type
|
||||||
$[a_1 >: L_1 <: U_1 \commadots a_n >: L_n <: U_n] T$ conforms to the polymorphic type
|
$[a_1 >: L_1 <: U_1 \commadots a_n >: L_n <: U_n] T$ conforms to the polymorphic type
|
||||||
$[a_1 >: L'_1 <: U'_1 \commadots a_n >: L'_n <: U'_n] T'$.
|
$[a_1 >: L'_1 <: U'_1 \commadots a_n >: L'_n <: U'_n] T'$.
|
||||||
|
@ -3776,7 +3776,9 @@ inserted by the compiler.
|
||||||
A view definition is a normal function definition with one value
|
A view definition is a normal function definition with one value
|
||||||
parameter where the name of the defined function is \code{view}.
|
parameter where the name of the defined function is \code{view}.
|
||||||
|
|
||||||
\example
|
\example
|
||||||
|
The following defines an implicit coercion function from strings to lists of
|
||||||
|
characters.
|
||||||
|
|
||||||
\begin{lstlisting}
|
\begin{lstlisting}
|
||||||
def view(xs: String): List[char] =
|
def view(xs: String): List[char] =
|
||||||
|
@ -3784,9 +3786,6 @@ def view(xs: String): List[char] =
|
||||||
else xs.charAt(0) :: xs.substring(1);
|
else xs.charAt(0) :: xs.substring(1);
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
|
|
||||||
This defines an implicit coercion function from strings to lists of
|
|
||||||
characters.
|
|
||||||
|
|
||||||
\section{View Application}
|
\section{View Application}
|
||||||
|
|
||||||
View applications are inserted implicitly in two situations.
|
View applications are inserted implicitly in two situations.
|
||||||
|
@ -3814,7 +3813,7 @@ Searching a view which is applicable to an expression $e$ of type $T$
|
||||||
is a three-step process.
|
is a three-step process.
|
||||||
\begin{enumerate}
|
\begin{enumerate}
|
||||||
\item
|
\item
|
||||||
First, the set $\VV$ of available views is determined. $\VV$ is the
|
First, the set $\AA$ of available views is determined. $\AA$ is the
|
||||||
smallest set such that:
|
smallest set such that:
|
||||||
\begin{enumerate}
|
\begin{enumerate}
|
||||||
\item
|
\item
|
||||||
|
@ -3849,7 +3848,7 @@ further view conversion of $e$ to the view's formal parameter type.
|
||||||
Likewise, a view's result type must conform to a given prototype
|
Likewise, a view's result type must conform to a given prototype
|
||||||
directly, no second view conversion is allowed.
|
directly, no second view conversion is allowed.
|
||||||
\item
|
\item
|
||||||
It is an error is the set of applicable views $\BB$ is empty. For
|
It is an error if the set of applicable views $\BB$ is empty. For
|
||||||
non-empty $\BB$, the view method which is most specific
|
non-empty $\BB$, the view method which is most specific
|
||||||
(\sref{sec:overloaded-refs}) in $\BB$ is selected. It is an error if
|
(\sref{sec:overloaded-refs}) in $\BB$ is selected. It is an error if
|
||||||
no most specific view exists, or if it is not unique.
|
no most specific view exists, or if it is not unique.
|
||||||
|
@ -3920,16 +3919,16 @@ Implicit view parameters of a method or class are then taken as
|
||||||
available view methods in its body.
|
available view methods in its body.
|
||||||
|
|
||||||
\example Consider the following definition of a trait
|
\example Consider the following definition of a trait
|
||||||
\code{Comparable} and a view from strings to that trait..
|
\code{Comparable} and a view from strings to that trait.
|
||||||
|
|
||||||
\begin{lstlisting}
|
\begin{lstlisting}
|
||||||
trait Comparable[a] {
|
trait Comparable[a] {
|
||||||
def less (x: a): boolean
|
def less(x: a): boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
object StringsAreComparable {
|
object StringsAreComparable {
|
||||||
def view(x: String): Comparable[String] = new Comparable[String] {
|
def view(x: String): Comparable[String] = new Comparable[String] {
|
||||||
def less (y: String) = x.compareTo(y) < 0
|
def less(y: String) = x.compareTo(y) < 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
|
@ -4039,7 +4038,7 @@ allows the definition of conditional views.
|
||||||
list element type is also comparable.
|
list element type is also comparable.
|
||||||
|
|
||||||
\begin{lstlisting}
|
\begin{lstlisting}
|
||||||
def view[a <% Comparable[a]](x: List[a]): Comparable[List[a]] =
|
def view[a <% Comparable[a]](xs: List[a]): Comparable[List[a]] =
|
||||||
new Comparable[List[a]] {
|
new Comparable[List[a]] {
|
||||||
def less (ys: List[a]): boolean =
|
def less (ys: List[a]): boolean =
|
||||||
!ys.isEmpty
|
!ys.isEmpty
|
||||||
|
@ -4057,6 +4056,7 @@ type parameters are translated to implicit \code{view} arguments. In
|
||||||
this case, the \code{view} method over lists would receive the
|
this case, the \code{view} method over lists would receive the
|
||||||
\code{view} method over list elements as implicit parameter.
|
\code{view} method over list elements as implicit parameter.
|
||||||
|
|
||||||
|
\comment{
|
||||||
This opens up the risk of infinite instantiations because view methods
|
This opens up the risk of infinite instantiations because view methods
|
||||||
are be passed to themselves as parameters. For instance, one might try
|
are be passed to themselves as parameters. For instance, one might try
|
||||||
to define the following ``magic'' universal converter:
|
to define the following ``magic'' universal converter:
|
||||||
|
@ -4086,6 +4086,7 @@ argument, either directly or indirectly. On the other hand,
|
||||||
contractive view methods may be passed to themselves as arguments. In the
|
contractive view methods may be passed to themselves as arguments. In the
|
||||||
examples above this case arises if a list of lists of strings is seen
|
examples above this case arises if a list of lists of strings is seen
|
||||||
as a \code{Comparable}.
|
as a \code{Comparable}.
|
||||||
|
}
|
||||||
|
|
||||||
\chapter{Top-Level Definitions}
|
\chapter{Top-Level Definitions}
|
||||||
\label{sec:topdefs}
|
\label{sec:topdefs}
|
||||||
|
|
|
@ -942,18 +942,6 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
|
||||||
val info = new LazyTreeType(tree);
|
val info = new LazyTreeType(tree);
|
||||||
clazz.setInfo(info);
|
clazz.setInfo(info);
|
||||||
modul.setInfo(info);
|
modul.setInfo(info);
|
||||||
// !!! Unfortunately, this breaks separate compilation
|
|
||||||
// val lclass = modul.linkedClass();
|
|
||||||
// // Taken from SymbolLoader.initializeRoot()
|
|
||||||
// if (lclass != null) {
|
|
||||||
// if (lclass.rawInfo().isInstanceOf[SymbolLoader] &&
|
|
||||||
// !lclass.rawInfo().isInstanceOf[SourceCompleter]) {
|
|
||||||
// lclass.setInfo(Type.ErrorType);
|
|
||||||
// //val allConstr = lclass.allConstructors();
|
|
||||||
// //allConstr.setInfo(Type.ErrorType);
|
|
||||||
// //allConstr.flags = allConstr.flags | Modifiers.PRIVATE;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
enterSym(tree, modul)
|
enterSym(tree, modul)
|
||||||
|
|
||||||
|
@ -1077,6 +1065,22 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
def addOverloaded(tp: Type, sym: Symbol): Type = {
|
||||||
|
if (!sym.isPrivate()) {
|
||||||
|
val owner = sym.owner();
|
||||||
|
if (owner.kind == CLASS) {
|
||||||
|
for (p <- sym.owner().info.parents()) {
|
||||||
|
val sym1 = p.lookupNonPrivate(sym.name);
|
||||||
|
if (sym1.kind != NONE) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// Definining Symbols -------------------------------------------------------
|
// Definining Symbols -------------------------------------------------------
|
||||||
|
|
||||||
/** Define symbol associated with `tree' using given `unit' and `context'.
|
/** Define symbol associated with `tree' using given `unit' and `context'.
|
||||||
|
@ -1176,6 +1180,7 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
|
||||||
|
|
||||||
owntype = makeMethodType(tparamSyms, vparamSyms, restype);
|
owntype = makeMethodType(tparamSyms, vparamSyms, restype);
|
||||||
//System.out.println("methtype " + name + ":" + owntype);//DEBUG
|
//System.out.println("methtype " + name + ":" + owntype);//DEBUG
|
||||||
|
sym.addInheritedOverloaded(owntype);
|
||||||
|
|
||||||
case Tree$ValDef(mods, name, _tpe, _rhs) =>
|
case Tree$ValDef(mods, name, _tpe, _rhs) =>
|
||||||
var tpe = _tpe;
|
var tpe = _tpe;
|
||||||
|
@ -1207,6 +1212,7 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
|
||||||
owntype = owntype.deconst();
|
owntype = owntype.deconst();
|
||||||
}
|
}
|
||||||
popContext();
|
popContext();
|
||||||
|
sym.addInheritedOverloaded(owntype);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Tree$AliasTypeDef(mods, name, tparams, _rhs) =>
|
case Tree$AliasTypeDef(mods, name, tparams, _rhs) =>
|
||||||
|
@ -1931,6 +1937,13 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
|
||||||
popContext();
|
popContext();
|
||||||
val templ1: Tree$Template = copy.Template(templ, parents, body1);
|
val templ1: Tree$Template = copy.Template(templ, parents, body1);
|
||||||
templ1.setType(owner.getType());
|
templ1.setType(owner.getType());
|
||||||
|
// initialize all members; necessary to initialize overloaded symbols
|
||||||
|
val members = owner.members().iterator(false);
|
||||||
|
while (members.hasNext()) {
|
||||||
|
val sym = members.next();
|
||||||
|
sym.initialize();
|
||||||
|
//System.out.println(owner.toString() + " defines " + sym + ":" + sym.getType());//DEBUG
|
||||||
|
}
|
||||||
templ1
|
templ1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2199,7 +2212,22 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
|
||||||
val templ1: Tree$Template = transformTemplate(templ, sym.moduleClass());
|
val templ1: Tree$Template = transformTemplate(templ, sym.moduleClass());
|
||||||
if (tpe1 != Tree.Empty && !templ1.getType().isSubType(tpe1.getType()))
|
if (tpe1 != Tree.Empty && !templ1.getType().isSubType(tpe1.getType()))
|
||||||
error(tree.pos, "" + sym + " does not implement " + tpe1.getType());
|
error(tree.pos, "" + sym + " does not implement " + tpe1.getType());
|
||||||
copy.ModuleDef(tree, sym, tpe1, templ1)
|
|
||||||
|
/*
|
||||||
|
// !!! Unfortunately, this breaks separate compilation
|
||||||
|
val lclass = sym.linkedClass();
|
||||||
|
// Taken from SymbolLoader.initializeRoot()
|
||||||
|
if (lclass != null) {
|
||||||
|
if (lclass.rawInfo().isInstanceOf[SymbolLoader]) {
|
||||||
|
lclass.setInfo(Type.ErrorType);
|
||||||
|
val allConstr = lclass.allConstructors();
|
||||||
|
allConstr.setInfo(Type.ErrorType);
|
||||||
|
allConstr.flags = allConstr.flags | Modifiers.PRIVATE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
copy.ModuleDef(tree, sym, tpe, templ1)
|
||||||
.setType(Type.NoType);
|
.setType(Type.NoType);
|
||||||
|
|
||||||
case Tree$DefDef(_, name, tparams, vparams, tpe, rhs) =>
|
case Tree$DefDef(_, name, tparams, vparams, tpe, rhs) =>
|
||||||
|
|
|
@ -391,7 +391,7 @@ class Infer(global: scalac_Global, gen: TreeGen, make: TreeFactory) extends scal
|
||||||
gen.mkNullLit(pos)
|
gen.mkNullLit(pos)
|
||||||
} else {
|
} else {
|
||||||
val v = bestView(vargs(0), vargs(1), Names.EMPTY);
|
val v = bestView(vargs(0), vargs(1), Names.EMPTY);
|
||||||
if (v != null) {
|
if (v != null && !v.locked) {
|
||||||
if (v.locked) {
|
if (v.locked) {
|
||||||
error(pos, "recursive view instantiation of non-contractive " +
|
error(pos, "recursive view instantiation of non-contractive " +
|
||||||
v.sym + v.sym.locationString() + " with type " +
|
v.sym + v.sym.locationString() + " with type " +
|
||||||
|
@ -802,7 +802,9 @@ class Infer(global: scalac_Global, gen: TreeGen, make: TreeFactory) extends scal
|
||||||
while (!viewMeths.isEmpty &&
|
while (!viewMeths.isEmpty &&
|
||||||
!isApplicable(viewMeths.head.symtype, argtypes, pt, Names.EMPTY, false))
|
!isApplicable(viewMeths.head.symtype, argtypes, pt, Names.EMPTY, false))
|
||||||
viewMeths = viewMeths.tail;
|
viewMeths = viewMeths.tail;
|
||||||
if (!viewMeths.isEmpty) true
|
if (!viewMeths.isEmpty) {
|
||||||
|
true
|
||||||
|
}
|
||||||
// todo: remove
|
// todo: remove
|
||||||
else {
|
else {
|
||||||
val coerceMeth: Symbol = tp1.lookup(Names.coerce);
|
val coerceMeth: Symbol = tp1.lookup(Names.coerce);
|
||||||
|
|
|
@ -41,7 +41,7 @@ public interface Modifiers {
|
||||||
|
|
||||||
int PACKAGE = 0x00100000; // symbol is a java package.
|
int PACKAGE = 0x00100000; // symbol is a java package.
|
||||||
int STABLE = 0x00800000; // functions that are assumed to be stable
|
int STABLE = 0x00800000; // functions that are assumed to be stable
|
||||||
// (typically, access methods for valdefs)
|
// (typically, access methods for valdefs)
|
||||||
|
|
||||||
int CAPTURED = 0x01000000; // variables is accessed from
|
int CAPTURED = 0x01000000; // variables is accessed from
|
||||||
// nested function. Set by LambdaLift
|
// nested function. Set by LambdaLift
|
||||||
|
|
|
@ -1067,7 +1067,7 @@ public abstract class Symbol implements Modifiers, Kinds {
|
||||||
String name1 = name.toString();
|
String name1 = name.toString();
|
||||||
if (name1.endsWith(Names._EQ.toString()))
|
if (name1.endsWith(Names._EQ.toString()))
|
||||||
name1 = name1.substring(0, name1.length() - Names._EQ.length());
|
name1 = name1.substring(0, name1.length() - Names._EQ.length());
|
||||||
return owner.info().lookup(Name.fromString(name1 + "$"));
|
return owner.lookup(Name.fromString(name1 + "$"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The members of this class or module symbol
|
/** The members of this class or module symbol
|
||||||
|
@ -1503,10 +1503,15 @@ public abstract class Symbol implements Modifiers, Kinds {
|
||||||
public Symbol overloadWith(Symbol that) {
|
public Symbol overloadWith(Symbol that) {
|
||||||
assert isTerm() : Debug.show(this);
|
assert isTerm() : Debug.show(this);
|
||||||
assert this.name == that.name : Debug.show(this) + " <> " + Debug.show(that);
|
assert this.name == that.name : Debug.show(this) + " <> " + Debug.show(that);
|
||||||
assert this.owner == that.owner : Debug.show(this) + " != " + Debug.show(that);
|
//assert this.owner == that.owner : Debug.show(this) + " != " + Debug.show(that);
|
||||||
assert this.isConstructor() == that.isConstructor();
|
assert this.isConstructor() == that.isConstructor();
|
||||||
int overflags = (this.flags & that.flags & (JAVA | ACCESSFLAGS | DEFERRED | PARAM | SYNTHETIC)) |
|
int overflags;
|
||||||
((this.flags | that.flags) & ACCESSOR);
|
//if (this.owner == that.owner)
|
||||||
|
overflags = (this.flags & that.flags &
|
||||||
|
(JAVA | ACCESSFLAGS | DEFERRED | PARAM | SYNTHETIC)) |
|
||||||
|
((this.flags | that.flags) & ACCESSOR);
|
||||||
|
// else // it's an inherited overloaded alternative
|
||||||
|
// overflags = this.flags & SOURCEFLAGS;
|
||||||
Symbol overloaded = (this.isConstructor())
|
Symbol overloaded = (this.isConstructor())
|
||||||
? this.constructorClass().newConstructor(this.constructorClass().pos, overflags)
|
? this.constructorClass().newConstructor(this.constructorClass().pos, overflags)
|
||||||
: owner.newTerm(pos, overflags, name, 0);
|
: owner.newTerm(pos, overflags, name, 0);
|
||||||
|
@ -1638,6 +1643,62 @@ public abstract class Symbol implements Modifiers, Kinds {
|
||||||
public int tag() {
|
public int tag() {
|
||||||
return name.toString().hashCode();
|
return name.toString().hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addInheritedOverloaded(Type owntype) {
|
||||||
|
if (false && owner().kind == CLASS && !isConstructor() && owner().lookup(name) == this) {
|
||||||
|
// it's a class member which is not an overloaded alternative
|
||||||
|
Symbol sym = Type.lookupNonPrivate(owner().parents(), name);
|
||||||
|
if (sym.kind == VAL) {
|
||||||
|
Type symtype = owner.thisType().memberType(sym);
|
||||||
|
switch (symtype) {
|
||||||
|
case OverloadedType(Symbol[] alts, Type[] alttypes):
|
||||||
|
for (int i = 0; i < alts.length; i++)
|
||||||
|
addInheritedOverloaded(owntype, alts[i], alttypes[i]);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
addInheritedOverloaded(owntype, sym, symtype);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addInheritedOverloaded(Type owntype, Symbol sym, Type symtype) {
|
||||||
|
if (!owntype.overrides(symtype)) {
|
||||||
|
System.out.println(owner() + " inherits overloaded: " + sym + ":" + symtype + sym.locationString());//debug
|
||||||
|
owner().members().lookupEntry(name).setSymbol(overloadWith(sym));
|
||||||
|
//System.out.println("type is now: " + owner().members().lookup(name).type());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type removeInheritedOverloaded(Type owntype) {
|
||||||
|
//assert name != Names.toString ||
|
||||||
|
// Global.instance.currentPhase.id != Global.instance.PHASE.UNCURRY.id();
|
||||||
|
switch (owntype) {
|
||||||
|
case OverloadedType(Symbol[] alts, Type[] alttypes):
|
||||||
|
int n = 0;
|
||||||
|
for (int i = 0; i < alts.length; i++)
|
||||||
|
if (alts[i].owner() == owner()) n++;
|
||||||
|
if (n < alts.length) {
|
||||||
|
Symbol[] alts1 = new Symbol[n];
|
||||||
|
Type[] alttypes1 = new Type[n];
|
||||||
|
int j = 0;
|
||||||
|
for (int i = 0; i < alts.length; i++) {
|
||||||
|
if (alts[i].owner() == owner()) {
|
||||||
|
alts1[j] = alts[i];
|
||||||
|
alttypes1[j] = alttypes[i];
|
||||||
|
j++;
|
||||||
|
} else {
|
||||||
|
System.out.println("removing inherited alternatve " + alts[i] + ":" + alttypes[i]);//debug
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Type.OverloadedType(alts1, alttypes1);
|
||||||
|
} else {
|
||||||
|
return owntype;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return owntype;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A class for term symbols
|
/** A class for term symbols
|
||||||
|
|
|
@ -197,7 +197,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Type typeRef(Type pre, Symbol sym, Type[] args) {
|
public static Type typeRef(Type pre, Symbol sym, Type[] args) {
|
||||||
if (!pre.isLegalPrefix() && !pre.isError())
|
if (sym.kind == TYPE && !pre.isLegalPrefix() && !pre.isError())
|
||||||
throw new Type.Malformed(pre, sym.nameString());
|
throw new Type.Malformed(pre, sym.nameString());
|
||||||
rebind:
|
rebind:
|
||||||
if (sym.isAbstractType()) {
|
if (sym.isAbstractType()) {
|
||||||
|
@ -225,7 +225,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
|
||||||
return new ExtTypeRef(pre, sym, args);
|
return new ExtTypeRef(pre, sym, args);
|
||||||
}
|
}
|
||||||
private static boolean isLegalTypeRef(Type pre, Symbol sym, Type[] args) {
|
private static boolean isLegalTypeRef(Type pre, Symbol sym, Type[] args) {
|
||||||
if (!pre.isLegalPrefix() && !pre.isError()) return false;
|
if (sym.kind == TYPE && !pre.isLegalPrefix() && !pre.isError()) return false;
|
||||||
if (!sym.isType() && !sym.isError()) return false;
|
if (!sym.isType() && !sym.isError()) return false;
|
||||||
// !!! return args.length == 0 || args.length == sym.typeParams().length;
|
// !!! return args.length == 0 || args.length == sym.typeParams().length;
|
||||||
return true;
|
return true;
|
||||||
|
@ -687,9 +687,12 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
|
||||||
return true;
|
return true;
|
||||||
case TypeRef(_, Symbol sym, _):
|
case TypeRef(_, Symbol sym, _):
|
||||||
if (sym.isParameter() && sym.isSynthetic()) return true;
|
if (sym.isParameter() && sym.isSynthetic()) return true;
|
||||||
|
return false;
|
||||||
|
/*
|
||||||
return sym.kind == CLASS &&
|
return sym.kind == CLASS &&
|
||||||
((sym.flags & JAVA) != 0 ||
|
((sym.flags & JAVA) != 0 ||
|
||||||
(sym.flags & (TRAIT | ABSTRACT)) == 0);
|
(sym.flags & (TRAIT | ABSTRACT)) == 0);
|
||||||
|
*/
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -806,33 +809,34 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
|
||||||
return sym.info().lookupNonPrivate(name);
|
return sym.info().lookupNonPrivate(name);
|
||||||
case CompoundType(Type[] parts, Scope members):
|
case CompoundType(Type[] parts, Scope members):
|
||||||
Symbol sym = members.lookup(name);
|
Symbol sym = members.lookup(name);
|
||||||
if (sym.kind != NONE && (sym.flags & PRIVATE) == 0)
|
if (sym.kind != NONE && (sym.flags & PRIVATE) == 0) return sym;
|
||||||
return sym;
|
else return lookupNonPrivate(parts, name);
|
||||||
|
|
||||||
// search base types in reverse; non-abstract members
|
|
||||||
// take precedence over abstract ones.
|
|
||||||
int i = parts.length;
|
|
||||||
sym = Symbol.NONE;
|
|
||||||
while (i > 0) {
|
|
||||||
i--;
|
|
||||||
Symbol sym1 = parts[i].lookupNonPrivate(name);
|
|
||||||
if (sym1.kind != NONE &&
|
|
||||||
(sym1.flags & PRIVATE) == 0 &&
|
|
||||||
(sym.kind == NONE
|
|
||||||
||
|
|
||||||
(sym.flags & DEFERRED) != 0 &&
|
|
||||||
(sym1.flags & DEFERRED) == 0
|
|
||||||
||
|
|
||||||
(sym.flags & DEFERRED) == (sym1.flags & DEFERRED) &&
|
|
||||||
sym1.owner().isSubClass(sym.owner())))
|
|
||||||
sym = sym1;
|
|
||||||
}
|
|
||||||
return sym;
|
|
||||||
default:
|
default:
|
||||||
return Symbol.NONE;
|
return Symbol.NONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Symbol lookupNonPrivate(Type[] parts, Name name) {
|
||||||
|
// search base types in reverse; non-abstract members
|
||||||
|
// take precedence over abstract ones.
|
||||||
|
int i = parts.length;
|
||||||
|
Symbol sym = Symbol.NONE;
|
||||||
|
while (i > 0) {
|
||||||
|
i--;
|
||||||
|
Symbol sym1 = parts[i].lookupNonPrivate(name);
|
||||||
|
if (sym1.kind != NONE &&
|
||||||
|
(sym.kind == NONE
|
||||||
|
||
|
||||||
|
(sym.flags & DEFERRED) != 0 &&
|
||||||
|
(sym1.flags & DEFERRED) == 0
|
||||||
|
||
|
||||||
|
(sym.flags & DEFERRED) == (sym1.flags & DEFERRED) &&
|
||||||
|
sym1.owner().isSubClass(sym.owner())))
|
||||||
|
sym = sym1;
|
||||||
|
}
|
||||||
|
return sym;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Looks up in the current type a symbol with the same name as the
|
* Looks up in the current type a symbol with the same name as the
|
||||||
* given symbol and whose type (as seen from the given prefix) is
|
* given symbol and whose type (as seen from the given prefix) is
|
||||||
|
@ -2342,6 +2346,55 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Does this type match type `tp', so that corresponding symbols with
|
||||||
|
* the two types would be taken to override each other?
|
||||||
|
*/
|
||||||
|
public boolean overrides(Type tp) {
|
||||||
|
switch (this) {
|
||||||
|
case OverloadedType(Symbol[] alts, Type[] alttypes):
|
||||||
|
for (int i = 0; i < alttypes.length; i++) {
|
||||||
|
if (alttypes[i].overrides(tp)) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
switch (tp) {
|
||||||
|
case MethodType(Symbol[] ps1, Type res1):
|
||||||
|
switch (this) {
|
||||||
|
case MethodType(Symbol[] ps, Type res):
|
||||||
|
if (ps.length != ps1.length) return false;
|
||||||
|
for (int i = 0; i < ps.length; i++) {
|
||||||
|
Symbol p1 = ps1[i];
|
||||||
|
Symbol p = ps[i];
|
||||||
|
if (!p1.type().isSameAs(p.type()) ||
|
||||||
|
(p1.flags & (DEF | REPEATED)) != (p.flags & (DEF | REPEATED)))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return res.overrides(res1);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
|
||||||
|
case PolyType(Symbol[] ps1, Type res1):
|
||||||
|
switch (this) {
|
||||||
|
case PolyType(Symbol[] ps, Type res):
|
||||||
|
if (ps.length != ps1.length) return false;
|
||||||
|
for (int i = 0; i < ps.length; i++)
|
||||||
|
if (!ps1[i].info().subst(ps1, ps).isSameAs(ps[i].info()) ||
|
||||||
|
!ps[i].loBound().isSameAs(ps1[i].loBound().subst(ps1, ps)) ||
|
||||||
|
!ps[i].vuBound().isSameAs(ps1[i].vuBound().subst(ps1, ps)))
|
||||||
|
return false;
|
||||||
|
return res.overrides(res1.subst(ps1, ps));
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
|
||||||
|
case OverloadedType(_, _):
|
||||||
|
throw new ApplicationError("overrides inapplicable for " + tp);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Closures and Least Upper Bounds ---------------------------------------------------
|
// Closures and Least Upper Bounds ---------------------------------------------------
|
||||||
|
|
||||||
/** The closure of this type, i.e. the widened type itself followed by all
|
/** The closure of this type, i.e. the widened type itself followed by all
|
||||||
|
|
|
@ -226,6 +226,7 @@ public class ClassfileParser implements ClassfileConstants {
|
||||||
symbol = owner.newTerm(Position.NOPOS, sflags, name);
|
symbol = owner.newTerm(Position.NOPOS, sflags, name);
|
||||||
}
|
}
|
||||||
setParamOwners(type, symbol);
|
setParamOwners(type, symbol);
|
||||||
|
symbol.addInheritedOverloaded(type);
|
||||||
symbol.setInfo(type);
|
symbol.setInfo(type);
|
||||||
attrib.readAttributes(symbol, type, METH_ATTR);
|
attrib.readAttributes(symbol, type, METH_ATTR);
|
||||||
if (name != CONSTR_N) {
|
if (name != CONSTR_N) {
|
||||||
|
|
|
@ -138,7 +138,7 @@ public class Pickle implements Kinds, Modifiers, EntryTags {
|
||||||
putSymbol(it.next());
|
putSymbol(it.next());
|
||||||
break;
|
break;
|
||||||
case VAL:
|
case VAL:
|
||||||
putType(sym.info());
|
putType(sym.removeInheritedOverloaded(sym.info()));
|
||||||
if (sym.isConstructor() &&
|
if (sym.isConstructor() &&
|
||||||
sym == sym.constructorClass().allConstructors())
|
sym == sym.constructorClass().allConstructors())
|
||||||
putSymbol(sym.constructorClass());
|
putSymbol(sym.constructorClass());
|
||||||
|
@ -358,7 +358,7 @@ public class Pickle implements Kinds, Modifiers, EntryTags {
|
||||||
writeRef(sym.allConstructors());
|
writeRef(sym.allConstructors());
|
||||||
break;
|
break;
|
||||||
case VAL:
|
case VAL:
|
||||||
writeRef(sym.info());
|
writeRef(sym.removeInheritedOverloaded(sym.info()));
|
||||||
if (sym.isConstructor() &&
|
if (sym.isConstructor() &&
|
||||||
sym == sym.constructorClass().allConstructors())
|
sym == sym.constructorClass().allConstructors())
|
||||||
writeRef(sym.constructorClass());
|
writeRef(sym.constructorClass());
|
||||||
|
|
|
@ -306,7 +306,9 @@ public class UnPickle implements Kinds, Modifiers, EntryTags, TypeTags {
|
||||||
Symbol clasz = readSymbolRef();
|
Symbol clasz = readSymbolRef();
|
||||||
assert clasz == sym.moduleClass(): Debug.show(sym);
|
assert clasz == sym.moduleClass(): Debug.show(sym);
|
||||||
}
|
}
|
||||||
sym.setInfo(getType(inforef, sym));
|
Type owntype = getType(inforef, sym);
|
||||||
|
sym.addInheritedOverloaded(owntype);
|
||||||
|
sym.setInfo(owntype);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -222,15 +222,21 @@ public class AddInterfaces extends GenTransformer {
|
||||||
/**
|
/**
|
||||||
* Returns the tree of the given class whose body is built by
|
* Returns the tree of the given class whose body is built by
|
||||||
* adding to the given body the class members. Non-abstract
|
* adding to the given body the class members. Non-abstract
|
||||||
* methods are removed from the given method map. All other
|
* methods are removed from the ngiven method map. All other
|
||||||
* members are generated from their symbol.
|
* members are generated from their symbol.
|
||||||
*/
|
*/
|
||||||
private Tree getClassTree(Symbol clasz, TreeList body, Map methods) {
|
private Tree getClassTree(Symbol clasz, TreeList body, Map methods) {
|
||||||
Scope members = clasz.nextInfo().members();
|
Scope members = clasz.nextInfo().members();
|
||||||
|
/*
|
||||||
|
for (Scope.SymbolIterator i = members.iterator(false); i.hasNext(); ) {
|
||||||
|
Symbol sym = i.next();
|
||||||
|
System.out.println(clasz + " defines " + sym + ":" + sym.getType());
|
||||||
|
}
|
||||||
|
*/
|
||||||
for (Scope.SymbolIterator i = members.iterator(true); i.hasNext(); ) {
|
for (Scope.SymbolIterator i = members.iterator(true); i.hasNext(); ) {
|
||||||
Symbol member = i.next();
|
Symbol member = i.next();
|
||||||
if (!member.isTerm()) continue;
|
if (!member.isTerm()) continue;
|
||||||
body.append(getMemberTree(member, methods));
|
body.append(getMemberTree(clasz, member, methods));
|
||||||
}
|
}
|
||||||
return gen.ClassDef(clasz, body.toArray());
|
return gen.ClassDef(clasz, body.toArray());
|
||||||
}
|
}
|
||||||
|
@ -240,11 +246,11 @@ public class AddInterfaces extends GenTransformer {
|
||||||
* removed from the given method map. All other members are
|
* removed from the given method map. All other members are
|
||||||
* generated from their symbol.
|
* generated from their symbol.
|
||||||
*/
|
*/
|
||||||
private Tree getMemberTree(Symbol member, Map methods) {
|
private Tree getMemberTree(Symbol clasz, Symbol member, Map methods) {
|
||||||
if (!member.isMethod()) return gen.ValDef(member, Tree.Empty);
|
if (!member.isMethod()) return gen.ValDef(member, Tree.Empty);
|
||||||
if (member.isDeferred()) return gen.DefDef(member, Tree.Empty);
|
if (member.isDeferred()) return gen.DefDef(member, Tree.Empty);
|
||||||
Tree method = (Tree)methods.remove(member);
|
Tree method = (Tree)methods.remove(member);
|
||||||
assert method != null: Debug.show(member);
|
assert method != null: Debug.show(clasz + "." + member + ":" + member.info() + member.locationString());
|
||||||
return method;
|
return method;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -113,7 +113,14 @@ public class UnCurry extends OwnerTransformer
|
||||||
System.out.flush();
|
System.out.flush();
|
||||||
//uncurry type and symbol
|
//uncurry type and symbol
|
||||||
Type prevtype = tree.type;
|
Type prevtype = tree.type;
|
||||||
if (prevtype != null) tree.type = descr.uncurry(prevtype);
|
if (prevtype != null) {
|
||||||
|
switch (prevtype) {
|
||||||
|
case OverloadedType(_, _):
|
||||||
|
assert tree.symbol() != null;
|
||||||
|
prevtype = tree.symbol().removeInheritedOverloaded(prevtype);
|
||||||
|
}
|
||||||
|
tree.type = descr.uncurry(prevtype);
|
||||||
|
}
|
||||||
switch (tree) {
|
switch (tree) {
|
||||||
case ClassDef(_, _, AbsTypeDef[] tparams, ValDef[][] vparams, Tree tpe, Template impl):
|
case ClassDef(_, _, AbsTypeDef[] tparams, ValDef[][] vparams, Tree tpe, Template impl):
|
||||||
return copy.ClassDef(
|
return copy.ClassDef(
|
||||||
|
|
|
@ -30,7 +30,7 @@ public class UnCurryPhase extends Phase implements Modifiers {
|
||||||
* - if symbol is a def parameter with transformed type T, return () => T
|
* - if symbol is a def parameter with transformed type T, return () => T
|
||||||
*/
|
*/
|
||||||
public Type transformInfo(Symbol sym, Type tp0) {
|
public Type transformInfo(Symbol sym, Type tp0) {
|
||||||
Type tp1 = uncurry(tp0);
|
Type tp1 = uncurry(sym.removeInheritedOverloaded(tp0));
|
||||||
if (sym.isDefParameter()) return global.definitions.FUNCTION_TYPE(Type.EMPTY_ARRAY, tp1);
|
if (sym.isDefParameter()) return global.definitions.FUNCTION_TYPE(Type.EMPTY_ARRAY, tp1);
|
||||||
else return tp1;
|
else return tp1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,9 +76,12 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
|
||||||
void checkAllOverrides(int pos, Symbol clazz) {
|
void checkAllOverrides(int pos, Symbol clazz) {
|
||||||
Type[] closure = clazz.closure();
|
Type[] closure = clazz.closure();
|
||||||
for (int i = 0; i < closure.length; i++) {
|
for (int i = 0; i < closure.length; i++) {
|
||||||
for (Scope.SymbolIterator it = closure[i].members().iterator(true);
|
Type basetype = closure[i];
|
||||||
|
Symbol baseclazz = basetype.symbol();
|
||||||
|
for (Scope.SymbolIterator it = basetype.members().iterator(true);
|
||||||
it.hasNext();) {
|
it.hasNext();) {
|
||||||
checkOverride(pos, clazz, it.next());
|
Symbol sym = it.next();
|
||||||
|
if (sym.owner() == baseclazz) checkOverride(pos, clazz, sym);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,12 +89,12 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
|
||||||
for (Scope.SymbolIterator it = clazz.members().iterator(true);
|
for (Scope.SymbolIterator it = clazz.members().iterator(true);
|
||||||
it.hasNext();) {
|
it.hasNext();) {
|
||||||
Symbol sym = it.next();
|
Symbol sym = it.next();
|
||||||
if ((sym.flags & OVERRIDE) != 0) {
|
if ((sym.flags & OVERRIDE) != 0 && sym.owner() == clazz) {
|
||||||
int i = parents.length - 1;
|
int i = parents.length - 1;
|
||||||
while (i >= 0 && sym.overriddenSymbol(parents[i]).kind == NONE)
|
while (i >= 0 && sym.overriddenSymbol(parents[i]).kind == NONE)
|
||||||
i--;
|
i--;
|
||||||
if (i < 0) {
|
if (i < 0) {
|
||||||
unit.error(sym.pos, sym + " overrides nothing");
|
unit.error(sym.pos, sym + ":" + sym.type() + sym.locationString() + " overrides nothing");//debug
|
||||||
sym.flags &= ~OVERRIDE;
|
sym.flags &= ~OVERRIDE;
|
||||||
} else if (sym.isAbstractOverride() &&
|
} else if (sym.isAbstractOverride() &&
|
||||||
sym.overriddenSymbol(parents[0]).kind == NONE) {
|
sym.overriddenSymbol(parents[0]).kind == NONE) {
|
||||||
|
@ -117,7 +120,8 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
|
||||||
switch (member1.info()) {
|
switch (member1.info()) {
|
||||||
case OverloadedType(Symbol[] alts, _):
|
case OverloadedType(Symbol[] alts, _):
|
||||||
for (int i = 0; i < alts.length; i++) {
|
for (int i = 0; i < alts.length; i++) {
|
||||||
if (normalizedInfo(self, alts[i]).isSubType(template)) {
|
if (normalizedInfo(self, alts[i]).isSubType(template) &&
|
||||||
|
alts[i].owner() == clazz) {
|
||||||
if (member == other)
|
if (member == other)
|
||||||
member = alts[i];
|
member = alts[i];
|
||||||
else
|
else
|
||||||
|
|
|
@ -27,9 +27,8 @@ public class RefCheckPhase extends Phase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Type transformInfo(Symbol sym, Type tp) {
|
public Type transformInfo(Symbol sym, Type tp) {
|
||||||
if (sym.isModule() && !sym.isStatic()) {
|
if (sym.isModule() && !sym.isStatic())
|
||||||
return Type.PolyType(Symbol.EMPTY_ARRAY, tp);
|
return Type.PolyType(Symbol.EMPTY_ARRAY, tp);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
return tp;
|
return tp;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
bug96.scala:5: method foo overrides nothing
|
bug96.scala:5: method foo:(def scala.Any)java.lang.Object in class B overrides nothing
|
||||||
override def foo(def x: Any): Object = null;
|
override def foo(def x: Any): Object = null;
|
||||||
^
|
^
|
||||||
one error found
|
one error found
|
||||||
|
|
Loading…
Reference in New Issue