From b14f95ca68887d9e6cea211b47e04e5ec00c05fa Mon Sep 17 00:00:00 2001 From: Eduardo Julian Date: Tue, 13 Mar 2018 23:28:19 -0400 Subject: - Initial Ruby back-end implementation. --- new-luxc/project.clj | 3 +- new-luxc/source/luxc/lang/host/ruby.lux | 219 +++++++ .../source/luxc/lang/translation/lua/eval.jvm.lux | 2 +- .../lang/translation/lua/procedure/common.jvm.lux | 2 +- .../luxc/lang/translation/lua/runtime.jvm.lux | 11 +- new-luxc/source/luxc/lang/translation/ruby.lux | 192 ++++++ .../source/luxc/lang/translation/ruby/case.jvm.lux | 174 ++++++ .../source/luxc/lang/translation/ruby/eval.jvm.lux | 121 ++++ .../luxc/lang/translation/ruby/expression.jvm.lux | 82 +++ .../luxc/lang/translation/ruby/function.jvm.lux | 79 +++ .../source/luxc/lang/translation/ruby/loop.jvm.lux | 35 ++ .../luxc/lang/translation/ruby/primitive.jvm.lux | 42 ++ .../luxc/lang/translation/ruby/procedure.jvm.lux | 28 + .../lang/translation/ruby/procedure/common.jvm.lux | 664 +++++++++++++++++++++ .../lang/translation/ruby/procedure/host.jvm.lux | 89 +++ .../luxc/lang/translation/ruby/reference.jvm.lux | 36 ++ .../luxc/lang/translation/ruby/runtime.jvm.lux | 385 ++++++++++++ .../luxc/lang/translation/ruby/statement.jvm.lux | 48 ++ .../luxc/lang/translation/ruby/structure.jvm.lux | 31 + new-luxc/test/test/luxc/common.lux | 10 +- new-luxc/test/test/luxc/lang/translation/case.lux | 11 +- .../test/test/luxc/lang/translation/common.lux | 10 +- .../test/test/luxc/lang/translation/function.lux | 19 +- .../test/test/luxc/lang/translation/primitive.lux | 4 + .../test/test/luxc/lang/translation/reference.lux | 56 +- .../test/test/luxc/lang/translation/structure.lux | 28 +- new-luxc/test/tests.lux | 9 +- 27 files changed, 2333 insertions(+), 57 deletions(-) create mode 100644 new-luxc/source/luxc/lang/host/ruby.lux create mode 100644 new-luxc/source/luxc/lang/translation/ruby.lux create mode 100644 new-luxc/source/luxc/lang/translation/ruby/case.jvm.lux create mode 100644 new-luxc/source/luxc/lang/translation/ruby/eval.jvm.lux create mode 100644 new-luxc/source/luxc/lang/translation/ruby/expression.jvm.lux create mode 100644 new-luxc/source/luxc/lang/translation/ruby/function.jvm.lux create mode 100644 new-luxc/source/luxc/lang/translation/ruby/loop.jvm.lux create mode 100644 new-luxc/source/luxc/lang/translation/ruby/primitive.jvm.lux create mode 100644 new-luxc/source/luxc/lang/translation/ruby/procedure.jvm.lux create mode 100644 new-luxc/source/luxc/lang/translation/ruby/procedure/common.jvm.lux create mode 100644 new-luxc/source/luxc/lang/translation/ruby/procedure/host.jvm.lux create mode 100644 new-luxc/source/luxc/lang/translation/ruby/reference.jvm.lux create mode 100644 new-luxc/source/luxc/lang/translation/ruby/runtime.jvm.lux create mode 100644 new-luxc/source/luxc/lang/translation/ruby/statement.jvm.lux create mode 100644 new-luxc/source/luxc/lang/translation/ruby/structure.jvm.lux diff --git a/new-luxc/project.clj b/new-luxc/project.clj index 1ada593e5..b35dc7c1a 100644 --- a/new-luxc/project.clj +++ b/new-luxc/project.clj @@ -19,7 +19,8 @@ :dependencies [[org.ow2.asm/asm-all "5.0.3"] [net.sandius.rembulan/rembulan-runtime "0.1-SNAPSHOT"] [net.sandius.rembulan/rembulan-stdlib "0.1-SNAPSHOT"] - [net.sandius.rembulan/rembulan-compiler "0.1-SNAPSHOT"]] + [net.sandius.rembulan/rembulan-compiler "0.1-SNAPSHOT"] + [org.jruby/jruby-complete "9.1.16.0"]] :source-paths ["source"] :test-paths ["test"] diff --git a/new-luxc/source/luxc/lang/host/ruby.lux b/new-luxc/source/luxc/lang/host/ruby.lux new file mode 100644 index 000000000..3f179105d --- /dev/null +++ b/new-luxc/source/luxc/lang/host/ruby.lux @@ -0,0 +1,219 @@ +(.module: + [lux #- not or and] + (lux (data [text] + text/format + (coll [list "list/" Functor Fold])))) + +(type: #export Ruby Text) + +(type: #export Expression Ruby) + +(type: #export Statement Ruby) + +(def: #export nil + Expression + "nil") + +(def: #export bool + (-> Bool Expression) + %b) + +(def: #export int + (-> Int Expression) + %i) + +(def: #export float + (-> Frac Expression) + %f) + +(def: #export (string value) + (-> Text Expression) + (%t value)) + +(def: #export splat + (-> Expression Expression) + (|>> (format "*"))) + +(def: #export (array-range from to array) + (-> Expression Expression Expression Expression) + (format "(" array "[" from ".." to "])")) + +(def: #export (array elements) + (-> (List Expression) Expression) + (format "([" (text.join-with "," elements) "])")) + +(def: #export (dictionary kvs) + (-> (List [Expression Expression]) Expression) + (format "({" + (|> kvs + (list/map (.function [[k v]] + (format k " => " v))) + (text.join-with ", ")) + "})")) + +(def: #export (apply func args) + (-> Expression (List Expression) Expression) + (format "(" func "(" (text.join-with "," args) ")" ")")) + +(def: #export (send method args object) + (-> Text (List Expression) Expression Expression) + (apply (format object "." method) args)) + +(def: #export call + (-> (List Expression) Expression Expression) + (send "call")) + +(def: #export (nth idx array) + (-> Expression Expression Expression) + (format "(" array "[" idx "])")) + +(def: #export (set-nth! idx value array) + (-> Expression Expression Expression Statement) + (format array "[" idx "] = " value ";")) + +(def: #export (field name object) + (-> Text Expression Expression) + (format "(" object "." name ")")) + +(def: #export (length array) + (-> Expression Expression) + (format "(" array ".length)")) + +(def: #export (set! vars value) + (-> (List Text) Expression Statement) + (format (text.join-with ", " vars) " = " value ";")) + +(def: #export (global var) + (-> Text Expression) + (format "$" var)) + +(def: #export (global! var value) + (-> Text Expression Statement) + (set! (list (global var)) value)) + +(def: #export (? test then! else!) + (-> Expression Expression Expression Expression) + (format "(" test " ? " then! " : " else! ")")) + +(def: #export (if! test then! else!) + (-> Expression Statement Statement Statement) + (format "if " test + "\n" then! + "\n" "else" + "\n" else! + "\n" "end;")) + +(def: #export (when! test then!) + (-> Expression Statement Statement) + (format "if " test + "\n" then! + "\n" "end;")) + +(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 (block! statements) + (-> (List Statement) Statement) + (text.join-with " " statements)) + +(def: #export (statement expression) + (-> Expression Statement) + (format expression ";")) + +(def: #export (while! test body) + (-> Expression Statement Statement) + (format "while " test + "\n" body + "\n" "end;")) + +(def: #export (for-in! var array body) + (-> Text Expression Statement Statement) + (format "for " var " in " array "do" "\n" + body "\n" + "end;" "\n")) + +(def: #export (begin! body rescues) + (-> Statement (List [(List Text) Text Statement]) Statement) + (format "begin" + "\n" body "\n" + (|> rescues + (list/map (function [[ex-classes ex-value ex-handler]] + (format "rescue " (text.join-with ", " ex-classes) + (case ex-value + "" "" + _ (format " => " ex-value)) + "\n" + ex-handler))) + (text.join-with "\n")) + "\n" "end;")) + +(def: #export (raise message) + (-> Expression Expression) + (format "raise " message ";")) + +(def: #export (return! value) + (-> Expression Statement) + (format "return " value ";")) + +(def: #export (function! name args body) + (-> Text (List Text) Statement Statement) + (format "def " name "(" (text.join-with "," args) ")\n" + body + "\n" "end;")) + +(def: #export (lambda name args body) + (-> (Maybe Text) (List Text) Statement Expression) + (let [proc (format "lambda {" (format "|" (text.join-with ", " args) "|") " " body "}")] + (case name + #.None + (format "(" proc ")") + + (#.Some name) + (format "(" name " = " proc ")")))) + +(do-template [ ] + [(def: #export ( param subject) + (-> Expression Expression Expression) + (format "(" subject " " " " param ")"))] + + [= "=="] + [< "<"] + [<= "<="] + [> ">"] + [>= ">="] + [+ "+"] + [- "-"] + [* "*"] + [/ "/"] + [% "%"] + [pow "**"] + ) + +(do-template [ ] + [(def: #export ( param subject) + (-> Expression Expression Expression) + (format "(" param " " " " subject ")"))] + + [or "||"] + [and "&&"] + [bit-or "|"] + [bit-and "&"] + [bit-xor "^"] + ) + +(do-template [ ] + [(def: #export ( param subject) + (-> Expression Expression Expression) + (format "(" subject " " " " param ")"))] + + [bit-shl "<<"] + [bit-shr ">>"] + ) + +(def: #export (not subject) + (-> Expression Expression) + (format "(!" subject ")")) diff --git a/new-luxc/source/luxc/lang/translation/lua/eval.jvm.lux b/new-luxc/source/luxc/lang/translation/lua/eval.jvm.lux index 331ec857d..c42ba0668 100644 --- a/new-luxc/source/luxc/lang/translation/lua/eval.jvm.lux +++ b/new-luxc/source/luxc/lang/translation/lua/eval.jvm.lux @@ -8,7 +8,7 @@ (coll [array])) [host]) (luxc [lang] - (lang (host [js #+ JS Expression Statement]))) + (lang (host [lua #+ Lua Expression Statement]))) [//]) (host.import java/lang/Object diff --git a/new-luxc/source/luxc/lang/translation/lua/procedure/common.jvm.lux b/new-luxc/source/luxc/lang/translation/lua/procedure/common.jvm.lux index 2b277dec4..77e57a5db 100644 --- a/new-luxc/source/luxc/lang/translation/lua/procedure/common.jvm.lux +++ b/new-luxc/source/luxc/lang/translation/lua/procedure/common.jvm.lux @@ -176,7 +176,7 @@ (def: (array//remove [arrayO idxO]) Binary - (runtimeT.array//remove arrayO idxO)) + (runtimeT.array//put arrayO idxO runtimeT.unit)) (def: array//size Unary 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 b5e2147e0..50b8008dd 100644 --- a/new-luxc/source/luxc/lang/translation/lua/runtime.jvm.lux +++ b/new-luxc/source/luxc/lang/translation/lua/runtime.jvm.lux @@ -19,8 +19,8 @@ (def: (flag value) (-> Bool Lua) (if value - (%t "") - "null")) + (lua.string "") + lua.nil)) (def: (variant' tag last? value) (-> Expression Expression Expression Expression) @@ -111,7 +111,7 @@ (runtime: (lux//program-args program-args) (lua.block! (list (lua.local! "inputs" (#.Some none)) - (lua.for-step! "idx" (lua.int 1) (lua.length program-args) (lua.int 1) + (lua.for-step! "idx" (lua.length program-args) (lua.int 1) (lua.int -1) (lua.set! "inputs" (some (lua.array (list (lua.nth "idx" program-args) "inputs"))))) (lua.return! "inputs")))) @@ -378,17 +378,14 @@ (lua.block! (list (lua.set! (lua.nth idx array) value) (lua.return! array))))) -(runtime: (array//remove array idx) - (array//put array idx unit)) - (def: runtime//array Runtime (format @@array//sub @@array//concat @@array//copy + @@array//new @@array//get @@array//put - @@array//remove )) (def: #export atom//field Text "_lux_atom") diff --git a/new-luxc/source/luxc/lang/translation/ruby.lux b/new-luxc/source/luxc/lang/translation/ruby.lux new file mode 100644 index 000000000..8f00c0ecd --- /dev/null +++ b/new-luxc/source/luxc/lang/translation/ruby.lux @@ -0,0 +1,192 @@ +(.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 [ruby #+ Ruby Expression Statement])) + [".C" io])) + +(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 org/jruby/embed/ScriptingContainer + (new []) + (runScriptlet [String] #? Object)) + +(type: #export Anchor [Text Register]) + +(type: #export Host + {#context [Text Nat] + #anchor (Maybe Anchor) + #interpreter (-> Text (Error Top)) + #module-buffer (Maybe StringBuilder) + #program-buffer StringBuilder}) + +(def: #export init + (IO Host) + (io {#context ["" +0] + #anchor #.None + #interpreter (let [interpreter (ScriptingContainer::new [])] + (function [code] + ("lux try" (io (: Top (maybe.default [] (ScriptingContainer::runScriptlet [code] interpreter))))))) + #module-buffer #.None + #program-buffer (StringBuilder::new [])})) + +(def: #export ruby-module-name Text "module.rb") + +(def: #export init-module-buffer + (Meta Unit) + (function [compiler] + (#e.Success [(update@ #.host + (|>> (:! Host) + (set@ #module-buffer (#.Some (StringBuilder::new []))) + (:! Void)) + compiler) + []]))) + +(exception: #export No-Active-Module-Buffer) +(exception: #export Cannot-Execute) + +(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 "___" (%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))))) + +(exception: #export No-Anchor) + +(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.fail (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))]))) + +(def: (execute code) + (-> Expression (Meta Unit)) + (function [compiler] + (let [interpreter (|> compiler (get@ #.host) (:! Host) (get@ #interpreter))] + (case (interpreter code) + (#e.Error error) + ((lang.fail (Cannot-Execute error)) compiler) + + (#e.Success _) + (#e.Success [compiler []]))))) + +(exception: #export Unknown-Member) + +(def: #export variant-tag-field "_lux_tag") +(def: #export variant-flag-field "_lux_flag") +(def: #export variant-value-field "_lux_value") + +(def: #export unit Text "\u0000") + +(def: #export (definition-name [module name]) + (-> Ident Text) + (lang.normalize-name (format module "$" name))) + +(def: #export (save code) + (-> Ruby (Meta Unit)) + (do macro.Monad + [module-buffer module-buffer + #let [_ (Appendable::append [(:! CharSequence code)] + module-buffer)]] + (execute code))) + +(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) "/" ruby-module-name) + (|> module-code + (String::getBytes ["UTF-8"]) + e.assume))))) diff --git a/new-luxc/source/luxc/lang/translation/ruby/case.jvm.lux b/new-luxc/source/luxc/lang/translation/ruby/case.jvm.lux new file mode 100644 index 000000000..016038d03 --- /dev/null +++ b/new-luxc/source/luxc/lang/translation/ruby/case.jvm.lux @@ -0,0 +1,174 @@ +(.module: + lux + (lux (control [monad #+ do] + ["ex" exception #+ exception:]) + (data text/format + (coll [list "list/" Fold])) + [macro #+ "meta/" Monad]) + (luxc [lang] + (lang ["ls" synthesis] + (host [ruby #+ Ruby Expression Statement]))) + [//] + (// [".T" runtime] + [".T" primitive] + [".T" reference])) + +(def: (expression-block body) + (-> Statement Expression) + (ruby.call (list) + (ruby.lambda #.None (list) + body))) + +(def: #export (translate-let translate register valueS bodyS) + (-> (-> ls.Synthesis (Meta Expression)) Nat ls.Synthesis ls.Synthesis + (Meta Expression)) + (do macro.Monad + [valueO (translate valueS) + bodyO (translate bodyS)] + (wrap (expression-block + (ruby.block! (list (ruby.set! (list (referenceT.variable register)) valueO) + (ruby.return! bodyO))))))) + +(def: #export (translate-record-get translate valueS path) + (-> (-> ls.Synthesis (Meta Expression)) ls.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 (ruby.int (:! Int idx))))) + valueO + path)))) + +(def: #export (translate-if testO thenO elseO) + (-> Expression Expression Expression Expression) + (expression-block + (ruby.if! testO + (ruby.return! thenO) + (ruby.return! elseO)))) + +(def: savepoint + Expression + "pm_cursor_savepoint") + +(def: cursor + Expression + "pm_cursor") + +(def: (push-cursor! value) + (-> Expression Statement) + (ruby.statement (ruby.send "push" (list value) cursor))) + +(def: save-cursor! + Statement + (ruby.statement + (ruby.send "push" + (list (ruby.array-range (ruby.int 0) (ruby.int -1) cursor)) + savepoint))) + +(def: restore-cursor! + Statement + (ruby.set! (list cursor) (ruby.send "pop" (list) savepoint))) + +(def: cursor-top + Expression + (ruby.nth (ruby.- (ruby.int 1) + (ruby.length cursor)) + cursor)) + +(def: pop-cursor! + Statement + (ruby.statement (ruby.send "pop" (list) cursor))) + +(def: pm-error + Expression + (ruby.string "PM-ERROR")) + +(exception: #export Unrecognized-Path) + +(def: (translate-pattern-matching' translate path) + (-> (-> ls.Synthesis (Meta Expression)) Code (Meta Expression)) + (case path + (^code ("lux case exec" (~ bodyS))) + (do macro.Monad + [bodyO (translate bodyS)] + (wrap (ruby.return! bodyO))) + + (^code ("lux case pop")) + (meta/wrap pop-cursor!) + + (^code ("lux case bind" (~ [_ (#.Nat register)]))) + (meta/wrap (ruby.set! (list (referenceT.variable register)) cursor-top)) + + (^template [ ] + [_ ( value)] + (meta/wrap (ruby.when! (ruby.not (ruby.= (|> value ) cursor-top)) + (ruby.raise pm-error)))) + ([#.Nat (<| ruby.int (:! Int))] + [#.Int ruby.int] + [#.Deg (<| ruby.int (:! Int))] + [#.Bool ruby.bool] + [#.Frac ruby.float] + [#.Text ruby.string]) + + (^template [ ] + (^code ( (~ [_ (#.Nat idx)]))) + (meta/wrap (push-cursor! ( cursor-top (ruby.int (:! Int idx)))))) + (["lux case tuple left" runtimeT.product//left] + ["lux case tuple right" runtimeT.product//right]) + + (^template [ ] + (^code ( (~ [_ (#.Nat idx)]))) + (meta/wrap (ruby.block! (list (ruby.set! (list "temp") (runtimeT.sum//get cursor-top (ruby.int (:! Int idx)) )) + (ruby.if! (ruby.not (ruby.= ruby.nil "temp")) + (push-cursor! "temp") + (ruby.raise pm-error)))))) + (["lux case variant left" ruby.nil] + ["lux case variant right" (ruby.string "")]) + + (^code ("lux case seq" (~ leftP) (~ rightP))) + (do macro.Monad + [leftO (translate-pattern-matching' translate leftP) + rightO (translate-pattern-matching' translate rightP)] + (wrap (ruby.block! (list leftO rightO)))) + + (^code ("lux case alt" (~ leftP) (~ rightP))) + (do macro.Monad + [leftO (translate-pattern-matching' translate leftP) + rightO (translate-pattern-matching' translate rightP)] + (wrap (ruby.begin! (ruby.block! (list save-cursor! + leftO)) + (list [(list) "alt_error" (ruby.if! (ruby.= pm-error (ruby.field "message" "alt_error")) + (ruby.block! (list restore-cursor! + rightO)) + (ruby.raise "alt_error"))])))) + + _ + (lang.throw Unrecognized-Path (%code path)) + )) + +(def: (translate-pattern-matching translate path) + (-> (-> ls.Synthesis (Meta Expression)) Code (Meta Expression)) + (do macro.Monad + [pattern-matching (translate-pattern-matching' translate path)] + (wrap (ruby.begin! pattern-matching + (list [(list) "alt_error" + (ruby.if! (ruby.= pm-error (ruby.field "message" "alt_error")) + (ruby.raise (ruby.string "Invalid expression for pattern-matching.")) + (ruby.raise "alt_error"))]))))) + +(def: (initialize-pattern-matching stack-init) + (-> Expression Statement) + (ruby.block! (list (ruby.set! (list cursor) (ruby.array (list stack-init))) + (ruby.set! (list savepoint) (ruby.array (list)))))) + +(def: #export (translate-case translate valueS path) + (-> (-> ls.Synthesis (Meta Expression)) ls.Synthesis Code (Meta Expression)) + (do macro.Monad + [valueO (translate valueS) + pattern-matching (translate-pattern-matching translate path)] + (wrap (expression-block + (ruby.block! (list (initialize-pattern-matching valueO) + pattern-matching)))))) diff --git a/new-luxc/source/luxc/lang/translation/ruby/eval.jvm.lux b/new-luxc/source/luxc/lang/translation/ruby/eval.jvm.lux new file mode 100644 index 000000000..bce63ce9c --- /dev/null +++ b/new-luxc/source/luxc/lang/translation/ruby/eval.jvm.lux @@ -0,0 +1,121 @@ +(.module: + lux + (lux (control ["ex" exception #+ exception:]) + (data [bit] + [maybe] + ["e" error #+ Error] + text/format + (coll [array])) + [host]) + (luxc [lang] + (lang (host [ruby #+ Ruby Expression Statement]))) + [//]) + +(host.import java/lang/Object + (toString [] String) + (getClass [] (Class Object))) + +(host.import java/lang/Long + (intValue [] Integer)) + +(host.import org/jruby/RubyArray + (getLength [] int) + (get [int] #? Object)) + +(host.import org/jruby/RubyHash + (get [Object] #? Object)) + +(def: (tuple lux-object host-object) + (-> (-> Object (Error Top)) RubyArray (Error Top)) + (let [size (:! Nat (RubyArray::getLength [] host-object))] + (loop [idx +0 + output (:! (Array Top) (array.new size))] + (if (n/< size idx) + (case (RubyArray::get [(:! Int idx)] host-object) + #.None + (recur (n/inc idx) output) + + (#.Some value) + (case (lux-object value) + (#e.Error error) + (#e.Error error) + + (#e.Success lux-value) + (recur (n/inc idx) (array.write idx lux-value output)))) + (#e.Success output))))) + +(exception: #export Not-A-Variant) + +(def: (variant lux-object host-object) + (-> (-> Object (Error Top)) RubyHash (Error Top)) + (case [(RubyHash::get [(:! Object //.variant-tag-field)] host-object) + (RubyHash::get [(:! Object //.variant-flag-field)] host-object) + (RubyHash::get [(:! Object //.variant-value-field)] host-object)] + (^multi [(#.Some tag) ?flag (#.Some value)] + [(lux-object value) + (#.Some value)]) + (#e.Success [(Long::intValue [] (:! Long tag)) + (: Top (case ?flag (#.Some _) "" #.None (host.null))) + value]) + + _ + (ex.throw Not-A-Variant ""))) + +(exception: #export Unknown-Kind-Of-Host-Object) +(exception: #export Null-Has-No-Lux-Representation) + +(def: (lux-object host-object) + (-> Object (Error Top)) + (`` (cond (host.null? host-object) + (ex.throw Null-Has-No-Lux-Representation "") + + (or (host.instance? java/lang/Boolean host-object) + (host.instance? java/lang/Long host-object) + (host.instance? java/lang/Double host-object) + (host.instance? java/lang/String host-object)) + (ex.return host-object) + + (host.instance? org/jruby/RubyArray host-object) + (tuple lux-object (:! RubyArray host-object)) + + (host.instance? org/jruby/RubyHash host-object) + (case (variant lux-object (:! RubyHash host-object)) + (#e.Success value) + (#e.Success value) + + _ + (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)))) + + ## 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))) + ))) + +(exception: #export Cannot-Evaluate) + +(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" + "<< " code "\n" + error)) + ((lang.throw Cannot-Evaluate error) compiler)) + + (#e.Success output) + (case (lux-object (:! Object output)) + (#e.Success parsed-output) + (exec ## (log! (format "eval #e.Success\n" + ## "<< " code)) + (#e.Success [compiler parsed-output])) + + (#e.Error error) + (exec (log! (format "eval #e.Error\n" + "<< " code "\n" + error)) + ((lang.throw Cannot-Evaluate error) compiler))))))) diff --git a/new-luxc/source/luxc/lang/translation/ruby/expression.jvm.lux b/new-luxc/source/luxc/lang/translation/ruby/expression.jvm.lux new file mode 100644 index 000000000..d0e42c22d --- /dev/null +++ b/new-luxc/source/luxc/lang/translation/ruby/expression.jvm.lux @@ -0,0 +1,82 @@ +(.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 [ruby #+ Ruby Expression Statement]))) + [//] + (// [".T" runtime] + [".T" primitive] + [".T" structure] + [".T" function] + [".T" reference] + [".T" case] + [".T" procedure])) + +(exception: #export Invalid-Function-Syntax) +(exception: #export Unrecognized-Synthesis) + +(def: #export (translate synthesis) + (-> ls.Synthesis (Meta Expression)) + (case synthesis + (^code []) + (:: macro.Monad wrap runtimeT.unit) + + (^code [(~ singleton)]) + (translate singleton) + + (^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 [(~+ 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/ruby/function.jvm.lux b/new-luxc/source/luxc/lang/translation/ruby/function.jvm.lux new file mode 100644 index 000000000..ba349dedd --- /dev/null +++ b/new-luxc/source/luxc/lang/translation/ruby/function.jvm.lux @@ -0,0 +1,79 @@ +(.module: + lux + (lux (control [monad #+ do]) + (data [product] + [text] + text/format + (coll [list "list/" Functor])) + [macro]) + (luxc ["&" lang] + (lang ["ls" synthesis] + [".L" variable #+ Variable Register] + (host [ruby #+ Ruby Expression Statement]))) + [//] + (// [".T" reference] + [".T" runtime])) + +(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 (ruby.call argsO+ functionO)))) + +(def: (input-declaration registers) + (-> (List Register) Statement) + (ruby.set! (list.concat (list (list/map (|>> n/inc referenceT.variable) registers) + (list "_"))) + "curried")) + +(def: (with-closure inits function-definition) + (-> (List Expression) Statement Expression) + (case inits + #.Nil + function-definition + + _ + (ruby.call inits + (ruby.lambda #.None + (|> (list.enumerate inits) + (list/map (|>> product.left referenceT.closure))) + (ruby.return! function-definition))))) + +(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-initsO+ (input-declaration (list.n/range +0 (n/dec arity))) + selfO (ruby.set! (list (referenceT.variable +0)) function-name) + arityO (|> arity nat-to-int %i) + limitO (|> arity n/dec nat-to-int %i)]] + (wrap (with-closure closureO+ + (ruby.lambda (#.Some function-name) + (list (ruby.splat "curried")) + (ruby.block! (list (ruby.set! (list "num_args") (ruby.length "curried")) + (ruby.if! (ruby.= arityO "num_args") + (ruby.block! (list selfO + args-initsO+ + (ruby.while! (ruby.bool true) + (ruby.return! bodyO)))) + (ruby.return! (let [recur (function [args] (ruby.call (list args) function-name))] + (ruby.? (ruby.> arityO "num_args") + (let [slice (function [from to] + (ruby.array-range from to "curried")) + arity-args (ruby.splat (slice (ruby.int 0) limitO)) + output-func-args (ruby.splat (slice arityO "num_args"))] + (ruby.call (list output-func-args) + (recur arity-args))) + (ruby.lambda #.None + (list (ruby.splat "extra")) + (recur (ruby.splat (|> (ruby.array (list)) + (ruby.send "concat" (list "curried")) + (ruby.send "concat" (list "extra"))))))))))))))))) diff --git a/new-luxc/source/luxc/lang/translation/ruby/loop.jvm.lux b/new-luxc/source/luxc/lang/translation/ruby/loop.jvm.lux new file mode 100644 index 000000000..e4da02c2a --- /dev/null +++ b/new-luxc/source/luxc/lang/translation/ruby/loop.jvm.lux @@ -0,0 +1,35 @@ +(.module: + lux + (lux (control [monad #+ do]) + (data [text] + text/format + (coll [list "list/" Functor])) + [macro]) + (luxc [lang] + (lang ["ls" synthesis] + (host [ruby #+ Ruby 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 (:: @ map (|>> %code lang.normalize-name) + (macro.gensym "loop")) + initsO+ (monad.map @ translate initsS+) + bodyO (//.with-anchor [loop-name offset] + (translate bodyS)) + #let [registersO+ (|> (list.n/range +0 (n/dec (list.size initsS+))) + (list/map (|>> (n/+ offset) referenceT.variable)))] + _ (//.save (ruby.function! loop-name registersO+ + (ruby.return! bodyO)))] + (wrap (ruby.apply loop-name initsO+)))) + +(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 (ruby.apply loop-name argsO+)))) diff --git a/new-luxc/source/luxc/lang/translation/ruby/primitive.jvm.lux b/new-luxc/source/luxc/lang/translation/ruby/primitive.jvm.lux new file mode 100644 index 000000000..15e68d8c6 --- /dev/null +++ b/new-luxc/source/luxc/lang/translation/ruby/primitive.jvm.lux @@ -0,0 +1,42 @@ +(.module: + lux + (lux (control pipe) + (data [number] + text/format) + [macro "meta/" Monad]) + (luxc (lang (host [ruby #+ Ruby Expression Statement])))) + +(def: #export translate-bool + (-> Bool (Meta Expression)) + (|>> %b meta/wrap)) + +(def: #export translate-int + (-> Int (Meta Expression)) + (|>> %i meta/wrap)) + +(def: #export translate-nat + (-> Nat (Meta Expression)) + (|>> (:! Int) %i meta/wrap)) + +(def: #export translate-deg + (-> Deg (Meta Expression)) + (|>> (:! Int) %i meta/wrap)) + +(def: #export translate-frac + (-> Frac (Meta Expression)) + (|>> (cond> [(f/= number.positive-infinity)] + [(new> "(1/0)")] + + [(f/= number.negative-infinity)] + [(new> "(-1/0)")] + + [(f/= number.not-a-number)] + [(new> "(0/0)")] + + ## else + [%f]) + meta/wrap)) + +(def: #export translate-text + (-> Text (Meta Expression)) + (|>> %t meta/wrap)) diff --git a/new-luxc/source/luxc/lang/translation/ruby/procedure.jvm.lux b/new-luxc/source/luxc/lang/translation/ruby/procedure.jvm.lux new file mode 100644 index 000000000..e7121ac98 --- /dev/null +++ b/new-luxc/source/luxc/lang/translation/ruby/procedure.jvm.lux @@ -0,0 +1,28 @@ +(.module: + lux + (lux (control [monad #+ do] + ["ex" exception #+ exception:]) + (data [maybe] + text/format + (coll [dict]))) + (luxc ["&" lang] + (lang ["ls" synthesis] + (host [ruby #+ Ruby Expression Statement]))) + [//] + (/ ["/." common] + ["/." host])) + +(exception: #export Unknown-Procedure) + +(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/ruby/procedure/common.jvm.lux b/new-luxc/source/luxc/lang/translation/ruby/procedure/common.jvm.lux new file mode 100644 index 000000000..0fc0029eb --- /dev/null +++ b/new-luxc/source/luxc/lang/translation/ruby/procedure/common.jvm.lux @@ -0,0 +1,664 @@ +(.module: + lux + (lux (control [monad #+ do] + ["ex" exception #+ exception:] + ["p" parser]) + (data ["e" error] + [text] + text/format + (coll [list "list/" Functor] + [dict #+ Dict])) + [macro #+ with-gensyms] + (macro [code] + ["s" syntax #+ syntax:]) + [host]) + (luxc ["&" lang] + (lang ["la" analysis] + ["ls" synthesis] + (host [ruby #+ Ruby 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!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!name)] + (function [(~ 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 + (ruby.= leftO rightO)) + +(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) +(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 ruby.bit-and] + [bit//or ruby.bit-or] + [bit//xor ruby.bit-xor] + ) + +(def: (bit//shift-left [subjectO paramO]) + Binary + (ruby.bit-and "0xFFFFFFFFFFFFFFFF" + (ruby.bit-shl paramO subjectO))) + +(do-template [ ] + [(def: ( [subjectO paramO]) + Binary + ( paramO subjectO))] + + [bit//shift-right ruby.bit-shr] + [bit//unsigned-shift-right runtimeT.bit//shift-right] + ) + +(def: bit//count + Unary + runtimeT.bit//count) + +(def: bit-procs + Bundle + (<| (prefix "bit") + (|> (dict.new text.Hash) + (install "count" (unary 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//unsigned-shift-right)) + (install "shift-right" (binary bit//shift-right)) + ))) + +## [[Arrays]] +(def: (array//new sizeO) + Unary + (ruby.apply "Array.new" (list sizeO))) + +(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 ruby.nil)) + +(def: array//size + Unary + ruby.length) + +(def: array-procs + Bundle + (<| (prefix "array") + (|> (dict.new text.Hash) + (install "new" (unary array//new)) + (install "get" (binary array//get)) + (install "put" (trinary array//put)) + (install "remove" (binary array//remove)) + (install "size" (unary array//size)) + ))) + +## [[Numbers]] +(host.import java/lang/Double + (#static MIN_VALUE Double) + (#static MAX_VALUE Double)) + +(do-template [ ] + [(def: ( _) + Nullary + ( ))] + + [nat//min 0 ruby.int] + [nat//max -1 ruby.int] + + [frac//smallest Double::MIN_VALUE ruby.float] + [frac//min (f/* -1.0 Double::MAX_VALUE) ruby.float] + [frac//max Double::MAX_VALUE ruby.float] + + [deg//min 0 ruby.int] + [deg//max -1 ruby.int] + ) + +(do-template [ ] + [(def: ( _) + Nullary + )] + + [int//min (|> (ruby.int -2) (ruby.pow (ruby.int 63)))] + [int//max (|> (ruby.int 2) (ruby.pow (ruby.int 63)) (ruby.- (ruby.int 1)))] + ) + +(do-template [ ] + [(def: ( _) + Nullary + )] + + [frac//not-a-number (ruby./ (ruby.float 0.0) (ruby.float 0.0))] + [frac//positive-infinity (ruby./ (ruby.float 0.0) (ruby.float 1.0))] + [frac//negative-infinity (ruby./ (ruby.float 0.0) (ruby.float -1.0))] + ) + +(do-template [ ] + [(def: ( [subjectO paramO]) + Binary + (ruby.bit-and "0xFFFFFFFFFFFFFFFF" + ( paramO subjectO)))] + + [int//add ruby.+] + [int//sub ruby.-] + [int//mul ruby.*] + ) + +(do-template [ ] + [(def: ( [subjectO paramO]) + Binary + ( paramO subjectO))] + + [int//div ruby./] + [int//rem ruby.%] + + [nat//add ruby.+] + [nat//sub ruby.-] + [nat//mul ruby.*] + [nat//div runtimeT.nat///] + [nat//rem runtimeT.nat//%] + + [deg//add ruby.+] + [deg//sub ruby.-] + [deg//mul runtimeT.deg//*] + [deg//div runtimeT.deg///] + [deg//rem ruby.-] + [deg//scale ruby.*] + [deg//reciprocal ruby./] + ) + +(do-template [ ] + [(def: ( [subjectO paramO]) + Binary + ( paramO subjectO))] + + [frac//add ruby.+] + [frac//sub ruby.-] + [frac//mul ruby.*] + [frac//div ruby./] + [frac//rem ruby.%] + [frac//= ruby.=] + [frac//< ruby.<] + + [text//= ruby.=] + [text//< ruby.<] + ) + +(do-template [ ] + [(def: ( [subjectO paramO]) + Binary + ( paramO subjectO))] + + [nat//= ruby.=] + [nat//< runtimeT.nat//<] + [int//= ruby.=] + [int//< ruby.<] + [deg//= ruby.=] + [deg//< runtimeT.nat//<]) + +(do-template [] + [(def: ( inputO) + Unary + inputO)] + + [nat//to-int] + [int//to-nat] + ) + +(def: frac//encode + Unary + (ruby.send "to_s" (list))) + +(def: (frac//decode inputO) + Unary + (ruby.call (list) + (ruby.lambda #.None (list) + (ruby.block! (list (ruby.set! (list "input") inputO) + (ruby.set! (list "temp") (ruby.send "to_f" (list) "input")) + (ruby.if! (ruby.or (ruby.not (ruby.= (ruby.float 0.0) "temp")) + (ruby.or (ruby.= (ruby.string "0") "input") + (ruby.= (ruby.string "0.0") "input"))) + (ruby.return! (runtimeT.some "temp")) + (ruby.return! runtimeT.none))))))) + +(do-template [ ] + [(def: ( inputO) + Unary + (ruby./ inputO))] + + [int//to-frac (ruby.float 1.0)] + [deg//to-frac (ruby.send "to_f" (list) + (ruby.bit-shl (ruby.int 32) (ruby.int 1)))] + ) + +(do-template [ ] + [(def: + Unary + )] + + [frac//to-int (ruby.send "floor" (list))] + [frac//to-deg runtimeT.deg//from-frac] + ) + +(def: nat//char + Unary + (ruby.send "chr" (list))) + +(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 nat//to-int)) + (install "char" (unary nat//char))))) + +(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 int//to-nat)) + (install "to-frac" (unary int//to-frac))))) + +(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 deg//to-frac))))) + +(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 frac//to-deg)) + (install "to-int" (unary frac//to-int)) + (install "encode" (unary frac//encode)) + (install "decode" (unary frac//decode))))) + +## [[Text]] +(do-template [ ] + [(def: + Unary + (ruby.send (list)))] + + [text//size "length"] + [text//upper "upcase"] + [text//lower "downcase"] + [text//trim "strip"] + [text//hash "hash"] + ) + +(def: (text//concat [subjectO paramO]) + Binary + (|> subjectO (ruby.+ paramO))) + +(def: (text//contains? [subjectO paramO]) + Binary + (ruby.send "include?" (list paramO) subjectO)) + +(def: (text//char [subjectO paramO]) + Binary + (runtimeT.text//char subjectO paramO)) + +(do-template [ ] + [(def: ( [subjectO paramO extraO]) + Trinary + (ruby.send (list paramO extraO) subjectO))] + + [text//replace-all "gsub"] + [text//replace-once "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 text//size)) + (install "hash" (unary 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 text//upper)) + (install "lower" (unary text//lower)) + ))) + +## [[Math]] +(do-template [ ] + [(def: + Unary + (|>> (list) (ruby.apply )))] + + [math//cos "Math.cos"] + [math//sin "Math.sin"] + [math//tan "Math.tan"] + [math//acos "Math.acos"] + [math//asin "Math.asin"] + [math//atan "Math.atan"] + [math//exp "Math.exp"] + [math//log "Math.log"] + ) + +(do-template [ ] + [(def: + Unary + (ruby.send (list)))] + + [math//ceil "ceil"] + [math//floor "floor"] + ) + +(def: (math//pow [inputO paramO]) + Binary + (ruby.pow paramO inputO)) + +(def: math-procs + Bundle + (<| (prefix "math") + (|> (dict.new text.Hash) + (install "cos" (unary math//cos)) + (install "sin" (unary math//sin)) + (install "tan" (unary math//tan)) + (install "acos" (unary math//acos)) + (install "asin" (unary math//asin)) + (install "atan" (unary math//atan)) + (install "exp" (unary math//exp)) + (install "log" (unary math//log)) + (install "ceil" (unary math//ceil)) + (install "floor" (unary math//floor)) + (install "pow" (binary math//pow)) + ))) + +## [[IO]] +(def: (io//log messageO) + Unary + (ruby.or (ruby.apply "puts" (list (ruby.+ (ruby.string "\n") messageO))) + runtimeT.unit)) + +(def: io//error + Unary + ruby.raise) + +(def: io//exit + Unary + (|>> (list) (ruby.apply "exit"))) + +(def: (io//current-time []) + Nullary + (|> "Time" + (ruby.send "now" (list)) + (ruby.send "to_f" (list)) + (ruby.* (ruby.float 1000.0)) + (ruby.send "to_i" (list)))) + +(def: io-procs + Bundle + (<| (prefix "io") + (|> (dict.new text.Hash) + (install "log" (unary io//log)) + (install "error" (unary io//error)) + (install "exit" (unary io//exit)) + (install "current-time" (nullary io//current-time))))) + +## [[Atoms]] +(def: atom//new + Unary + (|>> [(ruby.string runtimeT.atom//field)] (list) ruby.dictionary)) + +(def: atom//read + Unary + (ruby.nth (ruby.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) ruby.array)) + +(def: box//read + Unary + (ruby.nth (ruby.int 0))) + +(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 + (ruby.int 1)) + +(def: process//future + Unary + runtimeT.process//future) + +(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 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/ruby/procedure/host.jvm.lux b/new-luxc/source/luxc/lang/translation/ruby/procedure/host.jvm.lux new file mode 100644 index 000000000..c1b43da2f --- /dev/null +++ b/new-luxc/source/luxc/lang/translation/ruby/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/ruby/reference.jvm.lux b/new-luxc/source/luxc/lang/translation/ruby/reference.jvm.lux new file mode 100644 index 000000000..9612cdb7a --- /dev/null +++ b/new-luxc/source/luxc/lang/translation/ruby/reference.jvm.lux @@ -0,0 +1,36 @@ +(.module: + lux + (lux [macro] + (data [text] + text/format)) + (luxc ["&" lang] + (lang [".L" variable #+ Variable Register] + (host [ruby #+ Ruby Expression Statement]))) + [//] + (// [".T" runtime])) + +(do-template [ ] + [(def: #export ( register) + (-> Register Expression) + (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 (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 Expression) + //.definition-name) + +(def: #export (translate-definition name) + (-> Ident (Meta Expression)) + (:: macro.Monad wrap (ruby.global (global name)))) diff --git a/new-luxc/source/luxc/lang/translation/ruby/runtime.jvm.lux b/new-luxc/source/luxc/lang/translation/ruby/runtime.jvm.lux new file mode 100644 index 000000000..190b9cf6a --- /dev/null +++ b/new-luxc/source/luxc/lang/translation/ruby/runtime.jvm.lux @@ -0,0 +1,385 @@ +(.module: + lux + (lux (control ["p" parser "p/" Monad] + [monad #+ do]) + (data text/format + (coll [list "list/" Monad])) + [macro] + (macro [code] + ["s" syntax #+ syntax:]) + [io #+ Process]) + [//] + (luxc [lang] + (lang (host [ruby #+ Ruby Expression Statement])))) + +(def: prefix Text "LuxRuntime") + +(def: #export unit Expression (%t //.unit)) + +(def: (flag value) + (-> Bool Ruby) + (if value + (ruby.string "") + ruby.nil)) + +(def: (variant' tag last? value) + (-> Expression Expression Expression Expression) + (ruby.dictionary (list [(ruby.string //.variant-tag-field) tag] + [(ruby.string //.variant-flag-field) last?] + [(ruby.string //.variant-value-field) value]))) + +(def: #export (variant tag last? value) + (-> Nat Bool Expression Expression) + (variant' (%i (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 Ruby) + +(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 (code.text (format "__" prefix "__" (lang.normalize-name name))) + argsC+ (list/map code.local-symbol args) + argsLC+ (list/map (|>> lang.normalize-name code.text) args) + declaration (` ((~ (code.local-symbol name)) + (~+ argsC+))) + type (` (-> (~+ (list.repeat (list.size argsC+) (` ruby.Ruby))) + ruby.Ruby))] + (wrap (list (` (def: #export (~ declaration) + (~ type) + (ruby.apply (~ runtime) (list (~+ argsC+))))) + (` (def: (~ implementation) + Ruby + (~ (case argsC+ + #.Nil + (` (ruby.set! (list (~ runtime)) (~ definition))) + + _ + (` (let [(~' @) (~ runtime) + (~+ (|> (list.zip2 argsC+ argsLC+) + (list/map (function [[left right]] (list left right))) + list/join))] + (ruby.function! (~ runtime) + (list (~+ argsLC+)) + (~ definition)))))))))))) + +(runtime: (lux//try op) + (ruby.begin! (ruby.block! (list (ruby.set! (list "value") (ruby.call (list unit) op)) + (ruby.return! (right "value")))) + (list [(list) "error" + (ruby.return! (left (ruby.field "message" "error")))]))) + +(runtime: (lux//program-args program-args) + (ruby.block! (list (ruby.set! (list "inputs") none) + (ruby.for-in! "value" program-args + (ruby.set! (list "inputs") (some (ruby.array (list "value" "inputs"))))) + (ruby.return! "inputs")))) + +(def: runtime//lux + Runtime + (format @@lux//try "\n" + @@lux//program-args "\n")) + +(runtime: (product//left product index) + (ruby.block! (list (ruby.set! (list "index_min_length") (ruby.+ (ruby.int 1) index)) + (ruby.if! (ruby.> "index_min_length" (ruby.length product)) + ## No need for recursion + (ruby.return! (ruby.nth index product)) + ## Needs recursion + (ruby.return! (product//left (ruby.nth (ruby.- (ruby.int 1) + (ruby.length product)) + product) + (ruby.- (ruby.length product) + "index_min_length"))))))) + +(runtime: (product//right product index) + (ruby.block! (list (ruby.set! (list "index_min_length") (ruby.+ (ruby.int 1) index)) + (ruby.cond! (list [(ruby.= "index_min_length" (ruby.length product)) + ## Last element. + (ruby.return! (ruby.nth index product))] + [(ruby.< "index_min_length" (ruby.length product)) + ## Needs recursion + (ruby.return! (product//right (ruby.nth (ruby.- (ruby.int 1) + (ruby.length product)) + product) + (ruby.- (ruby.length product) + "index_min_length")))]) + ## Must slice + (ruby.return! (ruby.array-range index (ruby.length product) product)))))) + +(runtime: (sum//get sum wantedTag wantsLast) + (let [no-match! (ruby.return! ruby.nil) + sum-tag (ruby.nth (ruby.string //.variant-tag-field) sum) + sum-flag (ruby.nth (ruby.string //.variant-flag-field) sum) + sum-value (ruby.nth (ruby.string //.variant-value-field) sum) + is-last? (ruby.= (ruby.string "") sum-flag) + test-recursion! (ruby.if! is-last? + ## Must recurse. + (ruby.return! (sum//get sum-value (ruby.- sum-tag wantedTag) wantsLast)) + no-match!)] + (ruby.cond! (list [(ruby.= sum-tag wantedTag) + (ruby.if! (ruby.= wantsLast sum-flag) + (ruby.return! sum-value) + test-recursion!)] + + [(ruby.> sum-tag wantedTag) + test-recursion!] + + [(ruby.and (ruby.< sum-tag wantedTag) + (ruby.= (ruby.string "") wantsLast)) + (ruby.return! (variant' (ruby.- wantedTag sum-tag) sum-flag sum-value))]) + + no-match!))) + +(def: runtime//adt + Runtime + (format @@product//left "\n" + @@product//right "\n" + @@sum//get "\n")) + +(runtime: (bit//count subject) + (ruby.block! (list (ruby.set! (list "count") (ruby.int 0)) + (ruby.while! (ruby.> (ruby.int 0) subject) + (ruby.block! (list (ruby.set! (list "count") (ruby.+ (ruby.% (ruby.int 2) subject) + "count")) + (ruby.set! (list subject) (ruby./ (ruby.int 2) subject))))) + (ruby.return! "count")))) + +(runtime: (bit//shift-right param subject) + (let [mask (|> (ruby.int 1) + (ruby.bit-shl (ruby.- param (ruby.int 64))) + (ruby.- (ruby.int 1)))] + (ruby.return! (|> subject + (ruby.bit-shr param) + (ruby.bit-and mask))))) + +(def: runtime//bit + Runtime + (format @@bit//count + @@bit//shift-right)) + +(def: high (-> Expression Expression) (bit//shift-right (ruby.int 32))) +(def: low (-> Expression Expression) (ruby.bit-and "0xFFFFFFFF")) + +(runtime: (nat//< param subject) + (ruby.block! (list (ruby.set! (list "ph") (high param)) + (ruby.set! (list "sh") (high subject)) + (ruby.return! (ruby.or (ruby.< "ph" "sh") + (ruby.and (ruby.= "ph" "sh") + (ruby.< (low param) (low subject)))))))) + +(runtime: (nat/// param subject) + (ruby.if! (ruby.< (ruby.int 0) param) + (ruby.if! (nat//< param subject) + (ruby.return! (ruby.int 0)) + (ruby.return! (ruby.int 1))) + (ruby.block! (list (ruby.set! (list "quotient") (|> subject + (ruby.bit-shr (ruby.int 1)) + (ruby./ param) + (ruby.bit-shl (ruby.int 1)))) + (ruby.set! (list "remainder") (ruby.- (ruby.* param "quotient") + subject)) + (ruby.if! (ruby.not (nat//< param "remainder")) + (ruby.return! (ruby.+ (ruby.int 1) "quotient")) + (ruby.return! "quotient")))))) + +(runtime: (nat//% param subject) + (let [flat (|> subject + (nat/// param) + (ruby.* param))] + (ruby.return! (ruby.- flat subject)))) + +(def: runtime//nat + Runtime + (format @@nat//< + @@nat/// + @@nat//%)) + +(runtime: (deg//* param subject) + (ruby.block! (list (ruby.set! (list "sL") (low subject)) + (ruby.set! (list "sH") (high subject)) + (ruby.set! (list "pL") (low param)) + (ruby.set! (list "pH") (high param)) + (ruby.set! (list "bottom") (bit//shift-right (ruby.int 32) + (ruby.* "pL" "sL"))) + (ruby.set! (list "middle") (ruby.+ (ruby.* "pL" "sH") + (ruby.* "pH" "sL"))) + (ruby.set! (list "top") (ruby.* "pH" "sH")) + (ruby.return! (|> "bottom" + (ruby.+ "middle") + high + (ruby.+ "top")))))) + +(runtime: (deg//leading-zeroes input) + (ruby.block! (list (ruby.set! (list "zeroes") (ruby.int 64)) + (ruby.while! (ruby.not (ruby.= (ruby.int 0) input)) + (ruby.block! (list (ruby.set! (list "zeroes") (ruby.- (ruby.int 1) "zeroes")) + (ruby.set! (list input) (bit//shift-right (ruby.int 1) input))))) + (ruby.return! "zeroes")))) + +(runtime: (deg/// param subject) + (ruby.if! (ruby.= param subject) + (ruby.return! (ruby.int -1)) + (ruby.block! (list (ruby.set! (list "min_shift") + (ruby.send "min" (list) + (ruby.array (list (deg//leading-zeroes param) + (deg//leading-zeroes subject))))) + (ruby.return! (|> (ruby.bit-shl "min_shift" subject) + (ruby./ (|> param (ruby.bit-shl "min_shift") low)) + (ruby.bit-shl (ruby.int 32)))))))) + +(runtime: (deg//from-frac input) + (let [->int (ruby.send "floor" (list))] + (ruby.block! (list (ruby.set! (list "two32") (ruby.pow (ruby.float 32.0) (ruby.float 2.0))) + (ruby.set! (list "shifted") (|> input + (ruby.% (ruby.float 1.0)) + (ruby.* "two32"))) + (ruby.set! (list "low") (|> "shifted" + (ruby.% (ruby.float 1.0)) + (ruby.* "two32") + ->int)) + (ruby.set! (list "high") (|> "shifted" ->int)) + (ruby.return! (ruby.+ (ruby.bit-shl (ruby.int 32) "high") + "low")))))) + +(def: runtime//deg + Runtime + (format @@deg//* + @@deg//leading-zeroes + @@deg/// + @@deg//from-frac)) + +(runtime: (text//index subject param start) + (ruby.block! (list (ruby.set! (list "idx") (ruby.send "index" (list param start) subject)) + (ruby.if! (ruby.= ruby.nil "idx") + (ruby.return! none) + (ruby.return! (some "idx")))))) + +(runtime: (text//clip text from to) + (ruby.if! ($_ ruby.and + (ruby.>= (ruby.int 0) from) + (ruby.< (ruby.send "length" (list) text) from) + (ruby.>= (ruby.int 0) to) + (ruby.< (ruby.send "length" (list) text) to) + (ruby.<= to from)) + (ruby.return! (some (ruby.array-range from to text))) + (ruby.return! none))) + +(runtime: (text//char text idx) + (ruby.if! (ruby.and (ruby.>= (ruby.int 0) idx) + (ruby.< (ruby.send "length" (list) text) idx)) + (ruby.return! (some (ruby.send "ord" (list) + (ruby.array-range idx idx text)))) + (ruby.return! none))) + +(def: runtime//text + Runtime + (format @@text//index + @@text//clip + @@text//char)) + +(def: (check-index-out-of-bounds array idx body!) + (-> Expression Expression Statement Statement) + (ruby.if! (ruby.<= (ruby.length array) + idx) + body! + (ruby.raise (ruby.string "Array index out of bounds!")))) + +(runtime: (array//get array idx) + (<| (check-index-out-of-bounds array idx) + (ruby.block! (list (ruby.set! (list "temp") (ruby.nth idx array)) + (ruby.if! (ruby.= ruby.nil "temp") + (ruby.return! none) + (ruby.return! (some "temp"))))))) + +(runtime: (array//put array idx value) + (<| (check-index-out-of-bounds array idx) + (ruby.block! (list (ruby.set-nth! idx value array) + (ruby.return! array))))) + +(def: runtime//array + Runtime + (format @@array//get + @@array//put)) + +(def: #export atom//field Text "_lux_atom") + +(runtime: (atom//compare-and-swap atom old new) + (let [atom//field (ruby.string atom//field)] + (ruby.if! (ruby.= old (ruby.nth atom//field atom)) + (ruby.block! (list (ruby.set-nth! atom//field new atom) + (ruby.return! (ruby.bool true)))) + (ruby.return! (ruby.bool false))))) + +(def: runtime//atom + Runtime + (format @@atom//compare-and-swap "\n")) + +(runtime: (box//write value box) + (ruby.block! (list (ruby.set-nth! (ruby.int 0) value box) + (ruby.return! ..unit)))) + +(def: runtime//box + Runtime + (format @@box//write)) + +(runtime: (process//future procedure) + (ruby.and (format "(Thread.new {" + (ruby.statement (ruby.call (list ..unit) procedure)) + "})") + ..unit)) + +(runtime: (process//schedule milli-seconds procedure) + (ruby.and (format "(Thread.new {" + (ruby.statement (ruby.apply "sleep" (list (ruby./ (ruby.float 1_000.0) milli-seconds)))) + (ruby.statement (ruby.call (list ..unit) procedure)) + "})") + ..unit)) + +(def: runtime//process + Runtime + (format @@process//future + @@process//schedule)) + +(def: runtime + Runtime + (format runtime//lux "\n" + runtime//adt "\n" + runtime//bit "\n" + runtime//nat "\n" + runtime//deg "\n" + runtime//text "\n" + runtime//array "\n" + runtime//atom "\n" + runtime//box "\n" + runtime//process "\n" + )) + +(def: #export artifact Text (format prefix ".rb")) + +(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/ruby/statement.jvm.lux b/new-luxc/source/luxc/lang/translation/ruby/statement.jvm.lux new file mode 100644 index 000000000..5f2cdef06 --- /dev/null +++ b/new-luxc/source/luxc/lang/translation/ruby/statement.jvm.lux @@ -0,0 +1,48 @@ +(.module: + lux + (lux (control [monad #+ do]) + [macro] + (data text/format)) + (luxc (lang [".L" module] + (host [ruby #+ Ruby 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 (ruby.global! def-name expressionO)) + expressionV (evalT.eval (ruby.global 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") + ## (hostT.save (format "var " (referenceT.variable +0) " = " runtimeT.lux//program-args "();" + ## "(" programO ")(null);")) + ) diff --git a/new-luxc/source/luxc/lang/translation/ruby/structure.jvm.lux b/new-luxc/source/luxc/lang/translation/ruby/structure.jvm.lux new file mode 100644 index 000000000..5bf7c9e8b --- /dev/null +++ b/new-luxc/source/luxc/lang/translation/ruby/structure.jvm.lux @@ -0,0 +1,31 @@ +(.module: + lux + (lux (control [monad #+ do]) + (data [text] + text/format) + [macro]) + (luxc ["&" lang] + (lang [synthesis #+ Synthesis] + (host [ruby #+ Ruby 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 (ruby.array 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 cc8302aa3..5021dc258 100644 --- a/new-luxc/test/test/luxc/common.lux +++ b/new-luxc/test/test/luxc/common.lux @@ -18,7 +18,12 @@ [lua] (lua [".T_lua" expression] [".T_lua" eval] - [".T_lua" runtime]))))) + [".T_lua" runtime]) + + [ruby] + (ruby [".T_ruby" expression] + [".T_ruby" eval] + [".T_ruby" runtime]))))) (do-template [ ] [(def: #export @@ -30,6 +35,7 @@ [init-jvm &host.init-host] [init-js js.init] [init-lua lua.init] + [init-ruby ruby.init] ) (def: (run-synthesis translate-runtime translate-expression eval init) @@ -48,3 +54,5 @@ (def: #export run-js (run-synthesis runtimeT_js.translate expressionT_js.translate evalT_js.eval init-js)) (def: #export run-lua (run-synthesis runtimeT_lua.translate expressionT_lua.translate evalT_lua.eval init-lua)) + +(def: #export run-ruby (run-synthesis runtimeT_ruby.translate expressionT_ruby.translate evalT_ruby.eval init-ruby)) diff --git a/new-luxc/test/test/luxc/lang/translation/case.lux b/new-luxc/test/test/luxc/lang/translation/case.lux index e2ad48613..cc33d03d3 100644 --- a/new-luxc/test/test/luxc/lang/translation/case.lux +++ b/new-luxc/test/test/luxc/lang/translation/case.lux @@ -23,7 +23,11 @@ (lua ["/_lua" case] [".T_lua" expression] [".T_lua" eval] - [".T_lua" runtime])))) + [".T_lua" runtime]) + (ruby ["/_ruby" case] + [".T_ruby" expression] + [".T_ruby" eval] + [".T_ruby" runtime])))) (test/luxc common)) (def: struct-limit Nat +10) @@ -132,3 +136,8 @@ (<| (times +100) (pattern-matching-spec expressionT_lua.translate evalT_lua.eval runtimeT_lua.translate init-lua /_lua.translate-case))) + +(context: "[Ruby] Pattern-matching." + (<| (times +100) + (pattern-matching-spec expressionT_ruby.translate evalT_ruby.eval runtimeT_ruby.translate init-ruby + /_ruby.translate-case))) diff --git a/new-luxc/test/test/luxc/lang/translation/common.lux b/new-luxc/test/test/luxc/lang/translation/common.lux index 2f735a0d1..72dbeb1da 100644 --- a/new-luxc/test/test/luxc/lang/translation/common.lux +++ b/new-luxc/test/test/luxc/lang/translation/common.lux @@ -26,7 +26,10 @@ [".T_js" runtime]) (lua [".T_lua" eval] [".T_lua" expression] - [".T_lua" runtime])))) + [".T_lua" runtime]) + (ruby [".T_ruby" eval] + [".T_ruby" expression] + [".T_ruby" runtime])))) (test/luxc common)) (def: (bit-spec translate-expression eval translate-runtime init) @@ -832,3 +835,8 @@ (<| (times +100) (all-specs expressionT_lua.translate evalT_lua.eval runtimeT_lua.translate init-lua run-lua))) + +(context: "[Ruby] Common procedures." + (<| (times +100) + (all-specs expressionT_ruby.translate evalT_ruby.eval runtimeT_ruby.translate init-ruby + run-ruby))) diff --git a/new-luxc/test/test/luxc/lang/translation/function.lux b/new-luxc/test/test/luxc/lang/translation/function.lux index cbf8b3dbd..c25632916 100644 --- a/new-luxc/test/test/luxc/lang/translation/function.lux +++ b/new-luxc/test/test/luxc/lang/translation/function.lux @@ -6,6 +6,7 @@ (data [product] [maybe] ["e" error] + text/format (coll ["a" array] [list "list/" Functor])) ["r" math/random "r/" Monad] @@ -23,7 +24,10 @@ [".T_js" runtime]) (lua [".T_lua" eval] [".T_lua" expression] - [".T_lua" runtime])))) + [".T_lua" runtime]) + (ruby [".T_ruby" eval] + [".T_ruby" expression] + [".T_ruby" runtime])))) (test/luxc common)) (def: arity-limit Nat +10) @@ -65,7 +69,8 @@ (n/= arg-value (:! Nat valueT)) (#e.Error error) - false))) + (exec (log! error) + false)))) (test "Can partially apply functions." (or (n/= +1 arity) (|> (do macro.Monad @@ -83,7 +88,8 @@ (n/= arg-value (:! Nat valueT)) (#e.Error error) - false)))) + (exec (log! error) + false))))) (test "Can read environment." (or (n/= +1 arity) (|> (do macro.Monad @@ -106,7 +112,8 @@ (n/= arg-value (:! Nat valueT)) (#e.Error error) - false)))) + (exec (log! error) + false))))) ))) (context: "[JVM] Function." @@ -120,3 +127,7 @@ (context: "[Lua] Function." (<| (times +100) (function-spec expressionT_lua.translate evalT_lua.eval runtimeT_lua.translate init-lua))) + +(context: "[Ruby] Function." + (<| (times +100) + (function-spec expressionT_ruby.translate evalT_ruby.eval runtimeT_ruby.translate init-ruby))) diff --git a/new-luxc/test/test/luxc/lang/translation/primitive.lux b/new-luxc/test/test/luxc/lang/translation/primitive.lux index d94806601..8dc48db6f 100644 --- a/new-luxc/test/test/luxc/lang/translation/primitive.lux +++ b/new-luxc/test/test/luxc/lang/translation/primitive.lux @@ -61,3 +61,7 @@ (context: "[Lua] Primitives." (<| (times +100) (spec run-lua))) + +(context: "[Ruby] Primitives." + (<| (times +100) + (spec run-ruby))) diff --git a/new-luxc/test/test/luxc/lang/translation/reference.lux b/new-luxc/test/test/luxc/lang/translation/reference.lux index 130a42ed3..919e35ab2 100644 --- a/new-luxc/test/test/luxc/lang/translation/reference.lux +++ b/new-luxc/test/test/luxc/lang/translation/reference.lux @@ -26,7 +26,13 @@ [".T_lua" eval] [".T_lua" expression] [".T_lua" case] - [".T_lua" runtime])))) + [".T_lua" runtime]) + (ruby [".T_ruby" statement] + [".T_ruby" eval] + [".T_ruby" expression] + [".T_ruby" case] + [".T_ruby" runtime]) + ))) (test/luxc common)) (def: upper-alpha-ascii @@ -97,32 +103,38 @@ false))) ))) -(context: "[JVM] Definitions." - (<| (times +100) - (definitions-spec expressionT_jvm.translate evalT_jvm.eval runtimeT_jvm.translate init-jvm - statementT_jvm.translate-def))) - -(context: "[JVM] Variables." - (<| (times +100) - (variables-spec expressionT_jvm.translate evalT_jvm.eval runtimeT_jvm.translate init-jvm - caseT_jvm.translate-let))) +(def: (references-spec translate-expression eval translate-runtime init + translate-def translate-let) + (All [a] + (-> (-> ls.Synthesis (Meta a)) (-> a (Meta Top)) (Meta Top) (IO Compiler) + (-> Text Type a Code (Meta Unit)) + (-> (-> ls.Synthesis (Meta a)) Nat ls.Synthesis ls.Synthesis (Meta a)) + Test)) + (seq (definitions-spec translate-expression eval translate-runtime init + translate-def) + (variables-spec translate-expression eval translate-runtime init + translate-let))) -(context: "[JS] Definitions." +(context: "[JVM] References." (<| (times +100) - (definitions-spec expressionT_js.translate evalT_js.eval runtimeT_js.translate init-js - statementT_js.translate-def))) + (references-spec expressionT_jvm.translate evalT_jvm.eval runtimeT_jvm.translate init-jvm + statementT_jvm.translate-def + caseT_jvm.translate-let))) -(context: "[JS] Variables." +(context: "[JS] References." (<| (times +100) - (variables-spec expressionT_js.translate evalT_js.eval runtimeT_js.translate init-js - caseT_js.translate-let))) + (references-spec expressionT_js.translate evalT_js.eval runtimeT_js.translate init-js + statementT_js.translate-def + caseT_js.translate-let))) -(context: "[Lua] Definitions." +(context: "[Lua] References." (<| (times +100) - (definitions-spec expressionT_lua.translate evalT_lua.eval runtimeT_lua.translate init-lua - statementT_lua.translate-def))) + (references-spec expressionT_lua.translate evalT_lua.eval runtimeT_lua.translate init-lua + statementT_lua.translate-def + caseT_lua.translate-let))) -(context: "[Lua] Variables." +(context: "[Ruby] References." (<| (times +100) - (variables-spec expressionT_lua.translate evalT_lua.eval runtimeT_lua.translate init-lua - caseT_lua.translate-let))) + (references-spec expressionT_ruby.translate evalT_ruby.eval runtimeT_ruby.translate init-ruby + statementT_ruby.translate-def + caseT_ruby.translate-let))) diff --git a/new-luxc/test/test/luxc/lang/translation/structure.lux b/new-luxc/test/test/luxc/lang/translation/structure.lux index 21a338196..cf2b8a729 100644 --- a/new-luxc/test/test/luxc/lang/translation/structure.lux +++ b/new-luxc/test/test/luxc/lang/translation/structure.lux @@ -106,26 +106,24 @@ (exec (log! error) false)))))) -(context: "[JVM] Tuples." - (<| (times +100) - (tuples-spec run-jvm))) - -(context: "[JVM] Variants." - (<| (times +100) - (variants-spec run-jvm))) +(def: (structure-spec run) + (-> (-> Synthesis (e.Error Top)) Test) + ($_ seq + (tuples-spec run) + (variants-spec run))) -(context: "[JS] Tuples." +(context: "[JVM] Structures." (<| (times +100) - (tuples-spec run-js))) + (structure-spec run-jvm))) -(context: "[JS] Variants." +(context: "[JS] Structures." (<| (times +100) - (variants-spec run-js))) + (structure-spec run-js))) -(context: "[Lua] Tuples." +(context: "[Lua] Structures." (<| (times +100) - (tuples-spec run-lua))) + (structure-spec run-lua))) -(context: "[Lua] Variants." +(context: "[Ruby] Structures." (<| (times +100) - (variants-spec run-lua))) + (structure-spec run-ruby))) diff --git a/new-luxc/test/tests.lux b/new-luxc/test/tests.lux index 9268e492c..886d3d05d 100644 --- a/new-luxc/test/tests.lux +++ b/new-luxc/test/tests.lux @@ -20,13 +20,16 @@ ["_.S" procedure] ["_.S" loop]) (translation ["_.T" primitive] - ["_.T" reference] ["_.T" structure] - ["_.T" case] ["_.T" function] + ["_.T" case] + ["_.T" reference] ["_.T" common] ["_.T" jvm] - ["_.T" js])) + ["_.T" js] + ## ["_.T" lua] + ## ["_.T" ruby] + )) ))) (program: args -- cgit v1.2.3