(;module: [lux #- char] (lux (control monad ["p" parser]) (data [maybe] ["R" result] text/format (coll [list "L/" Functor])) [host #+ do-to] [macro] (macro [code] ["s" syntax #+ syntax:])) ["$" ..] (.. ["$t" type])) ## [Host] (host;import #long java.lang.Object) (host;import #long java.lang.String) (syntax: (declare [codes (p;many s;local-symbol)]) (|> codes (L/map (function [code] (` ((~' #static) (~ (code;local-symbol code)) (~' int))))) wrap)) (with-expansions [ (declare D2F D2I D2L F2D F2I F2L I2B I2C I2D I2F I2L I2S L2D L2F L2I) (declare T_BOOLEAN T_CHAR T_FLOAT T_DOUBLE T_BYTE T_SHORT T_INT T_LONG) (declare DUP DUP2 DUP2_X1 DUP2_X2 POP POP2 SWAP) (declare IF_ICMPEQ IF_ICMPGT IF_ICMPLT IF_ACMPEQ IFNULL IFEQ IFNE IFLT IFLE IFGT IFGE GOTO) (declare ILOAD LLOAD DLOAD ALOAD ISTORE LSTORE ASTORE) (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) (declare IAND IOR IXOR ISHL ISHR IUSHR LAND LOR LXOR LSHL LSHR LUSHR) (declare RETURN IRETURN LRETURN DRETURN ARETURN)] (host;import org.objectweb.asm.Opcodes (#static NOP int) (#static CHECKCAST int) (#static NEW int) (#static NEWARRAY int) (#static ANEWARRAY int) (#static ACONST_NULL int) (#static AALOAD int) (#static AASTORE int) (#static ARRAYLENGTH int) (#static GETSTATIC int) (#static PUTSTATIC int) (#static GETFIELD int) (#static PUTFIELD int) (#static INVOKESTATIC int) (#static INVOKESPECIAL int) (#static INVOKEVIRTUAL int) (#static ATHROW int) )) (host;import org.objectweb.asm.FieldVisitor (visitEnd [] void)) (host;import org.objectweb.asm.Label (new [])) (host;import org.objectweb.asm.MethodVisitor (visitCode [] void) (visitMaxs [int int] void) (visitEnd [] void) (visitInsn [int] void) (visitLdcInsn [Object] void) (visitFieldInsn [int String String String] void) (visitTypeInsn [int String] void) (visitVarInsn [int int] void) (visitIntInsn [int int] void) (visitMethodInsn [int String String String boolean] void) (visitLabel [Label] void) (visitJumpInsn [int Label] void) (visitTryCatchBlock [Label Label Label String] void) (visitTableSwitchInsn [int int Label (Array Label)] void) ) ## [Insts] (def: #export make-label (Lux Label) (function [compiler] (#R;Success [compiler (Label.new [])]))) (def: #export (with-label action) (-> (-> Label $;Inst) $;Inst) (action (Label.new []))) (do-template [ ] [(def: #export ( value) (-> $;Inst) (function [visitor] (do-to visitor (MethodVisitor.visitLdcInsn [( value)]))))] [boolean Bool id] [int Int host;l2i] [long Int id] [double Frac id] [char Nat (|>. nat-to-int host;l2i host;i2c)] [string Text id] ) (syntax: (prefix [base s;local-symbol]) (wrap (list (code;local-symbol (format "Opcodes." base))))) (def: #export NULL $;Inst (function [visitor] (do-to visitor (MethodVisitor.visitInsn [(prefix ACONST_NULL)])))) (do-template [] [(def: #export $;Inst (function [visitor] (do-to visitor (MethodVisitor.visitInsn [(prefix )]))))] [NOP] ## Stack [DUP] [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 arithmethic [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 [AALOAD] [AASTORE] [ARRAYLENGTH] ## Exceptions [ATHROW] ## Return [RETURN] [IRETURN] [LRETURN] [DRETURN] [ARETURN] ) (do-template [] [(def: #export ( register) (-> Nat $;Inst) (function [visitor] (do-to visitor (MethodVisitor.visitVarInsn [(prefix ) (nat-to-int register)]))))] [ILOAD] [LLOAD] [DLOAD] [ALOAD] [ISTORE] [LSTORE] [ASTORE] ) (do-template [ ] [(def: #export ( class field type) (-> Text Text $;Type $;Inst) (function [visitor] (do-to visitor (MethodVisitor.visitFieldInsn [ ($t;binary-name class) field ($t;descriptor type)]))))] [GETSTATIC Opcodes.GETSTATIC] [PUTSTATIC Opcodes.PUTSTATIC] [PUTFIELD Opcodes.PUTFIELD] [GETFIELD Opcodes.GETFIELD] ) (do-template [ ] [(def: #export ( class) (-> Text $;Inst) (function [visitor] (do-to visitor (MethodVisitor.visitTypeInsn [ ($t;binary-name class)]))))] [CHECKCAST Opcodes.CHECKCAST] [NEW Opcodes.NEW] [ANEWARRAY Opcodes.ANEWARRAY] ) (def: #export (NEWARRAY type) (-> $;Primitive $;Inst) (function [visitor] (do-to visitor (MethodVisitor.visitIntInsn [Opcodes.NEWARRAY (case type #$;Boolean Opcodes.T_BOOLEAN #$;Byte Opcodes.T_SHORT #$;Short Opcodes.T_SHORT #$;Int Opcodes.T_INT #$;Long Opcodes.T_LONG #$;Float Opcodes.T_FLOAT #$;Double Opcodes.T_DOUBLE #$;Char Opcodes.T_CHAR)])))) (do-template [ ] [(def: #export ( class method-name method-signature interface?) (-> Text Text $;Method Bool $;Inst) (function [visitor] (do-to visitor (MethodVisitor.visitMethodInsn [ ($t;binary-name class) method-name ($t;method-descriptor method-signature) interface?]))))] [INVOKESTATIC Opcodes.INVOKESTATIC] [INVOKEVIRTUAL Opcodes.INVOKEVIRTUAL] [INVOKESPECIAL Opcodes.INVOKESPECIAL] ) (do-template [] [(def: #export ( @where) (-> $;Label $;Inst) (function [visitor] (do-to visitor (MethodVisitor.visitJumpInsn [(prefix ) @where]))))] [IF_ICMPEQ] [IF_ICMPGT] [IF_ICMPLT] [IF_ACMPEQ] [IFNULL] [IFEQ] [IFNE] [IFLT] [IFLE] [IFGT] [IFGE] [GOTO] ) (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 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 (n.inc idx))) []))] (do-to visitor (MethodVisitor.visitTableSwitchInsn [min max default labels-array]))))) (def: #export (try @from @to @handler exception) (-> $;Label $;Label $;Label Text $;Inst) (function [visitor] (do-to visitor (MethodVisitor.visitTryCatchBlock [@from @to @handler ($t;binary-name exception)])))) (def: #export (label @label) (-> $;Label $;Inst) (function [visitor] (do-to visitor (MethodVisitor.visitLabel [@label])))) (def: #export (array type size) (-> $;Type Nat $;Inst) (case type (#$;Primitive prim) (|>. (int (nat-to-int size)) (NEWARRAY prim)) (#$;Generic generic) (let [elem-class (case generic (#$;Class class params) ($t;binary-name class) _ ($t;binary-name "java.lang.Object"))] (|>. (int (nat-to-int size)) (ANEWARRAY elem-class))) _ (|>. (int (nat-to-int size)) (ANEWARRAY ($t;descriptor type))))) (def: (primitive-wrapper type) (-> $;Primitive Text) (case type #$;Boolean "java.lang.Boolean" #$;Byte "java.lang.Byte" #$;Short "java.lang.Short" #$;Int "java.lang.Integer" #$;Long "java.lang.Long" #$;Float "java.lang.Float" #$;Double "java.lang.Double" #$;Char "java.lang.Character")) (def: (primitive-unwrap type) (-> $;Primitive Text) (case type #$;Boolean "booleanValue" #$;Byte "byteValue" #$;Short "shortValue" #$;Int "intValue" #$;Long "longValue" #$;Float "floatValue" #$;Double "doubleValue" #$;Char "charValue")) (def: #export (wrap type) (-> $;Primitive $;Inst) (let [class (primitive-wrapper type)] (|>. (INVOKESTATIC class "valueOf" ($t;method (list (#$;Primitive type)) (#;Some ($t;class class (list))) (list)) false)))) (def: #export (unwrap type) (-> $;Primitive $;Inst) (let [class (primitive-wrapper type)] (|>. (CHECKCAST class) (INVOKEVIRTUAL class (primitive-unwrap type) ($t;method (list) (#;Some (#$;Primitive type)) (list)) false)))) (def: #export (fuse insts) (-> (List $;Inst) $;Inst) (case insts #;Nil id (#;Cons singleton #;Nil) singleton (#;Cons head tail) (. (fuse tail) head)))