summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2003-10-30 14:59:42 +0000
committerMartin Odersky <odersky@gmail.com>2003-10-30 14:59:42 +0000
commitd23d0a9c737c6350b3f00a555a3ec61fff8d92dc (patch)
tree7c6a3649edf42fceb39087c97eeae9f760a8503f
parent4764fc555502237fc7f423af4200520a975a69fd (diff)
downloadscala-d23d0a9c737c6350b3f00a555a3ec61fff8d92dc.tar.gz
scala-d23d0a9c737c6350b3f00a555a3ec61fff8d92dc.tar.bz2
scala-d23d0a9c737c6350b3f00a555a3ec61fff8d92dc.zip
*** empty log message ***
-rw-r--r--config/list/compiler.lst1
-rw-r--r--doc/reference/ScalaReference.tex38
-rw-r--r--sources/examples/auction.scala6
-rw-r--r--sources/scalac/ast/TreeGen.java2
-rw-r--r--sources/scalac/symtab/EntryTags.java75
-rw-r--r--sources/scalac/symtab/Symbol.java7
-rw-r--r--sources/scalac/symtab/SymbolTablePrinter.java3
-rw-r--r--sources/scalac/symtab/Type.java145
-rw-r--r--sources/scalac/symtab/classfile/Pickle.java62
-rw-r--r--sources/scalac/symtab/classfile/UnPickle.java54
-rw-r--r--sources/scalac/transformer/Erasure.java3
-rw-r--r--sources/scalac/transformer/UnCurry.java3
-rw-r--r--sources/scalac/transformer/UnCurryPhase.java6
-rw-r--r--sources/scalac/typechecker/Analyzer.java91
-rw-r--r--sources/scalac/typechecker/Infer.java3
-rw-r--r--sources/scalac/typechecker/RefCheck.java6
16 files changed, 404 insertions, 101 deletions
diff --git a/config/list/compiler.lst b/config/list/compiler.lst
index 4702e62f3b..de796bb41d 100644
--- a/config/list/compiler.lst
+++ b/config/list/compiler.lst
@@ -129,6 +129,7 @@ transformer/matching/WordAutomInScala.java
typechecker/Analyzer.java
typechecker/AnalyzerPhase.java
+typechecker/ConstantFolder.java
typechecker/Context.java
typechecker/DeSugarize.java
typechecker/ImportList.java
diff --git a/doc/reference/ScalaReference.tex b/doc/reference/ScalaReference.tex
index 63be10f36d..fa8045290b 100644
--- a/doc/reference/ScalaReference.tex
+++ b/doc/reference/ScalaReference.tex
@@ -166,11 +166,6 @@ floating point numbers (of types \code{Float} and \code{Double}), characters, an
strings. The syntax of these literals is in each case as in Java.
\syntax\begin{lstlisting}
-literal ::= intLit
- | floatLit
- | charLit
- | stringLit
- | symbolLit
intLit ::= $\mbox{\rm\em ``as in Java''}$
floatLit ::= $\mbox{\rm\em ``as in Java''}$
charLit ::= $\mbox{\rm\em ``as in Java''}$
@@ -2237,7 +2232,7 @@ module FileSystem with {
InfixExpr ::= PrefixExpr
| InfixExpr id InfixExpr
PrefixExpr ::= [`-' | `+' | `~' | `!'] SimpleExpr
- SimpleExpr ::= literal
+ SimpleExpr ::= Literal
| Path
| `(' [Expr] `)'
| BlockExpr
@@ -2265,12 +2260,15 @@ $T$.
\section{Literals}
\syntax\begin{lstlisting}
- SimpleExpr ::= literal
- literal ::= intLit
+ SimpleExpr ::= Literal
+ Literal ::= intLit
| floatLit
| charLit
| stringLit
| symbolLit
+ | true
+ | false
+ | null
\end{lstlisting}
Typing and evaluation of numeric, character, and string literals are
@@ -2290,20 +2288,20 @@ actual parameters, as in ~\lstinline@'$x$($\args\,$)@, then the whole expression
is taken to be a shorthand for
~\lstinline@scala.Labelled(scala.Symbol("$x$"), $\args\,$)@.
-\section{Boolean constants}
+\subsection{Boolean constants}
\begin{lstlisting}
- SimpleExpr ::= true | false
+ Literal ::= true | false
\end{lstlisting}
The boolean truth values are denoted by the reserved words \code{true}
and \code{false}. The type of these expressions is \code{boolean}, and
their evaluation is immediate.
-\section{The $\NULL$ Reference}
+\subsection{The $\NULL$ Reference}
\syntax\begin{lstlisting}
- SimpleExpr ::= null
+ Literal ::= null
\end{lstlisting}
The \code{null} expression is of type \lstinline@scala.AllRef@. It
@@ -3280,7 +3278,7 @@ Pattern2 ::= SimplePattern [ '*' |'?' | '+' ]
| SimplePattern { id SimplePattern }
SimplePattern ::= varid [ '@' SimplePattern ]
| `_'
- | literal
+ | Literal
| StableId [ `(' [Patterns] `)' ]
| `(' Patterns `)'
|
@@ -4149,11 +4147,14 @@ The context-free syntax of Scala is given by the following EBNF
grammar.
\begin{lstlisting}
- literal ::= intLit
+ Literal ::= intLit
| floatLit
| charLit
| stringLit
| symbolLit
+ | true
+ | false
+ | null
StableId ::= id
| Path `.' id
@@ -4178,7 +4179,7 @@ grammar.
|
Exprs ::= Expr {`,' Expr}
- Expr ::= [Bindings `=>'] Expr
+ Expr ::= Bindings `=>' Expr
| if `(' Expr `)' Expr [[`;'] else Expr]
| try `{' block `}' [catch Expr] [finally Expr]
| do Expr [`;'] while `(' Expr ')'
@@ -4192,10 +4193,7 @@ grammar.
InfixExpr ::= PrefixExpr
| InfixExpr id InfixExpr
PrefixExpr ::= [`-' | `+' | `~' | `!'] SimpleExpr
- SimpleExpr ::= literal
- | true
- | false
- | null
+ SimpleExpr ::= Literal
| Path
| `(' [Expr] `)'
| BlockExpr
@@ -4234,7 +4232,7 @@ grammar.
| SimplePattern { id SimplePattern }
SimplePattern ::= `_'
| varid
- | literal
+ | Literal
| StableId [ `(' [Patterns] `)' ]
| `(' [Patterns] `)'
Patterns ::= Pattern {`,' Pattern}
diff --git a/sources/examples/auction.scala b/sources/examples/auction.scala
index 8e32831942..ecf121ef7d 100644
--- a/sources/examples/auction.scala
+++ b/sources/examples/auction.scala
@@ -3,6 +3,10 @@ package examples;
import java.util.Date;
import scala.concurrent._;
+/** A simple demonstrator program implementing an online auction service
+ * The example uses the actor abstraction defined in the API of
+ * package scala.concurrent.
+ */
trait AuctionMessage;
case class
Offer(bid: int, client: Actor), // make a bid
@@ -62,7 +66,7 @@ class Auction(seller: Actor, minBid: int, closing: Date) extends Actor {
}
}
-////////////////////////// TEST /////////////////////////////////
+// ---- Test -------------------------------------------------------------
object testAuction {
diff --git a/sources/scalac/ast/TreeGen.java b/sources/scalac/ast/TreeGen.java
index ebb6f29a61..c1e838f250 100644
--- a/sources/scalac/ast/TreeGen.java
+++ b/sources/scalac/ast/TreeGen.java
@@ -282,7 +282,7 @@ public class TreeGen implements Kinds, Modifiers, TypeTags {
Tree id = mkRef(pos, pre1, sym);
switch (sym.type()) {
case MethodType(Symbol[] params, _):
- assert params.length == 0 : sym;
+ assert params.length == 0 : pre;
id = this.Apply(id, Tree.EMPTY_ARRAY);
}
return id;
diff --git a/sources/scalac/symtab/EntryTags.java b/sources/scalac/symtab/EntryTags.java
index 71df3f73ff..ade0cb60bd 100644
--- a/sources/scalac/symtab/EntryTags.java
+++ b/sources/scalac/symtab/EntryTags.java
@@ -15,24 +15,27 @@ public interface EntryTags {
* Symtab = nentries_Nat {Entry}
* Entry = 1 TERMNAME len_Nat NameInfo
* | 2 TYPENAME len_Nat NameInfo
- * | 3 NONEsym len_Nat
- * | 4 TYPEsym len_Nat SymbolInfo lobound_Ref
- * | 5 ALIASsym len_Nat SymbolInfo constrsym_Ref
- * | 6 CLASSsym len_Nat SymbolInfo thistype_Ref constrsym_Ref
- * | 7 VALsym len_Nat SymbolInfo [classsym_Ref]
- * | 8 EXTref len_Nat name_Ref [owner_Ref]
- * | 9 EXTMODCLASSref len_Nat name_Ref [owner_Ref]
- * | 10 NOtpe len_Nat
- * | 11 THIStpe len_Nat sym_Ref
- * | 12 SINGLEtpe len_Nat type_Ref sym_Ref
- * | 13 TYPEREFtpe len_Nat type_Ref sym_Ref {targ_Ref}
- * | 14 COMPOUNDtpe len_Nat classsym_Ref {tpe_Ref}
- * | 15 METHODtpe len_Nat tpe_Ref {tpe_Ref}
- * | 16 POLYTtpe len_Nat tpe_Ref {sym_Ref}
- * | 17 OVERLOADEDtpe len_Nat {sym_Ref} {tpe_Ref}
- * | 20 FLAGGEDtpe len_Nat flags_Nat tpe_Ref
+ * | 3 NUMBER lenNat NumInfo
+ * | 4 NONEsym len_Nat
+ * | 5 TYPEsym len_Nat SymbolInfo lobound_Ref
+ * | 6 ALIASsym len_Nat SymbolInfo constrsym_Ref
+ * | 7 CLASSsym len_Nat SymbolInfo thistype_Ref constrsym_Ref
+ * | 8 VALsym len_Nat SymbolInfo [classsym_Ref]
+ * | 9 EXTref len_Nat name_Ref [owner_Ref]
+ * | 10 EXTMODCLASSref len_Nat name_Ref [owner_Ref]
+ * | 11 NOtpe len_Nat
+ * | 12 THIStpe len_Nat sym_Ref
+ * | 13 SINGLEtpe len_Nat type_Ref sym_Ref
+ * | 14 CONSTANTtpe len_Nat type_Ref value_Ref
+ * | 15 TYPEREFtpe len_Nat type_Ref sym_Ref {targ_Ref}
+ * | 16 COMPOUNDtpe len_Nat classsym_Ref {tpe_Ref}
+ * | 17 METHODtpe len_Nat tpe_Ref {tpe_Ref}
+ * | 18 POLYTtpe len_Nat tpe_Ref {sym_Ref}
+ * | 19 OVERLOADEDtpe len_Nat {sym_Ref} {tpe_Ref}
+ * | 22 FLAGGEDtpe len_Nat flags_Nat tpe_Ref
* SymbolInfo = name_Ref owner_Ref flags_Nat info_Ref
* NameInfo = <character sequence of length len_Nat in Utf8 format>
+ * NumInfo = <len_Nat-byte signed number in big endian format>
* Ref = Nat
*
* len is remaining length after `len'.
@@ -40,25 +43,27 @@ public interface EntryTags {
int TERMname = 1,
TYPEname = 2,
- NONEsym = 3,
- TYPEsym = 4,
- ALIASsym = 5,
- CLASSsym = 6,
- VALsym = 7,
- EXTref = 8,
- EXTMODCLASSref = 9,
- NOtpe = 10,
- THIStpe = 11,
- SINGLEtpe = 12,
- TYPEREFtpe = 13,
- COMPOUNDtpe = 14,
- METHODtpe = 15,
- POLYtpe = 16,
- OVERLOADEDtpe = 17,
- UNBOXEDtpe = 18,
- UNBOXEDARRAYtpe = 19,
- FLAGGEDtpe = 20,
- ERRORtpe = 21;
+ NUMBER = 3,
+ NONEsym = 4,
+ TYPEsym = 5,
+ ALIASsym = 6,
+ CLASSsym = 7,
+ VALsym = 8,
+ EXTref = 9,
+ EXTMODCLASSref = 10,
+ NOtpe = 11,
+ THIStpe = 12,
+ SINGLEtpe = 13,
+ CONSTANTtpe = 14,
+ TYPEREFtpe = 15,
+ COMPOUNDtpe = 16,
+ METHODtpe = 17,
+ POLYtpe = 18,
+ OVERLOADEDtpe = 19,
+ UNBOXEDtpe = 20,
+ UNBOXEDARRAYtpe = 21,
+ FLAGGEDtpe = 22,
+ ERRORtpe = 23;
int firstSymTag = NONEsym, lastSymTag = VALsym;
int firstTypeTag = NOtpe, lastTypeTag = FLAGGEDtpe;
diff --git a/sources/scalac/symtab/Symbol.java b/sources/scalac/symtab/Symbol.java
index ea75fdbd52..7dd1823ad3 100644
--- a/sources/scalac/symtab/Symbol.java
+++ b/sources/scalac/symtab/Symbol.java
@@ -281,6 +281,13 @@ public abstract class Symbol implements Modifiers, Kinds {
(flags & MUTABLE) == 0 && type().isObjectType());
}
+ /** Is this symbol final?
+ */
+ public final boolean isFinal() {
+ return
+ (flags & (FINAL | PRIVATE)) != 0 || isLocal() || owner.isModuleClass();
+ }
+
/** Does this symbol denote a variable? */
public final boolean isVariable() {
return kind == VAL && (flags & MUTABLE) != 0;
diff --git a/sources/scalac/symtab/SymbolTablePrinter.java b/sources/scalac/symtab/SymbolTablePrinter.java
index a56a082d5d..c23a6107eb 100644
--- a/sources/scalac/symtab/SymbolTablePrinter.java
+++ b/sources/scalac/symtab/SymbolTablePrinter.java
@@ -526,6 +526,9 @@ public class SymbolTablePrinter {
return this;
case SingleType(Type pre, Symbol sym):
return printPrefix(pre).printSymbolName(sym);
+ case ConstantType(Type base, Object value):
+ return printType(base)
+ .print("(").print(value.toString()).print(")");
case CompoundType(Type[] parts, Scope members):
return printTypes(parts," with ").space()
.printScope(members,true)
diff --git a/sources/scalac/symtab/Type.java b/sources/scalac/symtab/Type.java
index e574a35776..3635b51ca7 100644
--- a/sources/scalac/symtab/Type.java
+++ b/sources/scalac/symtab/Type.java
@@ -35,6 +35,17 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
assert this instanceof ExtSingleType;
}
+ /** Type for a numeric or string constant.
+ */
+ public case ConstantType(Type base, Object value) {
+ if (base.symbol() == Global.instance.definitions.BYTE_CLASS)
+ assert value instanceof Byte;
+ if (base.symbol() == Global.instance.definitions.CHAR_CLASS)
+ assert value instanceof Character;
+ if (base.symbol() == Global.instance.definitions.SHORT_CLASS)
+ assert value instanceof Short;
+ }
+
/** pre.sym[args]
* sym represents a type
* for example: scala.List[java.lang.String] is coded as
@@ -136,6 +147,28 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
}
}
+ public static ConstantType constantType(Object value) {
+ return new ConstantType(value2type(value), value);
+ }
+
+ private static Type value2type(Object value) {
+ if (value instanceof Character)
+ return Global.instance.definitions.CHAR_TYPE();
+ else if (value instanceof Integer)
+ return Global.instance.definitions.INT_TYPE();
+ else if (value instanceof Long)
+ return Global.instance.definitions.LONG_TYPE();
+ else if (value instanceof Float)
+ return Global.instance.definitions.FLOAT_TYPE();
+ else if (value instanceof Double)
+ return Global.instance.definitions.DOUBLE_TYPE();
+ else if (value instanceof String)
+ return Global.instance.definitions.JAVA_STRING_TYPE();
+ else if (value instanceof Boolean)
+ return Global.instance.definitions.BOOLEAN_TYPE();
+ else throw new ApplicationError();
+ }
+
public static Type singleTypeMethod(Type pre, Symbol sym) {
Global global = Global.instance;
if (global.currentPhase.id <= global.PHASE.UNCURRY.id())
@@ -242,6 +275,8 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
return sym;
case SingleType(_, Symbol sym):
return sym;
+ case ConstantType(Type base, _):
+ return base.symbol();
case TypeVar(Type origin, _):
return origin.symbol();
case CompoundType(_, _):
@@ -282,6 +317,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
return this;
case ThisType(_):
case SingleType(_, _):
+ case ConstantType(_, _):
return singleDeref().bound();
case TypeVar(Type origin, Constraint constr):
if (constr.inst != NoType) return constr.inst.bound();
@@ -301,6 +337,8 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
case SingleType(Type pre, Symbol sym):
// overridden in ExtSingleType
throw new ApplicationError();
+ case ConstantType(Type base, _):
+ return base;
case TypeVar(Type origin, Constraint constr):
if (constr.inst != NoType) return constr.inst.singleDeref();
else return this;
@@ -317,6 +355,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
switch (tp) {
case ThisType(_):
case SingleType(_, _):
+ case ConstantType(_, _):
return tp.widen();
default:
return tp;
@@ -347,6 +386,18 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
}
}
+ /** If this type is a constant type, its underlying basetype;
+ * otherwise the type itself
+ */
+ public Type deconst() {
+ switch (this) {
+ case ConstantType(Type base, _):
+ return base;
+ default:
+ return this;
+ }
+ }
+
/** If this type is a parameterless method, its underlying resulttype;
* otherwise the type itself
*/
@@ -459,6 +510,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
switch (unalias()) {
case ThisType(_):
case SingleType(_, _):
+ case ConstantType(_, _):
return singleDeref().parents();
case TypeRef(Type pre, Symbol sym, Type[] args):
if (sym.kind == CLASS) {
@@ -587,6 +639,62 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
return this;
}
+ /** Numeric values
+ */
+ public int intValue() {
+ switch (this) {
+ case ConstantType(_, Object value):
+ return toNumber(value).intValue();
+ default:
+ throw new ApplicationError();
+ }
+ }
+ public long longValue() {
+ switch (this) {
+ case ConstantType(_, Object value):
+ return toNumber(value).longValue();
+ default:
+ throw new ApplicationError();
+ }
+ }
+ public float floatValue() {
+ switch (this) {
+ case ConstantType(_, Object value):
+ return toNumber(value).floatValue();
+ default:
+ throw new ApplicationError();
+ }
+ }
+ public double doubleValue() {
+ switch (this) {
+ case ConstantType(_, Object value):
+ return toNumber(value).doubleValue();
+ default:
+ throw new ApplicationError();
+ }
+ }
+ public boolean booleanValue() {
+ switch (this) {
+ case ConstantType(_, Object value):
+ return ((Boolean)value).booleanValue();
+ default:
+ throw new ApplicationError();
+ }
+ }
+ public String stringValue() {
+ switch (this) {
+ case ConstantType(_, Object value):
+ return (String)value;
+ default:
+ throw new ApplicationError();
+ }
+ }
+ private static Number toNumber(Object value) {
+ return (value instanceof Character)
+ ? new Integer(((Character)value).charValue())
+ : (Number)value;
+ }
+
// Tests --------------------------------------------------------------------
/** Is this type a this type or singleton type?
@@ -595,6 +703,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
switch (unalias()) {
case ThisType(_):
case SingleType(_, _):
+ case ConstantType(_, _):
return true;
default:
return false;
@@ -624,6 +733,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
switch (unalias()) {
case ThisType(_):
case SingleType(_, _):
+ case ConstantType(_, _):
case CompoundType(_, _):
case TypeRef(_, _, _):
return true;
@@ -675,7 +785,8 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
return new Scope();
case TypeRef(_, Symbol sym, _):
return sym.info().members();
- case SingleType(_, Symbol sym):
+ case SingleType(_, _):
+ case ConstantType(_, _):
return singleDeref().members();
case CompoundType(Type[] basetypes, Scope members):
return members;
@@ -693,6 +804,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
return Symbol.ERROR;
case ThisType(_):
case SingleType(_, _):
+ case ConstantType(_, _):
return singleDeref().lookup(name);
case TypeRef(_, Symbol sym, _):
return sym.info().lookup(name);
@@ -722,6 +834,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
return Symbol.ERROR;
case ThisType(_):
case SingleType(_, _):
+ case ConstantType(_, _):
return singleDeref().lookupNonPrivate(name);
case TypeRef(_, Symbol sym, _):
return sym.info().lookupNonPrivate(name, start);
@@ -860,6 +973,10 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
Type pre1 = apply(pre);
if (pre1 == pre) return tp;
else return singleType(pre1, sym);
+ case ConstantType(Type base, Object value):
+ Type base1 = apply(base);
+ if (base1 == base) return tp;
+ else return new ConstantType(base1, value);
case CompoundType(Type[] parts, Scope members):
Type[] parts1 = map(parts);
Scope members1 = map(members);
@@ -1014,6 +1131,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
case ThisType(_):
case SingleType(_, _):
+ case ConstantType(_, _):
return singleDeref().baseType(clazz);
case TypeRef(Type pre, Symbol sym, Type[] args):
@@ -1687,9 +1805,11 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
case ThisType(_):
case SingleType(_, _):
+ case ConstantType(_, _):
switch (this) {
case ThisType(_):
case SingleType(_, _):
+ case ConstantType(_, _):
return this.isSameAs(that);
}
break;
@@ -1795,6 +1915,9 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
case SingleType(_, _):
if (this.singleDeref().isSubType(that)) return true;
break;
+ case ConstantType(_, Object value):
+ if (this.singleDeref().isSubType(that)) return true;
+ break;
case TypeVar(Type origin, Constraint constr):
if (constr.inst != NoType) {
return constr.inst.isSubType(that);
@@ -1987,6 +2110,13 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
}
break;
+ case ConstantType(Type base, Object value):
+ switch (that) {
+ case ConstantType(Type base1, Object value1):
+ return base.isSameAs(base1) && value.equals(value1);
+ }
+ break;
+
case TypeRef(Type pre, Symbol sym, Type[] args):
switch (that) {
case TypeRef(Type pre1, Symbol sym1, Type[] args1):
@@ -2560,6 +2690,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
break;
case ThisType(_):
case SingleType(_, _):
+ case ConstantType(_, _):
return Global.instance.definitions.ALL_TYPE();
}
}
@@ -2871,6 +3002,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
switch (this) {
case ThisType(_):
case SingleType(_, _):
+ case ConstantType(_, _):
return singleDeref().erasure();
case TypeRef(Type pre, Symbol sym, Type[] args):
switch (sym.kind) {
@@ -2958,6 +3090,10 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
return SINGLEtpe
^ (pre.hashCode() * 41)
^ (sym.hashCode() * (41*41));
+ case ConstantType(Type base, Object value):
+ return CONSTANTtpe
+ ^ (base.hashCode() * 41)
+ ^ (value.hashCode() * (41*41));
case CompoundType(Type[] parts, Scope members):
return symbol().hashCode();
//return COMPOUNDtpe
@@ -3026,6 +3162,12 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
return pre.equals(pre1) && sym == sym1;
default: return false;
}
+ case ConstantType(Type base, Object value):
+ switch (that) {
+ case ConstantType(Type base1, Object value1):
+ return base.equals(base1) && value.equals(value1);
+ default: return false;
+ }
case CompoundType(Type[] parts, Scope members):
switch (that) {
case CompoundType(Type[] parts1, Scope members1):
@@ -3194,6 +3336,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
case ThisType(Symbol sym):
case TypeRef(Type pre, Symbol sym, Type[] args):
case SingleType(Type pre, Symbol sym):
+ case ConstantType(Type base, Object value):
case CompoundType(Type[] parts, Scope members):
case MethodType(Symbol[] vparams, Type result):
case PolyType(Symbol[] tparams, Type result):
diff --git a/sources/scalac/symtab/classfile/Pickle.java b/sources/scalac/symtab/classfile/Pickle.java
index bdc552e507..871a417509 100644
--- a/sources/scalac/symtab/classfile/Pickle.java
+++ b/sources/scalac/symtab/classfile/Pickle.java
@@ -168,6 +168,10 @@ public class Pickle implements Kinds, Modifiers, EntryTags {
putType(pre);
putSymbol(sym);
break;
+ case ConstantType(Type base, Object value):
+ putType(base);
+ putEntry(value);
+ break;
case TypeRef(Type pre, Symbol sym, Type[] args):
putType(pre);
putSymbol(sym);
@@ -258,6 +262,15 @@ public class Pickle implements Kinds, Modifiers, EntryTags {
if (y != 0) patchNatPrefix(pos, y);
}
+ /** Write a long number in signed big endian format, base 256.
+ */
+ private void writeLong(long x) {
+ long y = x >> 8;
+ long z = x & 0xff;
+ if (-y != z >> 7) writeLong(y);
+ writeByte((int) z);
+ }
+
/** Write a reference to object, i.e., the object's number in the index.
*/
private void writeRef(Object ref) {
@@ -281,6 +294,15 @@ public class Pickle implements Kinds, Modifiers, EntryTags {
bp = bp + name.length();
}
+ /** Write a long number in big endian format, base 128.
+ * All but the last digits have bit 0x80 set.
+ */
+ private void writeNumber(long x) {
+ writeByte(NUMBER);
+ writeByte(0); // space for length
+ writeLong(x);
+ }
+
/** Write a symbol entry.
*/
private void writeSymbol(Symbol sym) {
@@ -367,6 +389,13 @@ public class Pickle implements Kinds, Modifiers, EntryTags {
writeRef(sym);
break;
+ case ConstantType(Type base, Object value):
+ writeByte(CONSTANTtpe);
+ writeByte(0); // space for length
+ writeRef(base);
+ writeRef(value);
+ break;
+
case TypeRef(Type pre, Symbol sym, Type[] args):
writeByte(TYPEREFtpe);
writeByte(0); // space for length
@@ -425,11 +454,34 @@ public class Pickle implements Kinds, Modifiers, EntryTags {
private void writeEntry(Object e) {
int startpos = bp;
- if (e instanceof Symbol) writeSymbol((Symbol) e);
- else if (e instanceof Type) writeType((Type) e);
- else if (e instanceof Name) writeName((Name) e);
- else if (e instanceof FlagsAndType) writeFlagsAndType((FlagsAndType) e);
- else throw new ApplicationError();
+ if (e instanceof Symbol)
+ writeSymbol((Symbol) e);
+ else if (e instanceof Type)
+ writeType((Type) e);
+ else if (e instanceof Name)
+ writeName((Name) e);
+ else if (e instanceof FlagsAndType)
+ writeFlagsAndType((FlagsAndType) e);
+ else if (e instanceof String)
+ writeName(Name.fromString((String)e));
+ else if (e instanceof Double)
+ writeNumber(Double.doubleToLongBits(((Double)e).doubleValue()));
+ else if (e instanceof Float)
+ writeNumber(Float.floatToIntBits(((Float)e).floatValue()));
+ else if (e instanceof Long)
+ writeNumber(((Long)e).longValue());
+ else if (e instanceof Integer)
+ writeNumber(((Integer)e).intValue());
+ else if (e instanceof Short)
+ writeNumber(((Short)e).intValue());
+ else if (e instanceof Byte)
+ writeNumber(((Byte)e).intValue());
+ else if (e instanceof Character)
+ writeNumber(((Character)e).charValue());
+ else if (e instanceof Boolean)
+ writeNumber(((Boolean)e).booleanValue() ? 1 : 0);
+ else
+ throw new ApplicationError(e);
patchNat(startpos + 1, bp - (startpos + 2));
}
diff --git a/sources/scalac/symtab/classfile/UnPickle.java b/sources/scalac/symtab/classfile/UnPickle.java
index 482287fbb7..68c2a99177 100644
--- a/sources/scalac/symtab/classfile/UnPickle.java
+++ b/sources/scalac/symtab/classfile/UnPickle.java
@@ -17,7 +17,7 @@ import scalac.symtab.*;
import Symbol.*;
import Type.*;
-public class UnPickle implements Kinds, Modifiers, EntryTags {
+public class UnPickle implements Kinds, Modifiers, EntryTags, TypeTags {
/***************************************************
* Symbol table attribute format: see EntryTags.java
@@ -91,6 +91,15 @@ public class UnPickle implements Kinds, Modifiers, EntryTags {
return x;
}
+ long readLong(int n) {
+ long x = 0;
+ for (int i = 0; i < n; i++) {
+ x = (x << 8) + (readByte() & 0xff);
+ }
+ int leading = 64 - (n * 8);
+ return x << leading >> leading;
+ }
+
boolean isTypeEntry(int i) {
int tag = bytes[index[i]];
return (firstTypeTag <= tag && tag <= lastTypeTag);
@@ -328,6 +337,11 @@ public class UnPickle implements Kinds, Modifiers, EntryTags {
case SINGLEtpe:
tpe = Type.singleType(readTypeRef(), readSymbolRef());
break;
+ case CONSTANTtpe:
+ Type base = readTypeRef();
+ Object value = readValueRef(base);
+ tpe = new Type.ConstantType(base, value);
+ break;
case TYPEREFtpe:
tpe = Type.TypeRef(
readTypeRef(), readSymbolRef(), readTypeRefs(end));
@@ -436,6 +450,44 @@ public class UnPickle implements Kinds, Modifiers, EntryTags {
return flags;
}
+ long getNumber(int n) {
+ int savedBp = bp;
+ bp = index[n];
+ int tag = bytes[bp++];
+ long x = readLong(readNat());
+ bp = savedBp;
+ return x;
+ }
+
+ long readNumberRef() {
+ return getNumber(readNat());
+ }
+
+ Object readValueRef(Type base) {
+ switch (base.unbox()) {
+ case UnboxedType(BYTE):
+ return new Byte((byte)readNumberRef());
+ case UnboxedType(SHORT):
+ return new Short((short)readNumberRef());
+ case UnboxedType(INT):
+ return new Integer((int)readNumberRef());
+ case UnboxedType(CHAR):
+ return new Character((char)readNumberRef());
+ case UnboxedType(LONG):
+ return new Long(readNumberRef());
+ case UnboxedType(FLOAT):
+ return new Float(Float.intBitsToFloat((int)readNumberRef()));
+ case UnboxedType(DOUBLE):
+ return new Float(Double.longBitsToDouble(readNumberRef()));
+ case UnboxedType(BOOLEAN):
+ return new Boolean(readNumberRef() == 0 ? false : true);
+ case UnboxedType(STRING):
+ return readNameRef().toString();
+ default:
+ return new ApplicationError("bad constant base type: " + base);
+ }
+ }
+
public static class BadSignature extends java.lang.Error {
public BadSignature(UnPickle outer, String msg) {
super("symbol data " + outer.sourceName +
diff --git a/sources/scalac/transformer/Erasure.java b/sources/scalac/transformer/Erasure.java
index 0b5b3b29d8..ae1a6ae658 100644
--- a/sources/scalac/transformer/Erasure.java
+++ b/sources/scalac/transformer/Erasure.java
@@ -232,7 +232,8 @@ public class Erasure extends Transformer implements Modifiers {
return gen.Ident(tree.pos, symbol);
case Literal(Object value):
- return gen.mkLit(tree.pos, value);
+ return tree.setType(tree.type.erasure());
+ //return gen.mkLit(tree.pos, value);
case Block(_):
case If(_, _, _):
diff --git a/sources/scalac/transformer/UnCurry.java b/sources/scalac/transformer/UnCurry.java
index 88d978fb43..32389d9841 100644
--- a/sources/scalac/transformer/UnCurry.java
+++ b/sources/scalac/transformer/UnCurry.java
@@ -113,7 +113,8 @@ public class UnCurry extends OwnerTransformer
public Tree transform(Tree tree) {
//new scalac.ast.printer.TextTreePrinter().print("uncurry: ").print(tree).println().end();//DEBUG
//uncurry type and symbol
- if (tree.type != null) tree.type = descr.uncurry(tree.type);
+ Type prevtype = tree.type;
+ if (prevtype != null) tree.type = descr.uncurry(prevtype);
switch (tree) {
case ClassDef(_, _, AbsTypeDef[] tparams, ValDef[][] vparams, Tree tpe, Template impl):
return copy.ClassDef(
diff --git a/sources/scalac/transformer/UnCurryPhase.java b/sources/scalac/transformer/UnCurryPhase.java
index e8bdc1b77e..3309bce67b 100644
--- a/sources/scalac/transformer/UnCurryPhase.java
+++ b/sources/scalac/transformer/UnCurryPhase.java
@@ -53,13 +53,13 @@ public class UnCurryPhase extends Phase implements Modifiers {
else return Type.MethodType(params, newtp1);
}
case PolyType(Symbol[] tparams, Type tp1):
+ Type newtp1 = uncurry(tp1);
switch (tp1) {
case MethodType(_, _):
- Type newtp1 = uncurry(tp1);
if (newtp1 == tp1) return tp;
else return Type.PolyType(tparams, newtp1);
default:
- Type newtp1 = Type.MethodType(Symbol.EMPTY_ARRAY, tp1);
+ newtp1 = Type.MethodType(Symbol.EMPTY_ARRAY, newtp1);
if (tparams.length == 0) return newtp1;
else return Type.PolyType(tparams, newtp1);
}
@@ -67,6 +67,8 @@ public class UnCurryPhase extends Phase implements Modifiers {
return new Type.Map() {
public Type apply(Type t) { return uncurry(t); }
}.map(tp);
+ case ConstantType(Type base, _):
+ return base;
default:
return tp;
}
diff --git a/sources/scalac/typechecker/Analyzer.java b/sources/scalac/typechecker/Analyzer.java
index 5d96732ad0..b3cdccee72 100644
--- a/sources/scalac/typechecker/Analyzer.java
+++ b/sources/scalac/typechecker/Analyzer.java
@@ -29,20 +29,22 @@ import java.util.*;
*/
public class Analyzer extends Transformer implements Modifiers, Kinds {
- private final Definitions definitions;
+ final Definitions definitions;
private final DeSugarize desugarize;
private final AnalyzerPhase descr;
final Infer infer;
+ final ConstantFolder constfold;
public Analyzer(Global global, AnalyzerPhase descr) {
super(global);
this.definitions = global.definitions;
this.descr = descr;
this.infer = new Infer(this);
+ this.constfold = new ConstantFolder(this);
this.desugarize = new DeSugarize(this, global);
}
- private Unit unit;
+ Unit unit;
private Context context;
private Type pt;
private int mode;
@@ -595,17 +597,6 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
return fn.type == Type.ErrorType ? Type.ErrorType : Type.NoType;
}
- private Type value2Type(Object value) {
- if (value instanceof Character) return definitions.CHAR_TYPE();
- else if (value instanceof Integer) return definitions.INT_TYPE();
- else if (value instanceof Long) return definitions.LONG_TYPE();
- else if (value instanceof Float) return definitions.FLOAT_TYPE();
- else if (value instanceof Double) return definitions.DOUBLE_TYPE();
- else if (value instanceof String) return definitions.JAVA_STRING_TYPE();
- else if (value instanceof Boolean) return definitions.BOOLEAN_TYPE();
- else throw new ApplicationError();
- }
-
private boolean isSetterMethod(Symbol sym) {
return sym != null &&
!sym.isLocal() &&
@@ -1050,6 +1041,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
} else {
((DefDef) tree).rhs = rhs = transform(rhs, EXPRmode);
restype = rhs.type;
+ if (!sym.isFinal()) restype = restype.deconst();
// !!! restype = rhs.type.widen(); // !!!
}
restype = checkNoEscape(tpe.pos, restype);
@@ -1080,6 +1072,8 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
((ValDef) tree).rhs = rhs = transform(rhs, EXPRmode);
}
owntype = rhs.type;
+ if (sym.isVariable() || !sym.isFinal())
+ owntype = owntype.deconst();
// !!! owntype = rhs.type.widen(); // !!!
}
popContext();
@@ -1188,10 +1182,18 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
this.context = curcontext;
Type selftype = transform(tree, TYPEmode).type;
-
- sym.setInfo(
- Type.compoundType(
- new Type[]{selftype, clazz.type()}, Scope.EMPTY));
+ switch (selftype) {
+ case CompoundType(Type[] parts, Scope members):
+ Type[] parts1 = new Type[parts.length + 1];
+ System.arraycopy(parts, 0, parts1, 0, parts.length);
+ parts1[parts.length] = clazz.type();
+ sym.setInfo(Type.compoundType(parts1, members));
+ break;
+ default:
+ sym.setInfo(
+ Type.compoundType(
+ new Type[]{selftype, clazz.type()}, Scope.EMPTY));
+ }
this.unit = savedUnit;
this.context= savedContext;
@@ -1203,6 +1205,10 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
* context.
*/
Tree mkStable(Tree tree, Type pre, int mode, Type pt) {
+ switch (tree.type) {
+ case ConstantType(Type base, Object value):
+ return make.Literal(tree.pos, value).setType(tree.type);
+ }
if ((pt != null && pt.isStable() || (mode & QUALmode) != 0) &&
pre.isStable()) {
Symbol sym = tree.symbol();
@@ -1362,8 +1368,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
// this works as for superclass constructor calls the expected
// type `pt' is always AnyType (see transformConstrInvocations).
}
- if (!(owntype instanceof Type.PolyType ||
- owntype.isSubType(pt))) {
+ if (!(owntype instanceof Type.PolyType || owntype.isSubType(pt))) {
switch (tree) {
case Literal(Object value):
int n = Integer.MAX_VALUE;
@@ -1371,15 +1376,19 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
n = ((Integer) value).intValue();
else if (value instanceof Character)
n = ((Character) value).charValue();
+ Object value1 = null;
if (pt.symbol() == definitions.BYTE_CLASS &&
-128 <= n && n <= 127)
- return copy.Literal(tree, new Byte((byte) n)).setType(pt);
+ value1 = new Byte((byte) n);
else if (pt.symbol() == definitions.SHORT_CLASS &&
-32768 <= n && n <= 32767)
- return copy.Literal(tree, new Short((short) n)).setType(pt);
+ value1 = new Short((short) n);
else if (pt.symbol() == definitions.CHAR_CLASS &&
0 <= n && n <= 65535)
- return copy.Literal(tree, new Character((char) n)).setType(pt);
+ value1 = new Character((char) n);
+ if (value1 != null)
+ return make.Literal(tree.pos, value1)
+ .setType(Type.ConstantType(pt, value1));
}
typeError(tree.pos, owntype, pt);
Type.explainTypes(owntype, pt);
@@ -1700,7 +1709,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
if (tparams.length == 0) {
for (int i = 0; i < args.length; i++) {
args[i] = transform(args[i], argMode, formals[i]);
- argtypes[i] = args[i].type;
+ argtypes[i] = args[i].type.deconst();
}
} else {
// targs: the type arguments inferred from the prototype
@@ -1724,7 +1733,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
: tparams[i].type();
for (int i = 0; i < args.length; i++) {
- argtypes[i] = args[i].type;
+ argtypes[i] = args[i].type.deconst();
switch (argtypes[i]) {
case PolyType(Symbol[] tparams1, Type restype1):
argtypes[i] = infer.argumentTypeInstance(
@@ -1757,14 +1766,14 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
case Type.ErrorType:
for (int i = 0; i < args.length; i++) {
args[i] = transform(args[i], argMode, Type.ErrorType);
- argtypes[i] = args[i].type;
+ argtypes[i] = args[i].type.deconst();
}
return argtypes;
default:
for (int i = 0; i < args.length; i++) {
args[i] = transform(args[i], argMode, Type.AnyType);
- argtypes[i] = args[i].type;
+ argtypes[i] = args[i].type.deconst();
}
return argtypes;
}
@@ -2016,7 +2025,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
if( name != Names.PATTERN_WILDCARD ) {
//assert body.type != null;
if( TreeInfo.isSequenceValued( body ) ) {
- vble.setType( definitions.listType(pt) );
+ vble.setType( definitions.LIST_TYPE(pt) );
} else {
vble.setType( body.type );
}
@@ -2213,6 +2222,13 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
Tree[] args1 = transform(args, TYPEmode);
Type[] argtypes = Tree.typeOf(args1);
+ // propagate errors in arguments
+ for (int i = 0; i < argtypes.length; i++) {
+ if (argtypes[i] == Type.ErrorType) {
+ return tree.setType(Type.ErrorType);
+ }
+ }
+
// resolve overloading
switch (fn1.type) {
case OverloadedType(Symbol[] alts, Type[] alttypes):
@@ -2226,9 +2242,26 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
// match against arguments
switch (fn1.type) {
case PolyType(Symbol[] tparams, Type restp):
- if (tparams.length == argtypes.length)
+ if (tparams.length == argtypes.length) {
+ // constant fold asInstanceOf calls.
+ switch (fn1) {
+ case Select(Tree qual, Name name):
+ if (fn1.symbol() == definitions.ANY_AS &&
+ qual.type instanceof Type.ConstantType) {
+ Type restp1 = constfold.foldAsInstanceOf(
+ tree.pos,
+ (Type.ConstantType)qual.type,
+ argtypes[0]);
+ switch (restp1) {
+ case ConstantType(_, Object value):
+ return make.Literal(tree.pos, value)
+ .setType(restp1);
+ }
+ }
+ }
return copy.TypeApply(tree, fn1, args1)
.setType(restp.subst(tparams, argtypes));
+ }
break;
case ErrorType:
return tree.setType(Type.ErrorType);
@@ -2496,7 +2529,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
}
case Literal(Object value):
- return tree.setType(value2Type(value));
+ return tree.setType(Type.constantType(value));
case LabelDef(Name name, Ident[] params, Tree body):
assert params.length == 0;
diff --git a/sources/scalac/typechecker/Infer.java b/sources/scalac/typechecker/Infer.java
index 41f007059d..0ad12d6cd2 100644
--- a/sources/scalac/typechecker/Infer.java
+++ b/sources/scalac/typechecker/Infer.java
@@ -252,7 +252,8 @@ public class Infer implements Modifiers, Kinds {
case ErrorType:
case AnyType:
case NoType:
- case ThisType(Symbol sym):
+ case ThisType(_):
+ case ConstantType(_, _):
return VARIANCES;
case TypeRef(Type pre, Symbol sym, Type[] args):
if (sym == tparam) return COVARIANT;
diff --git a/sources/scalac/typechecker/RefCheck.java b/sources/scalac/typechecker/RefCheck.java
index a2b4cfe140..6bf3e9b0a5 100644
--- a/sources/scalac/typechecker/RefCheck.java
+++ b/sources/scalac/typechecker/RefCheck.java
@@ -842,16 +842,16 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
}
}
-// Type node eliminiation ------------------------------------------------------
+// Tree node simplification---------------------------------------------------
private Tree elimTypeNode(Tree tree) {
if (tree.isType() && !tree.isMissing())
- return gen.mkType(tree.pos, tree.type);
+ return gen.mkType(tree.pos, tree.type.deconst());
else
return tree;
}
-// Transformation ---------------------------------------------------------------
+// Transformation ------------------------------------------------------------
public Tree[] transformStats(Tree[] stats) {
pushLevel();