summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/reflect/internal/AnnotationInfos.scala1
-rw-r--r--src/compiler/scala/reflect/internal/ByteCodecs.scala216
-rw-r--r--src/compiler/scala/reflect/internal/Definitions.scala3
-rw-r--r--src/compiler/scala/reflect/internal/Phase.scala5
-rw-r--r--src/compiler/scala/reflect/internal/SymbolTable.scala2
-rw-r--r--src/compiler/scala/reflect/internal/pickling/ByteCodecs.scala3
-rw-r--r--src/compiler/scala/reflect/runtime/JavaConversions.scala196
-rw-r--r--src/compiler/scala/reflect/runtime/Loaders.scala87
-rw-r--r--src/compiler/scala/reflect/runtime/Settings.scala4
-rw-r--r--src/compiler/scala/reflect/runtime/Universe.scala41
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala3
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/package.scala7
-rw-r--r--src/scalap/scala/tools/scalap/Decode.scala2
-rw-r--r--src/scalap/scala/tools/scalap/scalax/rules/scalasig/ScalaSig.scala2
-rw-r--r--test/files/run/bytecodecs.scala2
15 files changed, 283 insertions, 291 deletions
diff --git a/src/compiler/scala/reflect/internal/AnnotationInfos.scala b/src/compiler/scala/reflect/internal/AnnotationInfos.scala
index 7f78d3a470..62b27c2daf 100644
--- a/src/compiler/scala/reflect/internal/AnnotationInfos.scala
+++ b/src/compiler/scala/reflect/internal/AnnotationInfos.scala
@@ -7,6 +7,7 @@ package scala.reflect
package internal
import util._
+import pickling.ByteCodecs
/** AnnotationInfo and its helpers */
trait AnnotationInfos extends api.AnnotationInfos { self: SymbolTable =>
diff --git a/src/compiler/scala/reflect/internal/ByteCodecs.scala b/src/compiler/scala/reflect/internal/ByteCodecs.scala
deleted file mode 100644
index 8b0fc9300a..0000000000
--- a/src/compiler/scala/reflect/internal/ByteCodecs.scala
+++ /dev/null
@@ -1,216 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2007-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-package scala.reflect.internal
-
-object ByteCodecs {
-
- def avoidZero(src: Array[Byte]): Array[Byte] = {
- var i = 0
- val srclen = src.length
- var count = 0
- while (i < srclen) {
- if (src(i) == 0x7f) count += 1
- i += 1
- }
- val dst = new Array[Byte](srclen + count)
- i = 0
- var j = 0
- while (i < srclen) {
- val in = src(i)
- if (in == 0x7f) {
- dst(j) = (0xc0).toByte
- dst(j + 1) = (0x80).toByte
- j += 2
- } else {
- dst(j) = (in + 1).toByte
- j += 1
- }
- i += 1
- }
- dst
- }
-
- def regenerateZero(src: Array[Byte]): Int = {
- var i = 0
- val srclen = src.length
- var j = 0
- while (i < srclen) {
- val in: Int = src(i) & 0xff
- if (in == 0xc0 && (src(i + 1) & 0xff) == 0x80) {
- src(j) = 0x7f
- i += 2
- } else {
- src(j) = (in - 1).toByte
- i += 1
- }
- j += 1
- }
- j
- }
-
- def encode8to7(src: Array[Byte]): Array[Byte] = {
- val srclen = src.length
- val dstlen = (srclen * 8 + 6) / 7
- val dst = new Array[Byte](dstlen)
- var i = 0
- var j = 0
- while (i + 6 < srclen) {
- var in: Int = src(i) & 0xff
- dst(j) = (in & 0x7f).toByte
- var out: Int = in >>> 7
- in = src(i + 1) & 0xff
- dst(j + 1) = (out | (in << 1) & 0x7f).toByte
- out = in >>> 6
- in = src(i + 2) & 0xff
- dst(j + 2) = (out | (in << 2) & 0x7f).toByte
- out = in >>> 5
- in = src(i + 3) & 0xff
- dst(j + 3) = (out | (in << 3) & 0x7f).toByte
- out = in >>> 4
- in = src(i + 4) & 0xff
- dst(j + 4) = (out | (in << 4) & 0x7f).toByte
- out = in >>> 3
- in = src(i + 5) & 0xff
- dst(j + 5) = (out | (in << 5) & 0x7f).toByte
- out = in >>> 2
- in = src(i + 6) & 0xff
- dst(j + 6) = (out | (in << 6) & 0x7f).toByte
- out = in >>> 1
- dst(j + 7) = out.toByte
- i += 7
- j += 8
- }
- if (i < srclen) {
- var in: Int = src(i) & 0xff
- dst(j) = (in & 0x7f).toByte; j += 1
- var out: Int = in >>> 7
- if (i + 1 < srclen) {
- in = src(i + 1) & 0xff
- dst(j) = (out | (in << 1) & 0x7f).toByte; j += 1
- out = in >>> 6
- if (i + 2 < srclen) {
- in = src(i + 2) & 0xff
- dst(j) = (out | (in << 2) & 0x7f).toByte; j += 1
- out = in >>> 5
- if (i + 3 < srclen) {
- in = src(i + 3) & 0xff
- dst(j) = (out | (in << 3) & 0x7f).toByte; j += 1
- out = in >>> 4
- if (i + 4 < srclen) {
- in = src(i + 4) & 0xff
- dst(j) = (out | (in << 4) & 0x7f).toByte; j += 1
- out = in >>> 3
- if (i + 5 < srclen) {
- in = src(i + 5) & 0xff
- dst(j) = (out | (in << 5) & 0x7f).toByte; j += 1
- out = in >>> 2
- }
- }
- }
- }
- }
- if (j < dstlen) dst(j) = out.toByte
- }
- dst
- }
-
- @deprecated("use 2-argument version instead", "2.8.0")
- def decode7to8(src: Array[Byte], srclen: Int, dstlen: Int) { decode7to8(src, srclen) }
-
- def decode7to8(src: Array[Byte], srclen: Int): Int = {
- var i = 0
- var j = 0
- val dstlen = (srclen * 7 + 7) / 8
- while (i + 7 < srclen) {
- var out: Int = src(i)
- var in: Byte = src(i + 1)
- src(j) = (out | (in & 0x01) << 7).toByte
- out = in >>> 1
- in = src(i + 2)
- src(j + 1) = (out | (in & 0x03) << 6).toByte
- out = in >>> 2
- in = src(i + 3)
- src(j + 2) = (out | (in & 0x07) << 5).toByte
- out = in >>> 3
- in = src(i + 4)
- src(j + 3) = (out | (in & 0x0f) << 4).toByte
- out = in >>> 4
- in = src(i + 5)
- src(j + 4) = (out | (in & 0x1f) << 3).toByte
- out = in >>> 5
- in = src(i + 6)
- src(j + 5) = (out | (in & 0x3f) << 2).toByte
- out = in >>> 6
- in = src(i + 7)
- src(j + 6) = (out | in << 1).toByte
- i += 8
- j += 7
- }
- if (i < srclen) {
- var out: Int = src(i)
- if (i + 1 < srclen) {
- var in: Byte = src(i + 1)
- src(j) = (out | (in & 0x01) << 7).toByte; j += 1
- out = in >>> 1
- if (i + 2 < srclen) {
- in = src(i + 2)
- src(j) = (out | (in & 0x03) << 6).toByte; j += 1
- out = in >>> 2
- if (i + 3 < srclen) {
- in = src(i + 3)
- src(j) = (out | (in & 0x07) << 5).toByte; j += 1
- out = in >>> 3
- if (i + 4 < srclen) {
- in = src(i + 4)
- src(j) = (out | (in & 0x0f) << 4).toByte; j += 1
- out = in >>> 4
- if (i + 5 < srclen) {
- in = src(i + 5)
- src(j) = (out | (in & 0x1f) << 3).toByte; j += 1
- out = in >>> 5
- if (i + 6 < srclen) {
- in = src(i + 6)
- src(j) = (out | (in & 0x3f) << 2).toByte; j += 1
- out = in >>> 6
- }
- }
- }
- }
- }
- }
- if (j < dstlen) src(j) = out.toByte
- }
- dstlen
- }
-
- def encode(xs: Array[Byte]): Array[Byte] = avoidZero(encode8to7(xs))
-
- @deprecated("use 1-argument version instead", "2.8.0")
- def decode(xs: Array[Byte], dstlen: Int) { decode(xs) }
-
- /**
- * Destructively decodes array xs and returns the length of the decoded array.
- *
- * Sometimes returns (length+1) of the decoded array. Example:
- *
- * scala> val enc = reflect.generic.ByteCodecs.encode(Array(1,2,3))
- * enc: Array[Byte] = Array(2, 5, 13, 1)
- *
- * scala> reflect.generic.ByteCodecs.decode(enc)
- * res43: Int = 4
- *
- * scala> enc
- * res44: Array[Byte] = Array(1, 2, 3, 0)
- *
- * However, this does not always happen.
- */
- def decode(xs: Array[Byte]): Int = {
- val len = regenerateZero(xs)
- decode7to8(xs, len)
- }
-}
diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala
index 500a5cb428..314fe1ed82 100644
--- a/src/compiler/scala/reflect/internal/Definitions.scala
+++ b/src/compiler/scala/reflect/internal/Definitions.scala
@@ -647,6 +647,8 @@ trait Definitions extends reflect.api.StandardDefinitions {
var j = fullname.pos('.', i)
while (j < fullname.length) {
sym = sym.info.member(fullname.subName(i, j))
+ // if (sym == NoSymbol)
+ // println("no member "+fullname.subName(i, j)+" found in "+sym0+sym0.info.getClass+" "+sym0.info.typeSymbol.info.getClass)
i = j + 1
j = fullname.pos('.', i)
}
@@ -654,6 +656,7 @@ trait Definitions extends reflect.api.StandardDefinitions {
if (module) sym.info.member(fullname.subName(i, j)).suchThat(_ hasFlag MODULE)
else sym.info.member(fullname.subName(i, j).toTypeName)
if (result == NoSymbol) {
+ // println("no member "+fullname.subName(i, j)+" found in "+sym+" "+module)
if (settings.debug.value)
{ log(sym.info); log(sym.info.members) }//debug
throw new MissingRequirementError((if (module) "object " else "class ") + fullname)
diff --git a/src/compiler/scala/reflect/internal/Phase.scala b/src/compiler/scala/reflect/internal/Phase.scala
index f65af1eaae..996fd423d0 100644
--- a/src/compiler/scala/reflect/internal/Phase.scala
+++ b/src/compiler/scala/reflect/internal/Phase.scala
@@ -51,3 +51,8 @@ object NoPhase extends Phase(null) {
def name = "<no phase>"
def run() { throw new Error("NoPhase.run") }
}
+
+object SomePhase extends Phase(NoPhase) {
+ def name = "<some phase>"
+ def run() { throw new Error("SomePhase.run") }
+}
diff --git a/src/compiler/scala/reflect/internal/SymbolTable.scala b/src/compiler/scala/reflect/internal/SymbolTable.scala
index 32fa88ac15..81c4cef4d4 100644
--- a/src/compiler/scala/reflect/internal/SymbolTable.scala
+++ b/src/compiler/scala/reflect/internal/SymbolTable.scala
@@ -50,7 +50,7 @@ abstract class SymbolTable extends api.Universe
final val NoRunId = 0
private var ph: Phase = NoPhase
- protected var per = NoPeriod
+ private var per = NoPeriod
final def phase: Phase = ph
diff --git a/src/compiler/scala/reflect/internal/pickling/ByteCodecs.scala b/src/compiler/scala/reflect/internal/pickling/ByteCodecs.scala
index 0a02d09a71..1add69ddd4 100644
--- a/src/compiler/scala/reflect/internal/pickling/ByteCodecs.scala
+++ b/src/compiler/scala/reflect/internal/pickling/ByteCodecs.scala
@@ -44,6 +44,9 @@ object ByteCodecs {
if (in == 0xc0 && (src(i + 1) & 0xff) == 0x80) {
src(j) = 0x7f
i += 2
+ } else if (in == 0) {
+ src(j) = 0x7f
+ i += 1
} else {
src(j) = (in - 1).toByte
i += 1
diff --git a/src/compiler/scala/reflect/runtime/JavaConversions.scala b/src/compiler/scala/reflect/runtime/JavaConversions.scala
index b724292836..2ba648cec5 100644
--- a/src/compiler/scala/reflect/runtime/JavaConversions.scala
+++ b/src/compiler/scala/reflect/runtime/JavaConversions.scala
@@ -5,10 +5,10 @@ import java.lang.{Class => jClass, Package => jPackage}
import java.lang.reflect.{
Method => jMethod, Constructor => jConstructor, Modifier => jModifier, Field => jField,
Member => jMember, Type => jType, GenericDeclaration}
-import internal.ByteCodecs
+import internal.pickling.ByteCodecs
import internal.ClassfileConstants._
import internal.pickling.UnPickler
-import scala.collection.{ mutable, immutable }
+import collection.mutable.HashMap
trait JavaConversions { self: Universe =>
@@ -16,9 +16,12 @@ trait JavaConversions { self: Universe =>
val global: JavaConversions.this.type = self
}
- class TwoWayCache[J, S] {
- val toScalaMap = mutable.HashMap[J, S]()
- val toJavaMap = mutable.HashMap[S, J]()
+ /** A cache that maintains a bijection between Java reflection type `J`
+ * and Scala reflection type `S`.
+ */
+ private class TwoWayCache[J, S] {
+ private val toScalaMap = new HashMap[J, S]
+ private val toJavaMap = new HashMap[S, J]
def toScala(key: J)(body: => S) = toScalaMap.getOrElseUpdate(key, body)
def toJava(key: S)(body: => J) = toJavaMap.getOrElseUpdate(key, body)
@@ -30,27 +33,63 @@ trait JavaConversions { self: Universe =>
private val constructorCache = new TwoWayCache[jConstructor[_], Symbol]
private val fieldCache = new TwoWayCache[jField, Symbol]
- private def createClassModule(owner: Symbol, name: TypeName) = {
- val clazz = owner.newClass(NoPosition, name)
- val module = owner.newModule(NoPosition, name)
- if (owner.isClass) {
- owner.info.decls enter clazz
- owner.info.decls enter module
+ /** Generate types for top-level Scala root class and root companion object
+ * from the pickled information stored in a corresponding Java class
+ * @param clazz The top-level Scala class for which info is unpickled
+ * @param module The top-level Scala companion object for which info is unpickled
+ * @param jclazz The Java class which contains the unpickled information in a
+ * ScalaSignature or ScalaLongSignature annotation.
+ */
+ def unpickleClass(clazz: Symbol, module: Symbol, jclazz: jClass[_]): Unit = {
+ println("unpickling "+clazz+" "+module)
+ val ssig = jclazz.getAnnotation(classOf[scala.reflect.ScalaSignature])
+ if (ssig != null) {
+ val bytes = ssig.bytes.getBytes
+ val len = ByteCodecs.decode(bytes)
+ unpickler.unpickle(bytes take len, 0, clazz, module, jclazz.getName)
+ } else {
+ val slsig = jclazz.getAnnotation(classOf[scala.reflect.ScalaLongSignature])
+ if (slsig != null) {
+ val byteSegments = slsig.bytes map (_.getBytes)
+ val lens = byteSegments map ByteCodecs.decode
+ val bytes = Array.ofDim[Byte](lens.sum)
+ var len = 0
+ for ((bs, l) <- byteSegments zip lens) {
+ bs.copyToArray(bytes, len, l)
+ len += l
+ }
+ println("long sig")
+ unpickler.unpickle(bytes, 0, clazz, module, jclazz.getName)
+ } else { // class does not have a Scala signature; it's a Java class
+ println("no sig found for "+jclazz)
+ copyMembers(clazz, module, jclazz)
+ }
}
- (clazz, module)
}
- private def unpickleClass(jclazz: jClass[_], bytes: Array[Byte], len: Int): ClassSymbol = {
- val (clazz, module) = createClassModule(sOwner(jclazz), newTypeName(jclazz.getSimpleName))
- unpickler.unpickle(bytes, 0, clazz, module, jclazz.getName)
- println("found: "+len+" bytes from "+bytes.deep)
- clazz
+ /** Generate types for top-level Scala root class and root companion object
+ * by copying corresponding types from a Java class. This method used
+ * to reflect classes in Scala that do not have a Scala pickle info, be it
+ * because they are local classes or have been compiled from Java sources.
+ * @param clazz The top-level Scala class for which info is copied
+ * @param module The top-level Scala companion object for which info is copied
+ * @param jclazz The Java class
+ */
+ def copyMembers(clazz: Symbol, module: Symbol, jclazz: jClass[_]) {
+ clazz setInfo new ClassInfoType(List(), newScope, clazz)
+ module.moduleClass setInfo new ClassInfoType(List(), newScope, module.moduleClass)
+ module setInfo module.moduleClass.tpe
}
- def followStatic(clazz: Symbol, mods: Int) =
+ /** If Java modifiers `mods` contain STATIC, return the module class
+ * of the companion module of `clazz`, otherwise the class `clazz` itself.
+ */
+ private def followStatic(clazz: Symbol, mods: Int) =
if (jModifier.isStatic(mods)) clazz.companionModule.moduleClass else clazz
- def sOwner(jclazz: jClass[_]): Symbol = {
+ /** The Scala owner of the Scala class corresponding to the Java class `jclazz`
+ */
+ private def sOwner(jclazz: jClass[_]): Symbol = {
if (jclazz.isMemberClass)
followStatic(classToScala(jclazz.getEnclosingClass), jclazz.getModifiers)
else if (jclazz.isLocalClass)
@@ -59,11 +98,18 @@ trait JavaConversions { self: Universe =>
packageToScala(jclazz.getPackage)
}
- def sOwner(jmember: jMember): Symbol = {
+ /** The Scala owner of the Scala symbol corresponding to the Java member `jmember`
+ */
+ private def sOwner(jmember: jMember): Symbol = {
followStatic(classToScala(jmember.getDeclaringClass), jmember.getModifiers)
}
- def lookup(clazz: Symbol, jname: String): Symbol =
+ /** Find declarations or definition in class `clazz` that maps to a Java
+ * entity with name `jname`. Because of name-mangling, this is more difficult
+ * than a simple name-based lookup via `decl`. If `decl` fails, members
+ * that start with the given name are searched instead.
+ */
+ private def lookup(clazz: Symbol, jname: String): Symbol =
clazz.info.decl(newTermName(jname)) orElse {
(clazz.info.decls.iterator filter (_.name.toString startsWith jname)).toList match {
case List() => NoSymbol
@@ -72,82 +118,128 @@ trait JavaConversions { self: Universe =>
}
}
- def erasesTo(meth: Symbol, jmeth: jMethod): Boolean = true
- def erasesTo(meth: Symbol, jconstr: jConstructor[_]): Boolean = true
-
+ /** Does method `meth` erase to Java method `jmeth`?
+ * This is true if the Java method type is the same as the Scala method type after performing
+ * all Scala-specific transformations in InfoTransformers. (to be done)
+ */
+ def erasesTo(meth: Symbol, jmeth: jMethod): Boolean = true //to do: implement
+
+ /** Does constructor `meth` erase to Java method `jconstr`?
+ * This is true if the Java constructor type is the same as the Scala constructor type after performing
+ * all Scala-specific transformations in InfoTransformers. (to be done)
+ */
+ def erasesTo(meth: Symbol, jconstr: jConstructor[_]): Boolean = true // to do: implement
+
+ /** The Scala method corresponding to given Java method.
+ * @param jmeth The Java method
+ * @return A Scala method object that corresponds to `jmeth`.
+ */
def methodToScala(jmeth: jMethod): Symbol = methodCache.toScala(jmeth) {
val owner = followStatic(classToScala(jmeth.getDeclaringClass), jmeth.getModifiers)
lookup(owner, jmeth.getName) suchThat (erasesTo(_, jmeth)) orElse jmethodAsScala(jmeth)
}
+ /** The Scala constructor corresponding to given Java constructor.
+ * @param jconstr The Java constructor
+ * @return A Scala method object that corresponds to `jconstr`.
+ */
def constrToScala(jconstr: jConstructor[_]): Symbol = constructorCache.toScala(jconstr) {
val owner = followStatic(classToScala(jconstr.getDeclaringClass), jconstr.getModifiers)
lookup(owner, "<init>") suchThat (erasesTo(_, jconstr)) orElse jconstrAsScala(jconstr)
}
+ /** The Scala package corresponding to given Java package
+ */
def packageToScala(jpkg: jPackage): Symbol = packageCache.toScala(jpkg) {
makeScalaPackage(jpkg.getName)
}
+ /** The Scala package with given fully qualified name.
+ */
def packageNameToScala(fullname: String): Symbol = {
val jpkg = jPackage.getPackage(fullname)
if (jpkg != null) packageToScala(jpkg) else makeScalaPackage(fullname)
}
+ /** The Scala package with given fully qualified name. Unlike `packageNameToScala`,
+ * this one bypasses the cache.
+ */
private def makeScalaPackage(fullname: String): Symbol = {
val split = fullname lastIndexOf '.'
val owner = if (split > 0) packageNameToScala(fullname take split) else definitions.RootClass
+ assert(owner.isModuleClass)
val name = fullname drop (split + 1)
- val pkg = owner.newPackage(NoPosition, newTermName(name))
- pkg.moduleClass setInfo new ClassInfoType(List(), new Scope, pkg)
- pkg setInfo pkg.moduleClass.tpe
+ val pkg = owner.info decl newTermName(name)
pkg.moduleClass
}
+ /** The Scala class that corresponds to a given Java class.
+ * @param jclazz The Java class
+ * @return A Scala class symbol that reflects all elements of the Java class,
+ * in the form they appear in the Scala pickling info, or, if that is
+ * not available, wrapped from the Java reflection info.
+ */
def classToScala(jclazz: jClass[_]): Symbol = classCache.toScala(jclazz) {
if (jclazz.isMemberClass) {
sOwner(jclazz).info.decl(newTypeName(jclazz.getSimpleName)).asInstanceOf[ClassSymbol]
} else if (jclazz.isLocalClass) { // local classes not preserved by unpickling - treat as Java
jclassAsScala(jclazz)
} else { // jclazz is top-level - get signature
- val ssig = jclazz.getAnnotation(classOf[scala.reflect.ScalaSignature])
- if (ssig != null) {
- val bytes = ssig.bytes.getBytes
- val len = ByteCodecs.decode(bytes)
- unpickleClass(jclazz, bytes, len)
- } else {
- val slsig = jclazz.getAnnotation(classOf[scala.reflect.ScalaLongSignature])
- if (slsig != null) {
- val byteSegments = slsig.bytes map (_.getBytes)
- val lens = byteSegments map ByteCodecs.decode
- val bytes = Array.ofDim[Byte](lens.sum)
- var len = 0
- for ((bs, l) <- byteSegments zip lens) {
- bs.copyToArray(bytes, len, l)
- len += l
- }
- unpickleClass(jclazz, bytes, len)
- } else { // class does not have a Scala signature; it's a Java class
- jclassAsScala(jclazz)
- }
- }
+ val (clazz, module) = createClassModule(sOwner(jclazz), newTypeName(jclazz.getSimpleName))
+ clazz
}
}
+ /** The Scala type that corresponds to given Java type (to be done)
+ */
def typeToScala(tpe: jType): Type = NoType
- def jclassAsScala(jclazz: jClass[_]): Symbol = {
+ /** The Scala class that corresponds to given Java class without taking
+ * Scala pickling info into account.
+ * @param jclazz The Java class
+ * @return A Scala class symbol that wraps all reflection info of `jclazz`
+ */
+ private def jclassAsScala(jclazz: jClass[_]): Symbol = {
val (clazz, module) = createClassModule(sOwner(jclazz), newTypeName(jclazz.getSimpleName))
// fill in clazz, module from jclazz
+ copyMembers(clazz, module, jclazz)
clazz
}
- def jfieldAsScala(jfield: jField): Symbol = fieldCache.toScala(jfield) {
+ /** The Scala field that corresponds to given Java field without taking
+ * Scala pickling info into account.
+ * @param jfield The Java field
+ * @return A Scala value symbol that wraps all reflection info of `jfield`
+ */
+ private def jfieldAsScala(jfield: jField): Symbol = fieldCache.toScala(jfield) {
sOwner(jfield).newValue(NoPosition, newTermName(jfield.getName))
.setFlag(toScalaFlags(jfield.getModifiers, isClass = false))
.setInfo(typeToScala(jfield.getGenericType))
+ // todo: copy annotations
}
- def jmethodAsScala(jmeth: jMethod): Symbol = NoSymbol
- def jconstrAsScala(jconstr: jConstructor[_]): Symbol = NoSymbol
+ /** The Scala method that corresponds to given Java method without taking
+ * Scala pickling info into account.
+ * @param jmeth The Java method
+ * @return A Scala method symbol that wraps all reflection info of `jmethod`
+ */
+ private def jmethodAsScala(jmeth: jMethod): Symbol = NoSymbol // to be done
+
+ /** The Scala constructor that corresponds to given Java constructor without taking
+ * Scala pickling info into account.
+ * @param jconstr The Java constructor
+ * @return A Scala constructor symbol that wraps all reflection info of `jconstr`
+ */
+ private def jconstrAsScala(jconstr: jConstructor[_]): Symbol = NoSymbol // to be done
+
+ // to be done:
+
+ def packageToJava(pkg: Symbol): jPackage = null // to be done
+
+ /** The Java class corresponding to given Scala class
+ */
+ def classToJava(clazz: Symbol): jClass[_] = null // to be done
+ def fieldToJava(fld: Symbol): jField = null // to be done
+ def methodToJava(meth: Symbol): jMethod = null // to be done
+ def constrToJava(constr: Symbol): jConstructor[_] = null // to be done
} \ No newline at end of file
diff --git a/src/compiler/scala/reflect/runtime/Loaders.scala b/src/compiler/scala/reflect/runtime/Loaders.scala
new file mode 100644
index 0000000000..cd608cd471
--- /dev/null
+++ b/src/compiler/scala/reflect/runtime/Loaders.scala
@@ -0,0 +1,87 @@
+package scala.reflect
+package runtime
+
+import java.lang.{Class => jClass, Package => jPackage}
+
+trait Loaders { self: Universe =>
+
+ /** The lazy type for root.
+ */
+ override val rootLoader = new LazyType {
+ override def complete(sym: Symbol) = sym setInfo new PackageType(definitions.RootClass)
+ }
+
+ /** The standard completer for top-level classes
+ * @param clazz The top-level class
+ * @param module The companion object of `clazz`
+ * Calling `complete` on this type will assign the infos of `clazz` and `module`
+ * by unpickling information from the corresponding Java class. If no Java class
+ * is found, a package is created instead.
+ */
+ class TopClassCompleter(clazz: Symbol, module: Symbol) extends LazyType {
+ def makePackage() {
+ val ptpe = new PackageType(module.moduleClass)
+ clazz setInfo ptpe
+ module setInfo ptpe
+ module.moduleClass setInfo ptpe
+ }
+ override def complete(sym: Symbol) = {
+ println("completing "+sym+"/"+clazz.fullName)
+ assert(sym == clazz || sym == module || sym == module.moduleClass)
+ try {
+ unpickleClass(clazz, module, jClass.forName(clazz.fullName))
+ } catch {
+ case ex: ClassNotFoundException => makePackage()
+ case ex: NoClassDefFoundError => makePackage()
+ // Note: We catch NoClassDefFoundError because there are situations
+ // where a package and a class have the same name except for capitalization.
+ // It seems in this case the class is loaded even if capitalization differs
+ // but then a NoClassDefFound error is issued with a ("wrong name: ...")
+ // reason. (I guess this is a concession to Windows).
+ // The present behavior is a bit too forgiving, in that it masks
+ // all class loade errors, not just wrong name errors. We should try
+ // to be more discriminating. To get on the right track simply delete
+ // the clause above and load a collection class such as collection.Iterable.
+ // You'll see an error that class `parallel` has the wrong name.
+ }
+ }
+ }
+
+ /** Create a class and a companion object, enter in enclosing scope,
+ * and initialize with a lazy type completer.
+ * @param owner The owner of the newly created class and object
+ * @param name The simple name of the newly created class
+ */
+ protected def createClassModule(owner: Symbol, name: TypeName) = {
+ val clazz = owner.newClass(NoPosition, name)
+ val module = owner.newModule(NoPosition, name.toTermName)
+ owner.info.decls enter clazz
+ owner.info.decls enter module
+ val classCompleter = new TopClassCompleter(clazz, module)
+ clazz.setInfo(classCompleter)
+ module.setInfo(classCompleter)
+ module.moduleClass.setInfo(classCompleter)
+ (clazz, module)
+ }
+
+ /** The type for packages.
+ * Since we cannot search the file system for classes in directories to populate
+ * a package, we do the following instead: For every member that is looked up in
+ * the package, create a class and companion object optimistically, giving it
+ * a TopClassCompleter type. When any of the two symbols is forced via info,
+ * the TopClassCompleter will sort things out.
+ */
+ class PackageType(pkg: Symbol) extends ClassInfoType(List(), newScope, pkg) {
+ override def decl(name: Name): Symbol =
+ (decls lookup name) orElse {
+ assert(this eq pkg.info, this+" "+pkg.info)
+ assert(decls eq pkg.info.decls)
+ println("creating "+name+" in "+pkg)
+ val (clazz, module) = createClassModule(pkg, name.toTypeName)
+ if (name.isTypeName) clazz else module
+ }
+ override def member(name: Name): Symbol = decl(name)
+ override def findMember(name: Name, excludedFlags: Long, requiredFlags: Long, stableOnly: Boolean) =
+ member(name).filter (m => m.hasAllFlags(requiredFlags) && !m.hasFlag(excludedFlags))
+ }
+} \ No newline at end of file
diff --git a/src/compiler/scala/reflect/runtime/Settings.scala b/src/compiler/scala/reflect/runtime/Settings.scala
index 2fdcaa2e5f..088ea019e2 100644
--- a/src/compiler/scala/reflect/runtime/Settings.scala
+++ b/src/compiler/scala/reflect/runtime/Settings.scala
@@ -1,6 +1,10 @@
package scala.reflect
package runtime
+/** The Settings class for runtime reflection.
+ * This should be refined, so that settings are settable via command
+ * line options or properties.
+ */
class Settings extends internal.settings.MutableSettings {
class Setting extends SettingValue
diff --git a/src/compiler/scala/reflect/runtime/Universe.scala b/src/compiler/scala/reflect/runtime/Universe.scala
index 9157cd9001..f6ffeba401 100644
--- a/src/compiler/scala/reflect/runtime/Universe.scala
+++ b/src/compiler/scala/reflect/runtime/Universe.scala
@@ -1,32 +1,30 @@
package scala.reflect
package runtime
-class Universe extends internal.SymbolTable with JavaConversions {
+import internal.{SomePhase, NoPhase, Phase, TreeGen}
- type AbstractFileType = AbstractFile
+/** The universe for standard runtime reflection from Java.
+ * This type implements all abstract term members in internal.SymbolTable.
+ * It also provides methods to go from Java members to Scala members,
+ * using the code in JavaConversions.
+ */
+class Universe extends internal.SymbolTable with JavaConversions with Loaders {
- def picklerPhase = internal.NoPhase
+ type AbstractFileType = AbstractFile
- //val treePrinter = null
+ def picklerPhase = SomePhase
- val gen = new internal.TreeGen { val global: Universe.this.type = Universe.this }
+ val gen = new TreeGen { val global: Universe.this.type = Universe.this }
def settings = new Settings
def forInteractive = false
def forScaladoc = false
- val phaseWithId: Array[internal.Phase] = Array()
- val currentRunId = 0
- per = 1 << 8 + 1 // fake a period so that it is different from NoPeriod
+ val phaseWithId: Array[Phase] = Array(NoPhase, SomePhase)
+ val currentRunId = 1 // fake a run id so that it is different from NoRunId
+ phase = SomePhase // set to a phase different from NoPhase
def log(msg: => AnyRef): Unit = println(" [] "+msg)
- override val rootLoader = new LazyType {
- override def complete(sym: Symbol) = sym setInfo packageType(definitions.RootClass)
- }
-
- private def packageType(clazz: Symbol) = new ClassInfoType(List(), newScope, clazz)
-
- // definitions.RootClass.setInfo(packageType(definitions.RootClass))
type TreeCopier = TreeCopierOps
def newStrictTreeCopier: TreeCopier = new StrictTreeCopier
@@ -40,6 +38,15 @@ class Universe extends internal.SymbolTable with JavaConversions {
val NoPosition = ""
}
-object Universe extends Universe with App {
- classToScala(classOf[scala.collection.Iterable[_]])
+object Universe extends Universe
+
+/** test code; should go to tests once things settle down a bit
+ */
+object Test extends Universe with App {
+ val sym = classToScala(classOf[scala.collection.Iterable[_]])
+ println(sym)
+ println("parents = "+sym.info.parents)
+ println("decls = "+(sym.info.decls.toList map (_.defString)))
+ val ms = sym.info.members.toList map (_.initialize)
+ println("members = "+(ms map (_.defString) mkString ("\n ")))
} \ No newline at end of file
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
index 3c98d0adcc..1d8588209e 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
@@ -10,8 +10,7 @@ package classfile
import scala.collection.{ mutable, immutable }
import mutable.ListBuffer
import backend.icode._
-import scala.reflect.internal.ClassfileConstants
-import scala.reflect.internal.ClassfileConstants._
+import ClassfileConstants._
import scala.reflect.internal.Flags._
/** ICode reader from Java bytecode.
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/package.scala b/src/compiler/scala/tools/nsc/symtab/classfile/package.scala
new file mode 100644
index 0000000000..fe66c515de
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/package.scala
@@ -0,0 +1,7 @@
+package scala.tools.nsc.symtab
+
+package object classfile {
+
+ val ClassfileConstants = reflect.internal.ClassfileConstants
+
+}
diff --git a/src/scalap/scala/tools/scalap/Decode.scala b/src/scalap/scala/tools/scalap/Decode.scala
index 53072189cd..b4f93bccd4 100644
--- a/src/scalap/scala/tools/scalap/Decode.scala
+++ b/src/scalap/scala/tools/scalap/Decode.scala
@@ -12,7 +12,7 @@ package scala.tools.scalap
import scala.tools.scalap.scalax.rules.scalasig._
import scala.tools.nsc.util.ScalaClassLoader
import scala.tools.nsc.util.ScalaClassLoader.getSystemLoader
-import scala.reflect.internal.ByteCodecs
+import scala.reflect.internal.pickling.ByteCodecs
import ClassFileParser.{ ConstValueIndex, Annotation }
import Main.{ SCALA_SIG, SCALA_SIG_ANNOTATION, BYTES_VALUE }
diff --git a/src/scalap/scala/tools/scalap/scalax/rules/scalasig/ScalaSig.scala b/src/scalap/scala/tools/scalap/scalax/rules/scalasig/ScalaSig.scala
index 5c4f18a573..2a08cc13f5 100644
--- a/src/scalap/scala/tools/scalap/scalax/rules/scalasig/ScalaSig.scala
+++ b/src/scalap/scala/tools/scalap/scalax/rules/scalasig/ScalaSig.scala
@@ -12,7 +12,7 @@ package rules
package scalasig
import ClassFileParser.{ ConstValueIndex, Annotation }
-import scala.reflect.internal.ByteCodecs
+import scala.reflect.internal.pickling.ByteCodecs
object ScalaSigParser {
import Main.{ SCALA_SIG, SCALA_SIG_ANNOTATION, BYTES_VALUE }
diff --git a/test/files/run/bytecodecs.scala b/test/files/run/bytecodecs.scala
index 786c9dbdb0..837be0edd9 100644
--- a/test/files/run/bytecodecs.scala
+++ b/test/files/run/bytecodecs.scala
@@ -1,4 +1,4 @@
-import scala.reflect.internal.ByteCodecs._
+import scala.reflect.internal.pickling.ByteCodecs._
object Test {