diff options
author | Iulian Dragos <jaguarul@gmail.com> | 2007-07-23 14:57:46 +0000 |
---|---|---|
committer | Iulian Dragos <jaguarul@gmail.com> | 2007-07-23 14:57:46 +0000 |
commit | 11f1b34dde88cc4911e5d126c76c30c67a0b7cc2 (patch) | |
tree | 7d3c87f3c048f338f9d07229ec27e1e3fe2f14b6 /src | |
parent | 08a42368c0931dea170b7320cc1bc5389a275548 (diff) | |
download | scala-11f1b34dde88cc4911e5d126c76c30c67a0b7cc2.tar.gz scala-11f1b34dde88cc4911e5d126c76c30c67a0b7cc2.tar.bz2 scala-11f1b34dde88cc4911e5d126c76c30c67a0b7cc2.zip |
Added multidimensional arrays (up to 9 dimensio...
Added multidimensional arrays (up to 9 dimensions).
Diffstat (limited to 'src')
11 files changed, 105 insertions, 25 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/icode/Checkers.scala b/src/compiler/scala/tools/nsc/backend/icode/Checkers.scala index cf8e14819f..0c467f1279 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/Checkers.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/Checkers.scala @@ -451,9 +451,9 @@ abstract class Checkers { error("NEW call to non-reference type: " + kind) } - case CREATE_ARRAY(elem) => - checkStack(1) - checkType(stack.pop, INT) + case CREATE_ARRAY(elem, dims) => + checkStack(dims) + stack.pop(dims) foreach (checkType(_, INT)) stack.push(ARRAY(elem)) case IS_INSTANCE(tpe) => diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala index 91832c0346..6a21b00f86 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala @@ -653,16 +653,20 @@ abstract class GenICode extends SubComponent { assert(ctor.isClassConstructor, "'new' call to non-constructor: " + ctor.name) - generatedType = toTypeKind(tpt.tpe) + generatedType = toTypeKind(fun.tpe.resultType) assert(generatedType.isReferenceType || generatedType.isArrayType, "Non reference type cannot be instantiated: " + generatedType) var ctx1 = ctx generatedType match { - case ARRAY(elem) => + case arr @ ARRAY(elem) => ctx1 = genLoadArguments(args, ctor.info.paramTypes, ctx) - ctx1.bb.emit(CREATE_ARRAY(elem), tree.pos) + val dims = arr.dimensions + var elemKind = arr.elementKind + if (args.length != dims) + for (i <- args.length until dims) elemKind = ARRAY(elemKind) + ctx1.bb.emit(CREATE_ARRAY(elemKind, args.length), tree.pos) case rt @ REFERENCE(cls) => assert(ctor.owner == cls, @@ -958,7 +962,7 @@ abstract class GenICode extends SubComponent { generatedType = ARRAY(elmKind) ctx1.bb.emit(CONSTANT(new Constant(elems.length)), tree.pos) - ctx1.bb.emit(CREATE_ARRAY(elmKind)) + ctx1.bb.emit(CREATE_ARRAY(elmKind, 1)) // inline array literals var i = 0 while (i < elems.length) { diff --git a/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala b/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala index 93941f653a..7590dea711 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala @@ -26,7 +26,7 @@ import scala.tools.nsc.util.{Position,NoPosition} case CALL_PRIMITIVE(primitive) => case CALL_METHOD(method, style) => case NEW(kind) => - case CREATE_ARRAY(elem) => + case CREATE_ARRAY(elem, dims) => case IS_INSTANCE(tpe) => case CHECK_CAST(tpe) => case SWITCH(tags, labels) => @@ -361,15 +361,15 @@ trait Opcodes { self: ICodes => /** This class represents a CREATE_ARRAY instruction - * Stack: ...:size(int) + * Stack: ...:size_1:size_2:..:size_n * ->: ...:arrayref */ - case class CREATE_ARRAY(elem: TypeKind) extends Instruction { + case class CREATE_ARRAY(elem: TypeKind, dims: Int) extends Instruction { /** Returns a string representation of this instruction */ - override def toString(): String ="CREATE_ARRAY "+elem.toString(); + override def toString(): String ="CREATE_ARRAY "+elem.toString() + " x " + dims; - override def consumed = 1; - override def consumedTypes = INT :: Nil + override def consumed = dims; + override def consumedTypes = List.make(dims, INT) override def produced = 1; } diff --git a/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala b/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala index 1bf5455a13..233fb09e0c 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala @@ -82,6 +82,9 @@ trait TypeKinds { self: ICodes => case DOUBLE | LONG => true case _ => false } + + /** The number of dimensions for array types. */ + def dimensions: Int = 0 } /** @@ -272,12 +275,28 @@ trait TypeKinds { self: ICodes => // "VALUE(" + cls.fullNameString + ")"; // } + def ArrayN(elem: TypeKind, dims: Int): ARRAY = { + assert(dims > 0) + if (dims == 1) + ARRAY(elem) + else + ARRAY(ArrayN(elem, dims - 1)) + } + final case class ARRAY(val elem: TypeKind) extends TypeKind { override def toString(): String = "ARRAY[" + elem + "]" override def isArrayType = true + override def dimensions: Int = 1 + elem.dimensions + + /** The ultimate element type of this array. */ + def elementKind: TypeKind = elem match { + case a @ ARRAY(e1) => a.elementKind + case k => k + } + /** * Approximate `lub'. The common type of two references is * always AnyRef. For 'real' least upper bound wrt to subclassing diff --git a/src/compiler/scala/tools/nsc/backend/icode/TypeStacks.scala b/src/compiler/scala/tools/nsc/backend/icode/TypeStacks.scala index 53a1c13dc8..0fe5f852f2 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/TypeStacks.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/TypeStacks.scala @@ -60,12 +60,16 @@ trait TypeStacks { self: ICodes => def pop3: (TypeKind, TypeKind, TypeKind) = (pop, pop, pop) /** Drop the first n elements of the stack. */ - def pop(n: Int): Unit = types = types.drop(n) + def pop(n: Int): List[TypeKind] = { + val prefix = types.take(n) + types = types.drop(n) + prefix + } /** * A TypeStack aggress with another one if they have the same * length and each type kind agrees position-wise. Two - * types agree if they are subtypes of one another. + * types agree if one is a subtype of the other. */ def agreesWith(other: TypeStack): Boolean = (types.length == other.types.length) && diff --git a/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala b/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala index 4ab2883126..aca103aecf 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala @@ -341,8 +341,8 @@ abstract class CopyPropagation { } out.stack = v1 :: out.stack - case CREATE_ARRAY(elem) => - out.stack = Unknown :: out.stack.drop(1) + case CREATE_ARRAY(elem, dims) => + out.stack = Unknown :: out.stack.drop(dims) case IS_INSTANCE(tpe) => out.stack = Unknown :: out.stack.drop(1) diff --git a/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala b/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala index 4a69746c71..eacd40d42a 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala @@ -274,8 +274,8 @@ abstract class TypeFlowAnalysis { case NEW(kind) => stack.push(kind) - case CREATE_ARRAY(elem) => - stack.pop + case CREATE_ARRAY(elem, dims) => + stack.pop(dims) stack.push(ARRAY(elem)) case IS_INSTANCE(tpe) => diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala index 809ff80eb3..88f635f79d 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala @@ -811,12 +811,14 @@ abstract class GenJVM extends SubComponent { val className = javaName(cls) jcode.emitNEW(className) - case CREATE_ARRAY(elem) => elem match { + case CREATE_ARRAY(elem, 1) => elem match { case REFERENCE(_) | ARRAY(_) => jcode.emitANEWARRAY(javaType(elem).asInstanceOf[JReferenceType]) case _ => jcode.emitNEWARRAY(javaType(elem)) } + case CREATE_ARRAY(elem, dims) => + jcode.emitMULTIANEWARRAY(javaType(ArrayN(elem, dims)).asInstanceOf[JReferenceType], dims) case IS_INSTANCE(tpe) => tpe match { diff --git a/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala b/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala index 39c128d847..4111f2ec84 100644 --- a/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala +++ b/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala @@ -1473,7 +1473,10 @@ abstract class GenMSIL extends SubComponent { ignoreNextDup = true // works also for arrays and reference-types - case CREATE_ARRAY(elem) => mcode.Emit(OpCodes.Newarr, msilType(elem)) + case CREATE_ARRAY(elem, dims) => + // TODO: handle multi dimensional arrays + assert(dims == 1, "Can't handle multi dimensional arrays") + mcode.Emit(OpCodes.Newarr, msilType(elem)) // works for arrays and reference-types case IS_INSTANCE(tpe) => diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala index d9a6740b1e..3a3f67e549 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala @@ -490,11 +490,11 @@ abstract class ICodeReader extends ClassfileParser { case T_LONG => LONG } size += 1 - code.emit(CREATE_ARRAY(kind)) + code.emit(CREATE_ARRAY(kind, 1)) case JVM.anewarray => val tpe = pool.getClassOrArrayType(in.nextChar); size += 2 - code.emit(CREATE_ARRAY(toTypeKind(tpe))) + code.emit(CREATE_ARRAY(toTypeKind(tpe), 1)) case JVM.arraylength => code.emit(CALL_PRIMITIVE(ArrayLength(OBJECT))); // the kind does not matter case JVM.athrow => code.emit(THROW()); @@ -531,8 +531,8 @@ abstract class ICodeReader extends ClassfileParser { size += 3 val tpe = toTypeKind(pool.getClassOrArrayType(in.nextChar)) val dim = in.nextByte - assert(dim == 1, "Cannot handle multidimensional arrays yet.") - code.emit(CREATE_ARRAY(tpe)) +// assert(dim == 1, "Cannot handle multidimensional arrays yet.") + code.emit(CREATE_ARRAY(tpe, dim)) case JVM.ifnull => code.emit(LCZJUMP(parseJumpTarget, pc + size, EQ, OBJECT)) case JVM.ifnonnull => code.emit(LCZJUMP(parseJumpTarget, pc + size, NE, OBJECT)) diff --git a/src/library/scala/Array.scala b/src/library/scala/Array.scala index aaf72f1c92..b9e58afbed 100644 --- a/src/library/scala/Array.scala +++ b/src/library/scala/Array.scala @@ -189,6 +189,54 @@ object Array { */ final class Array[A](_length: Int) extends RandomAccessSeq.Mutable[A] { + /** Multidimensional array creation */ + def this(dim1: Int, dim2: Int) = { + this(dim1); + throw new Error() + } + + /** Multidimensional array creation */ + def this(dim1: Int, dim2: Int, dim3: Int) = { + this(dim1); + throw new Error() + } + + /** Multidimensional array creation */ + def this(dim1: Int, dim2: Int, dim3: Int, dim4: Int) = { + this(dim1); + throw new Error() + } + + /** Multidimensional array creation */ + def this(dim1: Int, dim2: Int, dim3: Int, dim4: Int, dim5: Int) = { + this(dim1); + throw new Error() + } + + /** Multidimensional array creation */ + def this(dim1: Int, dim2: Int, dim3: Int, dim4: Int, dim5: Int, dim6: Int) = { + this(dim1); + throw new Error() + } + + /** Multidimensional array creation */ + def this(dim1: Int, dim2: Int, dim3: Int, dim4: Int, dim5: Int, dim6: Int, dim7: Int) = { + this(dim1); + throw new Error() + } + + /** Multidimensional array creation */ + def this(dim1: Int, dim2: Int, dim3: Int, dim4: Int, dim5: Int, dim6: Int, dim7: Int, dim8: Int) = { + this(dim1); + throw new Error() + } + + /** Multidimensional array creation */ + def this(dim1: Int, dim2: Int, dim3: Int, dim4: Int, dim5: Int, dim6: Int, dim7: Int, dim8: Int, dim9: Int) = { + this(dim1); + throw new Error() + } + /** The length of the array */ def length: Int = throw new Error() |