From 787fc34a8f7c66746046a8ce0c16403cf6c2bf6c Mon Sep 17 00:00:00 2001 From: Eduardo Julian Date: Wed, 4 Apr 2018 00:56:16 -0400 Subject: - Initial Python back-end implementation. --- .../lang/translation/jvm/procedure/common.jvm.lux | 1 - new-luxc/source/luxc/lang/translation/python.lux | 208 ++++++++ .../luxc/lang/translation/python/case.jvm.lux | 265 ++++++++++ .../luxc/lang/translation/python/eval.jvm.lux | 146 ++++++ .../lang/translation/python/expression.jvm.lux | 82 +++ .../luxc/lang/translation/python/function.jvm.lux | 99 ++++ .../luxc/lang/translation/python/loop.jvm.lux | 36 ++ .../luxc/lang/translation/python/primitive.jvm.lux | 28 + .../luxc/lang/translation/python/procedure.jvm.lux | 28 + .../translation/python/procedure/common.jvm.lux | 572 ++++++++++++++++++++ .../lang/translation/python/procedure/host.jvm.lux | 89 ++++ .../luxc/lang/translation/python/reference.jvm.lux | 42 ++ .../luxc/lang/translation/python/runtime.jvm.lux | 583 +++++++++++++++++++++ .../luxc/lang/translation/python/statement.jvm.lux | 48 ++ .../luxc/lang/translation/python/structure.jvm.lux | 31 ++ .../luxc/lang/translation/ruby/primitive.jvm.lux | 6 +- 16 files changed, 2260 insertions(+), 4 deletions(-) create mode 100644 new-luxc/source/luxc/lang/translation/python.lux create mode 100644 new-luxc/source/luxc/lang/translation/python/case.jvm.lux create mode 100644 new-luxc/source/luxc/lang/translation/python/eval.jvm.lux create mode 100644 new-luxc/source/luxc/lang/translation/python/expression.jvm.lux create mode 100644 new-luxc/source/luxc/lang/translation/python/function.jvm.lux create mode 100644 new-luxc/source/luxc/lang/translation/python/loop.jvm.lux create mode 100644 new-luxc/source/luxc/lang/translation/python/primitive.jvm.lux create mode 100644 new-luxc/source/luxc/lang/translation/python/procedure.jvm.lux create mode 100644 new-luxc/source/luxc/lang/translation/python/procedure/common.jvm.lux create mode 100644 new-luxc/source/luxc/lang/translation/python/procedure/host.jvm.lux create mode 100644 new-luxc/source/luxc/lang/translation/python/reference.jvm.lux create mode 100644 new-luxc/source/luxc/lang/translation/python/runtime.jvm.lux create mode 100644 new-luxc/source/luxc/lang/translation/python/statement.jvm.lux create mode 100644 new-luxc/source/luxc/lang/translation/python/structure.jvm.lux (limited to 'new-luxc/source/luxc/lang/translation') diff --git a/new-luxc/source/luxc/lang/translation/jvm/procedure/common.jvm.lux b/new-luxc/source/luxc/lang/translation/jvm/procedure/common.jvm.lux index 422d9da1d..abd2d49c8 100644 --- a/new-luxc/source/luxc/lang/translation/jvm/procedure/common.jvm.lux +++ b/new-luxc/source/luxc/lang/translation/jvm/procedure/common.jvm.lux @@ -381,7 +381,6 @@ [text//size "java.lang.String" "length" lux-intI $t.int] [text//hash "java.lang.Object" "hashCode" lux-intI $t.int] - [text//trim "java.lang.String" "trim" id $String] [text//upper "java.lang.String" "toUpperCase" id $String] [text//lower "java.lang.String" "toLowerCase" id $String] ) diff --git a/new-luxc/source/luxc/lang/translation/python.lux b/new-luxc/source/luxc/lang/translation/python.lux new file mode 100644 index 000000000..7304ea560 --- /dev/null +++ b/new-luxc/source/luxc/lang/translation/python.lux @@ -0,0 +1,208 @@ +(.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 [python #+ 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/python/core/PyObject) + +(host.import org/python/util/PythonInterpreter + (new []) + (exec [String] void) + (eval [String] PyObject)) + +(type: #export Anchor [Text Register]) + +(type: #export Host + {#context [Text Nat] + #anchor (Maybe Anchor) + #loader (-> Statement (Error Unit)) + #interpreter (-> Expression (Error PyObject)) + #module-buffer (Maybe StringBuilder) + #program-buffer StringBuilder}) + +(def: #export init + (IO Host) + (io (let [interpreter (PythonInterpreter::new [])] + {#context ["" +0] + #anchor #.None + #loader (function [code] + ("lux try" (io (PythonInterpreter::exec [(python.statement code)] interpreter)))) + #interpreter (function [code] + ("lux try" (io (PythonInterpreter::eval [(python.expression code)] interpreter)))) + #module-buffer #.None + #program-buffer (StringBuilder::new [])}))) + +(def: #export python-module-name Text "module.py") + +(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))]))) + +(do-template [ ] + [(def: ( code) + (-> (Meta )) + (function [compiler] + (let [runner (|> compiler (get@ #.host) (:! Host) (get@ ))] + (case (runner code) + (#e.Error error) + ((lang.fail (Cannot-Execute error)) compiler) + + (#e.Success output) + (#e.Success [compiler output])))))] + + [load! #loader Statement Unit] + [interpret #interpreter Expression PyObject] + ) + +(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 "") + +(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! python.statement Statement Unit] + [run interpret python.expression Expression PyObject] + ) + +(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) "/" python-module-name) + (|> module-code + (String::getBytes ["UTF-8"]) + e.assume))))) diff --git a/new-luxc/source/luxc/lang/translation/python/case.jvm.lux b/new-luxc/source/luxc/lang/translation/python/case.jvm.lux new file mode 100644 index 000000000..2218c1994 --- /dev/null +++ b/new-luxc/source/luxc/lang/translation/python/case.jvm.lux @@ -0,0 +1,265 @@ +(.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 [python #+ Expression Statement Except 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 (|> bodyO + (python.lambda (list $register)) + (python.apply (list valueO)))))) + +(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 (python.int (:! Int idx))))) + valueO + pathP)))) + +(def: #export (translate-if testO thenO elseO) + (-> Expression Expression Expression Expression) + (python.if testO thenO elseO)) + +(def: $savepoint (python.var "pm_cursor_savepoint")) +(def: $cursor (python.var "pm_cursor")) + +(def: (push-cursor! value) + (-> Expression Statement) + (python.do! + (python.send (list value) + "append" (@@ $cursor)))) + +(def: save-cursor! + Statement + (python.do! + (python.send (list (python.slice-from (python.int 0) (@@ $cursor))) + "append" (@@ $savepoint)))) + +(def: restore-cursor! + Statement + (python.set! (list $cursor) + (python.send (list) "pop" (@@ $savepoint)))) + +(def: cursor-top + Expression + (python.nth (python.int -1) (@@ $cursor))) + +(def: pop-cursor! + Statement + (python.do! + (python.send (list) "pop" (@@ $cursor)))) + +(def: pm-error (python.string "PM-ERROR")) + +(def: (new-Exception error) + (-> Expression Expression) + (python.apply (list pm-error) (python.global "Exception"))) + +(def: fail-pm! (python.raise! (new-Exception pm-error))) + +(def: $temp (python.var "temp")) + +(exception: #export Unrecognized-Path) + +(def: $alt_error (python.var "alt_error")) + +(def: (pm-catch! handler!) + (-> Statement Except) + [(list "Exception") $alt_error + (python.if! (python.= pm-error (python.apply (list (@@ $alt_error)) (python.global "str"))) + handler! + (python.raise! (@@ $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 (python.return! bodyO))) + + (^code ("lux case pop")) + (meta/wrap pop-cursor!) + + (^code ("lux case bind" (~ [_ (#.Nat register)]))) + (meta/wrap (python.set! (list (referenceT.variable register)) cursor-top)) + + (^template [ ] + [_ ( value)] + (meta/wrap (python.when! (python.not (python.= (|> value ) cursor-top)) + fail-pm!))) + ([#.Nat (<| python.int (:! Int))] + [#.Int python.int] + [#.Deg (<| python.int (:! Int))] + [#.Bool python.bool] + [#.Frac python.float] + [#.Text python.string]) + + (^template [ ] + (^code ( (~ [_ (#.Nat idx)]))) + (meta/wrap (push-cursor! ( cursor-top (python.int (:! Int idx)))))) + (["lux case tuple left" runtimeT.product//left] + ["lux case tuple right" runtimeT.product//right]) + + (^template [ ] + (^code ( (~ [_ (#.Nat idx)]))) + (meta/wrap ($_ python.then! + (python.set! (list $temp) (runtimeT.sum//get cursor-top (python.int (:! Int idx)) )) + (python.if! (python.not (python.= python.none (@@ $temp))) + (push-cursor! (@@ $temp)) + fail-pm!)))) + (["lux case variant left" python.none] + ["lux case variant right" (python.string "")]) + + (^code ("lux case seq" (~ leftP) (~ rightP))) + (do macro.Monad + [leftO (translate-pattern-matching' translate leftP) + rightO (translate-pattern-matching' translate rightP)] + (wrap ($_ python.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 (python.try! ($_ python.then! + save-cursor! + leftO) + (list (pm-catch! + ($_ python.then! + restore-cursor! + rightO)))))) + + _ + (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 (python.try! pattern-matching + (list (pm-catch! + (python.raise! (new-Exception (python.string "Invalid expression for pattern-matching."))))))))) + +(def: (initialize-pattern-matching! stack-init) + (-> Expression Statement) + ($_ python.then! + (python.set! (list $cursor) (python.list (list stack-init))) + (python.set! (list $savepoint) (python.list (list))))) + +(def: empty (Set Variable) (set.new number.Hash)) + +(type: Storage + {#bindings (Set Variable) + #dependencies (Set Variable)}) + +(def: (path-variables pathP) + (-> Path Storage) + (loop [pathP pathP + outer-variables {#bindings empty + #dependencies empty}] + ## TODO: Remove (let [outer recur]) once loops can have names. + (let [outer recur] + (case pathP + (^code ("lux case bind" (~ [_ (#.Nat register)]))) + (update@ #bindings (set.add (nat-to-int register)) + outer-variables) + + (^or (^code ("lux case seq" (~ leftP) (~ rightP))) + (^code ("lux case alt" (~ leftP) (~ rightP)))) + (list/fold outer outer-variables (list leftP rightP)) + + (^code ("lux case exec" (~ bodyS))) + (loop [bodyS bodyS + inner-variables outer-variables] + ## TODO: Remove (let [inner recur]) once loops can have names. + (let [inner recur] + (case bodyS + (^code ((~ [_ (#.Nat tag)]) (~ [_ (#.Bool last?)]) (~ valueS))) + (inner valueS inner-variables) + + (^code [(~+ members)]) + (list/fold inner inner-variables members) + + (^ [_ (#.Form (list [_ (#.Int var)]))]) + (if (set.member? (get@ #bindings inner-variables) var) + inner-variables + (update@ #dependencies (set.add var) inner-variables)) + + (^code ("lux call" (~ functionS) (~+ argsS))) + (list/fold inner inner-variables (#.Cons functionS argsS)) + + (^code ("lux function" (~ [_ (#.Nat arity)]) [(~+ environment)] (~ bodyS))) + (|> environment + (list/map (|>> (list) code.form)) + (list/fold inner inner-variables)) + + (^code ("lux let" (~ [_ (#.Nat register)]) (~ inputS) (~ exprS))) + (list/fold inner (update@ #bindings (set.add (nat-to-int register)) + inner-variables) + (list inputS exprS)) + + (^code ("lux case" (~ inputS) (~ pathPS))) + (|> inner-variables (inner inputS) (outer pathPS)) + + (^code ((~ [_ (#.Text procedure)]) (~+ argsS))) + (list/fold inner inner-variables argsS) + + _ + inner-variables))) + + _ + outer-variables)))) + +(def: generated-name + (-> Text (Meta SVar)) + (|>> macro.gensym + (:: macro.Monad map (|>> %code + lang.normalize-name + python.var)))) + +(def: #export (translate-case translate valueS pathP) + (-> (-> Synthesis (Meta Expression)) Synthesis Path (Meta Expression)) + (do macro.Monad + [valueO (translate valueS) + $case (generated-name "case") + $value (generated-name "value") + #let [$dependencies+ (|> (path-variables pathP) + (get@ #dependencies) + set.to-list + (list/map referenceT.local)) + @dependencies+ (list/map @@ $dependencies+)] + pattern-matching! (translate-pattern-matching translate pathP) + _ (//.save (python.def! $case (list& $value $dependencies+) + ($_ python.then! + (initialize-pattern-matching! (@@ $value)) + pattern-matching!)))] + (wrap (python.apply (list& valueO @dependencies+) (@@ $case))))) diff --git a/new-luxc/source/luxc/lang/translation/python/eval.jvm.lux b/new-luxc/source/luxc/lang/translation/python/eval.jvm.lux new file mode 100644 index 000000000..bc6e1a342 --- /dev/null +++ b/new-luxc/source/luxc/lang/translation/python/eval.jvm.lux @@ -0,0 +1,146 @@ +(.module: + lux + (lux (control ["ex" exception #+ exception:]) + (data [bit] + [maybe] + ["e" error #+ Error] + text/format + (coll [array])) + [host]) + (luxc [lang] + (lang (host [python #+ Expression Statement]))) + [//]) + +(host.import java/lang/Object + (toString [] String) + (getClass [] (Class Object))) + +(host.import java/lang/Long + (intValue [] Integer)) + +(host.import org/python/core/PyType + (getName [] String)) + +(host.import org/python/core/PyString + (new [String])) + +(host.import org/python/core/PyObject + (asLong [] long) + (asDouble [] double) + (asString [] String) + (__nonzero__ [] boolean) + (__getitem__ [int] #try PyObject) + (__getitem__ #as __getitem__dict [PyObject] #try PyObject) + (__len__ [] int) + (getType [] PyType)) + +(def: (tuple lux-object host-object) + (-> (-> PyObject (Error Top)) PyObject (Error Top)) + (let [size (:! Nat (PyObject::__len__ [] host-object))] + (loop [idx +0 + output (:! (Array Top) (array.new size))] + (if (n/< size idx) + (case (PyObject::__getitem__ [(:! Int idx)] host-object) + (#e.Error error) + (#e.Error error) + + (#e.Success 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))))) + +(def: python-type + (-> PyObject Text) + (|>> (PyObject::getType []) (PyType::getName []) (:! Text))) + +(exception: #export Not-A-Variant) + +(def: tag-field (PyString::new [//.variant-tag-field])) +(def: flag-field (PyString::new [//.variant-flag-field])) +(def: value-field (PyString::new [//.variant-value-field])) + +(def: (variant lux-object host-object) + (-> (-> PyObject (Error Top)) PyObject (Error Top)) + (case [(PyObject::__getitem__dict [tag-field] host-object) + (PyObject::__getitem__dict [flag-field] host-object) + (PyObject::__getitem__dict [value-field] host-object)] + (^or [(#e.Error error) _ _] [_ (#e.Error error) _] [_ _ (#e.Error error)]) + (#e.Error error) + + (^multi [(#e.Success tag) (#e.Success flag) (#e.Success value)] + [(lux-object tag) + (#e.Success tag)] + [(lux-object value) + (#e.Success value)]) + (#e.Success [(Long::intValue [] (:! Long tag)) + (: Top + (case (python-type (:! PyObject flag)) + "NoneType" + (host.null) + + _ + "")) + value]) + + _ + (ex.throw Not-A-Variant (Object::toString [] host-object)))) + +(exception: #export Unknown-Kind-Of-Host-Object) +(exception: #export Null-Has-No-Lux-Representation) + +(def: (lux-object host-object) + (-> PyObject (Error Top)) + (case (python-type host-object) + "str" + (#e.Success (PyObject::asString [] host-object)) + + "bool" + (#e.Success (PyObject::__nonzero__ [] host-object)) + + "float" + (#e.Success (PyObject::asDouble [] host-object)) + + (^or "int" "long") + (#e.Success (PyObject::asLong [] 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))))) + +(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" + "<< " (python.expression code) "\n" + error)) + ((lang.throw Cannot-Evaluate error) compiler)) + + (#e.Success output) + (case (lux-object output) + (#e.Success parsed-output) + (exec ## (log! (format "eval #e.Success\n" + ## "<< " (python.expression code))) + (#e.Success [compiler parsed-output])) + + (#e.Error error) + (exec (log! (format "eval #e.Error\n" + "<< " (python.expression code) "\n" + error)) + ((lang.throw Cannot-Evaluate error) compiler))))))) diff --git a/new-luxc/source/luxc/lang/translation/python/expression.jvm.lux b/new-luxc/source/luxc/lang/translation/python/expression.jvm.lux new file mode 100644 index 000000000..6a7497c22 --- /dev/null +++ b/new-luxc/source/luxc/lang/translation/python/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 [python #+ 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/python/function.jvm.lux b/new-luxc/source/luxc/lang/translation/python/function.jvm.lux new file mode 100644 index 000000000..97b936fc4 --- /dev/null +++ b/new-luxc/source/luxc/lang/translation/python/function.jvm.lux @@ -0,0 +1,99 @@ +(.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 [python #+ 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 (python.apply argsO+ functionO)))) + +(def: $curried (python.var "curried")) + +(def: (input-declaration register) + (python.set! (list (referenceT.variable (n/inc register))) + (python.nth (|> register nat-to-int python.int) + (@@ $curried)))) + +(def: (with-closure function-name inits function-definition) + (-> Text (List Expression) Statement (Meta Expression)) + (let [$closure (python.var (format function-name "___CLOSURE"))] + (case inits + #.Nil + (do macro.Monad + [_ (//.save function-definition)] + (wrap (python.global function-name))) + + _ + (do macro.Monad + [_ (//.save (python.def! $closure + (|> (list.enumerate inits) + (list/map (|>> product.left referenceT.closure))) + ($_ python.then! + function-definition + (python.return! (python.global function-name)))))] + (wrap (python.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-initsO+ (|> (list.n/range +0 (n/dec arity)) + (list/map input-declaration) + (case> #.Nil + python.no-op! + + (#.Cons head tail) + (list/fold python.then! head tail))) + arityO (|> arity nat-to-int python.int) + @curried (@@ $curried) + $num_args (python.var "num_args") + @num_args (@@ $num_args) + $function (python.var function-name) + @function (@@ $function)]] + (with-closure function-name closureO+ + (python.def! $function (list (python.poly $curried)) + ($_ python.then! + (let [@len (python.global "len")] + (python.set! (list $num_args) (python.apply (list @curried) @len))) + (python.if! (python.= arityO @num_args) + ($_ python.then! + (python.set! (list (referenceT.variable +0)) @function) + args-initsO+ + (python.while! (python.bool true) + (python.return! bodyO))) + (python.if! (python.> arityO @num_args) + (let [arity-args (python.slice (python.int 0) arityO @curried) + output-func-args (python.slice arityO @num_args @curried)] + (python.return! (|> @function + (python.apply-poly (list) arity-args) + (python.apply-poly (list) output-func-args)))) + (let [$next (python.var "next") + $missing (python.var "missing")] + ($_ python.then! + (python.def! $next (list (python.poly $missing)) + (python.return! (|> @function + (python.apply-poly (list) (|> @curried + (python.+ (@@ $missing))))))) + (python.return! (@@ $next))))))))) + )) diff --git a/new-luxc/source/luxc/lang/translation/python/loop.jvm.lux b/new-luxc/source/luxc/lang/translation/python/loop.jvm.lux new file mode 100644 index 000000000..e490033bf --- /dev/null +++ b/new-luxc/source/luxc/lang/translation/python/loop.jvm.lux @@ -0,0 +1,36 @@ +(.module: + lux + (lux (control [monad #+ do]) + (data [text] + text/format + (coll [list "list/" Functor])) + [macro]) + (luxc [lang] + (lang ["ls" synthesis] + (host [python #+ 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 (python.var loop-name) + @loop-name (@@ $loop-name)] + _ (//.save (python.def! $loop-name (|> (list.n/range +0 (n/dec (list.size initsS+))) + (list/map (|>> (n/+ offset) referenceT.variable))) + (python.return! bodyO)))] + (wrap (python.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 (python.apply argsO+ (python.global loop-name))))) diff --git a/new-luxc/source/luxc/lang/translation/python/primitive.jvm.lux b/new-luxc/source/luxc/lang/translation/python/primitive.jvm.lux new file mode 100644 index 000000000..7b2ba1786 --- /dev/null +++ b/new-luxc/source/luxc/lang/translation/python/primitive.jvm.lux @@ -0,0 +1,28 @@ +(.module: + lux + (lux [macro "meta/" Monad]) + (luxc (lang (host [python #+ Expression Statement])))) + +(def: #export translate-bool + (-> Bool (Meta Expression)) + (|>> python.bool meta/wrap)) + +(def: #export translate-int + (-> Int (Meta Expression)) + (|>> python.int meta/wrap)) + +(def: #export translate-nat + (-> Nat (Meta Expression)) + (|>> (:! Int) python.int meta/wrap)) + +(def: #export translate-deg + (-> Deg (Meta Expression)) + (|>> (:! Int) python.int meta/wrap)) + +(def: #export translate-frac + (-> Frac (Meta Expression)) + (|>> python.float meta/wrap)) + +(def: #export translate-text + (-> Text (Meta Expression)) + (|>> python.string meta/wrap)) diff --git a/new-luxc/source/luxc/lang/translation/python/procedure.jvm.lux b/new-luxc/source/luxc/lang/translation/python/procedure.jvm.lux new file mode 100644 index 000000000..a46778503 --- /dev/null +++ b/new-luxc/source/luxc/lang/translation/python/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 [python #+ 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/python/procedure/common.jvm.lux b/new-luxc/source/luxc/lang/translation/python/procedure/common.jvm.lux new file mode 100644 index 000000000..6205d22a7 --- /dev/null +++ b/new-luxc/source/luxc/lang/translation/python/procedure/common.jvm.lux @@ -0,0 +1,572 @@ +(.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 [python #+ 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 + (python.is 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 python.bit-and] + [bit//or python.bit-or] + [bit//xor python.bit-xor] + ) + +(def: (bit//shift-left [subjectO paramO]) + Binary + (|> (python.bit-shl paramO subjectO) + runtimeT.bit//64)) + +(do-template [ ] + [(def: ( [subjectO paramO]) + Binary + ( paramO subjectO))] + + [bit//shift-right python.bit-shr] + [bit//unsigned-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//unsigned-shift-right)) + (install "shift-right" (binary bit//shift-right)) + ))) + +## [[Arrays]] +(def: (array//new sizeO) + Unary + (|> python.none + list python.list + (python.* 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 python.none)) + +(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 python.length)) + ))) + +## [[Numbers]] +(host.import java/lang/Double + (#static MIN_VALUE Double) + (#static MAX_VALUE Double)) + +(do-template [ ] + [(def: ( _) + Nullary + ( ))] + + [nat//min 0 python.int] + [nat//max -1 python.int] + + [frac//smallest Double::MIN_VALUE python.float] + [frac//min (f/* -1.0 Double::MAX_VALUE) python.float] + [frac//max Double::MAX_VALUE python.float] + + [deg//min 0 python.int] + [deg//max -1 python.int] + ) + +(do-template [ ] + [(def: ( _) + Nullary + )] + + [int//min (|> (python.int -2) (python.** (python.int 63)))] + [int//max (|> (python.int 2) (python.** (python.int 63)) (python.- (python.int 1)))] + ) + +(do-template [