summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/ast/NodePrinters.scala16
-rw-r--r--src/library/scala/reflect/Manifest.scala40
-rw-r--r--src/library/scala/util/Marshal.scala44
-rw-r--r--test/files/jvm/manifests.check54
-rw-r--r--test/files/jvm/manifests.scala79
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)
+ }
}
-