//
// Copyright (c) 2012, Brian Frank and Andy Frank
// Licensed under the Academic Free License version 3.0
//
// History:
// 17 Feb 12 Brian Frank Creation
//
**
** DasmClass models a single disassmbled Java classfile
**
class DasmClass
{
** It-block constructor, use `Dasm`
internal new make(|This| f) { f(this) }
** Classfile 'major.minor' version
const Version version
** Class access flags
const DasmFlags flags
** This class name signature
const DasmType thisClass
** Super class name signature (or null if object)
const DasmType? superClass
** Interface signatures
const DasmType[] interfaces
** Member fields
const DasmField[] fields
** Member methods
const DasmMethod[] methods
** Return 'thisClass.toStr'
override Str toStr() { thisClass.toStr }
** Dump debug to output stream
Void dump(OutStream out := Env.cur.out)
{
out.printLine("version: $version")
out.printLine("flags: $flags")
out.printLine("thisClass: $thisClass")
out.printLine("superClass: $superClass")
out.printLine("interfaces: $interfaces")
out.printLine("fields:")
fields.each |f| { out.print(" ").printLine(f) }
out.printLine("methods:")
methods.each |m| { out.print(" ").printLine(m) }
out.flush
}
}
**************************************************************************
** DasmFlags
**************************************************************************
**
** DasmFlags model class/member Java access flags
**
const class DasmFlags
{
new make(Int mask) { this.mask = mask }
static const Int PUBLIC := 0x0001
static const Int PRIVATE := 0x0002
static const Int PROTECTED := 0x0004
static const Int STATIC := 0x0008
static const Int FINAL := 0x0010
static const Int SUPER := 0x0020
static const Int VOLATILE := 0x0040
static const Int INTERFACE := 0x0200
static const Int ABSTRACT := 0x0400
static const Int TRANSIENT := 0x0800
static const Int SYNTHETIC := 0x1000
static const Int ANNOTATION := 0x2000
static const Int ENUM := 0x4000
Bool isPublic() { mask.and(PUBLIC) != 0 }
Bool isPrivate() { mask.and(PRIVATE) != 0 }
Bool isProtected() { mask.and(PROTECTED) != 0 }
Bool isStatic() { mask.and(STATIC) != 0 }
Bool isFinal() { mask.and(FINAL) != 0 }
Bool isSuper() { mask.and(SUPER) != 0 }
Bool isInterface() { mask.and(INTERFACE) != 0 }
Bool isAbstract() { mask.and(ABSTRACT) != 0 }
Bool isAnnotation() { mask.and(ANNOTATION) != 0 }
override Str toStr()
{
s := StrBuf()
typeof.methods.each |m|
{
if (m.parent == typeof && m.name.startsWith("is") && m.callOn(this, [,]))
s.add(m.name[2..-1].lower).add(" ")
}
if (!s.isEmpty) s.remove(-1)
return s.toStr
}
const Int mask
}
**************************************************************************
** DasmField
**************************************************************************
**
** DasmField models a disassembled Java field
**
const class DasmField
{
new make(|This| f) { f(this) }
const Str name
const DasmFlags flags
const DasmType type
override Str toStr() { "$flags $type $name;" }
}
**************************************************************************
** DasmMethod
**************************************************************************
**
** DasmMethod models a disassembled Java method
**
const class DasmMethod
{
new make(|This| f) { f(this) }
const Str name
const DasmFlags flags
const DasmType returns
const DasmType[] params
override Str toStr() { "$flags $returns $name(" + params.join(",") + ")" }
}
**************************************************************************
** DasmType
**************************************************************************
**
** DasmType models a type within a field or method descriptor
**
const class DasmType
{
new make(Str sig)
{
for (i:=0; sig[i] == '['; ++i) rank++
this.sig = sig
}
** Java signature such as "Ljava/lang/String;" or "I"
const Str sig
** If array, what is its rank (or zero if not an array)
const Int rank
** Is this an array type
Bool isArray() { rank > 0 }
** Is this a primitive type
Bool isPrimitive() { sig.size == 1 }
** Get array's component type
DasmType toComponentType()
{
if (rank == 0) throw ArgErr("Not an array: $sig")
return make(sig[1..-1])
}
override Str toStr()
{
s := rank == 0 ? sig : sig[rank..-1]
if (s[0] == 'L') s = s[1..-2].replace("/", ".")
else if (s.size == 1) s = sigToPrimitive[s] ?: throw Err(s)
rank.times { s = s += "[]" }
return s
}
private static const Str:Str sigToPrimitive :=
[
"B": "byte",
"C": "char",
"D": "double",
"F": "float",
"I": "int",
"J": "long",
"S": "short",
"V": "void",
"Z": "boolean",
]
}