diff options
-rw-r--r-- | src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala | 81 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/Constants.scala | 12 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 22 |
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 { |