From 4ef2dbc49cd6dae1b8235dfd13dcd298c8aa3bfe Mon Sep 17 00:00:00 2001 From: Eduardo Julian Date: Sat, 14 Apr 2018 02:02:13 -0400 Subject: - Initial R back-end implementation. --- new-luxc/project.clj | 7 +- new-luxc/source/luxc/lang/host/r.lux | 347 +++++++ .../luxc/lang/translation/lua/runtime.jvm.lux | 12 +- new-luxc/source/luxc/lang/translation/r.lux | 223 +++++ .../source/luxc/lang/translation/r/case.jvm.lux | 188 ++++ .../source/luxc/lang/translation/r/eval.jvm.lux | 162 ++++ .../luxc/lang/translation/r/expression.jvm.lux | 88 ++ .../luxc/lang/translation/r/function.jvm.lux | 101 ++ .../source/luxc/lang/translation/r/loop.jvm.lux | 37 + .../luxc/lang/translation/r/primitive.jvm.lux | 30 + .../luxc/lang/translation/r/procedure.jvm.lux | 29 + .../lang/translation/r/procedure/common.jvm.lux | 554 +++++++++++ .../luxc/lang/translation/r/procedure/host.jvm.lux | 89 ++ .../luxc/lang/translation/r/reference.jvm.lux | 42 + .../source/luxc/lang/translation/r/runtime.jvm.lux | 1023 ++++++++++++++++++++ .../luxc/lang/translation/r/statement.jvm.lux | 45 + .../luxc/lang/translation/r/structure.jvm.lux | 31 + new-luxc/test/test/luxc/common.lux | 12 +- new-luxc/test/test/luxc/lang/translation/case.lux | 4 + .../test/test/luxc/lang/translation/common.lux | 4 + .../test/test/luxc/lang/translation/function.lux | 4 + .../test/test/luxc/lang/translation/primitive.lux | 4 + .../test/test/luxc/lang/translation/reference.lux | 10 +- .../test/test/luxc/lang/translation/structure.lux | 4 + 24 files changed, 3039 insertions(+), 11 deletions(-) create mode 100644 new-luxc/source/luxc/lang/host/r.lux create mode 100644 new-luxc/source/luxc/lang/translation/r.lux create mode 100644 new-luxc/source/luxc/lang/translation/r/case.jvm.lux create mode 100644 new-luxc/source/luxc/lang/translation/r/eval.jvm.lux create mode 100644 new-luxc/source/luxc/lang/translation/r/expression.jvm.lux create mode 100644 new-luxc/source/luxc/lang/translation/r/function.jvm.lux create mode 100644 new-luxc/source/luxc/lang/translation/r/loop.jvm.lux create mode 100644 new-luxc/source/luxc/lang/translation/r/primitive.jvm.lux create mode 100644 new-luxc/source/luxc/lang/translation/r/procedure.jvm.lux create mode 100644 new-luxc/source/luxc/lang/translation/r/procedure/common.jvm.lux create mode 100644 new-luxc/source/luxc/lang/translation/r/procedure/host.jvm.lux create mode 100644 new-luxc/source/luxc/lang/translation/r/reference.jvm.lux create mode 100644 new-luxc/source/luxc/lang/translation/r/runtime.jvm.lux create mode 100644 new-luxc/source/luxc/lang/translation/r/statement.jvm.lux create mode 100644 new-luxc/source/luxc/lang/translation/r/structure.jvm.lux (limited to 'new-luxc') diff --git a/new-luxc/project.clj b/new-luxc/project.clj index 73c42b472..770612a73 100644 --- a/new-luxc/project.clj +++ b/new-luxc/project.clj @@ -12,7 +12,8 @@ [:name "Eduardo Julian"] [:url "https://github.com/eduardoejp"]]] :repositories [["snapshots" "https://oss.sonatype.org/content/repositories/snapshots/"] - ["releases" "https://oss.sonatype.org/service/local/staging/deploy/maven2/"]] + ["releases" "https://oss.sonatype.org/service/local/staging/deploy/maven2/"] + ["bedatadriven" "https://nexus.bedatadriven.com/content/groups/public/"]] :scm {:name "git" :url "https://github.com/LuxLang/lux.git"} @@ -21,7 +22,9 @@ [net.sandius.rembulan/rembulan-stdlib "0.1-SNAPSHOT"] [net.sandius.rembulan/rembulan-compiler "0.1-SNAPSHOT"] [org.jruby/jruby-complete "9.1.16.0"] - [org.python/jython-standalone "2.7.1"]] + [org.python/jython-standalone "2.7.1"] + [org.renjin/renjin-script-engine "0.8.2527"] + ] :source-paths ["source"] :test-paths ["test"] diff --git a/new-luxc/source/luxc/lang/host/r.lux b/new-luxc/source/luxc/lang/host/r.lux new file mode 100644 index 000000000..62c33479d --- /dev/null +++ b/new-luxc/source/luxc/lang/host/r.lux @@ -0,0 +1,347 @@ +(.module: + [lux #- not or and list if function cond] + (lux (control pipe) + (data [text] + text/format + [number] + (coll [list "list/" Functor Fold])) + (type abstract))) + +(abstract: #export Single {} Unit) +(abstract: #export Poly {} Unit) + +(abstract: #export (Var kind) + {} + + Text + + (def: name (All [k] (-> (Var k) Text)) (|>> @representation)) + + (def: #export var (-> Text (Var Single)) (|>> @abstraction)) + (def: #export var-args (Var Poly) (@abstraction "...")) + ) + +(type: #export SVar (Var Single)) +(type: #export PVar (Var Poly)) + +(abstract: #export Expression + {} + + Text + + (def: #export expression (-> Expression Text) (|>> @representation)) + + (def: #export code (-> Text Expression) (|>> @abstraction)) + + (def: (self-contained code) + (-> Text Text) + (format "(" code ")")) + + (def: #export null + Expression + (|> "NULL" self-contained @abstraction)) + + (def: #export n/a + Expression + (|> "NA" self-contained @abstraction)) + + (def: #export not-available Expression n/a) + (def: #export not-applicable Expression n/a) + (def: #export no-answer Expression n/a) + + (def: #export bool + (-> Bool Expression) + (|>> (case> true "TRUE" + false "FALSE") + self-contained + @abstraction)) + + (def: #export (int value) + (-> Int Expression) + (@abstraction + (self-contained + (format "as.integer(" (%i value) ")")))) + + (def: #export float + (-> Frac Expression) + (|>> (cond> [(f/= number.positive-infinity)] + [(new> "1.0/0.0")] + + [(f/= number.negative-infinity)] + [(new> "-1.0/0.0")] + + [(f/= number.not-a-number)] + [(new> "0.0/0.0")] + + ## else + [%f]) + self-contained + @abstraction)) + + (def: #export string + (-> Text Expression) + (|>> %t self-contained @abstraction)) + + (def: (composite-literal left-delimiter right-delimiter entry-serializer) + (All [a] (-> Text Text (-> a Text) + (-> (List a) Expression))) + (.function (_ entries) + (@abstraction + (self-contained + (format left-delimiter + (|> entries (list/map entry-serializer) (text.join-with ",")) + right-delimiter))))) + + (def: #export named-list + (-> (List [Text Expression]) Expression) + (composite-literal "list(" ")" (.function (_ [key value]) + (format key "=" (@representation value))))) + + (do-template [ ] + [(def: #export + (-> (List Expression) Expression) + (composite-literal (format "(") ")" expression))] + + [vector "c"] + [list "list"] + ) + + (def: #export (slice from to list) + (-> Expression Expression Expression Expression) + (@abstraction + (self-contained + (format (@representation list) + "[" (@representation from) ":" (@representation to) "]")))) + + (def: #export (slice-from from list) + (-> Expression Expression Expression) + (@abstraction + (self-contained + (format (@representation list) + "[-1" ":-" (@representation from) "]")))) + + (def: #export (apply args func) + (-> (List Expression) Expression Expression) + (@abstraction + (self-contained + (format (@representation func) "(" (text.join-with "," (list/map expression args)) ")")))) + + (def: #export (apply-kw args kw-args func) + (-> (List Expression) (List [Text Expression]) Expression Expression) + (@abstraction + (self-contained + (format (@representation func) + (format "(" + (text.join-with "," (list/map expression args)) + (text.join-with "," (list/map (.function (_ [key val]) + (format key "=" (expression val))) + kw-args)) + ")"))))) + + (def: #export (nth idx list) + (-> Expression Expression Expression) + (@abstraction + (self-contained + (format (@representation list) "[[" (@representation idx) "]]")))) + + (def: #export (if test then else) + (-> Expression Expression Expression Expression) + (@abstraction + (self-contained + (format "if(" (@representation test) ")" + " " (@representation then) + " else " (@representation else))))) + + (def: #export (cond clauses else) + (-> (List [Expression Expression]) Expression Expression) + (list/fold (.function (_ [test then] next) + (if test then next)) + else + (list.reverse clauses))) + + (do-template [ ] + [(def: #export ( param subject) + (-> Expression Expression Expression) + (@abstraction + (self-contained + (format (@representation subject) + " " " " + (@representation param)))))] + + [= "=="] + [< "<"] + [<= "<="] + [> ">"] + [>= ">="] + [+ "+"] + [- "-"] + [* "*"] + [/ "/"] + [%% "%%"] + [** "**"] + [or "||"] + [and "&&"] + ) + + (def: #export @@ + (All [k] (-> (Var k) Expression)) + (|>> ..name self-contained @abstraction)) + + (def: #export global + (-> Text Expression) + (|>> var @@)) + + (do-template [ ] + [(def: #export ( param subject) + (-> Expression Expression Expression) + (..apply (.list subject param) (..global )))] + + [bit-or "bitwOr"] + [bit-and "bitwAnd"] + [bit-xor "bitwXor"] + [bit-shl "bitwShiftL"] + [bit-ushr "bitwShiftR"] + ) + + (def: #export (bit-not subject) + (-> Expression Expression) + (..apply (.list subject) (..global "bitwNot"))) + + (do-template [ ] + [(def: #export + (-> Expression Expression) + (|>> @representation (format ) self-contained @abstraction))] + + [not "!"] + [negate "-"] + ) + + (def: #export (length list) + (-> Expression Expression) + (..apply (.list list) (..global "length"))) + + (def: #export (range from to) + (-> Expression Expression Expression) + (@abstraction + (self-contained + (format (@representation from) ":" (@representation to))))) + ) + +(abstract: #export Statement + {} + + Text + + (def: #export statement (-> Statement Text) (|>> @representation)) + + (def: nest + (-> Statement Text) + (|>> @representation + (format "\n") + (text.replace-all "\n" "\n "))) + + (def: #export (set-nth! idx value list) + (-> Expression Expression SVar Statement) + (@abstraction (format (..name list) "[" (expression idx) "] <- " (expression value)))) + + (def: #export (set! var value) + (-> (Var Single) Expression Statement) + (@abstraction + (format (..name var) " <- " (expression value)))) + + (def: #export (if! test then! else!) + (-> Expression Statement Statement Statement) + (@abstraction + (format "if(" (expression test) ") {" + (nest then!) + "\n" "} else {" + (nest else!) + "\n" "}"))) + + (def: #export (when! test then!) + (-> Expression Statement Statement) + (@abstraction + (format "if(" (expression test) ") {" + (nest then!) + "\n" "}"))) + + (def: #export (cond! clauses else!) + (-> (List [Expression Statement]) Statement Statement) + (list/fold (.function (_ [test then!] next!) + (if! test then! next!)) + else! + (list.reverse clauses))) + + (def: #export (then! pre! post!) + (-> Statement Statement Statement) + (@abstraction + (format (@representation pre!) + "\n" + (@representation post!)))) + + (def: #export (while! test body!) + (-> Expression Statement Statement) + (@abstraction + (format "while (" (expression test) ") {" + (nest body!) + "\n" "}"))) + + (def: #export (do! expression) + (-> Expression Statement) + (@abstraction (..expression expression))) + + (def: #export no-op! + Statement + (@abstraction "\n")) + + (do-template [ ] + [(def: #export ( message) + (-> Expression Statement) + (@abstraction + (format "(" (expression message) ")")))] + + [stop! "stop"] + [print! "print"] + ) + + (def: #export (block statement) + (-> Statement Expression) + (..code (format "{" + (nest statement) + "\n" "}"))) + + (def: #export (for-in! var inputs body!) + (-> SVar Expression Statement Statement) + (@abstraction + (format "for (" (..name var) " in " (..expression inputs) ")" + (..expression (..block body!))))) + ) + +(def: #export (function inputs body!) + (-> (List (Ex [k] (Var k))) Statement Expression) + (let [args (|> inputs (list/map ..name) (text.join-with ", "))] + (..code (format "function(" args ")" (..expression (..block body!)))))) + +(def: #export (try body! warning error finally!) + (-> Statement (Maybe Expression) (Maybe Expression) (Maybe Statement) Expression) + (..code (format "(tryCatch(" + (..expression (..block body!)) + (case warning + (#.Some warning) + (format ", warning = " (..expression warning)) + + #.None + "") + (case error + (#.Some error) + (format ", error = " (..expression error)) + + #.None + "") + (case finally! + (#.Some finally!) + (format ", finally = " (..expression (..block finally!))) + + #.None + "") + "))"))) diff --git a/new-luxc/source/luxc/lang/translation/lua/runtime.jvm.lux b/new-luxc/source/luxc/lang/translation/lua/runtime.jvm.lux index 137e5d4ab..12a0fe6a5 100644 --- a/new-luxc/source/luxc/lang/translation/lua/runtime.jvm.lux +++ b/new-luxc/source/luxc/lang/translation/lua/runtime.jvm.lux @@ -424,13 +424,13 @@ (lua.block! (list (lua.local! "process" (#.Some (lua.nth "idx" "queue"))) (lua.when! (lua.apply "coroutine.resume" (list "process")) (lua.apply "table.insert" (list "survivors" "process")))))) - (lua.set! "queue" "survivors")))] + (lua.set! "queue" "survivors"))) + loop-body! (lua.block! (list migrate-incoming! + consume-queue!))] (lua.block! (list (lua.local! "queue" (#.Some (lua.array (list)))) - migrate-incoming! - consume-queue! - (lua.when! (lua.> (lua.int 0) - (lua.length "queue")) - (process//loop unit)))))) + loop-body! + (lua.while! (|> (lua.length "queue") (lua.> (lua.int 0))) + loop-body!))))) (runtime: (process//future procedure) (lua.block! (list (lua.apply "table.insert" (list process//incoming diff --git a/new-luxc/source/luxc/lang/translation/r.lux b/new-luxc/source/luxc/lang/translation/r.lux new file mode 100644 index 000000000..aba64bc87 --- /dev/null +++ b/new-luxc/source/luxc/lang/translation/r.lux @@ -0,0 +1,223 @@ +(.module: + lux + (lux (control ["ex" exception #+ exception:] + pipe + [monad #+ do]) + (data [bit] + [maybe] + ["e" error #+ Error] + [text "text/" Eq] + text/format + (coll [array])) + [macro] + [io #+ IO Process io] + [host #+ class: interface: object] + (world [file #+ File])) + (luxc [lang] + (lang [".L" variable #+ Register] + (host [r #+ Expression Statement])) + [".C" io])) + +(do-template [] + [(exception: #export ( {message Text}) + message)] + + [No-Active-Module-Buffer] + [Cannot-Execute] + + [No-Anchor] + ) + +(host.import java/lang/Object) + +(host.import java/lang/String + (getBytes [String] #try (Array byte))) + +(host.import java/lang/CharSequence) + +(host.import java/lang/Appendable + (append [CharSequence] Appendable)) + +(host.import java/lang/StringBuilder + (new []) + (toString [] String)) + +(host.import javax/script/ScriptEngine + (eval [String] #try #? Object)) + +(host.import javax/script/ScriptEngineFactory + (getScriptEngine [] ScriptEngine)) + +(host.import org/renjin/script/RenjinScriptEngineFactory + (new [])) + +(type: #export Anchor [Text Register]) + +(type: #export Host + {#context [Text Nat] + #anchor (Maybe Anchor) + #loader (-> Statement (Error Unit)) + #interpreter (-> Expression (Error Object)) + #module-buffer (Maybe StringBuilder) + #program-buffer StringBuilder}) + +(def: #export init + (IO Host) + (io (let [interpreter (|> (RenjinScriptEngineFactory::new []) + (ScriptEngineFactory::getScriptEngine []))] + {#context ["" +0] + #anchor #.None + #loader (function (_ code) + (do e.Monad + [_ (ScriptEngine::eval [(r.statement code)] interpreter)] + (wrap []))) + #interpreter (function (_ code) + (do e.Monad + [output (ScriptEngine::eval [(r.expression code)] interpreter)] + (wrap (maybe.default (:! Object []) + output)))) + #module-buffer #.None + #program-buffer (StringBuilder::new [])}))) + +(def: #export r-module-name Text "module.r") + +(def: #export init-module-buffer + (Meta Unit) + (function (_ compiler) + (#e.Success [(update@ #.host + (|>> (:! Host) + (set@ #module-buffer (#.Some (StringBuilder::new []))) + (:! Void)) + compiler) + []]))) + +(def: #export (with-sub-context expr) + (All [a] (-> (Meta a) (Meta [Text a]))) + (function (_ compiler) + (let [old (:! Host (get@ #.host compiler)) + [old-name old-sub] (get@ #context old) + new-name (format old-name "f___" (%i (nat-to-int old-sub)))] + (case (expr (set@ #.host + (:! Void (set@ #context [new-name +0] old)) + compiler)) + (#e.Success [compiler' output]) + (#e.Success [(update@ #.host + (|>> (:! Host) + (set@ #context [old-name (n/inc old-sub)]) + (:! Void)) + compiler') + [new-name output]]) + + (#e.Error error) + (#e.Error error))))) + +(def: #export context + (Meta Text) + (function (_ compiler) + (#e.Success [compiler + (|> (get@ #.host compiler) + (:! Host) + (get@ #context) + (let> [name sub] + name))]))) + +(def: #export (with-anchor anchor expr) + (All [a] (-> Anchor (Meta a) (Meta a))) + (function (_ compiler) + (let [old (:! Host (get@ #.host compiler))] + (case (expr (set@ #.host + (:! Void (set@ #anchor (#.Some anchor) old)) + compiler)) + (#e.Success [compiler' output]) + (#e.Success [(update@ #.host + (|>> (:! Host) + (set@ #anchor (get@ #anchor old)) + (:! Void)) + compiler') + output]) + + (#e.Error error) + (#e.Error error))))) + +(def: #export anchor + (Meta Anchor) + (function (_ compiler) + (case (|> compiler (get@ #.host) (:! Host) (get@ #anchor)) + (#.Some anchor) + (#e.Success [compiler anchor]) + + #.None + ((lang.throw No-Anchor "") compiler)))) + +(def: #export module-buffer + (Meta StringBuilder) + (function (_ compiler) + (case (|> compiler (get@ #.host) (:! Host) (get@ #module-buffer)) + #.None + ((lang.throw No-Active-Module-Buffer "") compiler) + + (#.Some module-buffer) + (#e.Success [compiler module-buffer])))) + +(def: #export program-buffer + (Meta StringBuilder) + (function (_ compiler) + (#e.Success [compiler (|> compiler (get@ #.host) (:! Host) (get@ #program-buffer))]))) + +(do-template [ ] + [(def: ( code) + (-> (Meta )) + (function (_ compiler) + (let [runner (|> compiler (get@ #.host) (:! Host) (get@ ))] + (case (runner code) + (#e.Error error) + (exec ## (log! ( code)) + ((lang.throw Cannot-Execute error) compiler)) + + (#e.Success output) + (#e.Success [compiler output])))))] + + [load! #loader Statement Unit r.statement] + [interpret #interpreter Expression Object r.expression] + ) + +(def: #export variant-tag-field "luxVT") +(def: #export variant-flag-field "luxVF") +(def: #export variant-value-field "luxVV") + +(def: #export int-high-field "luxIH") +(def: #export int-low-field "luxIL") + +(def: #export unit Text "") + +(def: #export (definition-name [module name]) + (-> Ident Text) + (lang.normalize-name (format module "$" name))) + +(do-template [ ] + [(def: #export ( code) + (-> (Meta )) + (do macro.Monad + [module-buffer module-buffer + #let [_ (Appendable::append [(:! CharSequence ( code))] + module-buffer)]] + ( code)))] + + [save load! r.statement Statement Unit] + [run interpret r.expression Expression Object] + ) + +(def: #export (save-module! target) + (-> File (Meta (Process Unit))) + (do macro.Monad + [module macro.current-module-name + module-buffer module-buffer + program-buffer program-buffer + #let [module-code (StringBuilder::toString [] module-buffer) + _ (Appendable::append [(:! CharSequence (format module-code "\n"))] + program-buffer)]] + (wrap (ioC.write target + (format (lang.normalize-name module) "/" r-module-name) + (|> module-code + (String::getBytes ["UTF-8"]) + e.assume))))) diff --git a/new-luxc/source/luxc/lang/translation/r/case.jvm.lux b/new-luxc/source/luxc/lang/translation/r/case.jvm.lux new file mode 100644 index 000000000..2a635030c --- /dev/null +++ b/new-luxc/source/luxc/lang/translation/r/case.jvm.lux @@ -0,0 +1,188 @@ +(.module: + lux + (lux (control [monad #+ do] + ["ex" exception #+ exception:]) + (data [number] + [text] + text/format + (coll [list "list/" Functor Fold] + [set #+ Set])) + [macro #+ "meta/" Monad] + (macro [code])) + (luxc [lang] + (lang [".L" variable #+ Register Variable] + ["ls" synthesis #+ Synthesis Path] + (host [r #+ Expression Statement SVar @@]))) + [//] + (// [".T" runtime] + [".T" primitive] + [".T" reference])) + +(def: #export (translate-let translate register valueS bodyS) + (-> (-> Synthesis (Meta Expression)) Register Synthesis Synthesis + (Meta Expression)) + (do macro.Monad + [valueO (translate valueS) + bodyO (translate bodyS) + #let [$register (referenceT.variable register)]] + (wrap (r.block ($_ r.then! + (r.set! $register valueO) + (r.do! bodyO)))))) + +(def: #export (translate-record-get translate valueS pathP) + (-> (-> Synthesis (Meta Expression)) Synthesis (List [Nat Bool]) + (Meta Expression)) + (do macro.Monad + [valueO (translate valueS)] + (wrap (list/fold (function (_ [idx tail?] source) + (let [method (if tail? + runtimeT.product//right + runtimeT.product//left)] + (method source (r.int (:! Int idx))))) + valueO + pathP)))) + +(def: #export (translate-if testO thenO elseO) + (-> Expression Expression Expression Expression) + (r.if testO thenO elseO)) + +(def: $savepoint (r.var "lux_pm_cursor_savepoint")) +(def: $cursor (r.var "lux_pm_cursor")) + +(def: top r.length) +(def: next (|>> r.length (r.+ (r.int 1)))) +(def: (push! value var) + (-> Expression SVar Statement) + (r.set-nth! (next (@@ var)) value var)) +(def: (pop! var) + (-> SVar Statement) + (r.set-nth! (top (@@ var)) r.null var)) + +(def: (push-cursor! value) + (-> Expression Statement) + (push! value $cursor)) + +(def: save-cursor! + Statement + (push! (r.slice (r.float 1.0) (r.length (@@ $cursor)) (@@ $cursor)) + $savepoint)) + +(def: restore-cursor! + Statement + (r.set! $cursor (r.nth (top (@@ $savepoint)) (@@ $savepoint)))) + +(def: cursor-top + Expression + (top (@@ $cursor))) + +(def: pop-cursor! + Statement + (pop! $cursor)) + +(def: pm-error (r.string "PM-ERROR")) + +(def: fail-pm! (r.stop! pm-error)) + +(def: $temp (r.var "lux_pm_temp")) + +(exception: #export (Unrecognized-Path {message Text}) + message) + +(def: $alt_error (r.var "alt_error")) + +(def: (pm-catch handler!) + (-> Statement Expression) + (r.function (list $alt_error) + (r.if! (|> (@@ $alt_error) (r.= pm-error)) + handler! + (r.stop! (@@ $alt_error))))) + +(def: (translate-pattern-matching' translate pathP) + (-> (-> Synthesis (Meta Expression)) Path (Meta Statement)) + (case pathP + (^code ("lux case exec" (~ bodyS))) + (do macro.Monad + [bodyO (translate bodyS)] + (wrap (r.do! bodyO))) + + (^code ("lux case pop")) + (meta/wrap pop-cursor!) + + (^code ("lux case bind" (~ [_ (#.Nat register)]))) + (meta/wrap (r.set! (referenceT.variable register) cursor-top)) + + (^template [ ] + [_ ( value)] + (meta/wrap (r.when! (r.not (r.= (|> value ) cursor-top)) + fail-pm!))) + ([#.Nat (<| runtimeT.int (:! Int))] + [#.Int runtimeT.int] + [#.Deg (<| runtimeT.int (:! Int))] + [#.Bool r.bool] + [#.Frac r.float] + [#.Text r.string]) + + (^template [ ] + (^code ( (~ [_ (#.Nat idx)]))) + (meta/wrap (push-cursor! ( cursor-top (r.int (:! Int idx)))))) + (["lux case tuple left" runtimeT.product//left] + ["lux case tuple right" runtimeT.product//right]) + + (^template [ ] + (^code ( (~ [_ (#.Nat idx)]))) + (meta/wrap ($_ r.then! + (r.set! $temp (runtimeT.sum//get cursor-top (r.int (:! Int idx)) )) + (r.if! (r.not (r.= r.null (@@ $temp))) + (push-cursor! (@@ $temp)) + fail-pm!)))) + (["lux case variant left" r.null] + ["lux case variant right" (r.string "")]) + + (^code ("lux case seq" (~ leftP) (~ rightP))) + (do macro.Monad + [leftO (translate-pattern-matching' translate leftP) + rightO (translate-pattern-matching' translate rightP)] + (wrap ($_ r.then! + leftO + rightO))) + + (^code ("lux case alt" (~ leftP) (~ rightP))) + (do macro.Monad + [leftO (translate-pattern-matching' translate leftP) + rightO (translate-pattern-matching' translate rightP)] + (wrap (r.do! (r.try ($_ r.then! + save-cursor! + leftO) + #.None + (#.Some (pm-catch ($_ r.then! + restore-cursor! + rightO))) + #.None)))) + + _ + (lang.throw Unrecognized-Path (%code pathP)) + )) + +(def: (translate-pattern-matching translate pathP) + (-> (-> Synthesis (Meta Expression)) Path (Meta Statement)) + (do macro.Monad + [pattern-matching! (translate-pattern-matching' translate pathP)] + (wrap (r.do! (r.try pattern-matching! + #.None + (#.Some (pm-catch (r.stop! (r.string "Invalid expression for pattern-matching.")))) + #.None))))) + +(def: (initialize-pattern-matching! stack-init) + (-> Expression Statement) + ($_ r.then! + (r.set! $cursor (r.list (list stack-init))) + (r.set! $savepoint (r.list (list))))) + +(def: #export (translate-case translate valueS pathP) + (-> (-> Synthesis (Meta Expression)) Synthesis Path (Meta Expression)) + (do macro.Monad + [valueO (translate valueS) + pattern-matching! (translate-pattern-matching translate pathP)] + (wrap (r.block ($_ r.then! + (initialize-pattern-matching! valueO) + pattern-matching!))))) diff --git a/new-luxc/source/luxc/lang/translation/r/eval.jvm.lux b/new-luxc/source/luxc/lang/translation/r/eval.jvm.lux new file mode 100644 index 000000000..27d05fdaa --- /dev/null +++ b/new-luxc/source/luxc/lang/translation/r/eval.jvm.lux @@ -0,0 +1,162 @@ +(.module: + lux + (lux (control ["ex" exception #+ exception:] + [monad #+ do]) + (data [bit] + [maybe] + ["e" error #+ Error] + text/format + (coll [array])) + [host]) + (luxc [lang] + (lang (host [r #+ Expression Statement]))) + [//]) + +(do-template [] + [(exception: #export ( {message Text}) + message)] + + [Unknown-Kind-Of-Host-Object] + [Null-Has-No-Lux-Representation] + [Cannot-Evaluate] + ) + +(host.import java/lang/Object + (toString [] String) + (getClass [] (Class Object))) + +(host.import java/lang/Long + (intValue [] Integer)) + +(host.import org/renjin/sexp/SEXP) + +(host.import org/renjin/sexp/StringArrayVector + (getElementAsString [int] String)) + +(host.import org/renjin/sexp/LogicalArrayVector + (getElementAsRawLogical [int] int)) + +(host.import org/renjin/sexp/IntArrayVector + (getElementAsInt [int] int)) + +(host.import org/renjin/sexp/DoubleArrayVector + (getElementAsDouble [int] double)) + +(host.import org/renjin/sexp/ListVector + (length [] int) + (getElementAsSEXP [int] #try SEXP) + (getElementAsSEXP #as get-field-sexp [String] #try SEXP)) + +(host.import org/renjin/sexp/Null) + +(def: (parse-tuple lux-object host-object) + (-> (-> Object (Error Top)) ListVector (Error Top)) + (let [size (:! Nat (ListVector::length [] host-object))] + (loop [idx +0 + output (:! (Array Top) (array.new size))] + (if (n/< size idx) + (case (ListVector::getElementAsSEXP [(:! Int idx)] host-object) + (#e.Error error) + (#e.Error error) + + (#e.Success value) + (case (lux-object (:! Object value)) + (#e.Error error) + (#e.Error error) + + (#e.Success lux-value) + (recur (n/inc idx) (array.write idx (:! Top lux-value) output)))) + (#e.Success output))))) + +(def: (parse-variant lux-object host-object) + (-> (-> Object (Error Top)) ListVector (Error Top)) + (do e.Monad + [tag (ListVector::get-field-sexp [//.variant-tag-field] host-object) + flag (ListVector::get-field-sexp [//.variant-flag-field] host-object) + value (ListVector::get-field-sexp [//.variant-value-field] host-object) + value (lux-object (:! Object value))] + (wrap [(|> tag + (:! IntArrayVector) + (IntArrayVector::getElementAsInt [0]) + (Long::intValue [])) + (: Top + (if (host.instance? Null flag) + host.null + //.unit)) + value]))) + +(def: (parse-int host-object) + (-> ListVector (Error Int)) + (do e.Monad + [high (ListVector::get-field-sexp [//.int-high-field] host-object) + low (ListVector::get-field-sexp [//.int-low-field] host-object) + #let [high (:! Nat (IntArrayVector::getElementAsInt [0] (:! IntArrayVector high))) + low (:! Nat (IntArrayVector::getElementAsInt [0] (:! IntArrayVector low)))]] + (wrap (|> high (bit.shift-left +32) (n/+ low) nat-to-int)))) + +(def: (lux-object host-object) + (-> Object (Error Top)) + (cond (host.instance? StringArrayVector host-object) + (#e.Success (StringArrayVector::getElementAsString [0] (:! StringArrayVector host-object))) + + (host.instance? LogicalArrayVector host-object) + (#e.Success (i/= 1 (LogicalArrayVector::getElementAsRawLogical [0] (:! LogicalArrayVector host-object)))) + + (host.instance? IntArrayVector host-object) + (#e.Success (IntArrayVector::getElementAsInt [0] (:! IntArrayVector host-object))) + + (host.instance? DoubleArrayVector host-object) + (#e.Success (DoubleArrayVector::getElementAsDouble [0] (:! DoubleArrayVector host-object))) + + (host.instance? ListVector host-object) + (case (parse-int (:! ListVector host-object)) + (#e.Error error) + (case (parse-variant lux-object (:! ListVector host-object)) + (#e.Error error) + (parse-tuple lux-object (:! ListVector host-object)) + + output + output) + + output + output) + + ## else + (let [object-class (:! Text (Object::toString [] (Object::getClass [] (:! Object host-object)))) + text-representation (:! Text (Object::toString [] (:! Object host-object)))] + (ex.throw Unknown-Kind-Of-Host-Object (format object-class " --- " text-representation)))) + ## (case (python-type host-object) + ## "tuple" + ## (tuple lux-object host-object) + + ## "dict" + ## (variant lux-object host-object) + + ## "NoneType" + ## (#e.Success []) + + ## type + ## (ex.throw Unknown-Kind-Of-Host-Object (format type " " (Object::toString [] host-object)))) + ) + +(def: #export (eval code) + (-> Expression (Meta Top)) + (function (_ compiler) + (let [interpreter (|> compiler (get@ #.host) (:! //.Host) (get@ #//.interpreter))] + (case (interpreter code) + (#e.Error error) + (exec (log! (format "eval #e.Error\n" + "<< " (r.expression code) "\n" + error)) + ((lang.throw Cannot-Evaluate error) compiler)) + + (#e.Success output) + (case (lux-object output) + (#e.Success parsed-output) + (#e.Success [compiler parsed-output]) + + (#e.Error error) + (exec (log! (format "eval #e.Error\n" + "<< " (r.expression code) "\n" + error)) + ((lang.throw Cannot-Evaluate error) compiler))))))) diff --git a/new-luxc/source/luxc/lang/translation/r/expression.jvm.lux b/new-luxc/source/luxc/lang/translation/r/expression.jvm.lux new file mode 100644 index 000000000..67ea089a2 --- /dev/null +++ b/new-luxc/source/luxc/lang/translation/r/expression.jvm.lux @@ -0,0 +1,88 @@ +(.module: + lux + (lux (control [monad #+ do] + ["ex" exception #+ exception:] + ["p" parser]) + (data ["e" error] + text/format) + [macro] + (macro ["s" syntax])) + (luxc ["&" lang] + (lang [".L" variable #+ Variable Register] + [".L" extension] + ["ls" synthesis] + (host [r #+ Expression Statement]))) + [//] + (// [".T" runtime] + [".T" primitive] + [".T" structure] + [".T" reference] + [".T" function] + [".T" case] + [".T" procedure]) + ) + +(do-template [] + [(exception: #export ( {message Text}) + message)] + + [Invalid-Function-Syntax] + [Unrecognized-Synthesis] + ) + +(def: #export (translate synthesis) + (-> ls.Synthesis (Meta Expression)) + (case synthesis + (^code []) + (:: macro.Monad wrap runtimeT.unit) + + (^template [ ] + [_ ( value)] + ( value)) + ([#.Bool primitiveT.translate-bool] + [#.Nat primitiveT.translate-nat] + [#.Int primitiveT.translate-int] + [#.Deg primitiveT.translate-deg] + [#.Frac primitiveT.translate-frac] + [#.Text primitiveT.translate-text]) + + (^code ((~ [_ (#.Nat tag)]) (~ [_ (#.Bool last?)]) (~ valueS))) + (structureT.translate-variant translate tag last? valueS) + + (^code [(~ singleton)]) + (translate singleton) + + (^code [(~+ members)]) + (structureT.translate-tuple translate members) + + (^ [_ (#.Form (list [_ (#.Int var)]))]) + (referenceT.translate-variable var) + + [_ (#.Symbol definition)] + (referenceT.translate-definition definition) + + (^code ("lux let" (~ [_ (#.Nat register)]) (~ inputS) (~ exprS))) + (caseT.translate-let translate register inputS exprS) + + (^code ("lux case" (~ inputS) (~ pathPS))) + (caseT.translate-case translate inputS pathPS) + + (^code ("lux function" (~ [_ (#.Nat arity)]) [(~+ environment)] (~ bodyS))) + (case (s.run environment (p.some s.int)) + (#e.Success environment) + (functionT.translate-function translate environment arity bodyS) + + _ + (&.throw Invalid-Function-Syntax (%code synthesis))) + + (^code ("lux call" (~ functionS) (~+ argsS))) + (functionT.translate-apply translate functionS argsS) + + (^code ((~ [_ (#.Text procedure)]) (~+ argsS))) + (procedureT.translate-procedure translate procedure argsS) + ## (do macro.Monad + ## [translation (extensionL.find-translation procedure)] + ## (translation argsS)) + + _ + (&.throw Unrecognized-Synthesis (%code synthesis)))) diff --git a/new-luxc/source/luxc/lang/translation/r/function.jvm.lux b/new-luxc/source/luxc/lang/translation/r/function.jvm.lux new file mode 100644 index 000000000..c42327839 --- /dev/null +++ b/new-luxc/source/luxc/lang/translation/r/function.jvm.lux @@ -0,0 +1,101 @@ +(.module: + lux + (lux (control [monad #+ do] + pipe) + (data [product] + [text] + text/format + (coll [list "list/" Functor Fold])) + [macro]) + (luxc ["&" lang] + (lang ["ls" synthesis] + [".L" variable #+ Variable] + (host [r #+ Expression Statement @@]))) + [//] + (// [".T" reference])) + +(def: #export (translate-apply translate functionS argsS+) + (-> (-> ls.Synthesis (Meta Expression)) ls.Synthesis (List ls.Synthesis) (Meta Expression)) + (do macro.Monad + [functionO (translate functionS) + argsO+ (monad.map @ translate argsS+)] + (wrap (r.apply argsO+ functionO)))) + +(def: $curried (r.var "curried")) + +(def: (input-declaration register) + (r.set! (referenceT.variable (n/inc register)) + (|> (@@ $curried) (r.nth (|> register n/inc nat-to-int r.int))))) + +(def: (with-closure function-name inits function-definition) + (-> Text (List Expression) Statement (Meta Expression)) + (let [$closure (r.var (format function-name "___CLOSURE"))] + (case inits + #.Nil + (do macro.Monad + [_ (//.save function-definition)] + (wrap (r.global function-name))) + + _ + (do macro.Monad + [_ (//.save (r.set! $closure + (r.function (|> (list.enumerate inits) + (list/map (|>> product.left referenceT.closure))) + ($_ r.then! + function-definition + (r.do! (r.global function-name))))))] + (wrap (r.apply inits (@@ $closure))))))) + +(def: #export (translate-function translate env arity bodyS) + (-> (-> ls.Synthesis (Meta Expression)) + (List Variable) ls.Arity ls.Synthesis + (Meta Expression)) + (do macro.Monad + [[function-name bodyO] (//.with-sub-context + (do @ + [function-name //.context] + (//.with-anchor [function-name +1] + (translate bodyS)))) + closureO+ (monad.map @ referenceT.translate-variable env) + #let [args-inits! (|> (list.n/range +0 (n/dec arity)) + (list/map input-declaration) + (case> #.Nil + r.no-op! + + (#.Cons head tail) + (list/fold r.then! head tail))) + arityO (|> arity nat-to-int r.int) + $num_args (r.var "num_args") + $function (r.var function-name) + apply-poly (function (_ args func) + (r.apply (list func args) (r.global "do.call")))]] + (with-closure function-name closureO+ + (r.set! $function + (r.function (list r.var-args) + ($_ r.then! + ## (r.set! $curried (r.apply (list (@@ r.var-args)) (r.global "list"))) + (r.set! $curried (@@ r.var-args)) + (r.set! $num_args (r.length (@@ $curried))) + (r.do! + (r.cond (list [(|> (@@ $num_args) (r.= arityO)) + (r.block + ($_ r.then! + (r.set! (referenceT.variable +0) (@@ $function)) + args-inits! + (r.do! bodyO)))] + [(|> (@@ $num_args) (r.> arityO)) + (let [arity-args (r.slice (r.int 1) arityO (@@ $curried)) + output-func-args (r.slice arityO (@@ $num_args) (@@ $curried))] + (|> (@@ $function) + (apply-poly arity-args) + (apply-poly output-func-args)))]) + ## (|> (@@ $num_args) (r.< arityO)) + (let [$missing (r.var "missing")] + (r.function (list r.var-args) + ($_ r.then! + ## (r.set! $missing (r.apply (list (@@ r.var-args)) (r.global "list"))) + (r.set! $missing (@@ r.var-args)) + (r.do! (|> (@@ $function) + (apply-poly (r.apply (list (@@ $curried) (@@ $missing)) + (r.global "append")))))))))))))) + )) diff --git a/new-luxc/source/luxc/lang/translation/r/loop.jvm.lux b/new-luxc/source/luxc/lang/translation/r/loop.jvm.lux new file mode 100644 index 000000000..d0caebd80 --- /dev/null +++ b/new-luxc/source/luxc/lang/translation/r/loop.jvm.lux @@ -0,0 +1,37 @@ +(.module: + lux + (lux (control [monad #+ do]) + (data [text] + text/format + (coll [list "list/" Functor])) + [macro]) + (luxc [lang] + (lang ["ls" synthesis] + (host [r #+ Expression Statement @@]))) + [//] + (// [".T" reference])) + +(def: #export (translate-loop translate offset initsS+ bodyS) + (-> (-> ls.Synthesis (Meta Expression)) Nat (List ls.Synthesis) ls.Synthesis + (Meta Expression)) + (do macro.Monad + [loop-name (|> (macro.gensym "loop") + (:: @ map (|>> %code lang.normalize-name))) + initsO+ (monad.map @ translate initsS+) + bodyO (//.with-anchor [loop-name offset] + (translate bodyS)) + #let [$loop-name (r.var loop-name) + @loop-name (@@ $loop-name)] + _ (//.save (r.set! $loop-name + (r.function (|> (list.n/range +0 (n/dec (list.size initsS+))) + (list/map (|>> (n/+ offset) referenceT.variable))) + (r.do! bodyO))))] + (wrap (r.apply initsO+ @loop-name)))) + +(def: #export (translate-recur translate argsS+) + (-> (-> ls.Synthesis (Meta Expression)) (List ls.Synthesis) + (Meta Expression)) + (do macro.Monad + [[loop-name offset] //.anchor + argsO+ (monad.map @ translate argsS+)] + (wrap (r.apply argsO+ (r.global loop-name))))) diff --git a/new-luxc/source/luxc/lang/translation/r/primitive.jvm.lux b/new-luxc/source/luxc/lang/translation/r/primitive.jvm.lux new file mode 100644 index 000000000..2afe41421 --- /dev/null +++ b/new-luxc/source/luxc/lang/translation/r/primitive.jvm.lux @@ -0,0 +1,30 @@ +(.module: + lux + (lux [macro "meta/" Monad]) + (luxc (lang (host [r #+ Expression Statement]))) + [//] + (// [".T" runtime])) + +(def: #export translate-bool + (-> Bool (Meta Expression)) + (|>> r.bool meta/wrap)) + +(def: #export translate-int + (-> Int (Meta Expression)) + (|>> runtimeT.int meta/wrap)) + +(def: #export translate-nat + (-> Nat (Meta Expression)) + (|>> (:! Int) runtimeT.int meta/wrap)) + +(def: #export translate-deg + (-> Deg (Meta Expression)) + (|>> (:! Int) runtimeT.int meta/wrap)) + +(def: #export translate-frac + (-> Frac (Meta Expression)) + (|>> r.float meta/wrap)) + +(def: #export translate-text + (-> Text (Meta Expression)) + (|>> r.string meta/wrap)) diff --git a/new-luxc/source/luxc/lang/translation/r/procedure.jvm.lux b/new-luxc/source/luxc/lang/translation/r/procedure.jvm.lux new file mode 100644 index 000000000..699c0c000 --- /dev/null +++ b/new-luxc/source/luxc/lang/translation/r/procedure.jvm.lux @@ -0,0 +1,29 @@ +(.module: + lux + (lux (control [monad #+ do] + ["ex" exception #+ exception:]) + (data [maybe] + text/format + (coll [dict]))) + (luxc ["&" lang] + (lang ["ls" synthesis] + (host [python #+ Expression Statement]))) + [//] + (/ ["/." common] + ["/." host])) + +(exception: #export (Unknown-Procedure {message Text}) + message) + +(def: procedures + /common.Bundle + (|> /common.procedures + (dict.merge /host.procedures))) + +(def: #export (translate-procedure translate name args) + (-> (-> ls.Synthesis (Meta Expression)) Text (List ls.Synthesis) + (Meta Expression)) + (<| (maybe.default (&.throw Unknown-Procedure (%t name))) + (do maybe.Monad + [proc (dict.get name procedures)] + (wrap (proc translate args))))) diff --git a/new-luxc/source/luxc/lang/translation/r/procedure/common.jvm.lux b/new-luxc/source/luxc/lang/translation/r/procedure/common.jvm.lux new file mode 100644 index 000000000..849093126 --- /dev/null +++ b/new-luxc/source/luxc/lang/translation/r/procedure/common.jvm.lux @@ -0,0 +1,554 @@ +(.module: + lux + (lux (control [monad #+ do] + ["ex" exception #+ exception:] + ["p" parser]) + (data ["e" error] + [text] + text/format + [number] + (coll [list "list/" Functor] + [dict #+ Dict])) + [macro #+ with-gensyms] + (macro [code] + ["s" syntax #+ syntax:]) + [host]) + (luxc ["&" lang] + (lang ["la" analysis] + ["ls" synthesis] + (host [r #+ Expression Statement]))) + [///] + (/// [".T" runtime] + [".T" case] + [".T" function] + [".T" loop])) + +## [Types] +(type: #export Translator + (-> ls.Synthesis (Meta Expression))) + +(type: #export Proc + (-> Translator (List ls.Synthesis) (Meta Expression))) + +(type: #export Bundle + (Dict Text Proc)) + +(syntax: (Vector [size s.nat] elemT) + (wrap (list (` [(~+ (list.repeat size elemT))])))) + +(type: #export Nullary (-> (Vector +0 Expression) Expression)) +(type: #export Unary (-> (Vector +1 Expression) Expression)) +(type: #export Binary (-> (Vector +2 Expression) Expression)) +(type: #export Trinary (-> (Vector +3 Expression) Expression)) +(type: #export Variadic (-> (List Expression) Expression)) + +## [Utils] +(def: #export (install name unnamed) + (-> Text (-> Text Proc) + (-> Bundle Bundle)) + (dict.put name (unnamed name))) + +(def: #export (prefix prefix bundle) + (-> Text Bundle Bundle) + (|> bundle + dict.entries + (list/map (function (_ [key val]) [(format prefix " " key) val])) + (dict.from-list text.Hash))) + +(def: (wrong-arity proc expected actual) + (-> Text Nat Nat Text) + (format "Wrong number of arguments for " (%t proc) "\n" + "Expected: " (|> expected nat-to-int %i) "\n" + " Actual: " (|> actual nat-to-int %i))) + +(syntax: (arity: [name s.local-symbol] [arity s.nat]) + (with-gensyms [g!_ g!proc g!name g!translate g!inputs] + (do @ + [g!input+ (monad.seq @ (list.repeat arity (macro.gensym "input")))] + (wrap (list (` (def: #export ((~ (code.local-symbol name)) (~ g!proc)) + (-> (-> (..Vector (~ (code.nat arity)) Expression) Expression) + (-> Text ..Proc)) + (function ((~ g!_) (~ g!name)) + (function ((~ g!_) (~ g!translate) (~ g!inputs)) + (case (~ g!inputs) + (^ (list (~+ g!input+))) + (do macro.Monad + [(~+ (|> g!input+ + (list/map (function (_ g!input) + (list g!input (` ((~ g!translate) (~ g!input)))))) + list.concat))] + ((~' wrap) ((~ g!proc) [(~+ g!input+)]))) + + (~' _) + (macro.fail (wrong-arity (~ g!name) +1 (list.size (~ g!inputs)))))))))))))) + +(arity: nullary +0) +(arity: unary +1) +(arity: binary +2) +(arity: trinary +3) + +(def: #export (variadic proc) + (-> Variadic (-> Text Proc)) + (function (_ proc-name) + (function (_ translate inputsS) + (do macro.Monad + [inputsI (monad.map @ translate inputsS)] + (wrap (proc inputsI)))))) + +## [Procedures] +## [[Lux]] +(def: (lux//is [leftO rightO]) + Binary + (r.apply (list leftO rightO) + (r.global "identical"))) + +(def: (lux//if [testO thenO elseO]) + Trinary + (caseT.translate-if testO thenO elseO)) + +(def: (lux//try riskyO) + Unary + (runtimeT.lux//try riskyO)) + +(def: (lux//noop valueO) + Unary + valueO) + +(exception: #export (Wrong-Syntax {message Text}) + message) + +(def: #export (wrong-syntax procedure args) + (-> Text (List ls.Synthesis) Text) + (format "Procedure: " procedure "\n" + "Arguments: " (%code (code.tuple args)))) + +(def: lux//loop + (-> Text Proc) + (function (_ proc-name) + (function (_ translate inputsS) + (case (s.run inputsS ($_ p.seq s.nat (s.tuple (p.many s.any)) s.any)) + (#e.Success [offset initsS+ bodyS]) + (loopT.translate-loop translate offset initsS+ bodyS) + + (#e.Error error) + (&.throw Wrong-Syntax (wrong-syntax proc-name inputsS))) + ))) + +(def: lux//recur + (-> Text Proc) + (function (_ proc-name) + (function (_ translate inputsS) + (loopT.translate-recur translate inputsS)))) + +(def: lux-procs + Bundle + (|> (dict.new text.Hash) + (install "noop" (unary lux//noop)) + (install "is" (binary lux//is)) + (install "try" (unary lux//try)) + (install "if" (trinary lux//if)) + (install "loop" lux//loop) + (install "recur" lux//recur) + )) + +## [[Bits]] +(do-template [ ] + [(def: ( [subjectO paramO]) + Binary + ( paramO subjectO))] + + [bit//and runtimeT.bit//and] + [bit//or runtimeT.bit//or] + [bit//xor runtimeT.bit//xor] + ) + +(do-template [ ] + [(def: ( [subjectO paramO]) + Binary + ( paramO subjectO))] + + [bit//shift-left runtimeT.bit//shift-left] + [bit//signed-shift-right runtimeT.bit//signed-shift-right] + [bit//shift-right runtimeT.bit//shift-right] + ) + +(def: bit-procs + Bundle + (<| (prefix "bit") + (|> (dict.new text.Hash) + (install "count" (unary runtimeT.bit//count)) + (install "and" (binary bit//and)) + (install "or" (binary bit//or)) + (install "xor" (binary bit//xor)) + (install "shift-left" (binary bit//shift-left)) + (install "unsigned-shift-right" (binary bit//shift-right)) + (install "shift-right" (binary bit//signed-shift-right)) + ))) + +## [[Arrays]] +(def: (array//get [arrayO idxO]) + Binary + (runtimeT.array//get arrayO idxO)) + +(def: (array//put [arrayO idxO elemO]) + Trinary + (runtimeT.array//put arrayO idxO elemO)) + +(def: (array//remove [arrayO idxO]) + Binary + (runtimeT.array//put arrayO idxO r.null)) + +(def: array-procs + Bundle + (<| (prefix "array") + (|> (dict.new text.Hash) + (install "new" (unary runtimeT.array//new)) + (install "get" (binary array//get)) + (install "put" (trinary array//put)) + (install "remove" (binary array//remove)) + (install "size" (unary r.length)) + ))) + +## [[Numbers]] +(host.import java/lang/Double + (#static MIN_VALUE Double) + (#static MAX_VALUE Double)) + +(do-template [ ] + [(def: ( _) + Nullary + ( ))] + + [frac//smallest Double::MIN_VALUE r.float] + [frac//min (f/* -1.0 Double::MAX_VALUE) r.float] + [frac//max Double::MAX_VALUE r.float] + ) + +(do-template [ ] + [(def: ( _) + Nullary + )] + + [nat//min runtimeT.int//zero] + [nat//max runtimeT.int//-one] + + [int//min runtimeT.int//min] + [int//max runtimeT.int//max] + + [deg//min runtimeT.int//zero] + [deg//max runtimeT.int//-one] + ) + +(do-template [ ] + [(def: ( _) + Nullary + (r.float ))] + + [frac//not-a-number number.not-a-number] + [frac//positive-infinity number.positive-infinity] + [frac//negative-infinity number.negative-infinity] + ) + +(do-template [ ] + [(def: ( [subjectO paramO]) + Binary + (|> subjectO ( paramO)))] + + [int//add runtimeT.int//+] + [int//sub runtimeT.int//-] + [int//mul runtimeT.int//*] + [int//div runtimeT.int///] + [int//rem runtimeT.int//%] + + [nat//add runtimeT.int//+] + [nat//sub runtimeT.int//-] + [nat//mul runtimeT.int//*] + [nat//div runtimeT.nat///] + [nat//rem runtimeT.nat//%] + + [deg//add runtimeT.int//+] + [deg//sub runtimeT.int//-] + [deg//rem runtimeT.int//-] + [deg//scale runtimeT.int//*] + [deg//mul runtimeT.deg//*] + [deg//div runtimeT.deg///] + [deg//reciprocal runtimeT.int///] + ) + +(do-template [ ] + [(def: ( [subjectO paramO]) + Binary + ( paramO subjectO))] + + [frac//add r.+] + [frac//sub r.-] + [frac//mul r.*] + [frac//div r./] + [frac//rem r.%%] + [frac//= r.=] + [frac//< r.<] + + [text//= r.=] + [text//< r.<] + ) + +(do-template [ ] + [(def: ( [subjectO paramO]) + Binary + ( paramO subjectO))] + + [nat//= runtimeT.int//=] + [nat//< runtimeT.nat//<] + + [int//= runtimeT.int//=] + [int//< runtimeT.int//<] + + [deg//= runtimeT.int//=] + [deg//< runtimeT.nat//<] + ) + +(def: (apply1 func) + (-> Expression (-> Expression Expression)) + (function (_ value) + (r.apply (list value) func))) + +(def: nat-procs + Bundle + (<| (prefix "nat") + (|> (dict.new text.Hash) + (install "+" (binary nat//add)) + (install "-" (binary nat//sub)) + (install "*" (binary nat//mul)) + (install "/" (binary nat//div)) + (install "%" (binary nat//rem)) + (install "=" (binary nat//=)) + (install "<" (binary nat//<)) + (install "min" (nullary nat//min)) + (install "max" (nullary nat//max)) + (install "to-int" (unary id)) + (install "char" (unary (apply1 (r.global "intToUtf8"))))))) + +(def: int-procs + Bundle + (<| (prefix "int") + (|> (dict.new text.Hash) + (install "+" (binary int//add)) + (install "-" (binary int//sub)) + (install "*" (binary int//mul)) + (install "/" (binary int//div)) + (install "%" (binary int//rem)) + (install "=" (binary int//=)) + (install "<" (binary int//<)) + (install "min" (nullary int//min)) + (install "max" (nullary int//max)) + (install "to-nat" (unary id)) + (install "to-frac" (unary runtimeT.int//to-float))))) + +(def: deg-procs + Bundle + (<| (prefix "deg") + (|> (dict.new text.Hash) + (install "+" (binary deg//add)) + (install "-" (binary deg//sub)) + (install "*" (binary deg//mul)) + (install "/" (binary deg//div)) + (install "%" (binary deg//rem)) + (install "=" (binary deg//=)) + (install "<" (binary deg//<)) + (install "scale" (binary deg//scale)) + (install "reciprocal" (binary deg//reciprocal)) + (install "min" (nullary deg//min)) + (install "max" (nullary deg//max)) + (install "to-frac" (unary runtimeT.deg//to-frac))))) + +(def: (frac//encode value) + (-> Expression Expression) + (r.apply (list (r.string "%f") value) (r.global "sprintf"))) + +(def: frac-procs + Bundle + (<| (prefix "frac") + (|> (dict.new text.Hash) + (install "+" (binary frac//add)) + (install "-" (binary frac//sub)) + (install "*" (binary frac//mul)) + (install "/" (binary frac//div)) + (install "%" (binary frac//rem)) + (install "=" (binary frac//=)) + (install "<" (binary frac//<)) + (install "smallest" (nullary frac//smallest)) + (install "min" (nullary frac//min)) + (install "max" (nullary frac//max)) + (install "not-a-number" (nullary frac//not-a-number)) + (install "positive-infinity" (nullary frac//positive-infinity)) + (install "negative-infinity" (nullary frac//negative-infinity)) + (install "to-deg" (unary runtimeT.deg//from-frac)) + (install "to-int" (unary (apply1 (r.global "as.integer")))) + (install "encode" (unary frac//encode)) + (install "decode" (unary runtimeT.frac//decode))))) + +## [[Text]] +(def: (text//concat [subjectO paramO]) + Binary + (r.apply (list subjectO paramO) (r.global "paste0"))) + +(def: (text//char [subjectO paramO]) + Binary + (runtimeT.text//char subjectO paramO)) + +(def: (text//replace-all [textO patternO replacementO]) + Trinary + (r.apply (list patternO replacementO textO) (r.global "gsub"))) + +(def: (text//replace-once [textO patternO replacementO]) + Trinary + (r.apply (list patternO replacementO textO) (r.global "sub"))) + +(def: (text//clip [subjectO paramO extraO]) + Trinary + (runtimeT.text//clip subjectO paramO extraO)) + +(def: (text//index [textO partO startO]) + Trinary + (runtimeT.text//index textO partO startO)) + +(def: text-procs + Bundle + (<| (prefix "text") + (|> (dict.new text.Hash) + (install "=" (binary text//=)) + (install "<" (binary text//<)) + (install "concat" (binary text//concat)) + (install "index" (trinary text//index)) + (install "size" (unary (|>> (apply1 (r.global "nchar")) runtimeT.int//from-float))) + (install "hash" (unary runtimeT.text//hash)) + (install "replace-once" (trinary text//replace-once)) + (install "replace-all" (trinary text//replace-all)) + (install "char" (binary text//char)) + (install "clip" (trinary text//clip)) + (install "upper" (unary (apply1 (r.global "toupper")))) + (install "lower" (unary (apply1 (r.global "tolower")))) + ))) + +## [[Math]] +(def: (math//pow [subject param]) + Binary + (|> subject (r.** param))) + +(def: (math-func name) + (-> Text (-> Expression Expression)) + (function (_ input) + (r.apply (list input) (r.global name)))) + +(def: math-procs + Bundle + (<| (prefix "math") + (|> (dict.new text.Hash) + (install "cos" (unary (math-func "cos"))) + (install "sin" (unary (math-func "sin"))) + (install "tan" (unary (math-func "tan"))) + (install "acos" (unary (math-func "acos"))) + (install "asin" (unary (math-func "asin"))) + (install "atan" (unary (math-func "atan"))) + (install "exp" (unary (math-func "exp"))) + (install "log" (unary (math-func "log"))) + (install "ceil" (unary (math-func "ceiling"))) + (install "floor" (unary (math-func "floor"))) + (install "pow" (binary math//pow)) + ))) + +## [[IO]] +(def: (io//exit input) + (-> Expression Expression) + (r.apply-kw (list) + (list ["status" (runtimeT.int//to-float input)]) + (r.global "quit"))) + +(def: io-procs + Bundle + (<| (prefix "io") + (|> (dict.new text.Hash) + (install "log" (unary (apply1 (r.global "print")))) + (install "error" (unary (apply1 (r.global "stop")))) + (install "exit" (unary io//exit)) + (install "current-time" (nullary (function (_ _) + (runtimeT.io//current-time! runtimeT.unit))))))) + +## [[Atoms]] +(def: atom//new + Unary + (|>> [runtimeT.atom//field] (list) r.named-list)) + +(def: atom//read + Unary + (r.nth (r.string runtimeT.atom//field))) + +(def: (atom//compare-and-swap [atomO oldO newO]) + Trinary + (runtimeT.atom//compare-and-swap atomO oldO newO)) + +(def: atom-procs + Bundle + (<| (prefix "atom") + (|> (dict.new text.Hash) + (install "new" (unary atom//new)) + (install "read" (unary atom//read)) + (install "compare-and-swap" (trinary atom//compare-and-swap))))) + +## [[Box]] +(def: box//new + Unary + (|>> (list) r.list)) + +(def: box//read + Unary + (r.nth (r.int 1))) + +(def: (box//write [valueO boxO]) + Binary + (runtimeT.box//write valueO boxO)) + +(def: box-procs + Bundle + (<| (prefix "box") + (|> (dict.new text.Hash) + (install "new" (unary box//new)) + (install "read" (unary box//read)) + (install "write" (binary box//write))))) + +## [[Processes]] +(def: (process//concurrency-level []) + Nullary + (r.int 1)) + +(def: (process//schedule [milli-secondsO procedureO]) + Binary + (runtimeT.process//schedule milli-secondsO procedureO)) + +(def: process-procs + Bundle + (<| (prefix "process") + (|> (dict.new text.Hash) + (install "concurrency-level" (nullary process//concurrency-level)) + (install "future" (unary runtimeT.process//future)) + (install "schedule" (binary process//schedule)) + ))) + +## [Bundles] +(def: #export procedures + Bundle + (<| (prefix "lux") + (|> lux-procs + (dict.merge bit-procs) + (dict.merge nat-procs) + (dict.merge int-procs) + (dict.merge deg-procs) + (dict.merge frac-procs) + (dict.merge text-procs) + (dict.merge array-procs) + (dict.merge math-procs) + (dict.merge io-procs) + (dict.merge atom-procs) + (dict.merge box-procs) + (dict.merge process-procs) + ))) diff --git a/new-luxc/source/luxc/lang/translation/r/procedure/host.jvm.lux b/new-luxc/source/luxc/lang/translation/r/procedure/host.jvm.lux new file mode 100644 index 000000000..c1b43da2f --- /dev/null +++ b/new-luxc/source/luxc/lang/translation/r/procedure/host.jvm.lux @@ -0,0 +1,89 @@ +(.module: + lux + (lux (control [monad #+ do]) + (data [text] + text/format + (coll [list "list/" Functor] + [dict #+ Dict])) + [macro "macro/" Monad]) + (luxc ["&" lang] + (lang ["la" analysis] + ["ls" synthesis] + (host [ruby #+ Ruby Expression Statement]))) + [///] + (/// [".T" runtime]) + (// ["@" common])) + +## (do-template [ ] +## [(def: ( _) @.Nullary )] + +## [lua//nil "nil"] +## [lua//table "{}"] +## ) + +## (def: (lua//global proc translate inputs) +## (-> Text @.Proc) +## (case inputs +## (^ (list [_ (#.Text name)])) +## (do macro.Monad +## [] +## (wrap name)) + +## _ +## (&.throw @.Wrong-Syntax (@.wrong-syntax proc inputs)))) + +## (def: (lua//call proc translate inputs) +## (-> Text @.Proc) +## (case inputs +## (^ (list& functionS argsS+)) +## (do macro.Monad +## [functionO (translate functionS) +## argsO+ (monad.map @ translate argsS+)] +## (wrap (lua.apply functionO argsO+))) + +## _ +## (&.throw @.Wrong-Syntax (@.wrong-syntax proc inputs)))) + +## (def: lua-procs +## @.Bundle +## (|> (dict.new text.Hash) +## (@.install "nil" (@.nullary lua//nil)) +## (@.install "table" (@.nullary lua//table)) +## (@.install "global" lua//global) +## (@.install "call" lua//call))) + +## (def: (table//call proc translate inputs) +## (-> Text @.Proc) +## (case inputs +## (^ (list& tableS [_ (#.Text field)] argsS+)) +## (do macro.Monad +## [tableO (translate tableS) +## argsO+ (monad.map @ translate argsS+)] +## (wrap (lua.method field tableO argsO+))) + +## _ +## (&.throw @.Wrong-Syntax (@.wrong-syntax proc inputs)))) + +## (def: (table//get [fieldO tableO]) +## @.Binary +## (runtimeT.lua//get tableO fieldO)) + +## (def: (table//set [fieldO valueO tableO]) +## @.Trinary +## (runtimeT.lua//set tableO fieldO valueO)) + +## (def: table-procs +## @.Bundle +## (<| (@.prefix "table") +## (|> (dict.new text.Hash) +## (@.install "call" table//call) +## (@.install "get" (@.binary table//get)) +## (@.install "set" (@.trinary table//set))))) + +(def: #export procedures + @.Bundle + (<| (@.prefix "lua") + (dict.new text.Hash) + ## (|> lua-procs + ## (dict.merge table-procs)) + )) diff --git a/new-luxc/source/luxc/lang/translation/r/reference.jvm.lux b/new-luxc/source/luxc/lang/translation/r/reference.jvm.lux new file mode 100644 index 000000000..0a1bcae1f --- /dev/null +++ b/new-luxc/source/luxc/lang/translation/r/reference.jvm.lux @@ -0,0 +1,42 @@ +(.module: + lux + (lux [macro] + (data [text] + text/format)) + (luxc ["&" lang] + (lang [".L" variable #+ Variable Register] + (host [r #+ Expression Statement SVar @@]))) + [//] + (// [".T" runtime])) + +(do-template [ ] + [(def: #export ( register) + (-> Register SVar) + (r.var (format (%i (nat-to-int register))))) + + (def: #export ( register) + (-> Register (Meta Expression)) + (:: macro.Monad wrap (@@ ( register))))] + + [closure translate-captured "c"] + [variable translate-local "v"]) + +(def: #export (local var) + (-> Variable SVar) + (if (variableL.captured? var) + (closure (variableL.captured-register var)) + (variable (int-to-nat var)))) + +(def: #export (translate-variable var) + (-> Variable (Meta Expression)) + (if (variableL.captured? var) + (translate-captured (variableL.captured-register var)) + (translate-local (int-to-nat var)))) + +(def: #export global + (-> Ident SVar) + (|>> //.definition-name r.var)) + +(def: #export (translate-definition name) + (-> Ident (Meta Expression)) + (:: macro.Monad wrap (@@ (global name)))) diff --git a/new-luxc/source/luxc/lang/translation/r/runtime.jvm.lux b/new-luxc/source/luxc/lang/translation/r/runtime.jvm.lux new file mode 100644 index 000000000..9b6d0c862 --- /dev/null +++ b/new-luxc/source/luxc/lang/translation/r/runtime.jvm.lux @@ -0,0 +1,1023 @@ +(.module: + lux + (lux (control ["p" parser "p/" Monad] + [monad #+ do]) + (data [bit] + [number #+ hex] + text/format + (coll [list "list/" Monad])) + [macro] + (macro [code] + ["s" syntax #+ syntax:]) + [io #+ Process]) + [//] + (luxc [lang] + (lang (host [r #+ SVar Expression Statement @@])))) + +(def: prefix Text "LuxRuntime") + +(def: #export unit Expression (r.string //.unit)) + +(def: high (|>> int-to-nat (bit.shift-right +32) nat-to-int)) +(def: low (|>> int-to-nat (bit.and (hex "+FFFFFFFF")) nat-to-int)) + +(def: #export (int value) + (-> Int Expression) + (r.named-list (list [//.int-high-field (r.int (high value))] + [//.int-low-field (r.int (low value))]))) + +(def: (flag value) + (-> Bool Expression) + (if value + (r.string "") + r.null)) + +(def: (variant' tag last? value) + (-> Expression Expression Expression Expression) + (r.named-list (list [//.variant-tag-field tag] + [//.variant-flag-field last?] + [//.variant-value-field value]))) + +(def: #export (variant tag last? value) + (-> Nat Bool Expression Expression) + (variant' (r.int (nat-to-int tag)) + (flag last?) + value)) + +(def: #export none + Expression + (variant +0 false unit)) + +(def: #export some + (-> Expression Expression) + (variant +1 true)) + +(def: #export left + (-> Expression Expression) + (variant +0 false)) + +(def: #export right + (-> Expression Expression) + (variant +1 true)) + +(type: Runtime Statement) + +(def: declaration + (s.Syntax [Text (List Text)]) + (p.either (p.seq s.local-symbol (p/wrap (list))) + (s.form (p.seq s.local-symbol (p.some s.local-symbol))))) + +(syntax: (runtime: [[name args] declaration] + definition) + (let [implementation (code.local-symbol (format "@@" name)) + runtime (format prefix "__" (lang.normalize-name name)) + $runtime (` (r.var (~ (code.text runtime)))) + @runtime (` (@@ (~ $runtime))) + argsC+ (list/map code.local-symbol args) + argsLC+ (list/map (|>> lang.normalize-name code.text (~) (r.var) (`)) + args) + declaration (` ((~ (code.local-symbol name)) + (~+ argsC+))) + type (` (-> (~+ (list.repeat (list.size argsC+) (` r.Expression))) + r.Expression))] + (wrap (list (` (def: (~' #export) (~ declaration) + (~ type) + (r.apply (list (~+ argsC+)) (~ @runtime)))) + (` (def: (~ implementation) + r.Statement + (~ (case argsC+ + #.Nil + (` (r.set! (~ $runtime) (~ definition))) + + _ + (` (let [(~+ (|> (list.zip2 argsC+ argsLC+) + (list/map (function (_ [left right]) + (list left right))) + list/join))] + (r.set! (~ $runtime) + (r.function (list (~+ argsLC+)) + (~ definition))))))))))))) + +(syntax: #export (with-vars [vars (s.tuple (p.many s.local-symbol))] + body) + (wrap (list (` (let [(~+ (|> vars + (list/map (function (_ var) + (list (code.local-symbol var) + (` (r.var (~ (code.text (format "LRV__" (lang.normalize-name var))))))))) + list/join))] + (~ body)))))) + +(def: high-shift (r.bit-shl (r.int 32))) + +(def: f2^32 (|> (r.int 1) high-shift)) +(def: f2^63 (|> (r.int 1) (r.bit-shl (r.int 63)))) + +(def: (as-integer value) + (-> Expression Expression) + (r.apply (list value) (r.global "as.integer"))) + +(runtime: (int//unsigned-low input) + (with-vars [low] + ($_ r.then! + (r.set! low (|> (@@ input) (r.nth (r.string //.int-low-field)))) + (r.do! + (r.if (|> (@@ low) (r.>= (r.int 0))) + (@@ low) + (|> (@@ low) (r.+ f2^32))))))) + +(runtime: (int//to-float input) + (let [high (|> (@@ input) + (r.nth (r.string //.int-high-field)) + high-shift) + low (|> (@@ input) + int//unsigned-low)] + (r.do! (|> high (r.+ low))))) + +(runtime: (int//new high low) + (r.do! + (r.named-list (list [//.int-high-field (as-integer (@@ high))] + [//.int-low-field (as-integer (@@ low))])))) + +(do-template [ ] + [(runtime: + (int//new (r.int ) (r.int )))] + + [int//zero 0 0] + [int//one 0 1] + [int//min (hex "80000000") 0] + [int//max (hex "7FFFFFFF") (hex "FFFFFFFF")] + ) + +(def: int64-high (r.nth (r.string //.int-high-field))) +(def: int64-low (r.nth (r.string //.int-low-field))) + +(runtime: (bit//not input) + (r.do! (int//new (|> (@@ input) int64-high r.bit-not) + (|> (@@ input) int64-low r.bit-not)))) + +(runtime: (int//+ param subject) + (with-vars [sH sL pH pL + x00 x16 x32 x48] + ($_ r.then! + (r.set! sH (|> (@@ subject) int64-high)) + (r.set! sL (|> (@@ subject) int64-low)) + (r.set! pH (|> (@@ param) int64-high)) + (r.set! pL (|> (@@ param) int64-low)) + (let [bits16 (r.code "0xFFFF") + move-top-16 (r.bit-shl (r.int 16)) + top-16 (r.bit-ushr (r.int 16)) + bottom-16 (r.bit-and bits16) + split-16 (function (_ source) + [(|> source top-16) + (|> source bottom-16)]) + split-int (function (_ high low) + [(split-16 high) + (split-16 low)]) + + [[s48 s32] [s16 s00]] (split-int (@@ sH) (@@ sL)) + [[p48 p32] [p16 p00]] (split-int (@@ pH) (@@ pL)) + new-half (function (_ top bottom) + (|> top bottom-16 move-top-16 + (r.bit-or (bottom-16 bottom))))] + ($_ r.then! + (r.set! x00 (|> s00 (r.+ p00))) + (r.set! x16 (|> (@@ x00) top-16 (r.+ s16) (r.+ p16))) + (r.set! x32 (|> (@@ x16) top-16 (r.+ s32) (r.+ p32))) + (r.set! x48 (|> (@@ x32) top-16 (r.+ s48) (r.+ p48))) + (r.do! (int//new (new-half (@@ x48) (@@ x32)) + (new-half (@@ x16) (@@ x00))))))))) + +(runtime: (int//= reference sample) + (let [comparison (: (-> (-> Expression Expression) Expression) + (function (_ field) + (|> (field (@@ sample)) (r.= (field (@@ reference))))))] + (r.do! (|> (comparison int64-high) + (r.and (comparison int64-low)))))) + +(runtime: (int//negate input) + (r.do! + (r.if (|> (@@ input) (int//= int//min)) + int//min + (|> (@@ input) bit//not (int//+ int//one))))) + +(runtime: int//-one + (int//negate int//one)) + +(runtime: (int//- param subject) + (r.do! (int//+ (int//negate (@@ param)) (@@ subject)))) + +(runtime: (int//< reference sample) + (with-vars [r-? s-?] + ($_ r.then! + (r.set! s-? (|> (@@ sample) int64-high (r.< (r.int 0)))) + (r.set! r-? (|> (@@ reference) int64-high (r.< (r.int 0)))) + (r.do! (|> (|> (@@ s-?) (r.and (r.not (@@ r-?)))) + (r.or (|> (r.not (@@ s-?)) (r.and (@@ r-?)) r.not)) + (r.or (|> (@@ sample) + (int//- (@@ reference)) + int64-high + (r.< (r.int 0))))))))) + +(runtime: (int//from-float input) + (r.do! + (r.cond (list [(r.apply (list (@@ input)) (r.global "is.nan")) + int//zero] + [(|> (@@ input) (r.<= (r.negate f2^63))) + int//min] + [(|> (@@ input) (r.+ (r.float 1.0)) (r.>= f2^63)) + int//max] + [(|> (@@ input) (r.< (r.float 0.0))) + (|> (@@ input) r.negate int//from-float int//negate)]) + (int//new (|> (@@ input) (r./ f2^32)) + (|> (@@ input) (r.%% f2^32)))))) + +(runtime: (int//* param subject) + (with-vars [sH sL pH pL + x00 x16 x32 x48] + ($_ r.then! + (r.set! sH (|> (@@ subject) int64-high)) + (r.set! pH (|> (@@ param) int64-high)) + (let [negative-subject? (|> (@@ sH) (r.< (r.int 0))) + negative-param? (|> (@@ pH) (r.< (r.int 0)))] + (r.cond! (list [negative-subject? + (r.if! negative-param? + (r.do! (int//* (int//negate (@@ param)) + (int//negate (@@ subject)))) + (r.do! (int//negate (int//* (@@ param) + (int//negate (@@ subject))))))] + + [negative-param? + (r.do! (int//negate (int//* (int//negate (@@ param)) + (@@ subject))))]) + ($_ r.then! + (r.set! sL (|> (@@ subject) int64-low)) + (r.set! pL (|> (@@ param) int64-low)) + (let [bits16 (r.code "0xFFFF") + move-top-16 (r.bit-shl (r.int 16)) + top-16 (r.bit-ushr (r.int 16)) + bottom-16 (r.bit-and bits16) + split-16 (function (_ source) + [(|> source top-16) + (|> source bottom-16)]) + split-int (function (_ high low) + [(split-16 high) + (split-16 low)]) + new-half (function (_ top bottom) + (|> top bottom-16 move-top-16 + (r.bit-or (bottom-16 bottom)))) + + [[_s48 _s32] [_s16 _s00]] (split-int (@@ sH) (@@ sL)) + [[_p48 _p32] [_p16 _p00]] (split-int (@@ pH) (@@ pL)) + x16-top (|> (@@ x16) top-16) + x32-top (|> (@@ x32) top-16)] + (with-vars [s48 s32 s16 s00 + p48 p32 p16 p00] + ($_ r.then! + (r.set! s48 _s48) (r.set! s32 _s32) (r.set! s16 _s16) (r.set! s00 _s00) + (r.set! p48 _p48) (r.set! p32 _p32) (r.set! p16 _p16) (r.set! p00 _p00) + (r.set! x00 (|> (@@ s00) (r.* (@@ p00)))) + (r.set! x16 (|> (@@ x00) top-16 (r.+ (|> (@@ s16) (r.* (@@ p00)))))) + (r.set! x32 x16-top) + (r.set! x16 (|> (@@ x16) bottom-16 (r.+ (|> (@@ s00) (r.* (@@ p16)))))) + (r.set! x32 (|> (@@ x32) (r.+ x16-top) (r.+ (|> (@@ s32) (r.* (@@ p00)))))) + (r.set! x48 x32-top) + (r.set! x32 (|> (@@ x32) bottom-16 (r.+ (|> (@@ s16) (r.* (@@ p16)))))) + (r.set! x48 (|> (@@ x48) (r.+ x32-top))) + (r.set! x32 (|> (@@ x32) bottom-16 (r.+ (|> (@@ s00) (r.* (@@ p32)))))) + (r.set! x48 (|> (@@ x48) (r.+ x32-top) + (r.+ (|> (@@ s48) (r.* (@@ p00)))) + (r.+ (|> (@@ s32) (r.* (@@ p16)))) + (r.+ (|> (@@ s16) (r.* (@@ p32)))) + (r.+ (|> (@@ s00) (r.* (@@ p48)))))) + (r.do! (int//new (new-half (@@ x48) (@@ x32)) + (new-half (@@ x16) (@@ x00)))))) + ))))))) + +(def: (limit-shift! shift) + (-> SVar Statement) + (r.set! shift (|> (@@ shift) (r.bit-and (r.int 63))))) + +(def: (no-shift-clause shift input) + (-> SVar SVar [Expression Statement]) + [(|> (@@ shift) (r.= (r.int 0))) + (r.do! (@@ input))]) + +(runtime: (bit//shift-left shift input) + ($_ r.then! + (limit-shift! shift) + (r.cond! (list (no-shift-clause shift input) + [(|> (@@ shift) (r.< (r.int 32))) + (let [mid (|> (int64-low (@@ input)) (r.bit-ushr (|> (r.int 32) (r.- (@@ shift))))) + high (|> (int64-high (@@ input)) + (r.bit-shl (@@ shift)) + (r.bit-or mid)) + low (|> (int64-low (@@ input)) + (r.bit-shl (@@ shift)))] + (r.do! (int//new high low)))]) + (let [high (|> (int64-high (@@ input)) + (r.bit-shl (|> (@@ shift) (r.- (r.int 32)))))] + (r.do! (int//new high (r.int 0))))))) + +(runtime: (bit//signed-shift-right-32 shift input) + (let [top-bit (|> (@@ input) (r.bit-and (r.int (hex "80000000"))))] + (r.do! (|> (@@ input) + (r.bit-ushr (@@ shift)) + (r.bit-or top-bit))))) + +(runtime: (bit//signed-shift-right shift input) + ($_ r.then! + (limit-shift! shift) + (r.cond! (list (no-shift-clause shift input) + [(|> (@@ shift) (r.< (r.int 32))) + (let [mid (|> (int64-high (@@ input)) (r.bit-shl (|> (r.int 32) (r.- (@@ shift))))) + high (|> (int64-high (@@ input)) + (bit//signed-shift-right-32 (@@ shift))) + low (|> (int64-low (@@ input)) + (r.bit-ushr (@@ shift)) + (r.bit-or mid))] + (r.do! (int//new high low)))]) + (let [low (|> (int64-high (@@ input)) + (bit//signed-shift-right-32 (|> (@@ shift) (r.- (r.int 32))))) + high (r.if (|> (int64-high (@@ input)) (r.>= (r.int 0))) + (r.int 0) + (r.int -1))] + (r.do! (int//new high low)))))) + +(runtime: (int/// param subject) + (let [negative? (|>> (int//< int//zero)) + valid-division-check [(|> (@@ param) (int//= int//zero)) + (r.stop! (r.string "Cannot divide by zero!"))] + short-circuit-check [(|> (@@ subject) (int//= int//zero)) + (r.do! int//zero)]] + (r.cond! (list valid-division-check + short-circuit-check + + [(|> (@@ subject) (int//= int//min)) + (r.cond! (list [(|> (|> (@@ param) (int//= int//one)) + (r.or (|> (@@ param) (int//= int//-one)))) + (r.do! int//min)] + [(|> (@@ param) (int//= int//min)) + (r.do! int//one)]) + (with-vars [approximation] + ($_ r.then! + (r.set! approximation + (|> (@@ subject) + (bit//signed-shift-right (r.int 1)) + (int/// (@@ param)) + (bit//shift-left (r.int 1)))) + (r.if! (|> (@@ approximation) (int//= int//zero)) + (r.do! (r.if (negative? (@@ param)) + int//one + int//-one)) + (let [remainder (int//- (int//* (@@ param) (@@ approximation)) + (@@ subject))] + (r.do! (|> remainder + (int/// (@@ param)) + (int//+ (@@ approximation)))))))))] + [(|> (@@ param) (int//= int//min)) + (r.do! int//zero)] + + [(negative? (@@ subject)) + (r.do! (r.if (negative? (@@ param)) + (|> (int//negate (@@ subject)) + (int/// (int//negate (@@ param)))) + (|> (int//negate (@@ subject)) + (int/// (@@ param)) + int//negate)))] + + [(negative? (@@ param)) + (r.do! (|> (@@ param) + int//negate + (int/// (@@ subject)) + int//negate))]) + (with-vars [result remainder approximate approximate-result log2 approximate-remainder] + ($_ r.then! + (r.set! result int//zero) + (r.set! remainder (@@ subject)) + (r.while! (|> (|> (@@ remainder) (int//< (@@ param))) + (r.or (|> (@@ remainder) (int//= (@@ param))))) + (let [calc-rough-estimate (r.apply (list (|> (int//to-float (@@ remainder)) (r./ (int//to-float (@@ param))))) + (r.global "floor")) + calc-approximate-result (int//from-float (@@ approximate)) + calc-approximate-remainder (|> (@@ approximate-result) (int//* (@@ param))) + delta (r.if (|> (r.float 48.0) (r.<= (@@ log2))) + (r.float 1.0) + (r.** (|> (@@ log2) (r.- (r.float 48.0))) + (r.float 2.0)))] + ($_ r.then! + (r.set! approximate (r.apply (list (r.float 1.0) calc-rough-estimate) + (r.global "max"))) + (r.set! log2 (let [log (function (_ input) + (r.apply (list input) (r.global "log")))] + (r.apply (list (|> (log (r.int 2)) + (r./ (log (@@ approximate))))) + (r.global "ceil")))) + (r.set! approximate-result calc-approximate-result) + (r.set! approximate-remainder calc-approximate-remainder) + (r.while! (|> (negative? (@@ approximate-remainder)) + (r.or (|> (@@ approximate-remainder) (int//< (@@ remainder))))) + ($_ r.then! + (r.set! approximate (|> delta (r.- (@@ approximate)))) + (r.set! approximate-result calc-approximate-result) + (r.set! approximate-remainder calc-approximate-remainder))) + (r.set! result (|> (r.if (|> (@@ approximate-result) (int//= int//zero)) + int//one + (@@ approximate-result)) + (int//+ (@@ result)))) + (r.set! remainder (|> (@@ remainder) (int//- (@@ approximate-remainder))))))) + (r.do! (@@ result)))) + ))) + +(runtime: (int//% param subject) + (let [flat (|> (@@ subject) (int/// (@@ param)) (int//* (@@ param)))] + (r.do! (|> (@@ subject) (int//- flat))))) + +(def: runtime//int + Runtime + ($_ r.then! + @@int//unsigned-low + @@int//to-float + @@int//new + @@int//zero + @@int//one + @@int//min + @@int//max + @@int//= + @@int//< + @@int//+ + @@int//- + @@int//* + @@int/// + @@int//% + @@int//negate + @@int//from-float)) + +(runtime: (lux//try op) + (with-vars [error value] + (r.do! (r.try ($_ r.then! + (r.set! value (r.apply (list ..unit) (@@ op))) + (r.do! (..right (@@ value)))) + #.None + (#.Some (r.function (list error) + (r.do! (..left (@@ error))))) + #.None)))) + +(runtime: (lux//program-args program-args) + (with-vars [inputs value] + ($_ r.then! + (r.set! inputs ..none) + (<| (r.for-in! value (@@ program-args)) + (r.set! inputs (..some (r.list (list (@@ value) (@@ inputs)))))) + (r.do! (@@ inputs))))) + +(def: runtime//lux + Runtime + ($_ r.then! + @@lux//try + @@lux//program-args)) + +(def: current-time-float + Expression + (let [raw-time (r.apply (list) (r.global "Sys.time"))] + (r.apply (list raw-time) (r.global "as.numeric")))) + +(runtime: (io//current-time! _) + (r.do! (|> current-time-float + (r.* (r.float 1_000.0)) + int//from-float))) + +(def: runtime//io + Runtime + ($_ r.then! + @@io//current-time!)) + +(def: minimum-index-length + (-> SVar Expression) + (|>> @@ (r.+ (r.int 1)))) + +(def: (product-element product index) + (-> Expression Expression Expression) + (|> product (r.nth (|> index (r.+ (r.int 1)))))) + +(def: (product-tail product) + (-> SVar Expression) + (|> (@@ product) (r.nth (r.length (@@ product))))) + +(def: (updated-index min-length product) + (-> Expression Expression Expression) + (|> min-length (r.- (r.length product)))) + +(runtime: (product//left product index) + (let [$index_min_length (r.var "index_min_length")] + ($_ r.then! + (r.set! $index_min_length (minimum-index-length index)) + (r.do! (r.if (|> (r.length (@@ product)) (r.> (@@ $index_min_length))) + ## No need for recursion + (product-element (@@ product) (@@ index)) + ## Needs recursion + (product//left (product-tail product) + (updated-index (@@ $index_min_length) (@@ product)))))))) + +(runtime: (product//right product index) + (let [$index_min_length (r.var "index_min_length")] + ($_ r.then! + (r.set! $index_min_length (minimum-index-length index)) + (r.do! (r.cond (list [## Last element. + (|> (r.length (@@ product)) (r.= (@@ $index_min_length))) + (product-element (@@ product) (@@ index))] + [## Needs recursion + (|> (r.length (@@ product)) (r.< (@@ $index_min_length))) + (product//right (product-tail product) + (updated-index (@@ $index_min_length) (@@ product)))]) + ## Must slice + (|> (@@ product) (r.slice-from (@@ index)))))))) + +(runtime: (sum//get sum wanted_tag wants_last) + (let [no-match r.null + sum-tag (|> (@@ sum) (r.nth (r.string //.variant-tag-field))) + sum-flag (|> (@@ sum) (r.nth (r.string //.variant-flag-field))) + sum-value (|> (@@ sum) (r.nth (r.string //.variant-value-field))) + is-last? (|> sum-flag (r.= (r.string ""))) + test-recursion (r.if is-last? + ## Must recurse. + (sum//get sum-value + (|> (@@ wanted_tag) (r.- sum-tag)) + (@@ wants_last)) + no-match)] + (r.do! (r.cond (list [(r.= sum-tag (@@ wanted_tag)) + (r.if (r.= (@@ wants_last) sum-flag) + sum-value + test-recursion)] + + [(|> (@@ wanted_tag) (r.> sum-tag)) + test-recursion] + + [(|> (|> (@@ wants_last) (r.= (r.string ""))) + (r.and (|> (@@ wanted_tag) (r.< sum-tag)))) + (variant' (|> sum-tag (r.- (@@ wanted_tag))) sum-flag sum-value)]) + + no-match)))) + +(def: runtime//adt + Runtime + ($_ r.then! + @@product//left + @@product//right + @@sum//get + )) + +(do-template [ ] + [(runtime: ( mask input) + (r.do! (int//new ( (int64-high (@@ mask)) + (int64-high (@@ input))) + ( (int64-low (@@ mask)) + (int64-low (@@ input))))))] + + [bit//and r.bit-and] + [bit//or r.bit-or] + [bit//xor r.bit-xor] + ) + +(runtime: (bit//count-32 input) + (with-vars [count] + ($_ r.then! + (r.set! count (r.int 0)) + (let [last-input-bit (|> (@@ input) (r.bit-and (r.int 1))) + update-count! (r.set! count (|> (@@ count) (r.+ last-input-bit))) + consume-input! (r.set! input (|> (@@ input) (r.bit-ushr (r.int 1)))) + input-remaining? (|> (@@ input) (r.= (r.int 0)))] + (r.while! input-remaining? + ($_ r.then! + update-count! + consume-input!))) + (r.do! (@@ count))))) + +(runtime: (bit//count input) + (r.do! (int//from-float (r.+ (int64-high (@@ input)) + (int64-low (@@ input)))))) + +(runtime: (bit//shift-right shift input) + ($_ r.then! + (limit-shift! shift) + (r.cond! (list (no-shift-clause shift input) + [(|> (@@ shift) (r.< (r.int 32))) + (let [mid (|> (int64-high (@@ input)) (r.bit-shl (|> (r.int 32) (r.- (@@ shift))))) + high (|> (int64-high (@@ input)) (r.bit-ushr (@@ shift))) + low (|> (int64-low (@@ input)) + (r.bit-ushr (@@ shift)) + (r.bit-or mid))] + (r.do! (int//new high low)))] + [(|> (@@ shift) (r.= (r.int 32))) + (let [high (int64-high (@@ input))] + (r.do! (int//new (r.int 0) high)))]) + (let [low (|> (int64-high (@@ input)) (r.bit-ushr (|> (@@ shift) (r.- (r.int 32)))))] + (r.do! (int//new (r.int 0) low)))))) + +(def: runtime//bit + Runtime + ($_ r.then! + @@bit//and + @@bit//or + @@bit//xor + @@bit//not + @@bit//count-32 + @@bit//count + @@bit//shift-left + @@bit//signed-shift-right-32 + @@bit//signed-shift-right + @@bit//shift-right + )) + +(runtime: (nat//< param subject) + (with-vars [pH sH] + ($_ r.then! + (r.set! pH (..int64-high (@@ param))) + (r.set! sH (..int64-high (@@ subject))) + (let [lesser-high? (|> (@@ sH) (r.< (@@ pH))) + equal-high? (|> (@@ sH) (r.= (@@ pH))) + lesser-low? (|> (..int64-low (@@ subject)) (r.< (..int64-low (@@ param))))] + (r.do! (|> lesser-high? + (r.or (|> equal-high? + (r.and lesser-low?))))))))) + +(runtime: (nat/// parameter subject) + (let [negative? (int//< int//zero) + valid-division-check [(|> (@@ parameter) (int//= int//zero)) + (r.stop! (r.string "Cannot divide by zero!"))] + short-circuit-check [(|> (@@ subject) (nat//< (@@ parameter))) + (r.do! int//zero)]] + (r.cond! (list valid-division-check + short-circuit-check + + [(|> (@@ parameter) + (nat//< (|> (@@ subject) (bit//shift-right (r.int 1))))) + (r.do! int//one)]) + (with-vars [result remainder approximate log2 approximate-result approximate-remainder delta] + ($_ r.then! + (r.set! result int//zero) + (r.set! remainder (@@ subject)) + (r.while! (|> (|> (@@ remainder) (nat//< (@@ parameter))) + (r.or (|> (@@ remainder) (int//= (@@ parameter))))) + (let [rough-estimate (r.apply (list (|> (int//to-float (@@ parameter)) (r./ (int//to-float (@@ remainder))))) + (r.global "floor")) + calculate-approximate-result (int//from-float (@@ approximate)) + calculate-approximate-remainder (int//* (@@ parameter) (@@ approximate-result)) + delta (r.if (|> (r.float 48.0) (r.<= (@@ log2))) + (r.float 1.0) + (r.** (|> (r.float 48.0) (r.- (@@ log2))) + (r.float 2.0))) + update-approximates! ($_ r.then! + (r.set! approximate-result calculate-approximate-result) + (r.set! approximate-remainder calculate-approximate-remainder))] + ($_ r.then! + (r.set! approximate (r.apply (list (r.float 1.0) rough-estimate) + (r.global "max"))) + (r.set! log2 (let [log (function (_ input) + (r.apply (list input) (r.global "log")))] + (r.apply (list (|> (log (r.int 2)) + (r./ (log (@@ approximate))))) + (r.global "ceil")))) + update-approximates! + (r.while! (|> (negative? (@@ approximate-remainder)) + (r.or (|> (@@ approximate-remainder) (int//< (@@ remainder))))) + ($_ r.then! + (r.set! approximate (|> delta (r.- (@@ approximate)))) + update-approximates!)) + ($_ r.then! + (r.set! result (|> (@@ result) + (int//+ (r.if (|> (@@ approximate-result) (int//= int//zero)) + int//one + (@@ approximate-result))))) + (r.set! remainder (|> (@@ remainder) (int//- (@@ approximate-remainder)))))))) + (r.do! (@@ result)))) + ))) + +(runtime: (nat//% param subject) + (let [flat (|> (@@ subject) + (nat/// (@@ param)) + (int//* (@@ param)))] + (r.do! (|> (@@ subject) (int//- flat))))) + +(def: runtime//nat + Runtime + ($_ r.then! + @@nat//< + @@nat/// + @@nat//%)) + +(runtime: (deg//* param subject) + (with-vars [sL sH pL pH bottom middle top] + ($_ r.then! + (r.set! sL (int//from-float (int64-low (@@ subject)))) + (r.set! sH (int//from-float (int64-high (@@ subject)))) + (r.set! pL (int//from-float (int64-low (@@ param)))) + (r.set! pH (int//from-float (int64-high (@@ param)))) + (let [bottom (bit//shift-right (r.int 32) + (r.* (@@ pL) (@@ sL))) + middle (r.+ (r.* (@@ pL) (@@ sH)) + (r.* (@@ pH) (@@ sL))) + top (r.* (@@ pH) (@@ sH))] + (r.do! (|> bottom + (r.+ middle) + (bit//shift-right (r.int 32)) + (r.+ top))))))) + +(runtime: (deg//leading-zeroes input) + (with-vars [zeroes remaining] + ($_ r.then! + (r.set! zeroes (r.int 64)) + (r.set! remaining (@@ input)) + (r.while! (|> (@@ remaining) (int//= int//zero) r.not) + ($_ r.then! + (r.set! zeroes (|> (@@ zeroes) (r.- (r.int 1)))) + (r.set! remaining (|> (@@ remaining) (bit//shift-right (r.int 1)))))) + (r.do! (@@ zeroes))))) + +(runtime: (deg/// param subject) + (with-vars [min-shift] + (r.if! (|> (@@ subject) (int//= (@@ param))) + (r.do! int//-one) + ($_ r.then! + (r.set! min-shift + (r.apply (list (deg//leading-zeroes (@@ param)) + (deg//leading-zeroes (@@ subject))) + (r.global "min"))) + (let [subject' (|> (@@ subject) (bit//shift-left (@@ min-shift))) + param' (|> (@@ param) (bit//shift-left (@@ min-shift)) int64-low int//from-float)] + (r.do! (|> subject' + (int/// param') + (bit//shift-left (r.int 32))))))))) + +(runtime: (deg//from-frac input) + (with-vars [two32 shifted] + ($_ r.then! + (r.set! two32 (|> (r.float 2.0) (r.** (r.float 32.0)))) + (r.set! shifted (|> (@@ input) (r.%% (r.float 1.0)) (r.* (@@ two32)))) + (let [low (|> (@@ shifted) (r.%% (r.float 1.0)) (r.* (@@ two32)) as-integer) + high (|> (@@ shifted) as-integer)] + (r.do! (int//new high low)))))) + +(runtime: (deg//to-frac input) + (with-vars [two32] + ($_ r.then! + (r.set! two32 f2^32) + (let [high (|> (int64-high (@@ input)) (r./ (@@ two32))) + low (|> (int64-low (@@ input)) (r./ (@@ two32)) (r./ (@@ two32)))] + (r.do! (|> low (r.+ high))))))) + +(def: runtime//deg + Runtime + ($_ r.then! + @@deg//* + @@deg//leading-zeroes + @@deg/// + @@deg//from-frac + @@deg//to-frac)) + +(runtime: (frac//decode input) + (with-vars [output] + ($_ r.then! + (r.set! output (r.apply (list (@@ input)) (r.global "as.numeric"))) + (r.do! (r.if (|> (@@ output) (r.= r.n/a)) + ..none + (..some (@@ output))))))) + +(def: runtime//frac + Runtime + ($_ r.then! + @@frac//decode)) + +(def: inc (-> Expression Expression) (|>> (r.+ (r.int 1)))) + +(do-template [ ] + [(def: ( top value) + (-> Expression Expression Expression) + (|> (|> value (r.>= (r.int 0))) + (r.and (|> value ( top)))))] + + [within? r.<] + [up-to? r.<=] + ) + +(def: (text-clip start end text) + (-> Expression Expression Expression Expression) + (r.apply (list text start end) + (r.global "substr"))) + +(def: (text-length text) + (-> Expression Expression) + (r.apply (list text) (r.global "nchar"))) + +(runtime: (text//index subject param start) + (with-vars [idx startF subjectL] + ($_ r.then! + (r.set! startF (int//to-float (@@ start))) + (r.set! subjectL (text-length (@@ subject))) + (r.do! + (r.if (|> (@@ startF) (within? (@@ subjectL))) + (r.block + ($_ r.then! + (r.set! idx (|> (r.apply-kw (list (@@ param) (r.if (|> (@@ startF) (r.= (r.int 0))) + (@@ subject) + (text-clip (inc (@@ startF)) + (inc (@@ subjectL)) + (@@ subject)))) + (list ["fixed" (r.bool true)]) + (r.global "regexpr")) + (r.nth (r.int 1)))) + (r.do! + (r.if (|> (@@ idx) (r.= (r.int -1))) + ..none + (..some (int//from-float (|> (@@ idx) (r.+ (@@ startF))))))))) + ..none))))) + +(runtime: (text//clip text from to) + (with-vars [length] + ($_ r.then! + (r.set! length (r.length (@@ text))) + (r.do! + (r.if ($_ r.and + (|> (@@ to) (within? (@@ length))) + (|> (@@ from) (up-to? (@@ to)))) + (..some (text-clip (inc (@@ from)) (inc (@@ to)) (@@ text))) + ..none))))) + +(def: (char-at idx text) + (-> Expression Expression Expression) + (r.apply (list (text-clip idx idx text)) + (r.global "utf8ToInt"))) + +(runtime: (text//char text idx) + (r.if! (|> (@@ idx) (within? (r.length (@@ text)))) + ($_ r.then! + (r.set! idx (inc (@@ idx))) + (r.do! (..some (int//from-float (char-at (@@ idx) (@@ text)))))) + (r.do! ..none))) + +(runtime: (text//hash input) + (let [bits-32 (r.code "0xFFFFFFFF")] + (with-vars [idx hash] + ($_ r.then! + (r.set! hash (r.int 0)) + (r.for-in! idx (r.range (r.int 1) (text-length (@@ input))) + (r.set! hash (|> (@@ hash) + (r.bit-shl (r.int 5)) + (r.- (@@ hash)) + (r.+ (char-at (@@ idx) (@@ input))) + (r.bit-and bits-32)))) + (r.do! (int//from-float (@@ hash))))))) + +(def: runtime//text + Runtime + ($_ r.then! + @@text//index + @@text//clip + @@text//char + @@text//hash)) + +(def: (check-index-out-of-bounds array idx body!) + (-> Expression Expression Statement Statement) + (r.if! (|> idx (r.<= (r.length array))) + body! + (r.stop! (r.string "Array index out of bounds!")))) + +(runtime: (array//new size) + (with-vars [output] + ($_ r.then! + (r.set! output (r.list (list))) + (r.set-nth! (|> (@@ size) (r.+ (r.int 1))) + r.null + output) + (r.do! (@@ output))))) + +(runtime: (array//get array idx) + (with-vars [temp] + (<| (check-index-out-of-bounds (@@ array) (@@ idx)) + ($_ r.then! + (r.set! temp (|> (@@ array) (r.nth (@@ idx)))) + (r.if! (|> (@@ temp) (r.= r.null)) + (r.do! ..none) + (r.do! (..some (@@ temp)))))))) + +(runtime: (array//put array idx value) + (<| (check-index-out-of-bounds (@@ array) (@@ idx)) + ($_ r.then! + (r.set-nth! (@@ idx) (@@ value) array) + (r.do! (@@ array))))) + +(def: runtime//array + Runtime + ($_ r.then! + @@array//new + @@array//get + @@array//put)) + +(def: #export atom//field Text "lux_atom") + +(runtime: (atom//compare-and-swap atom old new) + (let [atom//field (r.string atom//field)] + (r.do! + (r.if (|> (@@ atom) (r.nth atom//field) (r.= (@@ old))) + (r.block + ($_ r.then! + (r.set-nth! atom//field (@@ new) atom) + (r.do! (r.bool true)))) + (r.bool false))))) + +(def: runtime//atom + Runtime + ($_ r.then! + @@atom//compare-and-swap)) + +(runtime: (box//write value box) + ($_ r.then! + (r.set-nth! (r.int 1) (@@ value) box) + (r.do! ..unit))) + +(def: runtime//box + Runtime + ($_ r.then! + @@box//write)) + +(def: process//incoming + SVar + (r.var (lang.normalize-name "process//incoming"))) + +(def: (list-append! value rlist) + (-> Expression SVar Statement) + (r.set-nth! (r.length (@@ rlist)) value rlist)) + +(runtime: (process//loop _) + (let [empty (r.list (list))] + (with-vars [queue process] + (let [migrate-incoming! ($_ r.then! + (r.set! queue empty) + (<| (r.for-in! process (@@ process//incoming)) + (list-append! (@@ process) queue)) + (r.set! process//incoming empty)) + consume-queue! (<| (r.for-in! process (@@ queue)) + (r.do! (r.apply (list ..unit) (@@ process))))] + ($_ r.then! + migrate-incoming! + consume-queue! + (r.when! (|> (r.length (@@ queue)) (r.> (r.int 0))) + (r.do! (process//loop ..unit)))))))) + +(runtime: (process//future procedure) + ($_ r.then! + (list-append! (@@ procedure) process//incoming) + (r.do! ..unit))) + +(runtime: (process//schedule milli-seconds procedure) + (let [to-seconds (|>> (r./ (r.float 1_000.0))) + to-millis (|>> (r.* (r.float 1_000.0)))] + (with-vars [start now seconds _arg elapsed-time] + ($_ r.then! + (r.set! start current-time-float) + (r.set! seconds (to-seconds (@@ milli-seconds))) + (list-append! (r.function (list _arg) + ($_ r.then! + (r.set! now current-time-float) + (r.set! elapsed-time (|> (@@ now) (r.- (@@ start)))) + (r.if! (|> (@@ elapsed-time) (r.>= (@@ seconds))) + (r.do! (@@ procedure)) + (r.do! (process//schedule (to-millis (@@ elapsed-time)) + (@@ procedure)))))) + process//incoming) + (r.do! ..unit))))) + +(def: runtime//process + Runtime + ($_ r.then! + (r.set! process//incoming (r.list (list))) + @@process//loop + @@process//future + @@process//schedule + )) + +(def: runtime + Runtime + ($_ r.then! + runtime//int + runtime//lux + runtime//adt + runtime//bit + runtime//nat + runtime//deg + runtime//frac + runtime//text + runtime//array + runtime//atom + runtime//box + runtime//io + runtime//process + )) + +(def: #export artifact Text (format prefix ".r")) + +(def: #export translate + (Meta (Process Unit)) + (do macro.Monad + [_ //.init-module-buffer + _ (//.save runtime)] + (//.save-module! artifact))) diff --git a/new-luxc/source/luxc/lang/translation/r/statement.jvm.lux b/new-luxc/source/luxc/lang/translation/r/statement.jvm.lux new file mode 100644 index 000000000..317abcf73 --- /dev/null +++ b/new-luxc/source/luxc/lang/translation/r/statement.jvm.lux @@ -0,0 +1,45 @@ +(.module: + lux + (lux (control [monad #+ do]) + [macro] + (data text/format)) + (luxc (lang [".L" module] + (host [r #+ Expression Statement @@]))) + [//] + (// [".T" runtime] + [".T" reference] + [".T" eval])) + +(def: #export (translate-def name expressionT expressionO metaV) + (-> Text Type Expression Code (Meta Unit)) + (do macro.Monad + [current-module macro.current-module-name + #let [def-ident [current-module name]]] + (case (macro.get-symbol-ann (ident-for #.alias) metaV) + (#.Some real-def) + (do @ + [[realT realA realV] (macro.find-def real-def) + _ (moduleL.define def-ident [realT metaV realV])] + (wrap [])) + + _ + (do @ + [#let [def-name (referenceT.global def-ident)] + _ (//.save (r.set! def-name expressionO)) + expressionV (evalT.eval (@@ def-name)) + _ (moduleL.define def-ident [expressionT metaV expressionV]) + _ (if (macro.type? metaV) + (case (macro.declared-tags metaV) + #.Nil + (wrap []) + + tags + (moduleL.declare-tags tags (macro.export? metaV) (:! Type expressionV))) + (wrap [])) + #let [_ (log! (format "DEF " (%ident def-ident)))]] + (wrap [])) + ))) + +(def: #export (translate-program programO) + (-> Expression (Meta Statement)) + (macro.fail "translate-program NOT IMPLEMENTED YET")) diff --git a/new-luxc/source/luxc/lang/translation/r/structure.jvm.lux b/new-luxc/source/luxc/lang/translation/r/structure.jvm.lux new file mode 100644 index 000000000..16d144f93 --- /dev/null +++ b/new-luxc/source/luxc/lang/translation/r/structure.jvm.lux @@ -0,0 +1,31 @@ +(.module: + lux + (lux (control [monad #+ do]) + (data [text] + text/format) + [macro]) + (luxc ["&" lang] + (lang [synthesis #+ Synthesis] + (host [r #+ Expression Statement]))) + [//] + (// [".T" runtime])) + +(def: #export (translate-tuple translate elemsS+) + (-> (-> Synthesis (Meta Expression)) (List Synthesis) (Meta Expression)) + (case elemsS+ + #.Nil + (:: macro.Monad wrap runtimeT.unit) + + (#.Cons singletonS #.Nil) + (translate singletonS) + + _ + (do macro.Monad + [elemsT+ (monad.map @ translate elemsS+)] + (wrap (r.list elemsT+))))) + +(def: #export (translate-variant translate tag tail? valueS) + (-> (-> Synthesis (Meta Expression)) Nat Bool Synthesis (Meta Expression)) + (do macro.Monad + [valueT (translate valueS)] + (wrap (runtimeT.variant tag tail? valueT)))) diff --git a/new-luxc/test/test/luxc/common.lux b/new-luxc/test/test/luxc/common.lux index 49f294a68..7d4b156b8 100644 --- a/new-luxc/test/test/luxc/common.lux +++ b/new-luxc/test/test/luxc/common.lux @@ -33,7 +33,13 @@ (python [".T_python" expression] [".T_python" eval] [".T_python" runtime] - [".T_python" statement]))))) + [".T_python" statement]) + [r] + (r [".T_r" expression] + [".T_r" eval] + [".T_r" runtime] + [".T_r" statement]) + )))) (type: #export Runner (-> Synthesis (e.Error Top))) (type: #export Definer (-> Ident Synthesis (e.Error Top))) @@ -50,6 +56,7 @@ [init-lua lua.init] [init-ruby ruby.init] [init-python python.init] + [init-r r.init] ) (def: (runner translate-runtime translate-expression eval init) @@ -92,3 +99,6 @@ (def: #export run-python (runner runtimeT_python.translate expressionT_python.translate evalT_python.eval init-python)) (def: #export def-python (definer runtimeT_python.translate expressionT_python.translate evalT_python.eval init-python statementT_python.translate-def)) + +(def: #export run-r (runner runtimeT_r.translate expressionT_r.translate evalT_r.eval init-r)) +(def: #export def-r (definer runtimeT_r.translate expressionT_r.translate evalT_r.eval init-r statementT_r.translate-def)) diff --git a/new-luxc/test/test/luxc/lang/translation/case.lux b/new-luxc/test/test/luxc/lang/translation/case.lux index ca960dba4..04a373e42 100644 --- a/new-luxc/test/test/luxc/lang/translation/case.lux +++ b/new-luxc/test/test/luxc/lang/translation/case.lux @@ -113,3 +113,7 @@ (context: "[Python] Function." (<| (times +100) (pattern-matching-spec run-python))) + +(context: "[R] Pattern-matching." + (<| (times +100) + (pattern-matching-spec run-r))) diff --git a/new-luxc/test/test/luxc/lang/translation/common.lux b/new-luxc/test/test/luxc/lang/translation/common.lux index 6de3ad822..e29931667 100644 --- a/new-luxc/test/test/luxc/lang/translation/common.lux +++ b/new-luxc/test/test/luxc/lang/translation/common.lux @@ -729,3 +729,7 @@ (context: "[Python] Common procedures." (<| (times +100) (all-specs run-python))) + +(context: "[R] Common procedures." + (<| (times +100) + (all-specs run-r))) diff --git a/new-luxc/test/test/luxc/lang/translation/function.lux b/new-luxc/test/test/luxc/lang/translation/function.lux index d7505bf37..105072df7 100644 --- a/new-luxc/test/test/luxc/lang/translation/function.lux +++ b/new-luxc/test/test/luxc/lang/translation/function.lux @@ -106,3 +106,7 @@ (context: "[Python] Function." (<| (times +100) (function-spec run-python))) + +(context: "[R] Function." + (<| (times +100) + (function-spec run-r))) diff --git a/new-luxc/test/test/luxc/lang/translation/primitive.lux b/new-luxc/test/test/luxc/lang/translation/primitive.lux index 6d74d4fca..d410f29f0 100644 --- a/new-luxc/test/test/luxc/lang/translation/primitive.lux +++ b/new-luxc/test/test/luxc/lang/translation/primitive.lux @@ -75,3 +75,7 @@ (context: "[Python] Primitives." (<| (times +100) (spec run-python))) + +(context: "[R] Primitives." + (<| (times +100) + (spec run-r))) diff --git a/new-luxc/test/test/luxc/lang/translation/reference.lux b/new-luxc/test/test/luxc/lang/translation/reference.lux index 3c2b66b2d..6f27b75f2 100644 --- a/new-luxc/test/test/luxc/lang/translation/reference.lux +++ b/new-luxc/test/test/luxc/lang/translation/reference.lux @@ -16,7 +16,8 @@ (js [".T_js" statement]) (lua [".T_lua" statement]) (ruby [".T_ruby" statement]) - (python [".T_python" statement])))) + (python [".T_python" statement]) + (r [".T_r" statement])))) (test/luxc common)) (def: upper-alpha-ascii @@ -42,7 +43,8 @@ (i/= def-value (:! Int valueT)) (#e.Error error) - false))))) + (exec (log! error) + false)))))) (def: (variables-spec run) (-> Runner Test) @@ -84,3 +86,7 @@ (context: "[Python] References." (<| (times +100) (references-spec run-python def-python))) + +(context: "[R] References." + (<| (times +100) + (references-spec run-r def-r))) diff --git a/new-luxc/test/test/luxc/lang/translation/structure.lux b/new-luxc/test/test/luxc/lang/translation/structure.lux index bd2cdcbb4..deb015727 100644 --- a/new-luxc/test/test/luxc/lang/translation/structure.lux +++ b/new-luxc/test/test/luxc/lang/translation/structure.lux @@ -131,3 +131,7 @@ (context: "[Python] Structures." (<| (times +100) (structure-spec run-python))) + +(context: "[R] Structures." + (<| (times +100) + (structure-spec run-r))) -- cgit v1.2.3