Generate the class bytecode from the provided type map. Returns a map
of the classes' :name and :bytes. Options:
:name of the class. Optional, but see below.
:flags seq of class/interface modifier flags (e.g., :final).
See the `insn.util` namespace.
:super defaults to Object.
:interfaces sequence of interface types to extend/implement.
:annotations map or sequence of tuples, described below.
:signature generic type information - usually only ever needed
for interop with Java libraries (reflection, etc.)
:fields sequence of field maps, described below.
:methods sequence of method maps, described below.
:version bytecode version given as a integer. For backwards
compatibility, a float of major.minor may be given
for versions 1.1 through 1.8.
:source string denoting the original source file - optional.
:debug string of arbitrary debug information - optional.
Each field and method can also be given :annotations and a :signature
as per above.
Some examples:
(visit {:flags #{:public :interface}
:name 'my.ns.Foo
:methods [{:flags #{:public :abstract}
:name :my_method
:desc [:int]}]})
(visit {:flags #{:public}
:name 'my.ns.Bar
:interfaces ['my.ns.Foo]
:methods [{:flags #{:public}
:name :toString
:desc [String]
:emit [[:ldc "Bar"]
[:areturn]]}
{:flags #{:public}
:name :my_method
:desc [:int]
:emit [[:ldc 42]
[:ireturn]]}]})
Class instance/static fields are provided as maps. Options:
:name field name (required).
:type field type (required).
:flags seq of field modifier flags.
:value initial value. Only for primitive and String static fields,
and if given, must be a corresponding Integer, Float, Long,
Double, or String value.
Some example maps:
{:flags #{:public :final}, :name :my_string, :type String}
{:flags #{:static}, :name :some_number, :type :long, :value 42}
Class/interface methods, constructors, and static initializers are
provided as maps. Options:
:name method name (required). Can be either :init or :clinit,
designating a constructor or the static initializer,
respectively.
:flags seq of method modifier flags. Ignored for the static
initializer.
:desc method parameter types and return type (specified last).
Ignored for the static initializer, optional for
constructors. For constructors, the method return type is
forced to void if not explicitly specified as such.
:emit either a fn taking a MethodVisitor or a sequence of
instructions to emit for the method (see `insn.op`).
Optional if method is abstract.
Some example maps, :emit has been omitted for brevity:
{:name :add_ints, :desc [:int :int :int]}
{:flags #{:private}, :name :init, :desc [String :boolean :void]}
{:name :clinit}
Additionally, methods may be given :parameter-annotations provided as
a map of {parameter-index annotations}.
If the class name is not package prefixed, the current namespace is
used as the resulting classes' package. If a name is not given, a
generated (gensym) class name is used, qualified by the current
namespace.
If the type does not define at least one constructor, and is not an
abstract type, a default, zero-argument constructor with default
access will be written that simply invokes the superclass constructor.
All annotations are provided as a map or sequence of tuples. Each key
is the Annotation name and each value is a map of elements. A non-map
value specifies a single element named :value as per java.
Annotation values are processed the same as in clojure.
See: https://clojure.org/reference/datatypes#_java_annotation_support