summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala81
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Constants.scala12
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala22
3 files changed, 74 insertions, 41 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
index 4a6d1b2c4e..6a6239e3ea 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
@@ -222,44 +222,51 @@ abstract class GenJVM extends SubComponent {
assert(consts.length == 1, consts.toString())
buf.putShort(1.toShort); // for now only 1 constructor parameter
buf.putShort(cpool.addUtf8("value").toShort);
- for (val const <- consts) {
- const.tag match {
- case BooleanTag =>
- buf.put('Z'.toByte)
- buf.putShort(cpool.addInteger(if(const.booleanValue) 1 else 0).toShort)
- case ByteTag =>
- buf.put('B'.toByte)
- buf.putShort(cpool.addInteger(const.byteValue).toShort)
- case ShortTag =>
- buf.put('S'.toByte)
- buf.putShort(cpool.addInteger(const.shortValue).toShort)
- case CharTag =>
- buf.put('C'.toByte)
- buf.putShort(cpool.addInteger(const.charValue).toShort)
- case IntTag =>
- buf.put('I'.toByte)
- buf.putShort(cpool.addInteger(const.intValue).toShort)
- case LongTag =>
- buf.put('J'.toByte)
- buf.putShort(cpool.addLong(const.longValue).toShort)
- case FloatTag =>
- buf.put('F'.toByte)
- buf.putShort(cpool.addFloat(const.floatValue).toShort)
- case DoubleTag =>
- buf.put('D'.toByte)
- buf.putShort(cpool.addDouble(const.doubleValue).toShort)
- case StringTag =>
- buf.put('s'.toByte)
- buf.putShort(cpool.addUtf8(const.stringValue).toShort)
- case ClassTag =>
- buf.put('c'.toByte)
- buf.putShort(cpool.addUtf8(javaType(const.typeValue).getSignature()).toShort)
- case EnumTag =>
- buf.put('e'.toByte)
- buf.putShort(cpool.addUtf8(javaType(const.tpe).getSignature()).toShort)
- buf.putShort(cpool.addUtf8(const.symbolValue.name.toString()).toShort)
- //case NullTag => AllRefClass.tpe
+ def emitElement(const: Constant): Unit = const.tag match {
+ case BooleanTag =>
+ buf.put('Z'.toByte)
+ buf.putShort(cpool.addInteger(if(const.booleanValue) 1 else 0).toShort)
+ case ByteTag =>
+ buf.put('B'.toByte)
+ buf.putShort(cpool.addInteger(const.byteValue).toShort)
+ case ShortTag =>
+ buf.put('S'.toByte)
+ buf.putShort(cpool.addInteger(const.shortValue).toShort)
+ case CharTag =>
+ buf.put('C'.toByte)
+ buf.putShort(cpool.addInteger(const.charValue).toShort)
+ case IntTag =>
+ buf.put('I'.toByte)
+ buf.putShort(cpool.addInteger(const.intValue).toShort)
+ case LongTag =>
+ buf.put('J'.toByte)
+ buf.putShort(cpool.addLong(const.longValue).toShort)
+ case FloatTag =>
+ buf.put('F'.toByte)
+ buf.putShort(cpool.addFloat(const.floatValue).toShort)
+ case DoubleTag =>
+ buf.put('D'.toByte)
+ buf.putShort(cpool.addDouble(const.doubleValue).toShort)
+ case StringTag =>
+ buf.put('s'.toByte)
+ buf.putShort(cpool.addUtf8(const.stringValue).toShort)
+ case ClassTag =>
+ buf.put('c'.toByte)
+ buf.putShort(cpool.addUtf8(javaType(const.typeValue).getSignature()).toShort)
+ case EnumTag =>
+ buf.put('e'.toByte)
+ buf.putShort(cpool.addUtf8(javaType(const.tpe).getSignature()).toShort)
+ buf.putShort(cpool.addUtf8(const.symbolValue.name.toString()).toShort)
+ case ArrayTag =>
+ buf.put('['.toByte)
+ val arr = const.arrayValue;
+ buf.putShort(arr.length.toShort);
+ for (val elem <- arr) emitElement(elem)
+ //case NullTag => AllRefClass.tpe
}
+
+ for (val const <- consts) {
+ emitElement(const)
}
}
if (nattr > 0) {
diff --git a/src/compiler/scala/tools/nsc/symtab/Constants.scala b/src/compiler/scala/tools/nsc/symtab/Constants.scala
index be12f93aa4..7e4be15fc5 100644
--- a/src/compiler/scala/tools/nsc/symtab/Constants.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Constants.scala
@@ -24,7 +24,8 @@ trait Constants requires SymbolTable {
final val StringTag = LITERALstring - LITERAL;
final val NullTag = LITERALnull - LITERAL;
final val ClassTag = LITERALclass - LITERAL;
- final val EnumTag = ClassTag + 1
+ final val EnumTag = ClassTag + 1;
+ final val ArrayTag = EnumTag + 1;
case class Constant(value: Any) {
@@ -41,6 +42,7 @@ trait Constants requires SymbolTable {
else if (value.isInstanceOf[String]) StringTag
else if (value.isInstanceOf[Type]) ClassTag
else if (value.isInstanceOf[Symbol]) EnumTag
+ else if (value.isInstanceOf[Array[Constant]]) ArrayTag
else if (value == null) NullTag
else throw new Error("bad constant value: " + value);
@@ -183,7 +185,15 @@ trait Constants requires SymbolTable {
def symbolValue: Symbol = value.asInstanceOf[Symbol]
+ def arrayValue: Array[Constant] =
+ throw new Error("value " + value + " is not an array");
+
override def hashCode(): int =
if (value == null) 0 else value.hashCode() * 41 + 17;
}
+
+ class ArrayConstant(override val arrayValue: Array[Constant],
+ override val tpe: Type)
+ extends Constant(arrayValue);
+
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index b2c408bf45..33599ef7ab 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -119,7 +119,10 @@ trait Typers requires Analyzer {
val LHSmode = 0x400; // Set for the left-hand side of an assignment
- private val stickyModes: int = EXPRmode | PATTERNmode | TYPEmode
+ val CONSTmode = 0x800 // expressions should evaluate to constants
+ // used for attribute arguments
+
+ private val stickyModes: int = EXPRmode | PATTERNmode | TYPEmode | CONSTmode
/** Report a type error.
* @param pos The position where to report the error
@@ -1070,7 +1073,20 @@ trait Typers requires Analyzer {
case MethodType(_, rtp) if ((mode & PATTERNmode) != 0) => rtp
case _ => tp
}
- constfold(copy.Apply(tree, fun, args1).setType(ifPatternSkipFormals(restpe)))
+ if ((mode & CONSTmode) != 0 && fun.symbol.owner == PredefModule.tpe.symbol && fun.symbol.name == nme.Array) {
+ val elems = new Array[Constant](args1.length)
+ var i = 0;
+ for (val arg <- args1) arg match {
+ case Literal(value) =>
+ elems(i) = value
+ i = i + 1
+ case _ => errorTree(arg, "constant required")
+ }
+ val arrayConst = new ArrayConstant(elems, restpe)
+ Literal(arrayConst) setType ConstantType(arrayConst)
+ }
+ else
+ constfold(copy.Apply(tree, fun, args1).setType(ifPatternSkipFormals(restpe)))
} else {
assert((mode & PATTERNmode) == 0); // this case cannot arise for patterns
val lenientTargs = protoTypeArgs(tparams, formals, restpe, pt)
@@ -1335,7 +1351,7 @@ trait Typers requires Analyzer {
typer1.typedLabelDef(ldef)
case Attributed(attr, defn) =>
- val attr1 = typed(attr, AttributeClass.tpe)
+ val attr1 = typed(attr, mode | CONSTmode, AttributeClass.tpe)
val attrInfo = attr1 match {
case Apply(Select(New(tpt), nme.CONSTRUCTOR), args) =>
Pair(tpt.tpe, args map {