(.module: [library [lux (#- Type int char try) ["." ffi (#+ import: do_to)] [abstract [monad (#+ do)]] [control ["." function] ["." maybe] ["." try] ["p" parser ["s" code]]] [data ["." product] [collection ["." list ("#@." functor)]]] [macro [syntax (#+ syntax:)] ["." code] ["." template]] [math [number ["n" nat] ["i" int]]] [target [jvm [encoding ["." name (#+ External)]] ["." type (#+ Type) ("#@." equivalence) [category (#+ Void Value Return Method Primitive Object Class Array Var Parameter)] ["." box] ["." descriptor] ["." reflection]]]] [tool [compiler [phase (#+ Operation)]]]]] ["." // (#+ Inst)]) (def: class_name (|>> type.descriptor descriptor.class_name name.read)) (def: descriptor (|>> type.descriptor descriptor.descriptor)) (def: reflection (|>> type.reflection reflection.reflection)) ... [Host] (import: java/lang/Object) (import: java/lang/String) (syntax: (declare [codes (p.many s.local_identifier)]) (|> codes (list@map (function (_ code) (` ((~' #static) (~ (code.local_identifier code)) (~' int))))) in)) (`` (import: org/objectweb/asm/Opcodes ["#::." (#static NOP int) ... Conversion (~~ (declare D2F D2I D2L F2D F2I F2L I2B I2C I2D I2F I2L I2S L2D L2F L2I)) ... Primitive (~~ (declare T_BOOLEAN T_CHAR T_FLOAT T_DOUBLE T_BYTE T_SHORT T_INT T_LONG)) ... Class (~~ (declare CHECKCAST NEW INSTANCEOF)) ... Stack (~~ (declare DUP DUP_X1 DUP_X2 DUP2 DUP2_X1 DUP2_X2 POP POP2 SWAP)) ... Jump (~~ (declare IF_ICMPEQ IF_ICMPGT IF_ICMPLT IF_ICMPNE IF_ICMPGE IF_ICMPLE IF_ACMPEQ IF_ACMPNE IFNULL IFNONNULL IFEQ IFNE IFLT IFLE IFGT IFGE GOTO)) (~~ (declare BIPUSH SIPUSH)) (~~ (declare ICONST_M1 ICONST_0 ICONST_1 ICONST_2 ICONST_3 ICONST_4 ICONST_5 LCONST_0 LCONST_1 FCONST_0 FCONST_1 FCONST_2 DCONST_0 DCONST_1)) (#static ACONST_NULL int) ... Var (~~ (declare IINC ILOAD LLOAD FLOAD DLOAD ALOAD ISTORE LSTORE FSTORE DSTORE ASTORE)) ... Arithmetic (~~ (declare IADD ISUB IMUL IDIV IREM INEG LADD LSUB LMUL LDIV LREM LNEG LCMP FADD FSUB FMUL FDIV FREM FNEG FCMPG FCMPL DADD DSUB DMUL DDIV DREM DNEG DCMPG DCMPL)) ... Bit-wise (~~ (declare IAND IOR IXOR ISHL ISHR IUSHR LAND LOR LXOR LSHL LSHR LUSHR)) ... Array (~~ (declare ARRAYLENGTH NEWARRAY ANEWARRAY AALOAD AASTORE BALOAD BASTORE SALOAD SASTORE IALOAD IASTORE LALOAD LASTORE FALOAD FASTORE DALOAD DASTORE CALOAD CASTORE)) ... Member (~~ (declare GETSTATIC PUTSTATIC GETFIELD PUTFIELD INVOKESTATIC INVOKESPECIAL INVOKEVIRTUAL INVOKEINTERFACE)) (#static ATHROW int) ... Concurrency (~~ (declare MONITORENTER MONITOREXIT)) ... Return (~~ (declare RETURN IRETURN LRETURN FRETURN DRETURN ARETURN))] )) (import: org/objectweb/asm/Label ["#::." (new [])]) (import: org/objectweb/asm/MethodVisitor ["#::." (visitCode [] void) (visitMaxs [int int] void) (visitEnd [] void) (visitInsn [int] void) (visitLdcInsn [java/lang/Object] void) (visitFieldInsn [int java/lang/String java/lang/String java/lang/String] void) (visitTypeInsn [int java/lang/String] void) (visitVarInsn [int int] void) (visitIntInsn [int int] void) (visitMethodInsn [int java/lang/String java/lang/String java/lang/String boolean] void) (visitLabel [org/objectweb/asm/Label] void) (visitJumpInsn [int org/objectweb/asm/Label] void) (visitTryCatchBlock [org/objectweb/asm/Label org/objectweb/asm/Label org/objectweb/asm/Label java/lang/String] void) (visitLookupSwitchInsn [org/objectweb/asm/Label [int] [org/objectweb/asm/Label]] void) (visitTableSwitchInsn [int int org/objectweb/asm/Label [org/objectweb/asm/Label]] void) ]) ... [Insts] (def: .public make_label (All [s] (Operation s org/objectweb/asm/Label)) (function (_ state) (#try.Success [state (org/objectweb/asm/Label::new)]))) (def: .public (with_label action) (All [a] (-> (-> org/objectweb/asm/Label a) a)) (action (org/objectweb/asm/Label::new))) (template [ ] [(def: .public ( value) (-> Inst) (function (_ visitor) (do_to visitor (org/objectweb/asm/MethodVisitor::visitLdcInsn ( value)))))] [boolean Bit function.identity] [int Int ffi.long_to_int] [long Int function.identity] [double Frac function.identity] [char Nat (|>> .int ffi.long_to_int ffi.int_to_char)] [string Text function.identity] ) (template: (!prefix short) [(`` ((~~ (template.identifier ["org/objectweb/asm/Opcodes::" short]))))]) (template [] [(def: .public Inst (function (_ visitor) (do_to visitor (org/objectweb/asm/MethodVisitor::visitInsn (!prefix )))))] [ICONST_M1] [ICONST_0] [ICONST_1] [ICONST_2] [ICONST_3] [ICONST_4] [ICONST_5] [LCONST_0] [LCONST_1] [FCONST_0] [FCONST_1] [FCONST_2] [DCONST_0] [DCONST_1] ) (def: .public NULL Inst (function (_ visitor) (do_to visitor (org/objectweb/asm/MethodVisitor::visitInsn (!prefix ACONST_NULL))))) (template [] [(def: .public ( constant) (-> Int Inst) (function (_ visitor) (do_to visitor (org/objectweb/asm/MethodVisitor::visitIntInsn (!prefix ) constant))))] [BIPUSH] [SIPUSH] ) (template [] [(def: .public Inst (function (_ visitor) (do_to visitor (org/objectweb/asm/MethodVisitor::visitInsn (!prefix )))))] [NOP] ... Stack [DUP] [DUP_X1] [DUP_X2] [DUP2] [DUP2_X1] [DUP2_X2] [POP] [POP2] [SWAP] ... Conversions [D2F] [D2I] [D2L] [F2D] [F2I] [F2L] [I2B] [I2C] [I2D] [I2F] [I2L] [I2S] [L2D] [L2F] [L2I] ... Integer arithmetic [IADD] [ISUB] [IMUL] [IDIV] [IREM] [INEG] ... Integer bitwise [IAND] [IOR] [IXOR] [ISHL] [ISHR] [IUSHR] ... Long arithmetic [LADD] [LSUB] [LMUL] [LDIV] [LREM] [LNEG] [LCMP] ... Long bitwise [LAND] [LOR] [LXOR] [LSHL] [LSHR] [LUSHR] ... Float arithmetic [FADD] [FSUB] [FMUL] [FDIV] [FREM] [FNEG] [FCMPG] [FCMPL] ... Double arithmetic [DADD] [DSUB] [DMUL] [DDIV] [DREM] [DNEG] [DCMPG] [DCMPL] ... Array [ARRAYLENGTH] [AALOAD] [AASTORE] [BALOAD] [BASTORE] [SALOAD] [SASTORE] [IALOAD] [IASTORE] [LALOAD] [LASTORE] [FALOAD] [FASTORE] [DALOAD] [DASTORE] [CALOAD] [CASTORE] ... Exceptions [ATHROW] ... Concurrency [MONITORENTER] [MONITOREXIT] ... Return [RETURN] [IRETURN] [LRETURN] [FRETURN] [DRETURN] [ARETURN] ) (type: .public Register Nat) (template [] [(def: .public ( register) (-> Register Inst) (function (_ visitor) (do_to visitor (org/objectweb/asm/MethodVisitor::visitVarInsn (!prefix ) (.int register)))))] [IINC] [ILOAD] [LLOAD] [FLOAD] [DLOAD] [ALOAD] [ISTORE] [LSTORE] [FSTORE] [DSTORE] [ASTORE] ) (template [ ] [(def: .public ( class field type) (-> (Type Class) Text (Type Value) Inst) (function (_ visitor) (do_to visitor (org/objectweb/asm/MethodVisitor::visitFieldInsn () (..class_name class) field (..descriptor type)))))] [GETSTATIC org/objectweb/asm/Opcodes::GETSTATIC] [PUTSTATIC org/objectweb/asm/Opcodes::PUTSTATIC] [PUTFIELD org/objectweb/asm/Opcodes::PUTFIELD] [GETFIELD org/objectweb/asm/Opcodes::GETFIELD] ) (template [ +] [(`` (template [ ] [(def: .public ( class) (-> (Type ) Inst) (function (_ visitor) (do_to visitor (org/objectweb/asm/MethodVisitor::visitTypeInsn () (..class_name class)))))] (~~ (template.spliced +))))] [Object [[CHECKCAST org/objectweb/asm/Opcodes::CHECKCAST] [ANEWARRAY org/objectweb/asm/Opcodes::ANEWARRAY]]] [Class [[NEW org/objectweb/asm/Opcodes::NEW] [INSTANCEOF org/objectweb/asm/Opcodes::INSTANCEOF]]] ) (def: .public (NEWARRAY type) (-> (Type Primitive) Inst) (function (_ visitor) (do_to visitor (org/objectweb/asm/MethodVisitor::visitIntInsn (org/objectweb/asm/Opcodes::NEWARRAY) (`` (cond (~~ (template [ ] [(type@= type) ()] [type.boolean org/objectweb/asm/Opcodes::T_BOOLEAN] [type.byte org/objectweb/asm/Opcodes::T_BYTE] [type.short org/objectweb/asm/Opcodes::T_SHORT] [type.int org/objectweb/asm/Opcodes::T_INT] [type.long org/objectweb/asm/Opcodes::T_LONG] [type.float org/objectweb/asm/Opcodes::T_FLOAT] [type.double org/objectweb/asm/Opcodes::T_DOUBLE] [type.char org/objectweb/asm/Opcodes::T_CHAR])) ... else (undefined))))))) (template [ ] [(def: .public ( class method_name method) (-> (Type Class) Text (Type Method) Inst) (function (_ visitor) (do_to visitor (org/objectweb/asm/MethodVisitor::visitMethodInsn () (..class_name class) method_name (|> method type.descriptor descriptor.descriptor) ))))] [INVOKESTATIC org/objectweb/asm/Opcodes::INVOKESTATIC false] [INVOKEVIRTUAL org/objectweb/asm/Opcodes::INVOKEVIRTUAL false] [INVOKESPECIAL org/objectweb/asm/Opcodes::INVOKESPECIAL false] [INVOKEINTERFACE org/objectweb/asm/Opcodes::INVOKEINTERFACE true] ) (template [] [(def: .public ( @where) (-> //.Label Inst) (function (_ visitor) (do_to visitor (org/objectweb/asm/MethodVisitor::visitJumpInsn (!prefix ) @where))))] [IF_ICMPEQ] [IF_ICMPGT] [IF_ICMPLT] [IF_ICMPNE] [IF_ICMPGE] [IF_ICMPLE] [IF_ACMPEQ] [IF_ACMPNE] [IFNULL] [IFNONNULL] [IFEQ] [IFNE] [IFLT] [IFLE] [IFGT] [IFGE] [GOTO] ) (def: .public (LOOKUPSWITCH default keys+labels) (-> //.Label (List [Int //.Label]) Inst) (function (_ visitor) (let [keys+labels (list.sorted (function (_ left right) (i.< (product.left left) (product.left right))) keys+labels) array_size (list.size keys+labels) keys_array (ffi.array int array_size) labels_array (ffi.array org/objectweb/asm/Label array_size) _ (loop [idx 0] (if (n.< array_size idx) (let [[key label] (maybe.trusted (list.item idx keys+labels))] (exec (ffi.write! idx (ffi.long_to_int key) keys_array) (ffi.write! idx label labels_array) (recur (++ idx)))) []))] (do_to visitor (org/objectweb/asm/MethodVisitor::visitLookupSwitchInsn default keys_array labels_array))))) (def: .public (TABLESWITCH min max default labels) (-> Int Int //.Label (List //.Label) Inst) (function (_ visitor) (let [num_labels (list.size labels) labels_array (ffi.array org/objectweb/asm/Label num_labels) _ (loop [idx 0] (if (n.< num_labels idx) (exec (ffi.write! idx (maybe.trusted (list.item idx labels)) labels_array) (recur (++ idx))) []))] (do_to visitor (org/objectweb/asm/MethodVisitor::visitTableSwitchInsn min max default labels_array))))) (def: .public (try @from @to @handler exception) (-> //.Label //.Label //.Label (Type Class) Inst) (function (_ visitor) (do_to visitor (org/objectweb/asm/MethodVisitor::visitTryCatchBlock @from @to @handler (..class_name exception))))) (def: .public (label @label) (-> //.Label Inst) (function (_ visitor) (do_to visitor (org/objectweb/asm/MethodVisitor::visitLabel @label)))) (def: .public (array elementT) (-> (Type Value) Inst) (case (type.primitive? elementT) (#.Left elementT) (ANEWARRAY elementT) (#.Right elementT) (NEWARRAY elementT))) (template [ ] [(def: ( type) (-> (Type Primitive) Text) (`` (cond (~~ (template [ ] [(type@= type) ] [type.boolean ] [type.byte ] [type.short ] [type.int ] [type.long ] [type.float ] [type.double ] [type.char ])) ... else (undefined))))] [primitive_wrapper box.boolean box.byte box.short box.int box.long box.float box.double box.char] [primitive_unwrap "booleanValue" "byteValue" "shortValue" "intValue" "longValue" "floatValue" "doubleValue" "charValue"] ) (def: .public (wrap type) (-> (Type Primitive) Inst) (let [wrapper (type.class (primitive_wrapper type) (list))] (INVOKESTATIC wrapper "valueOf" (type.method [(list) (list type) wrapper (list)])))) (def: .public (unwrap type) (-> (Type Primitive) Inst) (let [wrapper (type.class (primitive_wrapper type) (list))] (|>> (CHECKCAST wrapper) (INVOKEVIRTUAL wrapper (primitive_unwrap type) (type.method [(list) (list) type (list)]))))) (def: .public (fuse insts) (-> (List Inst) Inst) (case insts #.End function.identity (#.Item singleton #.End) singleton (#.Item head tail) (function.composite (fuse tail) head)))