diff options
author | Matthias Zenger <mzenger@gmail.com> | 2003-11-16 15:21:25 +0000 |
---|---|---|
committer | Matthias Zenger <mzenger@gmail.com> | 2003-11-16 15:21:25 +0000 |
commit | 02e19018945c1ba25574192c0d968c6e2978e6e2 (patch) | |
tree | 1feba8dc840b92f4f81081d335fc1ef6067deace | |
parent | b9035ad31a97b94eb95a549c125281f1c357699c (diff) | |
download | scala-02e19018945c1ba25574192c0d968c6e2978e6e2.tar.gz scala-02e19018945c1ba25574192c0d968c6e2978e6e2.tar.bz2 scala-02e19018945c1ba25574192c0d968c6e2978e6e2.zip |
*** empty log message ***
-rw-r--r-- | sources/scala/tools/scalap/JavaWriter.scala | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/sources/scala/tools/scalap/JavaWriter.scala b/sources/scala/tools/scalap/JavaWriter.scala new file mode 100644 index 0000000000..9ba45aefea --- /dev/null +++ b/sources/scala/tools/scalap/JavaWriter.scala @@ -0,0 +1,168 @@ +/* ___ ____ ___ __ ___ ___ +** / _// __// _ | / / / _ | / _ \ Scala classfile decoder +** __\ \/ /__/ __ |/ /__/ __ |/ ___/ (c) 2003, LAMP/EPFL +** /____/\___/_/ |_/____/_/ |_/_/ +** +** $Id$ +*/ + +package scala.tools.scalap; + +import java.io._; + + +class JavaWriter(classfile: Classfile, writer: Writer) extends CodeWriter(writer) { + + val cf = classfile; + + def flagsToStr(clazz: Boolean, flags: Int) = { + val buffer = new StringBuffer(); + var x: StringBuffer = buffer; + if (((flags & 0x0007) == 0) && + ((flags & 0x0002) != 0)) + x = buffer.append("private "); + if ((flags & 0x0004) != 0) + x = buffer.append("protected "); + if ((flags & 0x0010) != 0) + x = buffer.append("final "); + if ((flags & 0x0400) != 0) + x = if (clazz) buffer.append("abstract ") + else buffer.append("/*deferred*/ "); + buffer.toString() + } + + def nameToClass(str: String) = { + val res = Names.decode(str.replace('/', '.')); + if (res == "java.lang.Object") "scala.AnyRef" else res + } + + def nameToSimpleClass(str: String) = + Names.decode(str.substring(str.lastIndexOf('/') + 1)); + + def nameToPackage(str: String) = + Names.decode(str.substring(0, str.lastIndexOf('/')).replace('/', '.')); + + def sigToType(str: String): String = + sigToType(str, 0)._1; + + def sigToType(str: String, i: Int): Pair[String, Int] = str.charAt(i) match { + case 'B' => Pair("scala.Byte", i + 1) + case 'C' => Pair("scala.Char", i + 1) + case 'D' => Pair("scala.Double", i + 1) + case 'F' => Pair("scala.Float", i + 1) + case 'I' => Pair("scala.Int", i + 1) + case 'J' => Pair("scala.Long", i + 1) + case 'S' => Pair("scala.Short", i + 1) + case 'V' => Pair("scala.Unit", i + 1) + case 'Z' => Pair("scala.Boolean", i + 1) + case 'L' => val j = str.indexOf(';', i); + Pair(nameToClass(str.substring(i + 1, j)), j + 1) + case '[' => val Pair(tpe, j) = sigToType(str, i + 1); + Pair("scala.Array[" + tpe + "]", j) + case '(' => val Pair(tpe, j) = sigToType0(str, i + 1); + Pair("(" + tpe, j) + case ')' => val Pair(tpe, j) = sigToType(str, i + 1); + Pair("): " + tpe, j) + } + + def sigToType0(str: String, i: Int): Pair[String, Int] = + if (str.charAt(i) == ')') + sigToType(str, i) + else { + val Pair(tpe, j) = sigToType(str, i); + if (str.charAt(j) == ')') { + val Pair(rest, k) = sigToType(str, j); + Pair(tpe + rest, k) + } else { + val Pair(rest, k) = sigToType0(str, j); + Pair(tpe + ", " + rest, k) + } + }; + + def getName(n: Int): String = cf.pool(n) match { + case cf.UTF8(str) => str; + case cf.StringConst(m) => getName(m); + case cf.ClassRef(m) => getName(m); + case x => Console.println("* " + x); "<error>" + } + + def getClassName(n: Int): String = nameToClass(getName(n)); + + def getSimpleClassName(n: Int): String = nameToSimpleClass(getName(n)); + + def getPackage(n: Int): String = nameToPackage(getName(n)); + + def getType(n: Int): String = sigToType(getName(n)); + + def isStatic(flags: Int) = (flags & 0x0008) != 0; + + def isInterface(flags: Int) = (flags & 0x0200) != 0; + + def isConstr(name: String) = (name == "<init>"); + + def printField(flags: Int, name: Int, tpe: Int, attribs: List[cf.Attribute]) = { + print(flagsToStr(false, flags))*; + if ((flags & 0x0010) != 0) + print("val " + Names.decode(getName(name)))*; + else + print("final var " + Names.decode(getName(name)))*; + print(": " + getType(tpe) + ";").newline*; + } + + def printMethod(flags: Int, name: Int, tpe: Int, attribs: List[cf.Attribute]) = { + if (getName(name) == "<init>") + print(flagsToStr(false, flags))*; + if (getName(name) == "<init>") { + print("def this" + getType(tpe) + ";").newline*; + } else { + print("def " + Names.decode(getName(name)))*; + print(getType(tpe) + ";").newline*; + } + } + + def printClass = { + val pck = getPackage(cf.classname); + if (pck.length() > 0) + println("package " + pck + ";"); + print(flagsToStr(true, cf.flags))*; + if (isInterface(cf.flags)) { + print("trait " + getSimpleClassName(cf.classname))*; + } else { + print("class " + getSimpleClassName(cf.classname))*; + if (cf.pool(cf.superclass) != null) + print(" extends " + getClassName(cf.superclass))*; + } + cf.interfaces foreach { + n => print(" with " + getClassName(n))*; + } + var statics: List[cf.Member] = Nil; + print(" {").indent.newline; + cf.fields foreach { + case m@cf.Member(_, flags, name, tpe, attribs) => + if (isStatic(flags)) + statics = m :: statics; + else + printField(flags, name, tpe, attribs) + } + cf.methods foreach { + case m@cf.Member(_, flags, name, tpe, attribs) => + if (isStatic(flags)) + statics = m :: statics; + else + printMethod(flags, name, tpe, attribs) + } + undent.print("}").newline*; + if (!statics.isEmpty) { + print("object " + getSimpleClassName(cf.classname) + " {")*; + indent.newline; + statics foreach { + case cf.Member(true, flags, name, tpe, attribs) => + printField(flags, name, tpe, attribs) + case cf.Member(false, flags, name, tpe, attribs) => + if (getName(name) != "<clinit>") + printMethod(flags, name, tpe, attribs) + } + undent.print("}").newline* + } + } +} |