From 5dbf134346424602b0104d1f749c1a9eac6f21af Mon Sep 17 00:00:00 2001 From: Eduardo Julian Date: Tue, 12 Jan 2021 17:31:48 -0400 Subject: Compiler now shows suggestions when encountering unknown definitions. --- compilers.md | 43 ++- lux-bootstrapper/src/lux/compiler/jvm.clj | 3 +- lux-js/source/program.lux | 44 ++- lux-lein/src/leiningen/lux/utils.clj | 21 +- lux-python/project.clj | 4 +- lux-python/source/program.lux | 410 +++++++++++++-------- stdlib/source/lux/data/collection/list.lux | 45 ++- stdlib/source/lux/data/collection/set.lux | 17 +- stdlib/source/lux/data/collection/set/multi.lux | 2 +- stdlib/source/lux/data/maybe.lux | 4 +- stdlib/source/lux/host.old.lux | 24 +- stdlib/source/lux/meta.lux | 74 ++-- stdlib/source/lux/target/python.lux | 123 ++++--- stdlib/source/lux/time/month.lux | 13 +- .../lux/phase/extension/generation/python.lux | 5 +- .../phase/extension/generation/python/common.lux | 53 ++- .../compiler/language/lux/phase/generation/js.lux | 2 +- .../language/lux/phase/generation/js/case.lux | 7 +- .../language/lux/phase/generation/js/function.lux | 12 +- .../language/lux/phase/generation/js/runtime.lux | 20 +- .../language/lux/phase/generation/python.lux | 21 +- .../language/lux/phase/generation/python/case.lux | 240 +++++++----- .../lux/phase/generation/python/function.lux | 79 ++-- .../language/lux/phase/generation/python/loop.lux | 11 +- .../lux/phase/generation/python/reference.lux | 14 +- .../lux/phase/generation/python/runtime.lux | 222 +++++------ stdlib/source/program/aedifex/artifact/build.lux | 43 +++ stdlib/source/test/aedifex/artifact/build.lux | 34 ++ stdlib/source/test/lux/abstract.lux | 2 + stdlib/source/test/lux/abstract/hash.lux | 39 ++ stdlib/source/test/lux/data/collection/list.lux | 5 + stdlib/source/test/lux/data/collection/set.lux | 5 + .../source/test/lux/data/collection/set/multi.lux | 8 +- stdlib/source/test/lux/data/maybe.lux | 5 + stdlib/source/test/lux/data/name.lux | 5 + stdlib/source/test/lux/data/text.lux | 4 + stdlib/source/test/lux/locale.lux | 22 +- stdlib/source/test/lux/time/month.lux | 93 +++-- 38 files changed, 1116 insertions(+), 662 deletions(-) create mode 100644 stdlib/source/program/aedifex/artifact/build.lux create mode 100644 stdlib/source/test/aedifex/artifact/build.lux create mode 100644 stdlib/source/test/lux/abstract/hash.lux diff --git a/compilers.md b/compilers.md index 8b331622a..917c5909d 100644 --- a/compilers.md +++ b/compilers.md @@ -78,8 +78,23 @@ cd ~/lux/lux-js/ && lein clean && lein lux auto test cd ~/lux/lux-js/ && lein lux auto build cd ~/lux/lux-js/ && lein clean && lein lux auto build +## Build JVM-based compiler +cd ~/lux/lux-js/ \ +&& lein clean \ +&& lein lux build \ +&& mv target/program.jar program.jar + ## Use JVM-based compiler to produce a JS/Node-based compiler. -cd ~/lux/lux-js/ && lein clean && lein lux build && mv target/program.jar program.jar +cd ~/lux/lux-js/ \ +&& lein clean \ +&& time java -jar program.jar build --source ~/lux/lux-js/source --target ~/lux/lux-js/target --module program \ +&& mv target/program.js program.js + +## Use JS/Node-based compiler to produce another JS/Node-based compiler. +cd ~/lux/lux-js/ \ +&& lein clean \ +&& cd ~/lux/lux-js/ \ +&& time node --stack_size=8192 program.js build --source ~/lux/lux-js/source --target ~/lux/lux-js/target --module program ``` ## Try @@ -88,15 +103,7 @@ cd ~/lux/lux-js/ && lein clean && lein lux build && mv target/program.jar progra cd ~/lux/stdlib/ && lein clean && cd ~/lux/lux-js/ && time java -jar program.jar build --source ~/lux/stdlib/source --target ~/lux/stdlib/target --module test/lux cd ~/lux/stdlib/target/ && node program.js -cd ~/lux/lux-js/ && lein clean && time java -jar program.jar build --source ~/lux/lux-js/source --target ~/lux/lux-js/target --module program && mv target/program.js program.js - cd ~/lux/stdlib/ && lein clean && cd ~/lux/lux-js/ && time node --stack_size=8192 program.js build --source ~/lux/stdlib/source --target ~/lux/stdlib/target --module test/lux - -## Use JS/Node-based compiler to produce another JS/Node-based compiler. -cd ~/lux/lux-js/ \ -&& lein clean \ -&& cd ~/lux/lux-js/ \ -&& time node --stack_size=8192 program.js build --source ~/lux/lux-js/source --target ~/lux/lux-js/target --module program ``` --- @@ -113,8 +120,22 @@ cd ~/lux/lux-python/ && lein clean && lein lux auto test ## Build ``` -cd ~/lux/lux-python/ && lein lux auto build -cd ~/lux/lux-python/ && lein clean && lein lux auto build +## Develop +cd ~/lux/lux-python/ \ +&& lein clean \ +&& lein lux auto build + +## Build JVM-based compiler +cd ~/lux/lux-python/ \ +&& lein clean \ +&& lein lux build \ +&& mv target/program.jar program.jar + +## Use JVM-based compiler to produce a Python-based compiler. +cd ~/lux/lux-python/ \ +&& lein clean \ +&& time java -jar program.jar build --source ~/lux/lux-python/source --target ~/lux/lux-python/target --module program \ +&& mv target/program.js program.js ``` ## Try diff --git a/lux-bootstrapper/src/lux/compiler/jvm.clj b/lux-bootstrapper/src/lux/compiler/jvm.clj index 07c28dfac..bacf2cb9c 100644 --- a/lux-bootstrapper/src/lux/compiler/jvm.clj +++ b/lux-bootstrapper/src/lux/compiler/jvm.clj @@ -219,7 +219,8 @@ (findClass [^String class-name] (if-let [^bytes bytecode (get @store class-name)] (.invoke define-class this (to-array [class-name bytecode (int 0) (int (alength bytecode))])) - (throw (IllegalStateException. (str "[Class Loader] Unknown class: " class-name)))))))) + (throw (new IllegalStateException + (str "[Class Loader] Unknown class: " class-name)))))))) (defn jvm-host [] (let [store (atom {})] diff --git a/lux-js/source/program.lux b/lux-js/source/program.lux index c923aace5..48392d358 100644 --- a/lux-js/source/program.lux +++ b/lux-js/source/program.lux @@ -562,8 +562,8 @@ #platform.runtime runtime.generate #platform.write (|>> _.code (\ encoding.utf8 encode))}))) -(def: (program namer context program) - (-> (-> Context Text) (Program _.Expression _.Statement)) +(def: (program context program) + (-> (Program _.Expression _.Statement)) (let [@process (_.var "process") on_node_js? (|> (|> @process _.type_of (_.= (_.string "undefined")) _.not) (_.and (|> @process (_.the "argv")))) @@ -619,21 +619,25 @@ (list)))) (program: [{service /cli.service}] - (exec (do promise.monad - [_ (/.compiler {#/static.host @.js - #/static.host_module_extension ".js" - #/static.target (/cli.target service) - #/static.artifact_extension ".js"} - ..expander - analysis.bundle - ..platform - generation.bundle - extension/bundle.empty - (..program reference.artifact) - [(& Register Text) _.Expression _.Statement] - ..extender - service - [(packager.package _.use_strict _.code _.then ..scope) - (format (/cli.target service) (\ file.default separator) "program.js")])] - (..declare_success! [])) - (io.io []))) + (let [extension ".js"] + (exec (do promise.monad + [_ (/.compiler {#/static.host @.js + #/static.host_module_extension extension + #/static.target (/cli.target service) + #/static.artifact_extension extension} + ..expander + analysis.bundle + ..platform + generation.bundle + extension/bundle.empty + ..program + [(& Register Text) _.Expression _.Statement] + ..extender + service + [(packager.package _.use_strict _.code _.then ..scope) + (format (/cli.target service) + (\ file.default separator) + "program" + extension)])] + (..declare_success! [])) + (io.io [])))) diff --git a/lux-lein/src/leiningen/lux/utils.clj b/lux-lein/src/leiningen/lux/utils.clj index e2ec2c1ca..8aea46c44 100644 --- a/lux-lein/src/leiningen/lux/utils.clj +++ b/lux-lein/src/leiningen/lux/utils.clj @@ -116,16 +116,17 @@ deps (list* stdlib-path deps))) compiler-path (prepare-path (find-compiler-path raw-paths)) - class-path (->> compiler-dependencies - (list* compiler-path) - (interpose java.io.File/pathSeparator) - (reduce str "") - sanitize-path) - module-path (->> program-dependencies - (interpose java.io.File/pathSeparator) - (reduce str "") - sanitize-path)] - (str (java-command project) " -cp " class-path " --module-path " module-path + compiler-class-path (->> compiler-dependencies + (list* compiler-path) + (interpose java.io.File/pathSeparator) + (reduce str "") + sanitize-path) + program-class-path (->> program-dependencies + (interpose java.io.File/pathSeparator) + (reduce str "") + sanitize-path)] + (str (java-command project) + " -cp " (str compiler-class-path java.io.File/pathSeparator program-class-path) " " (lux-command project program-dependencies source-paths)))) compile-path (str "release " module) diff --git a/lux-python/project.clj b/lux-python/project.clj index 9722945b5..887cd2b89 100644 --- a/lux-python/project.clj +++ b/lux-python/project.clj @@ -20,9 +20,9 @@ ["snapshots" {:url ~sonatype-snapshots :creds :gpg}]] :plugins [[com.github.luxlang/lein-luxc ~version]] - :dependencies [[com.github.luxlang/luxc-jvm ~version] + :dependencies [[com.github.luxlang/lux-bootstrapper ~version] [com.github.luxlang/stdlib ~version] - [org.python/jython-standalone "2.7.1"]] + [org.python/jython-standalone "2.7.2"]] :manifest {"lux" ~version} :source-paths ["source"] diff --git a/lux-python/source/program.lux b/lux-python/source/program.lux index 756b27b9c..2acae70d3 100644 --- a/lux-python/source/program.lux +++ b/lux-python/source/program.lux @@ -1,144 +1,169 @@ (.module: [lux #* + [program (#+ program:)] + ["." host (#+ import: interface: do_to object)] [abstract [monad (#+ do)]] [control - pipe - [cli (#+ program:)] + [pipe (#+ new>)] + ["." try (#+ Try)] ["." exception (#+ exception:)] - ["." io (#+ IO io)]] + ["." io (#+ IO io)] + [concurrency + ["." promise (#+ Promise)]]] [data ["." maybe] - ["." error (#+ Error)] - [number - ["." i64]] - ["." text ("#@." hash) - format] + ["." text ("#\." hash) + ["%" format (#+ format)] + ["." encoding]] [collection - ["." array (#+ Array)] - ["." list ("#@." functor)]]] + ["." array (#+ Array)]]] [macro ["." template]] - [world - ["." file]] - ["." host (#+ import: interface: do-to object) + [math + [number + ["n" nat] + ["." i64]]] + ["." world #_ + ["." file] + ["#/." program]] + ["@" target ["_" python]] [tool [compiler - ["." name] - ["." synthesis] - [phase - [macro (#+ Expander)] - ["." generation - ["." python - ["." runtime] - ["." extension]]]] + [phase (#+ Operation Phase)] + [language + [lux + [program (#+ Program)] + [generation (#+ Context Host)] + ["." synthesis] + [analysis + [macro (#+ Expander)]] + [phase + ["." extension (#+ Extender Handler) + ["#/." bundle] + ["." generation #_ + ["#" python]]] + [generation + ["." reference] + ["." python + ["." runtime]]]]]] [default - ["." platform (#+ Platform)]]]]] + ["." platform (#+ Platform)]] + [meta + ["." packager #_ + ["#" script]]]]]] [program ["/" compositor - ["/." cli]]]) - -(import: #long java/lang/String) - -(import: #long (java/lang/Class a)) - -(import: #long java/lang/Object - (new []) - (toString [] java/lang/String) - (getClass [] (java/lang/Class java/lang/Object))) - -(import: #long org/python/core/PyNone) -(import: #long org/python/core/PyBoolean) -(import: #long org/python/core/PyInteger) -(import: #long org/python/core/PyLong) -(import: #long org/python/core/PyFloat) -(import: #long org/python/core/PyTuple) -(import: #long org/python/core/PyList) - -(import: #long org/python/core/PyString - (new [java/lang/String])) - -(import: #long org/python/core/PyObject - (asInt [] java/lang/Integer) - (asLong [] long) - (asDouble [] double) - (asString [] java/lang/String) - (__nonzero__ [] boolean) - (__getitem__ [int] #try org/python/core/PyObject) - (__getitem__ #as __getitem__dict [org/python/core/PyObject] #try org/python/core/PyObject) - (__len__ [] int)) - -(import: #long org/python/core/PyFunction - (__call__ [[org/python/core/PyObject]] org/python/core/PyObject)) - -(import: #long org/python/core/PyArray - (new [(java/lang/Class java/lang/Object) java/lang/Object]) - (getArray [] java/lang/Object)) - -(import: #long org/python/util/PythonInterpreter - (new []) - (exec [String] #try void) - (eval [String] #try PyObject)) + ["/." cli] + ["/." static]]]) + +(import: java/lang/String) + +(import: (java/lang/Class a)) + +(import: java/lang/Object + ["#::." + (new []) + (toString [] java/lang/String) + (getClass [] (java/lang/Class java/lang/Object))]) + +(import: org/python/core/PyNone) +(import: org/python/core/PyBoolean) +(import: org/python/core/PyInteger) +(import: org/python/core/PyLong) +(import: org/python/core/PyFloat) +(import: org/python/core/PyTuple) +(import: org/python/core/PyList) + +(import: org/python/core/PyString + ["#::." + (new [java/lang/String])]) + +(import: org/python/core/PyObject + ["#::." + (asInt [] java/lang/Integer) + (asLong [] long) + (asDouble [] double) + (asString [] java/lang/String) + (__nonzero__ [] boolean) + (__getitem__ [int] #try org/python/core/PyObject) + (__getitem__ #as __getitem__dict [org/python/core/PyObject] #try org/python/core/PyObject) + (__len__ [] int)]) + +(import: org/python/core/PyFunction + ["#::." + (__call__ [[org/python/core/PyObject]] org/python/core/PyObject)]) + +(import: org/python/core/PyArray + ["#::." + (new [(java/lang/Class java/lang/Object) java/lang/Object]) + (getArray [] java/lang/Object)]) + +(import: org/python/util/PythonInterpreter + ["#::." + (new []) + (exec [java/lang/String] #try void) + (eval [java/lang/String] #try PyObject)]) (type: Translator - (-> org/python/core/PyObject (Error Any))) + (-> org/python/core/PyObject (Try Any))) -(def: (read-tuple read host-object) +(def: (read_tuple read host_object) (-> Translator Translator) - (let [size (|> host-object org/python/core/PyObject::__len__ .nat)] + (let [size (|> host_object org/python/core/PyObject::__len__ .nat)] (loop [idx 0 output (:coerce (Array Any) (array.new size))] - (if (n/< size idx) - (case (org/python/core/PyObject::__getitem__ (.int idx) host-object) - (#error.Failure error) - (#error.Failure error) + (if (n.< size idx) + (case (org/python/core/PyObject::__getitem__ (.int idx) host_object) + (#try.Failure try) + (#try.Failure try) - (#error.Success value) + (#try.Success value) (case (read value) - (#error.Failure error) - (#error.Failure error) + (#try.Failure try) + (#try.Failure try) - (#error.Success lux-value) - (recur (inc idx) (array.write idx lux-value output)))) - (#error.Success output))))) + (#try.Success lux_value) + (recur (inc idx) (array.write! idx lux_value output)))) + (#try.Success output))))) -(exception: (unknown-kind-of-object {object java/lang/Object}) +(exception: (unknown_kind_of_object {object java/lang/Object}) (exception.report ["Object" (java/lang/Object::toString object)])) -(def: (read-variant read host-object) +(def: (read_variant read host_object) (-> Translator Translator) - (case [(org/python/core/PyObject::__getitem__ +0 host-object) - (org/python/core/PyObject::__getitem__ +1 host-object) - (org/python/core/PyObject::__getitem__ +2 host-object)] - (^or [(#error.Failure error) _ _] [_ (#error.Failure error) _] [_ _ (#error.Failure error)]) - (#error.Failure error) + (case [(org/python/core/PyObject::__getitem__ +0 host_object) + (org/python/core/PyObject::__getitem__ +1 host_object) + (org/python/core/PyObject::__getitem__ +2 host_object)] + (^or [(#try.Failure try) _ _] [_ (#try.Failure try) _] [_ _ (#try.Failure try)]) + (#try.Failure try) - (^multi [(#error.Success tag) (#error.Success flag) (#error.Success value)] + (^multi [(#try.Success tag) (#try.Success flag) (#try.Success value)] [(read tag) - (#error.Success tag)] + (#try.Success tag)] [(read value) - (#error.Success value)]) - (#error.Success [tag - (: Any - (case (host.check org/python/core/PyNone flag) - (#.Some _) - (host.null) + (#try.Success value)]) + (#try.Success [tag + (: Any + (case (host.check org/python/core/PyNone flag) + (#.Some _) + (host.null) - #.None - synthesis.unit)) - value]) + #.None + synthesis.unit)) + value]) _ - (exception.throw ..unknown-kind-of-object host-object))) + (exception.throw ..unknown_kind_of_object host_object))) -(def: (read host-object) +(def: (read host_object) Translator (`` (<| (~~ (template [ ] - [(case (host.check host-object) - (#.Some host-object) - (#error.Success (<| host-object)) + [(case (host.check host_object) + (#.Some host_object) + (#try.Success (<| host_object)) _)] @@ -153,115 +178,192 @@ [[java/lang/Object] (|>)] )) (~~ (template [ ] - [(case (host.check host-object) - (#.Some host-object) - (<| host-object) + [(case (host.check host_object) + (#.Some host_object) + (<| host_object) _)] - [org/python/core/PyTuple (..read-variant read)] - [org/python/core/PyList (..read-tuple read)] + [org/python/core/PyTuple (..read_variant read)] + [org/python/core/PyList (..read_tuple read)] )) - (exception.throw ..unknown-kind-of-object host-object)))) + (exception.throw ..unknown_kind_of_object host_object)))) -(exception: (cannot-apply-a-non-function {object java/lang/Object}) +(exception: (cannot_apply_a_non_function {object java/lang/Object}) (exception.report ["Non-function" (java/lang/Object::toString object)])) -(def: (ensure-macro macro) +(def: (ensure_macro macro) (-> Macro (Maybe org/python/core/PyFunction)) (host.check org/python/core/PyFunction (:coerce java/lang/Object macro))) -(def: object-class +(def: object_class (java/lang/Class java/lang/Object) (java/lang/Object::getClass (java/lang/Object::new))) -(def: to-host +(def: to_host (-> Any org/python/core/PyObject) - (|>> (:coerce java/lang/Object) (org/python/core/PyArray::new ..object-class))) + (|>> (:coerce java/lang/Object) (org/python/core/PyArray::new ..object_class))) -(def: (call-macro inputs lux macro) - (-> (List Code) Lux org/python/core/PyFunction (Error (Error [Lux (List Code)]))) +(def: ensure_function + (-> Any (Maybe org/python/core/PyFunction)) + (|>> (:coerce java/lang/Object) + (host.check org/python/core/PyFunction))) + +(def: (call_macro inputs lux macro) + (-> (List Code) Lux org/python/core/PyFunction (Try (Try [Lux (List Code)]))) (<| :assume ..read (org/python/core/PyFunction::__call__ (|> (host.array org/python/core/PyObject 2) - (host.array-write 0 (..to-host inputs)) - (host.array-write 1 (..to-host lux))) + (host.array_write 0 (..to_host inputs)) + (host.array_write 1 (..to_host lux))) macro))) (def: (expander macro inputs lux) Expander - (case (ensure-macro macro) + (case (ensure_macro macro) (#.Some macro) - (case (call-macro inputs lux macro) - (#error.Success output) + (case (call_macro inputs lux macro) + (#try.Success output) (|> output (:coerce org/python/core/PyObject) ..read - (:coerce (Error (Error [Lux (List Code)])))) + (:coerce (Try (Try [Lux (List Code)])))) - (#error.Failure error) - (#error.Failure error)) + (#try.Failure try) + (#try.Failure try)) #.None - (exception.throw cannot-apply-a-non-function (:coerce java/lang/Object macro))) + (exception.throw ..cannot_apply_a_non_function (:coerce java/lang/Object macro))) ) (def: separator "___") -(type: Host - (generation.Host (_.Expression Any) (_.Statement Any))) - (def: host - (IO Host) + (IO (Host (_.Expression Any) (_.Statement Any))) (io (let [interpreter (org/python/util/PythonInterpreter::new) - evaluate! (: (-> Text (_.Expression Any) (Error Any)) - (function (evaluate! alias input) - (do error.monad + evaluate! (: (-> Context (_.Expression Any) (Try Any)) + (function (evaluate! context input) + (do try.monad [output (org/python/util/PythonInterpreter::eval (_.code input) interpreter)] (..read output)))) - execute! (: (-> Text (_.Statement Any) (Error Any)) - (function (execute! alias input) - (do error.monad + execute! (: (-> (_.Statement Any) (Try Any)) + (function (execute! input) + (do try.monad [_ (org/python/util/PythonInterpreter::exec (_.code input) interpreter)] (wrap []))))] - (: Host + (: (Host (_.Expression Any) (_.Statement Any)) (structure (def: evaluate! evaluate!) (def: execute! execute!) - (def: (define! [module name] input) - (let [global (format (text.replace-all .module-separator ..separator module) - ..separator (name.normalize name) - "___" (%n (text@hash name))) + (def: (define! context input) + (let [global (reference.artifact context) @global (_.var global)] - (do error.monad + (do try.monad [#let [definition (_.set (list @global) input)] - _ (execute! global definition) - value (evaluate! global @global)] - (wrap [global value definition]))))))))) + _ (execute! definition) + value (evaluate! context @global)] + (wrap [global value definition])))) + + (def: (ingest context content) + (|> content (\ encoding.utf8 decode) try.assume (:coerce (_.Statement Any)))) + + (def: (re_learn context content) + (execute! content)) + + (def: (re_load context content) + (do try.monad + [_ (execute! content)] + (evaluate! context (_.var (reference.artifact context)))))))))) (def: platform - (IO (Platform IO _.SVar (_.Expression Any) (_.Statement Any))) + (IO (Platform _.SVar (_.Expression Any) (_.Statement Any))) (do io.monad [host ..host] - (wrap {#platform.&monad io.monad - #platform.&file-system file.system + (wrap {#platform.&file_system (file.async file.default) #platform.host host #platform.phase python.generate - #platform.runtime runtime.generate}))) + #platform.runtime runtime.generate + #platform.write (|>> _.code (\ encoding.utf8 encode))}))) -(def: (program program) - (-> (_.Expression Any) (_.Statement Any)) +(def: (program context program) + (Program (_.Expression Any) (_.Statement Any)) ($_ _.then (_.import "sys") (_.when (_.= (_.string "__main__") (_.var "__name__")) (_.statement (_.apply/2 program - (runtime.lux//program-args (|> (_.var "sys") (_.the "argv"))) + (runtime.lux//program_args (|> (_.var "sys") (_.the "argv"))) _.none))))) +(for {@.old + (def: extender + Extender + ## TODO: Stop relying on coercions ASAP. + (<| (:coerce Extender) + (function (@self handler)) + (:coerce Handler) + (function (@self name phase)) + (:coerce Phase) + (function (@self archive parameters)) + (:coerce Operation) + (function (@self state)) + (:coerce Try) + try.assume + (:coerce Try) + (do try.monad + [handler (try.from_maybe (..ensure_function handler)) + output (host.try + (org/python/core/PyFunction::__call__ (|> (host.array org/python/core/PyObject 5) + (host.array_write 0 (org/python/core/PyString::new name)) + (host.array_write 1 (..to_host phase)) + (host.array_write 2 (..to_host archive)) + (host.array_write 3 (..to_host parameters)) + (host.array_write 4 (..to_host state))) + handler))] + (..read output)))) + + @.python + (def: (extender handler) + Extender + (:assume handler))}) + +(def: (declare_success! _) + (-> Any (Promise Any)) + (promise.future (\ world/program.default exit +0))) + +(def: (scope body) + (-> (_.Statement Any) (_.Statement Any)) + (let [@program (_.var "lux_program")] + ($_ _.then + (_.def @program (list) body) + (_.statement (_.apply/* @program (list))) + ))) + (program: [{service /cli.service}] - (/.compiler ..expander - ..platform - extension.bundle - ..program - service)) + (let [extension ".py"] + (exec (do promise.monad + [_ (/.compiler {#/static.host @.python + #/static.host_module_extension extension + #/static.target (/cli.target service) + #/static.artifact_extension extension} + ..expander + extension/bundle.empty + ..platform + generation.bundle + extension/bundle.empty + ..program + [_.SVar (type (_.Expression Any)) (type (_.Statement Any))] + ..extender + service + [(packager.package (<| (_.comment "-*- coding: utf-8 -*-") + (: (_.Statement Any) (_.manual ""))) + _.code + _.then + ..scope) + (format (/cli.target service) + (\ file.default separator) + "program" + extension)])] + (..declare_success! [])) + (io.io [])))) + diff --git a/stdlib/source/lux/data/collection/list.lux b/stdlib/source/lux/data/collection/list.lux index 62e88645a..432e98abd 100644 --- a/stdlib/source/lux/data/collection/list.lux +++ b/stdlib/source/lux/data/collection/list.lux @@ -316,16 +316,11 @@ (def: &equivalence (..equivalence (\ super &equivalence))) - (def: (hash value) - (case value - #.Nil - 2 - - (#.Cons head tail) - ($_ n.* 3 - (n.+ (\ super hash head) - (hash tail))) - ))) + (def: hash + (\ ..fold fold + (function (_ member hash) + (n.+ (\ super hash member) hash)) + 0))) (structure: #export monoid (All [a] (Monoid (List a))) @@ -333,8 +328,11 @@ (def: identity #.Nil) (def: (compose xs ys) (case xs - #.Nil ys - (#.Cons x xs') (#.Cons x (compose xs' ys))))) + #.Nil + ys + + (#.Cons x xs') + (#.Cons x (compose xs' ys))))) (open: "." ..monoid) @@ -343,8 +341,11 @@ (def: (map f ma) (case ma - #.Nil #.Nil - (#.Cons a ma') (#.Cons (f a) (map f ma'))))) + #.Nil + #.Nil + + (#.Cons a ma') + (#.Cons (f a) (map f ma'))))) (open: "." ..functor) @@ -389,15 +390,21 @@ (def: #export (empty? xs) (All [a] (Predicate (List a))) (case xs - #.Nil true - _ false)) + #.Nil + true + + _ + false)) (def: #export (member? eq xs x) (All [a] (-> (Equivalence a) (List a) a Bit)) (case xs - #.Nil #0 - (#.Cons x' xs') (or (\ eq = x x') - (member? eq xs' x)))) + #.Nil + #0 + + (#.Cons x' xs') + (or (\ eq = x x') + (member? eq xs' x)))) (template [ ] [(def: #export ( xs) diff --git a/stdlib/source/lux/data/collection/set.lux b/stdlib/source/lux/data/collection/set.lux index d0341b402..ca95a7a4b 100644 --- a/stdlib/source/lux/data/collection/set.lux +++ b/stdlib/source/lux/data/collection/set.lux @@ -2,16 +2,17 @@ [lux #* [abstract [equivalence (#+ Equivalence)] + [hash (#+ Hash)] [predicate (#+ Predicate)] - [monoid (#+ Monoid)] - ["." hash (#+ Hash)]] + [monoid (#+ Monoid)]] [data [collection - ["//" dictionary (#+ Dictionary)] ["." list ("#\." fold)]]] [math [number - ["n" nat]]]]) + ["n" nat]]]] + ["." // #_ + ["#" dictionary (#+ Dictionary)]]) (type: #export (Set a) (Dictionary a Any)) @@ -71,10 +72,10 @@ (def: &equivalence ..equivalence) - (def: (hash (^@ set [hash _])) - (list\fold (function (_ elem acc) (n.+ (\ hash hash elem) acc)) - 0 - (..to_list set)))) + (def: (hash set) + (|> set + ..to_list + (\ (list.hash (..member_hash set)) hash)))) (structure: #export (monoid hash) (All [a] (-> (Hash a) (Monoid (Set a)))) diff --git a/stdlib/source/lux/data/collection/set/multi.lux b/stdlib/source/lux/data/collection/set/multi.lux index fe5b2b8cb..6fd3a4671 100644 --- a/stdlib/source/lux/data/collection/set/multi.lux +++ b/stdlib/source/lux/data/collection/set/multi.lux @@ -130,7 +130,7 @@ (def: (hash (^:representation set)) (let [[hash _] set] (list\fold (function (_ [elem multiplicity] acc) - (|> elem (\ hash hash) (n.+ multiplicity) (n.+ acc))) + (|> elem (\ hash hash) (n.* multiplicity) (n.+ acc))) 0 (dictionary.entries set))))) ) diff --git a/stdlib/source/lux/data/maybe.lux b/stdlib/source/lux/data/maybe.lux index 6584eaf6a..a5a51300f 100644 --- a/stdlib/source/lux/data/maybe.lux +++ b/stdlib/source/lux/data/maybe.lux @@ -87,10 +87,10 @@ (def: (hash value) (case value #.None - 2 + 0 (#.Some value) - (.nat ("lux i64 *" (.int 3) (.int (\ super hash value))))))) + (\ super hash value)))) (structure: #export (with monad) (All [M] (-> (Monad M) (Monad (All [a] (M (Maybe a)))))) diff --git a/stdlib/source/lux/host.old.lux b/stdlib/source/lux/host.old.lux index 0d95d6e9e..2fc846e18 100644 --- a/stdlib/source/lux/host.old.lux +++ b/stdlib/source/lux/host.old.lux @@ -1634,25 +1634,29 @@ [=args (member_def_arg_bindings type_params class member)] (member_def_interop type_params kind class =args member method_prefix import_format)))) -(def: (interface? class) - (All [a] (-> (primitive "java.lang.Class" [a]) Bit)) - ("jvm invokevirtual:java.lang.Class:isInterface:" class)) +(type: (java/lang/Class a) + (primitive "java.lang.Class" [a])) + +(def: interface? + (All [a] (-> (java/lang/Class a) Bit)) + (|>> "jvm invokevirtual:java.lang.Class:isInterface:")) (def: (load_class class_name) - (-> Text (Try (primitive "java.lang.Class" [Any]))) - (try ("jvm invokestatic:java.lang.Class:forName:java.lang.String" class_name))) + (-> Text (Try (java/lang/Class Any))) + (..try ("jvm invokestatic:java.lang.Class:forName:java.lang.String" class_name))) (def: (class_kind [class_name _]) (-> Class_Declaration (Meta Class_Kind)) - (let [class_name (sanitize class_name)] - (case (load_class class_name) - (#.Right class) + (let [class_name (..sanitize class_name)] + (case (..load_class class_name) + (#try.Success class) (\ meta.monad wrap (if (interface? class) #Interface #Class)) - (#.Left _) - (meta.fail (format "Unknown class: " class_name))))) + (#try.Failure error) + (meta.fail (format "Cannot load class: " class_name text.new_line + error))))) (syntax: #export (import: {class_decl ..class_decl^} diff --git a/stdlib/source/lux/meta.lux b/stdlib/source/lux/meta.lux index e081280be..36a2294a2 100644 --- a/stdlib/source/lux/meta.lux +++ b/stdlib/source/lux/meta.lux @@ -12,7 +12,9 @@ ["." text ("#\." monoid equivalence)] ["." name ("#\." codec equivalence)] [collection - ["." list ("#\." monoid monad)]]] + ["." list ("#\." monoid monad)] + [dictionary + ["." plist]]]] [macro ["." code]] [math @@ -74,18 +76,6 @@ (#try.Success [compiler' ma]) (ma compiler'))))) -(def: (get k plist) - (All [a] - (-> Text (List [Text a]) (Maybe a))) - (case plist - #.Nil - #.None - - (#.Cons [k' v] plist') - (if (text\= k k') - (#.Some v) - (get k plist')))) - (def: #export (run' compiler action) (All [a] (-> Lux (Meta a) (Try [Lux a]))) (action compiler)) @@ -128,7 +118,7 @@ (def: #export (find_module name) (-> Text (Meta Module)) (function (_ compiler) - (case (get name (get@ #.modules compiler)) + (case (plist.get name (get@ #.modules compiler)) (#.Some module) (#try.Success [compiler module]) @@ -178,11 +168,11 @@ (-> (List [Text Module]) Text Text Text (Maybe Macro)) (do maybe.monad - [$module (get module modules) + [$module (plist.get module modules) definition (: (Maybe Global) (|> (: Module $module) (get@ #.definitions) - (get name)))] + (plist.get name)))] (case definition (#.Alias [r_module r_name]) (find_macro' modules this_module r_module r_name) @@ -215,7 +205,7 @@ (def: #export (module_exists? module) (-> Text (Meta Bit)) (function (_ compiler) - (#try.Success [compiler (case (get module (get@ #.modules compiler)) + (#try.Success [compiler (case (plist.get module (get@ #.modules compiler)) (#.Some _) #1 @@ -286,13 +276,15 @@ {#.doc "Looks-up a definition's whole data in the available modules (including the current one)."} (-> Name (Meta Global)) (do ..monad - [name (normalize name)] + [name (normalize name) + #let [[normal_module normal_short] name]] (function (_ compiler) (case (: (Maybe Global) (do maybe.monad - [#let [[v_prefix v_name] name] - (^slots [#.definitions]) (get v_prefix (get@ #.modules compiler))] - (get v_name definitions))) + [(^slots [#.definitions]) (|> compiler + (get@ #.modules) + (plist.get normal_module))] + (plist.get normal_short definitions))) (#.Some definition) (#try.Success [compiler definition]) @@ -302,15 +294,39 @@ (#try.Failure ($_ text\compose "Unknown definition: " (name\encode name) text.new_line " Current module: " current_module text.new_line - (case (get current_module (get@ #.modules compiler)) + (case (plist.get current_module (get@ #.modules compiler)) (#.Some this_module) - ($_ text\compose - " Imports: " (|> this_module (get@ #.imports) (text.join_with separator)) text.new_line - " Aliases: " (|> this_module (get@ #.module_aliases) (list\map (function (_ [alias real]) ($_ text\compose alias " => " real))) (text.join_with separator)) text.new_line) + (let [candidates (|> compiler + (get@ #.modules) + (list\map (function (_ [module_name module]) + (|> module + (get@ #.definitions) + (list.all (function (_ [def_name global]) + (case global + (#.Definition _) + (if (text\= normal_short def_name) + (#.Some (name\encode [module_name def_name])) + #.None) + + (#.Alias _) + #.None)))))) + list.concat + (text.join_with separator)) + imports (|> this_module + (get@ #.imports) + (text.join_with separator)) + aliases (|> this_module + (get@ #.module_aliases) + (list\map (function (_ [alias real]) ($_ text\compose alias " => " real))) + (text.join_with separator))] + ($_ text\compose + " Candidates: " candidates text.new_line + " Imports: " imports text.new_line + " Aliases: " aliases text.new_line)) _ "") - " All Known modules: " (|> compiler (get@ #.modules) (list\map product.left) (text.join_with separator)) text.new_line))))))) + " All known modules: " (|> compiler (get@ #.modules) (list\map product.left) (text.join_with separator)) text.new_line))))))) (def: #export (find_export name) {#.doc "Looks-up a definition's type in the available modules (including the current one)."} @@ -376,7 +392,7 @@ {#.doc "The entire list of globals in a module (including the non-exported/private ones)."} (-> Text (Meta (List [Text Global]))) (function (_ compiler) - (case (get module (get@ #.modules compiler)) + (case (plist.get module (get@ #.modules compiler)) #.None (#try.Failure ($_ text\compose "Unknown module: " module)) @@ -422,7 +438,7 @@ (do ..monad [#let [[module name] type_name] module (find_module module)] - (case (get name (get@ #.types module)) + (case (plist.get name (get@ #.types module)) (#.Some [tags _]) (wrap (#.Some tags)) @@ -473,7 +489,7 @@ =module (..find_module module) this_module_name ..current_module_name imported! (..imported? module)] - (case (get name (get@ #.tags =module)) + (case (plist.get name (get@ #.tags =module)) (#.Some [idx tag_list exported? type]) (if (or (text\= this_module_name module) (and imported! exported?)) diff --git a/stdlib/source/lux/target/python.lux b/stdlib/source/lux/target/python.lux index b71947d0b..3f0211e33 100644 --- a/stdlib/source/lux/target/python.lux +++ b/stdlib/source/lux/target/python.lux @@ -1,15 +1,12 @@ (.module: - [lux (#- Code not or and list if cond int comment) + [lux (#- Location Code not or and list if cond int comment) [abstract ["." enum]] [control [pipe (#+ new> case> cond>)] [parser - ["s" code]]] + ["<.>" code]]] [data - [number - ["n" nat] - ["f" frac]] ["." text ["%" format (#+ format)]] [collection @@ -18,15 +15,21 @@ ["." template] ["." code] [syntax (#+ syntax:)]] + [math + [number + ["n" nat] + ["f" frac]]] [type abstract]]) -(def: expression (-> Text Text) (text.enclose ["(" ")"])) +(def: expression + (-> Text Text) + (text.enclose ["(" ")"])) (def: nest (-> Text Text) - (|>> (format text.new-line) - (text.replace-all text.new-line (format text.new-line text.tab)))) + (|>> (format text.new_line) + (text.replace_all text.new_line (format text.new_line text.tab)))) (abstract: #export (Code brand) Text @@ -40,7 +43,7 @@ (|>> :representation)) (template [ ] - [(with-expansions [ (template.identifier [ "'"])] + [(with_expansions [ (template.identifier [ "'"])] (`` (abstract: #export ( brand) Any)) (`` (type: #export ( brand) ( ( brand)))))] @@ -53,7 +56,7 @@ ) (template [ ] - [(with-expansions [ (template.identifier [ "'"])] + [(with_expansions [ (template.identifier [ "'"])] (`` (abstract: #export Any)) (`` (type: #export ( ))))] @@ -108,11 +111,11 @@ (-> Frac Literal) (`` (|>> (cond> (~~ (template [ ] [[(f.= )] - [(new> (format "float(" text.double-quote text.double-quote ")") [])]] + [(new> (format "float(" text.double_quote text.double_quote ")") [])]] - [f.positive-infinity "inf"] - [f.negative-infinity "-inf"] - [f.not-a-number "nan"] + [f.positive_infinity "inf"] + [f.negative_infinity "-inf"] + [f.not_a_number "nan"] )) ## else @@ -122,43 +125,43 @@ (def: sanitize (-> Text Text) (`` (|>> (~~ (template [ ] - [(text.replace-all )] + [(text.replace_all )] ["\" "\\"] [text.tab "\t"] - [text.vertical-tab "\v"] + [text.vertical_tab "\v"] [text.null "\0"] - [text.back-space "\b"] - [text.form-feed "\f"] - [text.new-line "\n"] - [text.carriage-return "\r"] - [text.double-quote (format "\" text.double-quote)] + [text.back_space "\b"] + [text.form_feed "\f"] + [text.new_line "\n"] + [text.carriage_return "\r"] + [text.double_quote (format "\" text.double_quote)] )) ))) (def: #export string (-> Text Literal) (|>> ..sanitize - (text.enclose [text.double-quote text.double-quote]) + (text.enclose [text.double_quote text.double_quote]) :abstraction)) - (def: (composite-literal left-delimiter right-delimiter entry-serializer) + (def: (composite_literal left_delimiter right_delimiter entry_serializer) (All [a] (-> Text Text (-> a Text) (-> (List a) Literal))) (function (_ entries) (<| :abstraction ..expression - (format left-delimiter + (format left_delimiter (|> entries - (list\map entry-serializer) - (text.join-with ", ")) - right-delimiter)))) + (list\map entry_serializer) + (text.join_with ", ")) + right_delimiter)))) (template [
 ]
     [(def: #export 
        (-> (List (Expression Any)) Literal)
-       (composite-literal 
  ..code))]
+       (composite_literal 
  ..code))]
 
     [tuple "(" ")"]
     [list  "[" "]"]
@@ -170,7 +173,7 @@
         ..expression
         (format (:representation list) "[" (:representation from) ":" (:representation to) "]")))
 
-  (def: #export (slice-from from list)
+  (def: #export (slice_from from list)
     (-> (Expression Any) (Expression Any) Access)
     (<| :abstraction
         ..expression
@@ -178,21 +181,21 @@
 
   (def: #export dict
     (-> (List [(Expression Any) (Expression Any)]) (Computation Any))
-    (composite-literal "{" "}" (.function (_ [k v]) (format (:representation k) " : " (:representation v)))))
+    (composite_literal "{" "}" (.function (_ [k v]) (format (:representation k) " : " (:representation v)))))
 
   (def: #export (apply/* func args)
     (-> (Expression Any) (List (Expression Any)) (Computation Any))
     (<| :abstraction
         ..expression
-        (format (:representation func) "(" (text.join-with ", " (list\map ..code args)) ")")))
+        (format (:representation func) "(" (text.join_with ", " (list\map ..code args)) ")")))
 
   (template [  ]
     [(def: ( var)
        (-> (Expression Any) Text)
        (format  (:representation var)))]
 
-    [splat-poly    Poly    "*"]
-    [splat-keyword Keyword "**"]
+    [splat_poly    Poly    "*"]
+    [splat_keyword Keyword "**"]
     )
 
   (template [ ]
@@ -203,11 +206,11 @@
            (format (:representation func)
                    (format "(" (|> args
                                    (list\map (function (_ arg) (format (:representation arg) ", ")))
-                                   (text.join-with ""))
+                                   (text.join_with ""))
                            ( extra) ")"))))]
 
-    [apply-poly    splat-poly]
-    [apply-keyword splat-keyword]
+    [apply_poly    splat_poly]
+    [apply_keyword splat_keyword]
     )
 
   (def: #export (the name object)
@@ -224,8 +227,8 @@
            (-> (Expression Any) (Computation Any)))
        (|>> (..the method) ( args extra)))]
 
-    [do-poly    apply-poly]
-    [do-keyword apply-keyword]
+    [do_poly    apply_poly]
+    [do_keyword apply_keyword]
     )
 
   (def: #export (nth idx array)
@@ -257,11 +260,11 @@
     [/       "/"]
     [%       "%"]
     [**      "**"]
-    [bit-or  "|"]
-    [bit-and "&"]
-    [bit-xor "^"]
-    [bit-shl "<<"]
-    [bit-shr ">>"]
+    [bit_or  "|"]
+    [bit_and "&"]
+    [bit_xor "^"]
+    [bit_shl "<<"]
+    [bit_shr ">>"]
 
     [or      "or"]
     [and     "and"]
@@ -277,13 +280,13 @@
     (-> (List (Var Any)) (Expression Any) (Computation Any))
     (<| :abstraction
         ..expression
-        (format "lambda " (|> arguments (list\map ..code) (text.join-with ", ")) ": "
+        (format "lambda " (|> arguments (list\map ..code) (text.join_with ", ")) ": "
                 (:representation body))))
 
   (def: #export (set vars value)
     (-> (List (Location Any)) (Expression Any) (Statement Any))
     (:abstraction
-     (format (|> vars (list\map ..code) (text.join-with ", "))
+     (format (|> vars (list\map ..code) (text.join_with ", "))
              " = "
              (:representation value))))
 
@@ -296,7 +299,7 @@
     (:abstraction
      (format "if " (:representation test) ":"
              (..nest (:representation then!))
-             text.new-line "else:"
+             text.new_line "else:"
              (..nest (:representation else!)))))
 
   (def: #export (when test then!)
@@ -309,7 +312,7 @@
     (-> (Statement Any) (Statement Any) (Statement Any))
     (:abstraction
      (format (:representation pre!)
-             text.new-line
+             text.new_line
              (:representation post!))))
 
   (template [ <0>]
@@ -327,7 +330,7 @@
      (format "while " (:representation test) ":"
              (..nest (:representation body!)))))
 
-  (def: #export (for-in var inputs body!)
+  (def: #export (for_in var inputs body!)
     (-> SVar (Expression Any) (Statement Any) Loop)
     (:abstraction
      (format "for " (:representation var) " in " (:representation inputs) ":"
@@ -353,10 +356,10 @@
              (..nest (:representation body!))
              (|> excepts
                  (list\map (function (_ [classes exception catch!])
-                             (format text.new-line "except (" (text.join-with ", " (list\map ..code classes))
+                             (format text.new_line "except (" (text.join_with ", " (list\map ..code classes))
                                      ") as " (:representation exception) ":"
                                      (..nest (:representation catch!)))))
-                 (text.join-with "")))))
+                 (text.join_with "")))))
 
   (template [ ]
     [(def: #export ( message)
@@ -373,16 +376,16 @@
     (-> SVar (List (Ex [k] (Var k))) (Statement Any) (Statement Any))
     (:abstraction
      (format "def " (:representation name)
-             "(" (|> args (list\map ..code) (text.join-with ", ")) "):"
+             "(" (|> args (list\map ..code) (text.join_with ", ")) "):"
              (..nest (:representation body)))))
 
-  (def: #export (import module-name)
+  (def: #export (import module_name)
     (-> Text (Statement Any))
-    (:abstraction (format "import " module-name)))
+    (:abstraction (format "import " module_name)))
 
   (def: #export (comment commentary on)
     (All [brand] (-> Text (Code brand) (Code brand)))
-    (:abstraction (format "# "  (..sanitize commentary) text.new-line
+    (:abstraction (format "# "  (..sanitize commentary) text.new_line
                           (:representation on))))
   )
 
@@ -393,20 +396,20 @@
              else!
              (list.reverse clauses)))
 
-(syntax: (arity-inputs {arity s.nat})
+(syntax: (arity_inputs {arity .nat})
   (wrap (case arity
           0 (.list)
           _ (|> (dec arity)
                 (enum.range n.enum 0)
-                (list\map (|>> %.nat code.local-identifier))))))
+                (list\map (|>> %.nat code.local_identifier))))))
 
-(syntax: (arity-types {arity s.nat})
+(syntax: (arity_types {arity .nat})
   (wrap (list.repeat arity (` (Expression Any)))))
 
 (template [ +]
-  [(with-expansions [ (template.identifier ["apply/" ])
-                      (arity-inputs )
-                      (arity-types )
+  [(with_expansions [ (template.identifier ["apply/" ])
+                      (arity_inputs )
+                      (arity_types )
                       (template.splice +)]
      (def: #export ( function )
        (-> (Expression Any)  (Computation Any))
diff --git a/stdlib/source/lux/time/month.lux b/stdlib/source/lux/time/month.lux
index ba0408e34..60d66ce28 100644
--- a/stdlib/source/lux/time/month.lux
+++ b/stdlib/source/lux/time/month.lux
@@ -2,6 +2,7 @@
   [lux #*
    [abstract
     [equivalence (#+ Equivalence)]
+    [hash (#+ Hash)]
     [order (#+ Order)]
     [enum (#+ Enum)]]
    [control
@@ -70,7 +71,11 @@
 
   (exception: #export (invalid_month {number Nat})
     (exception.report
-     ["Number" (\ n.decimal encode number)]))
+     ["Number" (\ n.decimal encode number)]
+     ["Valid range" ($_ "lux text concat"
+                        (\ n.decimal encode (..number #January))
+                        " ~ "
+                        (\ n.decimal encode (..number #December)))]))
 
   (def: #export (by_number number)
     (-> Nat (Try Month))
@@ -81,6 +86,12 @@
       _ (exception.throw ..invalid_month [number])))
   )
 
+(structure: #export hash
+  (Hash Month)
+
+  (def: &equivalence ..equivalence)
+  (def: hash ..number))
+
 (structure: #export order
   (Order Month)
   
diff --git a/stdlib/source/lux/tool/compiler/language/lux/phase/extension/generation/python.lux b/stdlib/source/lux/tool/compiler/language/lux/phase/extension/generation/python.lux
index 536416b9d..6c09e4123 100644
--- a/stdlib/source/lux/tool/compiler/language/lux/phase/extension/generation/python.lux
+++ b/stdlib/source/lux/tool/compiler/language/lux/phase/extension/generation/python.lux
@@ -1,8 +1,5 @@
 (.module:
-  [lux #*
-   [data
-    [collection
-     ["." dictionary]]]]
+  [lux #*]
   ["." / #_
    ["#." common]
    [////
diff --git a/stdlib/source/lux/tool/compiler/language/lux/phase/extension/generation/python/common.lux b/stdlib/source/lux/tool/compiler/language/lux/phase/extension/generation/python/common.lux
index 1c58fec4c..14cc5f338 100644
--- a/stdlib/source/lux/tool/compiler/language/lux/phase/extension/generation/python/common.lux
+++ b/stdlib/source/lux/tool/compiler/language/lux/phase/extension/generation/python/common.lux
@@ -6,10 +6,11 @@
     ["." function]]
    [data
     ["." product]
-    [number
-     ["f" frac]]
     [collection
      ["." dictionary]]]
+   [math
+    [number
+     ["f" frac]]]
    [target
     ["_" python (#+ Expression)]]]
   [////
@@ -21,39 +22,34 @@
      ["//" python #_
       ["#." runtime (#+ Operation Phase Handler Bundle)]]]]])
 
-(def: lux-procs
+(def: lux_procs
   Bundle
   (|> /.empty
       (/.install "is" (binary (product.uncurry _.is)))
       (/.install "try" (unary //runtime.lux//try))))
 
-(def: i64-procs
+(def: i64_procs
   Bundle
   (<| (/.prefix "i64")
       (|> /.empty
-          (/.install "and" (binary (product.uncurry _.bit-and)))
-          (/.install "or" (binary (product.uncurry _.bit-or)))
-          (/.install "xor" (binary (product.uncurry _.bit-xor)))
-          (/.install "left-shift" (binary (function.compose //runtime.i64//64 (product.uncurry _.bit-shl))))
-          (/.install "logical-right-shift" (binary (product.uncurry //runtime.i64//logic-right-shift)))
-          (/.install "arithmetic-right-shift" (binary (product.uncurry _.bit-shr)))
+          (/.install "and" (binary (product.uncurry _.bit_and)))
+          (/.install "or" (binary (product.uncurry _.bit_or)))
+          (/.install "xor" (binary (product.uncurry _.bit_xor)))
+          (/.install "left-shift" (binary (function.compose //runtime.i64//64 (product.uncurry _.bit_shl))))
+          (/.install "logical-right-shift" (binary (product.uncurry //runtime.i64//logic_right_shift)))
+          (/.install "arithmetic-right-shift" (binary (product.uncurry _.bit_shr)))
+          (/.install "<" (binary (product.uncurry _.<)))
           (/.install "=" (binary (product.uncurry _.=)))
           (/.install "+" (binary (product.uncurry _.+)))
           (/.install "-" (binary (product.uncurry _.-)))
-          )))
-
-(def: int-procs
-  Bundle
-  (<| (/.prefix "int")
-      (|> /.empty
-          (/.install "<" (binary (product.uncurry _.<)))
           (/.install "*" (binary (product.uncurry _.*)))
           (/.install "/" (binary (product.uncurry _./)))
           (/.install "%" (binary (product.uncurry _.%)))
-          (/.install "frac" (unary _.float/1))
-          (/.install "char" (unary _.chr/1)))))
+          (/.install "f64" (unary _.float/1))
+          (/.install "char" (unary _.chr/1))
+          )))
 
-(def: frac-procs
+(def: frac_procs
   Bundle
   (<| (/.prefix "frac")
       (|> /.empty
@@ -76,7 +72,7 @@
   (Trinary (Expression Any))
   (//runtime.text//index textO partO startO))
 
-(def: text-procs
+(def: text_procs
   Bundle
   (<| (/.prefix "text")
       (|> /.empty
@@ -89,22 +85,21 @@
           (/.install "clip" (trinary text//clip))
           )))
 
-(def: io-procs
+(def: io_procs
   Bundle
   (<| (/.prefix "io")
       (|> /.empty
           (/.install "log" (unary //runtime.io//log!))
           (/.install "error" (unary //runtime.io//throw!))
           (/.install "exit" (unary //runtime.io//exit!))
-          (/.install "current-time" (nullary (function.constant (//runtime.io//current-time! //runtime.unit)))))))
+          (/.install "current-time" (nullary (function.constant (//runtime.io//current_time! //runtime.unit)))))))
 
 (def: #export bundle
   Bundle
   (<| (/.prefix "lux")
-      (|> lux-procs
-          (dictionary.merge i64-procs)
-          (dictionary.merge int-procs)
-          (dictionary.merge frac-procs)
-          (dictionary.merge text-procs)
-          (dictionary.merge io-procs)
+      (|> lux_procs
+          (dictionary.merge i64_procs)
+          (dictionary.merge frac_procs)
+          (dictionary.merge text_procs)
+          (dictionary.merge io_procs)
           )))
diff --git a/stdlib/source/lux/tool/compiler/language/lux/phase/generation/js.lux b/stdlib/source/lux/tool/compiler/language/lux/phase/generation/js.lux
index b8dbfc4ce..02197dc02 100644
--- a/stdlib/source/lux/tool/compiler/language/lux/phase/generation/js.lux
+++ b/stdlib/source/lux/tool/compiler/language/lux/phase/generation/js.lux
@@ -10,7 +10,7 @@
    [runtime (#+ Phase Phase!)]
    ["#." primitive]
    ["#." structure]
-   ["#." reference ("#\." system)]
+   ["#." reference]
    ["#." case]
    ["#." loop]
    ["#." function]
diff --git a/stdlib/source/lux/tool/compiler/language/lux/phase/generation/js/case.lux b/stdlib/source/lux/tool/compiler/language/lux/phase/generation/js/case.lux
index 3a828bbb9..4ba85c9b5 100644
--- a/stdlib/source/lux/tool/compiler/language/lux/phase/generation/js/case.lux
+++ b/stdlib/source/lux/tool/compiler/language/lux/phase/generation/js/case.lux
@@ -41,6 +41,7 @@
   (do ///////phase.monad
     [valueO (generate archive valueS)
      bodyO (generate archive bodyS)]
+    ## TODO: Find some way to do 'let' without paying the price of the closure.
     (wrap (_.apply/* (_.closure (list (..register register))
                                 (_.return bodyO))
                      (list valueO)))))
@@ -258,7 +259,7 @@
                                 (#.Cons cons))]
             (wrap (_.cond clauses ..fail_pm!)))
 
-          (^template [  ]
+          (^template [ ]
             [( cons)
              (do {! ///////phase.monad}
                [cases (monad.map ! (function (_ [match then])
@@ -267,8 +268,8 @@
                (wrap (_.switch ..peek_cursor
                                cases
                                (#.Some ..fail_pm!))))])
-          ([#/////synthesis.F64_Fork //primitive.f64 Frac]
-           [#/////synthesis.Text_Fork //primitive.text Text])
+          ([#/////synthesis.F64_Fork //primitive.f64]
+           [#/////synthesis.Text_Fork //primitive.text])
 
           (#/////synthesis.Then bodyS)
           (statement expression archive bodyS)
diff --git a/stdlib/source/lux/tool/compiler/language/lux/phase/generation/js/function.lux b/stdlib/source/lux/tool/compiler/language/lux/phase/generation/js/function.lux
index 0d47e9fe8..89fd86bb6 100644
--- a/stdlib/source/lux/tool/compiler/language/lux/phase/generation/js/function.lux
+++ b/stdlib/source/lux/tool/compiler/language/lux/phase/generation/js/function.lux
@@ -2,8 +2,6 @@
   [lux (#- function)
    [abstract
     ["." monad (#+ do)]]
-   [control
-    pipe]
    [data
     ["." product]
     [text
@@ -24,9 +22,9 @@
      ["#." generation (#+ Context)]
      ["//#" /// #_
       [arity (#+ Arity)]
+      ["#." phase ("#\." monad)]
       [reference
-       [variable (#+ Register Variable)]]
-      ["#." phase ("#\." monad)]]]]])
+       [variable (#+ Register Variable)]]]]]])
 
 (def: #export (apply generate archive [functionS argsS+])
   (Generator (Application Synthesis))
@@ -51,12 +49,14 @@
                     (_.return (_.function @self (list) function_body)))
        (_.apply/* @self inits)])))
 
-(def: @curried (_.var "curried"))
+(def: @curried
+  (_.var "curried"))
 
 (def: input
   (|>> inc //case.register))
 
-(def: @@arguments (_.var "arguments"))
+(def: @@arguments
+  (_.var "arguments"))
 
 (def: (@scope function_name)
   (-> Context Text)
diff --git a/stdlib/source/lux/tool/compiler/language/lux/phase/generation/js/runtime.lux b/stdlib/source/lux/tool/compiler/language/lux/phase/generation/js/runtime.lux
index a6cc85b10..c0f697584 100644
--- a/stdlib/source/lux/tool/compiler/language/lux/phase/generation/js/runtime.lux
+++ b/stdlib/source/lux/tool/compiler/language/lux/phase/generation/js/runtime.lux
@@ -5,8 +5,8 @@
     ["." monad (#+ do)]]
    [control
     ["." function]
-    ["p" parser
-     ["s" code]]]
+    ["<>" parser
+     ["<.>" code]]]
    [data
     ["." product]
     ["." text ("#\." hash)
@@ -32,7 +32,7 @@
    ["#." reference]
    ["//#" /// #_
     ["#." synthesis (#+ Synthesis)]
-    ["#." generation (#+ Buffer)]
+    ["#." generation]
     ["//#" /// (#+ Output)
      ["#." phase]
      [reference
@@ -73,7 +73,9 @@
   (let [mask (dec (i64.left_shift 32 1))]
     (|>> (i64.and mask))))
 
-(def: #export unit Computation (_.string /////synthesis.unit))
+(def: #export unit
+  Computation
+  (_.string /////synthesis.unit))
 
 (def: #export (flag value)
   (-> Bit Computation)
@@ -85,7 +87,7 @@
   (-> Var (-> Var Expression) Statement)
   (_.define name (definition name)))
 
-(syntax: #export (with_vars {vars (s.tuple (p.some s.local_identifier))}
+(syntax: #export (with_vars {vars (.tuple (<>.some .local_identifier))}
                    body)
   (do {! meta.monad}
     [ids (monad.seq ! (list.repeat (list.size vars) meta.count))]
@@ -105,9 +107,9 @@
     [(` (_.var (~ (code.text identifier))))
      (code.local_identifier identifier)]))
 
-(syntax: (runtime: {declaration (p.or s.local_identifier
-                                      (s.form (p.and s.local_identifier
-                                                     (p.some s.local_identifier))))}
+(syntax: (runtime: {declaration (<>.or .local_identifier
+                                       (.form (<>.and .local_identifier
+                                                            (<>.some .local_identifier))))}
            code)
   (case declaration
     (#.Left name)
@@ -786,7 +788,7 @@
 
 (def: #export artifact
   Text
-  prefix)
+  ..prefix)
 
 (def: #export generate
   (Operation [Registry Output])
diff --git a/stdlib/source/lux/tool/compiler/language/lux/phase/generation/python.lux b/stdlib/source/lux/tool/compiler/language/lux/phase/generation/python.lux
index d7e02b980..93300a02d 100644
--- a/stdlib/source/lux/tool/compiler/language/lux/phase/generation/python.lux
+++ b/stdlib/source/lux/tool/compiler/language/lux/phase/generation/python.lux
@@ -6,16 +6,20 @@
    [runtime (#+ Phase)]
    ["#." primitive]
    ["#." structure]
-   ["#." reference ("#\." system)]
+   ["#." reference]
    ["#." function]
    ["#." case]
    ["#." loop]
-   ["//#" /// #_
-    ["#." extension]
+   ["/#" // #_
+    ["#." reference]
     ["/#" // #_
-     ["#." synthesis]
-     ["//#" /// #_
-      ["#." phase ("#\." monad)]]]]])
+     ["#." extension]
+     ["/#" // #_
+      ["#." synthesis]
+      ["//#" /// #_
+       ["#." phase ("#\." monad)]
+       [reference (#+)
+        [variable (#+)]]]]]]])
 
 (def: #export (generate archive synthesis)
   Phase
@@ -35,7 +39,7 @@
     (/structure.tuple generate archive members)
 
     (#////synthesis.Reference value)
-    (/reference\reference archive value)
+    (//reference.reference /reference.system archive value)
 
     (^ (////synthesis.branch/case case))
     (/case.case generate archive case)
@@ -46,6 +50,9 @@
     (^ (////synthesis.branch/if if))
     (/case.if generate archive if)
 
+    (^ (////synthesis.branch/get get))
+    (/case.get generate archive get)
+
     (^ (////synthesis.loop/scope scope))
     (/loop.scope generate archive scope)
 
diff --git a/stdlib/source/lux/tool/compiler/language/lux/phase/generation/python/case.lux b/stdlib/source/lux/tool/compiler/language/lux/phase/generation/python/case.lux
index 4d5fc7f06..36700cf0c 100644
--- a/stdlib/source/lux/tool/compiler/language/lux/phase/generation/python/case.lux
+++ b/stdlib/source/lux/tool/compiler/language/lux/phase/generation/python/case.lux
@@ -1,22 +1,24 @@
 (.module:
   [lux (#- case let if)
    [abstract
-    [monad (#+ do)]]
+    ["." monad (#+ do)]]
    [control
-    ["ex" exception (#+ exception:)]]
+    [exception (#+ exception:)]]
    [data
     ["." text
      ["%" format (#+ format)]]
-    [number
-     ["n" nat]
-     ["i" int]]
     [collection
      ["." list ("#\." functor fold)]
      ["." set]]]
+   [math
+    [number
+     ["n" nat]
+     ["i" int]]]
    [target
     ["_" python (#+ Expression SVar Statement)]]]
   ["." // #_
    ["#." runtime (#+ Operation Phase Generator)]
+   ["#." reference]
    ["#." primitive]
    ["/#" // #_
     ["#." reference]
@@ -24,19 +26,22 @@
      [synthesis
       ["." case]]
      ["/#" // #_
-      ["#." synthesis (#+ Synthesis Path)]
+      ["#." synthesis (#+ Member Synthesis Path)]
       ["#." generation]
       ["//#" /// #_
-       ["#." reference (#+ Register)]
+       [reference
+        ["#." variable (#+ Register)]]
        ["#." phase ("#\." monad)]
        [meta
         [archive (#+ Archive)]]]]]]])
 
 (def: #export register
-  (///reference.local _.var))
+  (-> Register SVar)
+  (|>> (///reference.local //reference.system) :assume))
 
 (def: #export capture
-  (///reference.foreign _.var))
+  (-> Register SVar)
+  (|>> (///reference.foreign //reference.system) :assume))
 
 (def: #export (let generate archive [valueS register bodyS])
   (Generator [Synthesis Register Synthesis])
@@ -48,8 +53,16 @@
                                bodyO)
                      (list valueO)))))
 
-(def: #export (record-get generate archive [valueS pathP])
-  (Generator [Synthesis (List (Either Nat Nat))])
+(def: #export (if generate archive [testS thenS elseS])
+  (Generator [Synthesis Synthesis Synthesis])
+  (do ///////phase.monad
+    [testO (generate archive testS)
+     thenO (generate archive thenS)
+     elseO (generate archive elseS)]
+    (wrap (_.? testO thenO elseO))))
+
+(def: #export (get generate archive [pathP valueS])
+  (Generator [(List Member) Synthesis])
   (do ///////phase.monad
     [valueO (generate archive valueS)]
     (wrap (list\fold (function (_ side source)
@@ -63,14 +76,6 @@
                      valueO
                      pathP))))
 
-(def: #export (if generate archive [testS thenS elseS])
-  (Generator [Synthesis Synthesis Synthesis])
-  (do ///////phase.monad
-    [testO (generate archive testS)
-     thenO (generate archive thenS)
-     elseO (generate archive elseS)]
-    (wrap (_.? testO thenO elseO))))
-
 (def: @savepoint (_.var "lux_pm_savepoint"))
 (def: @cursor (_.var "lux_pm_cursor"))
 (def: @temp (_.var "lux_pm_temp"))
@@ -79,13 +84,13 @@
   (-> (Expression Any) (Statement Any))
   (_.statement (|> @cursor (_.do "append" (list value)))))
 
-(def: peek-and-pop
+(def: peek_and_pop
   (Expression Any)
   (|> @cursor (_.do "pop" (list))))
 
 (def: pop!
   (Statement Any)
-  (_.statement ..peek-and-pop))
+  (_.statement ..peek_and_pop))
 
 (def: peek
   (Expression Any)
@@ -93,18 +98,18 @@
 
 (def: save!
   (Statement Any)
-  (.let [cursor (_.slice-from (_.int +0) @cursor)]
+  (.let [cursor (_.slice_from (_.int +0) @cursor)]
     (_.statement (|> @savepoint (_.do "append" (list cursor))))))
 
 (def: restore!
   (Statement Any)
   (_.set (list @cursor) (|> @savepoint (_.do "pop" (list)))))
 
-(def: fail-pm! _.break)
+(def: fail_pm! _.break)
 
-(def: (multi-pop! pops)
+(def: (multi_pop! pops)
   (-> Nat (Statement Any))
-  (_.delete (_.slice-from (_.int (i.* -1 (.int pops))) @cursor)))
+  (_.delete (_.slice_from (_.int (i.* -1 (.int pops))) @cursor)))
 
 (template [  ]
   [(def: ( simple? idx)
@@ -113,14 +118,14 @@
          (_.set (list @temp) (|> idx  .int _.int (//runtime.sum//get ..peek )))
          (.if simple?
            (_.when (_.= _.none @temp)
-                   fail-pm!)
+                   fail_pm!)
            (_.if (_.= _.none @temp)
-             fail-pm!
+             fail_pm!
              (..push! @temp))
            )))]
 
-  [left-choice  _.none        (<|)]
-  [right-choice (_.string "") inc]
+  [left_choice  _.none        (<|)]
+  [right_choice (_.string "") inc]
   )
 
 (def: (alternation pre! post!)
@@ -134,79 +139,114 @@
           ..restore!
           post!)))
 
-(def: (pattern-matching' generate archive pathP)
+(def: (pattern_matching' generate archive)
   (-> Phase Archive Path (Operation (Statement Any)))
-  (.case pathP
-    (^ (/////synthesis.path/then bodyS))
-    (///////phase\map _.return (generate archive bodyS))
-
-    #/////synthesis.Pop
-    (///////phase\wrap ..pop!)
-
-    (#/////synthesis.Bind register)
-    (///////phase\wrap (_.set (list (..register register)) ..peek))
-
-    (^template [ ]
-      [(^ ( value))
-       (///////phase\wrap (_.when (|> value  (_.= ..peek) _.not)
-                                  fail-pm!))])
-    ([/////synthesis.path/bit  //primitive.bit]
-     [/////synthesis.path/i64  //primitive.i64]
-     [/////synthesis.path/f64  //primitive.f64]
-     [/////synthesis.path/text //primitive.text])
-
-    (^template [  ]
-      [(^ ( idx))
-       (///////phase\wrap ( false idx))
-
-       (^ ( idx nextP))
-       (|> nextP
-           (pattern-matching' generate archive)
-           (///////phase\map (_.then ( true idx))))])
-    ([/////synthesis.side/left  /////synthesis.simple-left-side  ..left-choice]
-     [/////synthesis.side/right /////synthesis.simple-right-side ..right-choice])
-
-    (^ (/////synthesis.member/left 0))
-    (///////phase\wrap (|> ..peek (_.nth (_.int +0)) ..push!))
-    
-    (^template [ ]
-      [(^ ( lefts))
-       (///////phase\wrap (|> ..peek ( (_.int (.int lefts))) ..push!))])
-    ([/////synthesis.member/left  //runtime.tuple//left]
-     [/////synthesis.member/right //runtime.tuple//right])
-
-    (^ (/////synthesis.!bind-top register thenP))
-    (do ///////phase.monad
-      [then! (pattern-matching' generate archive thenP)]
-      (///////phase\wrap ($_ _.then
-                             (_.set (list (..register register)) ..peek-and-pop)
-                             then!)))
-
-    (^ (/////synthesis.!multi-pop nextP))
-    (.let [[extra-pops nextP'] (case.count-pops nextP)]
+  (function (recur pathP)
+    (.case pathP
+      (^ (/////synthesis.path/then bodyS))
+      (///////phase\map _.return (generate archive bodyS))
+
+      #/////synthesis.Pop
+      (///////phase\wrap ..pop!)
+
+      (#/////synthesis.Bind register)
+      (///////phase\wrap (_.set (list (..register register)) ..peek))
+
+      (#/////synthesis.Bit_Fork when thenP elseP)
+      (do {! ///////phase.monad}
+        [then! (recur thenP)
+         else! (.case elseP
+                 (#.Some elseP)
+                 (recur elseP)
+
+                 #.None
+                 (wrap ..fail_pm!))]
+        (wrap (.if when
+                (_.if ..peek
+                  then!
+                  else!)
+                (_.if ..peek
+                  else!
+                  then!))))
+
+      (#/////synthesis.I64_Fork cons)
+      (do {! ///////phase.monad}
+        [clauses (monad.map ! (function (_ [match then])
+                                (do !
+                                  [then! (recur then)]
+                                  (wrap [(_.= (//primitive.i64 (.int match))
+                                              ..peek)
+                                         then!])))
+                            (#.Cons cons))]
+        (wrap (_.cond clauses
+                      ..fail_pm!)))
+
+      (^template [ ]
+        [( cons)
+         (do {! ///////phase.monad}
+           [clauses (monad.map ! (function (_ [match then])
+                                   (\ ! map
+                                      (|>> [(_.= ( match)
+                                                 ..peek)])
+                                      (recur then)))
+                               (#.Cons cons))]
+           (wrap (_.cond clauses
+                         ..fail_pm!)))])
+      ([#/////synthesis.F64_Fork //primitive.f64]
+       [#/////synthesis.Text_Fork //primitive.text])
+
+      (^template [  ]
+        [(^ ( idx))
+         (///////phase\wrap ( false idx))
+
+         (^ ( idx nextP))
+         (|> nextP
+             recur
+             (///////phase\map (_.then ( true idx))))])
+      ([/////synthesis.side/left  /////synthesis.simple_left_side  ..left_choice]
+       [/////synthesis.side/right /////synthesis.simple_right_side ..right_choice])
+
+      (^ (/////synthesis.member/left 0))
+      (///////phase\wrap (|> ..peek (_.nth (_.int +0)) ..push!))
+      
+      (^template [ ]
+        [(^ ( lefts))
+         (///////phase\wrap (|> ..peek ( (_.int (.int lefts))) ..push!))])
+      ([/////synthesis.member/left  //runtime.tuple//left]
+       [/////synthesis.member/right //runtime.tuple//right])
+
+      (^ (/////synthesis.!bind_top register thenP))
       (do ///////phase.monad
-        [next! (pattern-matching' generate archive nextP')]
+        [then! (recur thenP)]
         (///////phase\wrap ($_ _.then
-                               (..multi-pop! (n.+ 2 extra-pops))
-                               next!))))
-
-    (^template [ ]
-      [(^ ( preP postP))
-       (do ///////phase.monad
-         [pre! (pattern-matching' generate archive preP)
-          post! (pattern-matching' generate archive postP)]
-         (wrap ( pre! post!)))])
-    ([/////synthesis.path/seq _.then]
-     [/////synthesis.path/alt ..alternation])))
-
-(def: (pattern-matching generate archive pathP)
+                               (_.set (list (..register register)) ..peek_and_pop)
+                               then!)))
+
+      (^ (/////synthesis.!multi_pop nextP))
+      (.let [[extra_pops nextP'] (case.count_pops nextP)]
+        (do ///////phase.monad
+          [next! (recur nextP')]
+          (///////phase\wrap ($_ _.then
+                                 (..multi_pop! (n.+ 2 extra_pops))
+                                 next!))))
+
+      (^template [ ]
+        [(^ ( preP postP))
+         (do ///////phase.monad
+           [pre! (recur preP)
+            post! (recur postP)]
+           (wrap ( pre! post!)))])
+      ([/////synthesis.path/seq _.then]
+       [/////synthesis.path/alt ..alternation]))))
+
+(def: (pattern_matching generate archive pathP)
   (-> Phase Archive Path (Operation (Statement Any)))
   (do ///////phase.monad
-    [pattern-matching! (pattern-matching' generate archive pathP)]
+    [pattern_matching! (pattern_matching' generate archive pathP)]
     (wrap ($_ _.then
               (_.while (_.bool true)
-                       pattern-matching!)
-              (_.raise (_.Exception/1 (_.string case.pattern-matching-error)))))))
+                       pattern_matching!)
+              (_.raise (_.Exception/1 (_.string case.pattern_matching_error)))))))
 
 (def: (gensym prefix)
   (-> Text (Operation SVar))
@@ -216,24 +256,24 @@
   (Generator [Synthesis Path])
   (do ///////phase.monad
     [initG (generate archive valueS)
-     pattern-matching! (pattern-matching generate archive pathP)
+     pattern_matching! (pattern_matching generate archive pathP)
      @case (..gensym "case")
      @init (..gensym "init")
      #let [@dependencies+ (|> (case.storage pathP)
                               (get@ #case.dependencies)
-                              set.to-list
+                              set.to_list
                               (list\map (function (_ variable)
                                           (.case variable
-                                            (#///////reference.Local register)
+                                            (#///////variable.Local register)
                                             (..register register)
                                             
-                                            (#///////reference.Foreign register)
+                                            (#///////variable.Foreign register)
                                             (..capture register)))))]
      #let [directive (_.def @case (list& @init @dependencies+)
                             ($_ _.then
                                 (_.set (list @cursor) (_.list (list @init)))
                                 (_.set (list @savepoint) (_.list (list)))
-                                pattern-matching!))]
+                                pattern_matching!))]
      _ (/////generation.execute! directive)
      _ (/////generation.save! (_.code @case) directive)]
     (wrap (_.apply/* @case (list& initG @dependencies+)))))
diff --git a/stdlib/source/lux/tool/compiler/language/lux/phase/generation/python/function.lux b/stdlib/source/lux/tool/compiler/language/lux/phase/generation/python/function.lux
index 5ce811dfd..a4149f120 100644
--- a/stdlib/source/lux/tool/compiler/language/lux/phase/generation/python/function.lux
+++ b/stdlib/source/lux/tool/compiler/language/lux/phase/generation/python/function.lux
@@ -2,14 +2,14 @@
   [lux (#- function)
    [abstract
     ["." monad (#+ do)]]
-   [control
-    pipe]
    [data
     ["." product]
+    [text
+     ["%" format (#+ format)]]
     [collection
      ["." list ("#\." functor fold)]]]
    [target
-    ["_" python (#+ Expression Statement)]]]
+    ["_" python (#+ SVar Expression Statement)]]]
   ["." // #_
    [runtime (#+ Operation Phase Generator)]
    ["#." reference]
@@ -19,11 +19,12 @@
     ["//#" /// #_
      [analysis (#+ Variant Tuple Environment Abstraction Application Analysis)]
      [synthesis (#+ Synthesis)]
-     ["#." generation]
+     ["#." generation (#+ Context)]
      ["//#" /// #_
-      [reference (#+ Register Variable)]
       [arity (#+ Arity)]
-      ["#." phase]]]]])
+      ["#." phase]
+      [reference
+       [variable (#+ Register Variable)]]]]]])
 
 (def: #export (apply generate archive [functionS argsS+])
   (Generator (Application Synthesis))
@@ -33,16 +34,17 @@
     (wrap (_.apply/* functionO argsO+))))
 
 (def: #export capture
-  (///reference.foreign _.var))
+  (-> Register SVar)
+  (|>> (///reference.foreign //reference.system) :assume))
 
-(def: (with-closure function-name inits function-definition)
+(def: (with_closure function_name inits function_definition)
   (-> Text (List (Expression Any)) (Statement Any) (Operation (Expression Any)))
   (case inits
     #.Nil
     (do ///////phase.monad
-      [_ (/////generation.execute! function-definition)
-       _ (/////generation.save! function-name function-definition)]
-      (wrap (_.apply/* (_.var function-name) inits)))
+      [_ (/////generation.execute! function_definition)
+       _ (/////generation.save! function_name function_definition)]
+      (wrap (_.apply/* (_.var function_name) inits)))
 
     _
     (do {! ///////phase.monad}
@@ -51,60 +53,63 @@
                               (|> (list.enumeration inits)
                                   (list\map (|>> product.left ..capture)))
                               ($_ _.then
-                                  function-definition
-                                  (_.return (_.var function-name))))]
-       _ (/////generation.execute! function-definition)
+                                  function_definition
+                                  (_.return (_.var function_name))))]
+       _ (/////generation.execute! function_definition)
        _ (/////generation.save! (_.code @closure) directive)]
       (wrap (_.apply/* @closure inits)))))
 
 (def: input
   (|>> inc //case.register))
 
+(def: (@scope function_name)
+  (-> Context Text)
+  (format (///reference.artifact function_name) "_scope"))
+
 (def: #export (function generate archive [environment arity bodyS])
   (Generator (Abstraction Synthesis))
   (do {! ///////phase.monad}
-    [[function-name bodyO] (/////generation.with-new-context
+    [[function_name bodyO] (/////generation.with_new_context archive
                              (do !
-                               [function-name (\ ! map ///reference.artifact-name
-                                                 /////generation.context)]
-                               (/////generation.with-anchor (_.var function-name)
+                               [function_name (\ ! map ..@scope
+                                                 (/////generation.context archive))]
+                               (/////generation.with_anchor (_.var function_name)
                                  (generate archive bodyS))))
-     closureO+ (: (Operation (List (Expression Any)))
-                  (monad.map ! (\ //reference.system variable) environment))
-     #let [function-name (///reference.artifact-name function-name)
+     environment (monad.map ! (generate archive) environment)
+     #let [function_name (///reference.artifact function_name)
            @curried (_.var "curried")
            arityO (|> arity .int _.int)
-           @num-args (_.var "num_args")
-           @self (_.var function-name)
-           apply-poly (.function (_ args func)
-                        (_.apply-poly (list) args func))
-           initialize-self! (_.set (list (//case.register 0)) @self)
+           @num_args (_.var "num_args")
+           @self (_.var function_name)
+           apply_poly (.function (_ args func)
+                        (_.apply_poly (list) args func))
+           initialize_self! (_.set (list (//case.register 0)) @self)
            initialize! (list\fold (.function (_ post pre!)
                                     ($_ _.then
                                         pre!
                                         (_.set (list (..input post)) (_.nth (|> post .int _.int) @curried))))
-                                  initialize-self!
+                                  initialize_self!
                                   (list.indices arity))]]
-    (with-closure function-name closureO+
+    (with_closure function_name environment
       (_.def @self (list (_.poly @curried))
              ($_ _.then
-                 (_.set (list @num-args) (_.len/1 @curried))
-                 (_.cond (list [(|> @num-args (_.= arityO))
+                 (_.set (list @num_args) (_.len/1 @curried))
+                 (_.cond (list [(|> @num_args (_.= arityO))
                                 ($_ _.then
                                     initialize!
                                     (_.return bodyO))]
-                               [(|> @num-args (_.> arityO))
-                                (let [arity-inputs (_.slice (_.int +0) arityO @curried)
-                                      extra-inputs (_.slice arityO @num-args @curried)]
+                               [(|> @num_args (_.> arityO))
+                                (let [arity_inputs (_.slice (_.int +0) arityO @curried)
+                                      extra_inputs (_.slice arityO @num_args @curried)]
                                   (_.return (|> @self
-                                                (apply-poly arity-inputs)
-                                                (apply-poly extra-inputs))))])
-                         ## (|> @num-args (_.< arityO))
+                                                (apply_poly arity_inputs)
+                                                (apply_poly extra_inputs))))])
+                         ## (|> @num_args (_.< arityO))
                          (let [@next (_.var "next")
                                @missing (_.var "missing")]
                            ($_ _.then
                                (_.def @next (list (_.poly @missing))
-                                      (_.return (|> @self (apply-poly (|> @curried (_.+ @missing))))))
+                                      (_.return (|> @self (apply_poly (|> @curried (_.+ @missing))))))
                                (_.return @next)
                                )))
                  )))
diff --git a/stdlib/source/lux/tool/compiler/language/lux/phase/generation/python/loop.lux b/stdlib/source/lux/tool/compiler/language/lux/phase/generation/python/loop.lux
index 14868757d..d8914d1e6 100644
--- a/stdlib/source/lux/tool/compiler/language/lux/phase/generation/python/loop.lux
+++ b/stdlib/source/lux/tool/compiler/language/lux/phase/generation/python/loop.lux
@@ -4,12 +4,13 @@
     ["." monad (#+ do)]]
    [data
     ["." product]
-    [number
-     ["n" nat]]
     [text
      ["%" format (#+ format)]]
     [collection
      ["." list ("#\." functor)]]]
+   [math
+    [number
+     ["n" nat]]]
    [target
     ["_" python (#+ Expression SVar)]]]
   ["." // #_
@@ -21,16 +22,16 @@
     ["//#" /// #_
      ["#." phase]]]])
 
-(def: loop-name
+(def: loop_name
   (-> Nat SVar)
   (|>> %.nat (format "loop") _.var))
 
 (def: #export (scope generate archive [start initsS+ bodyS])
   (Generator (Scope Synthesis))
   (do {! ///////phase.monad}
-    [@loop (\ ! map ..loop-name /////generation.next)
+    [@loop (\ ! map ..loop_name /////generation.next)
      initsO+ (monad.map ! (generate archive) initsS+)
-     bodyO (/////generation.with-anchor @loop
+     bodyO (/////generation.with_anchor @loop
              (generate archive bodyS))
      #let [directive (_.def @loop (|> initsS+
                                       list.enumeration
diff --git a/stdlib/source/lux/tool/compiler/language/lux/phase/generation/python/reference.lux b/stdlib/source/lux/tool/compiler/language/lux/phase/generation/python/reference.lux
index 41ff5a802..0f7629614 100644
--- a/stdlib/source/lux/tool/compiler/language/lux/phase/generation/python/reference.lux
+++ b/stdlib/source/lux/tool/compiler/language/lux/phase/generation/python/reference.lux
@@ -2,11 +2,11 @@
   [lux #*
    [target
     ["_" python (#+ Expression)]]]
-  ["." /// #_
-   ["#." reference]])
+  [///
+   [reference (#+ System)]])
 
-(def: #export system
-  (let [constant (: (-> Text (Expression Any))
-                    _.var)
-        variable constant]
-    (///reference.system constant variable)))
+(structure: #export system
+  (System (Expression Any))
+
+  (def: constant _.var)
+  (def: variable _.var))
diff --git a/stdlib/source/lux/tool/compiler/language/lux/phase/generation/python/runtime.lux b/stdlib/source/lux/tool/compiler/language/lux/phase/generation/python/runtime.lux
index 7469aaa7d..876fab6a9 100644
--- a/stdlib/source/lux/tool/compiler/language/lux/phase/generation/python/runtime.lux
+++ b/stdlib/source/lux/tool/compiler/language/lux/phase/generation/python/runtime.lux
@@ -1,32 +1,39 @@
 (.module:
   [lux (#- inc)
+   ["." meta]
    [abstract
-    [monad (#+ do)]]
+    ["." monad (#+ do)]]
    [control
     ["." function]
-    ["p" parser
-     ["s" code]]]
+    ["<>" parser
+     ["<.>" code]]]
    [data
-    [number (#+ hex)
-     ["." i64]]
-    ["." text
-     ["%" format (#+ format)]]
+    ["." product]
+    ["." text ("#\." hash)
+     ["%" format (#+ format)]
+     ["." encoding]]
     [collection
-     ["." list ("#\." functor)]]]
+     ["." list ("#\." functor)]
+     ["." row]]]
    ["." macro
-    ["." code]
-    [syntax (#+ syntax:)]]
+    [syntax (#+ syntax:)]
+    ["." code]]
+   [math
+    [number (#+ hex)
+     ["." i64]]]
    [target
     ["_" python (#+ Expression SVar Computation Literal Statement)]]]
   ["." /// #_
    ["#." reference]
    ["//#" /// #_
+    ["$" version]
     ["#." synthesis]
-    ["#." generation (#+ Buffer)]
-    ["//#" /// #_
+    ["#." generation]
+    ["//#" /// (#+ Output)
      ["#." phase]
      [meta
-      [archive (#+ Archive)]]]]])
+      [archive (#+ Archive)
+       ["." artifact (#+ Registry)]]]]]])
 
 (template [ ]
   [(type: #export 
@@ -77,74 +84,78 @@
   (-> (Expression Any) Literal)
   (..variant 1 #1))
 
-(def: runtime-name
+(def: (runtime_name name)
   (-> Text SVar)
-  (|>> ///reference.sanitize
-       (format ..prefix "_")
-       _.var))
+  (let [identifier (format ..prefix
+                           "_" (%.nat $.version)
+                           "_" (%.nat (text\hash name)))]
+    (_.var identifier)))
 
 (def: (feature name definition)
   (-> SVar (-> SVar (Statement Any)) (Statement Any))
   (definition name))
 
-(syntax: #export (with-vars {vars (s.tuple (p.some s.local-identifier))}
+(syntax: #export (with_vars {vars (.tuple (<>.some .local_identifier))}
                    body)
-  (wrap (list (` (let [(~+ (|> vars
-                               (list\map (function (_ var)
-                                           (list (code.local-identifier var)
-                                                 (` (_.var (~ (code.text (///reference.sanitize var))))))))
-                               list.concat))]
-                   (~ body))))))
-
-(syntax: (runtime: {declaration (p.or s.local-identifier
-                                      (s.form (p.and s.local-identifier
-                                                     (p.some s.local-identifier))))}
+  (do {! meta.monad}
+    [ids (monad.seq ! (list.repeat (list.size vars) meta.count))]
+    (wrap (list (` (let [(~+ (|> vars
+                                 (list.zip/2 ids)
+                                 (list\map (function (_ [id var])
+                                             (list (code.local_identifier var)
+                                                   (` (_.var (~ (code.text (format "v" (%.nat id)))))))))
+                                 list.concat))]
+                     (~ body)))))))
+
+(syntax: (runtime: {declaration (<>.or .local_identifier
+                                       (.form (<>.and .local_identifier
+                                                            (<>.some .local_identifier))))}
            code)
   (case declaration
     (#.Left name)
-    (macro.with-gensyms [g!_]
-      (let [nameC (code.local-identifier name)
-            code-nameC (code.local-identifier (format "@" name))
-            runtime-nameC (` (runtime-name (~ (code.text name))))]
-        (wrap (list (` (def: #export (~ nameC) SVar (~ runtime-nameC)))
-                    (` (def: (~ code-nameC)
+    (macro.with_gensyms [g!_]
+      (let [nameC (code.local_identifier name)
+            code_nameC (code.local_identifier (format "@" name))
+            runtime_nameC (` (runtime_name (~ (code.text name))))]
+        (wrap (list (` (def: #export (~ nameC) SVar (~ runtime_nameC)))
+                    (` (def: (~ code_nameC)
                          (Statement Any)
-                         (..feature (~ runtime-nameC)
+                         (..feature (~ runtime_nameC)
                                     (function ((~ g!_) (~ nameC))
                                       (~ code)))))))))
     
     (#.Right [name inputs])
-    (macro.with-gensyms [g!_]
-      (let [nameC (code.local-identifier name)
-            code-nameC (code.local-identifier (format "@" name))
-            runtime-nameC (` (runtime-name (~ (code.text name))))
-            inputsC (list\map code.local-identifier inputs)
-            inputs-typesC (list\map (function.constant (` (_.Expression Any)))
+    (macro.with_gensyms [g!_]
+      (let [nameC (code.local_identifier name)
+            code_nameC (code.local_identifier (format "@" name))
+            runtime_nameC (` (runtime_name (~ (code.text name))))
+            inputsC (list\map code.local_identifier inputs)
+            inputs_typesC (list\map (function.constant (` (_.Expression Any)))
                                     inputs)]
         (wrap (list (` (def: #export ((~ nameC) (~+ inputsC))
-                         (-> (~+ inputs-typesC) (Computation Any))
-                         (_.apply/* (~ runtime-nameC) (list (~+ inputsC)))))
-                    (` (def: (~ code-nameC)
+                         (-> (~+ inputs_typesC) (Computation Any))
+                         (_.apply/* (~ runtime_nameC) (list (~+ inputsC)))))
+                    (` (def: (~ code_nameC)
                          (Statement Any)
-                         (..feature (~ runtime-nameC)
+                         (..feature (~ runtime_nameC)
                                     (function ((~ g!_) (~ g!_))
-                                      (..with-vars [(~+ inputsC)]
+                                      (..with_vars [(~+ inputsC)]
                                         (_.def (~ g!_) (list (~+ inputsC))
                                                (~ code)))))))))))))
 
 (runtime: (lux//try op)
-  (with-vars [error value]
+  (with_vars [error value]
     (_.try ($_ _.then
                (_.set (list value) (_.apply/* op (list unit)))
                (_.return (right value)))
            (list [(list (_.var "Exception")) error
                   (_.return (left (_.str/1 error)))]))))
 
-(runtime: (lux//program-args program-args)
-  (with-vars [inputs value]
+(runtime: (lux//program_args program_args)
+  (with_vars [inputs value]
     ($_ _.then
         (_.set (list inputs) none)
-        (<| (_.for-in value program-args)
+        (<| (_.for_in value program_args)
             (_.set (list inputs)
                    (some (_.tuple (list value inputs)))))
         (_.return inputs))))
@@ -153,7 +164,7 @@
   (Statement Any)
   ($_ _.then
       @lux//try
-      @lux//program-args
+      @lux//program_args
       ))
 
 (runtime: (io//log! message)
@@ -172,7 +183,7 @@
       (_.statement (|> (_.var "sys") (_.do "exit" (list code))))
       (_.return ..unit)))
 
-(runtime: (io//current-time! _)
+(runtime: (io//current_time! _)
   ($_ _.then
       (_.import "time")
       (_.return (|> (_.var "time")
@@ -186,63 +197,63 @@
       @io//log!
       @io//throw!
       @io//exit!
-      @io//current-time!
+      @io//current_time!
       ))
 
-(def: last-index
+(def: last_index
   (|>> _.len/1 (_.- (_.int +1))))
 
-(with-expansions [ (as-is ($_ _.then
-                                     (_.set (list lefts) (_.- last-index-right lefts))
-                                     (_.set (list tuple) (_.nth last-index-right tuple))))]
+(with_expansions [ (as_is ($_ _.then
+                                     (_.set (list lefts) (_.- last_index_right lefts))
+                                     (_.set (list tuple) (_.nth last_index_right tuple))))]
   (runtime: (tuple//left lefts tuple)
-    (with-vars [last-index-right]
+    (with_vars [last_index_right]
       (<| (_.while (_.bool true))
           ($_ _.then
-              (_.set (list last-index-right) (..last-index tuple))
-              (_.if (_.> lefts last-index-right)
+              (_.set (list last_index_right) (..last_index tuple))
+              (_.if (_.> lefts last_index_right)
                 ## No need for recursion
                 (_.return (_.nth lefts tuple))
                 ## Needs recursion
                 )))))
 
   (runtime: (tuple//right lefts tuple)
-    (with-vars [last-index-right right-index]
+    (with_vars [last_index_right right_index]
       (<| (_.while (_.bool true))
           ($_ _.then
-              (_.set (list last-index-right) (..last-index tuple))
-              (_.set (list right-index) (_.+ (_.int +1) lefts))
-              (_.cond (list [(_.= last-index-right right-index)
-                             (_.return (_.nth right-index tuple))]
-                            [(_.> last-index-right right-index)
+              (_.set (list last_index_right) (..last_index tuple))
+              (_.set (list right_index) (_.+ (_.int +1) lefts))
+              (_.cond (list [(_.= last_index_right right_index)
+                             (_.return (_.nth right_index tuple))]
+                            [(_.> last_index_right right_index)
                              ## Needs recursion.
                              ])
-                      (_.return (_.slice-from right-index tuple)))
+                      (_.return (_.slice_from right_index tuple)))
               )))))
 
 (runtime: (sum//get sum wantsLast wantedTag)
-  (let [no-match! (_.return _.none)
-        sum-tag (_.nth (_.int +0) sum)
-        sum-flag (_.nth (_.int +1) sum)
-        sum-value (_.nth (_.int +2) sum)
-        is-last? (_.= (_.string "") sum-flag)
-        test-recursion! (_.if is-last?
+  (let [no_match! (_.return _.none)
+        sum_tag (_.nth (_.int +0) sum)
+        sum_flag (_.nth (_.int +1) sum)
+        sum_value (_.nth (_.int +2) sum)
+        is_last? (_.= (_.string "") sum_flag)
+        test_recursion! (_.if is_last?
                           ## Must recurse.
-                          (_.return (sum//get sum-value wantsLast (_.- sum-tag wantedTag)))
-                          no-match!)]
-    (_.cond (list [(_.= sum-tag wantedTag)
-                   (_.if (_.= wantsLast sum-flag)
-                     (_.return sum-value)
-                     test-recursion!)]
+                          (_.return (sum//get sum_value wantsLast (_.- sum_tag wantedTag)))
+                          no_match!)]
+    (_.cond (list [(_.= sum_tag wantedTag)
+                   (_.if (_.= wantsLast sum_flag)
+                     (_.return sum_value)
+                     test_recursion!)]
 
-                  [(_.> sum-tag wantedTag)
-                   test-recursion!]
+                  [(_.> sum_tag wantedTag)
+                   test_recursion!]
 
-                  [(_.and (_.< sum-tag wantedTag)
+                  [(_.and (_.< sum_tag wantedTag)
                           (_.= (_.string "") wantsLast))
-                   (_.return (variant' (_.- wantedTag sum-tag) sum-flag sum-value))])
+                   (_.return (variant' (_.- wantedTag sum_tag) sum_flag sum_value))])
 
-            no-match!)))
+            no_match!)))
 
 (def: runtime//adt
   (Statement Any)
@@ -252,14 +263,14 @@
       @sum//get
       ))
 
-(def: full-64-bits
+(def: full_64_bits
   Literal
   (_.manual "0xFFFFFFFFFFFFFFFF"))
 
 (runtime: (i64//64 input)
-  (with-vars [capped]
-    (_.cond (list [(|> input (_.> full-64-bits))
-                   (_.return (|> input (_.bit-and full-64-bits) i64//64))]
+  (with_vars [capped]
+    (_.cond (list [(|> input (_.> full_64_bits))
+                   (_.return (|> input (_.bit_and full_64_bits) i64//64))]
                   [(|> input (_.> (: Literal (_.manual "0x7FFFFFFFFFFFFFFF"))))
                    ($_ _.then
                        (_.set (list capped)
@@ -270,23 +281,23 @@
                          (_.return (: Literal (_.manual "-9223372036854775808L")))))])
             (_.return input))))
 
-(runtime: (i64//logic-right-shift param subject)
+(runtime: (i64//logic_right_shift param subject)
   (let [mask (|> (_.int +1)
-                 (_.bit-shl (_.- param (_.int +64)))
+                 (_.bit_shl (_.- param (_.int +64)))
                  (_.- (_.int +1)))]
     (_.return (|> subject
-                  (_.bit-shr param)
-                  (_.bit-and mask)))))
+                  (_.bit_shr param)
+                  (_.bit_and mask)))))
 
 (def: runtime//i64
   (Statement Any)
   ($_ _.then
       @i64//64
-      @i64//logic-right-shift
+      @i64//logic_right_shift
       ))
 
 (runtime: (frac//decode input)
-  (with-vars [ex]
+  (with_vars [ex]
     (_.try
      (_.return (..some (_.float/1 input)))
      (list [(list (_.var "Exception")) ex
@@ -299,7 +310,7 @@
       ))
 
 (runtime: (text//index subject param start)
-  (with-vars [idx]
+  (with_vars [idx]
     ($_ _.then
         (_.set (list idx) (|> subject (_.do "find" (list param start))))
         (_.if (_.= (_.int -1) idx)
@@ -340,14 +351,19 @@
       runtime//io
       ))
 
-(def: #export artifact ..prefix)
+(def: #export artifact
+  ..prefix)
 
 (def: #export generate
-  (Operation (Buffer (Statement Any)))
-  (/////generation.with-buffer
+  (Operation [Registry Output])
+  (/////generation.with_buffer
     (do ///////phase.monad
-      [#let [directive (<| (_.comment "-*- coding: utf-8 -*-")
-                           ..runtime)]
-       _ (/////generation.execute! directive)
-       _ (/////generation.save! ..prefix directive)]
-      /////generation.buffer)))
+      [_ (/////generation.execute! ..runtime)
+       _ (/////generation.save! ..prefix ..runtime)]
+      (wrap [(|> artifact.empty
+                 artifact.resource
+                 product.right)
+             (row.row ["0"
+                       (|> ..runtime
+                           _.code
+                           (\ encoding.utf8 encode))])]))))
diff --git a/stdlib/source/program/aedifex/artifact/build.lux b/stdlib/source/program/aedifex/artifact/build.lux
new file mode 100644
index 000000000..d9a8b729e
--- /dev/null
+++ b/stdlib/source/program/aedifex/artifact/build.lux
@@ -0,0 +1,43 @@
+(.module:
+  [lux #*
+   [abstract
+    [equivalence (#+ Equivalence)]
+    [monad (#+ do)]]
+   [control
+    ["<>" parser
+     ["<.>" xml (#+ Parser)]
+     ["<.>" text]]]
+   [data
+    [text
+     ["%" format]]
+    [format
+     ["." xml (#+ XML)]]]
+   [math
+    [number
+     ["." nat]]]])
+
+(type: #export Build
+  Nat)
+
+(def: #export equivalence
+  (Equivalence Build)
+  nat.equivalence)
+
+(def: tag
+  xml.Tag
+  ["" "buildNumber"])
+
+(def: #export format
+  (-> Build XML)
+  (|>> %.nat
+       #xml.Text
+       list
+       (#xml.Node ..tag xml.attributes)))
+
+(def: #export parser
+  (Parser Build)
+  (do <>.monad
+    [_ (.node ..tag)]
+    (.embed (<>.codec nat.decimal
+                            (.many .decimal))
+                  (.children .text))))
diff --git a/stdlib/source/test/aedifex/artifact/build.lux b/stdlib/source/test/aedifex/artifact/build.lux
new file mode 100644
index 000000000..d0920b44c
--- /dev/null
+++ b/stdlib/source/test/aedifex/artifact/build.lux
@@ -0,0 +1,34 @@
+(.module:
+  [lux #*
+   ["_" test (#+ Test)]
+   [abstract
+    [monad (#+ do)]
+    {[0 #spec]
+     [/
+      ["$." equivalence]]}]
+   [control
+    ["." try ("#\." functor)]
+    [parser
+     ["<.>" xml]]]
+   [math
+    ["." random]]]
+  {#program
+   ["." /]})
+
+(def: #export test
+  Test
+  (<| (_.covering /._)
+      (_.for [/.Build]
+             ($_ _.and
+                 (_.for [/.equivalence]
+                        ($equivalence.spec /.equivalence random.nat))
+                 
+                 (do random.monad
+                   [expected random.nat]
+                   (_.cover [/.format /.parser]
+                            (|> expected
+                                /.format
+                                (.run /.parser)
+                                (try\map (\ /.equivalence = expected))
+                                (try.default false))))
+                 ))))
diff --git a/stdlib/source/test/lux/abstract.lux b/stdlib/source/test/lux/abstract.lux
index 9fd3986b8..b31c10617 100644
--- a/stdlib/source/test/lux/abstract.lux
+++ b/stdlib/source/test/lux/abstract.lux
@@ -8,6 +8,7 @@
     ["#/." cofree]]
    ["#." enum]
    ["#." equivalence]
+   ["#." hash]
    ["#." fold]
    ["#." functor
     ["#/." contravariant]]
@@ -46,6 +47,7 @@
       /codec.test
       /enum.test
       /equivalence.test
+      /hash.test
       /fold.test
       /interval.test
       /monoid.test
diff --git a/stdlib/source/test/lux/abstract/hash.lux b/stdlib/source/test/lux/abstract/hash.lux
new file mode 100644
index 000000000..c527fb9c9
--- /dev/null
+++ b/stdlib/source/test/lux/abstract/hash.lux
@@ -0,0 +1,39 @@
+(.module:
+  [lux #*
+   ["_" test (#+ Test)]
+   [abstract
+    [monad (#+ do)]
+    {[0 #spec]
+     [/
+      [functor
+       ["$." contravariant]]]}]
+   [data
+    ["." bit ("#\." equivalence)]]
+   [math
+    ["." random]
+    [number
+     ["." nat]]]]
+  {1
+   ["." / (#+ Hash)
+    [//
+     [equivalence (#+ Equivalence)]]]})
+
+(def: #export test
+  Test
+  (do random.monad
+    [leftN random.nat
+     rightN random.nat
+     #let [hash (: (Equivalence (/.Hash Nat))
+                   (structure
+                    (def: (= (^open "left\.") (^open "right\."))
+                      (and (bit\= (left\= (left\hash leftN) (left\hash leftN))
+                                  (right\= (right\hash leftN) (right\hash leftN)))
+                           (bit\= (left\= (left\hash rightN) (left\hash rightN))
+                                  (right\= (right\hash rightN) (right\hash rightN)))
+                           (bit\= (left\= (left\hash leftN) (left\hash rightN))
+                                  (right\= (right\hash leftN) (right\hash rightN)))))))]]
+    (<| (_.covering /._)
+        ($_ _.and
+            (_.for [/.functor]
+                   ($contravariant.spec hash nat.hash /.functor))
+            ))))
diff --git a/stdlib/source/test/lux/data/collection/list.lux b/stdlib/source/test/lux/data/collection/list.lux
index 6306f62fc..3efc42254 100644
--- a/stdlib/source/test/lux/data/collection/list.lux
+++ b/stdlib/source/test/lux/data/collection/list.lux
@@ -7,6 +7,7 @@
     {[0 #spec]
      [/
       ["$." equivalence]
+      ["$." hash]
       ["$." monoid]
       ["$." fold]
       ["$." functor]
@@ -49,6 +50,10 @@
   ($_ _.and
       (_.for [/.equivalence]
              ($equivalence.spec (/.equivalence n.equivalence) ..random))
+      (_.for [/.hash]
+             (|> random.nat
+                 (\ random.monad map (|>> list))
+                 ($hash.spec (/.hash n.hash))))
       (_.for [/.monoid]
              ($monoid.spec (/.equivalence n.equivalence) /.monoid ..random))
       (_.for [/.fold]
diff --git a/stdlib/source/test/lux/data/collection/set.lux b/stdlib/source/test/lux/data/collection/set.lux
index 6f981af91..282749f5e 100644
--- a/stdlib/source/test/lux/data/collection/set.lux
+++ b/stdlib/source/test/lux/data/collection/set.lux
@@ -7,6 +7,7 @@
     {[0 #spec]
      [/
       ["$." equivalence]
+      ["$." hash]
       ["$." monoid]]}]
    [data
     ["." bit ("#\." equivalence)]
@@ -33,6 +34,10 @@
         ($_ _.and
             (_.for [/.equivalence]
                    ($equivalence.spec /.equivalence (random.set n.hash size random.nat)))
+            (_.for [/.hash]
+                   (|> random.nat
+                       (\ random.monad map (|>> list (/.from_list n.hash)))
+                       ($hash.spec /.hash)))
             (_.for [/.monoid]
                    ($monoid.spec /.equivalence (/.monoid n.hash) (random.set n.hash size random.nat)))
 
diff --git a/stdlib/source/test/lux/data/collection/set/multi.lux b/stdlib/source/test/lux/data/collection/set/multi.lux
index 9d9572795..718c971c3 100644
--- a/stdlib/source/test/lux/data/collection/set/multi.lux
+++ b/stdlib/source/test/lux/data/collection/set/multi.lux
@@ -7,7 +7,8 @@
     ["." predicate]
     {[0 #spec]
      [/
-      ["$." equivalence]]}]
+      ["$." equivalence]
+      ["$." hash]]}]
    [data
     ["." bit ("#\." equivalence)]
     [collection
@@ -50,6 +51,11 @@
         (`` ($_ _.and
                 (_.for [/.equivalence]
                        ($equivalence.spec /.equivalence (..random diversity n.hash ..count random.nat)))
+                (_.for [/.hash]
+                       (|> random.nat
+                           (\ random.monad map (function (_ single)
+                                                 (/.add 1 single (/.new n.hash))))
+                           ($hash.spec /.hash)))
 
                 (_.cover [/.to_list /.from_list]
                          (|> sample
diff --git a/stdlib/source/test/lux/data/maybe.lux b/stdlib/source/test/lux/data/maybe.lux
index 64f9b5ff5..017d0799b 100644
--- a/stdlib/source/test/lux/data/maybe.lux
+++ b/stdlib/source/test/lux/data/maybe.lux
@@ -6,6 +6,7 @@
     {[0 #spec]
      [/
       ["$." equivalence]
+      ["$." hash]
       ["$." monoid]
       ["$." functor]
       ["$." apply]
@@ -31,6 +32,10 @@
       ($_ _.and
           (_.for [/.equivalence]
                  ($equivalence.spec (/.equivalence n.equivalence) (random.maybe random.nat)))
+          (_.for [/.hash]
+                 (|> random.nat
+                     (\ random.monad map (|>> #.Some))
+                     ($hash.spec (/.hash n.hash))))
           (_.for [/.monoid]
                  ($monoid.spec (/.equivalence n.equivalence) /.monoid (random.maybe random.nat)))
           (_.for [/.functor]
diff --git a/stdlib/source/test/lux/data/name.lux b/stdlib/source/test/lux/data/name.lux
index 7912994c3..f68a58d9a 100644
--- a/stdlib/source/test/lux/data/name.lux
+++ b/stdlib/source/test/lux/data/name.lux
@@ -6,6 +6,7 @@
     {[0 #spec]
      [/
       ["$." equivalence]
+      ["$." hash]
       ["$." order]
       ["$." codec]]}]
    [control
@@ -45,6 +46,10 @@
                ($_ _.and
                    (_.for [/.equivalence]
                           ($equivalence.spec /.equivalence (..random sizeM1 sizeS1)))
+                   (_.for [/.hash]
+                          (|> (random.ascii 2)
+                              (\ ! map (|>> [""]))
+                              ($hash.spec /.hash)))
                    (_.for [/.order]
                           ($order.spec /.order (..random sizeM1 sizeS1)))
                    (_.for [/.codec]
diff --git a/stdlib/source/test/lux/data/text.lux b/stdlib/source/test/lux/data/text.lux
index a5d11685f..c89ca97ba 100644
--- a/stdlib/source/test/lux/data/text.lux
+++ b/stdlib/source/test/lux/data/text.lux
@@ -6,6 +6,7 @@
     {[0 #spec]
      [/
       ["$." equivalence]
+      ["$." hash]
       ["$." order]
       ["$." monoid]]}]
    [control
@@ -238,6 +239,9 @@
       ($_ _.and
           (_.for [/.equivalence]
                  ($equivalence.spec /.equivalence (random.ascii 2)))
+          (_.for [/.hash]
+                 (|> (random.ascii 2)
+                     ($hash.spec /.hash)))
           (_.for [/.order]
                  ($order.spec /.order (random.ascii 2)))
           (_.for [/.monoid]
diff --git a/stdlib/source/test/lux/locale.lux b/stdlib/source/test/lux/locale.lux
index 5693eb2c4..23cb63a97 100644
--- a/stdlib/source/test/lux/locale.lux
+++ b/stdlib/source/test/lux/locale.lux
@@ -5,7 +5,8 @@
     [monad (#+ do)]
     {[0 #spec]
      [/
-      ["$." equivalence]]}]
+      ["$." equivalence]
+      ["$." hash]]}]
    [math
     ["." random (#+ Random) ("#\." monad)]]
    [data
@@ -51,6 +52,25 @@
       ($_ _.and
           (_.for [/.equivalence]
                  ($equivalence.spec /.equivalence ..random_locale))
+          (_.for [/.hash]
+                 (do {! random.monad}
+                   [fixed_language ..random_language
+                    fixed_territory ..random_territory
+                    fixed_encoding ..random_encoding]
+                   ($_ _.and
+                       (|> ..random_language
+                           (\ ! map (function (_ language)
+                                      (/.locale language (#.Some fixed_territory) (#.Some fixed_encoding))))
+                           ($hash.spec /.hash))
+                       (|> ..random_territory
+                           (\ ! map (function (_ territory)
+                                      (/.locale fixed_language (#.Some territory) (#.Some fixed_encoding))))
+                           ($hash.spec /.hash))
+                       (|> ..random_encoding
+                           (\ ! map (function (_ encoding)
+                                      (/.locale fixed_language (#.Some fixed_territory) (#.Some encoding))))
+                           ($hash.spec /.hash))
+                       )))
           
           (do random.monad
             [language ..random_language
diff --git a/stdlib/source/test/lux/time/month.lux b/stdlib/source/test/lux/time/month.lux
index d7078fa65..2cecfced6 100644
--- a/stdlib/source/test/lux/time/month.lux
+++ b/stdlib/source/test/lux/time/month.lux
@@ -1,38 +1,89 @@
 (.module:
   [lux #*
-   ["%" data/text/format (#+ format)]
    ["_" test (#+ Test)]
    [abstract
+    [monad (#+ do)]
+    ["." predicate]
     {[0 #spec]
      [/
       ["$." equivalence]
+      ["$." hash]
       ["$." order]
       ["$." enum]]}]
+   [control
+    ["." try ("#\." functor)]
+    ["." exception]]
+   [data
+    [collection
+     ["." set]
+     ["." list ("#\." functor fold)]]]
    [math
-    ["r" random (#+ Random) ("#\." monad)]]]
+    ["." random (#+ Random)]
+    [number
+     ["n" nat]]]]
   {1
-   ["." / (#+ Month)]})
+   ["." /
+    [//
+     ["." duration]]]})
 
-(def: #export month
-  (Random Month)
-  (r.either (r.either (r.either (r\wrap #/.January)
-                                (r.either (r\wrap #/.February)
-                                          (r\wrap #/.March)))
-                      (r.either (r\wrap #/.April)
-                                (r.either (r\wrap #/.May)
-                                          (r\wrap #/.June))))
-            (r.either (r.either (r\wrap #/.July)
-                                (r.either (r\wrap #/.August)
-                                          (r\wrap #/.September)))
-                      (r.either (r\wrap #/.October)
-                                (r.either (r\wrap #/.November)
-                                          (r\wrap #/.December))))))
+(def: #export random
+  (Random /.Month)
+  (let [december (/.number #/.December)]
+    (|> random.nat
+        (\ random.monad map (|>> (n.% december) inc))
+        (random.one (|>> /.by_number try.to_maybe)))))
 
 (def: #export test
   Test
-  (<| (_.context (%.name (name_of /._)))
+  (<| (_.covering /._)
+      (_.for [/.Month])
       ($_ _.and
-          ($equivalence.spec /.equivalence ..month)
-          ($order.spec /.order ..month)
-          ($enum.spec /.enum ..month)
+          (_.for [/.equivalence]
+                 ($equivalence.spec /.equivalence ..random))
+          (_.for [/.hash]
+                 ($hash.spec /.hash ..random))
+          (_.for [/.order]
+                 ($order.spec /.order ..random))
+          (_.for [/.enum]
+                 ($enum.spec /.enum ..random))
+
+          (do random.monad
+            [expected ..random
+             invalid (random.filter (predicate.unite (n.< (/.number #/.January))
+                                                     (n.> (/.number #/.December)))
+                                    random.nat)]
+            ($_ _.and
+                (_.cover [/.number /.by_number]
+                         (|> expected
+                             /.number
+                             /.by_number
+                             (try\map (\ /.equivalence = expected))
+                             (try.default false)))
+                (_.cover [/.invalid_month]
+                         (case (/.by_number invalid)
+                           (#try.Failure error)
+                           (exception.match? /.invalid_month error)
+                           
+                           (#try.Success _)
+                           false))
+                (_.cover [/.year]
+                         (let [all (list.size /.year)
+                               uniques (set.size (set.from_list /.hash /.year))]
+                           (and (n.= (/.number #/.December)
+                                     all)
+                                (n.= all
+                                     uniques))))
+                (_.cover [/.days]
+                         (let [expected (.nat (duration.query duration.day duration.normal_year))]
+                           (|> /.year
+                               (list\map /.days)
+                               (list\fold n.+ 0)
+                               (n.= expected))))
+                (_.cover [/.leap_year_days]
+                         (let [expected (.nat (duration.query duration.day duration.leap_year))]
+                           (|> /.year
+                               (list\map /.leap_year_days)
+                               (list\fold n.+ 0)
+                               (n.= expected))))
+                ))
           )))
-- 
cgit v1.2.3