(.module: [lux (#- Type int char) ["." host (#+ import: do-to)] [abstract [monad (#+ do)]] [control ["." function] ["p" parser ["s" code]]] [data ["." product] ["." maybe] ["." error] [text format] [collection ["." list ("#@." functor)]]] [macro ["." code] ["." template] [syntax (#+ syntax:)]] [target [jvm ["." type (#+ Primitive Method Type)]]] [tool [compiler [phase (#+ Operation)]]]] ["." // (#+ Inst)]) ## [Host] (import: #long java/lang/Object) (import: #long java/lang/String) (syntax: (declare {codes (p.many s.local-identifier)}) (|> codes (list@map (function (_ code) (` ((~' #static) (~ (code.local-identifier code)) (~' int))))) wrap)) (`` (import: #long 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 IFNULL IFEQ IFNE IFLT IFLE IFGT IFGE GOTO)) (#static ACONST_NULL int) ## Var (~~ (declare ILOAD LLOAD DLOAD ALOAD ISTORE LSTORE ASTORE)) ## Arithmetic (~~ (declare IADD ISUB IMUL IDIV IREM LADD LSUB LMUL LDIV LREM LCMP FADD FSUB FMUL FDIV FREM FCMPG FCMPL DADD DSUB DMUL DDIV DREM 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 DRETURN ARETURN)) )) (import: #long org/objectweb/asm/Label (new [])) (import: #long 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: #export make-label (All [s] (Operation s org/objectweb/asm/Label)) (function (_ state) (#error.Success [state (org/objectweb/asm/Label::new)]))) (def: #export (with-label action) (All [a] (-> (-> org/objectweb/asm/Label a) a)) (action (org/objectweb/asm/Label::new))) (template [ ] [(def: #export ( value) (-> Inst) (function (_ visitor) (do-to visitor (org/objectweb/asm/MethodVisitor::visitLdcInsn ( value)))))] [boolean Bit function.identity] [int Int host.long-to-int] [long Int function.identity] [double Frac function.identity] [char Nat (|>> .int host.long-to-int host.int-to-char)] [string Text function.identity] ) (template: (prefix short) (`` ((~~ (template.identifier ["org/objectweb/asm/Opcodes::" short]))))) (def: #export NULL Inst (function (_ visitor) (do-to visitor (org/objectweb/asm/MethodVisitor::visitInsn (prefix ACONST_NULL))))) (template [] [(def: #export 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] ## Integer bitwise [IAND] [IOR] [IXOR] [ISHL] [ISHR] [IUSHR] ## Long arithmetic [LADD] [LSUB] [LMUL] [LDIV] [LREM] [LCMP] ## Long bitwise [LAND] [LOR] [LXOR] [LSHL] [LSHR] [LUSHR] ## Float arithmetic [FADD] [FSUB] [FMUL] [FDIV] [FREM] [FCMPG] [FCMPL] ## Double arithmetic [DADD] [DSUB] [DMUL] [DDIV] [DREM] [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] [DRETURN] [ARETURN] ) (template [] [(def: #export ( register) (-> Nat Inst) (function (_ visitor) (do-to visitor (org/objectweb/asm/MethodVisitor::visitVarInsn (prefix ) (.int register)))))] [ILOAD] [LLOAD] [DLOAD] [ALOAD] [ISTORE] [LSTORE] [ASTORE] ) (template [ ] [(def: #export ( class field type) (-> Text Text Type Inst) (function (_ visitor) (do-to visitor (org/objectweb/asm/MethodVisitor::visitFieldInsn () (type.binary-name class) field (type.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 [ ] [(def: #export ( class) (-> Text Inst) (function (_ visitor) (do-to visitor (org/objectweb/asm/MethodVisitor::visitTypeInsn () (type.binary-name class)))))] [CHECKCAST org/objectweb/asm/Opcodes::CHECKCAST] [NEW org/objectweb/asm/Opcodes::NEW] [INSTANCEOF org/objectweb/asm/Opcodes::INSTANCEOF] [ANEWARRAY org/objectweb/asm/Opcodes::ANEWARRAY] ) (def: #export (NEWARRAY type) (-> Primitive Inst) (function (_ visitor) (do-to visitor (org/objectweb/asm/MethodVisitor::visitIntInsn (org/objectweb/asm/Opcodes::NEWARRAY) (case 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)))))) (template [ ] [(def: #export ( class method-name method-signature interface?) (-> Text Text Method Bit Inst) (function (_ visitor) (do-to visitor (org/objectweb/asm/MethodVisitor::visitMethodInsn () (type.binary-name class) method-name (type.method-descriptor method-signature) interface?))))] [INVOKESTATIC org/objectweb/asm/Opcodes::INVOKESTATIC] [INVOKEVIRTUAL org/objectweb/asm/Opcodes::INVOKEVIRTUAL] [INVOKESPECIAL org/objectweb/asm/Opcodes::INVOKESPECIAL] [INVOKEINTERFACE org/objectweb/asm/Opcodes::INVOKEINTERFACE] ) (template [] [(def: #export ( @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] [IFNULL] [IFEQ] [IFNE] [IFLT] [IFLE] [IFGT] [IFGE] [GOTO] ) (def: #export (LOOKUPSWITCH default keys+labels) (-> //.Label (List [Int //.Label]) Inst) (function (_ visitor) (let [keys+labels (list.sort (function (_ left right) (i/< (product.left left) (product.left right))) keys+labels) array-size (list.size keys+labels) keys-array (host.array int array-size) labels-array (host.array org/objectweb/asm/Label array-size) _ (loop [idx 0] (if (n/< array-size idx) (let [[key label] (maybe.assume (list.nth idx keys+labels))] (exec (host.array-write idx (host.long-to-int key) keys-array) (host.array-write idx label labels-array) (recur (inc idx)))) []))] (do-to visitor (org/objectweb/asm/MethodVisitor::visitLookupSwitchInsn default keys-array labels-array))))) (def: #export (TABLESWITCH min max default labels) (-> Int Int //.Label (List //.Label) Inst) (function (_ visitor) (let [num-labels (list.size labels) labels-array (host.array org/objectweb/asm/Label num-labels) _ (loop [idx 0] (if (n/< num-labels idx) (exec (host.array-write idx (maybe.assume (list.nth idx labels)) labels-array) (recur (inc idx))) []))] (do-to visitor (org/objectweb/asm/MethodVisitor::visitTableSwitchInsn min max default labels-array))))) (def: #export (try @from @to @handler exception) (-> //.Label //.Label //.Label Text Inst) (function (_ visitor) (do-to visitor (org/objectweb/asm/MethodVisitor::visitTryCatchBlock @from @to @handler (type.binary-name exception))))) (def: #export (label @label) (-> //.Label Inst) (function (_ visitor) (do-to visitor (org/objectweb/asm/MethodVisitor::visitLabel @label)))) (def: #export (array type) (-> Type Inst) (case type (#type.Primitive prim) (NEWARRAY prim) (#type.Generic generic) (let [elem-class (case generic (#type.Class class params) (type.binary-name class) _ (type.binary-name "java.lang.Object"))] (ANEWARRAY elem-class)) _ (ANEWARRAY (type.descriptor type)))) (def: (primitive-wrapper type) (-> Primitive Text) (case type #type.Boolean "java.lang.Boolean" #type.Byte "java.lang.Byte" #type.Short "java.lang.Short" #type.Int "java.lang.Integer" #type.Long "java.lang.Long" #type.Float "java.lang.Float" #type.Double "java.lang.Double" #type.Char "java.lang.Character")) (def: (primitive-unwrap type) (-> Primitive Text) (case type #type.Boolean "booleanValue" #type.Byte "byteValue" #type.Short "shortValue" #type.Int "intValue" #type.Long "longValue" #type.Float "floatValue" #type.Double "doubleValue" #type.Char "charValue")) (def: #export (wrap type) (-> Primitive Inst) (let [class (primitive-wrapper type)] (|>> (INVOKESTATIC class "valueOf" (type.method (list (#type.Primitive type)) (#.Some (type.class class (list))) (list)) #0)))) (def: #export (unwrap type) (-> Primitive Inst) (let [class (primitive-wrapper type)] (|>> (CHECKCAST class) (INVOKEVIRTUAL class (primitive-unwrap type) (type.method (list) (#.Some (#type.Primitive type)) (list)) #0)))) (def: #export (fuse insts) (-> (List Inst) Inst) (case insts #.Nil function.identity (#.Cons singleton #.Nil) singleton (#.Cons head tail) (function.compose (fuse tail) head)))