aboutsummaryrefslogtreecommitdiff
path: root/lux-jvm/source/luxc/lang/translation
diff options
context:
space:
mode:
authorEduardo Julian2020-05-30 15:19:28 -0400
committerEduardo Julian2020-05-30 15:19:28 -0400
commitb4d0eba7485caf0c6cf58de1193a9114fa273d8b (patch)
treef6f7fa2967bb5923347db1ed1d4c9b08e56bf8c6 /lux-jvm/source/luxc/lang/translation
parent6eaa3b57f3f1ea2ce13b942bdb4ef502fc1729bc (diff)
Split new-luxc into lux-jvm and lux-r.
Diffstat (limited to 'lux-jvm/source/luxc/lang/translation')
-rw-r--r--lux-jvm/source/luxc/lang/translation/jvm.lux182
-rw-r--r--lux-jvm/source/luxc/lang/translation/jvm/case.lux239
-rw-r--r--lux-jvm/source/luxc/lang/translation/jvm/common.lux72
-rw-r--r--lux-jvm/source/luxc/lang/translation/jvm/expression.lux72
-rw-r--r--lux-jvm/source/luxc/lang/translation/jvm/extension.lux16
-rw-r--r--lux-jvm/source/luxc/lang/translation/jvm/extension/common.lux388
-rw-r--r--lux-jvm/source/luxc/lang/translation/jvm/extension/host.lux1047
-rw-r--r--lux-jvm/source/luxc/lang/translation/jvm/function.lux331
-rw-r--r--lux-jvm/source/luxc/lang/translation/jvm/loop.lux81
-rw-r--r--lux-jvm/source/luxc/lang/translation/jvm/primitive.lux30
-rw-r--r--lux-jvm/source/luxc/lang/translation/jvm/program.lux82
-rw-r--r--lux-jvm/source/luxc/lang/translation/jvm/reference.lux65
-rw-r--r--lux-jvm/source/luxc/lang/translation/jvm/runtime.lux387
-rw-r--r--lux-jvm/source/luxc/lang/translation/jvm/structure.lux79
14 files changed, 3071 insertions, 0 deletions
diff --git a/lux-jvm/source/luxc/lang/translation/jvm.lux b/lux-jvm/source/luxc/lang/translation/jvm.lux
new file mode 100644
index 000000000..141e70184
--- /dev/null
+++ b/lux-jvm/source/luxc/lang/translation/jvm.lux
@@ -0,0 +1,182 @@
+(.module:
+ [lux (#- Module Definition)
+ ["." host (#+ import: do-to object)]
+ [abstract
+ [monad (#+ do)]]
+ [control
+ pipe
+ ["." try (#+ Try)]
+ ["." exception (#+ exception:)]
+ ["." io (#+ IO io)]
+ [concurrency
+ ["." atom (#+ Atom atom)]]]
+ [data
+ [binary (#+ Binary)]
+ ["." product]
+ ["." text ("#@." hash)
+ ["%" format (#+ format)]]
+ [collection
+ ["." array]
+ ["." dictionary (#+ Dictionary)]]]
+ [target
+ [jvm
+ ["." loader (#+ Library)]
+ ["." type
+ ["." descriptor]]]]
+ [tool
+ [compiler
+ [language
+ [lux
+ ["." generation]]]
+ ["." meta
+ [io (#+ lux-context)]
+ [archive
+ [descriptor (#+ Module)]
+ ["." artifact]]]]]]
+ [///
+ [host
+ ["." jvm (#+ Inst Definition Host State)
+ ["." def]
+ ["." inst]]]]
+ )
+
+(import: #long java/lang/reflect/Field
+ (get [#? java/lang/Object] #try #? java/lang/Object))
+
+(import: #long (java/lang/Class a)
+ (getField [java/lang/String] #try java/lang/reflect/Field))
+
+(import: #long java/lang/Object
+ (getClass [] (java/lang/Class java/lang/Object)))
+
+(import: #long java/lang/ClassLoader)
+
+(type: #export ByteCode Binary)
+
+(def: #export value-field Text "_value")
+(def: #export $Value (type.class "java.lang.Object" (list)))
+
+(exception: #export (cannot-load {class Text} {error Text})
+ (exception.report
+ ["Class" class]
+ ["Error" error]))
+
+(exception: #export (invalid-field {class Text} {field Text} {error Text})
+ (exception.report
+ ["Class" class]
+ ["Field" field]
+ ["Error" error]))
+
+(exception: #export (invalid-value {class Text})
+ (exception.report
+ ["Class" class]))
+
+(def: (class-value class-name class)
+ (-> Text (java/lang/Class java/lang/Object) (Try Any))
+ (case (java/lang/Class::getField ..value-field class)
+ (#try.Success field)
+ (case (java/lang/reflect/Field::get #.None field)
+ (#try.Success ?value)
+ (case ?value
+ (#.Some value)
+ (#try.Success value)
+
+ #.None
+ (exception.throw ..invalid-value class-name))
+
+ (#try.Failure error)
+ (exception.throw ..cannot-load [class-name error]))
+
+ (#try.Failure error)
+ (exception.throw ..invalid-field [class-name ..value-field error])))
+
+(def: class-path-separator ".")
+
+(def: #export bytecode-name
+ (-> Text Text)
+ (text.replace-all ..class-path-separator .module-separator))
+
+(def: #export (class-name [module-id artifact-id])
+ (-> generation.Context Text)
+ (format lux-context
+ ..class-path-separator (%.nat meta.version)
+ ..class-path-separator (%.nat module-id)
+ ..class-path-separator (%.nat artifact-id)))
+
+(def: (evaluate! library loader eval-class valueI)
+ (-> Library java/lang/ClassLoader Text Inst (Try [Any Definition]))
+ (let [bytecode-name (..bytecode-name eval-class)
+ bytecode (def.class #jvm.V1_6
+ #jvm.Public jvm.noneC
+ bytecode-name
+ (list) $Value
+ (list)
+ (|>> (def.field #jvm.Public ($_ jvm.++F jvm.finalF jvm.staticF)
+ ..value-field ..$Value)
+ (def.method #jvm.Public ($_ jvm.++M jvm.staticM jvm.strictM)
+ "<clinit>"
+ (type.method [(list) type.void (list)])
+ (|>> valueI
+ (inst.PUTSTATIC (type.class bytecode-name (list)) ..value-field ..$Value)
+ inst.RETURN))))]
+ (io.run (do (try.with io.monad)
+ [_ (loader.store eval-class bytecode library)
+ class (loader.load eval-class loader)
+ value (:: io.monad wrap (..class-value eval-class class))]
+ (wrap [value
+ [eval-class bytecode]])))))
+
+(def: (execute! library loader temp-label [class-name class-bytecode])
+ (-> Library java/lang/ClassLoader Text Definition (Try Any))
+ (io.run (do (try.with io.monad)
+ [existing-class? (|> (atom.read library)
+ (:: io.monad map (dictionary.contains? class-name))
+ (try.lift io.monad)
+ (: (IO (Try Bit))))
+ _ (if existing-class?
+ (wrap [])
+ (loader.store class-name class-bytecode library))]
+ (loader.load class-name loader))))
+
+(def: (define! library loader context valueI)
+ (-> Library java/lang/ClassLoader generation.Context Inst (Try [Text Any Definition]))
+ (let [class-name (..class-name context)]
+ (do try.monad
+ [[value definition] (evaluate! library loader class-name valueI)]
+ (wrap [class-name value definition]))))
+
+(def: #export host
+ (IO Host)
+ (io (let [library (loader.new-library [])
+ loader (loader.memory library)]
+ (: Host
+ (structure
+ (def: (evaluate! temp-label valueI)
+ (:: try.monad map product.left
+ (..evaluate! library loader (text.replace-all " " "$" temp-label) valueI)))
+
+ (def: execute!
+ (..execute! library loader))
+
+ (def: define!
+ (..define! library loader))
+
+ (def: (ingest context bytecode)
+ [(..class-name context) bytecode])
+
+ (def: (re-learn context [_ bytecode])
+ (io.run
+ (loader.store (..class-name context) bytecode library)))
+
+ (def: (re-load context [_ bytecode])
+ (io.run
+ (do (try.with io.monad)
+ [#let [class-name (..class-name context)]
+ _ (loader.store class-name bytecode library)
+ class (loader.load class-name loader)]
+ (:: io.monad wrap (..class-value class-name class))))))))))
+
+(def: #export $Variant (type.array ..$Value))
+(def: #export $Tuple (type.array ..$Value))
+(def: #export $Runtime (type.class (..class-name [0 0]) (list)))
+(def: #export $Function (type.class (..class-name [0 1]) (list)))
diff --git a/lux-jvm/source/luxc/lang/translation/jvm/case.lux b/lux-jvm/source/luxc/lang/translation/jvm/case.lux
new file mode 100644
index 000000000..0d8aaa91e
--- /dev/null
+++ b/lux-jvm/source/luxc/lang/translation/jvm/case.lux
@@ -0,0 +1,239 @@
+(.module:
+ [lux (#- Type if let case)
+ [abstract
+ [monad (#+ do)]]
+ [control
+ ["." function]
+ ["ex" exception (#+ exception:)]]
+ [data
+ [number
+ ["n" nat]]]
+ [target
+ [jvm
+ ["." type (#+ Type)
+ ["." category (#+ Void Value Return Primitive Object Class Array Var Parameter Method)]
+ ["." descriptor (#+ Descriptor)]
+ ["." signature (#+ Signature)]]]]
+ [tool
+ [compiler
+ ["." phase ("operation@." monad)]
+ [meta
+ [archive (#+ Archive)]]
+ [language
+ [lux
+ ["." synthesis (#+ Path Synthesis)]]]]]]
+ [luxc
+ [lang
+ [host
+ ["$" jvm (#+ Label Inst Operation Phase Generator)
+ ["_" inst]]]]]
+ ["." //
+ ["." runtime]])
+
+(def: (pop-altI stack-depth)
+ (-> Nat Inst)
+ (.case stack-depth
+ 0 function.identity
+ 1 _.POP
+ 2 _.POP2
+ _ ## (n.> 2)
+ (|>> _.POP2
+ (pop-altI (n.- 2 stack-depth)))))
+
+(def: peekI
+ Inst
+ (|>> _.DUP
+ (_.int +0)
+ _.AALOAD))
+
+(def: pushI
+ Inst
+ (_.INVOKESTATIC //.$Runtime "pm_push" (type.method [(list runtime.$Stack //.$Value) runtime.$Stack (list)])))
+
+(def: popI
+ (|>> (_.int +1)
+ _.AALOAD
+ (_.CHECKCAST runtime.$Stack)))
+
+(def: (path' stack-depth @else @end phase archive path)
+ (-> Nat Label Label Phase Archive Path (Operation Inst))
+ (.case path
+ #synthesis.Pop
+ (operation@wrap ..popI)
+
+ (#synthesis.Bind register)
+ (operation@wrap (|>> peekI
+ (_.ASTORE register)))
+
+ (^ (synthesis.path/bit value))
+ (operation@wrap (.let [jumpI (.if value _.IFEQ _.IFNE)]
+ (|>> peekI
+ (_.unwrap type.boolean)
+ (jumpI @else))))
+
+ (^ (synthesis.path/i64 value))
+ (operation@wrap (|>> peekI
+ (_.unwrap type.long)
+ (_.long (.int value))
+ _.LCMP
+ (_.IFNE @else)))
+
+ (^ (synthesis.path/f64 value))
+ (operation@wrap (|>> peekI
+ (_.unwrap type.double)
+ (_.double value)
+ _.DCMPL
+ (_.IFNE @else)))
+
+ (^ (synthesis.path/text value))
+ (operation@wrap (|>> peekI
+ (_.string value)
+ (_.INVOKEVIRTUAL (type.class "java.lang.Object" (list))
+ "equals"
+ (type.method [(list //.$Value) type.boolean (list)]))
+ (_.IFEQ @else)))
+
+ (#synthesis.Then bodyS)
+ (do phase.monad
+ [bodyI (phase archive bodyS)]
+ (wrap (|>> (pop-altI stack-depth)
+ bodyI
+ (_.GOTO @end))))
+
+ (^template [<pattern> <flag> <prepare>]
+ (^ (<pattern> idx))
+ (operation@wrap (<| _.with-label (function (_ @success))
+ _.with-label (function (_ @fail))
+ (|>> peekI
+ (_.CHECKCAST //.$Variant)
+ (_.int (.int (<prepare> idx)))
+ <flag>
+ (_.INVOKESTATIC //.$Runtime "pm_variant" (type.method [(list //.$Variant runtime.$Tag runtime.$Flag) runtime.$Value (list)]))
+ _.DUP
+ (_.IFNULL @fail)
+ (_.GOTO @success)
+ (_.label @fail)
+ _.POP
+ (_.GOTO @else)
+ (_.label @success)
+ pushI))))
+ ([synthesis.side/left _.NULL function.identity]
+ [synthesis.side/right (_.string "") .inc])
+
+ (^ (synthesis.member/left lefts))
+ (operation@wrap (.let [accessI (.case lefts
+ 0
+ _.AALOAD
+
+ lefts
+ (_.INVOKESTATIC //.$Runtime "tuple_left" (type.method [(list //.$Tuple runtime.$Index) //.$Value (list)])))]
+ (|>> peekI
+ (_.CHECKCAST //.$Tuple)
+ (_.int (.int lefts))
+ accessI
+ pushI)))
+
+ (^ (synthesis.member/right lefts))
+ (operation@wrap (|>> peekI
+ (_.CHECKCAST //.$Tuple)
+ (_.int (.int lefts))
+ (_.INVOKESTATIC //.$Runtime "tuple_right" (type.method [(list //.$Tuple runtime.$Index) //.$Value (list)]))
+ pushI))
+
+ ## Extra optimization
+ (^ (synthesis.path/seq
+ (synthesis.member/left 0)
+ (synthesis.!bind-top register thenP)))
+ (do phase.monad
+ [then! (path' stack-depth @else @end phase archive thenP)]
+ (wrap (|>> peekI
+ (_.CHECKCAST //.$Tuple)
+ (_.int +0)
+ _.AALOAD
+ (_.ASTORE register)
+ then!)))
+
+ ## Extra optimization
+ (^template [<pm> <getter>]
+ (^ (synthesis.path/seq
+ (<pm> lefts)
+ (synthesis.!bind-top register thenP)))
+ (do phase.monad
+ [then! (path' stack-depth @else @end phase archive thenP)]
+ (wrap (|>> peekI
+ (_.CHECKCAST //.$Tuple)
+ (_.int (.int lefts))
+ (_.INVOKESTATIC //.$Runtime <getter> (type.method [(list //.$Tuple runtime.$Index) //.$Value (list)]))
+ (_.ASTORE register)
+ then!))))
+ ([synthesis.member/left "tuple_left"]
+ [synthesis.member/right "tuple_right"])
+
+ (#synthesis.Alt leftP rightP)
+ (do phase.monad
+ [@alt-else _.make-label
+ leftI (path' (inc stack-depth) @alt-else @end phase archive leftP)
+ rightI (path' stack-depth @else @end phase archive rightP)]
+ (wrap (|>> _.DUP
+ leftI
+ (_.label @alt-else)
+ _.POP
+ rightI)))
+
+ (#synthesis.Seq leftP rightP)
+ (do phase.monad
+ [leftI (path' stack-depth @else @end phase archive leftP)
+ rightI (path' stack-depth @else @end phase archive rightP)]
+ (wrap (|>> leftI
+ rightI)))
+ ))
+
+(def: (path @end phase archive path)
+ (-> Label Phase Archive Path (Operation Inst))
+ (do phase.monad
+ [@else _.make-label
+ pathI (..path' 1 @else @end phase archive path)]
+ (wrap (|>> pathI
+ (_.label @else)
+ _.POP
+ (_.INVOKESTATIC //.$Runtime "pm_fail" (type.method [(list) type.void (list)]))
+ _.NULL
+ (_.GOTO @end)))))
+
+(def: #export (if phase archive [testS thenS elseS])
+ (Generator [Synthesis Synthesis Synthesis])
+ (do phase.monad
+ [testI (phase archive testS)
+ thenI (phase archive thenS)
+ elseI (phase archive elseS)]
+ (wrap (<| _.with-label (function (_ @else))
+ _.with-label (function (_ @end))
+ (|>> testI
+ (_.unwrap type.boolean)
+ (_.IFEQ @else)
+ thenI
+ (_.GOTO @end)
+ (_.label @else)
+ elseI
+ (_.label @end))))))
+
+(def: #export (let phase archive [inputS register exprS])
+ (Generator [Synthesis Nat Synthesis])
+ (do phase.monad
+ [inputI (phase archive inputS)
+ exprI (phase archive exprS)]
+ (wrap (|>> inputI
+ (_.ASTORE register)
+ exprI))))
+
+(def: #export (case phase archive [valueS path])
+ (Generator [Synthesis Path])
+ (do phase.monad
+ [@end _.make-label
+ valueI (phase archive valueS)
+ pathI (..path @end phase archive path)]
+ (wrap (|>> _.NULL
+ valueI
+ pushI
+ pathI
+ (_.label @end)))))
diff --git a/lux-jvm/source/luxc/lang/translation/jvm/common.lux b/lux-jvm/source/luxc/lang/translation/jvm/common.lux
new file mode 100644
index 000000000..6cd7f4f2f
--- /dev/null
+++ b/lux-jvm/source/luxc/lang/translation/jvm/common.lux
@@ -0,0 +1,72 @@
+(.module:
+ [lux #*
+ ## [abstract
+ ## [monad (#+ do)]]
+ ## [control
+ ## ["." try (#+ Try)]
+ ## ["ex" exception (#+ exception:)]
+ ## ["." io]]
+ ## [data
+ ## [binary (#+ Binary)]
+ ## ["." text ("#/." hash)
+ ## format]
+ ## [collection
+ ## ["." dictionary (#+ Dictionary)]]]
+ ## ["." macro]
+ ## [host (#+ import:)]
+ ## [tool
+ ## [compiler
+ ## [reference (#+ Register)]
+ ## ["." name]
+ ## ["." phase]]]
+ ]
+ ## [luxc
+ ## [lang
+ ## [host
+ ## ["." jvm
+ ## [type]]]]]
+ )
+
+## (def: #export (with-artifacts action)
+## (All [a] (-> (Meta a) (Meta [Artifacts a])))
+## (function (_ state)
+## (case (action (update@ #.host
+## (|>> (:coerce Host)
+## (set@ #artifacts (dictionary.new text.hash))
+## (:coerce Nothing))
+## state))
+## (#try.Success [state' output])
+## (#try.Success [(update@ #.host
+## (|>> (:coerce Host)
+## (set@ #artifacts (|> (get@ #.host state) (:coerce Host) (get@ #artifacts)))
+## (:coerce Nothing))
+## state')
+## [(|> state' (get@ #.host) (:coerce Host) (get@ #artifacts))
+## output]])
+
+## (#try.Failure error)
+## (#try.Failure error))))
+
+## (def: #export (load-definition state)
+## (-> Lux (-> Name Binary (Try Any)))
+## (function (_ (^@ def-name [def-module def-name]) def-bytecode)
+## (let [normal-name (format (name.normalize def-name) (%n (text/hash def-name)))
+## class-name (format (text.replace-all "/" "." def-module) "." normal-name)]
+## (<| (macro.run state)
+## (do macro.monad
+## [_ (..store-class class-name def-bytecode)
+## class (..load-class class-name)]
+## (case (do try.monad
+## [field (Class::getField [..value-field] class)]
+## (Field::get [#.None] field))
+## (#try.Success (#.Some def-value))
+## (wrap def-value)
+
+## (#try.Success #.None)
+## (phase.throw invalid-definition-value (%name def-name))
+
+## (#try.Failure error)
+## (phase.throw cannot-load-definition
+## (format "Definition: " (%name def-name) "\n"
+## "Error:\n"
+## error))))))))
diff --git a/lux-jvm/source/luxc/lang/translation/jvm/expression.lux b/lux-jvm/source/luxc/lang/translation/jvm/expression.lux
new file mode 100644
index 000000000..144e35f9b
--- /dev/null
+++ b/lux-jvm/source/luxc/lang/translation/jvm/expression.lux
@@ -0,0 +1,72 @@
+(.module:
+ [lux #*
+ [tool
+ [compiler
+ [language
+ [lux
+ ["." synthesis]
+ [phase
+ ["." extension]]]]]]]
+ [luxc
+ [lang
+ [host
+ [jvm (#+ Phase)]]]]
+ [//
+ ["." common]
+ ["." primitive]
+ ["." structure]
+ ["." reference]
+ ["." case]
+ ["." loop]
+ ["." function]])
+
+(def: #export (translate archive synthesis)
+ Phase
+ (case synthesis
+ (^ (synthesis.bit value))
+ (primitive.bit value)
+
+ (^ (synthesis.i64 value))
+ (primitive.i64 value)
+
+ (^ (synthesis.f64 value))
+ (primitive.f64 value)
+
+ (^ (synthesis.text value))
+ (primitive.text value)
+
+ (^ (synthesis.variant data))
+ (structure.variant translate archive data)
+
+ (^ (synthesis.tuple members))
+ (structure.tuple translate archive members)
+
+ (^ (synthesis.variable variable))
+ (reference.variable archive variable)
+
+ (^ (synthesis.constant constant))
+ (reference.constant archive constant)
+
+ (^ (synthesis.branch/let data))
+ (case.let translate archive data)
+
+ (^ (synthesis.branch/if data))
+ (case.if translate archive data)
+
+ (^ (synthesis.branch/case data))
+ (case.case translate archive data)
+
+ (^ (synthesis.loop/recur data))
+ (loop.recur translate archive data)
+
+ (^ (synthesis.loop/scope data))
+ (loop.scope translate archive data)
+
+ (^ (synthesis.function/apply data))
+ (function.call translate archive data)
+
+ (^ (synthesis.function/abstraction data))
+ (function.function translate archive data)
+
+ (#synthesis.Extension extension)
+ (extension.apply archive translate extension)))
diff --git a/lux-jvm/source/luxc/lang/translation/jvm/extension.lux b/lux-jvm/source/luxc/lang/translation/jvm/extension.lux
new file mode 100644
index 000000000..9066dd156
--- /dev/null
+++ b/lux-jvm/source/luxc/lang/translation/jvm/extension.lux
@@ -0,0 +1,16 @@
+(.module:
+ [lux #*
+ [data
+ [collection
+ ["." dictionary]]]]
+ [////
+ [host
+ [jvm (#+ Bundle)]]]
+ ["." / #_
+ ["#." common]
+ ["#." host]])
+
+(def: #export bundle
+ Bundle
+ (dictionary.merge /common.bundle
+ /host.bundle))
diff --git a/lux-jvm/source/luxc/lang/translation/jvm/extension/common.lux b/lux-jvm/source/luxc/lang/translation/jvm/extension/common.lux
new file mode 100644
index 000000000..383415c0a
--- /dev/null
+++ b/lux-jvm/source/luxc/lang/translation/jvm/extension/common.lux
@@ -0,0 +1,388 @@
+(.module:
+ [lux (#- Type)
+ [abstract
+ ["." monad (#+ do)]]
+ [control
+ ["." try]
+ ["<>" parser
+ ["<s>" synthesis (#+ Parser)]]]
+ [data
+ ["." product]
+ [number
+ ["f" frac]]
+ [collection
+ ["." list ("#@." monad)]
+ ["." dictionary]]]
+ [target
+ [jvm
+ ["." type]]]
+ [tool
+ [compiler
+ ["." phase]
+ [meta
+ [archive (#+ Archive)]]
+ [language
+ [lux
+ ["." synthesis (#+ Synthesis %synthesis)]
+ [phase
+ [generation
+ [extension (#+ Nullary Unary Binary Trinary Variadic
+ nullary unary binary trinary variadic)]]
+ ["." extension
+ ["." bundle]]]]]]]
+ [host (#+ import:)]]
+ [luxc
+ [lang
+ [host
+ ["$" jvm (#+ Label Inst Def Handler Bundle Operation Phase)
+ ["_" inst]]]]]
+ ["." ///
+ ["." runtime]])
+
+(def: #export (custom [parser handler])
+ (All [s]
+ (-> [(Parser s)
+ (-> Text Phase Archive s (Operation Inst))]
+ Handler))
+ (function (_ extension-name phase archive input)
+ (case (<s>.run parser input)
+ (#try.Success input')
+ (handler extension-name phase archive input')
+
+ (#try.Failure error)
+ (phase.throw extension.invalid-syntax [extension-name %synthesis input]))))
+
+(import: java/lang/Double
+ (#static MIN_VALUE Double)
+ (#static MAX_VALUE Double))
+
+(def: $String (type.class "java.lang.String" (list)))
+(def: $CharSequence (type.class "java.lang.CharSequence" (list)))
+(def: $System (type.class "java.lang.System" (list)))
+(def: $Object (type.class "java.lang.Object" (list)))
+
+(def: lux-intI Inst (|>> _.I2L (_.wrap type.long)))
+(def: jvm-intI Inst (|>> (_.unwrap type.long) _.L2I))
+(def: check-stringI Inst (_.CHECKCAST $String))
+
+(def: (predicateI tester)
+ (-> (-> Label Inst)
+ Inst)
+ (let [$Boolean (type.class "java.lang.Boolean" (list))]
+ (<| _.with-label (function (_ @then))
+ _.with-label (function (_ @end))
+ (|>> (tester @then)
+ (_.GETSTATIC $Boolean "FALSE" $Boolean)
+ (_.GOTO @end)
+ (_.label @then)
+ (_.GETSTATIC $Boolean "TRUE" $Boolean)
+ (_.label @end)
+ ))))
+
+(def: unitI Inst (_.string synthesis.unit))
+
+## TODO: Get rid of this ASAP
+(def: lux::syntax-char-case!
+ (..custom [($_ <>.and
+ <s>.any
+ <s>.any
+ (<>.some (<s>.tuple ($_ <>.and
+ (<s>.tuple (<>.many <s>.i64))
+ <s>.any))))
+ (function (_ extension-name phase archive [input else conditionals])
+ (<| _.with-label (function (_ @end))
+ _.with-label (function (_ @else))
+ (do {@ phase.monad}
+ [inputG (phase archive input)
+ elseG (phase archive else)
+ conditionalsG+ (: (Operation (List [(List [Int Label])
+ Inst]))
+ (monad.map @ (function (_ [chars branch])
+ (do @
+ [branchG (phase archive branch)]
+ (wrap (<| _.with-label (function (_ @branch))
+ [(list@map (function (_ char)
+ [(.int char) @branch])
+ chars)
+ (|>> (_.label @branch)
+ branchG
+ (_.GOTO @end))]))))
+ conditionals))
+ #let [table (|> conditionalsG+
+ (list@map product.left)
+ list@join)
+ conditionalsG (|> conditionalsG+
+ (list@map product.right)
+ _.fuse)]]
+ (wrap (|>> inputG (_.unwrap type.long) _.L2I
+ (_.LOOKUPSWITCH @else table)
+ conditionalsG
+ (_.label @else)
+ elseG
+ (_.label @end)
+ )))))]))
+
+(def: (lux::is [referenceI sampleI])
+ (Binary Inst)
+ (|>> referenceI
+ sampleI
+ (predicateI _.IF_ACMPEQ)))
+
+(def: (lux::try riskyI)
+ (Unary Inst)
+ (|>> riskyI
+ (_.CHECKCAST ///.$Function)
+ (_.INVOKESTATIC ///.$Runtime "try" runtime.try)))
+
+(template [<name> <op>]
+ [(def: (<name> [maskI inputI])
+ (Binary Inst)
+ (|>> inputI (_.unwrap type.long)
+ maskI (_.unwrap type.long)
+ <op> (_.wrap type.long)))]
+
+ [i64::and _.LAND]
+ [i64::or _.LOR]
+ [i64::xor _.LXOR]
+ )
+
+(template [<name> <op>]
+ [(def: (<name> [shiftI inputI])
+ (Binary Inst)
+ (|>> inputI (_.unwrap type.long)
+ shiftI jvm-intI
+ <op>
+ (_.wrap type.long)))]
+
+ [i64::left-shift _.LSHL]
+ [i64::arithmetic-right-shift _.LSHR]
+ [i64::logical-right-shift _.LUSHR]
+ )
+
+(template [<name> <const> <type>]
+ [(def: (<name> _)
+ (Nullary Inst)
+ (|>> <const> (_.wrap <type>)))]
+
+ [f64::smallest (_.double (Double::MIN_VALUE)) type.double]
+ [f64::min (_.double (f.* -1.0 (Double::MAX_VALUE))) type.double]
+ [f64::max (_.double (Double::MAX_VALUE)) type.double]
+ )
+
+(template [<name> <type> <op>]
+ [(def: (<name> [paramI subjectI])
+ (Binary Inst)
+ (|>> subjectI (_.unwrap <type>)
+ paramI (_.unwrap <type>)
+ <op>
+ (_.wrap <type>)))]
+
+ [i64::+ type.long _.LADD]
+ [i64::- type.long _.LSUB]
+ [i64::* type.long _.LMUL]
+ [i64::/ type.long _.LDIV]
+ [i64::% type.long _.LREM]
+
+ [f64::+ type.double _.DADD]
+ [f64::- type.double _.DSUB]
+ [f64::* type.double _.DMUL]
+ [f64::/ type.double _.DDIV]
+ [f64::% type.double _.DREM]
+ )
+
+(template [<eq> <lt> <type> <cmp>]
+ [(template [<name> <reference>]
+ [(def: (<name> [paramI subjectI])
+ (Binary Inst)
+ (|>> subjectI (_.unwrap <type>)
+ paramI (_.unwrap <type>)
+ <cmp>
+ (_.int <reference>)
+ (predicateI _.IF_ICMPEQ)))]
+
+ [<eq> +0]
+ [<lt> -1])]
+
+ [i64::= i64::< type.long _.LCMP]
+ [f64::= f64::< type.double _.DCMPG]
+ )
+
+(template [<name> <prepare> <transform>]
+ [(def: (<name> inputI)
+ (Unary Inst)
+ (|>> inputI <prepare> <transform>))]
+
+ [i64::f64 (_.unwrap type.long) (<| (_.wrap type.double) _.L2D)]
+ [i64::char (_.unwrap type.long)
+ ((|>> _.L2I _.I2C (_.INVOKESTATIC (type.class "java.lang.Character" (list)) "toString" (type.method [(list type.char) $String (list)]))))]
+
+ [f64::i64 (_.unwrap type.double) (<| (_.wrap type.long) _.D2L)]
+ [f64::encode (_.unwrap type.double)
+ (_.INVOKESTATIC (type.class "java.lang.Double" (list)) "toString" (type.method [(list type.double) $String (list)]))]
+ [f64::decode ..check-stringI
+ (_.INVOKESTATIC ///.$Runtime "decode_frac" (type.method [(list $String) ///.$Variant (list)]))]
+ )
+
+(def: (text::size inputI)
+ (Unary Inst)
+ (|>> inputI
+ ..check-stringI
+ (_.INVOKEVIRTUAL $String "length" (type.method [(list) type.int (list)]))
+ lux-intI))
+
+(template [<name> <pre-subject> <pre-param> <op> <post>]
+ [(def: (<name> [paramI subjectI])
+ (Binary Inst)
+ (|>> subjectI <pre-subject>
+ paramI <pre-param>
+ <op> <post>))]
+
+ [text::= (<|) (<|)
+ (_.INVOKEVIRTUAL $Object "equals" (type.method [(list $Object) type.boolean (list)]))
+ (_.wrap type.boolean)]
+ [text::< ..check-stringI ..check-stringI
+ (_.INVOKEVIRTUAL $String "compareTo" (type.method [(list $String) type.int (list)]))
+ (predicateI _.IFLT)]
+ [text::char ..check-stringI jvm-intI
+ (_.INVOKEVIRTUAL $String "charAt" (type.method [(list type.int) type.char (list)]))
+ lux-intI]
+ )
+
+(def: (text::concat [leftI rightI])
+ (Binary Inst)
+ (|>> leftI ..check-stringI
+ rightI ..check-stringI
+ (_.INVOKEVIRTUAL $String "concat" (type.method [(list $String) $String (list)]))))
+
+(def: (text::clip [startI endI subjectI])
+ (Trinary Inst)
+ (|>> subjectI ..check-stringI
+ startI jvm-intI
+ endI jvm-intI
+ (_.INVOKEVIRTUAL $String "substring" (type.method [(list type.int type.int) $String (list)]))))
+
+(def: index-method (type.method [(list $String type.int) type.int (list)]))
+(def: (text::index [startI partI textI])
+ (Trinary Inst)
+ (<| _.with-label (function (_ @not-found))
+ _.with-label (function (_ @end))
+ (|>> textI ..check-stringI
+ partI ..check-stringI
+ startI jvm-intI
+ (_.INVOKEVIRTUAL $String "indexOf" index-method)
+ _.DUP
+ (_.int -1)
+ (_.IF_ICMPEQ @not-found)
+ lux-intI
+ runtime.someI
+ (_.GOTO @end)
+ (_.label @not-found)
+ _.POP
+ runtime.noneI
+ (_.label @end))))
+
+(def: string-method (type.method [(list $String) type.void (list)]))
+(def: (io::log messageI)
+ (Unary Inst)
+ (let [$PrintStream (type.class "java.io.PrintStream" (list))]
+ (|>> (_.GETSTATIC $System "out" $PrintStream)
+ messageI
+ ..check-stringI
+ (_.INVOKEVIRTUAL $PrintStream "println" string-method)
+ unitI)))
+
+(def: (io::error messageI)
+ (Unary Inst)
+ (let [$Error (type.class "java.lang.Error" (list))]
+ (|>> (_.NEW $Error)
+ _.DUP
+ messageI
+ ..check-stringI
+ (_.INVOKESPECIAL $Error "<init>" string-method)
+ _.ATHROW)))
+
+(def: (io::exit codeI)
+ (Unary Inst)
+ (|>> codeI jvm-intI
+ (_.INVOKESTATIC $System "exit" (type.method [(list type.int) type.void (list)]))
+ _.NULL))
+
+(def: (io::current-time _)
+ (Nullary Inst)
+ (|>> (_.INVOKESTATIC $System "currentTimeMillis" (type.method [(list) type.long (list)]))
+ (_.wrap type.long)))
+
+(def: bundle::lux
+ Bundle
+ (|> (: Bundle bundle.empty)
+ (bundle.install "syntax char case!" lux::syntax-char-case!)
+ (bundle.install "is" (binary lux::is))
+ (bundle.install "try" (unary lux::try))))
+
+(def: bundle::i64
+ Bundle
+ (<| (bundle.prefix "i64")
+ (|> (: Bundle bundle.empty)
+ (bundle.install "and" (binary i64::and))
+ (bundle.install "or" (binary i64::or))
+ (bundle.install "xor" (binary i64::xor))
+ (bundle.install "left-shift" (binary i64::left-shift))
+ (bundle.install "logical-right-shift" (binary i64::logical-right-shift))
+ (bundle.install "arithmetic-right-shift" (binary i64::arithmetic-right-shift))
+ (bundle.install "=" (binary i64::=))
+ (bundle.install "<" (binary i64::<))
+ (bundle.install "+" (binary i64::+))
+ (bundle.install "-" (binary i64::-))
+ (bundle.install "*" (binary i64::*))
+ (bundle.install "/" (binary i64::/))
+ (bundle.install "%" (binary i64::%))
+ (bundle.install "f64" (unary i64::f64))
+ (bundle.install "char" (unary i64::char)))))
+
+(def: bundle::f64
+ Bundle
+ (<| (bundle.prefix "f64")
+ (|> (: Bundle bundle.empty)
+ (bundle.install "+" (binary f64::+))
+ (bundle.install "-" (binary f64::-))
+ (bundle.install "*" (binary f64::*))
+ (bundle.install "/" (binary f64::/))
+ (bundle.install "%" (binary f64::%))
+ (bundle.install "=" (binary f64::=))
+ (bundle.install "<" (binary f64::<))
+ (bundle.install "smallest" (nullary f64::smallest))
+ (bundle.install "min" (nullary f64::min))
+ (bundle.install "max" (nullary f64::max))
+ (bundle.install "i64" (unary f64::i64))
+ (bundle.install "encode" (unary f64::encode))
+ (bundle.install "decode" (unary f64::decode)))))
+
+(def: bundle::text
+ Bundle
+ (<| (bundle.prefix "text")
+ (|> (: Bundle bundle.empty)
+ (bundle.install "=" (binary text::=))
+ (bundle.install "<" (binary text::<))
+ (bundle.install "concat" (binary text::concat))
+ (bundle.install "index" (trinary text::index))
+ (bundle.install "size" (unary text::size))
+ (bundle.install "char" (binary text::char))
+ (bundle.install "clip" (trinary text::clip)))))
+
+(def: bundle::io
+ Bundle
+ (<| (bundle.prefix "io")
+ (|> (: Bundle bundle.empty)
+ (bundle.install "log" (unary io::log))
+ (bundle.install "error" (unary io::error))
+ (bundle.install "exit" (unary io::exit))
+ (bundle.install "current-time" (nullary io::current-time)))))
+
+(def: #export bundle
+ Bundle
+ (<| (bundle.prefix "lux")
+ (|> bundle::lux
+ (dictionary.merge bundle::i64)
+ (dictionary.merge bundle::f64)
+ (dictionary.merge bundle::text)
+ (dictionary.merge bundle::io))))
diff --git a/lux-jvm/source/luxc/lang/translation/jvm/extension/host.lux b/lux-jvm/source/luxc/lang/translation/jvm/extension/host.lux
new file mode 100644
index 000000000..7b90a8e4f
--- /dev/null
+++ b/lux-jvm/source/luxc/lang/translation/jvm/extension/host.lux
@@ -0,0 +1,1047 @@
+(.module:
+ [lux (#- Type primitive int char type)
+ [host (#+ import:)]
+ [abstract
+ ["." monad (#+ do)]]
+ [control
+ ["." exception (#+ exception:)]
+ ["." function]
+ ["<>" parser ("#@." monad)
+ ["<t>" text]
+ ["<s>" synthesis (#+ Parser)]]]
+ [data
+ ["." product]
+ ["." maybe]
+ ["." text ("#@." equivalence)
+ ["%" format (#+ format)]]
+ [number
+ ["." nat]]
+ [collection
+ ["." list ("#@." monad)]
+ ["." dictionary (#+ Dictionary)]
+ ["." set]]]
+ [target
+ [jvm
+ ["." type (#+ Type Typed Argument)
+ ["." category (#+ Void Value Return Primitive Object Class Array Var Parameter Method)]
+ ["." box]
+ ["." reflection]
+ ["." signature]
+ ["." parser]]]]
+ [tool
+ [compiler
+ ["." reference (#+ Variable)]
+ ["." phase ("#@." monad)]
+ [meta
+ [archive (#+ Archive)]]
+ [language
+ [lux
+ [analysis (#+ Environment)]
+ ["." synthesis (#+ Synthesis Path %synthesis)]
+ ["." generation]
+ [phase
+ [generation
+ [extension (#+ Nullary Unary Binary
+ nullary unary binary)]]
+ [analysis
+ [".A" reference]]
+ ["." extension
+ ["." bundle]
+ [analysis
+ ["/" jvm]]]]]]]]]
+ [luxc
+ [lang
+ [host
+ ["$" jvm (#+ Label Inst Def Handler Bundle Operation Phase)
+ ["_" inst]
+ ["_." def]]]]]
+ ["." // #_
+ [common (#+ custom)]
+ ["/#" //
+ ["#." reference]
+ ["#." function]]])
+
+(template [<name> <category> <parser>]
+ [(def: #export <name>
+ (Parser (Type <category>))
+ (<t>.embed <parser> <s>.text))]
+
+ [var Var parser.var]
+ [class Class parser.class]
+ [object Object parser.object]
+ [value Value parser.value]
+ [return Return parser.return]
+ )
+
+(exception: #export (not-an-object-array {arrayJT (Type Array)})
+ (exception.report
+ ["JVM Type" (|> arrayJT type.signature signature.signature)]))
+
+(def: #export object-array
+ (Parser (Type Object))
+ (do <>.monad
+ [arrayJT (<t>.embed parser.array <s>.text)]
+ (case (parser.array? arrayJT)
+ (#.Some elementJT)
+ (case (parser.object? elementJT)
+ (#.Some elementJT)
+ (wrap elementJT)
+
+ #.None
+ (<>.fail (exception.construct ..not-an-object-array arrayJT)))
+
+ #.None
+ (undefined))))
+
+(template [<name> <inst>]
+ [(def: <name>
+ Inst
+ <inst>)]
+
+ [L2S (|>> _.L2I _.I2S)]
+ [L2B (|>> _.L2I _.I2B)]
+ [L2C (|>> _.L2I _.I2C)]
+ )
+
+(template [<conversion> <name>]
+ [(def: (<name> inputI)
+ (Unary Inst)
+ (if (is? _.NOP <conversion>)
+ inputI
+ (|>> inputI
+ <conversion>)))]
+
+ [_.D2F conversion::double-to-float]
+ [_.D2I conversion::double-to-int]
+ [_.D2L conversion::double-to-long]
+ [_.F2D conversion::float-to-double]
+ [_.F2I conversion::float-to-int]
+ [_.F2L conversion::float-to-long]
+ [_.I2B conversion::int-to-byte]
+ [_.I2C conversion::int-to-char]
+ [_.I2D conversion::int-to-double]
+ [_.I2F conversion::int-to-float]
+ [_.I2L conversion::int-to-long]
+ [_.I2S conversion::int-to-short]
+ [_.L2D conversion::long-to-double]
+ [_.L2F conversion::long-to-float]
+ [_.L2I conversion::long-to-int]
+ [..L2S conversion::long-to-short]
+ [..L2B conversion::long-to-byte]
+ [..L2C conversion::long-to-char]
+ [_.I2B conversion::char-to-byte]
+ [_.I2S conversion::char-to-short]
+ [_.NOP conversion::char-to-int]
+ [_.I2L conversion::char-to-long]
+ [_.I2L conversion::byte-to-long]
+ [_.I2L conversion::short-to-long]
+ )
+
+(def: conversion
+ Bundle
+ (<| (bundle.prefix "conversion")
+ (|> (: Bundle bundle.empty)
+ (bundle.install "double-to-float" (unary conversion::double-to-float))
+ (bundle.install "double-to-int" (unary conversion::double-to-int))
+ (bundle.install "double-to-long" (unary conversion::double-to-long))
+ (bundle.install "float-to-double" (unary conversion::float-to-double))
+ (bundle.install "float-to-int" (unary conversion::float-to-int))
+ (bundle.install "float-to-long" (unary conversion::float-to-long))
+ (bundle.install "int-to-byte" (unary conversion::int-to-byte))
+ (bundle.install "int-to-char" (unary conversion::int-to-char))
+ (bundle.install "int-to-double" (unary conversion::int-to-double))
+ (bundle.install "int-to-float" (unary conversion::int-to-float))
+ (bundle.install "int-to-long" (unary conversion::int-to-long))
+ (bundle.install "int-to-short" (unary conversion::int-to-short))
+ (bundle.install "long-to-double" (unary conversion::long-to-double))
+ (bundle.install "long-to-float" (unary conversion::long-to-float))
+ (bundle.install "long-to-int" (unary conversion::long-to-int))
+ (bundle.install "long-to-short" (unary conversion::long-to-short))
+ (bundle.install "long-to-byte" (unary conversion::long-to-byte))
+ (bundle.install "long-to-char" (unary conversion::long-to-char))
+ (bundle.install "char-to-byte" (unary conversion::char-to-byte))
+ (bundle.install "char-to-short" (unary conversion::char-to-short))
+ (bundle.install "char-to-int" (unary conversion::char-to-int))
+ (bundle.install "char-to-long" (unary conversion::char-to-long))
+ (bundle.install "byte-to-long" (unary conversion::byte-to-long))
+ (bundle.install "short-to-long" (unary conversion::short-to-long))
+ )))
+
+(template [<name> <op>]
+ [(def: (<name> [xI yI])
+ (Binary Inst)
+ (|>> xI
+ yI
+ <op>))]
+
+ [int::+ _.IADD]
+ [int::- _.ISUB]
+ [int::* _.IMUL]
+ [int::/ _.IDIV]
+ [int::% _.IREM]
+ [int::and _.IAND]
+ [int::or _.IOR]
+ [int::xor _.IXOR]
+ [int::shl _.ISHL]
+ [int::shr _.ISHR]
+ [int::ushr _.IUSHR]
+
+ [long::+ _.LADD]
+ [long::- _.LSUB]
+ [long::* _.LMUL]
+ [long::/ _.LDIV]
+ [long::% _.LREM]
+ [long::and _.LAND]
+ [long::or _.LOR]
+ [long::xor _.LXOR]
+ [long::shl _.LSHL]
+ [long::shr _.LSHR]
+ [long::ushr _.LUSHR]
+
+ [float::+ _.FADD]
+ [float::- _.FSUB]
+ [float::* _.FMUL]
+ [float::/ _.FDIV]
+ [float::% _.FREM]
+
+ [double::+ _.DADD]
+ [double::- _.DSUB]
+ [double::* _.DMUL]
+ [double::/ _.DDIV]
+ [double::% _.DREM]
+ )
+
+(def: $Boolean (type.class box.boolean (list)))
+(def: falseI (_.GETSTATIC $Boolean "FALSE" $Boolean))
+(def: trueI (_.GETSTATIC $Boolean "TRUE" $Boolean))
+
+(template [<name> <op>]
+ [(def: (<name> [xI yI])
+ (Binary Inst)
+ (<| _.with-label (function (_ @then))
+ _.with-label (function (_ @end))
+ (|>> xI
+ yI
+ (<op> @then)
+ falseI
+ (_.GOTO @end)
+ (_.label @then)
+ trueI
+ (_.label @end))))]
+
+ [int::= _.IF_ICMPEQ]
+ [int::< _.IF_ICMPLT]
+
+ [char::= _.IF_ICMPEQ]
+ [char::< _.IF_ICMPLT]
+ )
+
+(template [<name> <op> <reference>]
+ [(def: (<name> [xI yI])
+ (Binary Inst)
+ (<| _.with-label (function (_ @then))
+ _.with-label (function (_ @end))
+ (|>> xI
+ yI
+ <op>
+ (_.int <reference>)
+ (_.IF_ICMPEQ @then)
+ falseI
+ (_.GOTO @end)
+ (_.label @then)
+ trueI
+ (_.label @end))))]
+
+ [long::= _.LCMP +0]
+ [long::< _.LCMP -1]
+
+ [float::= _.FCMPG +0]
+ [float::< _.FCMPG -1]
+
+ [double::= _.DCMPG +0]
+ [double::< _.DCMPG -1]
+ )
+
+(def: int
+ Bundle
+ (<| (bundle.prefix (reflection.reflection reflection.int))
+ (|> (: Bundle bundle.empty)
+ (bundle.install "+" (binary int::+))
+ (bundle.install "-" (binary int::-))
+ (bundle.install "*" (binary int::*))
+ (bundle.install "/" (binary int::/))
+ (bundle.install "%" (binary int::%))
+ (bundle.install "=" (binary int::=))
+ (bundle.install "<" (binary int::<))
+ (bundle.install "and" (binary int::and))
+ (bundle.install "or" (binary int::or))
+ (bundle.install "xor" (binary int::xor))
+ (bundle.install "shl" (binary int::shl))
+ (bundle.install "shr" (binary int::shr))
+ (bundle.install "ushr" (binary int::ushr))
+ )))
+
+(def: long
+ Bundle
+ (<| (bundle.prefix (reflection.reflection reflection.long))
+ (|> (: Bundle bundle.empty)
+ (bundle.install "+" (binary long::+))
+ (bundle.install "-" (binary long::-))
+ (bundle.install "*" (binary long::*))
+ (bundle.install "/" (binary long::/))
+ (bundle.install "%" (binary long::%))
+ (bundle.install "=" (binary long::=))
+ (bundle.install "<" (binary long::<))
+ (bundle.install "and" (binary long::and))
+ (bundle.install "or" (binary long::or))
+ (bundle.install "xor" (binary long::xor))
+ (bundle.install "shl" (binary long::shl))
+ (bundle.install "shr" (binary long::shr))
+ (bundle.install "ushr" (binary long::ushr))
+ )))
+
+(def: float
+ Bundle
+ (<| (bundle.prefix (reflection.reflection reflection.float))
+ (|> (: Bundle bundle.empty)
+ (bundle.install "+" (binary float::+))
+ (bundle.install "-" (binary float::-))
+ (bundle.install "*" (binary float::*))
+ (bundle.install "/" (binary float::/))
+ (bundle.install "%" (binary float::%))
+ (bundle.install "=" (binary float::=))
+ (bundle.install "<" (binary float::<))
+ )))
+
+(def: double
+ Bundle
+ (<| (bundle.prefix (reflection.reflection reflection.double))
+ (|> (: Bundle bundle.empty)
+ (bundle.install "+" (binary double::+))
+ (bundle.install "-" (binary double::-))
+ (bundle.install "*" (binary double::*))
+ (bundle.install "/" (binary double::/))
+ (bundle.install "%" (binary double::%))
+ (bundle.install "=" (binary double::=))
+ (bundle.install "<" (binary double::<))
+ )))
+
+(def: char
+ Bundle
+ (<| (bundle.prefix (reflection.reflection reflection.char))
+ (|> (: Bundle bundle.empty)
+ (bundle.install "=" (binary char::=))
+ (bundle.install "<" (binary char::<))
+ )))
+
+(def: (primitive-array-length-handler jvm-primitive)
+ (-> (Type Primitive) Handler)
+ (..custom
+ [<s>.any
+ (function (_ extension-name generate archive arrayS)
+ (do phase.monad
+ [arrayI (generate archive arrayS)]
+ (wrap (|>> arrayI
+ (_.CHECKCAST (type.array jvm-primitive))
+ _.ARRAYLENGTH))))]))
+
+(def: array::length::object
+ Handler
+ (..custom
+ [($_ <>.and ..object-array <s>.any)
+ (function (_ extension-name generate archive [elementJT arrayS])
+ (do phase.monad
+ [arrayI (generate archive arrayS)]
+ (wrap (|>> arrayI
+ (_.CHECKCAST (type.array elementJT))
+ _.ARRAYLENGTH))))]))
+
+(def: (new-primitive-array-handler jvm-primitive)
+ (-> (Type Primitive) Handler)
+ (function (_ extension-name generate archive inputs)
+ (case inputs
+ (^ (list lengthS))
+ (do phase.monad
+ [lengthI (generate archive lengthS)]
+ (wrap (|>> lengthI
+ (_.array jvm-primitive))))
+
+ _
+ (phase.throw extension.invalid-syntax [extension-name %synthesis inputs]))))
+
+(def: array::new::object
+ Handler
+ (..custom
+ [($_ <>.and ..object <s>.any)
+ (function (_ extension-name generate archive [objectJT lengthS])
+ (do phase.monad
+ [lengthI (generate archive lengthS)]
+ (wrap (|>> lengthI
+ (_.ANEWARRAY objectJT)))))]))
+
+(def: (read-primitive-array-handler jvm-primitive loadI)
+ (-> (Type Primitive) Inst Handler)
+ (function (_ extension-name generate archive inputs)
+ (case inputs
+ (^ (list idxS arrayS))
+ (do phase.monad
+ [arrayI (generate archive arrayS)
+ idxI (generate archive idxS)]
+ (wrap (|>> arrayI
+ (_.CHECKCAST (type.array jvm-primitive))
+ idxI
+ loadI)))
+
+ _
+ (phase.throw extension.invalid-syntax [extension-name %synthesis inputs]))))
+
+(def: array::read::object
+ Handler
+ (..custom
+ [($_ <>.and ..object-array <s>.any <s>.any)
+ (function (_ extension-name generate archive [elementJT idxS arrayS])
+ (do phase.monad
+ [arrayI (generate archive arrayS)
+ idxI (generate archive idxS)]
+ (wrap (|>> arrayI
+ (_.CHECKCAST (type.array elementJT))
+ idxI
+ _.AALOAD))))]))
+
+(def: (write-primitive-array-handler jvm-primitive storeI)
+ (-> (Type Primitive) Inst Handler)
+ (function (_ extension-name generate archive inputs)
+ (case inputs
+ (^ (list idxS valueS arrayS))
+ (do phase.monad
+ [arrayI (generate archive arrayS)
+ idxI (generate archive idxS)
+ valueI (generate archive valueS)]
+ (wrap (|>> arrayI
+ (_.CHECKCAST (type.array jvm-primitive))
+ _.DUP
+ idxI
+ valueI
+ storeI)))
+
+ _
+ (phase.throw extension.invalid-syntax [extension-name %synthesis inputs]))))
+
+(def: array::write::object
+ Handler
+ (..custom
+ [($_ <>.and ..object-array <s>.any <s>.any <s>.any)
+ (function (_ extension-name generate archive [elementJT idxS valueS arrayS])
+ (do phase.monad
+ [arrayI (generate archive arrayS)
+ idxI (generate archive idxS)
+ valueI (generate archive valueS)]
+ (wrap (|>> arrayI
+ (_.CHECKCAST (type.array elementJT))
+ _.DUP
+ idxI
+ valueI
+ _.AASTORE))))]))
+
+(def: array
+ Bundle
+ (<| (bundle.prefix "array")
+ (|> bundle.empty
+ (dictionary.merge (<| (bundle.prefix "length")
+ (|> bundle.empty
+ (bundle.install (reflection.reflection reflection.boolean) (primitive-array-length-handler type.boolean))
+ (bundle.install (reflection.reflection reflection.byte) (primitive-array-length-handler type.byte))
+ (bundle.install (reflection.reflection reflection.short) (primitive-array-length-handler type.short))
+ (bundle.install (reflection.reflection reflection.int) (primitive-array-length-handler type.int))
+ (bundle.install (reflection.reflection reflection.long) (primitive-array-length-handler type.long))
+ (bundle.install (reflection.reflection reflection.float) (primitive-array-length-handler type.float))
+ (bundle.install (reflection.reflection reflection.double) (primitive-array-length-handler type.double))
+ (bundle.install (reflection.reflection reflection.char) (primitive-array-length-handler type.char))
+ (bundle.install "object" array::length::object))))
+ (dictionary.merge (<| (bundle.prefix "new")
+ (|> bundle.empty
+ (bundle.install (reflection.reflection reflection.boolean) (new-primitive-array-handler type.boolean))
+ (bundle.install (reflection.reflection reflection.byte) (new-primitive-array-handler type.byte))
+ (bundle.install (reflection.reflection reflection.short) (new-primitive-array-handler type.short))
+ (bundle.install (reflection.reflection reflection.int) (new-primitive-array-handler type.int))
+ (bundle.install (reflection.reflection reflection.long) (new-primitive-array-handler type.long))
+ (bundle.install (reflection.reflection reflection.float) (new-primitive-array-handler type.float))
+ (bundle.install (reflection.reflection reflection.double) (new-primitive-array-handler type.double))
+ (bundle.install (reflection.reflection reflection.char) (new-primitive-array-handler type.char))
+ (bundle.install "object" array::new::object))))
+ (dictionary.merge (<| (bundle.prefix "read")
+ (|> bundle.empty
+ (bundle.install (reflection.reflection reflection.boolean) (read-primitive-array-handler type.boolean _.BALOAD))
+ (bundle.install (reflection.reflection reflection.byte) (read-primitive-array-handler type.byte _.BALOAD))
+ (bundle.install (reflection.reflection reflection.short) (read-primitive-array-handler type.short _.SALOAD))
+ (bundle.install (reflection.reflection reflection.int) (read-primitive-array-handler type.int _.IALOAD))
+ (bundle.install (reflection.reflection reflection.long) (read-primitive-array-handler type.long _.LALOAD))
+ (bundle.install (reflection.reflection reflection.float) (read-primitive-array-handler type.float _.FALOAD))
+ (bundle.install (reflection.reflection reflection.double) (read-primitive-array-handler type.double _.DALOAD))
+ (bundle.install (reflection.reflection reflection.char) (read-primitive-array-handler type.char _.CALOAD))
+ (bundle.install "object" array::read::object))))
+ (dictionary.merge (<| (bundle.prefix "write")
+ (|> bundle.empty
+ (bundle.install (reflection.reflection reflection.boolean) (write-primitive-array-handler type.boolean _.BASTORE))
+ (bundle.install (reflection.reflection reflection.byte) (write-primitive-array-handler type.byte _.BASTORE))
+ (bundle.install (reflection.reflection reflection.short) (write-primitive-array-handler type.short _.SASTORE))
+ (bundle.install (reflection.reflection reflection.int) (write-primitive-array-handler type.int _.IASTORE))
+ (bundle.install (reflection.reflection reflection.long) (write-primitive-array-handler type.long _.LASTORE))
+ (bundle.install (reflection.reflection reflection.float) (write-primitive-array-handler type.float _.FASTORE))
+ (bundle.install (reflection.reflection reflection.double) (write-primitive-array-handler type.double _.DASTORE))
+ (bundle.install (reflection.reflection reflection.char) (write-primitive-array-handler type.char _.CASTORE))
+ (bundle.install "object" array::write::object))))
+ )))
+
+(def: (object::null _)
+ (Nullary Inst)
+ _.NULL)
+
+(def: (object::null? objectI)
+ (Unary Inst)
+ (<| _.with-label (function (_ @then))
+ _.with-label (function (_ @end))
+ (|>> objectI
+ (_.IFNULL @then)
+ falseI
+ (_.GOTO @end)
+ (_.label @then)
+ trueI
+ (_.label @end))))
+
+(def: (object::synchronized [monitorI exprI])
+ (Binary Inst)
+ (|>> monitorI
+ _.DUP
+ _.MONITORENTER
+ exprI
+ _.SWAP
+ _.MONITOREXIT))
+
+(def: (object::throw exceptionI)
+ (Unary Inst)
+ (|>> exceptionI
+ _.ATHROW))
+
+(def: $Class (type.class "java.lang.Class" (list)))
+
+(def: (object::class extension-name generate archive inputs)
+ Handler
+ (case inputs
+ (^ (list (synthesis.text class)))
+ (do phase.monad
+ []
+ (wrap (|>> (_.string class)
+ (_.INVOKESTATIC $Class "forName" (type.method [(list (type.class "java.lang.String" (list))) $Class (list)])))))
+
+ _
+ (phase.throw extension.invalid-syntax [extension-name %synthesis inputs])))
+
+(def: object::instance?
+ Handler
+ (..custom
+ [($_ <>.and <s>.text <s>.any)
+ (function (_ extension-name generate archive [class objectS])
+ (do phase.monad
+ [objectI (generate archive objectS)]
+ (wrap (|>> objectI
+ (_.INSTANCEOF (type.class class (list)))
+ (_.wrap type.boolean)))))]))
+
+(def: (object::cast extension-name generate archive inputs)
+ Handler
+ (case inputs
+ (^ (list (synthesis.text from) (synthesis.text to) valueS))
+ (do phase.monad
+ [valueI (generate archive valueS)]
+ (`` (cond (~~ (template [<object> <type>]
+ [(and (text@= (reflection.reflection (type.reflection <type>))
+ from)
+ (text@= <object>
+ to))
+ (wrap (|>> valueI (_.wrap <type>)))
+
+ (and (text@= <object>
+ from)
+ (text@= (reflection.reflection (type.reflection <type>))
+ to))
+ (wrap (|>> valueI (_.unwrap <type>)))]
+
+ [box.boolean type.boolean]
+ [box.byte type.byte]
+ [box.short type.short]
+ [box.int type.int]
+ [box.long type.long]
+ [box.float type.float]
+ [box.double type.double]
+ [box.char type.char]))
+ ## else
+ (wrap valueI))))
+
+ _
+ (phase.throw extension.invalid-syntax [extension-name %synthesis inputs])))
+
+(def: object-bundle
+ Bundle
+ (<| (bundle.prefix "object")
+ (|> (: Bundle bundle.empty)
+ (bundle.install "null" (nullary object::null))
+ (bundle.install "null?" (unary object::null?))
+ (bundle.install "synchronized" (binary object::synchronized))
+ (bundle.install "throw" (unary object::throw))
+ (bundle.install "class" object::class)
+ (bundle.install "instance?" object::instance?)
+ (bundle.install "cast" object::cast)
+ )))
+
+(def: primitives
+ (Dictionary Text (Type Primitive))
+ (|> (list [(reflection.reflection reflection.boolean) type.boolean]
+ [(reflection.reflection reflection.byte) type.byte]
+ [(reflection.reflection reflection.short) type.short]
+ [(reflection.reflection reflection.int) type.int]
+ [(reflection.reflection reflection.long) type.long]
+ [(reflection.reflection reflection.float) type.float]
+ [(reflection.reflection reflection.double) type.double]
+ [(reflection.reflection reflection.char) type.char])
+ (dictionary.from-list text.hash)))
+
+(def: get::static
+ Handler
+ (..custom
+ [($_ <>.and <s>.text <s>.text <s>.text)
+ (function (_ extension-name generate archive [class field unboxed])
+ (do phase.monad
+ []
+ (case (dictionary.get unboxed ..primitives)
+ (#.Some primitive)
+ (wrap (_.GETSTATIC (type.class class (list)) field primitive))
+
+ #.None
+ (wrap (_.GETSTATIC (type.class class (list)) field (type.class unboxed (list)))))))]))
+
+(def: put::static
+ Handler
+ (..custom
+ [($_ <>.and <s>.text <s>.text <s>.text <s>.any)
+ (function (_ extension-name generate archive [class field unboxed valueS])
+ (do phase.monad
+ [valueI (generate archive valueS)
+ #let [$class (type.class class (list))]]
+ (case (dictionary.get unboxed ..primitives)
+ (#.Some primitive)
+ (wrap (|>> valueI
+ (_.PUTSTATIC $class field primitive)
+ (_.string synthesis.unit)))
+
+ #.None
+ (wrap (|>> valueI
+ (_.CHECKCAST $class)
+ (_.PUTSTATIC $class field $class)
+ (_.string synthesis.unit))))))]))
+
+(def: get::virtual
+ Handler
+ (..custom
+ [($_ <>.and <s>.text <s>.text <s>.text <s>.any)
+ (function (_ extension-name generate archive [class field unboxed objectS])
+ (do phase.monad
+ [objectI (generate archive objectS)
+ #let [$class (type.class class (list))
+ getI (case (dictionary.get unboxed ..primitives)
+ (#.Some primitive)
+ (_.GETFIELD $class field primitive)
+
+ #.None
+ (_.GETFIELD $class field (type.class unboxed (list))))]]
+ (wrap (|>> objectI
+ (_.CHECKCAST $class)
+ getI))))]))
+
+(def: put::virtual
+ Handler
+ (..custom
+ [($_ <>.and <s>.text <s>.text <s>.text <s>.any <s>.any)
+ (function (_ extension-name generate archive [class field unboxed valueS objectS])
+ (do phase.monad
+ [valueI (generate archive valueS)
+ objectI (generate archive objectS)
+ #let [$class (type.class class (list))
+ putI (case (dictionary.get unboxed ..primitives)
+ (#.Some primitive)
+ (_.PUTFIELD $class field primitive)
+
+ #.None
+ (let [$unboxed (type.class unboxed (list))]
+ (|>> (_.CHECKCAST $unboxed)
+ (_.PUTFIELD $class field $unboxed))))]]
+ (wrap (|>> objectI
+ (_.CHECKCAST $class)
+ _.DUP
+ valueI
+ putI))))]))
+
+(type: Input (Typed Synthesis))
+
+(def: input
+ (Parser Input)
+ (<s>.tuple (<>.and ..value <s>.any)))
+
+(def: (generate-input generate archive [valueT valueS])
+ (-> Phase Archive Input
+ (Operation (Typed Inst)))
+ (do phase.monad
+ [valueI (generate archive valueS)]
+ (case (type.primitive? valueT)
+ (#.Right valueT)
+ (wrap [valueT valueI])
+
+ (#.Left valueT)
+ (wrap [valueT (|>> valueI
+ (_.CHECKCAST valueT))]))))
+
+(def: voidI (_.string synthesis.unit))
+
+(def: (prepare-output outputT)
+ (-> (Type Return) Inst)
+ (case (type.void? outputT)
+ (#.Right outputT)
+ ..voidI
+
+ (#.Left outputT)
+ function.identity))
+
+(def: invoke::static
+ Handler
+ (..custom
+ [($_ <>.and ..class <s>.text ..return (<>.some ..input))
+ (function (_ extension-name generate archive [class method outputT inputsTS])
+ (do {@ phase.monad}
+ [inputsTI (monad.map @ (generate-input generate archive) inputsTS)]
+ (wrap (|>> (_.fuse (list@map product.right inputsTI))
+ (_.INVOKESTATIC class method (type.method [(list@map product.left inputsTI) outputT (list)]))
+ (prepare-output outputT)))))]))
+
+(template [<name> <invoke>]
+ [(def: <name>
+ Handler
+ (..custom
+ [($_ <>.and ..class <s>.text ..return <s>.any (<>.some ..input))
+ (function (_ extension-name generate archive [class method outputT objectS inputsTS])
+ (do {@ phase.monad}
+ [objectI (generate archive objectS)
+ inputsTI (monad.map @ (generate-input generate archive) inputsTS)]
+ (wrap (|>> objectI
+ (_.CHECKCAST class)
+ (_.fuse (list@map product.right inputsTI))
+ (<invoke> class method
+ (type.method [(list@map product.left inputsTI)
+ outputT
+ (list)]))
+ (prepare-output outputT)))))]))]
+
+ [invoke::virtual _.INVOKEVIRTUAL]
+ [invoke::special _.INVOKESPECIAL]
+ [invoke::interface _.INVOKEINTERFACE]
+ )
+
+(def: invoke::constructor
+ Handler
+ (..custom
+ [($_ <>.and ..class (<>.some ..input))
+ (function (_ extension-name generate archive [class inputsTS])
+ (do {@ phase.monad}
+ [inputsTI (monad.map @ (generate-input generate archive) inputsTS)]
+ (wrap (|>> (_.NEW class)
+ _.DUP
+ (_.fuse (list@map product.right inputsTI))
+ (_.INVOKESPECIAL class "<init>" (type.method [(list@map product.left inputsTI) type.void (list)]))))))]))
+
+(def: member
+ Bundle
+ (<| (bundle.prefix "member")
+ (|> (: Bundle bundle.empty)
+ (dictionary.merge (<| (bundle.prefix "get")
+ (|> (: Bundle bundle.empty)
+ (bundle.install "static" get::static)
+ (bundle.install "virtual" get::virtual))))
+ (dictionary.merge (<| (bundle.prefix "put")
+ (|> (: Bundle bundle.empty)
+ (bundle.install "static" put::static)
+ (bundle.install "virtual" put::virtual))))
+ (dictionary.merge (<| (bundle.prefix "invoke")
+ (|> (: Bundle bundle.empty)
+ (bundle.install "static" invoke::static)
+ (bundle.install "virtual" invoke::virtual)
+ (bundle.install "special" invoke::special)
+ (bundle.install "interface" invoke::interface)
+ (bundle.install "constructor" invoke::constructor))))
+ )))
+
+(def: annotation-parameter
+ (Parser (/.Annotation-Parameter Synthesis))
+ (<s>.tuple (<>.and <s>.text <s>.any)))
+
+(def: annotation
+ (Parser (/.Annotation Synthesis))
+ (<s>.tuple (<>.and <s>.text (<>.some ..annotation-parameter))))
+
+(def: argument
+ (Parser Argument)
+ (<s>.tuple (<>.and <s>.text ..value)))
+
+(def: overriden-method-definition
+ (Parser [Environment (/.Overriden-Method Synthesis)])
+ (<s>.tuple (do <>.monad
+ [_ (<s>.text! /.overriden-tag)
+ ownerT ..class
+ name <s>.text
+ strict-fp? <s>.bit
+ annotations (<s>.tuple (<>.some ..annotation))
+ vars (<s>.tuple (<>.some ..var))
+ self-name <s>.text
+ arguments (<s>.tuple (<>.some ..argument))
+ returnT ..return
+ exceptionsT (<s>.tuple (<>.some ..class))
+ [environment body] (<s>.function 1
+ (<s>.tuple <s>.any))]
+ (wrap [environment
+ [ownerT name
+ strict-fp? annotations vars
+ self-name arguments returnT exceptionsT
+ body]]))))
+
+(def: (normalize-path normalize)
+ (-> (-> Synthesis Synthesis)
+ (-> Path Path))
+ (function (recur path)
+ (case path
+ (^ (synthesis.path/then bodyS))
+ (synthesis.path/then (normalize bodyS))
+
+ (^template [<tag>]
+ (^ (<tag> leftP rightP))
+ (<tag> (recur leftP) (recur rightP)))
+ ([#synthesis.Alt]
+ [#synthesis.Seq])
+
+ (^template [<tag>]
+ (^ (<tag> value))
+ path)
+ ([#synthesis.Pop]
+ [#synthesis.Test]
+ [#synthesis.Bind]
+ [#synthesis.Access]))))
+
+(def: (normalize-method-body mapping)
+ (-> (Dictionary Variable Variable) Synthesis Synthesis)
+ (function (recur body)
+ (case body
+ (^template [<tag>]
+ (^ (<tag> value))
+ body)
+ ([#synthesis.Primitive]
+ [synthesis.constant])
+
+ (^ (synthesis.variant [lefts right? sub]))
+ (synthesis.variant [lefts right? (recur sub)])
+
+ (^ (synthesis.tuple members))
+ (synthesis.tuple (list@map recur members))
+
+ (^ (synthesis.variable var))
+ (|> mapping
+ (dictionary.get var)
+ (maybe.default var)
+ synthesis.variable)
+
+ (^ (synthesis.branch/case [inputS pathS]))
+ (synthesis.branch/case [(recur inputS) (normalize-path recur pathS)])
+
+ (^ (synthesis.branch/let [inputS register outputS]))
+ (synthesis.branch/let [(recur inputS) register (recur outputS)])
+
+ (^ (synthesis.branch/if [testS thenS elseS]))
+ (synthesis.branch/if [(recur testS) (recur thenS) (recur elseS)])
+
+ (^ (synthesis.loop/scope [offset initsS+ bodyS]))
+ (synthesis.loop/scope [offset (list@map recur initsS+) (recur bodyS)])
+
+ (^ (synthesis.loop/recur updatesS+))
+ (synthesis.loop/recur (list@map recur updatesS+))
+
+ (^ (synthesis.function/abstraction [environment arity bodyS]))
+ (synthesis.function/abstraction [(|> environment (list@map (function (_ local)
+ (|> mapping
+ (dictionary.get local)
+ (maybe.default local)))))
+ arity
+ bodyS])
+
+ (^ (synthesis.function/apply [functionS inputsS+]))
+ (synthesis.function/apply [(recur functionS) (list@map recur inputsS+)])
+
+ (#synthesis.Extension [name inputsS+])
+ (#synthesis.Extension [name (list@map recur inputsS+)]))))
+
+(def: $Object (type.class "java.lang.Object" (list)))
+
+(def: (anonymous-init-method env)
+ (-> Environment (Type Method))
+ (type.method [(list.repeat (list.size env) $Object)
+ type.void
+ (list)]))
+
+(def: (with-anonymous-init class env super-class inputsTI)
+ (-> (Type Class) Environment (Type Class) (List (Typed Inst)) Def)
+ (let [store-capturedI (|> env
+ list.size
+ list.indices
+ (list@map (.function (_ register)
+ (|>> (_.ALOAD 0)
+ (_.ALOAD (inc register))
+ (_.PUTFIELD class (///reference.foreign-name register) $Object))))
+ _.fuse)]
+ (_def.method #$.Public $.noneM "<init>" (anonymous-init-method env)
+ (|>> (_.ALOAD 0)
+ ((_.fuse (list@map product.right inputsTI)))
+ (_.INVOKESPECIAL super-class "<init>" (type.method [(list@map product.left inputsTI) type.void (list)]))
+ store-capturedI
+ _.RETURN))))
+
+(def: (anonymous-instance archive class env)
+ (-> Archive (Type Class) Environment (Operation Inst))
+ (do {@ phase.monad}
+ [captureI+ (monad.map @ (///reference.variable archive) env)]
+ (wrap (|>> (_.NEW class)
+ _.DUP
+ (_.fuse captureI+)
+ (_.INVOKESPECIAL class "<init>" (anonymous-init-method env))))))
+
+(def: (returnI returnT)
+ (-> (Type Return) Inst)
+ (case (type.void? returnT)
+ (#.Right returnT)
+ _.RETURN
+
+ (#.Left returnT)
+ (case (type.primitive? returnT)
+ (#.Left returnT)
+ (|>> (_.CHECKCAST returnT)
+ _.ARETURN)
+
+ (#.Right returnT)
+ (cond (or (:: type.equivalence = type.boolean returnT)
+ (:: type.equivalence = type.byte returnT)
+ (:: type.equivalence = type.short returnT)
+ (:: type.equivalence = type.int returnT)
+ (:: type.equivalence = type.char returnT))
+ _.IRETURN
+
+ (:: type.equivalence = type.long returnT)
+ _.LRETURN
+
+ (:: type.equivalence = type.float returnT)
+ _.FRETURN
+
+ ## (:: type.equivalence = type.double returnT)
+ _.DRETURN))))
+
+(def: class::anonymous
+ Handler
+ (..custom
+ [($_ <>.and
+ ..class
+ (<s>.tuple (<>.some ..class))
+ (<s>.tuple (<>.some ..input))
+ (<s>.tuple (<>.some ..overriden-method-definition)))
+ (function (_ extension-name generate archive [super-class super-interfaces
+ inputsTS
+ overriden-methods])
+ (do {@ phase.monad}
+ [[context _] (generation.with-new-context archive (wrap []))
+ #let [[module-id artifact-id] context
+ anonymous-class-name (///.class-name context)
+ class (type.class anonymous-class-name (list))
+ total-environment (|> overriden-methods
+ ## Get all the environments.
+ (list@map product.left)
+ ## Combine them.
+ list@join
+ ## Remove duplicates.
+ (set.from-list reference.hash)
+ set.to-list)
+ global-mapping (|> total-environment
+ ## Give them names as "foreign" variables.
+ list.enumerate
+ (list@map (function (_ [id capture])
+ [capture (#reference.Foreign id)]))
+ (dictionary.from-list reference.hash))
+ normalized-methods (list@map (function (_ [environment
+ [ownerT name
+ strict-fp? annotations vars
+ self-name arguments returnT exceptionsT
+ body]])
+ (let [local-mapping (|> environment
+ list.enumerate
+ (list@map (function (_ [foreign-id capture])
+ [(#reference.Foreign foreign-id)
+ (|> global-mapping
+ (dictionary.get capture)
+ maybe.assume)]))
+ (dictionary.from-list reference.hash))]
+ [ownerT name
+ strict-fp? annotations vars
+ self-name arguments returnT exceptionsT
+ (normalize-method-body local-mapping body)]))
+ overriden-methods)]
+ inputsTI (monad.map @ (generate-input generate archive) inputsTS)
+ method-definitions (|> normalized-methods
+ (monad.map @ (function (_ [ownerT name
+ strict-fp? annotations vars
+ self-name arguments returnT exceptionsT
+ bodyS])
+ (do @
+ [bodyG (generation.with-context artifact-id
+ (generate archive bodyS))]
+ (wrap (_def.method #$.Public
+ (if strict-fp?
+ ($_ $.++M $.finalM $.strictM)
+ $.finalM)
+ name
+ (type.method [(list@map product.right arguments)
+ returnT
+ exceptionsT])
+ (|>> bodyG (returnI returnT)))))))
+ (:: @ map _def.fuse))
+ _ (generation.save! true ["" (%.nat artifact-id)]
+ [anonymous-class-name
+ (_def.class #$.V1_6 #$.Public $.finalC
+ anonymous-class-name (list)
+ super-class super-interfaces
+ (|>> (///function.with-environment total-environment)
+ (..with-anonymous-init class total-environment super-class inputsTI)
+ method-definitions))])]
+ (anonymous-instance archive class total-environment)))]))
+
+(def: bundle::class
+ Bundle
+ (<| (bundle.prefix "class")
+ (|> (: Bundle bundle.empty)
+ (bundle.install "anonymous" class::anonymous)
+ )))
+
+(def: #export bundle
+ Bundle
+ (<| (bundle.prefix "jvm")
+ (|> ..conversion
+ (dictionary.merge ..int)
+ (dictionary.merge ..long)
+ (dictionary.merge ..float)
+ (dictionary.merge ..double)
+ (dictionary.merge ..char)
+ (dictionary.merge ..array)
+ (dictionary.merge ..object-bundle)
+ (dictionary.merge ..member)
+ (dictionary.merge ..bundle::class)
+ )))
diff --git a/lux-jvm/source/luxc/lang/translation/jvm/function.lux b/lux-jvm/source/luxc/lang/translation/jvm/function.lux
new file mode 100644
index 000000000..888ad9545
--- /dev/null
+++ b/lux-jvm/source/luxc/lang/translation/jvm/function.lux
@@ -0,0 +1,331 @@
+(.module:
+ [lux (#- Type function)
+ [abstract
+ ["." monad (#+ do)]]
+ [control
+ [pipe (#+ when> new>)]
+ ["." function]]
+ [data
+ ["." product]
+ [text
+ ["%" format (#+ format)]]
+ [number
+ ["n" nat]
+ ["i" int]]
+ [collection
+ ["." list ("#@." functor monoid)]]]
+ [target
+ [jvm
+ ["." type (#+ Type)
+ ["." category (#+ Void Value Return Primitive Object Class Array Var Parameter Method)]]]]
+ [tool
+ [compiler
+ [arity (#+ Arity)]
+ [reference (#+ Register)]
+ ["." phase]
+ [language
+ [lux
+ [analysis (#+ Environment)]
+ [synthesis (#+ Synthesis Abstraction Apply)]
+ ["." generation]]]
+ [meta
+ [archive (#+ Archive)]]]]]
+ [luxc
+ [lang
+ [host
+ ["$" jvm (#+ Label Inst Def Operation Phase Generator)
+ ["." def]
+ ["_" inst]]]]]
+ ["." //
+ ["#." runtime]
+ ["." reference]])
+
+(def: arity-field Text "arity")
+
+(def: (poly-arg? arity)
+ (-> Arity Bit)
+ (n.> 1 arity))
+
+(def: (captured-args env)
+ (-> Environment (List (Type Value)))
+ (list.repeat (list.size env) //.$Value))
+
+(def: (init-method env arity)
+ (-> Environment Arity (Type Method))
+ (if (poly-arg? arity)
+ (type.method [(list.concat (list (captured-args env)
+ (list type.int)
+ (list.repeat (dec arity) //.$Value)))
+ type.void
+ (list)])
+ (type.method [(captured-args env) type.void (list)])))
+
+(def: (implementation-method arity)
+ (type.method [(list.repeat arity //.$Value) //.$Value (list)]))
+
+(def: get-amount-of-partialsI
+ Inst
+ (|>> (_.ALOAD 0)
+ (_.GETFIELD //.$Function //runtime.partials-field type.int)))
+
+(def: (load-fieldI class field)
+ (-> (Type Class) Text Inst)
+ (|>> (_.ALOAD 0)
+ (_.GETFIELD class field //.$Value)))
+
+(def: (inputsI start amount)
+ (-> Register Nat Inst)
+ (|> (list.n/range start (n.+ start (dec amount)))
+ (list@map _.ALOAD)
+ _.fuse))
+
+(def: (applysI start amount)
+ (-> Register Nat Inst)
+ (let [max-args (n.min amount //runtime.num-apply-variants)
+ later-applysI (if (n.> //runtime.num-apply-variants amount)
+ (applysI (n.+ //runtime.num-apply-variants start) (n.- //runtime.num-apply-variants amount))
+ function.identity)]
+ (|>> (_.CHECKCAST //.$Function)
+ (inputsI start max-args)
+ (_.INVOKEVIRTUAL //.$Function //runtime.apply-method (//runtime.apply-signature max-args))
+ later-applysI)))
+
+(def: (inc-intI by)
+ (-> Nat Inst)
+ (|>> (_.int (.int by))
+ _.IADD))
+
+(def: (nullsI amount)
+ (-> Nat Inst)
+ (|> _.NULL
+ (list.repeat amount)
+ _.fuse))
+
+(def: (instance archive class arity env)
+ (-> Archive (Type Class) Arity Environment (Operation Inst))
+ (do {@ phase.monad}
+ [captureI+ (monad.map @ (reference.variable archive) env)
+ #let [argsI (if (poly-arg? arity)
+ (|> (nullsI (dec arity))
+ (list (_.int +0))
+ _.fuse)
+ function.identity)]]
+ (wrap (|>> (_.NEW class)
+ _.DUP
+ (_.fuse captureI+)
+ argsI
+ (_.INVOKESPECIAL class "<init>" (init-method env arity))))))
+
+(def: (reset-method return)
+ (-> (Type Class) (Type Method))
+ (type.method [(list) return (list)]))
+
+(def: (with-reset class arity env)
+ (-> (Type Class) Arity Environment Def)
+ (def.method #$.Public $.noneM "reset" (reset-method class)
+ (if (poly-arg? arity)
+ (let [env-size (list.size env)
+ captureI (|> (case env-size
+ 0 (list)
+ _ (list.n/range 0 (dec env-size)))
+ (list@map (.function (_ source)
+ (|>> (_.ALOAD 0)
+ (_.GETFIELD class (reference.foreign-name source) //.$Value))))
+ _.fuse)
+ argsI (|> (nullsI (dec arity))
+ (list (_.int +0))
+ _.fuse)]
+ (|>> (_.NEW class)
+ _.DUP
+ captureI
+ argsI
+ (_.INVOKESPECIAL class "<init>" (init-method env arity))
+ _.ARETURN))
+ (|>> (_.ALOAD 0)
+ _.ARETURN))))
+
+(def: (with-implementation arity @begin bodyI)
+ (-> Nat Label Inst Def)
+ (def.method #$.Public $.strictM "impl" (implementation-method arity)
+ (|>> (_.label @begin)
+ bodyI
+ _.ARETURN)))
+
+(def: function-init-method
+ (type.method [(list type.int) type.void (list)]))
+
+(def: (function-init arity env-size)
+ (-> Arity Nat Inst)
+ (if (n.= 1 arity)
+ (|>> (_.int +0)
+ (_.INVOKESPECIAL //.$Function "<init>" function-init-method))
+ (|>> (_.ILOAD (inc env-size))
+ (_.INVOKESPECIAL //.$Function "<init>" function-init-method))))
+
+(def: (with-init class env arity)
+ (-> (Type Class) Environment Arity Def)
+ (let [env-size (list.size env)
+ offset-partial (: (-> Nat Nat)
+ (|>> inc (n.+ env-size)))
+ store-capturedI (|> (case env-size
+ 0 (list)
+ _ (list.n/range 0 (dec env-size)))
+ (list@map (.function (_ register)
+ (|>> (_.ALOAD 0)
+ (_.ALOAD (inc register))
+ (_.PUTFIELD class (reference.foreign-name register) //.$Value))))
+ _.fuse)
+ store-partialI (if (poly-arg? arity)
+ (|> (list.n/range 0 (n.- 2 arity))
+ (list@map (.function (_ idx)
+ (let [register (offset-partial idx)]
+ (|>> (_.ALOAD 0)
+ (_.ALOAD (inc register))
+ (_.PUTFIELD class (reference.partial-name idx) //.$Value)))))
+ _.fuse)
+ function.identity)]
+ (def.method #$.Public $.noneM "<init>" (init-method env arity)
+ (|>> (_.ALOAD 0)
+ (function-init arity env-size)
+ store-capturedI
+ store-partialI
+ _.RETURN))))
+
+(def: (with-apply class env function-arity @begin bodyI apply-arity)
+ (-> (Type Class) Environment Arity Label Inst Arity
+ Def)
+ (let [num-partials (dec function-arity)
+ @default ($.new-label [])
+ @labels (list@map $.new-label (list.repeat num-partials []))
+ over-extent (|> (.int function-arity) (i.- (.int apply-arity)))
+ casesI (|> (list@compose @labels (list @default))
+ (list.zip2 (list.n/range 0 num-partials))
+ (list@map (.function (_ [stage @label])
+ (let [load-partialsI (if (n.> 0 stage)
+ (|> (list.n/range 0 (dec stage))
+ (list@map (|>> reference.partial-name (load-fieldI class)))
+ _.fuse)
+ function.identity)]
+ (cond (i.= over-extent (.int stage))
+ (|>> (_.label @label)
+ (_.ALOAD 0)
+ (when> [(new> (n.> 0 stage) [])]
+ [(_.INVOKEVIRTUAL class "reset" (reset-method class))])
+ load-partialsI
+ (inputsI 1 apply-arity)
+ (_.INVOKEVIRTUAL class "impl" (implementation-method function-arity))
+ _.ARETURN)
+
+ (i.> over-extent (.int stage))
+ (let [args-to-completion (|> function-arity (n.- stage))
+ args-left (|> apply-arity (n.- args-to-completion))]
+ (|>> (_.label @label)
+ (_.ALOAD 0)
+ (_.INVOKEVIRTUAL class "reset" (reset-method class))
+ load-partialsI
+ (inputsI 1 args-to-completion)
+ (_.INVOKEVIRTUAL class "impl" (implementation-method function-arity))
+ (applysI (inc args-to-completion) args-left)
+ _.ARETURN))
+
+ ## (i.< over-extent (.int stage))
+ (let [env-size (list.size env)
+ load-capturedI (|> (case env-size
+ 0 (list)
+ _ (list.n/range 0 (dec env-size)))
+ (list@map (|>> reference.foreign-name (load-fieldI class)))
+ _.fuse)]
+ (|>> (_.label @label)
+ (_.NEW class)
+ _.DUP
+ load-capturedI
+ get-amount-of-partialsI
+ (inc-intI apply-arity)
+ load-partialsI
+ (inputsI 1 apply-arity)
+ (nullsI (|> num-partials (n.- apply-arity) (n.- stage)))
+ (_.INVOKESPECIAL class "<init>" (init-method env function-arity))
+ _.ARETURN))
+ ))))
+ _.fuse)]
+ (def.method #$.Public $.noneM //runtime.apply-method (//runtime.apply-signature apply-arity)
+ (|>> get-amount-of-partialsI
+ (_.TABLESWITCH +0 (|> num-partials dec .int)
+ @default @labels)
+ casesI
+ ))))
+
+(def: #export with-environment
+ (-> Environment Def)
+ (|>> list.enumerate
+ (list@map (.function (_ [env-idx env-source])
+ (def.field #$.Private $.finalF (reference.foreign-name env-idx) //.$Value)))
+ def.fuse))
+
+(def: (with-partial arity)
+ (-> Arity Def)
+ (if (poly-arg? arity)
+ (|> (list.n/range 0 (n.- 2 arity))
+ (list@map (.function (_ idx)
+ (def.field #$.Private $.finalF (reference.partial-name idx) //.$Value)))
+ def.fuse)
+ function.identity))
+
+(def: #export (with-function archive @begin class env arity bodyI)
+ (-> Archive Label Text Environment Arity Inst
+ (Operation [Def Inst]))
+ (let [classD (type.class class (list))
+ applyD (: Def
+ (if (poly-arg? arity)
+ (|> (n.min arity //runtime.num-apply-variants)
+ (list.n/range 1)
+ (list@map (with-apply classD env arity @begin bodyI))
+ (list& (with-implementation arity @begin bodyI))
+ def.fuse)
+ (def.method #$.Public $.strictM //runtime.apply-method (//runtime.apply-signature 1)
+ (|>> (_.label @begin)
+ bodyI
+ _.ARETURN))))
+ functionD (: Def
+ (|>> (def.int-field #$.Public ($_ $.++F $.staticF $.finalF) arity-field (.int arity))
+ (with-environment env)
+ (with-partial arity)
+ (with-init classD env arity)
+ (with-reset classD arity env)
+ applyD
+ ))]
+ (do phase.monad
+ [instanceI (instance archive classD arity env)]
+ (wrap [functionD instanceI]))))
+
+(def: #export (function generate archive [env arity bodyS])
+ (Generator Abstraction)
+ (do phase.monad
+ [@begin _.make-label
+ [function-context bodyI] (generation.with-new-context archive
+ (generation.with-anchor [@begin 1]
+ (generate archive bodyS)))
+ #let [function-class (//.class-name function-context)]
+ [functionD instanceI] (with-function archive @begin function-class env arity bodyI)
+ _ (generation.save! true ["" (%.nat (product.right function-context))]
+ [function-class
+ (def.class #$.V1_6 #$.Public $.finalC
+ function-class (list)
+ //.$Function (list)
+ functionD)])]
+ (wrap instanceI)))
+
+(def: #export (call generate archive [functionS argsS])
+ (Generator Apply)
+ (do {@ phase.monad}
+ [functionI (generate archive functionS)
+ argsI (monad.map @ (generate archive) argsS)
+ #let [applyI (|> argsI
+ (list.split-all //runtime.num-apply-variants)
+ (list@map (.function (_ chunkI+)
+ (|>> (_.CHECKCAST //.$Function)
+ (_.fuse chunkI+)
+ (_.INVOKEVIRTUAL //.$Function //runtime.apply-method (//runtime.apply-signature (list.size chunkI+))))))
+ _.fuse)]]
+ (wrap (|>> functionI
+ applyI))))
diff --git a/lux-jvm/source/luxc/lang/translation/jvm/loop.lux b/lux-jvm/source/luxc/lang/translation/jvm/loop.lux
new file mode 100644
index 000000000..1f2168fed
--- /dev/null
+++ b/lux-jvm/source/luxc/lang/translation/jvm/loop.lux
@@ -0,0 +1,81 @@
+(.module:
+ [lux #*
+ [abstract
+ ["." monad (#+ do)]]
+ [control
+ ["." function]]
+ [data
+ [number
+ ["n" nat]]
+ [collection
+ ["." list ("#/." functor monoid)]]]
+ [tool
+ [compiler
+ [reference (#+ Register)]
+ ["." phase]
+ [language
+ [lux
+ ["." synthesis (#+ Synthesis)]
+ ["." generation]]]]]]
+ [luxc
+ [lang
+ [host
+ [jvm (#+ Inst Operation Phase Generator)
+ ["_" inst]]]]]
+ ["." //])
+
+(def: (invariant? register changeS)
+ (-> Register Synthesis Bit)
+ (case changeS
+ (^ (synthesis.variable/local var))
+ (n.= register var)
+
+ _
+ false))
+
+(def: #export (recur translate archive argsS)
+ (Generator (List Synthesis))
+ (do {@ phase.monad}
+ [[@begin start] generation.anchor
+ #let [end (|> argsS list.size dec (n.+ start))
+ pairs (list.zip2 (list.n/range start end)
+ argsS)]
+ ## It may look weird that first I compile the values separately,
+ ## and then I compile the stores/allocations.
+ ## It must be done that way in order to avoid a potential bug.
+ ## Let's say that you'll recur with 2 expressions: X and Y.
+ ## If Y depends on the value of X, and you don't compile values
+ ## and stores separately, then by the time Y is evaluated, it
+ ## will refer to the new value of X, instead of the old value, as
+ ## should be the case.
+ valuesI+ (monad.map @ (function (_ [register argS])
+ (: (Operation Inst)
+ (if (invariant? register argS)
+ (wrap function.identity)
+ (translate archive argS))))
+ pairs)
+ #let [storesI+ (list/map (function (_ [register argS])
+ (: Inst
+ (if (invariant? register argS)
+ function.identity
+ (_.ASTORE register))))
+ (list.reverse pairs))]]
+ (wrap (|>> (_.fuse valuesI+)
+ (_.fuse storesI+)
+ (_.GOTO @begin)))))
+
+(def: #export (scope translate archive [start initsS+ iterationS])
+ (Generator [Nat (List Synthesis) Synthesis])
+ (do {@ phase.monad}
+ [@begin _.make-label
+ initsI+ (monad.map @ (translate archive) initsS+)
+ iterationI (generation.with-anchor [@begin start]
+ (translate archive iterationS))
+ #let [initializationI (|> (list.enumerate initsI+)
+ (list/map (function (_ [register initI])
+ (|>> initI
+ (_.ASTORE (n.+ start register)))))
+ _.fuse)]]
+ (wrap (|>> initializationI
+ (_.label @begin)
+ iterationI))))
diff --git a/lux-jvm/source/luxc/lang/translation/jvm/primitive.lux b/lux-jvm/source/luxc/lang/translation/jvm/primitive.lux
new file mode 100644
index 000000000..873c363bd
--- /dev/null
+++ b/lux-jvm/source/luxc/lang/translation/jvm/primitive.lux
@@ -0,0 +1,30 @@
+(.module:
+ [lux (#- i64)
+ [target
+ [jvm
+ ["." type]]]
+ [tool
+ [compiler
+ [phase ("operation@." monad)]]]]
+ [luxc
+ [lang
+ [host
+ ["." jvm (#+ Inst Operation)
+ ["_" inst]]]]])
+
+(def: #export bit
+ (-> Bit (Operation Inst))
+ (let [Boolean (type.class "java.lang.Boolean" (list))]
+ (function (_ value)
+ (operation@wrap (_.GETSTATIC Boolean (if value "TRUE" "FALSE") Boolean)))))
+
+(template [<name> <type> <load> <wrap>]
+ [(def: #export (<name> value)
+ (-> <type> (Operation Inst))
+ (let [loadI (|> value <load>)]
+ (operation@wrap (|>> loadI <wrap>))))]
+
+ [i64 (I64 Any) (<| _.long .int) (_.wrap type.long)]
+ [f64 Frac _.double (_.wrap type.double)]
+ [text Text _.string (<|)]
+ )
diff --git a/lux-jvm/source/luxc/lang/translation/jvm/program.lux b/lux-jvm/source/luxc/lang/translation/jvm/program.lux
new file mode 100644
index 000000000..7ac897009
--- /dev/null
+++ b/lux-jvm/source/luxc/lang/translation/jvm/program.lux
@@ -0,0 +1,82 @@
+(.module:
+ [lux #*
+ [target
+ [jvm
+ ["$t" type]]]]
+ [luxc
+ [lang
+ [host
+ ["_" jvm
+ ["$d" def]
+ ["$i" inst]]]
+ [translation
+ ["." jvm
+ ["." runtime]]]]])
+
+(def: #export class "LuxProgram")
+
+(def: ^Object ($t.class "java.lang.Object" (list)))
+
+(def: #export (program programI)
+ (-> _.Inst _.Definition)
+ (let [nilI runtime.noneI
+ num-inputsI (|>> ($i.ALOAD 0) $i.ARRAYLENGTH)
+ decI (|>> ($i.int +1) $i.ISUB)
+ headI (|>> $i.DUP
+ ($i.ALOAD 0)
+ $i.SWAP
+ $i.AALOAD
+ $i.SWAP
+ $i.DUP_X2
+ $i.POP)
+ pairI (|>> ($i.int +2)
+ ($i.ANEWARRAY ..^Object)
+ $i.DUP_X1
+ $i.SWAP
+ ($i.int +0)
+ $i.SWAP
+ $i.AASTORE
+ $i.DUP_X1
+ $i.SWAP
+ ($i.int +1)
+ $i.SWAP
+ $i.AASTORE)
+ consI (|>> ($i.int +1)
+ ($i.string "")
+ $i.DUP2_X1
+ $i.POP2
+ runtime.variantI)
+ prepare-input-listI (<| $i.with-label (function (_ @loop))
+ $i.with-label (function (_ @end))
+ (|>> nilI
+ num-inputsI
+ ($i.label @loop)
+ decI
+ $i.DUP
+ ($i.IFLT @end)
+ headI
+ pairI
+ consI
+ $i.SWAP
+ ($i.GOTO @loop)
+ ($i.label @end)
+ $i.POP))
+ feed-inputsI ($i.INVOKEVIRTUAL jvm.$Function runtime.apply-method (runtime.apply-signature 1))
+ run-ioI (|>> ($i.CHECKCAST jvm.$Function)
+ $i.NULL
+ ($i.INVOKEVIRTUAL jvm.$Function runtime.apply-method (runtime.apply-signature 1)))
+ main-type ($t.method [(list ($t.array ($t.class "java.lang.String" (list))))
+ $t.void
+ (list)])]
+ [..class
+ ($d.class #_.V1_6
+ #_.Public _.finalC
+ ..class
+ (list) ..^Object
+ (list)
+ (|>> ($d.method #_.Public _.staticM "main" main-type
+ (|>> programI
+ prepare-input-listI
+ feed-inputsI
+ run-ioI
+ $i.RETURN))))]))
diff --git a/lux-jvm/source/luxc/lang/translation/jvm/reference.lux b/lux-jvm/source/luxc/lang/translation/jvm/reference.lux
new file mode 100644
index 000000000..6bcf4a2e5
--- /dev/null
+++ b/lux-jvm/source/luxc/lang/translation/jvm/reference.lux
@@ -0,0 +1,65 @@
+(.module:
+ [lux #*
+ [abstract
+ [monad (#+ do)]]
+ [data
+ [text
+ ["%" format (#+ format)]]]
+ [target
+ [jvm
+ ["." type]]]
+ [tool
+ [compiler
+ ["." reference (#+ Register Variable)]
+ ["." phase ("operation@." monad)]
+ [meta
+ [archive (#+ Archive)]]
+ [language
+ [lux
+ ["." generation]]]]]]
+ [luxc
+ [lang
+ [host
+ [jvm (#+ Inst Operation)
+ ["_" inst]]]]]
+ ["." //
+ ["#." runtime]])
+
+(template [<name> <prefix>]
+ [(def: #export <name>
+ (-> Nat Text)
+ (|>> %.nat (format <prefix>)))]
+
+ [foreign-name "f"]
+ [partial-name "p"]
+ )
+
+(def: (foreign archive variable)
+ (-> Archive Register (Operation Inst))
+ (do {@ phase.monad}
+ [class-name (:: @ map //.class-name
+ (generation.context archive))]
+ (wrap (|>> (_.ALOAD 0)
+ (_.GETFIELD (type.class class-name (list))
+ (|> variable .nat foreign-name)
+ //.$Value)))))
+
+(def: local
+ (-> Register Inst)
+ (|>> _.ALOAD))
+
+(def: #export (variable archive variable)
+ (-> Archive Variable (Operation Inst))
+ (case variable
+ (#reference.Local variable)
+ (operation@wrap (local variable))
+
+ (#reference.Foreign variable)
+ (foreign archive variable)))
+
+(def: #export (constant archive name)
+ (-> Archive Name (Operation Inst))
+ (do {@ phase.monad}
+ [class-name (:: @ map //.class-name
+ (generation.remember archive name))]
+ (wrap (_.GETSTATIC (type.class class-name (list)) //.value-field //.$Value))))
diff --git a/lux-jvm/source/luxc/lang/translation/jvm/runtime.lux b/lux-jvm/source/luxc/lang/translation/jvm/runtime.lux
new file mode 100644
index 000000000..a657a7a38
--- /dev/null
+++ b/lux-jvm/source/luxc/lang/translation/jvm/runtime.lux
@@ -0,0 +1,387 @@
+(.module:
+ [lux (#- Type)
+ [abstract
+ [monad (#+ do)]]
+ [data
+ [binary (#+ Binary)]
+ ["." product]
+ [text
+ ["%" format (#+ format)]]
+ [collection
+ ["." list ("#@." functor)]
+ ["." row]]]
+ ["." math]
+ [target
+ [jvm
+ ["." type (#+ Type)
+ ["." category (#+ Void Value' Value Return' Return Primitive Object Class Array Var Parameter Method)]
+ ["." reflection]]]]
+ [tool
+ [compiler (#+ Output)
+ [arity (#+ Arity)]
+ ["." phase]
+ [language
+ [lux
+ ["." synthesis]
+ ["." generation]]]
+ [meta
+ [archive
+ ["." artifact (#+ Registry)]]]]]]
+ [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: 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 //.$Runtime "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: (tryI 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 partials-field Text "partials")
+(def: #export apply-method Text "apply")
+(def: #export num-apply-variants Nat 8)
+
+(def: #export (apply-signature arity)
+ (-> Arity (Type 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-methods
+ Def
+ (|>> ($d.method #$.Public $.staticM "decode_frac" (type.method [(list $Text) //.$Variant (list)])
+ (tryI
+ (|>> (_.ALOAD 0)
+ (_.INVOKESTATIC (type.class "java.lang.Double" (list)) "parseDouble" (type.method [(list $Text) type.double (list)]))
+ (_.wrap type.double))))
+ ))
+
+(def: (illegal-state-exception message)
+ (-> Text Inst)
+ (let [IllegalStateException (type.class "java.lang.IllegalStateException" (list))]
+ (|>> (_.NEW IllegalStateException)
+ _.DUP
+ (_.string message)
+ (_.INVOKESPECIAL IllegalStateException "<init>" (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 (_ @perfect-match!))
+ _.with-label (function (_ @tags-match!))
+ _.with-label (function (_ @maybe-nested))
+ _.with-label (function (_ @mismatch!))
+ (let [$variant (_.ALOAD 0)
+ $tag (_.ILOAD 1)
+ $last? (_.ALOAD 2)
+
+ variant-partI (: (-> Nat Inst)
+ (function (_ idx)
+ (|>> (_.int (.int idx)) _.AALOAD)))
+ ::tag (: Inst
+ (|>> (variant-partI 0) (_.unwrap type.int)))
+ ::last? (variant-partI 1)
+ ::value (variant-partI 2)
+
+ super-nested-tag (|>> _.SWAP ## variant::tag, tag
+ _.ISUB)
+ super-nested (|>> super-nested-tag ## super-tag
+ $variant ::last? ## super-tag, super-last
+ $variant ::value ## super-tag, super-last, super-value
+ ..variantI)
+
+ update-$tag _.ISUB
+ update-$variant (|>> $variant ::value
+ (_.CHECKCAST //.$Variant)
+ (_.ASTORE 0))
+ iterate! (: (-> Label Inst)
+ (function (_ @loop)
+ (|>> update-$variant
+ update-$tag
+ (_.GOTO @loop))))
+
+ not-found _.NULL])
+ (|>> $tag ## tag
+ (_.label @loop)
+ $variant ::tag ## tag, variant::tag
+ _.DUP2 (_.IF_ICMPEQ @tags-match!) ## tag, variant::tag
+ _.DUP2 (_.IF_ICMPGT @maybe-nested) ## tag, variant::tag
+ $last? (_.IFNULL @mismatch!) ## tag, variant::tag
+ super-nested ## super-variant
+ _.ARETURN
+ (_.label @tags-match!) ## tag, variant::tag
+ $last? ## tag, variant::tag, last?
+ $variant ::last? ## tag, variant::tag, last?, variant::last?
+ (_.IF_ACMPEQ @perfect-match!) ## tag, variant::tag
+ (_.label @maybe-nested) ## tag, variant::tag
+ $variant ::last? ## tag, variant::tag, variant::last?
+ (_.IFNULL @mismatch!) ## tag, variant::tag
+ (iterate! @loop)
+ (_.label @perfect-match!) ## tag, variant::tag
+ ## _.POP2
+ $variant ::value
+ _.ARETURN
+ (_.label @mismatch!) ## tag, variant::tag
+ ## _.POP2
+ not-found
+ _.ARETURN)))
+ ($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: #export try (type.method [(list //.$Function) //.$Variant (list)]))
+
+(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 "<init>" nullary-init-methodT))
+ print-writerI (|>> (_.NEW PrintWriter)
+ _.SWAP
+ _.DUP2
+ _.POP
+ _.SWAP
+ (_.boolean true)
+ (_.INVOKESPECIAL PrintWriter "<init>" (type.method [(list (type.class "java.io.Writer" (list)) type.boolean) type.void (list)]))
+ )]
+ (|>> ($d.method #$.Public $.staticM "try" ..try
+ (<| _.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: reflection
+ (All [category]
+ (-> (Type (<| Return' Value' category)) Text))
+ (|>> type.reflection reflection.reflection))
+
+(def: translate-runtime
+ (Operation [Text Binary])
+ (let [runtime-class (..reflection //.$Runtime)
+ 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))
+ payload ["0" bytecode]]
+ (do phase.monad
+ [_ (generation.execute! runtime-class [runtime-class bytecode])
+ _ (generation.save! false ["" "0"] payload)]
+ (wrap payload))))
+
+(def: translate-function
+ (Operation [Text Binary])
+ (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))
+ function-class (..reflection //.$Function)
+ bytecode ($d.abstract #$.V1_6 #$.Public $.noneC function-class (list) $Object (list)
+ (|>> ($d.field #$.Public $.finalF partials-field type.int)
+ ($d.method #$.Public $.noneM "<init>" (type.method [(list type.int) type.void (list)])
+ (|>> (_.ALOAD 0)
+ (_.INVOKESPECIAL $Object "<init>" nullary-init-methodT)
+ (_.ALOAD 0)
+ (_.ILOAD 1)
+ (_.PUTFIELD //.$Function partials-field type.int)
+ _.RETURN))
+ applyI))
+ payload ["1" bytecode]]
+ (do phase.monad
+ [_ (generation.execute! function-class [function-class bytecode])
+ _ (generation.save! false ["" "1"] payload)]
+ (wrap payload))))
+
+(def: #export translate
+ (Operation [Registry Output])
+ (do phase.monad
+ [runtime-payload ..translate-runtime
+ function-payload ..translate-function]
+ (wrap [(|> artifact.empty
+ artifact.resource
+ product.right
+ artifact.resource
+ product.right)
+ (row.row runtime-payload
+ function-payload)])))
diff --git a/lux-jvm/source/luxc/lang/translation/jvm/structure.lux b/lux-jvm/source/luxc/lang/translation/jvm/structure.lux
new file mode 100644
index 000000000..46f87142a
--- /dev/null
+++ b/lux-jvm/source/luxc/lang/translation/jvm/structure.lux
@@ -0,0 +1,79 @@
+(.module:
+ [lux (#- Type)
+ [abstract
+ ["." monad (#+ do)]]
+ [control
+ ["ex" exception (#+ exception:)]]
+ [data
+ [number
+ ["n" nat]]
+ [text
+ ["%" format (#+ format)]]
+ [collection
+ ["." list]]]
+ [target
+ [jvm
+ ["." type (#+ Type)
+ ["." category (#+ Void Value Return Primitive Object Class Array Var Parameter Method)]
+ ["." descriptor (#+ Descriptor)]
+ ["." signature (#+ Signature)]]]]
+ [tool
+ [compiler
+ ["." phase]
+ [meta
+ [archive (#+ Archive)]]
+ [language
+ [lux
+ [synthesis (#+ Synthesis)]]]]]]
+ [luxc
+ [lang
+ [host
+ [jvm (#+ Inst Operation Phase Generator)
+ ["_" inst]]]]]
+ ["." //
+ ["#." runtime]])
+
+(exception: #export (not-a-tuple {size Nat})
+ (ex.report ["Expected size" ">= 2"]
+ ["Actual size" (%.nat size)]))
+
+(def: #export (tuple generate archive members)
+ (Generator (List Synthesis))
+ (do {@ phase.monad}
+ [#let [size (list.size members)]
+ _ (phase.assert not-a-tuple size
+ (n.>= 2 size))
+ membersI (|> members
+ list.enumerate
+ (monad.map @ (function (_ [idx member])
+ (do @
+ [memberI (generate archive member)]
+ (wrap (|>> _.DUP
+ (_.int (.int idx))
+ memberI
+ _.AASTORE)))))
+ (:: @ map _.fuse))]
+ (wrap (|>> (_.int (.int size))
+ (_.array //runtime.$Value)
+ membersI))))
+
+(def: (flagI right?)
+ (-> Bit Inst)
+ (if right?
+ (_.string "")
+ _.NULL))
+
+(def: #export (variant generate archive [lefts right? member])
+ (Generator [Nat Bit Synthesis])
+ (do phase.monad
+ [memberI (generate archive member)]
+ (wrap (|>> (_.int (.int (if right?
+ (.inc lefts)
+ lefts)))
+ (flagI right?)
+ memberI
+ (_.INVOKESTATIC //.$Runtime
+ "variant_make"
+ (type.method [(list //runtime.$Tag //runtime.$Flag //runtime.$Value)
+ //.$Variant
+ (list)]))))))