aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/lux/tool/compiler/phase/generation/jvm/runtime.lux
diff options
context:
space:
mode:
Diffstat (limited to 'stdlib/source/lux/tool/compiler/phase/generation/jvm/runtime.lux')
-rw-r--r--stdlib/source/lux/tool/compiler/phase/generation/jvm/runtime.lux594
1 files changed, 518 insertions, 76 deletions
diff --git a/stdlib/source/lux/tool/compiler/phase/generation/jvm/runtime.lux b/stdlib/source/lux/tool/compiler/phase/generation/jvm/runtime.lux
index 3868b747f..a47892039 100644
--- a/stdlib/source/lux/tool/compiler/phase/generation/jvm/runtime.lux
+++ b/stdlib/source/lux/tool/compiler/phase/generation/jvm/runtime.lux
@@ -1,27 +1,53 @@
(.module:
- [lux (#- Type Definition case)
+ [lux (#- Type Definition case log! false true)
+ [abstract
+ ["." monad (#+ do)]]
+ [control
+ [state (#+ State)]]
[data
[binary (#+ Binary)]
[number
["." i32]
["." i64]
- ["n" nat]]]
+ ["n" nat]]
+ [collection
+ ["." list ("#@." functor)]
+ ["." row]]
+ [format
+ [".F" binary]]]
[target
[jvm
["_" instruction (#+ Label Instruction)]
- ["." constant]
+ ["." modifier (#+ Modifier) ("#@." monoid)]
+ ["." field (#+ Field)]
+ ["." method (#+ Method)]
+ ["." version]
+ ["." class (#+ Class)]
+ ["." constant
+ [pool (#+ Pool)]]
+ [encoding
+ ["." unsigned]
+ ["." name]]
["." type (#+ Type)
- ["." category (#+ Method)]]]]]
+ ["." category (#+ Return' Value')]
+ ["." reflection]]]]]
["." // #_
+ ["#." type]
["#." value]
["#." function #_
- ["#" abstract]]
+ ["#" abstract]
+ [field
+ [constant
+ ["#/." arity]]
+ [variable
+ [partial
+ ["#/." count]]]]]
["/#" //
["/#" //
[//
+ [arity (#+ Arity)]
[reference (#+ Register)]
- ["." synthesis]]]]]
- )
+ ["." synthesis]]]]])
(type: #export Byte-Code Binary)
@@ -44,83 +70,76 @@
(def: #export class (type.class "LuxRuntime" (list)))
-(def: $Text (type.class "java.lang.String" (list)))
-
-(def: #export $Tag type.int)
-(def: #export $Flag //value.type)
-(def: #export $Variant (type.array //value.type))
-
-(def: #export $Offset type.int)
-(def: #export $Tuple (type.array //value.type))
-
-(def: #export $Stack (type.array //value.type))
-
(def: procedure
- (-> Text (Type Method) (Instruction Any))
+ (-> Text (Type category.Method) (Instruction Any))
(_.invokestatic ..class))
-(def: failure-type
- (type.method [(list) type.void (list)]))
-
-(def: #export apply-failure
- (..procedure "apply_failure" ..failure-type))
-
-(def: #export pm-failure
- (..procedure "pm_failure" ..failure-type))
-
-(def: push-name
- "push")
-
-(def: push-type
- (type.method [(list ..$Stack //value.type) ..$Stack (list)]))
-
-(def: #export push
- (..procedure ..push-name ..push-type))
-
-(def: case-name
- "case")
-
-(def: case-type
- (type.method [(list ..$Variant ..$Tag ..$Flag) //value.type (list)]))
+(def: modifier
+ (Modifier Method)
+ ($_ modifier@compose
+ method.public
+ method.static
+ method.strict
+ ))
-(def: #export case
- (..procedure ..case-name ..case-type))
+(def: local
+ (-> Nat (Instruction Any))
+ (|>> unsigned.u1 _.aload))
-(def: projection-type
- (type.method [(list ..$Tuple $Offset) //value.type (list)]))
-
-(def: #export left-projection
- (..procedure "left" ..projection-type))
-
-(def: #export right-projection
- (..procedure "right" ..projection-type))
-
-(def: try-name
- "try")
-
-(def: try-type
- (type.method [(list //function.class) ..$Variant (list)]))
-
-(def: #export try
- (_.invokestatic ..class ..try-name ..try-type))
-
-(def: #export decode-frac
- (..procedure "decode_frac" (type.method [(list ..$Text) ..$Variant (list)])))
+(def: this
+ (Instruction Any)
+ _.aload-0)
-(def: #export variant
- (..procedure "variant" (type.method [(list ..$Tag ..$Flag //value.type) ..$Variant (list)])))
+(def: #export (get index)
+ (-> (Instruction Any) (Instruction Any))
+ ($_ _.compose
+ index
+ _.aaload))
-(def: ldc/integer
- (-> (I64 Any) (Instruction Any))
- (|>> .i64 i32.i32 constant.integer _.ldc/integer))
+(def: (set! index value)
+ (-> (Instruction Any) (Instruction Any) (Instruction Any))
+ ($_ _.compose
+ _.dup
+ index
+ value
+ _.aastore))
+
+(def: #export unit (_.ldc/string synthesis.unit))
+
+(def: variant::name "variant")
+(def: variant::type (type.method [(list //type.tag //type.flag //type.value) //type.variant (list)]))
+(def: #export variant (..procedure ..variant::name ..variant::type))
+
+(def: variant-tag _.iconst-0)
+(def: variant-last? _.iconst-1)
+(def: variant-value _.iconst-2)
+
+(def: variant::method
+ (let [new-variant ($_ _.compose
+ _.iconst-3
+ (_.anewarray //type.value))
+ $tag ($_ _.compose
+ _.iload-0
+ (//value.wrap type.int))
+ $last? _.aload-1
+ $value _.aload-2]
+ (method.method ..modifier ..variant::name
+ ..variant::type
+ (list)
+ ($_ _.compose
+ new-variant
+ (..set! ..variant-tag $tag)
+ (..set! ..variant-last? $last?)
+ (..set! ..variant-value $value)
+ _.areturn))))
(def: #export left-flag _.aconst-null)
-(def: #export right-flag (_.ldc/string ""))
+(def: #export right-flag ..unit)
(def: #export left-injection
(Instruction Any)
($_ _.compose
- (..ldc/integer +0)
+ _.iconst-0
..left-flag
_.dup2-x1
_.pop2
@@ -129,25 +148,448 @@
(def: #export right-injection
(Instruction Any)
($_ _.compose
- (..ldc/integer +1)
+ _.iconst-1
..right-flag
_.dup2-x1
_.pop2
..variant))
-(def: #export some-injection right-injection)
+(def: #export some-injection ..right-injection)
(def: #export none-injection
(Instruction Any)
($_ _.compose
- (..ldc/integer +0)
+ _.iconst-0
_.aconst-null
- (_.ldc/string synthesis.unit)
+ ..unit
..variant))
+(def: (risky $unsafe)
+ (-> (Instruction Any) (Instruction Any))
+ (do _.monad
+ [@from _.new-label
+ @to _.new-label
+ @handler _.new-label]
+ ($_ _.compose
+ (_.try @from @to @handler //type.error)
+ (_.set-label @from)
+ $unsafe
+ ..some-injection
+ _.areturn
+ (_.set-label @to)
+ (_.set-label @handler)
+ ..none-injection
+ _.areturn)))
+
+(def: decode-frac::name "decode_frac")
+(def: decode-frac::type (type.method [(list //type.text) //type.variant (list)]))
+(def: #export decode-frac (..procedure ..decode-frac::name ..decode-frac::type))
+
+(def: decode-frac::method
+ (method.method ..modifier ..variant::name
+ ..variant::type
+ (list)
+ (..risky
+ ($_ _.compose
+ ..this
+ (_.invokestatic //type.frac "parseDouble" (type.method [(list //type.text) type.double (list)]))
+ (//value.wrap type.double)))))
+
+(def: #export log!
+ (Instruction Any)
+ (let [^PrintStream (type.class "java.io.PrintStream" (list))
+ ^System (type.class "java.lang.System" (list))
+ out (_.getstatic ^System "out" ^PrintStream)
+ print-type (type.method [(list //type.value) type.void (list)])
+ print! (function (_ method) (_.invokevirtual ^PrintStream method print-type))]
+ ($_ _.compose
+ out (_.ldc/string "LOG: ") (print! "print")
+ out _.swap (print! "println"))))
+
+(def: exception-constructor (type.method [(list //type.text) type.void (list)]))
+(def: (illegal-state-exception message)
+ (-> Text (Instruction Any))
+ (let [^IllegalStateException (type.class "java.lang.IllegalStateException" (list))]
+ ($_ _.compose
+ (_.new ^IllegalStateException)
+ _.dup
+ (_.ldc/string message)
+ (_.invokespecial ^IllegalStateException "<init>" ..exception-constructor))))
+
+(def: failure::type
+ (type.method [(list) type.void (list)]))
+
+(def: (failure name message)
+ (-> Text Text (State Pool Method))
+ (method.method ..modifier name
+ ..failure::type
+ (list)
+ ($_ _.compose
+ (..illegal-state-exception message)
+ _.athrow)))
+
+(def: apply-failure::name "apply_failure")
+(def: #export apply-failure (..procedure ..apply-failure::name ..failure::type))
+
+(def: apply-failure::method
+ (..failure ..apply-failure::name "Error while applying function."))
+
+(def: pm-failure::name "pm_failure")
+(def: #export pm-failure (..procedure ..pm-failure::name ..failure::type))
+
+(def: pm-failure::method
+ (..failure ..pm-failure::name "Invalid expression for pattern-matching."))
+
+(def: #export stack-head _.iconst-0)
+(def: #export stack-tail _.iconst-1)
+
+(def: push::name "push")
+(def: push::type (type.method [(list //type.stack //type.value) //type.stack (list)]))
+(def: #export push (..procedure ..push::name ..push::type))
+
+(def: push::method
+ (method.method ..modifier ..push::name
+ ..push::type
+ (list)
+ (let [new-stack-frame! ($_ _.compose
+ _.iconst-2
+ (_.anewarray //type.value))
+ $head _.aload-1
+ $tail _.aload-0]
+ ($_ _.compose
+ new-stack-frame!
+ (..set! ..stack-head $head)
+ (..set! ..stack-tail $tail)
+ _.areturn))))
+
+(def: case::name "case")
+(def: case::type (type.method [(list //type.variant //type.tag //type.flag) //type.value (list)]))
+(def: #export case (..procedure ..case::name ..case::type))
+
+(def: case::method
+ (method.method ..modifier ..case::name ..case::type
+ (list)
+ (do _.monad
+ [@loop _.new-label
+ @perfect-match! _.new-label
+ @tags-match! _.new-label
+ @maybe-nested _.new-label
+ @maybe-super-nested _.new-label
+ @mismatch! _.new-label
+ #let [::tag ($_ _.compose
+ (..get ..variant-tag)
+ (//value.unwrap type.int))
+ ::last? (..get ..variant-last?)
+ ::value (..get ..variant-value)
+
+ $variant _.aload-0
+ $tag _.iload-1
+ $last? _.aload-2
+
+ not-found _.aconst-null
+
+ update-$tag ($_ _.compose
+ _.isub
+ _.istore-1)
+ update-$variant ($_ _.compose
+ $variant ::value
+ (_.checkcast //type.variant)
+ _.astore-0)
+ recur (: (-> Label (Instruction Any))
+ (function (_ @loop-start)
+ ($_ _.compose
+ update-$tag
+ update-$variant
+ (_.goto @loop-start))))
+
+ super-nested-tag ($_ _.compose
+ $variant ::tag
+ $tag _.isub)
+ super-nested ($_ _.compose
+ super-nested-tag
+ $variant ::last?
+ $variant ::value
+ ..variant)]]
+ ($_ _.compose
+ (_.set-label @loop)
+ $tag
+ $variant ::tag
+ _.dup2 (_.if-icmpeq @tags-match!)
+ _.dup2 (_.if-icmpgt @maybe-nested)
+ _.dup2 (_.if-icmplt @maybe-super-nested)
+ ## _.pop2
+ not-found
+ _.areturn
+ (_.set-label @tags-match!) ## tag, sumT
+ $last? ## tag, sumT, wants-last?
+ $variant ::last? ## tag, sumT, wants-last?, is-last?
+ (_.if-acmpeq @perfect-match!) ## tag, sumT
+ (_.set-label @maybe-nested) ## tag, sumT
+ $variant ::last? ## tag, sumT, last?
+ (_.ifnull @mismatch!) ## tag, sumT
+ (recur @loop)
+ (_.set-label @perfect-match!) ## tag, sumT
+ ## _.pop2
+ $variant ::value
+ _.areturn
+ (_.set-label @maybe-super-nested) ## tag, sumT
+ $last? (_.ifnull @mismatch!)
+ ## _.pop2
+ super-nested
+ _.areturn
+ (_.set-label @mismatch!) ## tag, sumT
+ ## _.pop2
+ not-found
+ _.areturn
+ ))))
+
+(def: projection-type (type.method [(list //type.tuple //type.offset) //type.value (list)]))
+
+(def: left-projection::name "left")
+(def: #export left-projection (..procedure ..left-projection::name ..projection-type))
+
+(def: right-projection::name "right")
+(def: #export right-projection (..procedure ..right-projection::name ..projection-type))
+
+(def: projection::method2
+ [(State Pool Method) (State Pool Method)]
+ (let [$tuple _.aload-0
+ $tuple::size ($_ _.compose
+ $tuple _.arraylength)
+
+ $lefts _.iload-1
+
+ $last-right ($_ _.compose
+ $tuple::size _.iconst-1 _.isub)
+
+ update-$lefts ($_ _.compose
+ $lefts $last-right _.isub
+ _.istore-1)
+ update-$tuple ($_ _.compose
+ $tuple $last-right _.aaload (_.checkcast //type.tuple)
+ _.astore-0)
+ recur (: (-> Label (Instruction Any))
+ (function (_ @loop)
+ ($_ _.compose
+ update-$lefts
+ update-$tuple
+ (_.goto @loop))))
+
+ left-projection::method
+ (method.method ..modifier ..left-projection::name ..projection-type
+ (list)
+ (do _.monad
+ [@loop _.new-label
+ @recursive _.new-label
+ #let [::left ($_ _.compose
+ $lefts _.aaload)]]
+ ($_ _.compose
+ (_.set-label @loop)
+ $lefts $last-right (_.if-icmpge @recursive)
+ $tuple ::left
+ _.areturn
+ (_.set-label @recursive)
+ ## Recursive
+ (recur @loop))))
+
+ right-projection::method
+ (method.method ..modifier ..right-projection::name ..projection-type
+ (list)
+ (do _.monad
+ [@loop _.new-label
+ @not-tail _.new-label
+ @slice _.new-label
+ #let [$right ($_ _.compose
+ $lefts
+ _.iconst-1
+ _.iadd)
+ $::nested ($_ _.compose
+ $tuple _.swap _.aaload)
+ super-nested ($_ _.compose
+ $tuple
+ $right
+ $tuple::size
+ (_.invokestatic (type.class "java.util.Arrays" (list)) "copyOfRange"
+ (type.method [(list //type.tuple //type.index //type.index) //type.tuple (list)])))]]
+ ($_ _.compose
+ (_.set-label @loop)
+ $last-right $right
+ _.dup2 (_.if-icmpne @not-tail)
+ ## _.pop
+ $::nested
+ _.areturn
+ (_.set-label @not-tail)
+ (_.if-icmpgt @slice)
+ ## Must recurse
+ (recur @loop)
+ (_.set-label @slice)
+ super-nested
+ _.areturn)))]
+ [left-projection::method
+ right-projection::method]))
+
+(def: #export apply::name "apply")
+
+(def: #export (apply::type arity)
+ (-> Arity (Type category.Method))
+ (type.method [(list.repeat arity //type.value) //type.value (list)]))
+
+(def: #export apply
+ (_.invokevirtual //function.class ..apply::name (..apply::type 1)))
+
+(def: try::name "try")
+(def: try::type (type.method [(list //function.class) //type.variant (list)]))
+(def: #export try (..procedure ..try::name ..try::type))
+
+(def: false _.iconst-0)
+(def: true _.iconst-1)
+
+(def: try::method
+ (method.method ..modifier ..try::name ..try::type
+ (list)
+ (do _.monad
+ [@from _.new-label
+ @to _.new-label
+ @handler _.new-label
+ #let [$unsafe ..this
+ unit _.aconst-null
+
+ ^StringWriter (type.class "java.io.StringWriter" (list))
+ string-writer ($_ _.compose
+ (_.new ^StringWriter)
+ _.dup
+ (_.invokespecial ^StringWriter "<init>" (type.method [(list) type.void (list)])))
+
+ ^PrintWriter (type.class "java.io.PrintWriter" (list))
+ print-writer ($_ _.compose
+ ## WTW
+ (_.new ^PrintWriter) ## WTWP
+ _.dup-x1 ## WTPWP
+ _.swap ## WTPPW
+ ..true ## WTPPWZ
+ (_.invokespecial ^PrintWriter "<init>" (type.method [(list (type.class "java.io.Writer" (list)) type.boolean) type.void (list)]))
+ ## WTP
+ )]]
+ ($_ _.compose
+ (_.try @from @to @handler //type.error)
+ (_.set-label @from)
+ $unsafe unit ..apply
+ ..right-injection _.areturn
+ (_.set-label @to)
+ (_.set-label @handler) ## T
+ string-writer ## TW
+ _.dup-x1 ## WTW
+ print-writer ## WTP
+ (_.invokevirtual //type.error "printStackTrace" (type.method [(list ^PrintWriter) type.void (list)])) ## W
+ (_.invokevirtual ^StringWriter "toString" (type.method [(list) //type.text (list)])) ## S
+ ..left-injection _.areturn
+ ))))
+
+(def: reflection
+ (All [category]
+ (-> (Type (<| Return' Value' category)) Text))
+ (|>> type.reflection reflection.reflection))
+
+(def: #export ^Object (type.class "java.lang.Object" (list)))
+
+(def: translate-runtime
+ (Operation Any)
+ (let [class (..reflection ..class)
+ modifier (: (Modifier Class)
+ ($_ modifier@compose
+ class.public
+ class.final))
+ bytecode (<| (binaryF.run class.writer)
+ (class.class version.v6_0
+ modifier
+ (name.internal class)
+ (name.internal (..reflection ^Object)) (list)
+ (list)
+ (let [[left-projection::method right-projection::method] projection::method2]
+ (list ..decode-frac::method
+ ..variant::method
+
+ ..apply-failure::method
+ ..pm-failure::method
+
+ ..push::method
+ ..case::method
+ left-projection::method
+ right-projection::method
+
+ ..try::method))
+ (row.row)))]
+ (do ////.monad
+ [_ (///.execute! class [class bytecode])]
+ (///.save! .false ["" class] [class bytecode]))))
+
+(def: translate-function
+ (Operation Any)
+ (let [apply::method+ (|> (list.n/range (inc //function/arity.minimum)
+ //function/arity.maximum)
+ (list@map (function (_ arity)
+ (method.method method.public ..apply::name (..apply::type arity)
+ (list)
+ (let [previous-inputs (|> arity
+ list.indices
+ (monad.map _.monad ..local))]
+ ($_ _.compose
+ previous-inputs
+ (_.invokevirtual //function.class ..apply::name (..apply::type (dec arity)))
+ (_.checkcast //function.class)
+ (..local arity)
+ (_.invokevirtual //function.class ..apply::name (..apply::type //function/arity.minimum))
+ _.areturn)))))
+ (list& (method.method (modifier@compose method.public method.abstract)
+ ..apply::name (..apply::type //function/arity.minimum)
+ (list)
+ ## TODO: It shouldn't be necessary to set the code for this method, since it's abstract.
+ ## Setting this might be a bug. Verify & fix ASAP.
+ ($_ _.compose
+ ..apply-failure
+ ..this
+ _.areturn))))
+ <init>::method (method.method method.public "<init>" //function.init
+ (list)
+ (let [$partials _.iload-1]
+ ($_ _.compose
+ ..this
+ (_.invokespecial ..^Object "<init>" (type.method [(list) type.void (list)]))
+ ..this
+ $partials
+ (_.putfield //function.class //function/count.field //function/count.type)
+ _.return)))
+ modifier (: (Modifier Class)
+ ($_ modifier@compose
+ class.public
+ class.abstract))
+ class (..reflection //function.class)
+ partial-count (: (State Pool Field)
+ (field.field (modifier@compose field.public field.final)
+ //function/count.field
+ //function/count.type
+ (row.row)))
+ bytecode (<| (binaryF.run class.writer)
+ (class.class version.v6_0
+ modifier
+ (name.internal class)
+ (name.internal (..reflection ..^Object)) (list)
+ (list partial-count)
+ (list& <init>::method apply::method+)
+ (row.row)))]
+ (do ////.monad
+ [_ (///.execute! class [class bytecode])]
+ (///.save! .false ["" class] [class bytecode]))))
+
+(def: #export translate
+ (Operation Any)
+ (do ////.monad
+ [_ ..translate-runtime]
+ ..translate-function))
+
(def: #export forge-label
(Operation Label)
- (let [shift (n./ 2 i64.width)]
+ (let [shift (n./ 4 i64.width)]
## This shift is done to avoid the possibility of forged labels
## to be in the range of the labels that are generated automatically
## during the evaluation of Instruction expressions.