summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpaltherr <paltherr@epfl.ch>2004-02-01 03:15:00 +0000
committerpaltherr <paltherr@epfl.ch>2004-02-01 03:15:00 +0000
commite4731931589d6313988337a921747f9caf6fc3e7 (patch)
tree92c7298118201c435ef42d99d6b6d6c00a70c64a
parentc9e045f5c67d44313e9e2436ec107e514548272e (diff)
downloadscala-e4731931589d6313988337a921747f9caf6fc3e7.tar.gz
scala-e4731931589d6313988337a921747f9caf6fc3e7.tar.bz2
scala-e4731931589d6313988337a921747f9caf6fc3e7.zip
- Generalized use of AConstant to represent con...
- Generalized use of AConstant to represent constant values
-rw-r--r--sources/meta/scalac/ast/Tree.java3
-rw-r--r--sources/scala/tools/scalac/ast/parser/Parser.scala26
-rw-r--r--sources/scala/tools/scalac/ast/printer/TextTreePrinter.scala7
-rw-r--r--sources/scala/tools/scalac/backend/GenJVMFromICode.scala2
-rw-r--r--sources/scala/tools/scalac/icode/ICTypeStack.scala4
-rw-r--r--sources/scala/tools/scalac/typechecker/Analyzer.scala27
-rw-r--r--sources/scala/tools/scalac/typechecker/ConstantFolder.scala324
-rw-r--r--sources/scala/tools/scaladoc/SymbolTablePrinter.java3
-rw-r--r--sources/scala/tools/scalai/ExpressionCompiler.java30
-rw-r--r--sources/scalac/Global.java11
-rw-r--r--sources/scalac/ast/Transformer.java.tmpl4
-rw-r--r--sources/scalac/ast/TreeGen.java124
-rw-r--r--sources/scalac/ast/parser/Parser.java29
-rw-r--r--sources/scalac/ast/printer/TextTreePrinter.java12
-rw-r--r--sources/scalac/atree/AConstant.java343
-rw-r--r--sources/scalac/atree/ATreeFromSTree.java21
-rw-r--r--sources/scalac/atree/ATreeTyper.java23
-rw-r--r--sources/scalac/atree/ATypeKind.java12
-rw-r--r--sources/scalac/backend/jvm/GenJVM.java107
-rw-r--r--sources/scalac/backend/msil/GenMSIL.java155
-rw-r--r--sources/scalac/checkers/TreeChecker.java13
-rw-r--r--sources/scalac/symtab/Definitions.java13
-rw-r--r--sources/scalac/symtab/EntryTags.java29
-rw-r--r--sources/scalac/symtab/SymbolTablePrinter.java3
-rw-r--r--sources/scalac/symtab/Type.java111
-rw-r--r--sources/scalac/symtab/classfile/AttributeParser.java26
-rw-r--r--sources/scalac/symtab/classfile/Pickle.java112
-rw-r--r--sources/scalac/symtab/classfile/UnPickle.java86
-rw-r--r--sources/scalac/transformer/Erasure.java7
-rw-r--r--sources/scalac/transformer/matching/AlgebraicMatcher.java5
-rw-r--r--sources/scalac/transformer/matching/BerrySethi.java4
-rw-r--r--sources/scalac/transformer/matching/CodeFactory.java20
-rw-r--r--sources/scalac/transformer/matching/LeftTracerInScala.java2
-rw-r--r--sources/scalac/transformer/matching/PatternMatcher.java17
-rw-r--r--sources/scalac/transformer/matching/PatternNode.java11
-rw-r--r--sources/scalac/transformer/matching/PatternNodeCreator.java3
-rw-r--r--sources/scalac/transformer/matching/RightTracerInScala.java6
-rw-r--r--sources/scalac/typechecker/Analyzer.java52
-rw-r--r--sources/scalac/typechecker/ConstantFolder.java631
-rw-r--r--test/files/neg/bug45.check2
-rw-r--r--test/files/neg/constrparams.check2
-rw-r--r--test/files/shl/basic.check6
42 files changed, 1277 insertions, 1151 deletions
diff --git a/sources/meta/scalac/ast/Tree.java b/sources/meta/scalac/ast/Tree.java
index d3f9847f37..6efdfea707 100644
--- a/sources/meta/scalac/ast/Tree.java
+++ b/sources/meta/scalac/ast/Tree.java
@@ -35,6 +35,7 @@ public class Tree {
t_Global = TreeType.Reference("scalac", "Global"),
t_Unit = TreeType.Reference("scalac", "Unit"),
t_TreeGen = TreeType.Reference("scalac.ast", "TreeGen"),
+ t_AConstant = TreeType.Reference("scalac.atree", "AConstant"),
t_Symbol = TreeType.Reference("scalac.symtab", "Symbol"),
t_Type = TreeType.Reference("scalac.symtab", "Type"),
t_Name = TreeType.Name(Any),
@@ -335,7 +336,7 @@ public class Tree {
n_Literal.
setDescription("Literal").
setRange(Phase.PARSER, Phase.END).
- addField(t_Object, "value");
+ addField(t_AConstant, "value");
n_TypeTerm.
setDescription("TypeTerm").
diff --git a/sources/scala/tools/scalac/ast/parser/Parser.scala b/sources/scala/tools/scalac/ast/parser/Parser.scala
index 6cd6effa88..bd22ef19f2 100644
--- a/sources/scala/tools/scalac/ast/parser/Parser.scala
+++ b/sources/scala/tools/scalac/ast/parser/Parser.scala
@@ -37,6 +37,10 @@ class Parser(unit: Unit) {
*/
val make: TreeFactory = unit.global.make;
+ /** the tree generator
+ */
+ val gen: TreeGen = unit.global.treeGen;
+
/** pattern checker and normalizer
*/
val pN = new PatternNormalizer(unit);
@@ -571,23 +575,23 @@ class Parser(unit: Unit) {
def literal(isPattern: boolean): Tree = {
def litToTree() = s.token match {
case CHARLIT =>
- make.Literal(s.pos, new Character(s.intVal.asInstanceOf[char]))
+ gen.mkCharLit(s.pos, s.intVal.asInstanceOf[char])
case INTLIT =>
- make.Literal(s.pos, new Integer(s.intVal.asInstanceOf[int]))
+ gen.mkIntLit(s.pos, s.intVal.asInstanceOf[int])
case LONGLIT =>
- make.Literal(s.pos, new Long(s.intVal))
+ gen.mkLongLit(s.pos, s.intVal)
case FLOATLIT =>
- make.Literal(s.pos, new Float(s.floatVal.asInstanceOf[float]))
+ gen.mkFloatLit(s.pos, s.floatVal.asInstanceOf[float])
case DOUBLELIT =>
- make.Literal(s.pos, new Double(s.floatVal))
+ gen.mkDoubleLit(s.pos, s.floatVal)
case STRINGLIT | SYMBOLLIT =>
- make.Literal(s.pos, s.name.toString())
+ gen.mkStringLit(s.pos, s.name.toString())
case TRUE =>
- make.Literal(s.pos, java.lang.Boolean.TRUE)
+ gen.mkBooleanLit(s.pos, true)
case FALSE =>
- make.Literal(s.pos, java.lang.Boolean.FALSE)
+ gen.mkBooleanLit(s.pos, false)
case NULL =>
- make.Ident(s.pos, Names.null_)
+ gen.mkNullLit(s.pos)
case _ =>
syntaxError("illegal literal", true)
}
@@ -1083,10 +1087,10 @@ class Parser(unit: Unit) {
NewArray.CaseDef(
make.CaseDef(
rhs.pos, pat.duplicate(),
- Tree.Empty, make.Literal(s.pos, java.lang.Boolean.TRUE)),
+ Tree.Empty, gen.mkBooleanLit(s.pos, true)),
make.CaseDef(
rhs.pos, make.Ident(rhs.pos, Names.PATTERN_WILDCARD),
- Tree.Empty, make.Literal(s.pos, java.lang.Boolean.FALSE))))));
+ Tree.Empty, gen.mkBooleanLit(s.pos, false))))));
make.PatDef(pos, 0, pat, rhs)
}
diff --git a/sources/scala/tools/scalac/ast/printer/TextTreePrinter.scala b/sources/scala/tools/scalac/ast/printer/TextTreePrinter.scala
index d073ec135a..f7a43f3ee7 100644
--- a/sources/scala/tools/scalac/ast/printer/TextTreePrinter.scala
+++ b/sources/scala/tools/scalac/ast/printer/TextTreePrinter.scala
@@ -471,12 +471,7 @@ class TextTreePrinter(writer: PrintWriter) with TreePrinter {
printType(tree);
case Tree$Literal(obj) =>
- val str = obj match {
- case s: String => "\"" + s + "\"";
- case c: Character => "\'" + c + "\'";
- case _ => String.valueOf(obj);
- }
- print(Literal(str));
+ print(Literal(obj.toString()));
printType(tree);
case Tree$TypeTerm() =>
diff --git a/sources/scala/tools/scalac/backend/GenJVMFromICode.scala b/sources/scala/tools/scalac/backend/GenJVMFromICode.scala
index a7b5627452..a3f81e9bfd 100644
--- a/sources/scala/tools/scalac/backend/GenJVMFromICode.scala
+++ b/sources/scala/tools/scalac/backend/GenJVMFromICode.scala
@@ -32,7 +32,7 @@ class GenJVMFromICode(global: scalac_Global) {
private val fjbgContext = new FJBGContext();
- private val typer = new ATreeTyper(global);
+ private val typer = defs.atyper;
// ##################################################
// Private fields - Data
diff --git a/sources/scala/tools/scalac/icode/ICTypeStack.scala b/sources/scala/tools/scalac/icode/ICTypeStack.scala
index 4bb93c9b1f..750821db13 100644
--- a/sources/scala/tools/scalac/icode/ICTypeStack.scala
+++ b/sources/scala/tools/scalac/icode/ICTypeStack.scala
@@ -22,10 +22,10 @@ class ICTypeStack() {
private val global = Global.instance;
- private val typer = new ATreeTyper(global); // !!! Using atree typer !
-
private val definitions = global.definitions;
+ private val typer = definitions.atyper; // !!! Using atree typer !
+
// ##################################################
// Private constructor
diff --git a/sources/scala/tools/scalac/typechecker/Analyzer.scala b/sources/scala/tools/scalac/typechecker/Analyzer.scala
index 49533273a5..da8e2d5c65 100644
--- a/sources/scala/tools/scalac/typechecker/Analyzer.scala
+++ b/sources/scala/tools/scalac/typechecker/Analyzer.scala
@@ -19,6 +19,9 @@ import scalac._;
import scalac.util._;
import scalac.ast._;
import scalac.ast.printer._;
+import scalac.atree.AConstant;
+import scalac.atree.AConstant$CHAR;
+import scalac.atree.AConstant$INT;
import scalac.symtab._;
import scalac.symtab.classfile._;
import Tree._;
@@ -39,7 +42,7 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
val definitions = global.definitions;
val infer = new scala.tools.scalac.typechecker.Infer(this);
val desugarize = new DeSugarize(make, copy, gen, infer, global);
- val constfold = new ConstantFolder(this);
+ val constfold = new ConstantFolder(global);
var unit: Unit = _;
@@ -1400,22 +1403,22 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
}
if (!(owntype.isInstanceOf[Type$PolyType] || owntype.isSubType(pt))) {
tree match {
- case Tree$Literal(value) =>
- var n: int = Integer.MAX_VALUE;
- if (value.isInstanceOf[Integer])
- n = value.asInstanceOf[Integer].intValue();
- else if (value.isInstanceOf[Character])
- n = value.asInstanceOf[Character].charValue();
- val value1: Object =
+ case Tree$Literal(constant) =>
+ var n: int = constant match {
+ case AConstant$INT(value) => value
+ case AConstant$CHAR(value) => value
+ case _ => Integer.MAX_VALUE
+ }
+ val value1: AConstant =
if (pt.symbol() == definitions.BYTE_CLASS && -128 <= n && n <= 127)
- new Byte(n.asInstanceOf[byte])
+ AConstant.BYTE(n.asInstanceOf[byte])
else if (pt.symbol() == definitions.SHORT_CLASS && -32768 <= n && n <= 32767)
- new Short(n.asInstanceOf[short])
+ AConstant.SHORT(n.asInstanceOf[short])
else if (pt.symbol() == definitions.CHAR_CLASS && 0 <= n && n <= 65535)
- new Character(n.asInstanceOf[char])
+ AConstant.CHAR(n.asInstanceOf[char])
else null;
if (value1 != null)
- return make.Literal(tree.pos, value1).setType(new Type$ConstantType(pt, value1));
+ return gen.Literal(tree.pos, value1);
case _ =>
}
if ((mode & EXPRmode) != 0) {
diff --git a/sources/scala/tools/scalac/typechecker/ConstantFolder.scala b/sources/scala/tools/scalac/typechecker/ConstantFolder.scala
index 22950466ca..07909efc70 100644
--- a/sources/scala/tools/scalac/typechecker/ConstantFolder.scala
+++ b/sources/scala/tools/scalac/typechecker/ConstantFolder.scala
@@ -10,327 +10,13 @@
* if this copyright notice stays attached.
*************************************************************************/
-import scalac.util._;
-import scalac.ast._;
-import scalac.symtab._;
-import java.lang.{Byte,Character,Short,Integer,Long,Float,Double,Boolean,Object,Number}
+import scalac.{Global => scalac_Global}
+import scalac.typechecker.{ConstantFolder => scalac_typechecker_ConstantFolder}
package scala.tools.scalac.typechecker {
-class ConstantFolder(ana: Analyzer) {
-
- import TypeTags._;
-
- /** fold binary operation.
- */
- def foldBinary(pos: int, left: Type$ConstantType, right: Type$ConstantType, op: Name): Type = {
- try {
- var ltype: Type = left.deconst();
- var lsymbol: Symbol = left.symbol();
- if (lsymbol == ana.definitions.BYTE_CLASS ||
- lsymbol == ana.definitions.CHAR_CLASS ||
- lsymbol == ana.definitions.SHORT_CLASS) {
- ltype = ana.definitions.INT_TYPE();
- lsymbol = ana.definitions.INT_CLASS;
- }
- var rtype: Type = right.deconst();
- var rsymbol: Symbol = right.symbol();
- if (rsymbol == ana.definitions.BYTE_CLASS ||
- rsymbol == ana.definitions.CHAR_CLASS ||
- rsymbol == ana.definitions.SHORT_CLASS) {
- rtype = ana.definitions.INT_TYPE();
- rsymbol = ana.definitions.INT_CLASS;
- }
- val optype: Type =
- if (ltype.isSameAs(rtype))
- ltype;
- else if (lsymbol == ana.definitions.JAVA_STRING_CLASS)
- ltype;
- else if (rsymbol == ana.definitions.JAVA_STRING_CLASS)
- rtype;
- else if (lsymbol == ana.definitions.INT_CLASS)
- rtype;
- else if (rsymbol == ana.definitions.INT_CLASS)
- ltype;
- else if (lsymbol == ana.definitions.LONG_CLASS)
- rtype;
- else if (rsymbol == ana.definitions.LONG_CLASS)
- ltype;
- else if (lsymbol == ana.definitions.FLOAT_CLASS)
- rtype;
- else if (rsymbol == ana.definitions.FLOAT_CLASS)
- ltype;
- else
- throw Debug.abort("illegal case", ltype.toString() +" - "+ rtype);
- var value: Object = null;
- optype.unbox() match {
- case Type$UnboxedType(INT) =>
- if (op == Names.ADD)
- value = new Integer(left.intValue() + right.intValue());
- else if (op == Names.SUB)
- value = new Integer(left.intValue() - right.intValue());
- else if (op == Names.MUL)
- value = new Integer(left.intValue() * right.intValue());
- else if (op == Names.DIV)
- value = new Integer(left.intValue() / right.intValue());
- else if (op == Names.MOD)
- value = new Integer(left.intValue() % right.intValue());
- else if (op == Names.EQ)
- value = new Boolean(left.intValue() == right.intValue());
- else if (op == Names.NE)
- value = new Boolean(left.intValue() != right.intValue());
- else if (op == Names.LT)
- value = new Boolean(left.intValue() < right.intValue());
- else if (op == Names.GT)
- value = new Boolean(left.intValue() > right.intValue());
- else if (op == Names.LE)
- value = new Boolean(left.intValue() <= right.intValue());
- else if (op == Names.GE)
- value = new Boolean(left.intValue() >= right.intValue());
- else if (op == Names.OR)
- value = new Integer(left.intValue() | right.intValue());
- else if (op == Names.AND)
- value = new Integer(left.intValue() & right.intValue());
- else if (op == Names.XOR)
- value = new Integer(left.intValue() ^ right.intValue());
- else if (op == Names.LSL)
- value = new Integer(left.intValue() << right.intValue());
- else if (op == Names.LSR)
- value = new Integer(left.intValue() >>> right.intValue());
- else if (op == Names.ASR)
- value = new Integer(left.intValue() >> right.intValue());
-
- case Type$UnboxedType(LONG) =>
- if (op == Names.ADD)
- value = new Long(left.longValue() + right.longValue());
- else if (op == Names.SUB)
- value = new Long(left.longValue() - right.longValue());
- else if (op == Names.MUL)
- value = new Long(left.longValue() * right.longValue());
- else if (op == Names.DIV)
- value = new Long(left.longValue() / right.longValue());
- else if (op == Names.MOD)
- value = new Long(left.longValue() % right.longValue());
- else if (op == Names.EQ)
- value = new Boolean(left.longValue() == right.longValue());
- else if (op == Names.NE)
- value = new Boolean(left.longValue() != right.longValue());
- else if (op == Names.LT)
- value = new Boolean(left.longValue() < right.longValue());
- else if (op == Names.GT)
- value = new Boolean(left.longValue() > right.longValue());
- else if (op == Names.LE)
- value = new Boolean(left.longValue() <= right.longValue());
- else if (op == Names.GE)
- value = new Boolean(left.longValue() >= right.longValue());
- else if (op == Names.OR)
- value = new Long(left.longValue() | right.longValue());
- else if (op == Names.AND)
- value = new Long(left.longValue() & right.longValue());
- else if (op == Names.XOR)
- value = new Long(left.longValue() ^ right.longValue());
- else if (op == Names.LSL)
- value = new Long(left.longValue() << right.intValue());
- else if (op == Names.LSR)
- value = new Long(left.longValue() >>> right.intValue());
- else if (op == Names.ASR)
- value = new Long(left.longValue() >> right.intValue());
-
- case Type$UnboxedType(FLOAT) =>
- if (op == Names.ADD)
- value = new Float(left.floatValue() + right.floatValue());
- else if (op == Names.SUB)
- value = new Float(left.floatValue() - right.floatValue());
- else if (op == Names.MUL)
- value = new Float(left.floatValue() * right.floatValue());
- else if (op == Names.DIV)
- value = new Float(left.floatValue() / right.floatValue());
- else if (op == Names.MOD)
- value = new Float(left.floatValue() % right.floatValue());
- else if (op == Names.EQ)
- value = new Boolean(left.floatValue() == right.floatValue());
- else if (op == Names.NE)
- value = new Boolean(left.floatValue() != right.floatValue());
- else if (op == Names.LT)
- value = new Boolean(left.floatValue() < right.floatValue());
- else if (op == Names.GT)
- value = new Boolean(left.floatValue() > right.floatValue());
- else if (op == Names.LE)
- value = new Boolean(left.floatValue() <= right.floatValue());
- else if (op == Names.GE)
- value = new Boolean(left.floatValue() >= right.floatValue());
-
- case Type$UnboxedType(DOUBLE) =>
- if (op == Names.ADD)
- value = new Double(left.doubleValue() + right.doubleValue());
- else if (op == Names.SUB)
- value = new Double(left.doubleValue() - right.doubleValue());
- else if (op == Names.MUL)
- value = new Double(left.doubleValue() * right.doubleValue());
- else if (op == Names.DIV)
- value = new Double(left.doubleValue() / right.doubleValue());
- else if (op == Names.MOD)
- value = new Double(left.doubleValue() % right.doubleValue());
- else if (op == Names.EQ)
- value = new Boolean(left.doubleValue() == right.doubleValue());
- else if (op == Names.NE)
- value = new Boolean(left.doubleValue() != right.doubleValue());
- else if (op == Names.LT)
- value = new Boolean(left.doubleValue() < right.doubleValue());
- else if (op == Names.GT)
- value = new Boolean(left.doubleValue() > right.doubleValue());
- else if (op == Names.LE)
- value = new Boolean(left.doubleValue() <= right.doubleValue());
- else if (op == Names.GE)
- value = new Boolean(left.doubleValue() >= right.doubleValue());
-
- case Type$UnboxedType(BOOLEAN) =>
- if (op == Names.EQ)
- value = new Boolean(left.booleanValue() == right.booleanValue());
- else if (op == Names.NE)
- value = new Boolean(left.booleanValue() != right.booleanValue());
- else if (op == Names.OR || op == Names.ZOR)
- value = new Boolean(left.booleanValue() | right.booleanValue());
- else if (op == Names.AND || op == Names.ZAND)
- value = new Boolean(left.booleanValue() & right.booleanValue());
- else if (op == Names.XOR)
- value = new Boolean(left.booleanValue() ^ right.booleanValue());
-
- case _ =>
- if (optype.symbol() == ana.definitions.JAVA_STRING_CLASS &&
- op == Names.ADD)
- value = left.stringValue() + right.stringValue();
- }
- if (value != null) Type.constantType(value) else Type.NoType;
- } catch {
- case e: ArithmeticException =>
- ana.unit.warning(pos, e.toString());
- Type.NoType
- }
- }
-
- /** fold unary operation.
- */
- def foldUnary(pos: int, od: Type$ConstantType, op: Name): Type = {
- try {
- var value: Object = null;
- od.deconst().unbox() match {
- case Type$UnboxedType(INT) =>
- if (op == Names.ADD)
- value = new Integer(od.intValue());
- else if (op == Names.SUB)
- value = new Integer(-od.intValue());
- else if (op == Names.NOT)
- value = new Integer(~od.intValue());
-
- case Type$UnboxedType(LONG) =>
- if (op == Names.ADD)
- value = new Long(od.longValue());
- else if (op == Names.SUB)
- value = new Long(-od.longValue());
- else if (op == Names.NOT)
- value = new Long(~od.longValue());
-
- case Type$UnboxedType(FLOAT) =>
- if (op == Names.ADD)
- value = new Float(od.floatValue());
- else if (op == Names.SUB)
- value = new Float(-od.floatValue());
-
- case Type$UnboxedType(DOUBLE) =>
- if (op == Names.ADD)
- value = new Double(od.doubleValue());
- else if (op == Names.SUB)
- value = new Double(-od.doubleValue());
-
- case Type$UnboxedType(BOOLEAN) =>
- if (op == Names.ZNOT)
- value = new Boolean(!od.booleanValue());
-
- case _ =>
- }
- if (value != null) Type.constantType(value) else Type.NoType;
- } catch {
- case e: ArithmeticException =>
- ana.unit.warning(pos, e.toString());
- Type.NoType
- }
- }
-
- /** fold cast operation
- */
- def foldAsInstanceOf(pos: int, od: Type$ConstantType, argtype: Type): Type = {
- try {
- var value: Object = null;
- argtype.unbox() match {
- case Type$UnboxedType(BYTE) =>
- value = new Byte(od.intValue().asInstanceOf[byte]);
-
- case Type$UnboxedType(CHAR) =>
- value = new Character(od.intValue().asInstanceOf[char]);
-
- case Type$UnboxedType(SHORT) =>
- value = new Short(od.intValue().asInstanceOf[short]);
-
- case Type$UnboxedType(INT) =>
- value = new Integer(od.intValue());
-
- case Type$UnboxedType(LONG) =>
- value = new Long(od.longValue());
-
- case Type$UnboxedType(FLOAT) =>
- value = new Float(od.longValue());
-
- case Type$UnboxedType(DOUBLE) =>
- value = new Double(od.doubleValue());
-
- case Type$UnboxedType(BOOLEAN) =>
- value = new Boolean(od.booleanValue());
-
- case _ =>
- }
- if (value != null) new Type$ConstantType(argtype, value) else Type.NoType;
- } catch {
- case e: ClassCastException =>
- ana.unit.warning(pos, e.toString());
- Type.NoType
- }
- }
-
- /** attempt to constant fold tree.
- */
- def tryToFold(tree: Tree): Tree = {
- var ctp: Type = Type.NoType;
- tree match {
- case Tree$Apply(Tree$Select(qual, op), args) =>
- if (qual.getType().isInstanceOf[Type$ConstantType]) {
- if (args.length == 0)
- ctp = foldUnary(
- tree.pos, qual.getType().asInstanceOf[Type$ConstantType], op);
- else if (args.length == 1 &&
- args(0).getType().isInstanceOf[Type$ConstantType])
- ctp = foldBinary(
- tree.pos,
- qual.getType().asInstanceOf[Type$ConstantType],
- args(0).getType().asInstanceOf[Type$ConstantType],
- op);
- }
-
- case Tree$TypeApply(Tree$Select(qual, op), targs) =>
- qual.getType() match {
- case ct: Type$ConstantType if (op == Names.asInstanceOf) =>
- ctp = foldAsInstanceOf(tree.pos, ct, targs(0).getType());
- case _ =>
- }
-
- case _ =>
- }
- ctp match {
- case Type$ConstantType(base, value) =>
- ana.make.Literal(tree.pos, value).setType(ctp);
- case _ =>
- tree
- }
- }
+class ConstantFolder(g: scalac_Global) extends scalac_typechecker_ConstantFolder(g) {
+ // !!! rewrite
}
+
}
diff --git a/sources/scala/tools/scaladoc/SymbolTablePrinter.java b/sources/scala/tools/scaladoc/SymbolTablePrinter.java
index 25ea8e8bc7..b5a1db9dab 100644
--- a/sources/scala/tools/scaladoc/SymbolTablePrinter.java
+++ b/sources/scala/tools/scaladoc/SymbolTablePrinter.java
@@ -14,6 +14,7 @@ import ch.epfl.lamp.util.CodePrinter;
import ch.epfl.lamp.util.HTMLPrinter;
import scalac.Global;
+import scalac.atree.AConstant;
import scalac.symtab.*;
import scalac.symtab.Scope.SymbolIterator;
import scalac.symtab.Type.Constraint;
@@ -401,7 +402,7 @@ public abstract class SymbolTablePrinter extends scalac.symtab.SymbolTablePrinte
printUsedSymbolName(sym);
return this;
- case ConstantType(Type base, Object value):
+ case ConstantType(Type base, AConstant value):
printType(base);
// print("(");
// print(value.toString());
diff --git a/sources/scala/tools/scalai/ExpressionCompiler.java b/sources/scala/tools/scalai/ExpressionCompiler.java
index 8f76849ccd..35eb5edbca 100644
--- a/sources/scala/tools/scalai/ExpressionCompiler.java
+++ b/sources/scala/tools/scalai/ExpressionCompiler.java
@@ -13,6 +13,7 @@ import java.lang.reflect.Constructor;
import java.util.ArrayList;
import scalac.ast.Tree;
+import scalac.atree.AConstant;
import scalac.symtab.Symbol;
import scalac.symtab.Definitions;
import scalac.util.Debug;
@@ -166,8 +167,33 @@ public class ExpressionCompiler {
case This(_):
return Code.Self;
- case Literal(Object value):
- return Code.Literal(value);
+ case Literal(AConstant constant):
+ switch (constant) {
+ case UNIT:
+ return Code.Literal(constants.literal());
+ case BOOLEAN(boolean value):
+ return Code.Literal(new Boolean(value));
+ case BYTE(byte value):
+ return Code.Literal(new Byte(value));
+ case SHORT(short value):
+ return Code.Literal(new Short(value));
+ case CHAR(char value):
+ return Code.Literal(new Character(value));
+ case INT(int value):
+ return Code.Literal(new Integer(value));
+ case LONG(long value):
+ return Code.Literal(new Long(value));
+ case FLOAT(float value):
+ return Code.Literal(new Float(value));
+ case DOUBLE(double value):
+ return Code.Literal(new Double(value));
+ case STRING(String value):
+ return Code.Literal(new String(value));
+ case NULL:
+ return Code.Null;
+ default:
+ throw Debug.abort("illegal case", constant);
+ }
default:
return load(tree, tree.symbol());
diff --git a/sources/scalac/Global.java b/sources/scalac/Global.java
index 37e2ed95d9..3c24f16468 100644
--- a/sources/scalac/Global.java
+++ b/sources/scalac/Global.java
@@ -452,9 +452,8 @@ public class Global {
SET_EVALUATION_RESULT()),
new Tree[] {
last,
- make.Literal(last.pos,
- show(last.getType())).setType(
- definitions.JAVA_STRING_TYPE())});
+ treeGen.mkStringLit(
+ last.pos, show(last.getType()))});
}
TreeList body = new TreeList();
for (int j = 0; j < impl.body.length; j++)
@@ -484,8 +483,7 @@ public class Global {
treeGen.mkRef(tree.pos, INTERPRETER()),
SHOW_DEFINITION()),
new Tree[] {
- make.Literal(tree.pos, show(tree.symbol())).setType(
- definitions.JAVA_STRING_TYPE())}));
+ treeGen.mkStringLit(tree.pos, show(tree.symbol()))}));
return;
case ValDef(_, _, _, _):
if (!mustShow(tree.symbol())) return;
@@ -495,8 +493,7 @@ public class Global {
treeGen.mkRef(tree.pos, INTERPRETER()),
SHOW_VALUE_DEFINITION()),
new Tree[] {
- make.Literal(tree.pos, show(tree.symbol())).setType(
- definitions.JAVA_STRING_TYPE()),
+ treeGen.mkStringLit(tree.pos, show(tree.symbol())),
treeGen.Ident(tree.pos, tree.symbol())}));
return;
default:
diff --git a/sources/scalac/ast/Transformer.java.tmpl b/sources/scalac/ast/Transformer.java.tmpl
index 32f69eb3b5..69aef7dfca 100644
--- a/sources/scalac/ast/Transformer.java.tmpl
+++ b/sources/scalac/ast/Transformer.java.tmpl
@@ -265,8 +265,8 @@ public class GenTransformer {
Symbol symbol = getSymbolFor(tree);
return gen.Ident(tree.pos, symbol);
- case Literal(Object value):
- return gen.mkLit(tree.pos, value);
+ case Literal(AConstant value):
+ return gen.Literal(tree.pos, value);
case TypeTerm():
return gen.mkType(tree.pos, transform(tree.type()));
diff --git a/sources/scalac/ast/TreeGen.java b/sources/scalac/ast/TreeGen.java
index 2718287946..669f513c78 100644
--- a/sources/scalac/ast/TreeGen.java
+++ b/sources/scalac/ast/TreeGen.java
@@ -10,6 +10,7 @@ package scalac.ast;
import scalac.Global;
import scalac.ast.Tree.*;
+import scalac.atree.AConstant;
import scalac.symtab.*;
import scalac.typechecker.Infer;
import scalac.util.*;
@@ -94,154 +95,64 @@ public class TreeGen implements Kinds, Modifiers, TypeTags {
//########################################################################
// Public Methods - Building constants
- /** Builds a literal. */
- public Tree mkLit(int pos, Object value) {
- if (value instanceof Boolean) return mkBooleanLit(pos, (Boolean)value);
- if (value instanceof Byte) return mkByteLit(pos, (Byte)value);
- if (value instanceof Short) return mkShortLit(pos, (Short)value);
- if (value instanceof Character) return mkCharLit(pos,(Character)value);
- if (value instanceof Integer) return mkIntLit(pos, (Integer)value);
- if (value instanceof Long) return mkLongLit(pos, (Long)value);
- if (value instanceof Float) return mkFloatLit(pos, (Float)value);
- if (value instanceof Double) return mkDoubleLit(pos, (Double)value);
- if (value instanceof String) return mkStringLit(pos, (String)value);
- throw Debug.abort("unknown literal class " + value.getClass(), value);
- }
-
/** Builds a unit literal. */
public Tree mkUnitLit(int pos) {
- return Block(pos, Tree.EMPTY_ARRAY);
+ return Literal(pos, AConstant.UNIT);
}
/** Builds a boolean literal. */
public Tree mkBooleanLit(int pos, boolean value) {
- return mkBooleanLit(pos, value ? Boolean.TRUE : Boolean.FALSE);
- }
-
- /** Builds a boolean literal. */
- public Tree mkBooleanLit(int pos, Boolean value) {
- Tree tree = make.Literal(pos, value);
- global.nextPhase();
- tree.setType(definitions.BOOLEAN_TYPE());
- global.prevPhase();
- return tree;
+ return Literal(pos, AConstant.BOOLEAN(value));
}
/** Builds a byte literal. */
public Tree mkByteLit(int pos, byte value) {
- return mkByteLit(pos, new Byte(value));
- }
-
- /** Builds a byte literal. */
- public Tree mkByteLit(int pos, Byte value) {
- Tree tree = make.Literal(pos, value);
- global.nextPhase();
- tree.setType(definitions.BYTE_TYPE());
- global.prevPhase();
- return tree;
+ return Literal(pos, AConstant.BYTE(value));
}
/** Builds a short literal. */
public Tree mkShortLit(int pos, short value) {
- return mkShortLit(pos, new Short(value));
- }
-
- /** Builds a short literal. */
- public Tree mkShortLit(int pos, Short value) {
- Tree tree = make.Literal(pos, value);
- global.nextPhase();
- tree.setType(definitions.SHORT_TYPE());
- global.prevPhase();
- return tree;
+ return Literal(pos, AConstant.SHORT(value));
}
/** Builds a character literal. */
public Tree mkCharLit(int pos, char value) {
- return mkCharLit(pos, new Character(value));
- }
-
- /** Builds a character literal. */
- public Tree mkCharLit(int pos, Character value) {
- Tree tree = make.Literal(pos, value);
- global.nextPhase();
- tree.setType(definitions.CHAR_TYPE());
- global.prevPhase();
- return tree;
+ return Literal(pos, AConstant.CHAR(value));
}
/** Builds an integer literal */
public Tree mkIntLit(int pos, int value) {
- return mkIntLit(pos, new Integer(value));
- }
-
- /** Builds an integer literal */
- public Tree mkIntLit(int pos, Integer value) {
- Tree tree = make.Literal(pos, value);
- global.nextPhase();
- tree.setType(definitions.INT_TYPE());
- global.prevPhase();
- return tree;
+ return Literal(pos, AConstant.INT(value));
}
/** Builds a long literal. */
public Tree mkLongLit(int pos, long value) {
- return mkLongLit(pos, new Long(value));
- }
-
- /** Builds a long literal. */
- public Tree mkLongLit(int pos, Long value) {
- Tree tree = make.Literal(pos, value);
- global.nextPhase();
- tree.setType(definitions.LONG_TYPE());
- global.prevPhase();
- return tree;
+ return Literal(pos, AConstant.LONG(value));
}
/** Builds a float literal. */
public Tree mkFloatLit(int pos, float value) {
- return mkFloatLit(pos, new Float(value));
- }
-
- /** Builds a float literal. */
- public Tree mkFloatLit(int pos, Float value) {
- Tree tree = make.Literal(pos, value);
- global.nextPhase();
- tree.setType(definitions.FLOAT_TYPE());
- global.prevPhase();
- return tree;
+ return Literal(pos, AConstant.FLOAT(value));
}
/** Builds a double literal. */
public Tree mkDoubleLit(int pos, double value) {
- return mkDoubleLit(pos, new Double(value));
- }
-
- /** Builds a double literal. */
- public Tree mkDoubleLit(int pos, Double value) {
- Tree tree = make.Literal(pos, value);
- global.nextPhase();
- tree.setType(definitions.DOUBLE_TYPE());
- global.prevPhase();
- return tree;
+ return Literal(pos, AConstant.DOUBLE(value));
}
/** Builds a string literal. */
public Tree mkStringLit(int pos, String value) {
- Tree tree = make.Literal(pos, value);
- global.nextPhase();
- tree.setType(definitions.STRING_TYPE());
- global.prevPhase();
- return tree;
+ return Literal(pos, AConstant.STRING(value));
}
/** Builds a null literal. */
public Tree mkNullLit(int pos) {
- return Ident(pos, definitions.NULL);
+ return Literal(pos, AConstant.NULL);
}
/** Builds a zero literal. */
public Tree mkZeroLit(int pos) {
- return Ident(pos, definitions.ZERO);
+ return Literal(pos, AConstant.ZERO);
}
/** Builds a default zero value according to given type tag. */
@@ -269,6 +180,15 @@ public class TreeGen implements Kinds, Modifiers, TypeTags {
return mkZeroLit(pos);
}
+ /** Builds a Literal node of given value. */
+ public Literal Literal(int pos, AConstant value) {
+ Literal tree = make.Literal(pos, value);
+ global.nextPhase();
+ tree.setType(definitions.atyper.type(value));
+ global.prevPhase();
+ return tree;
+ }
+
//########################################################################
// Public Methods - Building references
diff --git a/sources/scalac/ast/parser/Parser.java b/sources/scalac/ast/parser/Parser.java
index d98324c970..12226aa922 100644
--- a/sources/scalac/ast/parser/Parser.java
+++ b/sources/scalac/ast/parser/Parser.java
@@ -32,6 +32,10 @@ public class Parser implements Tokens {
*/
TreeFactory make;
+ /** the tree generator
+ */
+ TreeGen gen;
+
/** pattern checker and normalizer
*/
PatternNormalizer pN;
@@ -43,6 +47,7 @@ public class Parser implements Tokens {
public Parser(Unit unit) {
s = new Scanner(unit);
make = unit.global.make;
+ gen = unit.global.treeGen;
pN = new PatternNormalizer( unit );
mapTreeComment = unit.global.mapTreeComment;
loopNestingDepth = 0;
@@ -620,38 +625,38 @@ public class Parser implements Tokens {
Tree t;
switch (s.token) {
case CHARLIT:
- t = make.Literal(s.pos, new Character((char)s.intVal));
+ t = gen.mkCharLit(s.pos, (char)s.intVal);
break;
case INTLIT:
- t = make.Literal(s.pos, new Integer((int)s.intVal));
+ t = gen.mkIntLit(s.pos, (int)s.intVal);
break;
case LONGLIT:
- t = make.Literal(s.pos, new Long(s.intVal));
+ t = gen.mkLongLit(s.pos, s.intVal);
break;
case FLOATLIT:
- t = make.Literal(s.pos, new Float((float)s.floatVal));
+ t = gen.mkFloatLit(s.pos, (float)s.floatVal);
break;
case DOUBLELIT:
- t = make.Literal(s.pos, new Double(s.floatVal));
+ t = gen.mkDoubleLit(s.pos, s.floatVal);
break;
case STRINGLIT:
- t = make.Literal(s.pos, s.name.toString());
+ t = gen.mkStringLit(s.pos, s.name.toString());
break;
case TRUE:
- t = make.Literal(s.pos, Boolean.TRUE);
+ t = gen.mkBooleanLit(s.pos, true);
break;
case FALSE:
- t = make.Literal(s.pos, Boolean.FALSE);
+ t = gen.mkBooleanLit(s.pos, false);
break;
case NULL:
- t = make.Ident(s.pos, Names.null_);
+ t = gen.mkNullLit(s.pos);
break;
case SYMBOLLIT:
int pos = s.pos;
Tree symt = scalaDot(s.pos, Names.Symbol);
if (isPattern) symt = convertToTypeId(symt);
TreeList ts = new TreeList();
- ts.append(make.Literal(s.pos, s.name.toString()));
+ ts.append(gen.mkStringLit(s.pos, s.name.toString()));
s.nextToken();
if (s.token == LPAREN || s.token == LBRACE)
ts.append(argumentExprs());
@@ -1171,10 +1176,10 @@ public class Parser implements Tokens {
new Tree.CaseDef[]{
(CaseDef)make.CaseDef(
rhs.pos, pat.duplicate(), Tree.Empty,
- make.Literal(s.pos, Boolean.TRUE)),
+ gen.mkBooleanLit(s.pos, true)),
(CaseDef)make.CaseDef(
rhs.pos, make.Ident(rhs.pos, Names.PATTERN_WILDCARD), Tree.Empty,
- make.Literal(s.pos, Boolean.FALSE))})});
+ gen.mkBooleanLit(s.pos, false))})});
return make.PatDef(pos, 0, pat, rhs);
}
diff --git a/sources/scalac/ast/printer/TextTreePrinter.java b/sources/scalac/ast/printer/TextTreePrinter.java
index 730c53fe06..cbe607b3b2 100644
--- a/sources/scalac/ast/printer/TextTreePrinter.java
+++ b/sources/scalac/ast/printer/TextTreePrinter.java
@@ -10,6 +10,7 @@
package scalac.ast.printer;
import scalac.ast.*;
+import scalac.atree.AConstant;
import scalac.symtab.*;
import scalac.util.Debug;
import scalac.Global;
@@ -558,15 +559,8 @@ public class TextTreePrinter implements TreePrinter {
printType(tree);
break;
- case Literal(Object obj):
- String str;
- if (obj instanceof String)
- str = "\"" + obj + "\"";
- else if (obj instanceof Character)
- str = "\'" + obj + "\'";
- else
- str = String.valueOf(obj);
- print(Text.Literal(str));
+ case Literal(AConstant value):
+ print(Text.Literal(value.toString()));
printType(tree);
break;
diff --git a/sources/scalac/atree/AConstant.java b/sources/scalac/atree/AConstant.java
index 626ab2a5da..4abd485f66 100644
--- a/sources/scalac/atree/AConstant.java
+++ b/sources/scalac/atree/AConstant.java
@@ -8,6 +8,8 @@
package scalac.atree;
+import scalac.util.Debug;
+
/** This class represents a constant. */
public class AConstant {
@@ -30,6 +32,347 @@ public class AConstant {
//########################################################################
// Public Methods
+ /** Returns the type kind of this constant. */
+ public ATypeKind kind() {
+ switch (this) {
+ case UNIT:
+ return ATypeKind.UNIT;
+ case BOOLEAN(_):
+ return ATypeKind.BOOL;
+ case BYTE(_):
+ return ATypeKind.I1;
+ case SHORT(_):
+ return ATypeKind.I2;
+ case CHAR(_):
+ return ATypeKind.U2;
+ case INT(_):
+ return ATypeKind.I4;
+ case LONG(_):
+ return ATypeKind.I8;
+ case FLOAT(_):
+ return ATypeKind.R4;
+ case DOUBLE(_):
+ return ATypeKind.R8;
+ case STRING(_):
+ return ATypeKind.STR;
+ case NULL:
+ return ATypeKind.NULL;
+ case ZERO:
+ return ATypeKind.ZERO;
+ default:
+ throw Debug.abort("unknown case", this);
+ }
+ }
+
+
+ /** Converts this constant to a boolean value. */
+ public boolean booleanValue() {
+ switch (this) {
+ case BOOLEAN(boolean value):
+ return value;
+ default:
+ throw Debug.abort("not convertible to boolean", this);
+ }
+ }
+
+ /** Converts this constant to a byte value. */
+ public byte byteValue() {
+ switch (this) {
+ case BYTE(byte value):
+ return (byte)value;
+ case SHORT(short value):
+ return (byte)value;
+ case CHAR(char value):
+ return (byte)value;
+ case INT(int value):
+ return (byte)value;
+ case LONG(long value):
+ return (byte)value;
+ case FLOAT(float value):
+ return (byte)value;
+ case DOUBLE(double value):
+ return (byte)value;
+ default:
+ throw Debug.abort("not convertible to byte", this);
+ }
+ }
+
+ /** Converts this constant to a short value. */
+ public short shortValue() {
+ switch (this) {
+ case BYTE(byte value):
+ return (short)value;
+ case SHORT(short value):
+ return (short)value;
+ case CHAR(char value):
+ return (short)value;
+ case INT(int value):
+ return (short)value;
+ case LONG(long value):
+ return (short)value;
+ case FLOAT(float value):
+ return (short)value;
+ case DOUBLE(double value):
+ return (short)value;
+ default:
+ throw Debug.abort("not convertible to short", this);
+ }
+ }
+
+ /** Converts this constant to a char value. */
+ public char charValue() {
+ switch (this) {
+ case BYTE(byte value):
+ return (char)value;
+ case SHORT(short value):
+ return (char)value;
+ case CHAR(char value):
+ return (char)value;
+ case INT(int value):
+ return (char)value;
+ case LONG(long value):
+ return (char)value;
+ case FLOAT(float value):
+ return (char)value;
+ case DOUBLE(double value):
+ return (char)value;
+ default:
+ throw Debug.abort("not convertible to char", this);
+ }
+ }
+
+ /** Converts this constant to a int value. */
+ public int intValue() {
+ switch (this) {
+ case BYTE(byte value):
+ return (int)value;
+ case SHORT(short value):
+ return (int)value;
+ case CHAR(char value):
+ return (int)value;
+ case INT(int value):
+ return (int)value;
+ case LONG(long value):
+ return (int)value;
+ case FLOAT(float value):
+ return (int)value;
+ case DOUBLE(double value):
+ return (int)value;
+ default:
+ throw Debug.abort("not convertible to int", this);
+ }
+ }
+
+ /** Converts this constant to a long value. */
+ public long longValue() {
+ switch (this) {
+ case BYTE(byte value):
+ return (long)value;
+ case SHORT(short value):
+ return (long)value;
+ case CHAR(char value):
+ return (long)value;
+ case INT(int value):
+ return (long)value;
+ case LONG(long value):
+ return (long)value;
+ case FLOAT(float value):
+ return (long)value;
+ case DOUBLE(double value):
+ return (long)value;
+ default:
+ throw Debug.abort("not convertible to long", this);
+ }
+ }
+
+ /** Converts this constant to a float value. */
+ public float floatValue() {
+ switch (this) {
+ case BYTE(byte value):
+ return (float)value;
+ case SHORT(short value):
+ return (float)value;
+ case CHAR(char value):
+ return (float)value;
+ case INT(int value):
+ return (float)value;
+ case LONG(long value):
+ return (float)value;
+ case FLOAT(float value):
+ return (float)value;
+ case DOUBLE(double value):
+ return (float)value;
+ default:
+ throw Debug.abort("not convertible to float", this);
+ }
+ }
+
+ /** Converts this constant to a double value. */
+ public double doubleValue() {
+ switch (this) {
+ case BYTE(byte value):
+ return (double)value;
+ case SHORT(short value):
+ return (double)value;
+ case CHAR(char value):
+ return (double)value;
+ case INT(int value):
+ return (double)value;
+ case LONG(long value):
+ return (double)value;
+ case FLOAT(float value):
+ return (double)value;
+ case DOUBLE(double value):
+ return (double)value;
+ default:
+ throw Debug.abort("not convertible to double", this);
+ }
+ }
+
+ /** Converts this constant to a String value. */
+ public String stringValue() {
+ switch (this) {
+ case UNIT:
+ return "()";
+ case BOOLEAN(boolean value):
+ return String.valueOf(value);
+ case BYTE(byte value):
+ return String.valueOf(value);
+ case SHORT(short value):
+ return String.valueOf(value);
+ case CHAR(char value):
+ return String.valueOf(value);
+ case INT(int value):
+ return String.valueOf(value);
+ case LONG(long value):
+ return String.valueOf(value);
+ case FLOAT(float value):
+ return String.valueOf(value);
+ case DOUBLE(double value):
+ return String.valueOf(value);
+ case STRING(String value):
+ return value;
+ case NULL:
+ return String.valueOf(null);
+ default:
+ throw Debug.abort("not convertible to String", this);
+ }
+ }
+
+ /** Tests whether this constant equals given Object. */
+ public boolean equals(Object that) {
+ if (this == that) return true;
+ return (that instanceof AConstant) && this.equals((AConstant)that);
+ }
+
+ /** Tests whether this constant equals given one. */
+ public boolean equals(AConstant that) {
+ if (this == that) return true;
+ if (null == that) return false;
+ switch (this) {
+ case BOOLEAN(boolean ivalue):
+ switch (that) {
+ case BOOLEAN(boolean avalue):
+ return ivalue == avalue;
+ default:
+ return false;
+ }
+ case BYTE(byte ivalue):
+ switch (that) {
+ case BYTE(byte avalue):
+ return ivalue == avalue;
+ default:
+ return false;
+ }
+ case SHORT(short ivalue):
+ switch (that) {
+ case SHORT(short avalue):
+ return ivalue == avalue;
+ default:
+ return false;
+ }
+ case CHAR(char ivalue):
+ switch (that) {
+ case CHAR(char avalue):
+ return ivalue == avalue;
+ default:
+ return false;
+ }
+ case INT(int ivalue):
+ switch (that) {
+ case INT(int avalue):
+ return ivalue == avalue;
+ default:
+ return false;
+ }
+ case LONG(long ivalue):
+ switch (that) {
+ case LONG(long avalue):
+ return ivalue == avalue;
+ default:
+ return false;
+ }
+ case FLOAT(float ivalue):
+ switch (that) {
+ case FLOAT(float avalue):
+ return ivalue == avalue;
+ default:
+ return false;
+ }
+ case DOUBLE(double ivalue):
+ switch (that) {
+ case DOUBLE(double avalue):
+ return ivalue == avalue;
+ default:
+ return false;
+ }
+ case STRING(String ivalue):
+ switch (that) {
+ case STRING(String avalue):
+ return ivalue.equals(avalue);
+ default:
+ return false;
+ }
+ default:
+ throw Debug.abort("unknown case", this);
+ }
+ }
+
+ /** Returns the hash code of this constant. */
+ public int hashCode() {
+ switch (this) {
+ case UNIT:
+ return 4041;
+ case BOOLEAN(boolean value):
+ return value ? 1231 : 1237;
+ case BYTE(byte value):
+ return value;
+ case SHORT(short value):
+ return value;
+ case CHAR(char value):
+ return value;
+ case INT(int value):
+ return value;
+ case LONG(long value):
+ long bits = value;
+ return (int)(bits ^ (bits >>> 32));
+ case FLOAT(float value):
+ int bits = java.lang.Float.floatToIntBits(value);
+ return bits;
+ case DOUBLE(double value):
+ long bits = java.lang.Double.doubleToLongBits(value);
+ return (int)(bits ^ (bits >>> 32));
+ case STRING(String value):
+ return value.hashCode();
+ case NULL:
+ return 0;
+ case ZERO:
+ return 0;
+ default:
+ throw Debug.abort("unknown case", this);
+ }
+ }
+
/** Returns a string representation of this constant. */
public String toString() {
return new ATreePrinter().printConstant(this).toString();
diff --git a/sources/scalac/atree/ATreeFromSTree.java b/sources/scalac/atree/ATreeFromSTree.java
index 6ffeeefef2..405875c0cf 100644
--- a/sources/scalac/atree/ATreeFromSTree.java
+++ b/sources/scalac/atree/ATreeFromSTree.java
@@ -231,8 +231,8 @@ public class ATreeFromSTree {
return make.Constant(tree, make.ZERO);
return make.Load(tree, location(tree));
- case Literal(Object value):
- return make.Constant(tree, constant(value));
+ case Literal(AConstant value):
+ return make.Constant(tree, value);
default:
throw Debug.abort("illegal case", tree);
@@ -311,21 +311,4 @@ public class ATreeFromSTree {
}
//########################################################################
- // Private Methods - Translating constants
-
- /** Translates the constant. */
- private AConstant constant(Object value) {
- if (value instanceof Boolean ) return make.BOOLEAN((Boolean )value);
- if (value instanceof Byte ) return make.BYTE (((Byte )value));
- if (value instanceof Short ) return make.SHORT ((Short )value);
- if (value instanceof Character) return make.CHAR ((Character)value);
- if (value instanceof Integer ) return make.INT ((Integer )value);
- if (value instanceof Long ) return make.LONG ((Long )value);
- if (value instanceof Float ) return make.FLOAT ((Float )value);
- if (value instanceof Double ) return make.DOUBLE ((Double )value);
- if (value instanceof String ) return make.STRING ((String )value);
- throw Debug.abort("illegal constant", value +" -- "+ value.getClass());
- }
-
- //########################################################################
}
diff --git a/sources/scalac/atree/ATreeTyper.java b/sources/scalac/atree/ATreeTyper.java
index dead4e7c40..70156802d5 100644
--- a/sources/scalac/atree/ATreeTyper.java
+++ b/sources/scalac/atree/ATreeTyper.java
@@ -25,6 +25,9 @@ public class ATreeTyper {
//########################################################################
// Private Fields
+ /** The global environment */
+ public final Global global;
+
/** The global definitions */
private final Definitions definitions;
@@ -32,8 +35,9 @@ public class ATreeTyper {
// Public Constructors
/** Initializes this instance. */
- public ATreeTyper(Global global) {
- this.definitions = global.definitions;
+ public ATreeTyper(Global global, Definitions definitions) {
+ this.global = global;
+ this.definitions = definitions;
}
//########################################################################
@@ -176,8 +180,15 @@ public class ATreeTyper {
/** Returns the type of the given constant. */
public Type type(AConstant constant) {
+ Type base = basetype(constant);
+ if (global.currentPhase.id > global.PHASE.ERASURE.id()) return base;
+ return Type.ConstantType(base, constant);
+ }
+
+ /** Returns the base type of the given constant. */
+ public Type basetype(AConstant constant) {
switch (constant) {
- case UNIT : return definitions.UNIT_CLASS.type();
+ case UNIT : return definitions.UNIT_TYPE();
case BOOLEAN(_): return definitions.BOOLEAN_TYPE();
case BYTE(_) : return definitions.BYTE_TYPE();
case SHORT(_) : return definitions.SHORT_TYPE();
@@ -199,6 +210,7 @@ public class ATreeTyper {
/** Returns the type of the given type kind. */
public Type type(ATypeKind kind) {
switch (kind) {
+ case UNIT: return definitions.UNIT_TYPE();
case BOOL: return definitions.BOOLEAN_TYPE();
// !!! case U1 : return ?;
case U2 : return definitions.CHAR_TYPE();
@@ -212,12 +224,15 @@ public class ATreeTyper {
case R8 : return definitions.DOUBLE_TYPE();
case REF : return definitions.ANYREF_TYPE();
case STR : return definitions.STRING_TYPE();
+ case NULL: return definitions.ALLREF_TYPE();
+ case ZERO: return definitions.ALL_TYPE();
default : throw Debug.abort("unknown case", kind);
}
}
//########################################################################
- // Public Methods - aliases of type() for scala
+ // Public Methods - Aliases for scala
+
public Type[] computeType(ACode[] codes) {
return type(codes);
}
diff --git a/sources/scalac/atree/ATypeKind.java b/sources/scalac/atree/ATypeKind.java
index 57b827473d..1be2eb540d 100644
--- a/sources/scalac/atree/ATypeKind.java
+++ b/sources/scalac/atree/ATypeKind.java
@@ -16,6 +16,9 @@ public class ATypeKind {
//########################################################################
// Public Cases
+ /** The unit value */
+ public case UNIT;
+
/** A boolean value */
public case BOOL;
@@ -55,12 +58,19 @@ public class ATypeKind {
/** A string reference */
public case STR;
+ /** The null reference */
+ public case NULL;
+
+ /** The zero value */
+ public case ZERO;
+
//########################################################################
// Public Methods
/** Returns a string representation of this type kind. */
public String toString() {
switch (this) {
+ case UNIT: return "UNIT";
case BOOL: return "BOOL";
case U1 : return "U1";
case U2 : return "U2";
@@ -74,6 +84,8 @@ public class ATypeKind {
case R8 : return "R8";
case REF : return "REF";
case STR : return "STR";
+ case NULL: return "NULL";
+ case ZERO: return "ZERO";
default : throw Debug.abort("unknown case", this);
}
}
diff --git a/sources/scalac/backend/jvm/GenJVM.java b/sources/scalac/backend/jvm/GenJVM.java
index 05e073abc5..58d9e6d55a 100644
--- a/sources/scalac/backend/jvm/GenJVM.java
+++ b/sources/scalac/backend/jvm/GenJVM.java
@@ -14,6 +14,7 @@ import scalac.*;
import scalac.backend.*;
import scalac.util.*;
import scalac.ast.*;
+import scalac.atree.AConstant;
import scalac.symtab.*;
import scalac.symtab.classfile.ClassfileConstants;
import scalac.symtab.classfile.Pickle;
@@ -530,37 +531,52 @@ class GenJVM {
generatedType = JAVA_LANG_OBJECT_T;
break;
- case Literal(Object value):
- if (value instanceof Integer) {
- generatedType = JType.INT;
- ctx.code.emitPUSH((Integer)value);
- } else if (value instanceof Short) {
- generatedType = JType.SHORT;
- ctx.code.emitPUSH((Short)value);
- } else if (value instanceof Byte) {
- generatedType = JType.BYTE;
- ctx.code.emitPUSH((Byte)value);
- } else if (value instanceof Long) {
- generatedType = JType.LONG;
- ctx.code.emitPUSH((Long)value);
- } else if (value instanceof Float) {
- generatedType = JType.FLOAT;
- ctx.code.emitPUSH((Float)value);
- } else if (value instanceof Double) {
- generatedType = JType.DOUBLE;
- ctx.code.emitPUSH((Double)value);
- } else if (value instanceof Character) {
- generatedType = JType.CHAR;
- ctx.code.emitPUSH((Character)value);
- } else if (value instanceof String) {
- generatedType = JAVA_LANG_STRING_T;
- ctx.code.emitPUSH((String)value);
- } else if (value instanceof Boolean) {
- generatedType = JType.BOOLEAN;
- ctx.code.emitPUSH((Boolean)value);
- } else
- throw global.fail("unknown literal " + value);
+ case Literal(UNIT):
+ maybeGenLoadUnit(ctx, expectedType);
+ generatedType = expectedType;
+ break;
+ case Literal(BOOLEAN(boolean value)):
+ ctx.code.emitPUSH(value);
+ generatedType = JType.BOOLEAN;
+ break;
+ case Literal(BYTE(byte value)):
+ ctx.code.emitPUSH(value);
+ generatedType = JType.BYTE;
+ break;
+ case Literal(SHORT(short value)):
+ ctx.code.emitPUSH(value);
+ generatedType = JType.SHORT;
+ break;
+ case Literal(CHAR(char value)):
+ ctx.code.emitPUSH(value);
+ generatedType = JType.CHAR;
+ break;
+ case Literal(INT(int value)):
+ ctx.code.emitPUSH(value);
+ generatedType = JType.INT;
break;
+ case Literal(LONG(long value)):
+ ctx.code.emitPUSH(value);
+ generatedType = JType.LONG;
+ break;
+ case Literal(FLOAT(float value)):
+ ctx.code.emitPUSH(value);
+ generatedType = JType.FLOAT;
+ break;
+ case Literal(DOUBLE(double value)):
+ ctx.code.emitPUSH(value);
+ generatedType = JType.DOUBLE;
+ break;
+ case Literal(STRING(String value)):
+ ctx.code.emitPUSH(value);
+ generatedType = JAVA_LANG_STRING_T;
+ break;
+ case Literal(NULL):
+ if (expectedType != JType.VOID) ctx.code.emitACONST_NULL();
+ generatedType = expectedType;
+ break;
+ case Literal(AConstant value):
+ throw Debug.abort("unknown literal", value);
case Empty:
case AbsTypeDef(_, _, _, _):
@@ -925,16 +941,27 @@ class GenJVM {
boolean isIntZero = false;
if (maxTypeIdx <= intTypeIdx) {
switch (args[i]) {
- case Literal(Object val):
+ case Literal(AConstant constant):
int intVal;
- if (val instanceof Number)
- intVal = ((Number)val).intValue();
- else if (val instanceof Character)
- intVal = ((Character)val).charValue();
- else if (val instanceof Boolean)
- intVal = ((Boolean)val).booleanValue() ? 1 : 0;
- else
- throw Debug.abort("unknown literal", val);
+ switch (constant) {
+ case BOOLEAN(boolean value):
+ intVal = value ? 1 : 0;
+ break;
+ case BYTE(byte value):
+ intVal = value;
+ break;
+ case SHORT(short value):
+ intVal = value;
+ break;
+ case CHAR(char value):
+ intVal = value;
+ break;
+ case INT(int value):
+ intVal = value;
+ break;
+ default:
+ throw Debug.abort("unknown literal", constant);
+ }
if (intVal == 0) {
isIntZero = true;
if (i == 0) prim = prim.swap();
@@ -1056,7 +1083,7 @@ class GenJVM {
String className;
switch (classNameLit) {
- case Literal(Object name): className = (String)name; break;
+ case Literal(STRING(String name)): className = name; break;
default: throw global.fail("invalid argument for oarray " + classNameLit);
}
diff --git a/sources/scalac/backend/msil/GenMSIL.java b/sources/scalac/backend/msil/GenMSIL.java
index 4f86ce8c29..5450241104 100644
--- a/sources/scalac/backend/msil/GenMSIL.java
+++ b/sources/scalac/backend/msil/GenMSIL.java
@@ -18,6 +18,7 @@ import scalac.util.Name;
import scalac.util.Names;
import scalac.util.Debug;
import scalac.ast.Tree;
+import scalac.atree.AConstant;
import Tree.*;
import scalac.symtab.Symbol;
import scalac.symtab.Scope;
@@ -554,10 +555,12 @@ public final class GenMSIL {
lastStatement = tmpLastStatement;
return check(store(var));
- case Typed(Literal(Object value), Tree tpe):
+ // !!! all Typed nodes are removed by phase ExplicitOuter
+ case Typed(Literal(AConstant value), Tree tpe):
log("Typed.Literal: " + Debug.show(tree));
return items.LiteralItem(type2MSILType(tpe.type), value);
+ // !!! all Typed nodes are removed by phase ExplicitOuter
case Typed(Tree expr, Tree tpe):
//log("gen.Typed: processing node: " + Debug.show(tree));
return gen(expr, type2MSILType(tpe.type));
@@ -591,7 +594,7 @@ public final class GenMSIL {
//log("gen.Super: generated item: " + retItem);
return retItem;
- case Literal(Object value):
+ case Literal(AConstant value):
//log("Literal: " + Debug.show(tree));
//log("\ttype = " + Debug.show(tree.type));
MSILType t = type2MSILType(tree.type);
@@ -621,7 +624,7 @@ public final class GenMSIL {
assert tags.length == bodies.length;
for (int i = 0; i < tags.length; i++) {
load(loc);
- loadLiteral(MSILType.I4, new Integer(tags[i]));
+ loadI4(tags[i]);
code.Emit(OpCodes.Bne_Un, nextCase);
load(gen(bodies[i]));
if (lastStatement)
@@ -725,7 +728,7 @@ public final class GenMSIL {
return items.StackItem(toType);
}
return item;
- case LiteralItem(MSILType type, Object value):
+ case LiteralItem(MSILType type, AConstant value):
//log("coercing Literal " + type + " -> " + toType);
switch (type) {
case REF(_): return item;
@@ -1379,8 +1382,8 @@ public final class GenMSIL {
case StackItem():
return (StackItem) that;
- case LiteralItem(MSILType type, Object value):
- return loadLiteral(type, value);
+ case LiteralItem(_, AConstant value):
+ return loadLiteral(value);
case SelfItem():
emitThis();
@@ -1504,66 +1507,122 @@ public final class GenMSIL {
case I2:
case I4:
case CHAR:
- int i = (obj instanceof Character) ?
+ return loadI4((obj instanceof Character) ?
(int)((Character) obj).charValue() :
- ((Number)obj).intValue();
-// int i = (type == MSILType.CHAR) ?
+ ((Number)obj).intValue());
+// return loadI4((type == MSILType.CHAR) ?
// (int)((Character) obj).charValue() :
-// ((Number)obj).intValue();
- switch (i) {
- case -1:code.Emit(OpCodes.Ldc_I4_M1); break;
- case 0: code.Emit(OpCodes.Ldc_I4_0); break;
- case 1: code.Emit(OpCodes.Ldc_I4_1); break;
- case 2: code.Emit(OpCodes.Ldc_I4_2); break;
- case 3: code.Emit(OpCodes.Ldc_I4_3); break;
- case 4: code.Emit(OpCodes.Ldc_I4_4); break;
- case 5: code.Emit(OpCodes.Ldc_I4_5); break;
- case 6: code.Emit(OpCodes.Ldc_I4_6); break;
- case 7: code.Emit(OpCodes.Ldc_I4_7); break;
- case 8: code.Emit(OpCodes.Ldc_I4_8); break;
- default:
- if (i >= -128 && i <= 127)
- code.Emit(OpCodes.Ldc_I4_S, i);
- else
- code.Emit(OpCodes.Ldc_I4, i);
- }
- break;
+// ((Number)obj).intValue());
case I8:
- code.Emit(OpCodes.Ldc_I8, ((Number)obj).longValue());
- break;
+ return loadI8(((Number)obj).longValue());
case R4:
- code.Emit(OpCodes.Ldc_R4, ((Number)obj).floatValue());
- break;
+ return loadR4(((Number)obj).floatValue());
case R8:
- code.Emit(OpCodes.Ldc_R8, ((Number)obj).doubleValue());
- break;
+ return loadR8(((Number)obj).doubleValue());
case BOOL:
- if (((Boolean)obj).booleanValue())
- code.Emit(OpCodes.Ldc_I4_1);
- else
- code.Emit(OpCodes.Ldc_I4_0);
- break;
+ return loadBool(((Boolean)obj).booleanValue());
case VOID:
- code.Emit(OpCodes.Ldsfld, tc.RUNTIME_UNIT_VAL);
- break;
+ return loadUnit();
case REF(Type refType):
if (obj == null) {
- code.Emit(OpCodes.Ldnull);
+ return loadNull();
} else if (refType == tc.STRING) {
- code.Emit(OpCodes.Ldstr, obj.toString());
+ return loadString(obj.toString());
} else {
throw new ApplicationError
("loadLiteral(): unexpected literal type: " + refType +
"; value = " + obj);
}
- break;
default:
throw new ApplicationError
("loadLiteral(): Unknown literal type: " + type);
}
- return items.StackItem(type);
} // genLiteral()
+ Item.StackItem loadLiteral(AConstant constant) {
+ switch (constant) {
+ case UNIT:
+ return loadUnit();
+ case BOOLEAN(boolean value):
+ return loadBool(value);
+ case BYTE(byte value):
+ return loadI4(value);
+ case SHORT(short value):
+ return loadI4(value);
+ case CHAR(char value):
+ return loadI4(value);
+ case INT(int value):
+ return loadI4(value);
+ case LONG(long value):
+ return loadI8(value);
+ case FLOAT(float value):
+ return loadR4(value);
+ case DOUBLE(double value):
+ return loadR8(value);
+ case STRING(String value):
+ return loadString(value);
+ case NULL:
+ return loadNull();
+ default:
+ throw Debug.abort("illegal case", constant);
+ }
+ }
+
+ Item.StackItem loadUnit() {
+ code.Emit(OpCodes.Ldsfld, tc.RUNTIME_UNIT_VAL);
+ return items.StackItem(MSILType.VOID);
+ }
+
+ Item.StackItem loadBool(boolean value) {
+ code.Emit(value ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0);
+ return items.StackItem(MSILType.BOOL);
+ }
+
+ Item.StackItem loadI4(int value) {
+ switch (value) {
+ case -1:code.Emit(OpCodes.Ldc_I4_M1); break;
+ case 0: code.Emit(OpCodes.Ldc_I4_0); break;
+ case 1: code.Emit(OpCodes.Ldc_I4_1); break;
+ case 2: code.Emit(OpCodes.Ldc_I4_2); break;
+ case 3: code.Emit(OpCodes.Ldc_I4_3); break;
+ case 4: code.Emit(OpCodes.Ldc_I4_4); break;
+ case 5: code.Emit(OpCodes.Ldc_I4_5); break;
+ case 6: code.Emit(OpCodes.Ldc_I4_6); break;
+ case 7: code.Emit(OpCodes.Ldc_I4_7); break;
+ case 8: code.Emit(OpCodes.Ldc_I4_8); break;
+ default:
+ if (value >= -128 && value <= 127)
+ code.Emit(OpCodes.Ldc_I4_S, value);
+ else
+ code.Emit(OpCodes.Ldc_I4, value);
+ }
+ return items.StackItem(MSILType.I4);
+ }
+
+ Item.StackItem loadI8(long value) {
+ code.Emit(OpCodes.Ldc_I8, value);
+ return items.StackItem(MSILType.I8);
+ }
+
+ Item.StackItem loadR4(float value) {
+ code.Emit(OpCodes.Ldc_R4, value);
+ return items.StackItem(MSILType.R4);
+ }
+
+ Item.StackItem loadR8(double value) {
+ code.Emit(OpCodes.Ldc_R8, value);
+ return items.StackItem(MSILType.R8);
+ }
+
+ Item.StackItem loadString(String value) {
+ code.Emit(OpCodes.Ldstr, value);
+ return items.StackItem(MSILType.STRING_REF);
+ }
+
+ Item.StackItem loadNull() {
+ code.Emit(OpCodes.Ldnull);
+ return items.StackItem(MSILType.NULL_REF);
+ }
/**
*/
@@ -1969,7 +2028,7 @@ class Item {
public case VoidItem();
public case StackItem();
public case SelfItem();
- public case LiteralItem(MSILType typ, Object value);
+ public case LiteralItem(MSILType typ, AConstant value);
public case ArgItem(int slot);
public case LocalItem(LocalBuilder local);
public case StaticItem(FieldInfo field);
@@ -1981,7 +2040,7 @@ class Item {
case VoidItem(): return "VoidItem: " + type;
case StackItem(): return "StackItem: " + type ;
case SelfItem(): return "this: " + type;
- case LiteralItem(_, Object value): return "LiteralItem(" + value + "): " + type;
+ case LiteralItem(_, AConstant value): return "LiteralItem(" + value + "): " + type;
case ArgItem( int slot): return "ArgItem(" + slot + "): " + type;
case LocalItem( LocalBuilder local): return "LocalItem(" + local + "): " + type;
case StaticItem( FieldInfo field): return "StaticItem(" + field + "): " + type;
@@ -2024,7 +2083,7 @@ class ItemFactory {
item.type = MSILType.REF(t);
return item;
}
- public Item.LiteralItem LiteralItem(MSILType type, Object value) {
+ public Item.LiteralItem LiteralItem(MSILType type, AConstant value) {
Item.LiteralItem item = Item.LiteralItem(type, value);
item.type = type;
return item;
diff --git a/sources/scalac/checkers/TreeChecker.java b/sources/scalac/checkers/TreeChecker.java
index e523df6238..9cb683595b 100644
--- a/sources/scalac/checkers/TreeChecker.java
+++ b/sources/scalac/checkers/TreeChecker.java
@@ -308,18 +308,7 @@ public class TreeChecker {
if (symbol == definitions.ZERO) return true;
return location(tree);
- case Literal(Object value):
- assert value != null: show(tree);
- if (value instanceof Boolean ) return true;
- if (value instanceof Byte ) return true;
- if (value instanceof Short ) return true;
- if (value instanceof Character) return true;
- if (value instanceof Integer ) return true;
- if (value instanceof Long ) return true;
- if (value instanceof Float ) return true;
- if (value instanceof Double ) return true;
- if (value instanceof String ) return true;
- assert false: show(tree) + format("value.class", value.getClass());
+ case Literal(_):
return true;
default:
diff --git a/sources/scalac/symtab/Definitions.java b/sources/scalac/symtab/Definitions.java
index aaac2ee960..1cfc8995f8 100644
--- a/sources/scalac/symtab/Definitions.java
+++ b/sources/scalac/symtab/Definitions.java
@@ -11,6 +11,7 @@ package scalac.symtab;
import ch.epfl.lamp.util.Position;
import scalac.Global;
+import scalac.atree.ATreeTyper;
import scalac.symtab.classfile.PackageParser;
import scalac.util.Debug;
import scalac.util.Name;
@@ -19,6 +20,12 @@ import scalac.util.Names;
public class Definitions {
//########################################################################
+ // Public Fields - Root module
+
+ /** The attributed tree typer */
+ public final ATreeTyper atyper;
+
+ //########################################################################
// Public Fields & Methods - Root module
/** The root module */
@@ -461,6 +468,8 @@ public class Definitions {
global.definitions = this;
// force initialization of class Type
Type.localThisType.symbol();
+ // create attributed tree typer
+ atyper = new ATreeTyper(global, this);
// the root module
ROOT = TermSymbol.newJavaPackageModule(
@@ -520,7 +529,6 @@ public class Definitions {
initAlias(ANYREF_CLASS, JAVA_OBJECT_TYPE());
initClass(ALLREF_CLASS, new Type[]{ANYREF_TYPE()});
initClass(ALL_CLASS, new Type[]{ANY_TYPE()});
- initAlias(STRING_CLASS, JAVA_STRING_TYPE());
// create type symbols
UNIT_TYPE = newTypeSymbol(Names.Unit , UNIT_CLASS.type ());
@@ -535,6 +543,9 @@ public class Definitions {
ARRAY_TYPE = newTypeSymbol(Names.Array ,
Type.appliedType(ARRAY_CLASS.type(), new Type[]{ANYREF_TYPE()}));
+ // initialize generated classes and aliases
+ initAlias(STRING_CLASS, JAVA_STRING_TYPE());
+
// add members to scala.Any
ANY_EQ = newTerm(ANY_CLASS, Names.eq , 0);
ANY_EQEQ = newTerm(ANY_CLASS, Names.EQEQ , Modifiers.FINAL);
diff --git a/sources/scalac/symtab/EntryTags.java b/sources/scalac/symtab/EntryTags.java
index ade0cb60bd..04cdcdc704 100644
--- a/sources/scalac/symtab/EntryTags.java
+++ b/sources/scalac/symtab/EntryTags.java
@@ -26,13 +26,25 @@ public interface EntryTags {
* | 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
+ * | 14 CONSTANTtpe len_Nat type_Ref constant_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
+ * | 24 LITERALunit len_Nat
+ * | 25 LITERALboolean len_Nat value_Byte
+ * | 26 LITERALbyte len_Nat value_Long
+ * | 27 LITERALshort len_Nat value_Long
+ * | 28 LITERALchar len_Nat value_Long
+ * | 29 LITERALint len_Nat value_Long
+ * | 30 LITERALlong len_Nat value_Long
+ * | 31 LITERALfloat len_Nat value_Long
+ * | 32 LITERALdouble len_Nat value_Long
+ * | 33 LITERALstring len_Nat name_Ref
+ * | 34 LITERALnull len_Nat
+ * | 35 LITERALzero len_Nat
* 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>
@@ -43,7 +55,6 @@ public interface EntryTags {
int TERMname = 1,
TYPEname = 2,
- NUMBER = 3,
NONEsym = 4,
TYPEsym = 5,
ALIASsym = 6,
@@ -63,7 +74,19 @@ public interface EntryTags {
UNBOXEDtpe = 20,
UNBOXEDARRAYtpe = 21,
FLAGGEDtpe = 22,
- ERRORtpe = 23;
+ ERRORtpe = 23,
+ LITERALunit = 24,
+ LITERALboolean = 25,
+ LITERALbyte = 26,
+ LITERALshort = 27,
+ LITERALchar = 28,
+ LITERALint = 29,
+ LITERALlong = 30,
+ LITERALfloat = 31,
+ LITERALdouble = 32,
+ LITERALstring = 33,
+ LITERALnull = 34,
+ LITERALzero = 35;
int firstSymTag = NONEsym, lastSymTag = VALsym;
int firstTypeTag = NOtpe, lastTypeTag = FLAGGEDtpe;
diff --git a/sources/scalac/symtab/SymbolTablePrinter.java b/sources/scalac/symtab/SymbolTablePrinter.java
index c23a6107eb..8cf3ce3608 100644
--- a/sources/scalac/symtab/SymbolTablePrinter.java
+++ b/sources/scalac/symtab/SymbolTablePrinter.java
@@ -13,6 +13,7 @@ import java.io.StringWriter;
import ch.epfl.lamp.util.CodePrinter;
import scalac.Global;
+import scalac.atree.AConstant;
import scalac.symtab.Type.Constraint;
import scalac.symtab.Scope.SymbolIterator;
import scalac.util.Name;
@@ -526,7 +527,7 @@ public class SymbolTablePrinter {
return this;
case SingleType(Type pre, Symbol sym):
return printPrefix(pre).printSymbolName(sym);
- case ConstantType(Type base, Object value):
+ case ConstantType(Type base, AConstant value):
return printType(base)
.print("(").print(value.toString()).print(")");
case CompoundType(Type[] parts, Scope members):
diff --git a/sources/scalac/symtab/Type.java b/sources/scalac/symtab/Type.java
index 7abd0133ff..d21cbba3ba 100644
--- a/sources/scalac/symtab/Type.java
+++ b/sources/scalac/symtab/Type.java
@@ -13,6 +13,7 @@ import java.util.HashMap;
import ch.epfl.lamp.util.Position;
import scalac.ApplicationError;
+import scalac.atree.AConstant;
import scalac.util.*;
import scalac.Global;
@@ -38,14 +39,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
/** 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;
- }
+ public case ConstantType(Type base, AConstant value);
/** pre.sym[args]
* sym represents a type
@@ -168,26 +162,8 @@ 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_CLASS.typeConstructor();
- else if (value instanceof Integer)
- return Global.instance.definitions.INT_CLASS.typeConstructor();
- else if (value instanceof Long)
- return Global.instance.definitions.LONG_CLASS.typeConstructor();
- else if (value instanceof Float)
- return Global.instance.definitions.FLOAT_CLASS.typeConstructor();
- else if (value instanceof Double)
- return Global.instance.definitions.DOUBLE_CLASS.typeConstructor();
- else if (value instanceof String)
- return Global.instance.definitions.JAVA_STRING_CLASS.typeConstructor();
- else if (value instanceof Boolean)
- return Global.instance.definitions.BOOLEAN_CLASS.typeConstructor();
- else throw new ApplicationError();
+ public static Type constantType(AConstant value) {
+ return Global.instance.definitions.atyper.type(value);
}
public static Type singleTypeMethod(Type pre, Symbol sym) {
@@ -690,62 +666,6 @@ 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 value.toString();
- 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?
@@ -1098,7 +1018,7 @@ 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):
+ case ConstantType(Type base, AConstant value):
Type base1 = apply(base);
if (base1 == base) return tp;
else return new ConstantType(base1, value);
@@ -1961,15 +1881,20 @@ 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;
+ case ConstantType(_, _):
+ switch (this) {
+ case ConstantType(Type base, _):
+ return this.isSameAs(that) || base.isSubType(that);
+ }
+ break;
+
case TypeRef(Type pre1, Symbol sym1, Type[] args1):
switch (this) {
case TypeRef(Type pre, Symbol sym, Type[] args):
@@ -2062,7 +1987,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
case SingleType(_, _):
if (this.singleDeref().isSubType(that)) return true;
break;
- case ConstantType(_, Object value):
+ case ConstantType(_, _):
if (this.singleDeref().isSubType(that)) return true;
break;
case TypeVar(Type origin, Constraint constr):
@@ -2251,9 +2176,9 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
}
break;
- case ConstantType(Type base, Object value):
+ case ConstantType(Type base, AConstant value):
switch (that) {
- case ConstantType(Type base1, Object value1):
+ case ConstantType(Type base1, AConstant value1):
return base.isSameAs(base1) && value.equals(value1);
}
break;
@@ -3278,7 +3203,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
return SINGLEtpe
^ (pre.hashCode() * 41)
^ (sym.hashCode() * (41*41));
- case ConstantType(Type base, Object value):
+ case ConstantType(Type base, AConstant value):
return CONSTANTtpe
^ (base.hashCode() * 41)
^ (value.hashCode() * (41*41));
@@ -3350,9 +3275,9 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags {
return pre.equals(pre1) && sym == sym1;
default: return false;
}
- case ConstantType(Type base, Object value):
+ case ConstantType(Type base, AConstant value):
switch (that) {
- case ConstantType(Type base1, Object value1):
+ case ConstantType(Type base1, AConstant value1):
return base.equals(base1) && value.equals(value1);
default: return false;
}
diff --git a/sources/scalac/symtab/classfile/AttributeParser.java b/sources/scalac/symtab/classfile/AttributeParser.java
index dc982c23af..83bc52e94d 100644
--- a/sources/scalac/symtab/classfile/AttributeParser.java
+++ b/sources/scalac/symtab/classfile/AttributeParser.java
@@ -10,6 +10,7 @@ package scalac.symtab.classfile;
import ch.epfl.lamp.util.Position;
import scalac.*;
+import scalac.atree.AConstant;
import scalac.symtab.*;
import scalac.util.*;
import java.util.*;
@@ -169,13 +170,28 @@ public class AttributeParser implements ClassfileConstants {
/** return the constant type for the given constant.
*/
Type constantType(Type base, Object value) {
+ return Type.constantType(constantValue(base, value));
+ }
+ AConstant constantValue(Type base, Object value) {
+ if (base.symbol() == parser.global.definitions.BOOLEAN_CLASS)
+ return AConstant.BOOLEAN(((Number)value).intValue() != 0);
if (base.symbol() == parser.global.definitions.BYTE_CLASS)
- value = new Byte(((Number)value).byteValue());
- if (base.symbol() == parser.global.definitions.CHAR_CLASS)
- value = new Character((char)((Number)value).intValue());
+ return AConstant.BYTE(((Number)value).byteValue());
if (base.symbol() == parser.global.definitions.SHORT_CLASS)
- value = new Short(((Number)value).shortValue());
- return Type.ConstantType(base, value);
+ return AConstant.SHORT(((Number)value).shortValue());
+ if (base.symbol() == parser.global.definitions.CHAR_CLASS)
+ return AConstant.CHAR((char)((Number)value).intValue());
+ if (base.symbol() == parser.global.definitions.INT_CLASS)
+ return AConstant.INT(((Number)value).intValue());
+ if (base.symbol() == parser.global.definitions.LONG_CLASS)
+ return AConstant.LONG(((Number)value).longValue());
+ if (base.symbol() == parser.global.definitions.FLOAT_CLASS)
+ return AConstant.FLOAT(((Number)value).floatValue());
+ if (base.symbol() == parser.global.definitions.DOUBLE_CLASS)
+ return AConstant.DOUBLE(((Number)value).doubleValue());
+ if (base.symbol() == parser.global.definitions.JAVA_STRING_CLASS)
+ return AConstant.STRING((String)value);
+ throw Debug.abort("illegal value", value + " - " + base);
}
/** return the type of a given constant.
diff --git a/sources/scalac/symtab/classfile/Pickle.java b/sources/scalac/symtab/classfile/Pickle.java
index 7309f4d8d7..c43b56fef0 100644
--- a/sources/scalac/symtab/classfile/Pickle.java
+++ b/sources/scalac/symtab/classfile/Pickle.java
@@ -13,6 +13,7 @@ import java.util.HashMap;
import java.io.*;
import scalac.Global;
import scalac.ApplicationError;
+import scalac.atree.AConstant;
import scalac.util.*;
import scalac.symtab.*;
import Symbol.*;
@@ -169,9 +170,9 @@ public class Pickle implements Kinds, Modifiers, EntryTags {
putType(pre);
putSymbol(sym);
break;
- case ConstantType(Type base, Object value):
+ case ConstantType(Type base, AConstant value):
putType(base);
- putEntry(value);
+ putConstant(value);
break;
case TypeRef(Type pre, Symbol sym, Type[] args):
putType(pre);
@@ -212,6 +213,16 @@ public class Pickle implements Kinds, Modifiers, EntryTags {
putType(tps[i]);
}
+ private void putConstant(AConstant constant) {
+ if (putEntry(constant)) {
+ switch (constant) {
+ case STRING(String value):
+ putEntry(Name.fromString(value));
+ return;
+ }
+ }
+ }
+
/* **************************************************
* Phase 2: Write byte array
************************************************* */
@@ -294,15 +305,6 @@ 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) {
@@ -390,7 +392,7 @@ public class Pickle implements Kinds, Modifiers, EntryTags {
writeRef(sym);
break;
- case ConstantType(Type base, Object value):
+ case ConstantType(Type base, AConstant value):
writeByte(CONSTANTtpe);
writeByte(0); // space for length
writeRef(base);
@@ -452,6 +454,72 @@ public class Pickle implements Kinds, Modifiers, EntryTags {
writeRef(ft.type);
}
+ /** Write a constant entry.
+ */
+ private void writeConstant(AConstant constant) {
+ switch (constant) {
+ case UNIT:
+ writeByte(LITERALunit);
+ writeByte(0); // space for length
+ return;
+ case BOOLEAN(boolean value):
+ writeByte(LITERALboolean);
+ writeByte(0); // space for length
+ writeByte(value ? 1 : 0);
+ return;
+ case BYTE(byte value):
+ writeByte(LITERALbyte);
+ writeByte(0); // space for length
+ writeLong(value);
+ return;
+ case SHORT(short value):
+ writeByte(LITERALshort);
+ writeByte(0); // space for length
+ writeLong(value);
+ return;
+ case CHAR(char value):
+ writeByte(LITERALchar);
+ writeByte(0); // space for length
+ writeLong(value);
+ return;
+ case INT(int value):
+ writeByte(LITERALint);
+ writeByte(0); // space for length
+ writeLong(value);
+ return;
+ case LONG(long value):
+ writeByte(LITERALlong);
+ writeByte(0); // space for length
+ writeLong(value);
+ return;
+ case FLOAT(float value):
+ writeByte(LITERALfloat);
+ writeByte(0); // space for length
+ writeLong(Float.floatToIntBits(value));
+ return;
+ case DOUBLE(double value):
+ writeByte(LITERALdouble);
+ writeByte(0); // space for length
+ writeLong(Double.doubleToLongBits(value));
+ return;
+ case STRING(String value):
+ writeByte(LITERALstring);
+ writeByte(0); // space for length
+ writeRef(Name.fromString(value));
+ return;
+ case NULL:
+ writeByte(LITERALnull);
+ writeByte(0); // space for length
+ return;
+ case ZERO:
+ writeByte(LITERALzero);
+ writeByte(0); // space for length
+ return;
+ default:
+ throw Debug.abort("unknown case", constant);
+ }
+ }
+
private void writeEntry(Object e) {
int startpos = bp;
if (e instanceof Symbol)
@@ -462,24 +530,8 @@ public class Pickle implements Kinds, Modifiers, EntryTags {
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 if (e instanceof AConstant)
+ writeConstant((AConstant)e);
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 9e2f687d5f..5939455f30 100644
--- a/sources/scalac/symtab/classfile/UnPickle.java
+++ b/sources/scalac/symtab/classfile/UnPickle.java
@@ -11,6 +11,7 @@ package scalac.symtab.classfile;
import java.util.HashMap;
import java.io.PrintStream;
import scalac.*;
+import scalac.atree.AConstant;
import scalac.util.*;
import ch.epfl.lamp.util.Position;
import scalac.symtab.*;
@@ -338,7 +339,7 @@ public class UnPickle implements Kinds, Modifiers, EntryTags, TypeTags {
break;
case CONSTANTtpe:
Type base = readTypeRef();
- Object value = readValueRef(base);
+ AConstant value = readConstantRef();
tpe = new Type.ConstantType(base, value);
break;
case TYPEREFtpe:
@@ -445,43 +446,46 @@ public class UnPickle implements Kinds, Modifiers, EntryTags, TypeTags {
return flags;
}
- long getNumber(int n) {
- int savedBp = bp;
- bp = index[n];
+ AConstant readConstant() {
int tag = bytes[bp++];
- long x = readLong(readNat());
- bp = savedBp;
- return x;
+ int len = readNat();
+ switch (tag) {
+ case LITERALunit:
+ return AConstant.UNIT;
+ case LITERALboolean:
+ return AConstant.BOOLEAN(readByte() == 0 ? false : true);
+ case LITERALbyte:
+ return AConstant.BYTE((byte)readLong(len));
+ case LITERALshort:
+ return AConstant.SHORT((short)readLong(len));
+ case LITERALchar:
+ return AConstant.CHAR((char)readLong(len));
+ case LITERALint:
+ return AConstant.INT((int)readLong(len));
+ case LITERALlong:
+ return AConstant.LONG(readLong(len));
+ case LITERALfloat:
+ return AConstant.FLOAT(Float.intBitsToFloat((int)readLong(len)));
+ case LITERALdouble:
+ return AConstant.DOUBLE(Double.longBitsToDouble(readLong(len)));
+ case LITERALstring:
+ return AConstant.STRING(readNameRef().toString());
+ case LITERALnull:
+ return AConstant.NULL;
+ case LITERALzero:
+ return AConstant.ZERO;
+ default:
+ throw Debug.abort("illegal tag: " + tag);
+ }
}
- 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);
- default:
- if (base.symbol() == Global.instance.definitions.JAVA_STRING_CLASS)
- return readNameRef().toString();
- else
- throw new ApplicationError("bad constant base type: " + base);
- }
+ AConstant readConstantRef() {
+ int n = readNat();
+ int savedBp = bp;
+ bp = index[n];
+ AConstant constant = readConstant();
+ bp = savedBp;
+ return constant;
}
public static class BadSignature extends java.lang.Error {
@@ -519,6 +523,18 @@ public class UnPickle implements Kinds, Modifiers, EntryTags, TypeTags {
case UNBOXEDARRAYtpe: return "UNBOXEDARRAYtpe";
case FLAGGEDtpe: return "FLAGGEDtpe";
case ERRORtpe: return "ERRORtpe";
+ case LITERALunit: return "LITERALunit";
+ case LITERALboolean: return "LITERALboolean";
+ case LITERALbyte: return "LITERALbyte";
+ case LITERALshort: return "LITERALshort";
+ case LITERALchar: return "LITERALchar";
+ case LITERALint: return "LITERALint";
+ case LITERALlong: return "LITERALlong";
+ case LITERALfloat: return "LITERALfloat";
+ case LITERALdouble: return "LITERALdouble";
+ case LITERALstring: return "LITERALstring";
+ case LITERALnull: return "LITERALnull";
+ case LITERALzero: return "LITERALzero";
default: return "***BAD TAG***(" + tag + ")";
}
}
diff --git a/sources/scalac/transformer/Erasure.java b/sources/scalac/transformer/Erasure.java
index acb14659cb..7d7a4c2659 100644
--- a/sources/scalac/transformer/Erasure.java
+++ b/sources/scalac/transformer/Erasure.java
@@ -26,6 +26,7 @@ import scalac.ast.Tree.AliasTypeDef;
import scalac.ast.Tree.ValDef;
import scalac.ast.TreeList;
import scalac.ast.GenTransformer;
+import scalac.atree.AConstant;
import scalac.symtab.Definitions;
import scalac.symtab.Kinds;
import scalac.symtab.Type;
@@ -221,6 +222,9 @@ public class Erasure extends GenTransformer implements Modifiers {
if (symbol == definitions.ZERO) return gen.mkNullLit(tree.pos);
return gen.Ident(tree.pos, symbol);
+ case Literal(AConstant.ZERO):
+ return gen.mkNullLit(tree.pos);
+
case Block(_):
case If(_, _, _):
case Switch(_, _, _, _):
@@ -276,9 +280,6 @@ public class Erasure extends GenTransformer implements Modifiers {
Tree value = transform(gen.mkDefaultValue(tree.pos, pt), pt);
return gen.mkBlock(new Tree[] {transform(tree), value});
- case Typed(Tree expr, _): // !!!
- return transform(expr, pt);
-
case LabelDef(_, _, _):
case Assign(_, _):
case New(_):
diff --git a/sources/scalac/transformer/matching/AlgebraicMatcher.java b/sources/scalac/transformer/matching/AlgebraicMatcher.java
index 7c564882b3..681ced6c8c 100644
--- a/sources/scalac/transformer/matching/AlgebraicMatcher.java
+++ b/sources/scalac/transformer/matching/AlgebraicMatcher.java
@@ -10,6 +10,7 @@ package scalac.transformer.matching;
import scalac.*;
import scalac.ast.*;
+import scalac.atree.AConstant;
import scalac.symtab.*;
import PatternNode.*;
@@ -86,9 +87,9 @@ public class AlgebraicMatcher extends PatternMatcher {
return q.type.isSubType(p.type);
}
return false;
- case ConstantPat( Object pval ):
+ case ConstantPat( AConstant pval ):
switch (q) {
- case ConstantPat( Object qval ):
+ case ConstantPat( AConstant qval ):
return pval.equals(qval);
}
return false;
diff --git a/sources/scalac/transformer/matching/BerrySethi.java b/sources/scalac/transformer/matching/BerrySethi.java
index dd50fac722..2a1aecf29e 100644
--- a/sources/scalac/transformer/matching/BerrySethi.java
+++ b/sources/scalac/transformer/matching/BerrySethi.java
@@ -379,7 +379,7 @@ class BerrySethi {
return ;
- case Literal( Object val ):
+ case Literal( _ ):
Label label = new Label.SimpleLabel( (Literal) pat );
seenLabel( pat, label ) ;
@@ -624,7 +624,7 @@ class BerrySethi {
it.hasNext(); ) {
Tree t = (Tree) it.next();
switch(t) {
- case Literal( Object value ):
+ case Literal( _ ):
System.out.print( "(" + t.toString() + " -> ");
String s2 = ((Integer) posMap.get(t)).toString();
System.out.print( s2 +") ");
diff --git a/sources/scalac/transformer/matching/CodeFactory.java b/sources/scalac/transformer/matching/CodeFactory.java
index fb80e66ae7..36c4a29683 100644
--- a/sources/scalac/transformer/matching/CodeFactory.java
+++ b/sources/scalac/transformer/matching/CodeFactory.java
@@ -150,32 +150,32 @@ class CodeFactory extends PatternTool {
// unused
public Tree Negate(Tree tree) {
switch (tree) {
- case Literal(Object value):
- return gen.mkBooleanLit(tree.pos, !((Boolean)value).booleanValue());
+ case Literal(BOOLEAN(boolean value)):
+ return gen.mkBooleanLit(tree.pos, !value);
}
return gen.mkApply__(gen.Select(tree, defs.BOOLEAN_NOT()));
}
protected Tree And(Tree left, Tree right) {
switch (left) {
- case Literal(Object value):
- return ((Boolean)value).booleanValue() ? right : left;
+ case Literal(BOOLEAN(boolean value)):
+ return value ? right : left;
}
switch (right) {
- case Literal(Object value):
- if (((Boolean)value).booleanValue()) return left;
+ case Literal(BOOLEAN(boolean value)):
+ if (value) return left;
}
return gen.mkApply_V(gen.Select(left, defs.BOOLEAN_AND()), new Tree[]{right});
}
protected Tree Or(Tree left, Tree right) {
switch (left) {
- case Literal(Object value):
- return ((Boolean)value).booleanValue() ? left : right;
+ case Literal(BOOLEAN(boolean value)):
+ return value ? left : right;
}
switch (right) {
- case Literal(Object value):
- if (!((Boolean)value).booleanValue()) return left;
+ case Literal(BOOLEAN(boolean value)):
+ if (!value) return left;
}
return gen.mkApply_V(gen.Select(left, defs.BOOLEAN_OR()), new Tree[]{right});
}
diff --git a/sources/scalac/transformer/matching/LeftTracerInScala.java b/sources/scalac/transformer/matching/LeftTracerInScala.java
index 6bdd4c95dd..4c02ce28dc 100644
--- a/sources/scalac/transformer/matching/LeftTracerInScala.java
+++ b/sources/scalac/transformer/matching/LeftTracerInScala.java
@@ -134,7 +134,7 @@ public class LeftTracerInScala extends TracerInScala {
gen.Ident( cf.pos, accumSym ));
//return callFun( new Tree[] { newAcc , _iter(), gen.mkIntLit( cf.pos, target )} );
- return callFun( new Tree[] { gen.mkIntLit( cf.pos, target ), newAcc } );
+ return callFun( new Tree[] { gen.mkIntLit( cf.pos, target.intValue() ), newAcc } );
}
diff --git a/sources/scalac/transformer/matching/PatternMatcher.java b/sources/scalac/transformer/matching/PatternMatcher.java
index 2db3b81164..b2c45278ef 100644
--- a/sources/scalac/transformer/matching/PatternMatcher.java
+++ b/sources/scalac/transformer/matching/PatternMatcher.java
@@ -11,6 +11,7 @@ package scalac.transformer.matching;
import ch.epfl.lamp.util.Position;
import scalac.*;
import scalac.ast.*;
+import scalac.atree.AConstant;
import scalac.util.*;
import scalac.symtab.*;
import PatternNode.*;
@@ -134,7 +135,7 @@ public class PatternMatcher extends PatternTool {
if (patNode.or != null)
print(patNode.or, indent);
break;
- case ConstantPat(Object value):
+ case ConstantPat(AConstant value):
String s = "-- CONST(" + value + ") -> ";
String ind = indent;
indent = (patNode.or != null) ?
@@ -376,7 +377,7 @@ public class PatternMatcher extends PatternTool {
return mk.ConstrPat(tree.pos, tree.type);
else
return mk.VariablePat(tree.pos, tree);
- case Literal(Object value):
+ case Literal(AConstant value):
return mk.ConstantPat(tree.pos, tree.type, value);
case Sequence(Tree[] ts):
if ( !delegateSequenceMatching ) {
@@ -691,10 +692,10 @@ public class PatternMatcher extends PatternTool {
// for one case we use a normal if-then-else instruction
else if (ncases == 1) {
switch (root.and.or) {
- case ConstantPat(Object value):
+ case ConstantPat(AConstant value):
return gen.If(
cf.Equals(selector,
- gen.mkLit(root.and.or.pos, value)),
+ gen.Literal(root.and.or.pos, value)),
bodyToTree(root.and.or.and),
defaultBody(root.and, matchError));
default:
@@ -717,9 +718,9 @@ public class PatternMatcher extends PatternTool {
defaultBody = bodyToTree(node.and);
node = node.or;
break;
- case ConstantPat(Object value):
+ case ConstantPat(INT(int value)):
mappings = insert(
- ((Integer)value).intValue(),
+ value,
bodyToTree(node.and),
mappings);
node = node.or;
@@ -943,10 +944,10 @@ public class PatternMatcher extends PatternTool {
gen.mkAsInstanceOf(selector.duplicate(), node.type)),
toTree(node.and)}),
toTree(node.or, selector.duplicate()));
- case ConstantPat(Object value):
+ case ConstantPat(AConstant value):
return gen.If(
cf.Equals(selector.duplicate(),
- gen.mkLit(selector.pos, value)),
+ gen.Literal(selector.pos, value)),
toTree(node.and),
toTree(node.or, selector.duplicate()));
case VariablePat(Tree tree):
diff --git a/sources/scalac/transformer/matching/PatternNode.java b/sources/scalac/transformer/matching/PatternNode.java
index 89cc6c5d5f..b1d871b9b5 100644
--- a/sources/scalac/transformer/matching/PatternNode.java
+++ b/sources/scalac/transformer/matching/PatternNode.java
@@ -11,6 +11,7 @@ package scalac.transformer.matching;
import ch.epfl.lamp.util.Position;
import scalac.*;
import scalac.ast.*;
+import scalac.atree.AConstant;
import scalac.symtab.*;
import scalac.typechecker.*;
@@ -27,7 +28,7 @@ public class PatternNode {
public case Body(Tree.ValDef[][] bound, Tree[] guard, Tree[] body);
public case DefaultPat();
public case ConstrPat(Symbol casted);
- public case ConstantPat(Object value);
+ public case ConstantPat(AConstant value);
public case VariablePat(Tree tree);
public case AltPat(Header subheader);
public case SequencePat(Symbol casted, int len); // only used in PatternMatcher
@@ -54,7 +55,7 @@ public class PatternNode {
case SeqContainerPat(Symbol casted, Tree seqpat):
res = SeqContainerPat(casted, seqpat);
break;
- case ConstantPat(Object value):
+ case ConstantPat(AConstant value):
res = ConstantPat(value);
break;
case VariablePat(Tree tree):
@@ -149,9 +150,9 @@ public class PatternNode {
return (plen == qlen) && q.type.isSubType(this.type);
}
return false;
- case ConstantPat(Object pval):
+ case ConstantPat(AConstant pval):
switch (q) {
- case ConstantPat(Object qval):
+ case ConstantPat(AConstant qval):
return pval.equals(qval);
}
return false;
@@ -182,7 +183,7 @@ public class PatternNode {
return "SequencePat(" + casted + ", " + len + "...)";
case SeqContainerPat(Symbol casted, Tree seqpat):
return "SeqContainerPat(" + casted + ", " + seqpat + ")";
- case ConstantPat(Object value):
+ case ConstantPat(AConstant value):
return "ConstantPat(" + value + ")";
case VariablePat(Tree tree):
return "VariablePat";
diff --git a/sources/scalac/transformer/matching/PatternNodeCreator.java b/sources/scalac/transformer/matching/PatternNodeCreator.java
index d0a2cddef1..dedae105d0 100644
--- a/sources/scalac/transformer/matching/PatternNodeCreator.java
+++ b/sources/scalac/transformer/matching/PatternNodeCreator.java
@@ -4,6 +4,7 @@ import ch.epfl.lamp.util.Position;
import scalac.*;
import scalac.ast.*;
+import scalac.atree.AConstant;
import scalac.util.*;
import scalac.symtab.*;
import PatternNode.*;
@@ -56,7 +57,7 @@ public class PatternNodeCreator extends PatternTool {
return node;
}
- public static ConstantPat ConstantPat(int pos, Type type, Object value) {
+ public static ConstantPat ConstantPat(int pos, Type type, AConstant value) {
ConstantPat node = new ConstantPat( value );
node.pos = pos;
node.type = type;
diff --git a/sources/scalac/transformer/matching/RightTracerInScala.java b/sources/scalac/transformer/matching/RightTracerInScala.java
index c0265370c1..028b7e2bd2 100644
--- a/sources/scalac/transformer/matching/RightTracerInScala.java
+++ b/sources/scalac/transformer/matching/RightTracerInScala.java
@@ -213,7 +213,7 @@ public class RightTracerInScala extends TracerInScala {
tmapTag.put( targetL, I );
tmapBody.put( I, callFun( new Tree[] {
cf.SeqTrace_tail( _iter() ),
- gen.mkIntLit( cf.pos, targetR ) }));
+ gen.mkIntLit( cf.pos, targetR.intValue() ) }));
}
i = 0;
int[] tags = new int[ n ];
@@ -234,7 +234,7 @@ public class RightTracerInScala extends TracerInScala {
Tree currentMatches( Label label ) {
switch( label ) {
case Pair( Integer target, Label theLab ):
- return cf.Equals( gen.mkIntLit( cf.pos, target ),
+ return cf.Equals( gen.mkIntLit( cf.pos, target.intValue() ),
current() );
}
throw new ApplicationError("expected Pair label");
@@ -431,7 +431,7 @@ System.out.println("RightTracerInScala - the seqVars"+seqVars);
stms[ j++ ] = algMatchTree ;
stms[ j ] = callFun( new Tree[] { cf.SeqTrace_tail( _iter() ),
- gen.mkIntLit( cf.pos, ntarget ) } );
+ gen.mkIntLit( cf.pos, ntarget.intValue() ) } );
return gen.mkBlock( pos, stms );
}
diff --git a/sources/scalac/typechecker/Analyzer.java b/sources/scalac/typechecker/Analyzer.java
index 9c7b5fbaf0..7099163995 100644
--- a/sources/scalac/typechecker/Analyzer.java
+++ b/sources/scalac/typechecker/Analyzer.java
@@ -20,6 +20,7 @@ import ch.epfl.lamp.util.Pair;
import scalac.*;
import scalac.util.*;
import scalac.ast.*;
+import scalac.atree.AConstant;
import scalac.ast.printer.*;
import scalac.symtab.*;
import scalac.symtab.classfile.*;
@@ -41,7 +42,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
this.definitions = global.definitions;
this.descr = descr;
this.infer = new Infer(this);
- this.constfold = new ConstantFolder(this);
+ this.constfold = new ConstantFolder(global);
this.desugarize = new DeSugarize(this, global);
}
@@ -1209,13 +1210,13 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
*/
Tree mkStable(Tree tree, Type pre, int mode, Type pt) {
switch (tree.type) {
- case ConstantType(_, Object value):
- return make.Literal(tree.pos, value).setType(tree.type);
+ case ConstantType(_, AConstant value):
+ return gen.Literal(tree.pos, value);
case PolyType(Symbol[] tparams, Type restp):
if (tparams.length == 0) {
switch (restp) {
- case ConstantType(_, Object value):
- return make.Literal(tree.pos, value).setType(tree.type);
+ case ConstantType(_, AConstant value):
+ return gen.Literal(tree.pos, value);
}
}
}
@@ -1386,25 +1387,24 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
}
if (!(owntype instanceof Type.PolyType || owntype.isSubType(pt))) {
switch (tree) {
- case Literal(Object value):
+ case Literal(AConstant constant):
int n = Integer.MAX_VALUE;
- if (value instanceof Integer)
- n = ((Integer) value).intValue();
- else if (value instanceof Character)
- n = ((Character) value).charValue();
- Object value1 = null;
+ switch (constant) {
+ case INT(int value): n = value; break;
+ case CHAR(char value): n = value; break;
+ }
+ AConstant value1 = null;
if (pt.symbol() == definitions.BYTE_CLASS &&
-128 <= n && n <= 127)
- value1 = new Byte((byte) n);
+ value1 = AConstant.BYTE((byte) n);
else if (pt.symbol() == definitions.SHORT_CLASS &&
-32768 <= n && n <= 32767)
- value1 = new Short((short) n);
+ value1 = AConstant.SHORT((short) n);
else if (pt.symbol() == definitions.CHAR_CLASS &&
0 <= n && n <= 65535)
- value1 = new Character((char) n);
+ value1 = AConstant.CHAR((char) n);
if (value1 != null)
- return make.Literal(tree.pos, value1)
- .setType(Type.ConstantType(pt, value1));
+ return gen.Literal(tree.pos, value1);
break;
}
if ((mode & EXPRmode) != 0) {
@@ -2286,17 +2286,13 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
// 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);
- }
+ if (fn1.symbol() == definitions.ANY_AS) {
+ switch (qual.type()) {
+ case ConstantType(_, AConstant value):
+ value = constfold.cast(value, argtypes[0]);
+ if (value != null)
+ return gen.Literal(tree.pos, value);
+ }
}
}
return constfold.tryToFold(
@@ -2592,7 +2588,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
return transformIdent(tree, name);
}
- case Literal(Object value):
+ case Literal(AConstant value):
return tree.setType(Type.constantType(value));
case LabelDef(Name name, Ident[] params, Tree body):
diff --git a/sources/scalac/typechecker/ConstantFolder.java b/sources/scalac/typechecker/ConstantFolder.java
index 46d33b702f..20b37323eb 100644
--- a/sources/scalac/typechecker/ConstantFolder.java
+++ b/sources/scalac/typechecker/ConstantFolder.java
@@ -12,331 +12,352 @@
package scalac.typechecker;
-import scalac.util.*;
-import scalac.ast.*;
-import scalac.symtab.*;
-import scalac.symtab.Type.*;
+import scalac.Global;
+import scalac.ast.Tree;
+import scalac.ast.TreeGen;
+import scalac.atree.AConstant;
+import scalac.atree.ATypeKind;
+import scalac.symtab.Definitions;
+import scalac.symtab.Type;
+import scalac.util.Name;
+import scalac.util.Names;
-class ConstantFolder implements /*imports*/ TypeTags {
+public class ConstantFolder {
- private final Analyzer ana;
+ //########################################################################
+ // Private Fields
- ConstantFolder(Analyzer ana) {
- this.ana = ana;
+ /** The global definitions */
+ private final Definitions definitions;
+
+ /** The tree generator */
+ private final TreeGen gen;
+
+ //########################################################################
+ // Public Constructors
+
+ /** Initializes this instance. */
+ public ConstantFolder(Global global) {
+ this.definitions = global.definitions;
+ this.gen = global.treeGen;
}
- /** fold binary operation.
+ //########################################################################
+ // Public Methods
+
+ /**
+ * Attempts to constant fold given tree. Returns the input tree if
+ * constant folding fails.
*/
- Type foldBinary(int pos, ConstantType left, ConstantType right, Name op) {
- try {
- Type ltype = left.deconst();
- Symbol lsymbol = left.symbol();
- if (lsymbol == ana.definitions.BYTE_CLASS ||
- lsymbol == ana.definitions.CHAR_CLASS ||
- lsymbol == ana.definitions.SHORT_CLASS) {
- ltype = ana.definitions.INT_TYPE();
- lsymbol = ana.definitions.INT_CLASS;
- }
- Type rtype = right.deconst();
- Symbol rsymbol = right.symbol();
- if (rsymbol == ana.definitions.BYTE_CLASS ||
- rsymbol == ana.definitions.CHAR_CLASS ||
- rsymbol == ana.definitions.SHORT_CLASS) {
- rtype = ana.definitions.INT_TYPE();
- rsymbol = ana.definitions.INT_CLASS;
- }
- Type optype;
- if (ltype.isSameAs(rtype))
- optype = ltype;
- else if (lsymbol == ana.definitions.JAVA_STRING_CLASS)
- optype = ltype;
- else if (rsymbol == ana.definitions.JAVA_STRING_CLASS)
- optype = rtype;
- else if (lsymbol == ana.definitions.INT_CLASS)
- optype = rtype;
- else if (rsymbol == ana.definitions.INT_CLASS)
- optype = ltype;
- else if (lsymbol == ana.definitions.LONG_CLASS)
- optype = rtype;
- else if (rsymbol == ana.definitions.LONG_CLASS)
- optype = ltype;
- else if (lsymbol == ana.definitions.FLOAT_CLASS)
- optype = rtype;
- else if (rsymbol == ana.definitions.FLOAT_CLASS)
- optype = ltype;
- else
- throw Debug.abort("illegal case", ltype + " - " + rtype);
- Object value = null;
- switch (optype.unbox()) {
- case UnboxedType(INT):
- if (op == Names.ADD)
- value = new Integer(left.intValue() + right.intValue());
- else if (op == Names.SUB)
- value = new Integer(left.intValue() - right.intValue());
- else if (op == Names.MUL)
- value = new Integer(left.intValue() * right.intValue());
- else if (op == Names.DIV)
- value = new Integer(left.intValue() / right.intValue());
- else if (op == Names.MOD)
- value = new Integer(left.intValue() % right.intValue());
- else if (op == Names.EQ)
- value = new Boolean(left.intValue() == right.intValue());
- else if (op == Names.NE)
- value = new Boolean(left.intValue() != right.intValue());
- else if (op == Names.LT)
- value = new Boolean(left.intValue() < right.intValue());
- else if (op == Names.GT)
- value = new Boolean(left.intValue() > right.intValue());
- else if (op == Names.LE)
- value = new Boolean(left.intValue() <= right.intValue());
- else if (op == Names.GE)
- value = new Boolean(left.intValue() >= right.intValue());
- else if (op == Names.OR)
- value = new Integer(left.intValue() | right.intValue());
- else if (op == Names.AND)
- value = new Integer(left.intValue() & right.intValue());
- else if (op == Names.XOR)
- value = new Integer(left.intValue() ^ right.intValue());
- else if (op == Names.LSL)
- value = new Integer(left.intValue() << right.intValue());
- else if (op == Names.LSR)
- value = new Integer(left.intValue() >>> right.intValue());
- else if (op == Names.ASR)
- value = new Integer(left.intValue() >> right.intValue());
- break;
- case UnboxedType(LONG):
- if (op == Names.ADD)
- value = new Long(left.longValue() + right.longValue());
- else if (op == Names.SUB)
- value = new Long(left.longValue() - right.longValue());
- else if (op == Names.MUL)
- value = new Long(left.longValue() * right.longValue());
- else if (op == Names.DIV)
- value = new Long(left.longValue() / right.longValue());
- else if (op == Names.MOD)
- value = new Long(left.longValue() % right.longValue());
- else if (op == Names.EQ)
- value = new Boolean(left.longValue() == right.longValue());
- else if (op == Names.NE)
- value = new Boolean(left.longValue() != right.longValue());
- else if (op == Names.LT)
- value = new Boolean(left.longValue() < right.longValue());
- else if (op == Names.GT)
- value = new Boolean(left.longValue() > right.longValue());
- else if (op == Names.LE)
- value = new Boolean(left.longValue() <= right.longValue());
- else if (op == Names.GE)
- value = new Boolean(left.longValue() >= right.longValue());
- else if (op == Names.OR)
- value = new Long(left.longValue() | right.longValue());
- else if (op == Names.AND)
- value = new Long(left.longValue() & right.longValue());
- else if (op == Names.XOR)
- value = new Long(left.longValue() ^ right.longValue());
- else if (op == Names.LSL)
- value = new Long(left.longValue() << right.intValue());
- else if (op == Names.LSR)
- value = new Long(left.longValue() >>> right.intValue());
- else if (op == Names.ASR)
- value = new Long(left.longValue() >> right.intValue());
- break;
- case UnboxedType(FLOAT):
- if (op == Names.ADD)
- value = new Float(left.floatValue() + right.floatValue());
- else if (op == Names.SUB)
- value = new Float(left.floatValue() - right.floatValue());
- else if (op == Names.MUL)
- value = new Float(left.floatValue() * right.floatValue());
- else if (op == Names.DIV)
- value = new Float(left.floatValue() / right.floatValue());
- else if (op == Names.MOD)
- value = new Float(left.floatValue() % right.floatValue());
- else if (op == Names.EQ)
- value = new Boolean(left.floatValue() == right.floatValue());
- else if (op == Names.NE)
- value = new Boolean(left.floatValue() != right.floatValue());
- else if (op == Names.LT)
- value = new Boolean(left.floatValue() < right.floatValue());
- else if (op == Names.GT)
- value = new Boolean(left.floatValue() > right.floatValue());
- else if (op == Names.LE)
- value = new Boolean(left.floatValue() <= right.floatValue());
- else if (op == Names.GE)
- value = new Boolean(left.floatValue() >= right.floatValue());
- break;
- case UnboxedType(DOUBLE):
- if (op == Names.ADD)
- value = new Double(left.doubleValue() + right.doubleValue());
- else if (op == Names.SUB)
- value = new Double(left.doubleValue() - right.doubleValue());
- else if (op == Names.MUL)
- value = new Double(left.doubleValue() * right.doubleValue());
- else if (op == Names.DIV)
- value = new Double(left.doubleValue() / right.doubleValue());
- else if (op == Names.MOD)
- value = new Double(left.doubleValue() % right.doubleValue());
- else if (op == Names.EQ)
- value = new Boolean(left.doubleValue() == right.doubleValue());
- else if (op == Names.NE)
- value = new Boolean(left.doubleValue() != right.doubleValue());
- else if (op == Names.LT)
- value = new Boolean(left.doubleValue() < right.doubleValue());
- else if (op == Names.GT)
- value = new Boolean(left.doubleValue() > right.doubleValue());
- else if (op == Names.LE)
- value = new Boolean(left.doubleValue() <= right.doubleValue());
- else if (op == Names.GE)
- value = new Boolean(left.doubleValue() >= right.doubleValue());
- break;
- case UnboxedType(BOOLEAN):
- if (op == Names.EQ)
- value = new Boolean(left.booleanValue() == right.booleanValue());
- else if (op == Names.NE)
- value = new Boolean(left.booleanValue() != right.booleanValue());
- else if (op == Names.OR || op == Names.ZOR)
- value = new Boolean(left.booleanValue() | right.booleanValue());
- else if (op == Names.AND || op == Names.ZAND)
- value = new Boolean(left.booleanValue() & right.booleanValue());
- else if (op == Names.XOR)
- value = new Boolean(left.booleanValue() ^ right.booleanValue());
- break;
- default:
- if (optype.symbol() == ana.definitions.JAVA_STRING_CLASS &&
- op == Names.ADD)
- value = left.stringValue() + right.stringValue();
- }
- return (value != null) ? Type.constantType(value) : Type.NoType;
- } catch (ArithmeticException e) {
- ana.unit.warning(pos, e.toString());
- return Type.NoType;
- }
+ public Tree tryToFold(Tree tree) {
+ AConstant value = evaluate(tree);
+ return value != null ? gen.Literal(tree.pos, value) : tree;
}
- /** fold unary operation.
+ /**
+ * Evaluates the expression represented by the tree and returns
+ * the resulting value. Returns null if the evaluation can't be
+ * performed.
*/
- Type foldUnary(int pos, ConstantType od, Name op) {
- try {
- Object value = null;
- switch (od.deconst().unbox()) {
- case UnboxedType(INT):
- if (op == Names.ADD)
- value = new Integer(od.intValue());
- else if (op == Names.SUB)
- value = new Integer(-od.intValue());
- else if (op == Names.NOT)
- value = new Integer(~od.intValue());
- break;
- case UnboxedType(LONG):
- if (op == Names.ADD)
- value = new Long(od.longValue());
- else if (op == Names.SUB)
- value = new Long(-od.longValue());
- else if (op == Names.NOT)
- value = new Long(~od.longValue());
- break;
- case UnboxedType(FLOAT):
- if (op == Names.ADD)
- value = new Float(od.floatValue());
- else if (op == Names.SUB)
- value = new Float(-od.floatValue());
- break;
- case UnboxedType(DOUBLE):
- if (op == Names.ADD)
- value = new Double(od.doubleValue());
- else if (op == Names.SUB)
- value = new Double(-od.doubleValue());
- break;
- case UnboxedType(BOOLEAN):
- if (op == Names.ZNOT)
- value = new Boolean(!od.booleanValue());
- break;
- }
- return (value != null) ? Type.constantType(value) : Type.NoType;
- } catch (ArithmeticException e) {
- ana.unit.warning(pos, e.toString());
- return Type.NoType;
+ public AConstant evaluate(Tree tree) {
+ switch (tree) {
+ case TypeApply(Select(Tree qualifier, Name op), Tree[] args):
+ switch (qualifier.type()) {
+ case ConstantType(_, AConstant lvalue):
+ if (args.length == 1 && op == Names.asInstanceOf)
+ return cast(lvalue, args[0].type());
+ return null;
+ default:
+ return null;
+ }
+ case Apply(Select(Tree qualifier, Name op), Tree[] args):
+ switch (qualifier.type()) {
+ case ConstantType(_, AConstant lvalue):
+ switch (args.length) {
+ case 0:
+ return evaluate(op, lvalue);
+ case 1:
+ switch (args[0].type()) {
+ case ConstantType(_, AConstant rvalue):
+ return evaluate(op, lvalue, rvalue);
+ default:
+ return null;
+ }
+ default:
+ return null;
+ }
+ default:
+ return null;
+ }
+ default:
+ return null;
}
}
- /** fold cast operation
+ /**
+ * Evaluates the unary operation and returns the resulting value.
+ * Returns null if the evaluation can't be performed.
*/
- Type foldAsInstanceOf(int pos, ConstantType od, Type argtype) {
- try {
- Object value = null;
- switch (argtype.unbox()) {
- case UnboxedType(BYTE):
- value = new Byte((byte)od.intValue());
- break;
- case UnboxedType(CHAR):
- value = new Character((char)od.intValue());
- break;
- case UnboxedType(SHORT):
- value = new Short((short)od.intValue());
- break;
- case UnboxedType(INT):
- value = new Integer(od.intValue());
- break;
- case UnboxedType(LONG):
- value = new Long(od.longValue());
- break;
- case UnboxedType(FLOAT):
- value = new Float(od.longValue());
- break;
- case UnboxedType(DOUBLE):
- value = new Double(od.doubleValue());
- break;
- case UnboxedType(BOOLEAN):
- value = new Boolean(od.booleanValue());
- break;
- }
- return (value != null) ? new ConstantType(argtype, value)
- : Type.NoType;
- } catch (ClassCastException e) {
- ana.unit.warning(pos, e.toString());
- return Type.NoType;
- }
+ public AConstant evaluate(Name op, AConstant value) {
+ switch (kind(value)) {
+ case ATypeKind.BOOL:
+ boolean v = value.booleanValue();
+ if (op == Names.ZNOT) return AConstant.BOOLEAN(!v);
+ return null;
+ case ATypeKind.I4:
+ int v = value.intValue();
+ if (op == Names.ADD) return AConstant.INT(+v);
+ if (op == Names.SUB) return AConstant.INT(-v);
+ if (op == Names.NOT) return AConstant.INT(~v);
+ return null;
+ case ATypeKind.I8:
+ long v = value.longValue();
+ if (op == Names.ADD) return AConstant.LONG(+v);
+ if (op == Names.SUB) return AConstant.LONG(-v);
+ if (op == Names.NOT) return AConstant.LONG(~v);
+ return null;
+ case ATypeKind.R4:
+ float v = value.floatValue();
+ if (op == Names.ADD) return AConstant.FLOAT(+v);
+ if (op == Names.SUB) return AConstant.FLOAT(-v);
+ return null;
+ case ATypeKind.R8:
+ double v = value.doubleValue();
+ if (op == Names.ADD) return AConstant.DOUBLE(+v);
+ if (op == Names.SUB) return AConstant.DOUBLE(-v);
+ return null;
+ default:
+ return null;
+ }
}
- /** attempt to constant fold tree.
+ /**
+ * Evaluates the binary operation and returns the resulting value.
+ * Returns null if the evaluation can't be performed.
*/
- Tree tryToFold(Tree tree) {
- Type ctp = Type.NoType;
- switch (tree) {
- case Apply(Select(Tree qual, Name op), Tree[] args):
- if (qual.type instanceof ConstantType) {
- if (args.length == 0)
- ctp = foldUnary(
- tree.pos, (ConstantType)qual.type, op);
- else if (args.length == 1 &&
- args[0].type instanceof ConstantType)
- ctp = foldBinary(
- tree.pos,
- (ConstantType)qual.type,
- (ConstantType)(args[0].type),
- op);
- }
- break;
- case TypeApply(Select(Tree qual, Name op), Tree[] targs):
- if (qual.type instanceof Type.ConstantType &&
- op == Names.asInstanceOf)
- ctp = foldAsInstanceOf(
- tree.pos,
- (ConstantType)qual.type,
- targs[0].type);
- break;
- }
- switch (ctp) {
- case ConstantType(Type base, Object value):
- return ana.make.Literal(tree.pos, value).setType(ctp);
- default:
- return tree;
- }
- }
+ public AConstant evaluate(Name op, AConstant lvalue, AConstant rvalue) {
+ ATypeKind kind = kind(lvalue, rvalue);
+ if (kind == null) return null;
+ switch (kind) {
-}
+ case ATypeKind.I4:
+ int l = lvalue.intValue();
+ int r = rvalue.intValue();
+ if (op == Names.OR ) return AConstant.INT(l | r);
+ if (op == Names.AND) return AConstant.INT(l & r);
+ if (op == Names.XOR) return AConstant.INT(l ^ r);
+ if (op == Names.ADD) return AConstant.INT(l + r);
+ if (op == Names.SUB) return AConstant.INT(l - r);
+ if (op == Names.MUL) return AConstant.INT(l * r);
+ if (op == Names.DIV) return r == 0 ? null : AConstant.INT(l / r);
+ if (op == Names.MOD) return r == 0 ? null : AConstant.INT(l % r);
+ if (op == Names.EQ ) return AConstant.BOOLEAN(l == r);
+ if (op == Names.NE ) return AConstant.BOOLEAN(l != r);
+ if (op == Names.LT ) return AConstant.BOOLEAN(l < r);
+ if (op == Names.GT ) return AConstant.BOOLEAN(l > r);
+ if (op == Names.LE ) return AConstant.BOOLEAN(l <= r);
+ if (op == Names.GE ) return AConstant.BOOLEAN(l >= r);
+ if (op == Names.LSL) return AConstant.INT(l << r);
+ if (op == Names.LSR) return AConstant.INT(l >>> r);
+ if (op == Names.ASR) return AConstant.INT(l >> r);
+ return null;
+ case ATypeKind.I8:
+ long l = lvalue.longValue();
+ long r = rvalue.longValue();
+ if (op == Names.OR ) return AConstant.LONG(l | r);
+ if (op == Names.AND) return AConstant.LONG(l & r);
+ if (op == Names.XOR) return AConstant.LONG(l ^ r);
+ if (op == Names.ADD) return AConstant.LONG(l + r);
+ if (op == Names.SUB) return AConstant.LONG(l - r);
+ if (op == Names.MUL) return AConstant.LONG(l * r);
+ if (op == Names.DIV) return r == 0 ? null : AConstant.LONG(l / r);
+ if (op == Names.MOD) return r == 0 ? null : AConstant.LONG(l % r);
+ if (op == Names.EQ ) return AConstant.BOOLEAN(l == r);
+ if (op == Names.NE ) return AConstant.BOOLEAN(l != r);
+ if (op == Names.LT ) return AConstant.BOOLEAN(l < r);
+ if (op == Names.GT ) return AConstant.BOOLEAN(l > r);
+ if (op == Names.LE ) return AConstant.BOOLEAN(l <= r);
+ if (op == Names.GE ) return AConstant.BOOLEAN(l >= r);
+ if (kind(lvalue) == ATypeKind.I4) {
+ int li = lvalue.intValue();
+ if (op == Names.LSL) return AConstant.INT(li << r);
+ if (op == Names.LSR) return AConstant.INT(li >>> r);
+ if (op == Names.ASR) return AConstant.INT(li >> r);
+ } else {
+ if (op == Names.LSL) return AConstant.LONG(l << r);
+ if (op == Names.LSR) return AConstant.LONG(l >>> r);
+ if (op == Names.ASR) return AConstant.LONG(l >> r);
+ }
+ return null;
+ case ATypeKind.R4:
+ float l = lvalue.floatValue();
+ float r = rvalue.floatValue();
+ if (op == Names.ADD) return AConstant.FLOAT(l + r);
+ if (op == Names.SUB) return AConstant.FLOAT(l - r);
+ if (op == Names.MUL) return AConstant.FLOAT(l * r);
+ if (op == Names.DIV) return AConstant.FLOAT(l / r);
+ if (op == Names.MOD) return AConstant.FLOAT(l % r);
+ if (op == Names.EQ ) return AConstant.BOOLEAN(l == r);
+ if (op == Names.NE ) return AConstant.BOOLEAN(l != r);
+ if (op == Names.LT ) return AConstant.BOOLEAN(l < r);
+ if (op == Names.GT ) return AConstant.BOOLEAN(l > r);
+ if (op == Names.LE ) return AConstant.BOOLEAN(l <= r);
+ if (op == Names.GE ) return AConstant.BOOLEAN(l >= r);
+ return null;
+ case ATypeKind.R8:
+ double l = lvalue.doubleValue();
+ double r = rvalue.doubleValue();
+ if (op == Names.ADD) return AConstant.DOUBLE(l + r);
+ if (op == Names.SUB) return AConstant.DOUBLE(l - r);
+ if (op == Names.MUL) return AConstant.DOUBLE(l * r);
+ if (op == Names.DIV) return AConstant.DOUBLE(l / r);
+ if (op == Names.MOD) return AConstant.DOUBLE(l % r);
+ if (op == Names.EQ ) return AConstant.BOOLEAN(l == r);
+ if (op == Names.NE ) return AConstant.BOOLEAN(l != r);
+ if (op == Names.LT ) return AConstant.BOOLEAN(l < r);
+ if (op == Names.GT ) return AConstant.BOOLEAN(l > r);
+ if (op == Names.LE ) return AConstant.BOOLEAN(l <= r);
+ if (op == Names.GE ) return AConstant.BOOLEAN(l >= r);
+ return null;
+ case ATypeKind.BOOL:
+ boolean l = lvalue.booleanValue();
+ boolean r = rvalue.booleanValue();
+ if (op == Names.ZOR ) return AConstant.BOOLEAN(l | r);
+ if (op == Names.OR ) return AConstant.BOOLEAN(l | r);
+ if (op == Names.ZAND) return AConstant.BOOLEAN(l & r);
+ if (op == Names.AND ) return AConstant.BOOLEAN(l & r);
+ if (op == Names.XOR ) return AConstant.BOOLEAN(l ^ r);
+ if (op == Names.EQ ) return AConstant.BOOLEAN(l == r);
+ if (op == Names.NE ) return AConstant.BOOLEAN(l != r);
+ return null;
+ case ATypeKind.STR:
+ if (op == Names.ADD)
+ return AConstant.STRING(lvalue.stringValue()+rvalue.stringValue());
+ return null;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Casts the value to given type and returns the resulting value.
+ * Returns null if the cast can't be performed.
+ */
+ public AConstant cast(AConstant value, Type type) {
+ switch (value.kind()) {
+ case UNIT:
+ if (type.isSameAs(definitions.UNIT_CLASS.type()))
+ return value;
+ return null;
+ case BOOL:
+ if (type.isSameAs(definitions.BOOLEAN_TYPE()))
+ return value;
+ return null;
+ case U1:
+ case U2:
+ case U4:
+ case U8:
+ case I1:
+ case I2:
+ case I4:
+ case I8:
+ case R4:
+ case R8:
+ if (type.isSameAs(definitions.BYTE_TYPE()))
+ return AConstant.BYTE(value.byteValue());
+ if (type.isSameAs(definitions.SHORT_TYPE()))
+ return AConstant.SHORT(value.shortValue());
+ if (type.isSameAs(definitions.CHAR_TYPE()))
+ return AConstant.CHAR(value.charValue());
+ if (type.isSameAs(definitions.INT_TYPE()))
+ return AConstant.INT(value.intValue());
+ if (type.isSameAs(definitions.LONG_TYPE()))
+ return AConstant.LONG(value.longValue());
+ if (type.isSameAs(definitions.FLOAT_TYPE()))
+ return AConstant.FLOAT(value.floatValue());
+ if (type.isSameAs(definitions.DOUBLE_TYPE()))
+ return AConstant.DOUBLE(value.doubleValue());
+ return null;
+ case STR:
+ if (type.isSameAs(definitions.JAVA_STRING_TYPE()))
+ return value;
+ return null;
+ default:
+ return null;
+ }
+ }
+
+ //########################################################################
+ // Private Methods
+
+ /** Returns the kind of given value. */
+ private ATypeKind kind(AConstant value) {
+ ATypeKind kind = value.kind();
+ switch (kind) {
+ case I1:
+ case I2:
+ case U2:
+ return ATypeKind.I4;
+ default:
+ return kind;
+ }
+ }
+
+ /**
+ * Returns the combined kind of given values or null if the values
+ * can't be combined.
+ */
+ private ATypeKind kind(AConstant lvalue, AConstant rvalue) {
+ ATypeKind lkind = kind(lvalue);
+ ATypeKind rkind = kind(rvalue);
+ if (lkind == rkind) return lkind;
+ if (lkind == ATypeKind.ZERO) return null;
+ if (rkind == ATypeKind.ZERO) return null;
+ if (lkind == ATypeKind.STR) return lkind;
+ if (rkind == ATypeKind.STR) return rkind;
+ switch (lkind) {
+ case I4:
+ switch (rkind) {
+ case I4: return lkind;
+ case I8: return rkind;
+ case R4: return rkind;
+ case R8: return rkind;
+ default: return null;
+ }
+ case I8:
+ switch (rkind) {
+ case I4: return lkind;
+ case I8: return lkind;
+ case R4: return rkind;
+ case R8: return rkind;
+ default: return null;
+ }
+ case R4:
+ switch (rkind) {
+ case I4: return lkind;
+ case I8: return lkind;
+ case R4: return lkind;
+ case R8: return rkind;
+ default: return null;
+ }
+ case R8:
+ switch (rkind) {
+ case I4: return lkind;
+ case I8: return lkind;
+ case R4: return lkind;
+ case R8: return lkind;
+ default: return null;
+ }
+ default:
+ return null;
+ }
+ }
+
+ //########################################################################
+}
diff --git a/test/files/neg/bug45.check b/test/files/neg/bug45.check
index 530bd78c42..fe8d97ec16 100644
--- a/test/files/neg/bug45.check
+++ b/test/files/neg/bug45.check
@@ -1,5 +1,5 @@
bug45.scala:4: type mismatch;
- found : scala.AllRef
+ found : scala.AllRef(null)
required: Int
def foo[Int](x: Int): Int = null;
^
diff --git a/test/files/neg/constrparams.check b/test/files/neg/constrparams.check
index 6aef035af0..6e7ec7671e 100644
--- a/test/files/neg/constrparams.check
+++ b/test/files/neg/constrparams.check
@@ -1,5 +1,5 @@
constrparams.scala:4: type mismatch;
- found : scala.AllRef
+ found : scala.AllRef(null)
required: x.t
private val z: x.t = null; //error
^
diff --git a/test/files/shl/basic.check b/test/files/shl/basic.check
index bee7e5192d..2a4cd09b49 100644
--- a/test/files/shl/basic.check
+++ b/test/files/shl/basic.check
@@ -1,12 +1,12 @@
> > > > > > (): scala.Unit
> false: scala.Boolean(false)
-> 1: scala.Char(1)
+> 1: scala.Char('1')
> 2: scala.Int(2)
> 3: scala.Long(3)
> 4.0: scala.Float(4.0)
> 5.0: scala.Double(5.0)
-> null: scala.AllRef
-> hello: java.lang.String(hello)
+> null: scala.AllRef(null)
+> hello: java.lang.String("hello")
> List(): scala.Nil
> List(1,2,3): scala.List[scala.Int]
> > Exception in thread "main" java.lang.Error: error