(.module: [lux (#- Type) [abstract [monad (#+ do)]] [data [collection ["." list ("#@." functor)]]] ["." math] [target [jvm ["." type (#+ Type) ["." category (#+ Void Value Return Primitive Object Class Array Var Parameter Method)] ["." descriptor (#+ Descriptor)] ["." signature (#+ Signature)]]]] [tool [compiler [arity (#+ Arity)] ["." synthesis] ["." phase ["." generation]]]]] [luxc [lang [host ["$" jvm (#+ Label Inst Def Operation) ["$d" def] ["_" inst]]]]] ["." // (#+ ByteCode)]) (def: $Text (type.class "java.lang.String" (list))) (def: #export $Tag type.int) (def: #export $Flag (type.class "java.lang.Object" (list))) (def: #export $Value (type.class "java.lang.Object" (list))) (def: #export $Index type.int) (def: #export $Stack (type.array $Value)) (def: $Throwable (type.class "java.lang.Throwable" (list))) (def: #export $Runtime (type.class "java.lang.Runtime" (list))) (def: nullary-init-methodT (type.method [(list) type.void (list)])) (def: throw-methodT (type.method [(list) type.void (list)])) (def: #export logI Inst (let [PrintStream (type.class "java.io.PrintStream" (list)) outI (_.GETSTATIC (type.class "java.lang.System" (list)) "out" PrintStream) printI (function (_ method) (_.INVOKEVIRTUAL PrintStream method (type.method [(list $Value) type.void (list)])))] (|>> outI (_.string "LOG: ") (printI "print") outI _.SWAP (printI "println")))) (def: variant-method (type.method [(list $Tag $Flag $Value) //.$Variant (list)])) (def: #export variantI Inst (_.INVOKESTATIC (type.class //.runtime-class (list)) "variant_make" variant-method)) (def: #export leftI Inst (|>> (_.int +0) _.NULL _.DUP2_X1 _.POP2 variantI)) (def: #export rightI Inst (|>> (_.int +1) (_.string "") _.DUP2_X1 _.POP2 variantI)) (def: #export someI Inst rightI) (def: #export noneI Inst (|>> (_.int +0) _.NULL (_.string synthesis.unit) variantI)) (def: (try-methodI unsafeI) (-> Inst Inst) (<| _.with-label (function (_ @from)) _.with-label (function (_ @to)) _.with-label (function (_ @handler)) (|>> (_.try @from @to @handler (type.class "java.lang.Exception" (list))) (_.label @from) unsafeI someI _.ARETURN (_.label @to) (_.label @handler) noneI _.ARETURN))) (def: #export string-concatI Inst (_.INVOKEVIRTUAL $Text "concat" (type.method [(list $Text) $Text (list)]))) (def: #export partials-field Text "partials") (def: #export apply-method Text "apply") (def: #export num-apply-variants Nat 8) (def: #export (apply-signature arity) (-> Arity [(Signature Method) (Descriptor Method)]) (type.method [(list.repeat arity $Value) $Value (list)])) (def: adt-methods Def (let [store-tagI (|>> _.DUP (_.int +0) (_.ILOAD 0) (_.wrap type.int) _.AASTORE) store-flagI (|>> _.DUP (_.int +1) (_.ALOAD 1) _.AASTORE) store-valueI (|>> _.DUP (_.int +2) (_.ALOAD 2) _.AASTORE)] (|>> ($d.method #$.Public $.staticM "variant_make" (type.method [(list $Tag $Flag $Value) //.$Variant (list)]) (|>> (_.int +3) (_.ANEWARRAY $Value) store-tagI store-flagI store-valueI _.ARETURN))))) (def: frac-shiftI Inst (_.double (math.pow +32.0 +2.0))) (def: frac-methods Def (|>> ($d.method #$.Public $.staticM "decode_frac" (type.method [(list $Text) //.$Variant (list)]) (try-methodI (|>> (_.ALOAD 0) (_.INVOKESTATIC (type.class "java.lang.Double" (list)) "parseDouble" (type.method [(list $Text) type.double (list)])) (_.wrap type.double)))) )) (def: #export popI (|>> (_.int +1) _.AALOAD (_.CHECKCAST $Stack))) (def: #export peekI (|>> (_.int +0) _.AALOAD)) (def: (illegal-state-exception message) (-> Text Inst) (let [IllegalStateException (type.class "java.lang.IllegalStateException" (list))] (|>> (_.NEW IllegalStateException) _.DUP (_.string message) (_.INVOKESPECIAL IllegalStateException "" (type.method [(list $Text) type.void (list)]))))) (def: pm-methods Def (let [tuple-sizeI (|>> (_.ALOAD 0) _.ARRAYLENGTH) last-rightI (|>> tuple-sizeI (_.int +1) _.ISUB) leftsI (_.ILOAD 1) left-indexI leftsI sub-leftsI (|>> leftsI last-rightI _.ISUB) sub-tupleI (|>> (_.ALOAD 0) last-rightI _.AALOAD (_.CHECKCAST //.$Tuple)) recurI (: (-> Label Inst) (function (_ @loop) (|>> sub-leftsI (_.ISTORE 1) sub-tupleI (_.ASTORE 0) (_.GOTO @loop))))] (|>> ($d.method #$.Public $.staticM "pm_fail" throw-methodT (|>> (illegal-state-exception "Invalid expression for pattern-matching.") _.ATHROW)) ($d.method #$.Public $.staticM "apply_fail" throw-methodT (|>> (illegal-state-exception "Error while applying function.") _.ATHROW)) ($d.method #$.Public $.staticM "pm_push" (type.method [(list $Stack $Value) $Stack (list)]) (|>> (_.int +2) (_.ANEWARRAY $Value) _.DUP (_.int +1) (_.ALOAD 0) _.AASTORE _.DUP (_.int +0) (_.ALOAD 1) _.AASTORE _.ARETURN)) ($d.method #$.Public $.staticM "pm_variant" (type.method [(list //.$Variant $Tag $Flag) $Value (list)]) (<| _.with-label (function (_ @loop)) _.with-label (function (_ @just-return)) _.with-label (function (_ @then)) _.with-label (function (_ @further)) _.with-label (function (_ @shorten)) _.with-label (function (_ @wrong)) (let [variant-partI (: (-> Nat Inst) (function (_ idx) (|>> (_.int (.int idx)) _.AALOAD))) tagI (: Inst (|>> (variant-partI 0) (_.unwrap type.int))) flagI (variant-partI 1) datumI (variant-partI 2) shortenI (|>> (_.ALOAD 0) tagI ## Get tag (_.ILOAD 1) _.ISUB ## Shorten tag (_.ALOAD 0) flagI ## Get flag (_.ALOAD 0) datumI ## Get value variantI ## Build sum _.ARETURN) update-tagI (|>> _.ISUB (_.ISTORE 1)) update-variantI (|>> (_.ALOAD 0) datumI (_.CHECKCAST //.$Variant) (_.ASTORE 0)) failureI (|>> _.NULL _.ARETURN) return-datumI (|>> (_.ALOAD 0) datumI _.ARETURN)]) (|>> (_.label @loop) (_.ILOAD 1) ## tag (_.ALOAD 0) tagI ## tag, sumT _.DUP2 (_.IF_ICMPEQ @then) _.DUP2 (_.IF_ICMPGT @further) _.DUP2 (_.IF_ICMPLT @shorten) ## _.POP2 failureI (_.label @then) ## tag, sumT (_.ALOAD 2) ## tag, sumT, wants-last? (_.ALOAD 0) flagI ## tag, sumT, wants-last?, is-last? (_.IF_ACMPEQ @just-return) ## tag, sumT (_.label @further) ## tag, sumT (_.ALOAD 0) flagI ## tag, sumT, last? (_.IFNULL @wrong) ## tag, sumT update-tagI update-variantI (_.GOTO @loop) (_.label @just-return) ## tag, sumT ## _.POP2 return-datumI (_.label @shorten) ## tag, sumT (_.ALOAD 2) (_.IFNULL @wrong) ## _.POP2 shortenI (_.label @wrong) ## tag, sumT ## _.POP2 failureI))) ($d.method #$.Public $.staticM "tuple_left" (type.method [(list //.$Tuple $Index) $Value (list)]) (<| _.with-label (function (_ @loop)) _.with-label (function (_ @recursive)) (let [left-accessI (|>> (_.ALOAD 0) left-indexI _.AALOAD)]) (|>> (_.label @loop) leftsI last-rightI (_.IF_ICMPGE @recursive) left-accessI _.ARETURN (_.label @recursive) ## Recursive (recurI @loop)))) ($d.method #$.Public $.staticM "tuple_right" (type.method [(list //.$Tuple $Index) $Value (list)]) (<| _.with-label (function (_ @loop)) _.with-label (function (_ @not-tail)) _.with-label (function (_ @slice)) (let [right-indexI (|>> leftsI (_.int +1) _.IADD) right-accessI (|>> (_.ALOAD 0) _.SWAP _.AALOAD) sub-rightI (|>> (_.ALOAD 0) right-indexI tuple-sizeI (_.INVOKESTATIC (type.class "java.util.Arrays" (list)) "copyOfRange" (type.method [(list //.$Tuple $Index $Index) //.$Tuple (list)])))]) (|>> (_.label @loop) last-rightI right-indexI _.DUP2 (_.IF_ICMPNE @not-tail) ## _.POP right-accessI _.ARETURN (_.label @not-tail) (_.IF_ICMPGT @slice) ## Must recurse (recurI @loop) (_.label @slice) sub-rightI _.ARETURN ))) ))) (def: io-methods Def (let [StringWriter (type.class "java.io.StringWriter" (list)) PrintWriter (type.class "java.io.PrintWriter" (list)) string-writerI (|>> (_.NEW StringWriter) _.DUP (_.INVOKESPECIAL StringWriter "" nullary-init-methodT)) print-writerI (|>> (_.NEW PrintWriter) _.SWAP _.DUP2 _.POP _.SWAP (_.boolean true) (_.INVOKESPECIAL PrintWriter "" (type.method [(list (type.class "java.io.Writer" (list)) type.boolean) type.void (list)])) )] (|>> ($d.method #$.Public $.staticM "try" (type.method [(list //.$Function) //.$Variant (list)]) (<| _.with-label (function (_ @from)) _.with-label (function (_ @to)) _.with-label (function (_ @handler)) (|>> (_.try @from @to @handler $Throwable) (_.label @from) (_.ALOAD 0) _.NULL (_.INVOKEVIRTUAL //.$Function apply-method (apply-signature 1)) rightI _.ARETURN (_.label @to) (_.label @handler) string-writerI ## TW _.DUP2 ## TWTW print-writerI ## TWTP (_.INVOKEVIRTUAL $Throwable "printStackTrace" (type.method [(list (type.class "java.io.PrintWriter" (list))) type.void (list)])) ## TW (_.INVOKEVIRTUAL StringWriter "toString" (type.method [(list) $Text (list)])) ## TS _.SWAP _.POP leftI _.ARETURN))) ))) (def: translate-runtime (Operation ByteCode) (let [bytecode ($d.class #$.V1_6 #$.Public $.finalC //.runtime-class (list) (type.class "java.lang.Object" (list)) (list) (|>> adt-methods frac-methods pm-methods io-methods))] (do phase.monad [_ (generation.execute! //.runtime-class [//.runtime-class bytecode])] (wrap bytecode)))) (def: translate-function (Operation ByteCode) (let [applyI (|> (list.n/range 2 num-apply-variants) (list@map (function (_ arity) ($d.method #$.Public $.noneM apply-method (apply-signature arity) (let [preI (|> (list.n/range 0 (dec arity)) (list@map _.ALOAD) _.fuse)] (|>> preI (_.INVOKEVIRTUAL //.$Function apply-method (apply-signature (dec arity))) (_.CHECKCAST //.$Function) (_.ALOAD arity) (_.INVOKEVIRTUAL //.$Function apply-method (apply-signature 1)) _.ARETURN))))) (list& ($d.abstract-method #$.Public $.noneM apply-method (apply-signature 1))) $d.fuse) $Object (type.class "java.lang.Object" (list)) bytecode ($d.abstract #$.V1_6 #$.Public $.noneC //.function-class (list) $Object (list) (|>> ($d.field #$.Public $.finalF partials-field type.int) ($d.method #$.Public $.noneM "" (type.method [(list type.int) type.void (list)]) (|>> (_.ALOAD 0) (_.INVOKESPECIAL $Object "" nullary-init-methodT) (_.ALOAD 0) (_.ILOAD 1) (_.PUTFIELD //.$Function partials-field type.int) _.RETURN)) applyI))] (do phase.monad [_ (generation.execute! //.function-class [//.function-class bytecode])] (wrap bytecode)))) (def: #export translate (Operation Any) (do phase.monad [runtime-bc translate-runtime function-bc translate-function] (wrap [])))