From d5b02c8652d7edbdfb0b5a02570d370d3bad299f Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 21 Sep 2009 12:50:04 +0000 Subject: new arrays are done. --- src/compiler/scala/tools/nsc/Global.scala | 4 - src/compiler/scala/tools/nsc/ScriptRunner.scala | 2 +- src/compiler/scala/tools/nsc/ast/TreeGen.scala | 7 +- .../scala/tools/nsc/backend/icode/GenICode.scala | 3 +- src/compiler/scala/tools/nsc/io/Process.scala | 2 +- .../scala/tools/nsc/symtab/Definitions.scala | 40 ++- src/compiler/scala/tools/nsc/symtab/Symbols.scala | 2 +- .../scala/tools/nsc/transform/CleanUp.scala | 4 +- .../scala/tools/nsc/transform/Erasure.scala | 184 +++++--------- .../scala/tools/nsc/transform/UnCurry.scala | 127 +++++----- .../scala/tools/nsc/typechecker/Implicits.scala | 16 +- .../scala/tools/nsc/typechecker/Infer.scala | 5 +- .../scala/tools/nsc/typechecker/RefChecks.scala | 2 +- .../scala/tools/nsc/typechecker/Typers.scala | 88 +++---- .../scala/tools/nsc/util/JavaCharArrayReader.scala | 2 +- src/compiler/scala/tools/nsc/util/SourceFile.scala | 2 +- src/library/scala/Array.scala | 274 +++++++++------------ src/library/scala/LowPriorityImplicits.scala | 18 +- src/library/scala/Predef.scala | 33 ++- .../scala/collection/immutable/PagedSeq.scala | 8 +- .../scala/collection/immutable/StringLike.scala | 4 +- .../scala/collection/mutable/ArrayBuffer.scala | 8 +- .../scala/collection/mutable/ArrayBuilder.scala | 133 ++++------ .../scala/collection/mutable/ArrayLike.scala | 56 +++++ .../scala/collection/mutable/ArrayOps.scala | 69 ++++-- .../scala/collection/mutable/StringBuilder.scala | 8 +- .../scala/collection/mutable/WrappedArray.scala | 135 ++++------ src/library/scala/io/BytePickle.scala | 8 +- src/library/scala/reflect/ClassManifest.scala | 79 ++++-- src/library/scala/reflect/FullManifest.scala | 147 ----------- src/library/scala/reflect/Manifest.scala | 77 +++--- src/library/scala/reflect/RichClass.scala | 6 +- src/library/scala/runtime/BoxedArray.scala | 7 +- src/library/scala/runtime/RichString.scala | 4 +- src/library/scala/runtime/ScalaRunTime.scala | 54 ++-- src/library/scala/util/ClassLoader.scala | 4 +- src/library/scala/xml/Utility.scala | 2 +- .../scala/xml/transform/BasicTransformer.scala | 2 +- src/partest/scala/tools/partest/PartestTask.scala | 4 +- .../scala/tools/scalap/scalax/rules/SeqRule.scala | 2 +- src/swing/scala/swing/ListView.scala | 2 +- 41 files changed, 738 insertions(+), 896 deletions(-) create mode 100644 src/library/scala/collection/mutable/ArrayLike.scala delete mode 100644 src/library/scala/reflect/FullManifest.scala (limited to 'src') diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index a27169503e..56b8253fa7 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -655,10 +655,6 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable */ class Run { -// settings.newArrays.value = true -// settings.print.value = List("era") - if (settings.verbose.value) println("compiling with newArrays = "+settings.newArrays.value) - var isDefined = false private val firstPhase = { diff --git a/src/compiler/scala/tools/nsc/ScriptRunner.scala b/src/compiler/scala/tools/nsc/ScriptRunner.scala index f87fdf093d..392fce46a3 100644 --- a/src/compiler/scala/tools/nsc/ScriptRunner.scala +++ b/src/compiler/scala/tools/nsc/ScriptRunner.scala @@ -326,7 +326,7 @@ object ScriptRunner ObjectRunner.run( classpath, scriptMain(settings), - scriptArgs.toArray) + scriptArgs) true } catch { diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala index 233a3368bd..abf7026f3a 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala @@ -274,15 +274,10 @@ abstract class TreeGen DefDef(accessor setFlag lateDEFERRED, EmptyTree) def mkRuntimeCall(meth: Name, args: List[Tree]): Tree = { - assert(!settings.newArrays.value || meth.toString != "boxArray") + assert(meth.toString != "boxArray") // !!! can be removed once arrays are in. Apply(Select(mkAttributedRef(ScalaRunTimeModule), meth), args) } - // !!! todo: remove - def mkPredefCall(meth: Name, args: List[Tree]): Tree = { - Apply(Select(mkAttributedRef(PredefModule), meth), args) - } - /** Make a synchronized block on 'monitor'. */ def mkSynchronized(monitor: Tree, body: Tree): Tree = Apply(Select(monitor, Object_synchronized), List(body)) diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala index 2f8d6ae9f6..d7b6c16041 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala @@ -865,8 +865,7 @@ abstract class GenICode extends SubComponent { } else { ctx.bb.emit(THIS(ctx.clazz.symbol), tree.pos) if (tree.symbol == definitions.ArrayClass) - generatedType = REFERENCE( - if (settings.newArrays.value) definitions.ObjectClass else definitions.BoxedAnyArrayClass) + generatedType = REFERENCE(definitions.ObjectClass) else generatedType = REFERENCE(ctx.clazz.symbol) } diff --git a/src/compiler/scala/tools/nsc/io/Process.scala b/src/compiler/scala/tools/nsc/io/Process.scala index 6a1029fa02..e6626e0abe 100644 --- a/src/compiler/scala/tools/nsc/io/Process.scala +++ b/src/compiler/scala/tools/nsc/io/Process.scala @@ -42,7 +42,7 @@ object Process @experimental private[Process] class ProcessBuilder(val pb: JProcessBuilder) { - def this(cmd: String*) = this(new JProcessBuilder(cmd.toArray: _*)) + def this(cmd: String*) = this(new JProcessBuilder(cmd: _*)) def start() = new Process(() => pb.start()) def withOnlyEnv(env: Map[String, String]): this.type = { diff --git a/src/compiler/scala/tools/nsc/symtab/Definitions.scala b/src/compiler/scala/tools/nsc/symtab/Definitions.scala index 7d624d8289..6131d145f2 100644 --- a/src/compiler/scala/tools/nsc/symtab/Definitions.scala +++ b/src/compiler/scala/tools/nsc/symtab/Definitions.scala @@ -227,6 +227,11 @@ trait Definitions { } val MaxTupleArity, MaxProductArity, MaxFunctionArity = 22 + /** The maximal dimensions of a generic array creation. + * I.e. new Array[Array[Array[Array[Array[T]]]]] creates a 5 times + * nested array. More is not allowed. + */ + val MaxArrayDims = 5 lazy val TupleClass = mkArityArray("Tuple", MaxTupleArity) lazy val ProductClass = mkArityArray("Product", MaxProductArity) lazy val FunctionClass = mkArityArray("Function", MaxFunctionArity, 0) @@ -673,17 +678,15 @@ trait Definitions { def isValueClass(sym: Symbol): Boolean = (sym eq UnitClass) || (boxedClass contains sym) - /** Is symbol a value class? */ + /** Is symbol a numeric value class? */ def isNumericValueClass(sym: Symbol): Boolean = (sym ne BooleanClass) && (boxedClass contains sym) - // !!! todo comment & rename! - def isValueType(sym: Symbol) = + // !!! todo merge with isValueClass + def isValueType(sym: Symbol) = { + assert(isValueClass(sym) || !unboxMethod.contains(sym)) isValueClass(sym) || unboxMethod.contains(sym) - - /** Is symbol a value or array class? */ - def isUnboxedClass(sym: Symbol): Boolean = - isValueType(sym) || !settings.newArrays.value && sym == ArrayClass + } def signature(tp: Type): String = { def erasure(tp: Type): Type = tp match { @@ -751,6 +754,29 @@ trait Definitions { String_+ = newMethod( StringClass, "+", anyparam, StringClass.typeConstructor) setFlag FINAL + val forced = List( // force initialization of every symbol that is enetred as a side effect + AnnotationDefaultAttr, + RepeatedParamClass, + JavaRepeatedParamClass, + ByNameParamClass, + UnitClass, + ByteClass, + ShortClass, + CharClass, + IntClass, + LongClass, + FloatClass, + DoubleClass, + BooleanClass, + AnyClass, + AnyRefClass, + AnyValClass, + NullClass, + NothingClass, + SingletonClass, + EqualsPatternClass + ) + // #2264 var tmp = AnnotationDefaultAttr tmp = RepeatedParamClass // force initalization diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala index 885ff0d8ee..5f9a2b6bd3 100644 --- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala +++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala @@ -548,7 +548,7 @@ trait Symbols { /** Is this symbol a sealed class?*/ final def isSealed: Boolean = - isClass && (hasFlag(SEALED) || isUnboxedClass(this)) + isClass && (hasFlag(SEALED) || isValueClass(this)) /** Is this symbol locally defined? I.e. not accessed from outside `this' instance */ final def isLocal: Boolean = owner.isTerm diff --git a/src/compiler/scala/tools/nsc/transform/CleanUp.scala b/src/compiler/scala/tools/nsc/transform/CleanUp.scala index 45acc4f763..8136893fcb 100644 --- a/src/compiler/scala/tools/nsc/transform/CleanUp.scala +++ b/src/compiler/scala/tools/nsc/transform/CleanUp.scala @@ -337,7 +337,8 @@ abstract class CleanUp extends Transform with ast.TreeDSL { } } - def boxArray(t: Tree) = { + def boxArray(t: Tree) = t +/* was: assert(!settings.newArrays.value) val sym = currentOwner.newValue(ad.pos, mkTerm()) setInfo ObjectClass.tpe BLOCK( @@ -345,6 +346,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL { IF (NULL ANY_== REF(sym)) THEN NULL ELSE gen.mkRuntimeCall(nme.boxArray, List(REF(sym))) ) } +*/ /* ### BOXING PARAMS & UNBOXING RESULTS ### */ diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index 0efd87a0ac..37f28ec08e 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -33,25 +33,47 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer with ast. // -------- erasure on types -------------------------------------------------------- - /** If `tp` is of the form Array[...Array[T]...] where `T` is an abstract type - * then the number of Array constructors enclosing `T`, otherwise 0 - */ - def genericArrayLevel(tp: Type): Int = tp match { - case TypeRef(_, ArrayClass, List(arg)) => - arg match { - case TypeRef(_, argsym, _) if (argsym.isAbstractType && !(argsym.owner hasFlag JAVA)) => - 1 - case _ => - val l = genericArrayLevel(arg) - if (l > 0) l + 1 else 0 - } - case ExistentialType(tparams, restp) => - genericArrayLevel(restp) - case _ => - 0 + /** An extractor objec for generic arrays */ + object GenericArray { + + /** Is `tp` an unbounded generic type (i.e. which could be instantiated + * with primitive as well as class types)?. + */ + private def genericCore(tp: Type): Type = tp match { + case TypeRef(_, argsym, _) if (argsym.isAbstractType && !(argsym.owner hasFlag JAVA)) => + tp + case ExistentialType(tparams, restp) => + genericCore(restp) + case _ => + NoType + } + + /** If `tp` is of the form Array[...Array[T]...] where `T` is an abstract type + * then Some(N, T) where N is the number of Array constructors enclosing `T`, + * otherwise None. Existentials on any level are ignored. + */ + def unapply(tp: Type): Option[(Int, Type)] = tp match { + case TypeRef(_, ArrayClass, List(arg)) => + genericCore(arg) match { + case NoType => + unapply(arg) match { + case Some((level, core)) => Some((level + 1, core)) + case None => None + } + case core => + Some(1, core) + } + case ExistentialType(tparams, restp) => + unapply(restp) + case _ => + None + } } - def isTopLevelGenericArray(tp: Type): Boolean = genericArrayLevel(tp) == 1 + private def unboundedGenericArrayLevel(tp: Type): Int = tp match { + case GenericArray(level, core) if !(core <:< AnyRefClass.tpe) => level + case _ => 0 + } /**

* The erasure |T| of a type T. This is: @@ -104,8 +126,8 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer with ast. false } if (sym == ArrayClass) - if (!settings.newArrays.value && isGeneric(tp)) erasedTypeRef(BoxedArrayClass) - else if (settings.newArrays.value && isTopLevelGenericArray(tp)) ObjectClass.tpe + if (unboundedGenericArrayLevel(tp) == 1) ObjectClass.tpe + else if (args.head.typeSymbol == NothingClass || args.head.typeSymbol == NullClass) arrayType(ObjectClass.tpe) else typeRef(apply(pre), sym, args map this) else if (sym == AnyClass || sym == AnyValClass || sym == SingletonClass) erasedTypeRef(ObjectClass) else if (sym == UnitClass) erasedTypeRef(BoxedUnitClass) @@ -401,11 +423,9 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer with ast. case UnitClass => if (treeInfo isPureExpr tree) REF(BoxedUnit_UNIT) else BLOCK(tree, REF(BoxedUnit_UNIT)) - case ArrayClass => - assert(!settings.newArrays.value) - boxArray(tree) case x => - (REF(boxMethod(x)) APPLY tree) setPos (tree.pos) setType (ObjectClass.tpe) + assert(x != ArrayClass) + (REF(boxMethod(x)) APPLY tree) setPos (tree.pos) setType ObjectClass.tpe }) } @@ -435,57 +455,16 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer with ast. case UnitClass => if (treeInfo isPureExpr tree) UNIT else BLOCK(tree, UNIT) - case ArrayClass => - assert(!settings.newArrays.value) - val tree1 = adaptToType(tree, BoxedArrayClass.tpe) - gen.mkRuntimeCall(nme.arrayValue, List(tree1, Literal(pt.typeArgs.head))) - case _ => + case x => + assert(x != ArrayClass) (REF(unboxMethod(pt.typeSymbol)) APPLY tree) setType pt }) } - /**

- * Generate a cast operation from tree.tpe to pt. - * The following cases need to be treated specially: - *

- * - * - * - * - * - * - * - * - * - * - * - * - * - *
Object -> Array(might be a boxedarray)
Object -> Boxed*Array(might be an array, which nees to be boxed)
Object -> Seq, Iterable(might be an array, which needs to be boxed)
+ /** Generate a synthetic cast operation from tree.tpe to pt. */ - private def cast(tree: Tree, pt: Type): Tree = { - if (settings.newArrays.value) return tree AS_ATTR pt - assert(pt eq pt.normalize) - def asPt(t: Tree) = t AS_ATTR pt - def once(within: (() => Tree) => Tree) = - typedPos(tree.pos)(gen.evalOnce(tree, context.owner, context.unit)(within andThen asPt)) - - if (tree.tpe.typeSymbol == ObjectClass) { - if (pt.typeSymbol == ArrayClass) once (x => - (IF (x() IS_OBJ BoxedArrayClass.tpe) - THEN (unbox(x() AS_ATTR BoxedArrayClass.tpe, pt)) - ELSE (x()) - ) - ) - else if (pt.typeSymbol isNonBottomSubClass BoxedArrayClass) once (x => - (IF (x() IS_OBJ BoxedArrayClass.tpe) THEN (x()) ELSE boxArray(x())) - ) - else if (isSeqClass(pt.typeSymbol)) once (x => - (IF (x() IS_OBJ pt) THEN (x()) ELSE (boxArray(x()))) - ) - else asPt(tree) - } else asPt(tree) - } + private def cast(tree: Tree, pt: Type): Tree = + tree AS_ATTR pt /** Is symbol a member of unboxed arrays (which will be expanded directly * later)? @@ -512,14 +491,14 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer with ast. log("adapting " + tree + ":" + tree.tpe + " : " + tree.tpe.parents + " to " + pt)//debug if (tree.tpe <:< pt) tree - else if (isUnboxedClass(tree.tpe.typeSymbol) && !isUnboxedClass(pt.typeSymbol)) + else if (isValueClass(tree.tpe.typeSymbol) && !isValueClass(pt.typeSymbol)) adaptToType(box(tree), pt) else if (tree.tpe.isInstanceOf[MethodType] && tree.tpe.paramTypes.isEmpty) { if (!tree.symbol.isStable) assert(false, "adapt "+tree+":"+tree.tpe+" to "+pt) adaptToType(Apply(tree, List()) setPos tree.pos setType tree.tpe.resultType, pt) } else if (pt <:< tree.tpe) cast(tree, pt) - else if (isUnboxedClass(pt.typeSymbol) && !isUnboxedClass(tree.tpe.typeSymbol)) + else if (isValueClass(pt.typeSymbol) && !isValueClass(tree.tpe.typeSymbol)) adaptToType(unbox(tree, pt), pt) else cast(tree, pt) @@ -584,17 +563,6 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer with ast. private def adaptMember(tree: Tree): Tree = { //Console.println("adaptMember: " + tree); tree match { - // newArrays: we do not need to handle ofDim for ne generic arrays here; has been treated in RefChecks - case Apply(Select(New(tpt), name), args) if (tpt.tpe.typeSymbol == BoxedArrayClass) => - assert(!settings.newArrays.value) - assert(name == nme.CONSTRUCTOR); - val translated: Tree = - if (args.length >= 2) REF(ArrayModule) DOT nme.ofDim - else NEW(BoxedAnyArrayClass) DOT name - - typedPos(tree.pos) { - Typed(Apply(translated, args), tpt) - } case Apply(TypeApply(sel @ Select(qual, name), List(targ)), List()) if tree.symbol == Any_asInstanceOf => val qual1 = typedQualifier(qual) val qualClass = qual1.tpe.typeSymbol @@ -605,16 +573,8 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer with ast. atPos(tree.pos)(Apply(Select(qual1, "to" + targClass.name), List())) else */ - if (isValueType(targClass)) { - unbox(qual1, targ.tpe) - } else if (targClass == ArrayClass && (qualClass isNonBottomSubClass BoxedArrayClass)) { - assert(!settings.newArrays.value) - unbox(qual1, targ.tpe) - } else if (!settings.newArrays.value && targClass == ArrayClass && qualClass == ObjectClass || isSeqClass(targClass)) { - cast(qual1, targ.tpe) - } else { - tree - } + if (isValueType(targClass)) unbox(qual1, targ.tpe) + else tree case Select(qual, name) if (name != nme.CONSTRUCTOR) => if (tree.symbol == NoSymbol) tree @@ -626,15 +586,12 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer with ast. adaptMember(atPos(tree.pos)(Select(qual, getMember(ObjectClass, name)))) else { var qual1 = typedQualifier(qual); - if ((isValueType(qual1.tpe.typeSymbol) && !isUnboxedValueMember(tree.symbol)) || - (qual1.tpe.typeSymbol == ArrayClass && !isUnboxedArrayMember(tree.symbol) && !settings.newArrays.value)) - qual1 = box(qual1); + if ((isValueType(qual1.tpe.typeSymbol) && !isUnboxedValueMember(tree.symbol))) + qual1 = box(qual1) else if (!isValueType(qual1.tpe.typeSymbol) && isUnboxedValueMember(tree.symbol)) qual1 = unbox(qual1, tree.symbol.owner.tpe) - else if (tree.symbol.owner == ArrayClass && (BoxedArrayClass isSubClass qual1.tpe.typeSymbol) && !settings.newArrays.value) - qual1 = cast(qual1, BoxedArrayClass.tpe) - if (isUnboxedClass(tree.symbol.owner) && !isUnboxedClass(qual1.tpe.typeSymbol)) + if (isValueClass(tree.symbol.owner) && !isValueClass(qual1.tpe.typeSymbol)) tree.symbol = NoSymbol else if (qual1.tpe.isInstanceOf[MethodType] && qual1.tpe.paramTypes.isEmpty) { assert(qual1.symbol.isStable, qual1.symbol); @@ -948,10 +905,10 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer with ast. treeCopy.DefDef(tree, mods, name, List(), vparamss, tpt, rhs) case TypeDef(_, _, _, _) => EmptyTree - case TypeApply(fun, args @ List(arg)) + case TypeApply(fun, args @ List(arg)) // !!! todo: simplify by having GenericArray also extract trees if ((fun.symbol == Any_isInstanceOf || fun.symbol == Object_isInstanceOf) && - genericArrayLevel(arg.tpe) > 0) => - val level = genericArrayLevel(arg.tpe) + unboundedGenericArrayLevel(arg.tpe) > 0) => + val level = unboundedGenericArrayLevel(arg.tpe) def isArrayTest(arg: Tree) = gen.mkRuntimeCall("isArray", List(arg, Literal(Constant(level)))) typedPos(tree.pos) { @@ -969,23 +926,11 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer with ast. // leave all other type tests/type casts, remove all other type applications fun case Apply(fn @ Select(qual, name), args) - if (settings.newArrays.value && fn.symbol.owner == ArrayClass && isTopLevelGenericArray(qual.tpe.widen)) => + if (fn.symbol.owner == ArrayClass && (unboundedGenericArrayLevel(qual.tpe.widen) == 1)) => // convert calls to apply/update/length on generic arrays to // calls of ScalaRunTime.array_xxx method calls typedPos(tree.pos) { gen.mkRuntimeCall("array_"+name, qual :: args) } case Apply(fn, args) => - if (!settings.newArrays.value) { - def isGenericArray(tpe: Type): Boolean = erasure(tpe).typeSymbol == BoxedArrayClass - if (fn.hasSymbol && - fn.symbol.name == nme.arraycopy && - fn.symbol.owner.name == nme.System.toTypeName && - fn.symbol.owner.owner == JavaLangPackage.tpe.typeSymbol && - args.length == 5 && - (isGenericArray(args(0).tpe) || isGenericArray(args(2).tpe))) - unit.warning(tree.pos, - "System.arraycopy should be applied only to arrays with fixed element types;\n" + - "use Array.copy instead") - } if (fn.symbol == Any_asInstanceOf) fn match { case TypeApply(Select(qual, _), List(targ)) => @@ -1024,16 +969,7 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer with ast. } } case _ => - if (isSeqClass(targ.tpe.typeSymbol) && !settings.newArrays.value) { - atPos(tree.pos) { - gen.evalOnce(qual, currentOwner, unit) { q => - gen.mkOr( - mkIsInstanceOf(q)(targ.tpe), - atPos(tree.pos) { REF(isArrayMethod) APPLY (q()) } - ) - } - } - } else tree + tree } case _ => tree } diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala index e10a8d8365..1cd7842fd4 100644 --- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala +++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala @@ -23,11 +23,14 @@ import scala.tools.nsc.util.Position * if argument is not a reference to a def parameter: * convert argument `e' to (expansion of) `() => e' * - for every repeated Scala parameter `x: T*' --> x: Seq[T]. - * - for every repeated Java parameter `x: T*' --> x: Array[T]. - * - for every argument list that corresponds to a repeated parameter + * - for every repeated Java parameter `x: T...' --> x: Array[T], except: + * if T is an unbounded abstract type, replace --> x: Array[Object] + * - for every argument list that corresponds to a repeated Scala parameter * (a_1, ..., a_n) => (Seq(a_1, ..., a_n)) + * - for every argument list that corresponds to a repeated Java parameter + * (a_1, ..., a_n) => (Array(a_1, ..., a_n)) * - for every argument list that is an escaped sequence - * (a_1:_*) => (a_1)g + * (a_1:_*) => (a_1) (possibly converted to sequence or array, as needed) * - convert implicit method types to method types * - convert non-trivial catches in try statements to matches * - convert non-local returns to throws with enclosing try statements. @@ -49,6 +52,11 @@ abstract class UnCurry extends InfoTransform with TypingTransformers { // OTOH, should be a problem as calls to normalize only occur on types with kind * in principle (in well-typed programs) private def expandAlias(tp: Type): Type = if (!tp.isHigherKinded) tp.normalize else tp + private def isUnboundedGeneric(tp: Type) = tp match { + case t @ TypeRef(_, sym, _) => sym.isAbstractType && !(t <:< AnyRefClass.tpe) + case _ => false + } + private val uncurry: TypeMap = new TypeMap { def apply(tp0: Type): Type = { val tp = expandAlias(tp0) @@ -69,7 +77,8 @@ abstract class UnCurry extends InfoTransform with TypingTransformers { case TypeRef(pre, sym, args) if (sym == RepeatedParamClass) => apply(appliedType(SeqClass.typeConstructor, args)) case TypeRef(pre, sym, args) if (sym == JavaRepeatedParamClass) => - apply(appliedType(ArrayClass.typeConstructor, args)) + apply(arrayType( + if (isUnboundedGeneric(args.head)) ObjectClass.tpe else args.head)) case _ => expandAlias(mapOver(tp)) } @@ -131,11 +140,17 @@ abstract class UnCurry extends InfoTransform with TypingTransformers { freeLocalsTraverser(unit.body) unit.body = transform(unit.body) } + + private var nprinted = 0 + override def transform(tree: Tree): Tree = try { //debug postTransform(mainTransform(tree)) } catch { case ex: Throwable => - Console.println("exception when traversing " + tree) + if (nprinted < 10) { + Console.println("exception when traversing " + tree) + nprinted += 1 + } throw ex } @@ -357,70 +372,65 @@ abstract class UnCurry extends InfoTransform with TypingTransformers { } } - def transformArgs(pos: Position, args: List[Tree], formals: List[Type], isJava: Boolean) = { + def transformArgs(pos: Position, fun: Symbol, args: List[Tree], formals: List[Type]) = { + val isJava = fun hasFlag JAVA val args1 = formals.lastOption match { case Some(lastFormal) if isRepeatedParamType(lastFormal) => - def callMethod(tree: Tree, nme: Name): Tree = { - assert(!settings.newArrays.value) - val sym = tree.tpe member nme - assert(sym != NoSymbol) - val arguments = - if (sym.tpe.paramTypes.isEmpty) List() // !!! no manifest required - else List(localTyper.getManifestTree(tree.pos, tree.tpe.typeArgs.head, false)) // call with manifest + def mkArrayValue(ts: List[Tree], elemtp: Type) = + ArrayValue(TypeTree(elemtp), ts) setType arrayType(elemtp) + + // when calling into scala varargs, make sure it's a sequence. + def arrayToSequence(tree: Tree, elemtp: Type) = { atPhase(phase.next) { localTyper.typedPos(pos) { - Apply(gen.mkAttributedSelect(tree, sym), arguments) + val predef = gen.mkAttributedRef(PredefModule) + val meth = + if ((elemtp <:< AnyRefClass.tpe) && !isPhantomClass(elemtp.typeSymbol) || + isValueClass(elemtp.typeSymbol)) + Select(predef, "wrapArray") + else + TypeApply(Select(predef, "genericWrapArray"), List(TypeTree(elemtp))) + Apply(meth, List(tree)) } } } - def mkArrayValue(ts: List[Tree]) = { - val elemTp = lastFormal.typeArgs.head - val arr = ArrayValue(TypeTree(elemTp), ts) setType arrayType(elemTp) - if (isJava || inPattern) arr - else if (settings.newArrays.value) - atPhase(phase.next) { - localTyper.typedPos(pos) { - val predef = gen.mkAttributedRef(PredefModule) - val meth = - if ((elemTp <:< AnyRefClass.tpe) || isValueClass(elemTp.typeSymbol)) - Select(predef, "wrapArray") - else - TypeApply(Select(predef, "genericWrapArray"), List(TypeTree(elemTp))) - Apply(meth, List(arr)) - } - } - else callMethod(arr, nme.toSequence) // println("need to callMethod("+arr+", nme.toSequence)"); arr } - } setType formals.last - // when calling into java varargs, make sure it's an array - see bug #1360 - def forceToArray(arg: Tree) = { - val Typed(tree, _) = arg - if (isJava && tree.tpe.typeSymbol != ArrayClass && - (tree.tpe.typeSymbol isSubClass TraversableClass)) { - if (settings.newArrays.value) { - val toArraySym = tree.tpe member nme.toArray - assert(toArraySym != NoSymbol) - atPhase(phase.next) { - localTyper.typedPos(pos) { - Apply( - gen.mkAttributedSelect(tree, toArraySym), - List(localTyper.getManifestTree(tree.pos, tree.tpe.typeArgs.head, false))) - } - } - } else callMethod(tree, nme.toArray) - } else tree + def sequenceToArray(tree: Tree) = { + val toArraySym = tree.tpe member nme.toArray + assert(toArraySym != NoSymbol) + atPhase(phase.next) { + localTyper.typedPos(pos) { + Apply( + gen.mkAttributedSelect(tree, toArraySym), + List(localTyper.getManifestTree(tree.pos, tree.tpe.typeArgs.head, false))) + } + } } - if (args.isEmpty) - List(mkArrayValue(args)) - else { - val suffix: Tree = - if (treeInfo isWildcardStarArg args.last) forceToArray(args.last) - else mkArrayValue(args drop (formals.length - 1)) - args.take(formals.length - 1) ::: List(suffix) + var suffix: Tree = + if (!args.isEmpty && (treeInfo isWildcardStarArg args.last)) { + val Typed(tree, _) = args.last; + if (isJava && !(tree.tpe.typeSymbol == ArrayClass) && (tree.tpe.typeSymbol isSubClass TraversableClass)) sequenceToArray(tree) + else tree + } else { + val lastElemType = lastFormal.typeArgs.head + val tree = mkArrayValue(args drop (formals.length - 1), lastElemType) + if (isJava || inPattern) tree + else arrayToSequence(tree, lastElemType) + } + atPhase(phase.next) { + if (isJava && + suffix.tpe.typeSymbol == ArrayClass && + isValueClass(suffix.tpe.typeArgs.head.typeSymbol) && + fun.tpe.paramTypes.last.typeSymbol == ArrayClass && + fun.tpe.paramTypes.last.typeArgs.head.typeSymbol == ObjectClass) + suffix = localTyper.typedPos(pos) { + gen.mkRuntimeCall("toObjectArray", List(suffix)) + } } + args.take(formals.length - 1) ::: List(suffix setType formals.last) case _ => args } @@ -539,7 +549,7 @@ abstract class UnCurry extends InfoTransform with TypingTransformers { if (fn.symbol.name == nme.unapply) args else if (fn.symbol.name == nme.unapplySeq) - transformArgs(tree.pos, args, analyzer.unapplyTypeListFromReturnTypeSeq(fn.tpe), false) + transformArgs(tree.pos, fn.symbol, args, analyzer.unapplyTypeListFromReturnTypeSeq(fn.tpe)) else { assert(false,"internal error: UnApply node has wrong symbol"); null }) treeCopy.UnApply(tree, fn1, args1) @@ -556,8 +566,7 @@ abstract class UnCurry extends InfoTransform with TypingTransformers { } else { withNeedLift(true) { val formals = fn.tpe.paramTypes; - val isJava = fn.symbol hasFlag JAVA // in case we need a varargs transformation - treeCopy.Apply(tree, transform(fn), transformTrees(transformArgs(tree.pos, args, formals, isJava))) + treeCopy.Apply(tree, transform(fn), transformTrees(transformArgs(tree.pos, fn.symbol, args, formals))) } } diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index dbc90e569b..49e4b0758b 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -602,14 +602,14 @@ self: Analyzer => private def manifestOfType(tp: Type, full: Boolean): Tree = { /** Creates a tree that calls the factory method called constructor in object reflect.Manifest */ - def manifestFactoryCall(constructor: String, args: Tree*): Tree = + def manifestFactoryCall(constructor: String, tparg: Type, args: Tree*): Tree = if (args contains EmptyTree) EmptyTree else typed { atPos(tree.pos.focus) { Apply( TypeApply( Select(gen.mkAttributedRef(if (full) FullManifestModule else PartialManifestModule), constructor), - List(TypeTree(tp)) + List(TypeTree(tparg)) ), args.toList ) @@ -623,7 +623,7 @@ self: Analyzer => def mot(tp0: Type): Tree = tp0.normalize match { case ThisType(_) | SingleType(_, _) => - manifestFactoryCall("singleType", gen.mkAttributedQualifier(tp0)) + manifestFactoryCall("singleType", tp, gen.mkAttributedQualifier(tp0)) case ConstantType(value) => manifestOfType(tp0.deconst, full) case TypeRef(pre, sym, args) => @@ -631,15 +631,17 @@ self: Analyzer => typed { atPos(tree.pos.focus) { Select(gen.mkAttributedRef(FullManifestModule), sym.name.toString) }} - } else if (sym.isClass) { + } else if (sym == ArrayClass && args.length == 1) { + manifestFactoryCall("arrayType", args.head, findSubManifest(args.head)) + } else if (sym.isClass) { val suffix = gen.mkClassOf(tp0) :: (args map findSubManifest) manifestFactoryCall( - "classType", + "classType", tp, (if ((pre eq NoPrefix) || pre.typeSymbol.isStaticOwner) suffix else findSubManifest(pre) :: suffix): _*) } else if (sym.isAbstractType && !sym.isTypeParameterOrSkolem && !sym.isExistential) { manifestFactoryCall( - "abstractType", + "abstractType", tp, findSubManifest(pre) :: Literal(sym.name.toString) :: findManifest(tp0.bounds.hi) :: (args map findSubManifest): _*) } else { EmptyTree // a manifest should have been found by normal searchImplicit @@ -647,7 +649,7 @@ self: Analyzer => case RefinedType(parents, decls) => // refinement is not generated yet if (parents.length == 1) findManifest(parents.head) - else manifestFactoryCall("intersectionType", parents map (findSubManifest(_)): _*) + else manifestFactoryCall("intersectionType", tp, parents map (findSubManifest(_)): _*) case ExistentialType(tparams, result) => mot(result) case _ => diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala index 20f6a1ff45..f7829208b1 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala @@ -860,7 +860,7 @@ trait Infer { def isInProperSubClassOrObject(sym1: Symbol, sym2: Symbol) = sym2 == NoSymbol || isProperSubClassOrObject(sym1.owner, sym2.owner) - def isStrictlyMoreSpecific(ftpe1: Type, ftpe2: Type, sym1: Symbol, sym2: Symbol): Boolean = + def isStrictlyMoreSpecific(ftpe1: Type, ftpe2: Type, sym1: Symbol, sym2: Symbol): Boolean = { // ftpe1 / ftpe2 are OverloadedTypes (possibly with one single alternative) if they // denote the type of an "apply" member method (see "followApply") ftpe1.isError || { @@ -871,8 +871,11 @@ trait Infer { (!phase.erasedTypes || covariantReturnOverride(ftpe1, ftpe2))) 1 else 0) val subClassCount = (if (isInProperSubClassOrObject(sym1, sym2)) 1 else 0) - (if (isInProperSubClassOrObject(sym2, sym1)) 1 else 0) + //println("is more specific? "+sym1+sym1.locationString+"/"+sym2+sym2.locationString+":"+ + // specificCount+"/"+subClassCount+"/"+) specificCount + subClassCount > 0 } + } /* ftpe1.isError || { if (isAsSpecific(ftpe1, ftpe2)) diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 7cca32a779..be0c65c49b 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -916,7 +916,7 @@ abstract class RefChecks extends InfoTransform { List(ValDef(_, pname, tpt, _)), Match(_, CaseDef(pat1, _, _) :: _)))) if ((pname startsWith nme.CHECK_IF_REFUTABLE_STRING) && - isIrrefutable(pat1, tpt.tpe)) => + isIrrefutable(pat1, tpt.tpe) && (qual.tpe <:< tree.tpe)) => result = qual case Apply(Select(New(tpt), name), args) diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 2d519f8da8..792e24049f 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -142,12 +142,6 @@ trait Typers { self: Analyzer => */ val HKmode = 0x4000 // @M: could also use POLYmode | TAPPmode - /** The mode JAVACALLmode is set when we are typing a call to a Java method - * needed temporarily for vararg conversions - * !!!VARARG-CONVERSION!!! - */ - val JAVACALLmode = 0x8000 - /** The mode TYPEPATmode is set when we are typing a type in a pattern */ val TYPEPATmode = 0x10000 @@ -162,7 +156,6 @@ trait Typers { self: Analyzer => private def argMode(fun: Tree, mode: Int) = if (treeInfo.isSelfOrSuperConstrCall(fun)) mode | SCCmode - else if (fun.symbol hasFlag JAVA) mode | JAVACALLmode // !!!VARARG-CONVERSION!!! else mode abstract class Typer(context0: Context) { @@ -710,6 +703,23 @@ trait Typers { self: Analyzer => ex }} + /** Utility method: Try op1 on tree. If that gives an error try op2 instead. + */ + def tryBoth(tree: Tree)(op1: (Typer, Tree) => Tree)(op2: (Typer, Tree) => Tree): Tree = + silent(op1(_, tree.duplicate)) match { + case result1: Tree => + result1 + case ex1: TypeError => + silent(op2(_, tree)) match { + case result2: Tree => +// println("snd succeeded: "+result2) + result2 + case ex2: TypeError => + reportTypeError(tree.pos, ex1) + setError(tree) + } + } + /** Perform the following adaptations of expression, pattern or type `tree' wrt to * given mode `mode' and given prototype `pt': * (-1) For expressions with annotated types, let AnnotationCheckers decide what to do @@ -907,20 +917,7 @@ trait Typers { self: Analyzer => assert((mode & HKmode) == 0) //@M instantiate(tree, mode, pt) } else if (tree.tpe <:< pt) { - def isStructuralType(tpe: Type): Boolean = tpe match { - case RefinedType(ps, decls) => - decls.toList exists (x => x.isTerm && x.allOverriddenSymbols.isEmpty) - case _ => - false - } - if (isStructuralType(pt) && tree.tpe.typeSymbol == ArrayClass && !settings.newArrays.value) { - // all Arrays used as structural refinement typed values must be boxed - // this does not solve the case where the type to be adapted to comes - // from a type variable that was bound by a strctural but is instantiated - typed(Apply(Select(gen.mkAttributedRef(ScalaRunTimeModule), nme.forceBoxedArray), List(tree))) - } - else - tree + tree } else { if ((mode & PATTERNmode) != 0) { if ((tree.symbol ne null) && tree.symbol.isModule) @@ -1883,33 +1880,8 @@ trait Typers { self: Analyzer => val prefix = List.map2(args take nonVarCount, adaptedFormals take nonVarCount) ((arg, formal) => typedArg(arg, mode, 0, formal)) - - // if array is passed into java vararg and formal's element is not an array, - // convert it to vararg by adding : _* - // this is a gross hack to enable vararg transition; remove it as soon as possible. - // !!!VARARG-CONVERSION!!! - def hasArrayElement(tpe: Type) = - tpe.typeArgs.length == 1 && tpe.typeArgs.head.typeSymbol == ArrayClass - var args0 = args - if ((mode & JAVACALLmode) != 0 && - (args.length == originalFormals.length) && - !hasArrayElement(adaptedFormals(nonVarCount)) && - !settings.XnoVarargsConversion.value) { - val lastarg = typedArg(args(nonVarCount), mode, REGPATmode, WildcardType) - if ((lastarg.tpe.typeSymbol == ArrayClass || lastarg.tpe.typeSymbol == NullClass) && - !treeInfo.isWildcardStarArg(lastarg)) { - if (lastarg.tpe.typeSymbol == ArrayClass) - unit.warning( - lastarg.pos, - "I'm seeing an array passed into a Java vararg.\n"+ - "I assume that the elements of this array should be passed as individual arguments to the vararg.\n"+ - "Therefore I follow the array with a `: _*', to mark it as a vararg argument.\n"+ - "If that's not what you want, compile this file with option -Xno-varargs-conversion.") - args0 = args.init ::: List(gen.wildcardStar(args.last)) - } - } val suffix = - List.map2(args0 drop nonVarCount, adaptedFormals drop nonVarCount) ((arg, formal) => + List.map2(args drop nonVarCount, adaptedFormals drop nonVarCount) ((arg, formal) => typedArg(arg, mode, REGPATmode, formal)) prefix ::: suffix } else { @@ -3600,8 +3572,13 @@ trait Typers { self: Analyzer => case Typed(expr, tpt) => if (treeInfo.isWildcardStarArg(tree)) { - val expr1 = typed(expr, mode & stickyModes, seqType(pt)) - expr1.tpe.baseType(SeqClass) match { + val expr0 = typed(expr, mode & stickyModes, WildcardType) + val (expr1, baseClass) = + if (expr0.tpe.typeSymbol == ArrayClass) + (adapt(expr0, mode & stickyModes, arrayType(pt)), ArrayClass) + else + (adapt(expr0, mode & stickyModes, seqType(pt)), SeqClass) + expr1.tpe.baseType(baseClass) match { case TypeRef(_, _, List(elemtp)) => treeCopy.Typed(tree, expr1, tpt setType elemtp) setType elemtp case _ => @@ -3659,11 +3636,18 @@ trait Typers { self: Analyzer => case Apply(fun, args) => typedApply(fun, args) match { case Apply(Select(New(tpt), name), args) - if (settings.newArrays.value && tpt.tpe.typeSymbol == ArrayClass && args.length == 1 && erasure.isTopLevelGenericArray(tpt.tpe)) => + if (tpt.tpe != null && + tpt.tpe.typeSymbol == ArrayClass && + args.length == 1 && + erasure.GenericArray.unapply(tpt.tpe).isDefined) => // !!! todo simplify by using extractor // convert new Array[T](len) to evidence[ClassManifest[T]].newArray(len) + // convert new Array^N[T](len) for N > 1 to evidence[ClassManifest[T]].newArrayN(len) + val Some((level, manifType)) = erasure.GenericArray.unapply(tpt.tpe) + if (level > MaxArrayDims) + error(tree.pos, "cannot create a generic multi-dimensional array of more than "+MaxArrayDims+" dimensions") val newArrayApp = atPos(tree.pos) { - val manif = getManifestTree(tree.pos, tpt.tpe.typeArgs.head, false) - Apply(Select(manif, nme.newArray), args) + val manif = getManifestTree(tree.pos, manifType, false) + Apply(Select(manif, if (level == 1) "newArray" else "newArray"+level), args) } typed(newArrayApp, mode, pt) case tree1 => diff --git a/src/compiler/scala/tools/nsc/util/JavaCharArrayReader.scala b/src/compiler/scala/tools/nsc/util/JavaCharArrayReader.scala index 6876d74b81..37c8488804 100755 --- a/src/compiler/scala/tools/nsc/util/JavaCharArrayReader.scala +++ b/src/compiler/scala/tools/nsc/util/JavaCharArrayReader.scala @@ -62,7 +62,7 @@ class JavaCharArrayReader(buf: RandomAccessSeq[Char], start: Int, /* startline: def next: Char = { //cline = nextline //ccol = nextcol - val buf = this.buf.asInstanceOf[runtime.BoxedCharArray].value + val buf = this.buf.asInstanceOf[collection.mutable.WrappedArray[Char]].array if(!hasNext) { ch = SU return SU // there is an endless stream of SU's at the end diff --git a/src/compiler/scala/tools/nsc/util/SourceFile.scala b/src/compiler/scala/tools/nsc/util/SourceFile.scala index 2d8d963ca3..d11f9a3db1 100644 --- a/src/compiler/scala/tools/nsc/util/SourceFile.scala +++ b/src/compiler/scala/tools/nsc/util/SourceFile.scala @@ -176,7 +176,7 @@ extends BatchSourceFile(name, contents) this( name, components.toList, - Array.concat(components.toList.map(comp => + Array.concat(components.map(comp => CompoundSourceFile.stripSU(comp.content).toArray):_*)) } diff --git a/src/library/scala/Array.scala b/src/library/scala/Array.scala index bb711be10f..afd6f7bb9b 100644 --- a/src/library/scala/Array.scala +++ b/src/library/scala/Array.scala @@ -13,39 +13,52 @@ package scala import scala.collection.generic._ import scala.collection.Traversable -import scala.collection.mutable.{Vector, ArrayBuilder} +import scala.collection.mutable.{Vector, ArrayBuilder, GenericArray} import compat.Platform.arraycopy import scala.reflect.ClassManifest +import scala.runtime.ScalaRunTime.{array_apply, array_update} + +/** A class containing a fall back builder for arrays where the element type + * does not have a class manifest. In that case a generic array is built. + */ +class FallbackArrayBuilding { + + /** A builder factory that generates a generic array. + * Called instead of Array.newBuilder if the element type of an array + * does not have a class manifest. Note that fallbackBuilder fcatory + * needs an implicit parameter (otherwise it would not be dominated in implicit search + * by Array.builderFactory). We make sure that that implicit search is always + * succesfull. + */ + implicit def fallbackBuilderFactory[T](implicit m: DummyImplicit): BuilderFactory[T, GenericArray[T], Array[_]] = + new BuilderFactory[T, GenericArray[T], Array[_]] { + def apply(from: Array[_]) = GenericArray.newBuilder[T] + } +} /** This object contains utility methods operating on arrays. * * @author Martin Odersky * @version 1.0 */ -object Array { +object Array extends FallbackArrayBuilding { import runtime.BoxedArray; import scala.runtime.ScalaRunTime.boxArray; - implicit def builderFactory[A]/* !!!(implicit m: ClassManifest[A])*/: BuilderFactory[A, Array[A], Array[_]] = - new BuilderFactory[A, Array[A], Array[_]] { def apply(from: Array[_]) = newBuilder[A](null) } - - def newBuilder[A](implicit m: ClassManifest[A]): Builder[A, Array[A]] = - new ArrayBuilder[A](m).asInstanceOf[Builder[A, Array[A]]] // the cast is safe, because the erasure of Array[A] is BoxedArray[A] + implicit def builderFactory[T](implicit m: ClassManifest[T]): BuilderFactory[T, Array[T], Array[_]] = + new BuilderFactory[T, Array[T], Array[_]] { def apply(from: Array[_]) = ArrayBuilder.make[T]()(m) } - private def slowcopy( - src : AnyRef, - srcPos : Int, - dest : AnyRef, - destPos : Int, - length : Int) { + def newBuilder[T](implicit m: ClassManifest[T]): ArrayBuilder[T] = ArrayBuilder.make[T]()(m) - val srcArray = boxArray(src).asInstanceOf[BoxedArray[AnyRef]] - val destArray = boxArray(dest).asInstanceOf[BoxedArray[AnyRef]] - - var i = 0; + private def slowcopy(src : AnyRef, + srcPos : Int, + dest : AnyRef, + destPos : Int, + length : Int) { + var i = 0 while (i < length) { - destArray(destPos + i) = srcArray(srcPos + i) + array_update(dest, i, array_apply(src, i)) i += 1 } } @@ -70,102 +83,115 @@ object Array { } /** Returns array of length 0 */ - def empty[A: ClassManifest]: Array[A] = new Array[A](0) + def empty[T: ClassManifest]: Array[T] = new Array[T](0) /** Create an array with given elements. * * @param xs the elements to put in the array * @return the array containing elements xs. */ - def apply[A: ClassManifest](xs: A*): Array[A] = { - val array = new Array[A](xs.length) + def apply[T: ClassManifest](xs: T*): Array[T] = { + val array = new Array[T](xs.length) var i = 0 for (x <- xs.iterator) { array(i) = x; i += 1 } array } - def apply(xs: Boolean*): Array[Boolean] = { - val array = new Array[Boolean](xs.length) - var i = 0 + def apply(x: Boolean, xs: Boolean*): Array[Boolean] = { + val array = new Array[Boolean](xs.length + 1) + array(0) = x + var i = 1 for (x <- xs.iterator) { array(i) = x; i += 1 } array } - def apply(xs: Byte*): Array[Byte] = { - val array = new Array[Byte](xs.length) - var i = 0 + def apply(x: Byte, xs: Byte*): Array[Byte] = { + val array = new Array[Byte](xs.length + 1) + array(0) = x + var i = 1 for (x <- xs.iterator) { array(i) = x; i += 1 } array } - def apply(xs: Short*): Array[Short] = { - val array = new Array[Short](xs.length) - var i = 0 + def apply(x: Short, xs: Short*): Array[Short] = { + val array = new Array[Short](xs.length + 1) + array(0) = x + var i = 1 for (x <- xs.iterator) { array(i) = x; i += 1 } array } - def apply(xs: Char*): Array[Char] = { - val array = new Array[Char](xs.length) - var i = 0 + def apply(x: Char, xs: Char*): Array[Char] = { + val array = new Array[Char](xs.length + 1) + array(0) = x + var i = 1 for (x <- xs.iterator) { array(i) = x; i += 1 } array } - def apply(xs: Int*): Array[Int] = { - val array = new Array[Int](xs.length) - var i = 0 + def apply(x: Int, xs: Int*): Array[Int] = { + val array = new Array[Int](xs.length + 1) + array(0) = x + var i = 1 for (x <- xs.iterator) { array(i) = x; i += 1 } array } - def apply(xs: Long*): Array[Long] = { - val array = new Array[Long](xs.length) - var i = 0 + def apply(x: Long, xs: Long*): Array[Long] = { + val array = new Array[Long](xs.length + 1) + array(0) = x + var i = 1 for (x <- xs.iterator) { array(i) = x; i += 1 } array } - def apply(xs: Float*): Array[Float] = { - val array = new Array[Float](xs.length) - var i = 0 + def apply(x: Float, xs: Float*): Array[Float] = { + val array = new Array[Float](xs.length + 1) + array(0) = x + var i = 1 for (x <- xs.iterator) { array(i) = x; i += 1 } array } - def apply(xs: Double*): Array[Double] = { - val array = new Array[Double](xs.length) - var i = 0 + def apply(x: Double, xs: Double*): Array[Double] = { + val array = new Array[Double](xs.length + 1) + array(0) = x + var i = 1 for (x <- xs.iterator) { array(i) = x; i += 1 } array } - def apply(xs: Unit*): Array[Unit] = { - val array = new Array[Unit](xs.length) - var i = 0 + def apply(x: Unit, xs: Unit*): Array[Unit] = { + val array = new Array[Unit](xs.length + 1) + array(0) = x + var i = 1 for (x <- xs.iterator) { array(i) = x; i += 1 } array } /** Create array with given dimensions */ - def ofDim[A: ClassManifest](n1: Int): Array[A] = - new Array[A](n1) - def ofDim[A: ClassManifest](n1: Int, n2: Int): Array[Array[A]] = - tabulate(n1)(_ => ofDim[A](n2)) - def ofDim[A: ClassManifest](n1: Int, n2: Int, n3: Int): Array[Array[Array[A]]] = - tabulate(n1)(_ => ofDim[A](n2, n3)) - def ofDim[A: ClassManifest](n1: Int, n2: Int, n3: Int, n4: Int): Array[Array[Array[Array[A]]]] = - tabulate(n1)(_ => ofDim[A](n2, n3, n4)) - def ofDim[A: ClassManifest](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int): Array[Array[Array[Array[Array[A]]]]] = - tabulate(n1)(_ => ofDim[A](n2, n3, n4, n5)) + def ofDim[T: ClassManifest](n1: Int): Array[T] = + new Array[T](n1) + def ofDim[T: ClassManifest](n1: Int, n2: Int): Array[Array[T]] = { + val arr: Array[Array[T]] = (new Array[Array[T]](n1): Array[Array[T]]) + for (i <- 0 until n1) arr(i) = new Array[T](n2) + arr + // tabulate(n1)(_ => ofDim[T](n2)) + } + def ofDim[T: ClassManifest](n1: Int, n2: Int, n3: Int): Array[Array[Array[T]]] = + tabulate(n1)(_ => ofDim[T](n2, n3)) + def ofDim[T: ClassManifest](n1: Int, n2: Int, n3: Int, n4: Int): Array[Array[Array[Array[T]]]] = + tabulate(n1)(_ => ofDim[T](n2, n3, n4)) + def ofDim[T: ClassManifest](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int): Array[Array[Array[Array[Array[T]]]]] = + tabulate(n1)(_ => ofDim[T](n2, n3, n4, n5)) /** Concatenate all argument sequences into a single array. * * @param xs the given argument sequences * @return the array created from the concatenated arguments */ - def concat[A: ClassManifest](xss: Traversable[A]*): Array[A] = { - val b = newBuilder[A] + def concat[T: ClassManifest](xss: Array[T]*): Array[T] = { + val b = newBuilder[T] b.sizeHint(xss.map(_.size).sum) for (xs <- xss) b ++= xs b.result @@ -177,8 +203,8 @@ object Array { * @param n the number of elements returned * @param elem the element computation */ - def fill[A: ClassManifest](n: Int)(elem: => A): Array[A] = { - val b = newBuilder[A] + def fill[T: ClassManifest](n: Int)(elem: => T): Array[T] = { + val b = newBuilder[T] var i = 0 while (i < n) { b += elem @@ -194,7 +220,7 @@ object Array { * @param n2 the number of elements in the 2nd dimension * @param elem the element computation */ - def fill[A: ClassManifest](n1: Int, n2: Int)(elem: => A): Array[Array[A]] = + def fill[T: ClassManifest](n1: Int, n2: Int)(elem: => T): Array[Array[T]] = tabulate(n1)(_ => fill(n2)(elem)) /** A three-dimensional array that contains the results of some element @@ -205,7 +231,7 @@ object Array { * @param n3 the number of elements in the 3nd dimension * @param elem the element computation */ - def fill[A: ClassManifest](n1: Int, n2: Int, n3: Int)(elem: => A): Array[Array[Array[A]]] = + def fill[T: ClassManifest](n1: Int, n2: Int, n3: Int)(elem: => T): Array[Array[Array[T]]] = tabulate(n1)(_ => fill(n2, n3)(elem)) /** A four-dimensional array that contains the results of some element @@ -217,7 +243,7 @@ object Array { * @param n4 the number of elements in the 4th dimension * @param elem the element computation */ - def fill[A: ClassManifest](n1: Int, n2: Int, n3: Int, n4: Int)(elem: => A): Array[Array[Array[Array[A]]]] = + def fill[T: ClassManifest](n1: Int, n2: Int, n3: Int, n4: Int)(elem: => T): Array[Array[Array[Array[T]]]] = tabulate(n1)(_ => fill(n2, n3, n4)(elem)) /** A five-dimensional array that contains the results of some element @@ -230,7 +256,7 @@ object Array { * @param n5 the number of elements in the 5th dimension * @param elem the element computation */ - def fill[A: ClassManifest](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int)(elem: => A): Array[Array[Array[Array[Array[A]]]]] = + def fill[T: ClassManifest](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int)(elem: => T): Array[Array[Array[Array[Array[T]]]]] = tabulate(n1)(_ => fill(n2, n3, n4, n5)(elem)) /** An array containing values of a given function over a range of integer @@ -240,8 +266,8 @@ object Array { * @param f The function computing element values * @return A traversable consisting of elements `f(0), ..., f(n -1)` */ - def tabulate[A: ClassManifest](n: Int)(f: Int => A): Array[A] = { - val b = newBuilder[A] + def tabulate[T: ClassManifest](n: Int)(f: Int => T): Array[T] = { + val b = newBuilder[T] var i = 0 while (i < n) { b += f(i) @@ -257,7 +283,7 @@ object Array { * @param n2 the number of elements in the 2nd dimension * @param f The function computing element values */ - def tabulate[A: ClassManifest](n1: Int, n2: Int)(f: (Int, Int) => A): Array[Array[A]] = + def tabulate[T: ClassManifest](n1: Int, n2: Int)(f: (Int, Int) => T): Array[Array[T]] = tabulate(n1)(i1 => tabulate(n2)(f(i1, _))) /** A three-dimensional array containing values of a given function over @@ -268,7 +294,7 @@ object Array { * @param n3 the number of elements in the 3nd dimension * @param f The function computing element values */ - def tabulate[A: ClassManifest](n1: Int, n2: Int, n3: Int)(f: (Int, Int, Int) => A): Array[Array[Array[A]]] = + def tabulate[T: ClassManifest](n1: Int, n2: Int, n3: Int)(f: (Int, Int, Int) => T): Array[Array[Array[T]]] = tabulate(n1)(i1 => tabulate(n2, n3)(f(i1, _, _))) /** A four-dimensional array containing values of a given function over @@ -280,7 +306,7 @@ object Array { * @param n4 the number of elements in the 4th dimension * @param f The function computing element values */ - def tabulate[A: ClassManifest](n1: Int, n2: Int, n3: Int, n4: Int)(f: (Int, Int, Int, Int) => A): Array[Array[Array[Array[A]]]] = + def tabulate[T: ClassManifest](n1: Int, n2: Int, n3: Int, n4: Int)(f: (Int, Int, Int, Int) => T): Array[Array[Array[Array[T]]]] = tabulate(n1)(i1 => tabulate(n2, n3, n4)(f(i1, _, _, _))) /** A five-dimensional array containing values of a given function over @@ -293,7 +319,7 @@ object Array { * @param n5 the number of elements in the 5th dimension * @param f The function computing element values */ - def tabulate[A: ClassManifest](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int)(f: (Int, Int, Int, Int, Int) => A): Array[Array[Array[Array[Array[A]]]]] = + def tabulate[T: ClassManifest](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int)(f: (Int, Int, Int, Int, Int) => T): Array[Array[Array[Array[Array[T]]]]] = tabulate(n1)(i1 => tabulate(n2, n3, n4, n5)(f(i1, _, _, _, _))) /** An array containing a sequence of increasing integers in a range. @@ -330,8 +356,8 @@ object Array { * @param f the function that's repeatedly applied * @return the array returning `len` values in the sequence `start, f(start), f(f(start)), ...` */ - def iterate[A: ClassManifest](start: A, len: Int)(f: A => A): Array[A] = { - val b = newBuilder[A] + def iterate[T: ClassManifest](start: T, len: Int)(f: T => T): Array[T] = { + val b = newBuilder[T] var acc = start var i = 0 while (i < len) { @@ -347,7 +373,10 @@ object Array { * @param x the selector value * @return sequence wrapped in an option, if this is a Sequence, otherwise none */ - def unapplySeq[A](x: Array[A]): Some[Array[A]] = Some(x) + def unapplySeq[T](x: Array[T]): Option[Vector[T]] = + if (x == null) None else Some(x.toVector) + // !!! the null check should to be necessary, but without it 2241 fails. Seems to be a bug + // in pattern matcher. /** Create an array containing several copies of an element. * @@ -356,8 +385,8 @@ object Array { * @return an array composed of n elements all equal to elem */ @deprecated("use `Array.fill' instead") - def make[A: ClassManifest](n: Int, elem: A): Array[A] = { - val a = new Array[A](n) + def make[T: ClassManifest](n: Int, elem: T): Array[T] = { + val a = new Array[T](n) var i = 0 while (i < n) { a(i) = elem @@ -370,8 +399,8 @@ object Array { * over given range [0..n) */ @deprecated("use `Array.tabulate' instead") - def fromFunction[A: ClassManifest](f: Int => A)(n: Int): Array[A] = { - val a = new Array[A](n) + def fromFunction[T: ClassManifest](f: Int => T)(n: Int): Array[T] = { + val a = new Array[T](n) var i = 0 while (i < n) { a(i) = f(i) @@ -384,28 +413,28 @@ object Array { * over given range [0..n1, 0..n2) */ @deprecated("use `Array.tabulate' instead") - def fromFunction[A: ClassManifest](f: (Int, Int) => A)(n1: Int, n2: Int): Array[Array[A]] = + def fromFunction[T: ClassManifest](f: (Int, Int) => T)(n1: Int, n2: Int): Array[Array[T]] = fromFunction(i => fromFunction(f(i, _))(n2))(n1) /** Create an array containing the values of a given function f * over given range [0..n1, 0..n2, 0..n3) */ @deprecated("use `Array.tabulate' instead") - def fromFunction[A: ClassManifest](f: (Int, Int, Int) => A)(n1: Int, n2: Int, n3: Int): Array[Array[Array[A]]] = + def fromFunction[T: ClassManifest](f: (Int, Int, Int) => T)(n1: Int, n2: Int, n3: Int): Array[Array[Array[T]]] = fromFunction(i => fromFunction(f(i, _, _))(n2, n3))(n1) /** Create an array containing the values of a given function f * over given range [0..n1, 0..n2, 0..n3, 0..n4) */ @deprecated("use `Array.tabulate' instead") - def fromFunction[A: ClassManifest](f: (Int, Int, Int, Int) => A)(n1: Int, n2: Int, n3: Int, n4: Int): Array[Array[Array[Array[A]]]] = + def fromFunction[T: ClassManifest](f: (Int, Int, Int, Int) => T)(n1: Int, n2: Int, n3: Int, n4: Int): Array[Array[Array[Array[T]]]] = fromFunction(i => fromFunction(f(i, _, _, _))(n2, n3, n4))(n1) /** Create an array containing the values of a given function f * over given range [0..n1, 0..n2, 0..n3, 0..n4, 0..n5) */ @deprecated("use `Array.tabulate' instead") - def fromFunction[A: ClassManifest](f: (Int, Int, Int, Int, Int) => A)(n1: Int, n2: Int, n3: Int, n4: Int, n5: Int): Array[Array[Array[Array[Array[A]]]]] = + def fromFunction[T: ClassManifest](f: (Int, Int, Int, Int, Int) => T)(n1: Int, n2: Int, n3: Int, n4: Int, n5: Int): Array[Array[Array[Array[Array[T]]]]] = fromFunction(i => fromFunction(f(i, _, _, _, _))(n2, n3, n4, n5))(n1) } @@ -415,11 +444,7 @@ object Array { * @author Martin Odersky * @version 1.0 */ -final class Array[A](_length: Int) extends Vector[A] - with TraversableClass[A, Array] - with VectorTemplate[A, Array[A]] { - - override def companion: Companion[Array] = throw new Error() +final class Array[T](_length: Int) { /** Multidimensional array creation */ @deprecated("use `Array.ofDim' instead") @@ -494,7 +519,7 @@ final class Array[A](_length: Int) extends Vector[A] * @throws ArrayIndexOutOfBoundsException if i < 0 or * length <= i */ - def apply(i: Int): A = throw new Error() + def apply(i: Int): T = throw new Error() /**

* Update the element at given index. @@ -513,74 +538,5 @@ final class Array[A](_length: Int) extends Vector[A] * @throws ArrayIndexOutOfBoundsException if i < 0 or * length <= i */ - override def update(i: Int, x: A) { throw new Error() } - - /** Creates a possible nested vector which consists of all the elements - * of this array. If the elements are arrays themselves, the `deep' transformation - * is applied recursively to them. The stringPrefix of the vector is - * "Array", hence the vector prints like an array with all its - * elements shown, and the same recursively for any subarrays. - * - * Example: Array(Array(1, 2), Array(3, 4)).deep.toString - * prints: Array(Array(1, 2), Array(3, 4)) - */ - def deep: Vector[Any] = throw new Error() - - /** - * @return a deep string representation of this array. - */ - @deprecated("use deep.toString instead") - def deepToString(): String = throw new Error() - - /**

- * Returns a string representation of this array object. The resulting string - * begins with the string start and is finished by the string - * end. Inside, the string representations of elements (w.r.t. - * the method deepToString()) are separated by the string - * sep. For example: - *

- *

- * Array(Array(1, 2), Array(3)).deepMkString("[", "; ", "]") = "[[1; 2]; [3]]" - *

- * - * @param start starting string. - * @param sep separator string. - * @param end ending string. - * @return a string representation of this array object. - */ - @deprecated("use deep.mkString instead") - def deepMkString(start: String, sep: String, end: String): String = - throw new Error() - - /** Returns a string representation of this array object. The string - * representations of elements (w.r.t. the method deepToString()) - * are separated by the string sep. - * - * @param sep separator string. - * @return a string representation of this array object. - */ - @deprecated("use deep.mkString instead") - def deepMkString(sep: String): String = throw new Error() - - /**

- * Returns true if the two specified arrays are - * deeply equal to one another. - *

- *

- * Two array references are considered deeply equal if both are null, - * or if they refer to arrays that contain the same number of elements - * and all corresponding pairs of elements in the two arrays are deeply - * equal. - *

- *

- * See also method deepEquals in the Java class - * java.utils.Arrays - *

- * - * @param that the second - * @return true iff both arrays are deeply equal. - */ - @deprecated("use array1.deep.equals(array2.deep) instead") - def deepEquals(that: Any): Boolean = throw new Error() + def update(i: Int, x: T) { throw new Error() } } diff --git a/src/library/scala/LowPriorityImplicits.scala b/src/library/scala/LowPriorityImplicits.scala index ea12c07d63..58796b4ddc 100644 --- a/src/library/scala/LowPriorityImplicits.scala +++ b/src/library/scala/LowPriorityImplicits.scala @@ -20,20 +20,10 @@ import collection.immutable.WrappedString */ class LowPriorityImplicits { - implicit def genericWapArray[T](xs: Array[T]): WrappedArray[T] = (xs: AnyRef) match { // !!! drop the AnyRef and get unreachable code errors! - case x: Array[AnyRef] => wrapArray[AnyRef](x).asInstanceOf[WrappedArray[T]] - case x: Array[Int] => wrapArray(x).asInstanceOf[WrappedArray[T]] - case x: Array[Double] => wrapArray(x).asInstanceOf[WrappedArray[T]] - case x: Array[Long] => wrapArray(x).asInstanceOf[WrappedArray[T]] - case x: Array[Float] => wrapArray(x).asInstanceOf[WrappedArray[T]] - case x: Array[Char] => wrapArray(x).asInstanceOf[WrappedArray[T]] - case x: Array[Byte] => wrapArray(x).asInstanceOf[WrappedArray[T]] - case x: Array[Short] => wrapArray(x).asInstanceOf[WrappedArray[T]] - case x: Array[Boolean] => wrapArray(x).asInstanceOf[WrappedArray[T]] - case x: Array[Unit] => wrapArray(x).asInstanceOf[WrappedArray[T]] - } - - implicit def wrapArray[T <: AnyRef](xs: Array[T]): WrappedArray[T] = new WrappedArray.ofRef[T](xs.asInstanceOf[Array[AnyRef]]) + implicit def genericWrapArray[T](xs: Array[T]): WrappedArray[T] = + WrappedArray.make(xs) + + implicit def wrapArray[T <: AnyRef](xs: Array[T]): WrappedArray[T] = new WrappedArray.ofRef[T](xs) implicit def wrapArray(xs: Array[Int]): WrappedArray[Int] = new WrappedArray.ofInt(xs) implicit def wrapArray(xs: Array[Double]): WrappedArray[Double] = new WrappedArray.ofDouble(xs) implicit def wrapArray(xs: Array[Long]): WrappedArray[Long] = new WrappedArray.ofLong(xs) diff --git a/src/library/scala/Predef.scala b/src/library/scala/Predef.scala index 1412fbc924..3ab86869d1 100644 --- a/src/library/scala/Predef.scala +++ b/src/library/scala/Predef.scala @@ -12,7 +12,7 @@ package scala import collection.immutable.StringOps -import collection.mutable.{StringBuilder, ArrayOps} +import collection.mutable.ArrayOps import collection.generic.BuilderFactory /** The Predef object provides definitions that are @@ -67,7 +67,7 @@ object Predef extends LowPriorityImplicits { private val P = scala.`package` // to force scala package object to be seen. private val L = scala.collection.immutable.List // to force Nil, :: to be seen. - private val S = StringBuilder // to force StringBuilder to be seen. + private val S = scala.collection.mutable.StringBuilder // to force StringBuilder to be seen. val $scope = scala.xml.TopScope @@ -81,7 +81,7 @@ object Predef extends LowPriorityImplicits { type Manifest[T] = scala.reflect.Manifest[T] type ClassManifest[T] = scala.reflect.ClassManifest[T] - def evidence[T](implicit e: T) = e + def implicitly[T](implicit e: T) = e def manifest[T](implicit m: Manifest[T]) = m def classManifest[T](implicit m: ClassManifest[T]) = m @@ -89,6 +89,8 @@ object Predef extends LowPriorityImplicits { // @see `conforms` for the implicit version implicit def identity[A](x: A): A = x + def currentThread = java.lang.Thread.currentThread() + // errors and asserts ------------------------------------------------- def error(message: String): Nothing = throw new RuntimeException(message) @@ -214,7 +216,7 @@ object Predef extends LowPriorityImplicits { implicit def unaugmentString(x: StringOps): String = x.repr implicit def stringBuilderFactory: BuilderFactory[Char, String, String] = - new BuilderFactory[Char, String, String] { def apply(from: String) = new StringBuilder } + new BuilderFactory[Char, String, String] { def apply(from: String) = new scala.collection.mutable.StringBuilder } implicit def any2stringadd(x: Any) = new runtime.StringAdd(x) @@ -229,9 +231,10 @@ object Predef extends LowPriorityImplicits { case x: Array[Short] => arrayOps(x).asInstanceOf[ArrayOps[T]] case x: Array[Boolean] => arrayOps(x).asInstanceOf[ArrayOps[T]] case x: Array[Unit] => arrayOps(x).asInstanceOf[ArrayOps[T]] + case null => null } - implicit def arrayOps[T <: AnyRef](xs: Array[T]): ArrayOps[T] = new ArrayOps.ofRef[T](xs.asInstanceOf[Array[AnyRef]]) + implicit def arrayOps[T <: AnyRef](xs: Array[T]): ArrayOps[T] = new ArrayOps.ofRef[T](xs) implicit def arrayOps(xs: Array[Int]): ArrayOps[Int] = new ArrayOps.ofInt(xs) implicit def arrayOps(xs: Array[Double]): ArrayOps[Double] = new ArrayOps.ofDouble(xs) implicit def arrayOps(xs: Array[Long]): ArrayOps[Long] = new ArrayOps.ofLong(xs) @@ -294,6 +297,13 @@ object Predef extends LowPriorityImplicits { override def toString: String = xs.mkString("") } + implicit def arrayToCharSequence(xs: Array[Char]): CharSequence = new CharSequence { + def length: Int = xs.length + def charAt(index: Int): Char = xs(index) + def subSequence(start: Int, end: Int): CharSequence = arrayToCharSequence(xs.slice(start, end)) + override def toString: String = xs.mkString("") + } + // used, for example, in the encoding of generalized constraints // we need a new type constructor `<:<` and evidence `conforms`, as // reusing `Function2` and `identity` leads to ambiguities (any2stringadd is inferred) @@ -302,5 +312,16 @@ object Predef extends LowPriorityImplicits { sealed abstract class <:<[-From, +To] //extends (From => To) implicit def conforms[A]: A <:< A = new (A <:< A) {def convert(x: A) = x} - def currentThread = java.lang.Thread.currentThread() + /** A type for which there is aways an implicit value. + * @see fallbackBuilderFactory in Array.scala + */ + class DummyImplicit + + object DummyImplicit { + + /** An implicit value yielding a DummyImplicit. + * @see fallbackBuilderFactory in Array.scala + */ + implicit def dummyImplicit: DummyImplicit = new DummyImplicit + } } diff --git a/src/library/scala/collection/immutable/PagedSeq.scala b/src/library/scala/collection/immutable/PagedSeq.scala index b8888c3aef..be4f7a6e9d 100644 --- a/src/library/scala/collection/immutable/PagedSeq.scala +++ b/src/library/scala/collection/immutable/PagedSeq.scala @@ -21,7 +21,7 @@ object PagedSeq { final val UndeterminedEnd = Math.MAX_INT /** Constructs a character sequence from a character iterator */ - def fromIterator[T](source: Iterator[T]): PagedSeq[T] = + def fromIterator[T: ClassManifest](source: Iterator[T]): PagedSeq[T] = new PagedSeq[T]((data: Array[T], start: Int, len: Int) => { var i = 0 while (i < len && source.hasNext) { @@ -32,7 +32,7 @@ object PagedSeq { }) /** Constructs a character sequence from a character iterable */ - def fromIterable[T](source: Iterable[T]): PagedSeq[T] = + def fromIterable[T: ClassManifest](source: Iterable[T]): PagedSeq[T] = fromIterator(source.iterator) /** Constructs a character sequence from a string iterator */ @@ -107,7 +107,7 @@ import PagedSeq._ * * @author Martin Odersky */ -class PagedSeq[T] protected( +class PagedSeq[T: ClassManifest] protected( more: (Array[T], Int, Int) => Int, first1: Page[T], start: Int, @@ -191,7 +191,7 @@ extends collection.Vector[T] /** Page containing up to PageSize characters of the input sequence. */ -private class Page[T](val num: Int) { +private class Page[T: ClassManifest](val num: Int) { private final val PageSize = 4096 diff --git a/src/library/scala/collection/immutable/StringLike.scala b/src/library/scala/collection/immutable/StringLike.scala index 5813c86607..cad2ae2700 100644 --- a/src/library/scala/collection/immutable/StringLike.scala +++ b/src/library/scala/collection/immutable/StringLike.scala @@ -228,7 +228,7 @@ self => * @throws java.lang.IllegalArgumentException */ def format(args : Any*) : String = - java.lang.String.format(toString, args.asInstanceOf[Seq[AnyRef]].toArray: _*) + java.lang.String.format(toString, args.asInstanceOf[Seq[AnyRef]]: _*) /**

* Like format(args*) but takes an initial Locale parameter @@ -245,6 +245,6 @@ self => * @throws java.lang.IllegalArgumentException */ def format(l: java.util.Locale, args: Any*): String = - java.lang.String.format(l, toString, args.asInstanceOf[Seq[AnyRef]].toArray: _*) + java.lang.String.format(l, toString, args.asInstanceOf[Seq[AnyRef]]: _*) } diff --git a/src/library/scala/collection/mutable/ArrayBuffer.scala b/src/library/scala/collection/mutable/ArrayBuffer.scala index 55a4870748..d47a7cec9e 100644 --- a/src/library/scala/collection/mutable/ArrayBuffer.scala +++ b/src/library/scala/collection/mutable/ArrayBuffer.scala @@ -40,9 +40,11 @@ class ArrayBuffer[A](override protected val initialSize: Int) def clear() { reduceToSize(0) } override def sizeHint(len: Int) { - val newarray = new Array[AnyRef](len min 1) - Array.copy(array, 0, newarray, 0, size0) - array = newarray + if (len > size && len >= 1) { + val newarray = new Array[AnyRef](len min 1) + Array.copy(array, 0, newarray, 0, size0) + array = newarray + } } /** Appends a single element to this buffer and returns diff --git a/src/library/scala/collection/mutable/ArrayBuilder.scala b/src/library/scala/collection/mutable/ArrayBuilder.scala index 10f6b1ba10..bf5c34694b 100755 --- a/src/library/scala/collection/mutable/ArrayBuilder.scala +++ b/src/library/scala/collection/mutable/ArrayBuilder.scala @@ -16,70 +16,21 @@ import scala.reflect.ClassManifest import scala.runtime.BoxedArray /** A builder class for arrays */ -class ArrayBuilder[A](manifest: ClassManifest[A]) extends Builder[A, BoxedArray[A]] { - - private var elems: BoxedArray[A] = _ - private var capacity: Int = 0 - private var size: Int = 0 - - private def mkArray(size: Int): BoxedArray[A] = { - if (false && manifest != null) { // !!! - val newelems = manifest.newArray(size) - if (this.size > 0) Array.copy(elems.value, 0, newelems.value, 0, this.size) - newelems - } else { // !!! - val newelems = new scala.runtime.BoxedAnyArray[A](size) - if (this.size > 0) Array.copy(elems, 0, newelems, 0, this.size) - newelems - } - } - - private def resize(size: Int) { - elems = mkArray(size) - capacity = size - } - - override def sizeHint(size: Int) { - if (capacity < size) resize(size) - } - - private def ensureSize(size: Int) { - if (capacity < size) { - var newsize = if (capacity == 0) 16 else capacity * 2 - while (newsize < size) newsize *= 2 - resize(newsize) - } - } - - def +=(elem: A): this.type = { - ensureSize(size + 1) - elems(size) = elem - size += 1 - this - } - - def clear() { - size = 0 - } - - def result() = { - if (capacity != 0 && capacity == size) elems - else mkArray(size) - } - - // todo: add ++= -} +abstract class ArrayBuilder[T] extends Builder[T, Array[T]] object ArrayBuilder { - class ofRef[T <: AnyRef] extends Builder[T, Array[AnyRef]] { + def make[T: ClassManifest](): ArrayBuilder[T] = + implicitly[ClassManifest[T]].newArrayBuilder() + + class ofRef[T <: AnyRef : ClassManifest] extends ArrayBuilder[T] { - private var elems: Array[AnyRef] = _ + private var elems: Array[T] = _ private var capacity: Int = 0 private var size: Int = 0 - private def mkArray(size: Int): Array[AnyRef] = { - val newelems = new Array[AnyRef](size) + private def mkArray(size: Int): Array[T] = { + val newelems = new Array[T](size) if (this.size > 0) Array.copy(elems, 0, newelems, 0, this.size) newelems } @@ -94,8 +45,9 @@ object ArrayBuilder { } private def ensureSize(size: Int) { + if (capacity == 0) resize(16) if (capacity < size) { - var newsize = if (capacity == 0) 16 else capacity * 2 + var newsize = capacity * 2 while (newsize < size) newsize *= 2 resize(newsize) } @@ -111,7 +63,7 @@ object ArrayBuilder { override def ++=(xs: scala.collection.Traversable[T]): this.type = (xs: AnyRef) match { case xs: WrappedArray.ofRef[_] => ensureSize(this.size + xs.length) - Array.copy(elems, this.size, xs.array, 0, xs.length) + Array.copy(xs.array, 0, elems, this.size, xs.length) size += xs.length this case _ => @@ -128,7 +80,7 @@ object ArrayBuilder { } } - class ofByte extends Builder[Byte, Array[Byte]] { + class ofByte extends ArrayBuilder[Byte] { private var elems: Array[Byte] = _ private var capacity: Int = 0 @@ -150,8 +102,9 @@ object ArrayBuilder { } private def ensureSize(size: Int) { + if (capacity == 0) resize(16) if (capacity < size) { - var newsize = if (capacity == 0) 16 else capacity * 2 + var newsize = capacity * 2 while (newsize < size) newsize *= 2 resize(newsize) } @@ -167,7 +120,7 @@ object ArrayBuilder { override def ++=(xs: scala.collection.Traversable[Byte]): this.type = xs match { case xs: WrappedArray.ofByte => ensureSize(this.size + xs.length) - Array.copy(elems, this.size, xs.array, 0, xs.length) + Array.copy(xs.array, 0, elems, this.size, xs.length) size += xs.length this case _ => @@ -184,7 +137,7 @@ object ArrayBuilder { } } - class ofShort extends Builder[Short, Array[Short]] { + class ofShort extends ArrayBuilder[Short] { private var elems: Array[Short] = _ private var capacity: Int = 0 @@ -206,8 +159,9 @@ object ArrayBuilder { } private def ensureSize(size: Int) { + if (capacity == 0) resize(16) if (capacity < size) { - var newsize = if (capacity == 0) 16 else capacity * 2 + var newsize = capacity * 2 while (newsize < size) newsize *= 2 resize(newsize) } @@ -223,7 +177,7 @@ object ArrayBuilder { override def ++=(xs: scala.collection.Traversable[Short]): this.type = xs match { case xs: WrappedArray.ofShort => ensureSize(this.size + xs.length) - Array.copy(elems, this.size, xs.array, 0, xs.length) + Array.copy(xs.array, 0, elems, this.size, xs.length) size += xs.length this case _ => @@ -240,7 +194,7 @@ object ArrayBuilder { } } - class ofChar extends Builder[Char, Array[Char]] { + class ofChar extends ArrayBuilder[Char] { private var elems: Array[Char] = _ private var capacity: Int = 0 @@ -262,8 +216,9 @@ object ArrayBuilder { } private def ensureSize(size: Int) { + if (capacity == 0) resize(16) if (capacity < size) { - var newsize = if (capacity == 0) 16 else capacity * 2 + var newsize = capacity * 2 while (newsize < size) newsize *= 2 resize(newsize) } @@ -279,7 +234,7 @@ object ArrayBuilder { override def ++=(xs: scala.collection.Traversable[Char]): this.type = xs match { case xs: WrappedArray.ofChar => ensureSize(this.size + xs.length) - Array.copy(elems, this.size, xs.array, 0, xs.length) + Array.copy(xs.array, 0, elems, this.size, xs.length) size += xs.length this case _ => @@ -296,7 +251,7 @@ object ArrayBuilder { } } - class ofInt extends Builder[Int, Array[Int]] { + class ofInt extends ArrayBuilder[Int] { private var elems: Array[Int] = _ private var capacity: Int = 0 @@ -318,8 +273,9 @@ object ArrayBuilder { } private def ensureSize(size: Int) { + if (capacity == 0) resize(16) if (capacity < size) { - var newsize = if (capacity == 0) 16 else capacity * 2 + var newsize = capacity * 2 while (newsize < size) newsize *= 2 resize(newsize) } @@ -335,7 +291,7 @@ object ArrayBuilder { override def ++=(xs: scala.collection.Traversable[Int]): this.type = xs match { case xs: WrappedArray.ofInt => ensureSize(this.size + xs.length) - Array.copy(elems, this.size, xs.array, 0, xs.length) + Array.copy(xs.array, 0, elems, this.size, xs.length) size += xs.length this case _ => @@ -352,7 +308,7 @@ object ArrayBuilder { } } - class ofLong extends Builder[Long, Array[Long]] { + class ofLong extends ArrayBuilder[Long] { private var elems: Array[Long] = _ private var capacity: Int = 0 @@ -374,8 +330,9 @@ object ArrayBuilder { } private def ensureSize(size: Int) { + if (capacity == 0) resize(16) if (capacity < size) { - var newsize = if (capacity == 0) 16 else capacity * 2 + var newsize = capacity * 2 while (newsize < size) newsize *= 2 resize(newsize) } @@ -391,7 +348,7 @@ object ArrayBuilder { override def ++=(xs: scala.collection.Traversable[Long]): this.type = xs match { case xs: WrappedArray.ofLong => ensureSize(this.size + xs.length) - Array.copy(elems, this.size, xs.array, 0, xs.length) + Array.copy(xs.array, 0, elems, this.size, xs.length) size += xs.length this case _ => @@ -408,7 +365,7 @@ object ArrayBuilder { } } - class ofFloat extends Builder[Float, Array[Float]] { + class ofFloat extends ArrayBuilder[Float] { private var elems: Array[Float] = _ private var capacity: Int = 0 @@ -430,8 +387,9 @@ object ArrayBuilder { } private def ensureSize(size: Int) { + if (capacity == 0) resize(16) if (capacity < size) { - var newsize = if (capacity == 0) 16 else capacity * 2 + var newsize = capacity * 2 while (newsize < size) newsize *= 2 resize(newsize) } @@ -447,7 +405,7 @@ object ArrayBuilder { override def ++=(xs: scala.collection.Traversable[Float]): this.type = xs match { case xs: WrappedArray.ofFloat => ensureSize(this.size + xs.length) - Array.copy(elems, this.size, xs.array, 0, xs.length) + Array.copy(xs.array, 0, elems, this.size, xs.length) size += xs.length this case _ => @@ -464,7 +422,7 @@ object ArrayBuilder { } } - class ofDouble extends Builder[Double, Array[Double]] { + class ofDouble extends ArrayBuilder[Double] { private var elems: Array[Double] = _ private var capacity: Int = 0 @@ -486,8 +444,9 @@ object ArrayBuilder { } private def ensureSize(size: Int) { + if (capacity == 0) resize(16) if (capacity < size) { - var newsize = if (capacity == 0) 16 else capacity * 2 + var newsize = capacity * 2 while (newsize < size) newsize *= 2 resize(newsize) } @@ -503,7 +462,7 @@ object ArrayBuilder { override def ++=(xs: scala.collection.Traversable[Double]): this.type = xs match { case xs: WrappedArray.ofDouble => ensureSize(this.size + xs.length) - Array.copy(elems, this.size, xs.array, 0, xs.length) + Array.copy(xs.array, 0, elems, this.size, xs.length) size += xs.length this case _ => @@ -520,7 +479,7 @@ object ArrayBuilder { } } - class ofBoolean extends Builder[Boolean, Array[Boolean]] { + class ofBoolean extends ArrayBuilder[Boolean] { private var elems: Array[Boolean] = _ private var capacity: Int = 0 @@ -542,8 +501,9 @@ object ArrayBuilder { } private def ensureSize(size: Int) { + if (capacity == 0) resize(16) if (capacity < size) { - var newsize = if (capacity == 0) 16 else capacity * 2 + var newsize = capacity * 2 while (newsize < size) newsize *= 2 resize(newsize) } @@ -559,7 +519,7 @@ object ArrayBuilder { override def ++=(xs: scala.collection.Traversable[Boolean]): this.type = xs match { case xs: WrappedArray.ofBoolean => ensureSize(this.size + xs.length) - Array.copy(elems, this.size, xs.array, 0, xs.length) + Array.copy(xs.array, 0, elems, this.size, xs.length) size += xs.length this case _ => @@ -576,7 +536,7 @@ object ArrayBuilder { } } - class ofUnit extends Builder[Unit, Array[Unit]] { + class ofUnit extends ArrayBuilder[Unit] { private var elems: Array[Unit] = _ private var capacity: Int = 0 @@ -598,8 +558,9 @@ object ArrayBuilder { } private def ensureSize(size: Int) { + if (capacity == 0) resize(16) if (capacity < size) { - var newsize = if (capacity == 0) 16 else capacity * 2 + var newsize = capacity * 2 while (newsize < size) newsize *= 2 resize(newsize) } @@ -615,7 +576,7 @@ object ArrayBuilder { override def ++=(xs: scala.collection.Traversable[Unit]): this.type = xs match { case xs: WrappedArray.ofUnit => ensureSize(this.size + xs.length) - Array.copy(elems, this.size, xs.array, 0, xs.length) + Array.copy(xs.array, 0, elems, this.size, xs.length) size += xs.length this case _ => diff --git a/src/library/scala/collection/mutable/ArrayLike.scala b/src/library/scala/collection/mutable/ArrayLike.scala new file mode 100644 index 0000000000..939c8b3ccb --- /dev/null +++ b/src/library/scala/collection/mutable/ArrayLike.scala @@ -0,0 +1,56 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: MutableVectorTemplate.scala 18387 2009-07-24 15:28:37Z odersky $ + + +package scala.collection +package mutable +import generic._ + +/** A subtrait of collection.Vector which represents sequences + * that can be mutated. + */ +trait ArrayLike[A, +Repr] extends VectorLike[A, Repr] { self => + + /** Creates a possible nested vector which consists of all the elements + * of this array. If the elements are arrays themselves, the `deep' transformation + * is applied recursively to them. The stringPrefix of the vector is + * "Array", hence the vector prints like an array with all its + * elements shown, and the same recursively for any subarrays. + * + * Example: Array(Array(1, 2), Array(3, 4)).deep.toString + * prints: Array(Array(1, 2), Array(3, 4)) + */ + def deep: scala.collection.Vector[Any] = new collection.Vector[Any] { + def length = self.length + def apply(idx: Int): Any = self.apply(idx) match { + case x: AnyRef if x.getClass.isArray => WrappedArray.make(x).deep + case x => x + } + override def stringPrefix = "Array" + } + + @deprecated("use deep.toString instead") + final def deepToString() = + deep.toString + + @deprecated("use deep.mkString instead") + final def deepMkString(start: String, sep: String, end: String): String = + deep.mkString(start, sep, end) + + @deprecated("use deep.mkString instead") + final def deepMkString(sep: String): String = + deepMkString("", sep, "") + + @deprecated("use array1.deep.equals(array2.deep) instead") + final def deepEquals(that: Any): Boolean = that match { + case x: AnyRef if x.getClass.isArray => deep.equals(WrappedArray.make(x).deep) + case _ => false + } +} diff --git a/src/library/scala/collection/mutable/ArrayOps.scala b/src/library/scala/collection/mutable/ArrayOps.scala index 6a85d7cd02..b5c0d0e458 100755 --- a/src/library/scala/collection/mutable/ArrayOps.scala +++ b/src/library/scala/collection/mutable/ArrayOps.scala @@ -12,24 +12,61 @@ package scala.collection package mutable -abstract class ArrayOps[T] extends VectorLike[T, AnyRef /*!!!Array[T]!!!*/] { -} +import generic.Builder + +import scala.reflect.ClassManifest + +abstract class ArrayOps[T] extends ArrayLike[T, Array[T]] { + + private def rowBuilder[U]: Builder[U, Array[U]] = + Array.newBuilder( + ClassManifest.fromClass( + repr.getClass.getComponentType.getComponentType.asInstanceOf[Predef.Class[U]])) + /** Flattens a two-dimensional array by concatenating all its rows + * into a single array + */ + def flatten[U](implicit asArray: T => /*<: Array[U]): Array[Array[U]] = { + val bs = asArray(head) map (_ => rowBuilder[U]) + for (xs <- this) { + var i = 0 + for (x <- asArray(xs)) { + bs(i) += x + i += 1 + } + } + val bb: Builder[Array[U], Array[Array[U]]] = Array.newBuilder( + ClassManifest.fromClass( + repr.getClass.getComponentType.asInstanceOf[Predef.Class[Array[U]]])) + for (b <- bs) bb += b.result + bb.result + } +} object ArrayOps { - class ofRef[T <: AnyRef](override val repr: Array[AnyRef]) extends ArrayOps[T] with VectorLike[T, Array[AnyRef]] { + class ofRef[T <: AnyRef](override val repr: Array[T]) extends ArrayOps[T] with ArrayLike[T, Array[T]] { override protected[this] def thisCollection: WrappedArray[T] = new WrappedArray.ofRef[T](repr) - override protected[this] def toCollection(repr: Array[AnyRef]): WrappedArray[T] = new WrappedArray.ofRef[T](repr) - override protected[this] def newBuilder = new ArrayBuilder.ofRef[T] + override protected[this] def toCollection(repr: Array[T]): WrappedArray[T] = new WrappedArray.ofRef[T](repr) + override protected[this] def newBuilder = new ArrayBuilder.ofRef[T]()( + ClassManifest.classType[T](repr.getClass.getComponentType)) def length: Int = repr.length - def apply(index: Int): T = repr(index).asInstanceOf[T] - def update(index: Int, elem: T) { repr(index) = elem.asInstanceOf[AnyRef] } + def apply(index: Int): T = repr(index) + def update(index: Int, elem: T) { repr(index) = elem } } - class ofByte(override val repr: Array[Byte]) extends ArrayOps[Byte] with VectorLike[Byte, Array[Byte]] { + class ofByte(override val repr: Array[Byte]) extends ArrayOps[Byte] with ArrayLike[Byte, Array[Byte]] { override protected[this] def thisCollection: WrappedArray[Byte] = new WrappedArray.ofByte(repr) override protected[this] def toCollection(repr: Array[Byte]): WrappedArray[Byte] = new WrappedArray.ofByte(repr) @@ -40,7 +77,7 @@ object ArrayOps { def update(index: Int, elem: Byte) { repr(index) = elem } } - class ofShort(override val repr: Array[Short]) extends ArrayOps[Short] with VectorLike[Short, Array[Short]] { + class ofShort(override val repr: Array[Short]) extends ArrayOps[Short] with ArrayLike[Short, Array[Short]] { override protected[this] def thisCollection: WrappedArray[Short] = new WrappedArray.ofShort(repr) override protected[this] def toCollection(repr: Array[Short]): WrappedArray[Short] = new WrappedArray.ofShort(repr) @@ -51,7 +88,7 @@ object ArrayOps { def update(index: Int, elem: Short) { repr(index) = elem } } - class ofChar(override val repr: Array[Char]) extends ArrayOps[Char] with VectorLike[Char, Array[Char]] { + class ofChar(override val repr: Array[Char]) extends ArrayOps[Char] with ArrayLike[Char, Array[Char]] { override protected[this] def thisCollection: WrappedArray[Char] = new WrappedArray.ofChar(repr) override protected[this] def toCollection(repr: Array[Char]): WrappedArray[Char] = new WrappedArray.ofChar(repr) @@ -62,7 +99,7 @@ object ArrayOps { def update(index: Int, elem: Char) { repr(index) = elem } } - class ofInt(override val repr: Array[Int]) extends ArrayOps[Int] with VectorLike[Int, Array[Int]] { + class ofInt(override val repr: Array[Int]) extends ArrayOps[Int] with ArrayLike[Int, Array[Int]] { override protected[this] def thisCollection: WrappedArray[Int] = new WrappedArray.ofInt(repr) override protected[this] def toCollection(repr: Array[Int]): WrappedArray[Int] = new WrappedArray.ofInt(repr) @@ -73,7 +110,7 @@ object ArrayOps { def update(index: Int, elem: Int) { repr(index) = elem } } - class ofLong(override val repr: Array[Long]) extends ArrayOps[Long] with VectorLike[Long, Array[Long]] { + class ofLong(override val repr: Array[Long]) extends ArrayOps[Long] with ArrayLike[Long, Array[Long]] { override protected[this] def thisCollection: WrappedArray[Long] = new WrappedArray.ofLong(repr) override protected[this] def toCollection(repr: Array[Long]): WrappedArray[Long] = new WrappedArray.ofLong(repr) @@ -84,7 +121,7 @@ object ArrayOps { def update(index: Int, elem: Long) { repr(index) = elem } } - class ofFloat(override val repr: Array[Float]) extends ArrayOps[Float] with VectorLike[Float, Array[Float]] { + class ofFloat(override val repr: Array[Float]) extends ArrayOps[Float] with ArrayLike[Float, Array[Float]] { override protected[this] def thisCollection: WrappedArray[Float] = new WrappedArray.ofFloat(repr) override protected[this] def toCollection(repr: Array[Float]): WrappedArray[Float] = new WrappedArray.ofFloat(repr) @@ -95,7 +132,7 @@ object ArrayOps { def update(index: Int, elem: Float) { repr(index) = elem } } - class ofDouble(override val repr: Array[Double]) extends ArrayOps[Double] with VectorLike[Double, Array[Double]] { + class ofDouble(override val repr: Array[Double]) extends ArrayOps[Double] with ArrayLike[Double, Array[Double]] { override protected[this] def thisCollection: WrappedArray[Double] = new WrappedArray.ofDouble(repr) override protected[this] def toCollection(repr: Array[Double]): WrappedArray[Double] = new WrappedArray.ofDouble(repr) @@ -106,7 +143,7 @@ object ArrayOps { def update(index: Int, elem: Double) { repr(index) = elem } } - class ofBoolean(override val repr: Array[Boolean]) extends ArrayOps[Boolean] with VectorLike[Boolean, Array[Boolean]] { + class ofBoolean(override val repr: Array[Boolean]) extends ArrayOps[Boolean] with ArrayLike[Boolean, Array[Boolean]] { override protected[this] def thisCollection: WrappedArray[Boolean] = new WrappedArray.ofBoolean(repr) override protected[this] def toCollection(repr: Array[Boolean]): WrappedArray[Boolean] = new WrappedArray.ofBoolean(repr) @@ -117,7 +154,7 @@ object ArrayOps { def update(index: Int, elem: Boolean) { repr(index) = elem } } - class ofUnit(override val repr: Array[Unit]) extends ArrayOps[Unit] with VectorLike[Unit, Array[Unit]] { + class ofUnit(override val repr: Array[Unit]) extends ArrayOps[Unit] with ArrayLike[Unit, Array[Unit]] { override protected[this] def thisCollection: WrappedArray[Unit] = new WrappedArray.ofUnit(repr) override protected[this] def toCollection(repr: Array[Unit]): WrappedArray[Unit] = new WrappedArray.ofUnit(repr) diff --git a/src/library/scala/collection/mutable/StringBuilder.scala b/src/library/scala/collection/mutable/StringBuilder.scala index 6f7ecc8c70..a5eab238e5 100644 --- a/src/library/scala/collection/mutable/StringBuilder.scala +++ b/src/library/scala/collection/mutable/StringBuilder.scala @@ -716,7 +716,7 @@ final class StringBuilder(initCapacity: Int, private val initValue: String) * substring, -1 is returned. * @throws NullPointerException if str is null. */ - def indexOf(str: String): Int = indexOfSeq(str.toArray) + def indexOf(str: String): Int = indexOf(str, 0) /**

* Returns the index within this string of the first occurrence of the @@ -735,7 +735,7 @@ final class StringBuilder(initCapacity: Int, private val initValue: String) * @return the index within this string of the first occurrence * of the specified substring, starting at the specified index. */ - def indexOf(str: String, fromIndex: Int): Int = indexOfSeq(str.toArray, fromIndex) + def indexOf(str: String, fromIndex: Int): Int = indexOfSeq(str.toVector, fromIndex) /**

* Returns the index within this string of the rightmost occurrence @@ -757,7 +757,7 @@ final class StringBuilder(initCapacity: Int, private val initValue: String) * a substring, -1 is returned. * @throws NullPointerException if str is null. */ - def lastIndexOf(str: String): Int = lastIndexOfSeq(str.toArray, count) + def lastIndexOf(str: String): Int = lastIndexOf(str, count) /**

* Returns the index within this string of the last occurrence of the @@ -776,7 +776,7 @@ final class StringBuilder(initCapacity: Int, private val initValue: String) * @return the index within this sequence of the last occurrence * of the specified substring. */ - def lastIndexOf(str: String, fromIndex: Int): Int = lastIndexOfSeq(str.toArray, fromIndex) + def lastIndexOf(str: String, fromIndex: Int): Int = lastIndexOfSeq(str.toVector, fromIndex) /**

* Causes this character sequence to be replaced by the reverse of the diff --git a/src/library/scala/collection/mutable/WrappedArray.scala b/src/library/scala/collection/mutable/WrappedArray.scala index 020843aabc..46b9d3fa4a 100755 --- a/src/library/scala/collection/mutable/WrappedArray.scala +++ b/src/library/scala/collection/mutable/WrappedArray.scala @@ -21,185 +21,134 @@ import collection.generic._ * @author Martin Odersky, Stephane Micheloud * @version 1.0 */ -abstract class WrappedArray[A] extends Vector[A] with VectorLike[A, WrappedArray[A]] with Proxy { self => +abstract class WrappedArray[T] extends Vector[T] with ArrayLike[T, WrappedArray[T]] { - override protected[this] def thisCollection: WrappedArray[A] = this - override protected[this] def toCollection(repr: WrappedArray[A]): WrappedArray[A] = repr + override protected[this] def thisCollection: WrappedArray[T] = this + override protected[this] def toCollection(repr: WrappedArray[T]): WrappedArray[T] = repr /** The manifest of the element type */ - def elemManifest: ClassManifest[A] + def elemManifest: ClassManifest[T] /** The length of the array */ def length: Int /** The element at given index */ - def apply(index: Int): A + def apply(index: Int): T /** Update element at given index */ - def update(index: Int, elem: A): Unit + def update(index: Int, elem: T): Unit /** The underlying array */ - def array: AnyRef + def array: Array[T] - /** The original of a proxy represented by a wrapped array */ - override def self = repr + override def stringPrefix = "Array" /** Creates new builder for this collection ==> move to subclasses */ - override protected[this] def newBuilder: Builder[A, WrappedArray[A]] = - new WrappedArrayBuilder[A](elemManifest) + override protected[this] def newBuilder: Builder[T, WrappedArray[T]] = + new WrappedArrayBuilder[T](elemManifest) } object WrappedArray { - @serializable - final class ofRef[T](val array: Array[AnyRef]) extends WrappedArray[T] { + def make[T](x: AnyRef): WrappedArray[T] = x match { + case x: Array[AnyRef] => wrapArray[AnyRef](x).asInstanceOf[WrappedArray[T]] + case x: Array[Int] => wrapArray(x).asInstanceOf[WrappedArray[T]] + case x: Array[Double] => wrapArray(x).asInstanceOf[WrappedArray[T]] + case x: Array[Long] => wrapArray(x).asInstanceOf[WrappedArray[T]] + case x: Array[Float] => wrapArray(x).asInstanceOf[WrappedArray[T]] + case x: Array[Char] => wrapArray(x).asInstanceOf[WrappedArray[T]] + case x: Array[Byte] => wrapArray(x).asInstanceOf[WrappedArray[T]] + case x: Array[Short] => wrapArray(x).asInstanceOf[WrappedArray[T]] + case x: Array[Boolean] => wrapArray(x).asInstanceOf[WrappedArray[T]] + case x: Array[Unit] => wrapArray(x).asInstanceOf[WrappedArray[T]] + } - lazy val elemManifest = ClassManifest.classType[T](array.getClass.getComponentType) + implicit def builderFactory[T](implicit m: ClassManifest[T]): BuilderFactory[T, WrappedArray[T], WrappedArray[_]] = + new BuilderFactory[T, WrappedArray[T], WrappedArray[_]] { + def apply(from: WrappedArray[_]): Builder[T, WrappedArray[T]] = + ArrayBuilder.make[T]()(m) mapResult WrappedArray.make[T] + } - def length: Int = array.length + def newBuilder[A]: Builder[A, Vector[A]] = new ArrayBuffer + @serializable + final class ofRef[T <: AnyRef](val array: Array[T]) extends WrappedArray[T] { + lazy val elemManifest = ClassManifest.classType[T](array.getClass.getComponentType) + def length: Int = array.length def apply(index: Int): T = array(index).asInstanceOf[T] - - def update(index: Int, elem: T) { - array(index) = elem.asInstanceOf[AnyRef] - } - - def unbox(elemClass: Class[_]): AnyRef = array + def update(index: Int, elem: T) { array(index) = elem } } @serializable final class ofByte(val array: Array[Byte]) extends WrappedArray[Byte] { - def elemManifest = ClassManifest.Byte - def length: Int = array.length - def apply(index: Int): Byte = array(index) - - def update(index: Int, elem: Byte) { - array(index) = elem - } - def unbox(elemClass: Class[_]): AnyRef = array + def update(index: Int, elem: Byte) { array(index) = elem } } @serializable final class ofShort(val array: Array[Short]) extends WrappedArray[Short] { - def elemManifest = ClassManifest.Short - def length: Int = array.length - def apply(index: Int): Short = array(index) - - def update(index: Int, elem: Short) { - array(index) = elem - } - def unbox(elemClass: Class[_]): AnyRef = array + def update(index: Int, elem: Short) { array(index) = elem } } @serializable final class ofChar(val array: Array[Char]) extends WrappedArray[Char] { - def elemManifest = ClassManifest.Char - def length: Int = array.length - def apply(index: Int): Char = array(index) - - def update(index: Int, elem: Char) { - array(index) = elem - } - def unbox(elemClass: Class[_]): AnyRef = array + def update(index: Int, elem: Char) { array(index) = elem } } @serializable final class ofInt(val array: Array[Int]) extends WrappedArray[Int] { - def elemManifest = ClassManifest.Int - def length: Int = array.length - def apply(index: Int): Int = array(index) - - def update(index: Int, elem: Int) { - array(index) = elem - } - def unbox(elemClass: Class[_]): AnyRef = array + def update(index: Int, elem: Int) { array(index) = elem } } @serializable final class ofLong(val array: Array[Long]) extends WrappedArray[Long] { - def elemManifest = ClassManifest.Long - def length: Int = array.length - def apply(index: Int): Long = array(index) - - def update(index: Int, elem: Long) { - array(index) = elem - } - def unbox(elemClass: Class[_]): AnyRef = array + def update(index: Int, elem: Long) { array(index) = elem } } @serializable final class ofFloat(val array: Array[Float]) extends WrappedArray[Float] { - def elemManifest = ClassManifest.Float - def length: Int = array.length - def apply(index: Int): Float = array(index) - - def update(index: Int, elem: Float) { - array(index) = elem - } - def unbox(elemClass: Class[_]): AnyRef = array + def update(index: Int, elem: Float) { array(index) = elem } } @serializable final class ofDouble(val array: Array[Double]) extends WrappedArray[Double] { - def elemManifest = ClassManifest.Double - def length: Int = array.length - def apply(index: Int): Double = array(index) - - def update(index: Int, elem: Double) { - array(index) = elem - } - def unbox(elemClass: Class[_]): AnyRef = array + def update(index: Int, elem: Double) { array(index) = elem } } @serializable final class ofBoolean(val array: Array[Boolean]) extends WrappedArray[Boolean] { - def elemManifest = ClassManifest.Boolean - def length: Int = array.length - def apply(index: Int): Boolean = array(index) - - def update(index: Int, elem: Boolean) { - array(index) = elem - } - def unbox(elemClass: Class[_]): AnyRef = array + def update(index: Int, elem: Boolean) { array(index) = elem } } @serializable final class ofUnit(val array: Array[Unit]) extends WrappedArray[Unit] { - def elemManifest = ClassManifest.Unit - def length: Int = array.length - def apply(index: Int): Unit = array(index) - - def update(index: Int, elem: Unit) { - array(index) = elem - } - def unbox(elemClass: Class[_]): AnyRef = array + def update(index: Int, elem: Unit) { array(index) = elem } } } diff --git a/src/library/scala/io/BytePickle.scala b/src/library/scala/io/BytePickle.scala index b468ba4b52..558a299399 100644 --- a/src/library/scala/io/BytePickle.scala +++ b/src/library/scala/io/BytePickle.scala @@ -65,8 +65,8 @@ object BytePickle { def refDef: PU[RefDef] = new PU[RefDef] { def appP(b: RefDef, s: Array[Byte]): Array[Byte] = b match { - case Ref() => Array.concat(s, (List[Byte](0)).toArray) - case Def() => Array.concat(s, (List[Byte](1)).toArray) + case Ref() => Array.concat(s, Array[Byte](0)) + case Def() => Array.concat(s, Array[Byte](1)) }; def appU(s: Array[Byte]): (RefDef, Array[Byte]) = if (s(0) == 0) (Ref(), s.slice(1, s.length)) @@ -229,7 +229,7 @@ object BytePickle { sequ(j, pa, (x: a) => lift(i(x))) def appendByte(a: Array[Byte], b: Int): Array[Byte] = - Array.concat(a, (List[Byte](b.asInstanceOf[Byte])).toArray) + Array.concat(a, Array(b.toByte)) def nat2Bytes(x: Int): Array[Byte] = { val buf = new ArrayBuffer[Byte] @@ -266,7 +266,7 @@ object BytePickle { def byte: SPU[Byte] = new SPU[Byte] { def appP(b: Byte, s: PicklerState): PicklerState = - new PicklerState(Array.concat(s.stream, (List[Byte](b)).toArray), s.dict); + new PicklerState(Array.concat(s.stream, Array(b)), s.dict) def appU(s: UnPicklerState): (Byte, UnPicklerState) = (s.stream(0), new UnPicklerState(s.stream.slice(1, s.stream.length), s.dict)); } diff --git a/src/library/scala/reflect/ClassManifest.scala b/src/library/scala/reflect/ClassManifest.scala index 68183580ce..4dc9631710 100644 --- a/src/library/scala/reflect/ClassManifest.scala +++ b/src/library/scala/reflect/ClassManifest.scala @@ -13,7 +13,7 @@ package scala.reflect import scala.runtime._ import scala.collection.immutable.Nil -import scala.collection.mutable.{WrappedArray} +import scala.collection.mutable.{WrappedArray, ArrayBuilder} /**

* A ClassManifest[T] is an opaque descriptor for type T. @@ -72,24 +72,50 @@ trait ClassManifest[T] extends OptManifest[T] { case _ => false } - def newArray(len: Int): BoxedArray[T] = { - // it's safe to assume T <: AnyRef here because the method is overridden for all value type manifests - new BoxedObjectArray(java.lang.reflect.Array.newInstance(erasure, len).asInstanceOf[Array[AnyRef]]) - .asInstanceOf[BoxedArray[T]] - } + protected def arrayClass: Predef.Class[Array[T]] = + java.lang.reflect.Array.newInstance(erasure, 0).getClass + .asInstanceOf[Predef.Class[Array[T]]] - def newArray1(len: Int): Array[T] = + def arrayManifest: ClassManifest[Array[T]] = + ClassManifest.classType[Array[T]](arrayClass) + + def newArray(len: Int): Array[T] = java.lang.reflect.Array.newInstance(erasure, len).asInstanceOf[Array[T]] + def newArray2(len: Int): Array[Array[T]] = + java.lang.reflect.Array.newInstance( + java.lang.reflect.Array.newInstance(erasure, 0).getClass, len) + .asInstanceOf[Array[Array[T]]] + + def newArray3(len: Int): Array[Array[Array[T]]] = + java.lang.reflect.Array.newInstance( + java.lang.reflect.Array.newInstance(erasure, 0, 0).getClass, len) + .asInstanceOf[Array[Array[Array[T]]]] + + def newArray4(len: Int): Array[Array[Array[Array[T]]]] = + java.lang.reflect.Array.newInstance( + java.lang.reflect.Array.newInstance(erasure, 0, 0, 0).getClass, len) + .asInstanceOf[Array[Array[Array[Array[T]]]]] + + def newArray5(len: Int): Array[Array[Array[Array[Array[T]]]]] = + java.lang.reflect.Array.newInstance( + java.lang.reflect.Array.newInstance(erasure, 0, 0, 0, 0).getClass, len) + .asInstanceOf[Array[Array[Array[Array[Array[T]]]]]] + def newWrappedArray(len: Int): WrappedArray[T] = // it's safe to assume T <: AnyRef here because the method is overridden for all value type manifests - new WrappedArray.ofRef(java.lang.reflect.Array.newInstance(erasure, len).asInstanceOf[Array[AnyRef]]) - .asInstanceOf[WrappedArray[T]] + new WrappedArray.ofRef[T with AnyRef](newArray(len).asInstanceOf[Array[T with AnyRef]]).asInstanceOf[WrappedArray[T]] - def typeArguments: List[OptManifest[_]] = List() + def newArrayBuilder(): ArrayBuilder[T] = + // it's safe to assume T <: AnyRef here because the method is overridden for all value type manifests + new ArrayBuilder.ofRef[T with AnyRef]()(this.asInstanceOf[ClassManifest[T with AnyRef]]).asInstanceOf[ArrayBuilder[T]] - protected def argString = if (typeArguments.isEmpty) "" else typeArguments.mkString("[", ", ", "]") + def typeArguments: List[OptManifest[_]] = List() + protected def argString = + if (typeArguments.nonEmpty) typeArguments.mkString("[", ", ", "]") + else if (erasure.isArray) "["+ClassManifest.fromClass(erasure.getComponentType)+"]" + else "" } /**

@@ -114,10 +140,24 @@ object ClassManifest { val Boolean = Manifest.Boolean val Unit = Manifest.Unit val Any = Manifest.Any + val Object = Manifest.Object val AnyVal = Manifest.AnyVal val Nothing = Manifest.Nothing val Null = Manifest.Null + def fromClass[T](clazz: Predef.Class[T]): ClassManifest[T] = clazz match { + case java.lang.Byte.TYPE => Byte.asInstanceOf[ClassManifest[T]] + case java.lang.Short.TYPE => Short.asInstanceOf[ClassManifest[T]] + case java.lang.Character.TYPE => Char.asInstanceOf[ClassManifest[T]] + case java.lang.Integer.TYPE => Int.asInstanceOf[ClassManifest[T]] + case java.lang.Long.TYPE => Long.asInstanceOf[ClassManifest[T]] + case java.lang.Float.TYPE => Float.asInstanceOf[ClassManifest[T]] + case java.lang.Double.TYPE => Double.asInstanceOf[ClassManifest[T]] + case java.lang.Boolean.TYPE => Boolean.asInstanceOf[ClassManifest[T]] + case java.lang.Void.TYPE => Unit.asInstanceOf[ClassManifest[T]] + case _ => classType[T with AnyRef](clazz).asInstanceOf[ClassManifest[T]] + } + def singleType[T](value: Any): Manifest[T] = Manifest.singleType(value) /** ClassManifest for the class type `clazz', where `clazz' is @@ -127,32 +167,37 @@ object ClassManifest { * pass varargs as arrays into this, we get an infinitely recursive call * to boxArray. (Besides, having a separate case is more efficient) */ - def classType[T](clazz: Predef.Class[_]): ClassManifest[T] = + def classType[T <: AnyRef](clazz: Predef.Class[_]): ClassManifest[T] = new ClassTypeManifest[T](None, clazz, Nil) /** ClassManifest for the class type `clazz[args]', where `clazz' is * a top-level or static class and `args` are its type arguments */ - def classType[T](clazz: Predef.Class[_], arg1: OptManifest[_], args: OptManifest[_]*): ClassManifest[T] = + def classType[T <: AnyRef](clazz: Predef.Class[_], arg1: OptManifest[_], args: OptManifest[_]*): ClassManifest[T] = new ClassTypeManifest[T](None, clazz, arg1 :: args.toList) /** ClassManifest for the class type `clazz[args]', where `clazz' is * a class with non-package prefix type `prefix` and type arguments `args`. */ - def classType[T](prefix: OptManifest[_], clazz: Predef.Class[_], args: OptManifest[_]*): ClassManifest[T] = + def classType[T <: AnyRef](prefix: OptManifest[_], clazz: Predef.Class[_], args: OptManifest[_]*): ClassManifest[T] = new ClassTypeManifest[T](Some(prefix), clazz, args.toList) /** Manifest for the class type `clazz[args]', where `clazz' is * a top-level or static class. */ @serializable - private class ClassTypeManifest[T](prefix: Option[OptManifest[_]], - val erasure: Predef.Class[_], - override val typeArguments: List[OptManifest[_]]) extends ClassManifest[T] { + private class ClassTypeManifest[T <: AnyRef](prefix: Option[OptManifest[_]], + val erasure: Predef.Class[_], + override val typeArguments: List[OptManifest[_]]) extends ClassManifest[T] { override def toString = (if (prefix.isEmpty) "" else prefix.get.toString+"#") + (if (erasure.isArray) "Array" else erasure.getName) + argString } + def arrayType[T](arg: OptManifest[_]): ClassManifest[Array[T]] = arg match { + case NoManifest => Object.asInstanceOf[ClassManifest[Array[T]]] + case m: ClassManifest[_] => m.asInstanceOf[ClassManifest[T]].arrayManifest + } + /** ClassManifest for the abstract type `prefix # name'. `upperBound' is not * strictly necessary as it could be obtained by reflection. It was * added so that erasure can be calculated without reflection. */ diff --git a/src/library/scala/reflect/FullManifest.scala b/src/library/scala/reflect/FullManifest.scala deleted file mode 100644 index ea71aedf71..0000000000 --- a/src/library/scala/reflect/FullManifest.scala +++ /dev/null @@ -1,147 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2007-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id: Manifest.scala 18506 2009-08-18 17:24:36Z odersky $ - - -package scala.reflect - -import scala.runtime._ - -/**

- * A Manifest[T] is an opaque descriptor for type T. - * Currently, its only use is to give access to the erasure of the type as a - * Class instance. - *

- *

- * BE AWARE: The different type-relation operators are all forwarded - * to the erased type as an approximation of the final semantics where - * these operators should be on the unerased type. - *

- */ -@serializable -trait FullManifest[T] extends Manifest[T] { - override def typeArguments: List[FullManifest[_]] = List() -} - -/**

- * This object is used by the compiler and should not be used in client - * code. The object Manifest defines factory methods for - * manifests. - *

- *

- * BE AWARE: The factory for refinement types is missing and - * will be implemented in a later version of this class. - *

- */ -object FullManifest { - - val Byte = new (FullManifest[Byte] @serializable) { - def erasure = java.lang.Byte.TYPE - override def toString = "Byte" - override def newArray(len: Int): BoxedArray[Byte] = new BoxedByteArray(new Array[Byte](len)) - } - - val Short = new (FullManifest[Short] @serializable) { - def erasure = java.lang.Short.TYPE - override def toString = "Short" - override def newArray(len: Int): BoxedArray[Short] = new BoxedShortArray(new Array[Short](len)) - } - - val Char = new (FullManifest[Char] @serializable) { - def erasure = java.lang.Character.TYPE - override def toString = "Char" - override def newArray(len: Int): BoxedArray[Char] = new BoxedCharArray(new Array[Char](len)) - } - - val Int = new (FullManifest[Int] @serializable) { - def erasure = java.lang.Integer.TYPE - override def toString = "Int" - override def newArray(len: Int): BoxedArray[Int] = new BoxedIntArray(new Array[Int](len)) - } - - val Long = new (FullManifest[Long] @serializable) { - def erasure = java.lang.Long.TYPE - override def toString = "Long" - override def newArray(len: Int): BoxedArray[Long] = new BoxedLongArray(new Array[Long](len)) - } - - val Float = new (FullManifest[Float] @serializable) { - def erasure = java.lang.Float.TYPE - override def toString = "Float" - override def newArray(len: Int): BoxedArray[Float] = new BoxedFloatArray(new Array[Float](len)) - } - - val Double = new (FullManifest[Double] @serializable) { - def erasure = java.lang.Double.TYPE - override def toString = "Double" - override def newArray(len: Int): BoxedArray[Double] = new BoxedDoubleArray(new Array[Double](len)) - } - - val Boolean = new (FullManifest[Boolean] @serializable) { - def erasure = java.lang.Boolean.TYPE - override def toString = "Boolean" - override def newArray(len: Int): BoxedArray[Boolean] = new BoxedBooleanArray(new Array[Boolean](len)) - } - - val Unit = new (FullManifest[Unit] @serializable) { - def erasure = java.lang.Void.TYPE - override def toString = "Unit" - override def newArray(len: Int): BoxedArray[Unit] = new BoxedUnitArray(new Array[Unit](len)) - } - - /** Manifest for the singleton type `value.type'. */ - def singleType[T](value: Any): FullManifest[T] = - new (FullManifest[T] @serializable) { - lazy val erasure = - value match { - case anyRefValue: AnyRef => anyRefValue.getClass - case anyValue => error("There is no singleton type for AnyVal values") - } - override lazy val toString = value.toString + ".type" - } - - /** Manifest for the class type `clazz', where `clazz' is - * a top-level or static class. */ - def classType[T](clazz: Predef.Class[T], args: FullManifest[_]*): FullManifest[T] = - classType(None, clazz, args: _*) - - /** Manifest for the class type `clazz[args]', where `clazz' is - * a top-level or static class. */ - def classType[T](prefix: FullManifest[_], clazz: Predef.Class[_], args: FullManifest[_]*): FullManifest[T] = - classType(Some(prefix), clazz, args: _*) - - /** Manifest for the class type `clazz[args]', where `clazz' is - * a top-level or static class. */ - def classType[T](prefix: Option[FullManifest[_]], clazz: Predef.Class[_], args: FullManifest[_]*): FullManifest[T] = - new (FullManifest[T] @serializable) { - def erasure = clazz - override val typeArguments = args.toList - override def toString = - (if (prefix.isEmpty) "" else prefix.get.toString+"#") + - (if (erasure.isArray) "Array" else erasure.getName) + - argString - } - - /** Manifest for the abstract type `prefix # name'. `upperBound' is not - * strictly necessary as it could be obtained by reflection. It was - * added so that erasure can be calculated without reflection. */ - def abstractType[T](prefix: FullManifest[_], name: String, upperBound: FullManifest[_], args: FullManifest[_]*): FullManifest[T] = - new (FullManifest[T] @serializable) { - def erasure = upperBound.erasure - override val typeArguments = args.toList - override def toString = prefix.toString+"#"+name+argString - } - - /** Manifest for the intersection type `parents_0 with ... with parents_n'. */ - def intersectionType[T](parents: FullManifest[_]*): FullManifest[T] = - new (FullManifest[T] @serializable) { - def erasure = parents.head.erasure - override def toString = parents.mkString(" with ") - } -} diff --git a/src/library/scala/reflect/Manifest.scala b/src/library/scala/reflect/Manifest.scala index bf1ff5cfaf..f0c5183e6a 100644 --- a/src/library/scala/reflect/Manifest.scala +++ b/src/library/scala/reflect/Manifest.scala @@ -28,6 +28,9 @@ import scala.collection.mutable._ @serializable trait Manifest[T] extends ClassManifest[T] { override def typeArguments: List[Manifest[_]] = List() + + override def arrayManifest: Manifest[Array[T]] = + Manifest.classType[Array[T]](arrayClass) } /** @@ -45,64 +48,73 @@ object Manifest { val Byte = new (Manifest[Byte] @serializable) { def erasure = java.lang.Byte.TYPE override def toString = "Byte" - override def newArray(len: Int): BoxedArray[Byte] = new BoxedByteArray(new Array[Byte](len)) + override def newArray(len: Int): Array[Byte] = new Array[Byte](len) override def newWrappedArray(len: Int): WrappedArray[Byte] = new WrappedArray.ofByte(new Array[Byte](len)) + override def newArrayBuilder(): ArrayBuilder[Byte] = new ArrayBuilder.ofByte() } val Short = new (Manifest[Short] @serializable) { def erasure = java.lang.Short.TYPE override def toString = "Short" - override def newArray(len: Int): BoxedArray[Short] = new BoxedShortArray(new Array[Short](len)) + override def newArray(len: Int): Array[Short] = new Array[Short](len) override def newWrappedArray(len: Int): WrappedArray[Short] = new WrappedArray.ofShort(new Array[Short](len)) + override def newArrayBuilder(): ArrayBuilder[Short] = new ArrayBuilder.ofShort() } val Char = new (Manifest[Char] @serializable) { def erasure = java.lang.Character.TYPE override def toString = "Char" - override def newArray(len: Int): BoxedArray[Char] = new BoxedCharArray(new Array[Char](len)) + override def newArray(len: Int): Array[Char] = new Array[Char](len) override def newWrappedArray(len: Int): WrappedArray[Char] = new WrappedArray.ofChar(new Array[Char](len)) + override def newArrayBuilder(): ArrayBuilder[Char] = new ArrayBuilder.ofChar() } val Int = new (Manifest[Int] @serializable) { def erasure = java.lang.Integer.TYPE override def toString = "Int" - override def newArray(len: Int): BoxedArray[Int] = new BoxedIntArray(new Array[Int](len)) + override def newArray(len: Int): Array[Int] = new Array[Int](len) override def newWrappedArray(len: Int): WrappedArray[Int] = new WrappedArray.ofInt(new Array[Int](len)) + override def newArrayBuilder(): ArrayBuilder[Int] = new ArrayBuilder.ofInt() } val Long = new (Manifest[Long] @serializable) { def erasure = java.lang.Long.TYPE override def toString = "Long" - override def newArray(len: Int): BoxedArray[Long] = new BoxedLongArray(new Array[Long](len)) + override def newArray(len: Int): Array[Long] = new Array[Long](len) override def newWrappedArray(len: Int): WrappedArray[Long] = new WrappedArray.ofLong(new Array[Long](len)) + override def newArrayBuilder(): ArrayBuilder[Long] = new ArrayBuilder.ofLong() } val Float = new (Manifest[Float] @serializable) { def erasure = java.lang.Float.TYPE override def toString = "Float" - override def newArray(len: Int): BoxedArray[Float] = new BoxedFloatArray(new Array[Float](len)) + override def newArray(len: Int): Array[Float] = new Array[Float](len) override def newWrappedArray(len: Int): WrappedArray[Float] = new WrappedArray.ofFloat(new Array[Float](len)) + override def newArrayBuilder(): ArrayBuilder[Float] = new ArrayBuilder.ofFloat() } val Double = new (Manifest[Double] @serializable) { def erasure = java.lang.Double.TYPE override def toString = "Double" - override def newArray(len: Int): BoxedArray[Double] = new BoxedDoubleArray(new Array[Double](len)) + override def newArray(len: Int): Array[Double] = new Array[Double](len) override def newWrappedArray(len: Int): WrappedArray[Double] = new WrappedArray.ofDouble(new Array[Double](len)) + override def newArrayBuilder(): ArrayBuilder[Double] = new ArrayBuilder.ofDouble() } val Boolean = new (Manifest[Boolean] @serializable) { def erasure = java.lang.Boolean.TYPE override def toString = "Boolean" - override def newArray(len: Int): BoxedArray[Boolean] = new BoxedBooleanArray(new Array[Boolean](len)) + override def newArray(len: Int): Array[Boolean] = new Array[Boolean](len) override def newWrappedArray(len: Int): WrappedArray[Boolean] = new WrappedArray.ofBoolean(new Array[Boolean](len)) + override def newArrayBuilder(): ArrayBuilder[Boolean] = new ArrayBuilder.ofBoolean() } val Unit = new (Manifest[Unit] @serializable) { def erasure = java.lang.Void.TYPE override def toString = "Unit" - override def newArray(len: Int): BoxedArray[Unit] = new BoxedUnitArray(new Array[Unit](len)) + override def newArray(len: Int): Array[Unit] = new Array[Unit](len) override def newWrappedArray(len: Int): WrappedArray[Unit] = new WrappedArray.ofUnit(new Array[Unit](len)) + override def newArrayBuilder(): ArrayBuilder[Unit] = new ArrayBuilder.ofUnit() } val Any: Manifest[Any] = new ClassTypeManifest[Any](None, classOf[java.lang.Object], List()) { @@ -110,6 +122,11 @@ object Manifest { // todo: re-implement <:< } + val Object: Manifest[Object] = new ClassTypeManifest[Object](None, classOf[java.lang.Object], List()) { + override def toString = "Object" + // todo: re-implement <:< + } + val AnyVal: Manifest[AnyVal] = new ClassTypeManifest[AnyVal](None, classOf[java.lang.Object], List()) { override def toString = "AnyVal" // todo: re-implement <:< @@ -136,32 +153,29 @@ object Manifest { override lazy val toString = value.toString + ".type" } - /** Manifest for the class type clazz[args], where clazz - * is a top-level or static class. - * @note This no-prefix, no-arguments case is separate because we - * it's called from ScalaRunTime.boxArray itself. If we - * pass varargs as arrays into this, we get an infinitely recursive call - * to boxArray. (Besides, having a separate case is more efficient) - */ + /** Manifest for the class type `clazz[args]', where `clazz' is + * a top-level or static class. + * @note This no-prefix, no-arguments case is separate because we + * it's called from ScalaRunTime.boxArray itself. If we + * pass varargs as arrays into this, we get an infinitely recursive call + * to boxArray. (Besides, having a separate case is more efficient) + */ def classType[T](clazz: Predef.Class[_]): Manifest[T] = new ClassTypeManifest[T](None, clazz, Nil) - /** Manifest for the class type clazz, where clazz - * is a top-level or static class and args are its type arguments. - */ + /** Manifest for the class type `clazz', where `clazz' is + * a top-level or static class and args are its type arguments. */ def classType[T](clazz: Predef.Class[T], arg1: Manifest[_], args: Manifest[_]*): Manifest[T] = new ClassTypeManifest[T](None, clazz, arg1 :: args.toList) - /** Manifest for the class type clazz[args], where clazz - * is a class with non-package prefix type prefix and type - * arguments args. - */ + /** Manifest for the class type `clazz[args]', where `clazz' is + * a class with non-package prefix type `prefix` and type arguments `args`. + */ def classType[T](prefix: Manifest[_], clazz: Predef.Class[_], args: Manifest[_]*): Manifest[T] = new ClassTypeManifest[T](Some(prefix), clazz, args.toList) - /** Manifest for the class type clazz[args], where `clazz' is - * a top-level or static class. - */ + /** Manifest for the class type `clazz[args]', where `clazz' is + * a top-level or static class. */ @serializable private class ClassTypeManifest[T](prefix: Option[Manifest[_]], val erasure: Predef.Class[_], @@ -172,11 +186,12 @@ object Manifest { argString } - /** Manifest for the abstract type prefix # name. - * upperBound is not strictly necessary as it could be obtained - * by reflection. It was added so that erasure can be calculated without - * reflection. - */ + def arrayType[T](arg: Manifest[_]): Manifest[Array[T]] = + arg.asInstanceOf[Manifest[T]].arrayManifest + + /** Manifest for the abstract type `prefix # name'. `upperBound' is not + * strictly necessary as it could be obtained by reflection. It was + * added so that erasure can be calculated without reflection. */ def abstractType[T](prefix: Manifest[_], name: String, upperBound: Manifest[_], args: Manifest[_]*): Manifest[T] = new (Manifest[T] @serializable) { def erasure = upperBound.erasure diff --git a/src/library/scala/reflect/RichClass.scala b/src/library/scala/reflect/RichClass.scala index 5d58d12377..7d690f360d 100644 --- a/src/library/scala/reflect/RichClass.scala +++ b/src/library/scala/reflect/RichClass.scala @@ -10,9 +10,9 @@ package scala.reflect -import annotation.experimental -import util.control.Exception._ -import util.ScalaClassLoader._ +import scala.annotation.experimental +import scala.util.control.Exception._ +import scala.util.ScalaClassLoader._ import java.lang.{ Class => JClass } import java.lang.reflect. { Constructor => JConstructor } diff --git a/src/library/scala/runtime/BoxedArray.scala b/src/library/scala/runtime/BoxedArray.scala index c626f685d3..3e815d16a4 100644 --- a/src/library/scala/runtime/BoxedArray.scala +++ b/src/library/scala/runtime/BoxedArray.scala @@ -25,6 +25,10 @@ import collection.Sequence */ abstract class BoxedArray[A] extends Vector[A] with VectorTemplate[A, BoxedArray[A]] with Boxed { self => + val ex = new Error("trying to create a BoxedArray") + ex.printStackTrace() + throw ex + /** The manifest of the element type */ def elemManifest: ClassManifest[A] @@ -40,8 +44,7 @@ abstract class BoxedArray[A] extends Vector[A] with VectorTemplate[A, BoxedArray /** Creates new builder for this collection ==> move to subclasses */ override protected[this] def newBuilder: Builder[A, BoxedArray[A]] = - if (elemManifest != null) new ArrayBuilder[A](elemManifest) - else genericBuilder[A] + genericBuilder[A] // !!! todo: remove override def genericBuilder[B]: Builder[B, BoxedArray[B]] = new ArrayBuffer[B].mapResult { diff --git a/src/library/scala/runtime/RichString.scala b/src/library/scala/runtime/RichString.scala index 1be546a902..3c643131cc 100644 --- a/src/library/scala/runtime/RichString.scala +++ b/src/library/scala/runtime/RichString.scala @@ -232,7 +232,7 @@ class RichString(val self: String) extends Proxy with Vector[Char] with VectorTe * @throws java.lang.IllegalArgumentException */ def format(args : Any*) : String = - java.lang.String.format(self, args.asInstanceOf[Seq[AnyRef]].toArray: _*) + java.lang.String.format(self, args.asInstanceOf[Seq[AnyRef]]: _*) /**

* Like format(args*) but takes an initial Locale parameter @@ -249,6 +249,6 @@ class RichString(val self: String) extends Proxy with Vector[Char] with VectorTe * @throws java.lang.IllegalArgumentException */ def format(l: java.util.Locale, args: Any*): String = - java.lang.String.format(l, self, args.asInstanceOf[Seq[AnyRef]].toArray: _*) + java.lang.String.format(l, self, args.asInstanceOf[Seq[AnyRef]]: _*) } diff --git a/src/library/scala/runtime/ScalaRunTime.scala b/src/library/scala/runtime/ScalaRunTime.scala index 707433d241..158e83b582 100644 --- a/src/library/scala/runtime/ScalaRunTime.scala +++ b/src/library/scala/runtime/ScalaRunTime.scala @@ -19,16 +19,20 @@ import scala.collection.mutable._ */ object ScalaRunTime { - def isArray(x: AnyRef): Boolean = x != null && (x.getClass.isArray || x.isInstanceOf[BoxedArray[_]]) + def isArray(x: AnyRef): Boolean = // !!! remove once newarrays + x != null && (x.getClass.isArray || x.isInstanceOf[BoxedArray[_]]) + + def isArray(x: AnyRef, atLevel: Int): Boolean = + x != null && isArrayClass(x.getClass, atLevel) + + private def isArrayClass(clazz: Class[_], atLevel: Int): Boolean = + clazz.isArray && (atLevel == 1 || isArrayClass(clazz.getComponentType, atLevel - 1)) + def isValueClass(clazz: Class[_]) = clazz.isPrimitive() - // todo: [for Gilles] replace with boxArray - def forceBoxedArray[A <: Any](xs: Seq[A]): Array[A] = { - val array = new Array[A](xs.length) - var i = 0 - for (x <- xs.iterator) { array(i) = x; i += 1 } - array - } + // todo: remove? + def forceBoxedArray[A <: Any](xs: Seq[A]): Array[A] = + throw new Error(" not implemented: forceBoxedArray") /** Retrieve generic array element */ def array_apply(xs: AnyRef, idx: Int): Any = java.lang.reflect.Array.get(xs, idx) @@ -39,6 +43,18 @@ object ScalaRunTime { /** Get generic array length */ def array_length(xs: AnyRef): Int = java.lang.reflect.Array.getLength(xs) + /** Convert a numeric value array to an object array. + * Needed to deal with vararg arguments of primtive types that are passed + * to a generic Java vararg parameter T ... + */ + def toObjectArray(src: AnyRef): Array[Object] = { + val length = array_length(src) + val dest = new Array[Object](length) + for (i <- 0 until length) + array_update(dest, i, array_apply(src, i)) + dest + } + def toArray[T](xs: scala.collection.Sequence[T]) = { val arr = new Array[AnyRef](xs.length) var i = 0 @@ -46,23 +62,6 @@ object ScalaRunTime { arr } - /** Convert arrays to sequences, leave sequences as they are - * !!! see duplication wrt - */ - def toSequence[T](xs: AnyRef): Sequence[T] = xs match { - case ts: Sequence[T] => ts.asInstanceOf[Sequence[T]] - case null => null - case x: Array[AnyRef] => new WrappedArray.ofRef(x).asInstanceOf[Array[T]] - case x: Array[Int] => new WrappedArray.ofInt(x).asInstanceOf[Array[T]] - case x: Array[Double] => new WrappedArray.ofDouble(x).asInstanceOf[Array[T]] - case x: Array[Long] => new WrappedArray.ofLong(x).asInstanceOf[Array[T]] - case x: Array[Float] => new WrappedArray.ofFloat(x).asInstanceOf[Array[T]] - case x: Array[Char] => new WrappedArray.ofChar(x).asInstanceOf[Array[T]] - case x: Array[Byte] => new WrappedArray.ofByte(x).asInstanceOf[Array[T]] - case x: Array[Short] => new WrappedArray.ofShort(x).asInstanceOf[Array[T]] - case x: Array[Boolean] => new WrappedArray.ofBoolean(x).asInstanceOf[Array[T]] - } - def checkInitialized[T <: AnyRef](x: T): T = if (x == null) throw new UninitializedError else x @@ -191,7 +190,10 @@ object ScalaRunTime { */ def stringOf(arg : Any): String = arg match { case null => "null" - case (arg : AnyRef) if isArray(arg) => boxArray(arg).deepToString + case arg: AnyRef if isArray(arg) => + val d: collection.Vector[Any] = WrappedArray.make(arg).deep + d.toString + case arg: WrappedArray[_] => arg.deep.toString case arg => arg.toString } } diff --git a/src/library/scala/util/ClassLoader.scala b/src/library/scala/util/ClassLoader.scala index 6458b0900c..56ed6c70c2 100644 --- a/src/library/scala/util/ClassLoader.scala +++ b/src/library/scala/util/ClassLoader.scala @@ -51,7 +51,7 @@ trait ScalaClassLoader extends JavaClassLoader if (!Modifier.isStatic(method.getModifiers)) throw new NoSuchMethodException(objectName + ".main is not static") - asContext(method.invoke(null, Array(arguments.toArray): _*)) + asContext(method.invoke(null, Array(arguments.toArray).toSequence: _*)) // !!! todo: remove toSequence once newarrays starr is in } } @@ -89,4 +89,4 @@ object ScalaClassLoader { search(getContextLoader()) } -} \ No newline at end of file +} diff --git a/src/library/scala/xml/Utility.scala b/src/library/scala/xml/Utility.scala index 68d68ee4aa..39e594eb05 100644 --- a/src/library/scala/xml/Utility.scala +++ b/src/library/scala/xml/Utility.scala @@ -292,7 +292,7 @@ object Utility extends AnyRef with parsing.TokenTests def getName(s: String, index: Int): String = { if (index >= s.length) null else (s drop index) match { - case Seq(x, xs @ _*) if isNameStart(x) => (Array(x) ++ (xs takeWhile isNameChar)).mkString + case Seq(x, xs @ _*) if isNameStart(x) => x.toString + (xs takeWhile isNameChar).mkString case _ => "" } } diff --git a/src/library/scala/xml/transform/BasicTransformer.scala b/src/library/scala/xml/transform/BasicTransformer.scala index a79c32a5f0..6b01871397 100644 --- a/src/library/scala/xml/transform/BasicTransformer.scala +++ b/src/library/scala/xml/transform/BasicTransformer.scala @@ -31,7 +31,7 @@ abstract class BasicTransformer extends Function1[Node,Node] * to NodeBuffer. */ def transform(it: Iterator[Node], nb: NodeBuffer): Seq[Node] = - it.foldLeft(nb)(_ ++= transform(_)) toArray + it.foldLeft(nb)(_ ++= transform(_)).toSequence /** Call transform(Node) to each node in ns, yield ns if nothing changes, * otherwise a new sequence of concatenated results. diff --git a/src/partest/scala/tools/partest/PartestTask.scala b/src/partest/scala/tools/partest/PartestTask.scala index 7ad64f6e0d..000c363566 100644 --- a/src/partest/scala/tools/partest/PartestTask.scala +++ b/src/partest/scala/tools/partest/PartestTask.scala @@ -196,13 +196,13 @@ class PartestTask extends Task { def setFileManagerBooleanProperty(name: String, value: Boolean) { val setMethod = antFileManager.getClass.getMethod(name+"_$eq", Array(classOf[Boolean]): _*) - setMethod.invoke(antFileManager, Array(java.lang.Boolean.valueOf(value)): _*) + setMethod.invoke(antFileManager, Array(java.lang.Boolean.valueOf(value)).asInstanceOf[Array[Object]]: _*) } def setFileManagerStringProperty(name: String, value: String) { val setMethod = antFileManager.getClass.getMethod(name+"_$eq", Array(classOf[String]): _*) - setMethod.invoke(antFileManager, Array(value): _*) + setMethod.invoke(antFileManager, Array(value).asInstanceOf[Array[Object]]: _*) } setFileManagerBooleanProperty("showDiff", showDiff) diff --git a/src/scalap/scala/tools/scalap/scalax/rules/SeqRule.scala b/src/scalap/scala/tools/scalap/scalax/rules/SeqRule.scala index 6b36721c50..54f2c70bdc 100644 --- a/src/scalap/scala/tools/scalap/scalax/rules/SeqRule.scala +++ b/src/scalap/scala/tools/scalap/scalax/rules/SeqRule.scala @@ -82,7 +82,7 @@ class SeqRule[S, +A, +X](rule : Rule[S, S, A, X]) { /** Repeats this rule num times */ def times(num : Int) : Rule[S, S, Seq[A], X] = from[S] { - val result = new Array[A](num) + val result = new collection.mutable.GenericArray[A](num) // more compact using HoF but written this way so it's tail-recursive def rep(i : Int, in : S) : Result[S, Seq[A], X] = { if (i == num) Success(in, result) diff --git a/src/swing/scala/swing/ListView.scala b/src/swing/scala/swing/ListView.scala index 11b4a72441..9dbd14fcbe 100644 --- a/src/swing/scala/swing/ListView.scala +++ b/src/swing/scala/swing/ListView.scala @@ -204,7 +204,7 @@ class ListView[A] extends Component { * The currently selected items. */ object items extends scala.collection.SequenceProxy[A] { - def self = peer.getSelectedValues.map(_.asInstanceOf[A]) + def self = peer.getSelectedValues.toSequence.map(_.asInstanceOf[A]) def leadIndex: Int = peer.getSelectionModel.getLeadSelectionIndex def anchorIndex: Int = peer.getSelectionModel.getAnchorSelectionIndex } -- cgit v1.2.3