(.module: [lux (#- Type) ["." host (#+ import: do-to)] [control ["." function]] [data ["." product] [number ["i" int]] ["." text ["%" format (#+ format)]] [collection ["." array (#+ Array)] ["." list ("#/." functor)]]] [target [jvm ["." descriptor (#+ Descriptor)] [encoding ["." name]] ["$t" type (#+ Method Class Type Parameter) ["." reflection]]]]] ["." //]) (import: #long java/lang/Object) (import: #long java/lang/String) (import: org/objectweb/asm/Opcodes (#static ACC_PUBLIC int) (#static ACC_PROTECTED int) (#static ACC_PRIVATE int) (#static ACC_TRANSIENT int) (#static ACC_VOLATILE int) (#static ACC_ABSTRACT int) (#static ACC_FINAL int) (#static ACC_STATIC int) (#static ACC_SYNCHRONIZED int) (#static ACC_STRICT int) (#static ACC_SUPER int) (#static ACC_INTERFACE int) (#static V1_1 int) (#static V1_2 int) (#static V1_3 int) (#static V1_4 int) (#static V1_5 int) (#static V1_6 int) (#static V1_7 int) (#static V1_8 int) ) (import: org/objectweb/asm/FieldVisitor (visitEnd [] void)) (import: org/objectweb/asm/MethodVisitor (visitCode [] void) (visitMaxs [int int] void) (visitEnd [] void)) (import: org/objectweb/asm/ClassWriter (#static COMPUTE_MAXS int) (#static COMPUTE_FRAMES int) (new [int]) (visit [int int String String String [String]] void) (visitEnd [] void) (visitField [int String String String Object] FieldVisitor) (visitMethod [int String String String [String]] MethodVisitor) (toByteArray [] [byte])) (def: (string-array values) (-> (List Text) (Array Text)) (let [output (host.array String (list.size values))] (exec (list/map (function (_ [idx value]) (host.array-write idx value output)) (list.enumerate values)) output))) (def: (version-flag version) (-> //.Version Int) (case version #//.V1_1 (Opcodes::V1_1) #//.V1_2 (Opcodes::V1_2) #//.V1_3 (Opcodes::V1_3) #//.V1_4 (Opcodes::V1_4) #//.V1_5 (Opcodes::V1_5) #//.V1_6 (Opcodes::V1_6) #//.V1_7 (Opcodes::V1_7) #//.V1_8 (Opcodes::V1_8))) (def: (visibility-flag visibility) (-> //.Visibility Int) (case visibility #//.Public (Opcodes::ACC_PUBLIC) #//.Protected (Opcodes::ACC_PROTECTED) #//.Private (Opcodes::ACC_PRIVATE) #//.Default +0)) (def: (class-flags config) (-> //.Class-Config Int) ($_ i.+ (if (get@ #//.finalC config) (Opcodes::ACC_FINAL) +0))) (def: (method-flags config) (-> //.Method-Config Int) ($_ i.+ (if (get@ #//.staticM config) (Opcodes::ACC_STATIC) +0) (if (get@ #//.finalM config) (Opcodes::ACC_FINAL) +0) (if (get@ #//.synchronizedM config) (Opcodes::ACC_SYNCHRONIZED) +0) (if (get@ #//.strictM config) (Opcodes::ACC_STRICT) +0))) (def: (field-flags config) (-> //.Field-Config Int) ($_ i.+ (if (get@ #//.staticF config) (Opcodes::ACC_STATIC) +0) (if (get@ #//.finalF config) (Opcodes::ACC_FINAL) +0) (if (get@ #//.transientF config) (Opcodes::ACC_TRANSIENT) +0) (if (get@ #//.volatileF config) (Opcodes::ACC_VOLATILE) +0))) (def: class-to-type (-> Class Type) (|>> #$t.Class #$t.Generic)) (def: param-signature (-> Class Text) (|>> class-to-type $t.signature (format ":"))) (def: (formal-param [name super interfaces]) (-> Parameter Text) (format name (param-signature super) (|> interfaces (list/map param-signature) (text.join-with "")))) (def: (parameters-signature parameters super interfaces) (-> (List Parameter) Class (List Class) Text) (let [formal-params (if (list.empty? parameters) "" (format "<" (|> parameters (list/map formal-param) (text.join-with "")) ">"))] (format formal-params (|> super class-to-type $t.signature) (|> interfaces (list/map (|>> class-to-type $t.signature)) (text.join-with ""))))) (def: class-computes Int ($_ i.+ (ClassWriter::COMPUTE_MAXS) ## (ClassWriter::COMPUTE_FRAMES) )) (def: binary-name (|>> name.internal name.read)) (template [ ] [(def: #export ( version visibility config name parameters super interfaces definitions) (-> //.Version //.Visibility //.Class-Config Text (List Parameter) Class (List Class) //.Def (host.type [byte])) (let [writer (|> (do-to (ClassWriter::new class-computes) (ClassWriter::visit (version-flag version) ($_ i.+ (Opcodes::ACC_SUPER) (visibility-flag visibility) (class-flags config)) (..binary-name name) (parameters-signature parameters super interfaces) (|> super product.left ..binary-name) (|> interfaces (list/map (|>> product.left ..binary-name)) string-array))) definitions) _ (ClassWriter::visitEnd writer)] (ClassWriter::toByteArray writer)))] [class +0] [abstract (Opcodes::ACC_ABSTRACT)] ) (def: $Object Class ["java.lang.Object" (list)]) (def: #export (interface version visibility config name parameters interfaces definitions) (-> //.Version //.Visibility //.Class-Config Text (List Parameter) (List Class) //.Def (host.type [byte])) (let [writer (|> (do-to (ClassWriter::new class-computes) (ClassWriter::visit (version-flag version) ($_ i.+ (Opcodes::ACC_SUPER) (Opcodes::ACC_INTERFACE) (visibility-flag visibility) (class-flags config)) (..binary-name name) (parameters-signature parameters $Object interfaces) (|> $Object product.left ..binary-name) (|> interfaces (list/map (|>> product.left ..binary-name)) string-array))) definitions) _ (ClassWriter::visitEnd writer)] (ClassWriter::toByteArray writer))) (def: #export (method visibility config name type then) (-> //.Visibility //.Method-Config Text (Descriptor descriptor.Method) //.Inst //.Def) (function (_ writer) (let [=method (ClassWriter::visitMethod ($_ i.+ (visibility-flag visibility) (method-flags config)) (..binary-name name) (descriptor.descriptor type) (host.null) (string-array (list)) writer) _ (MethodVisitor::visitCode =method) _ (then =method) _ (MethodVisitor::visitMaxs +0 +0 =method) _ (MethodVisitor::visitEnd =method)] writer))) (def: #export (abstract-method visibility config name type) (-> //.Visibility //.Method-Config Text (Descriptor descriptor.Method) //.Def) (function (_ writer) (let [=method (ClassWriter::visitMethod ($_ i.+ (visibility-flag visibility) (method-flags config) (Opcodes::ACC_ABSTRACT)) (..binary-name name) (descriptor.descriptor type) (host.null) (string-array (list)) writer) _ (MethodVisitor::visitEnd =method)] writer))) (def: #export (field visibility config name type) (-> //.Visibility //.Field-Config Text (Descriptor descriptor.Field) //.Def) (function (_ writer) (let [=field (do-to (ClassWriter::visitField ($_ i.+ (visibility-flag visibility) (field-flags config)) (..binary-name name) (descriptor.descriptor type) (host.null) (host.null) writer) (FieldVisitor::visitEnd))] writer))) (template [ ] [(def: #export ( visibility config name value) (-> //.Visibility //.Field-Config Text //.Def) (function (_ writer) (let [=field (do-to (ClassWriter::visitField ($_ i.+ (visibility-flag visibility) (field-flags config)) (..binary-name name) (descriptor.descriptor ) (host.null) ( value) writer) (FieldVisitor::visitEnd))] writer)))] [boolean-field Bit descriptor.boolean function.identity] [byte-field Int descriptor.byte host.long-to-byte] [short-field Int descriptor.short host.long-to-short] [int-field Int descriptor.int host.long-to-int] [long-field Int descriptor.long function.identity] [float-field Frac descriptor.float host.double-to-float] [double-field Frac descriptor.double function.identity] [char-field Nat descriptor.char (|>> .int host.long-to-int host.int-to-char)] [string-field Text (descriptor.class "java.lang.String") function.identity] ) (def: #export (fuse defs) (-> (List //.Def) //.Def) (case defs #.Nil function.identity (#.Cons singleton #.Nil) singleton (#.Cons head tail) (function.compose (fuse tail) head)))