diff options
author | michelou <michelou@epfl.ch> | 2008-11-25 16:04:12 +0000 |
---|---|---|
committer | michelou <michelou@epfl.ch> | 2008-11-25 16:04:12 +0000 |
commit | 2d61f09332dbc6038f869c6a23a95dca1bc3b6c7 (patch) | |
tree | defa829dd7c0757a68b10b6b7b4235df2cb485de | |
parent | 6700e9988435eb981972754ecf86d11567457e4d (diff) | |
download | scala-2d61f09332dbc6038f869c6a23a95dca1bc3b6c7.tar.gz scala-2d61f09332dbc6038f869c6a23a95dca1bc3b6c7.tar.bz2 scala-2d61f09332dbc6038f869c6a23a95dca1bc3b6c7.zip |
added manifest tests and util.Marshal
-rw-r--r-- | src/compiler/scala/tools/nsc/ast/NodePrinters.scala | 16 | ||||
-rw-r--r-- | src/library/scala/reflect/Manifest.scala | 40 | ||||
-rw-r--r-- | src/library/scala/util/Marshal.scala | 44 | ||||
-rw-r--r-- | test/files/jvm/manifests.check | 54 | ||||
-rw-r--r-- | test/files/jvm/manifests.scala | 79 |
5 files changed, 191 insertions, 42 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/NodePrinters.scala b/src/compiler/scala/tools/nsc/ast/NodePrinters.scala index 42be088b07..57e60f9fba 100644 --- a/src/compiler/scala/tools/nsc/ast/NodePrinters.scala +++ b/src/compiler/scala/tools/nsc/ast/NodePrinters.scala @@ -1,5 +1,5 @@ /* NSC -- new Scala compiler - * Copyright 2005-2007 LAMP/EPFL + * Copyright 2005-2009 LAMP/EPFL * @author Martin Odersky */ // $Id$ @@ -41,7 +41,7 @@ abstract class NodePrinters { if (comma) buf.append(",") buf.append(EOL) } - def annotationInfoToString(attr: AnnotationInfo) = { + def annotationInfoToString(attr: AnnotationInfo): String = { val str = new StringBuilder str.append(attr.atp.toString()) if (!attr.args.isEmpty) @@ -123,7 +123,7 @@ abstract class NodePrinters { (if (buf.length() > 2) buf.substring(3) else "0") + ", // flags=" + flagsToString(sym.flags) + attrs } - def nodeinfo(tree: Tree) = + def nodeinfo(tree: Tree): String = if (infolevel == InfoLevel.Quiet) "" else { val buf = new StringBuilder(" // sym=" + tree.symbol) @@ -155,7 +155,7 @@ abstract class NodePrinters { } buf.toString } - def nodeinfo2(tree: Tree) = + def nodeinfo2(tree: Tree): String = (if (comma) "," else "") + nodeinfo(tree) tree match { case AppliedTypeTree(tpt, args) => @@ -200,13 +200,13 @@ abstract class NodePrinters { case Block(stats, expr) => println("Block(" + nodeinfo(tree)) if (stats.isEmpty) - println(" List() // no statement") + println(" List(), // no statement") else { val n = stats.length println(" List( // " + n + " statement(s)") for (i <- 0 until n) traverse(stats(i), level + 2, i < n-1) - println(" )") + println(" ),") } traverse(expr, level + 1, false) printcln(")") @@ -273,7 +273,9 @@ abstract class NodePrinters { printcln("Super(\"" + qual + "\", \"" + mix + "\")" + nodeinfo2(tree)) case Template(parents, self, body) => println("Template(" + nodeinfo(tree)) - println(" " + parents.map(p => if (p.tpe ne null) p.tpe.typeSymbol else "null-" + p) + ", // parents") + println(" " + parents.map(p => + if (p.tpe ne null) p.tpe.typeSymbol else "null-" + p + ) + ", // parents") traverse(self, level + 1, true) if (body.isEmpty) println(" List() // no body") diff --git a/src/library/scala/reflect/Manifest.scala b/src/library/scala/reflect/Manifest.scala index cac391670a..f4388fc30c 100644 --- a/src/library/scala/reflect/Manifest.scala +++ b/src/library/scala/reflect/Manifest.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2007-2008, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2007-2009, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** @@ -22,7 +22,8 @@ package scala.reflect * these operators should be on the unerased type. * </p> */ -@serializable trait Manifest[T] { +@serializable +trait Manifest[T] { /** A class representing the type U to which T would be erased. Note * that there is no subtyping relationship between T and U. */ @@ -75,7 +76,7 @@ object Manifest { /** Manifest for the singleton type `value.type'. */ def singleType[T](value: Any): Manifest[T] = - new Manifest[T] with java.io.Serializable { + new (Manifest[T] @serializable) { lazy val erasure = value match { case anyRefValue: AnyRef => anyRefValue.getClass @@ -87,7 +88,7 @@ object Manifest { /** Manifest for the class type `clazz', where `clazz' is * a top-level or static class. */ def classType[T](clazz: Predef.Class[T]): Manifest[T] = - new Manifest[T] with java.io.Serializable { + new (Manifest[T] @serializable) { val erasure = clazz override lazy val toString = erasure.getName } @@ -95,47 +96,60 @@ object Manifest { /** Manifest for the class type `clazz[args]', where `clazz' is * a top-level or static class. */ def classType[T](clazz: Predef.Class[_], args: Manifest[_]*): Manifest[T] = - new Manifest[T] with java.io.Serializable { + new (Manifest[T] @serializable) { val erasure = clazz val typeArguments: Seq[Manifest[_]] = args - override lazy val toString = erasure.getName + typeArguments.mkString("[", ", ", "]") + override def <:<(that: Manifest[_]): Boolean = { + try { + val meth = that.getClass().getMethod("typeArguments", null) + val args1 = meth.invoke(that, null).asInstanceOf[Array[Manifest[_]]] + super.<:<(that) && args.equalsWith(args1)((x, y) => x <:< y) + } catch { + case _ => false + } + } + override lazy val toString = + (if (erasure.isArray) "Array" else erasure.getName) + + typeArguments.mkString("[", ", ", "]") } /** Manifest for the class type `prefix # clazz'. */ def classType[T](prefix: Manifest[_], clazz: Predef.Class[_]): Manifest[T] = - new Manifest[T] with java.io.Serializable { + new (Manifest[T] @serializable) { val erasure = clazz override lazy val toString = prefix.toString + "#" + erasure.getName } /** Manifest for the class type `prefix # clazz[args]'. */ def classType[T](prefix: Manifest[_], clazz: Predef.Class[_], args: Manifest[_]*): Manifest[T] = - new Manifest[T] with java.io.Serializable { + new (Manifest[T] @serializable) { val erasure = clazz val typeArguments: Seq[Manifest[_]] = args - override lazy val toString = prefix.toString + "#" + erasure.getName + typeArguments.mkString("[", ", ", "]") + override lazy val toString = + prefix.toString + "#" + erasure.getName + typeArguments.mkString("[", ", ", "]") } /** 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[_]): Manifest[T] = - new Manifest[T] with java.io.Serializable { + new (Manifest[T] @serializable) { lazy val erasure = upperBound.erasure override lazy val toString = prefix.toString + "#" + name } /** Manifest for the abstract type `prefix # name[args]'. */ def abstractType[T](prefix: Manifest[_], name: String, upperBound: Manifest[_], args: Manifest[_]*): Manifest[T] = - new Manifest[T] with java.io.Serializable { + new (Manifest[T] @serializable) { lazy val erasure = upperBound.erasure val typeArguments: Seq[Manifest[_]] = args - override lazy val toString = prefix.toString + "#" + name + typeArguments.mkString("[", ", ", "]") + override lazy val toString = + prefix.toString + "#" + name + typeArguments.mkString("[", ", ", "]") } /** Manifest for the intersection type `parents_0 with ... with parents_n'. */ def intersectionType[T](parents: Manifest[_]*): Manifest[T] = - new Manifest[T] with java.io.Serializable { + new (Manifest[T] @serializable) { lazy val erasure = parents.first.erasure override lazy val toString = parents.mkString(" with ") } diff --git a/src/library/scala/util/Marshal.scala b/src/library/scala/util/Marshal.scala new file mode 100644 index 0000000000..9875a37c2a --- /dev/null +++ b/src/library/scala/util/Marshal.scala @@ -0,0 +1,44 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2008-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: $ + + +package scala.util + +/** + * Marshalling of Scala objects using Scala manifests. + * + * @author Stephane Micheloud + * @version 1.0 + */ +object Marshal { + import java.io._ + import scala.reflect.Manifest + + def dump[A](o: A)(implicit m: Manifest[A]): Array[Byte] = { + val ba = new ByteArrayOutputStream(512) + val out = new ObjectOutputStream(ba) + out.writeObject(m) + out.writeObject(o) + out.close() + ba.toByteArray() + } + + @throws(classOf[ClassCastException]) + def load[A](buffer: Array[Byte])(implicit expected: Manifest[A]): A = { + val in = new ObjectInputStream(new ByteArrayInputStream(buffer)) + val found = in.readObject.asInstanceOf[Manifest[_]] + if (! (found <:< expected)) + throw new ClassCastException("type mismatch;"+ + "\n found : "+found+ + "\n required: "+expected) + in.readObject.asInstanceOf[A] + } + +} diff --git a/test/files/jvm/manifests.check b/test/files/jvm/manifests.check index 995fb5f1e6..2539cd956b 100644 --- a/test/files/jvm/manifests.check +++ b/test/files/jvm/manifests.check @@ -3,23 +3,57 @@ x=true, m=boolean x=a, m=char x=1, m=int x=abc, m=java.lang.String +x='abc, m=scala.Symbol + x=List(()), m=scala.List[void] x=List(true), m=scala.List[boolean] x=List(1), m=scala.List[int] x=List(abc), m=scala.List[java.lang.String] -x=[Z, m=[Z[boolean] -x=[C, m=[C[char] -x=[I, m=[I[int] -x=Array(abc), m=[Ljava.lang.String;[java.lang.String] +x=List('abc), m=scala.List[scala.Symbol] + +x=[Z, m=Array[boolean] +x=[C, m=Array[char] +x=[I, m=Array[int] +x=Array(abc), m=Array[java.lang.String] +x=Array('abc), m=Array[scala.Symbol] + x=((),()), m=scala.Tuple2[void, void] x=(true,false), m=scala.Tuple2[boolean, boolean] x=(1,2), m=scala.Tuple2[int, int] x=(abc,xyz), m=scala.Tuple2[java.lang.String, java.lang.String] -x=Serialize$, m=Serialize$ +x=('abc,'xyz), m=scala.Tuple2[scala.Symbol, scala.Symbol] + x=Test$, m=Test$ x=scala.List$, m=scala.List$ -x=Test$Foo, m=Test$Foo[int] -x=Test$Foo, m=Test$Foo[scala.List[int]] -x=Test$Foo, m=Test$Foo[Test$Foo[int]] -x=Test$Foo, m=Test$Foo[scala.List[Test$Foo[int]]] -x=Test$$anon$1, m=Test$$anon$1 + +x=Foo, m=Foo[int] +x=Foo, m=Foo[scala.List[int]] +x=Foo, m=Foo[Foo[int]] +x=Foo, m=Foo[scala.List[Foo[int]]] + +x=Test1$$anon$1, m=Test1$$anon$1 + +()=() +true=true +a=a +1=1 +'abc='abc + +List(())=List(()) +List(true)=List(true) +List('abc)=List('abc) + +Array()=Array() +Array(true)=Array(true) +Array(a)=Array(a) +Array(1)=Array(1) + +((),())=((),()) +(true,false)=(true,false) + +List(List(1), List(2))=List(List(1), List(2)) + +Array(Array(1), Array(2))=Array(Array(1), Array(2)) + +x=char, m=scala.reflect.Manifest[char] + diff --git a/test/files/jvm/manifests.scala b/test/files/jvm/manifests.scala index 61c5152283..a240278eaa 100644 --- a/test/files/jvm/manifests.scala +++ b/test/files/jvm/manifests.scala @@ -1,50 +1,100 @@ object Test extends Application { - import scala.reflect._ + Test1 + Test2 + Test3 +} - def manifestOf[T](implicit m: Manifest[T]): Manifest[T] = m +class Foo[T](x: T) +trait Bar[T] { def f: T } - def print[T](x: T)(implicit m: Manifest[T]) { - val m1: Manifest[T] = Serialize.read(Serialize.write(m)) - val x1 = x.toString.replaceAll("@[0-9a-z]+$", "") - println("x="+x1+", m="+m1) - } +object Test1 extends TestUtil { print(()) print(true) print('a') print(1) print("abc") + print('abc) + println() print(List(())) print(List(true)) print(List(1)) print(List("abc")) + print(List('abc)) + println() //print(Array(())) //Illegal class name "[V" in class file Test$ print(Array(true)) print(Array('a')) print(Array(1)) print(Array("abc")) + print(Array('abc)) + println() print(((), ())) print((true, false)) print((1, 2)) print(("abc", "xyz")) + print(('abc, 'xyz)) + println() - print(Serialize) print(Test) print(List) + println() - class Foo[T](x: T) print(new Foo(2)) print(new Foo(List(2))) print(new Foo(new Foo(2))) print(new Foo(List(new Foo(2)))) + println() - trait Bar[T] { def f: T } print(new Bar[String] { def f = "abc" }) + println() } -object Serialize { +object Test2 { + import scala.util.Marshal._ + println("()="+load[Unit](dump(()))) + println("true="+load[Boolean](dump(true))) + println("a="+load[Char](dump('a'))) + println("1="+load[Int](dump(1))) + println("'abc="+load[Symbol](dump('abc))) + println() + + println("List(())="+load[List[Unit]](dump(List(())))) + println("List(true)="+load[List[Boolean]](dump(List(true)))) + println("List('abc)="+load[List[Symbol]](dump(List('abc)))) + println() + + def loadArray[T](x: Array[Byte])(implicit m: reflect.Manifest[Array[T]]) = + load[Array[T]](x)(m).deepToString + println("Array()="+loadArray[Int](dump(Array(): Array[Int]))) + println("Array(true)="+loadArray[Boolean](dump(Array(true)))) + println("Array(a)="+loadArray[Char](dump(Array('a')))) + println("Array(1)="+loadArray[Int](dump(Array(1)))) + println() + + println("((),())="+load[(Unit, Unit)](dump(((), ())))) + println("(true,false)="+load[(Boolean, Boolean)](dump((true, false)))) + println() + + println("List(List(1), List(2))="+load[List[List[Int]]](dump(List(List(1), List(2))))) + println() + + println("Array(Array(1), Array(2))="+loadArray[Array[Int]](dump(Array(Array(1), Array(2))))) + println() +} + +object Test3 extends TestUtil { + import scala.reflect.Manifest._ + val ct1 = classType(classOf[Char]) + val ct2 = classType(classOf[List[_]], ct1) + print(ct1) + //print(ct2) // ??? x=scala.List[char], m=scala.reflect.Manifest[scala.runtime.Nothing$] + println() +} + +trait TestUtil { import java.io._ def write[A](o: A): Array[Byte] = { val ba = new ByteArrayOutputStream(512) @@ -57,5 +107,10 @@ object Serialize { val in = new ObjectInputStream(new ByteArrayInputStream(buffer)) in.readObject().asInstanceOf[A] } + import scala.reflect._ + def print[T](x: T)(implicit m: Manifest[T]) { + val m1: Manifest[T] = read(write(m)) + val x1 = x.toString.replaceAll("@[0-9a-z]+$", "") + println("x="+x1+", m="+m1) + } } - |