From 6766be5427b1788a44e07151e3fabe33ec4f8b37 Mon Sep 17 00:00:00 2001 From: Eduardo Julian Date: Fri, 11 Mar 2022 05:52:21 -0400 Subject: Added an easy way to export Lux functionality to host programs (everywhere else). --- changelog.md | 1 + documentation/bookmark/back_end/c.md | 1 + documentation/bookmark/back_end/llvm.md | 4 + documentation/bookmark/batch.md | 4 + documentation/bookmark/documentation.md | 1 + documentation/bookmark/optics.md | 45 +-- documentation/bookmark/paradigm/object_oriented.md | 4 + documentation/bookmark/platform/node_js.md | 4 + documentation/bookmark/productivity.md | 4 + documentation/bookmark/reversible_computing.md | 4 + documentation/bookmark/security.md | 1 + documentation/bookmark/testing.md | 18 +- documentation/bookmark/user_interface/graphic.md | 26 +- lux-js/commands.md | 32 +- lux-js/project.lux | 6 +- lux-js/source/program.lux | 314 +++++++++-------- lux-lua/commands.md | 1 - lux-lua/project.lux | 46 ++- lux-lua/source/program.lux | 8 +- lux-ruby/source/program.lux | 41 ++- stdlib/project.lux | 16 +- .../library/lux/control/concurrency/thread.lux | 16 +- .../library/lux/control/parser/synthesis.lux | 2 +- stdlib/source/library/lux/control/parser/text.lux | 2 +- stdlib/source/library/lux/data/text.lux | 147 ++++---- .../source/library/lux/data/text/encoding/utf8.lux | 25 +- stdlib/source/library/lux/ffi.js.lux | 72 ++-- stdlib/source/library/lux/ffi.jvm.lux | 387 ++++++++------------- stdlib/source/library/lux/ffi.py.lux | 153 ++++---- stdlib/source/library/lux/ffi/export.js.lux | 96 +++++ stdlib/source/library/lux/ffi/export.jvm.lux | 106 ++++++ stdlib/source/library/lux/ffi/export.lua.lux | 112 ++++++ stdlib/source/library/lux/ffi/export.py.lux | 89 +++++ stdlib/source/library/lux/ffi/export.rb.lux | 144 ++++++++ stdlib/source/library/lux/static.lux | 22 +- .../language/lux/phase/extension/directive/lux.lux | 24 +- .../lux/phase/extension/generation/python/host.lux | 60 ++-- .../language/lux/phase/generation/js/case.lux | 69 ++-- .../language/lux/phase/generation/js/function.lux | 3 +- .../language/lux/phase/generation/js/runtime.lux | 7 +- .../language/lux/phase/generation/lua/case.lux | 13 +- .../language/lux/phase/generation/ruby/case.lux | 3 +- .../compiler/language/lux/synthesis/simple.lux | 6 +- stdlib/source/library/lux/tool/compiler/phase.lux | 1 - stdlib/source/library/lux/world/file.lux | 3 +- .../source/program/aedifex/artifact/extension.lux | 1 + stdlib/source/test/lux/ffi.js.lux | 41 ++- stdlib/source/test/lux/ffi.jvm.lux | 167 +-------- stdlib/source/test/lux/ffi.lua.lux | 26 +- stdlib/source/test/lux/ffi.py.lux | 26 +- stdlib/source/test/lux/ffi.rb.lux | 22 +- stdlib/source/test/lux/ffi/export.js.lux | 33 ++ stdlib/source/test/lux/ffi/export.jvm.lux | 186 ++++++++++ stdlib/source/test/lux/ffi/export.lua.lux | 33 ++ stdlib/source/test/lux/ffi/export.py.lux | 33 ++ stdlib/source/test/lux/ffi/export.rb.lux | 43 +++ stdlib/source/unsafe/lux/data/binary.lux | 6 +- 57 files changed, 1783 insertions(+), 977 deletions(-) create mode 100644 documentation/bookmark/back_end/llvm.md create mode 100644 documentation/bookmark/batch.md create mode 100644 documentation/bookmark/paradigm/object_oriented.md create mode 100644 documentation/bookmark/platform/node_js.md create mode 100644 documentation/bookmark/productivity.md create mode 100644 documentation/bookmark/reversible_computing.md create mode 100644 stdlib/source/library/lux/ffi/export.js.lux create mode 100644 stdlib/source/library/lux/ffi/export.jvm.lux create mode 100644 stdlib/source/library/lux/ffi/export.lua.lux create mode 100644 stdlib/source/library/lux/ffi/export.py.lux create mode 100644 stdlib/source/library/lux/ffi/export.rb.lux create mode 100644 stdlib/source/test/lux/ffi/export.js.lux create mode 100644 stdlib/source/test/lux/ffi/export.jvm.lux create mode 100644 stdlib/source/test/lux/ffi/export.lua.lux create mode 100644 stdlib/source/test/lux/ffi/export.py.lux create mode 100644 stdlib/source/test/lux/ffi/export.rb.lux diff --git a/changelog.md b/changelog.md index ddfd14d9a..5772001ac 100644 --- a/changelog.md +++ b/changelog.md @@ -7,6 +7,7 @@ * Code selection based on configuration parameters. * Code selection based on compiler version. * Extensible meta-compiler. +* Export machinery to consume Lux code from host-language programs. ### Changed * JVM compilation no longer relies on the ASM library. ### Removed diff --git a/documentation/bookmark/back_end/c.md b/documentation/bookmark/back_end/c.md index 71a372b3b..8e08e7326 100644 --- a/documentation/bookmark/back_end/c.md +++ b/documentation/bookmark/back_end/c.md @@ -1,5 +1,6 @@ # Reference +0. [Cello: High Level C](https://libcello.org/) 0. [C as a scripting language thanks to TinyCC](https://ciesie.com/post/tinycc_dynamic_compilation/) 0. [mlibc: Portable C standard library](https://github.com/managarm/mlibc) diff --git a/documentation/bookmark/back_end/llvm.md b/documentation/bookmark/back_end/llvm.md new file mode 100644 index 000000000..55a99f6e8 --- /dev/null +++ b/documentation/bookmark/back_end/llvm.md @@ -0,0 +1,4 @@ +# Reference + +0. [Taming Undefined Behavior in LLVM](https://www.cs.utah.edu/~regehr/papers/undef-pldi17.pdf) + diff --git a/documentation/bookmark/batch.md b/documentation/bookmark/batch.md new file mode 100644 index 000000000..596c72d23 --- /dev/null +++ b/documentation/bookmark/batch.md @@ -0,0 +1,4 @@ +# Reference + +0. [Automatically Process Your Operations in Bulk With Coroutines - Francesco Zoffoli - CppCon 2021](https://www.youtube.com/watch?v=XVZpTaYahdE) + diff --git a/documentation/bookmark/documentation.md b/documentation/bookmark/documentation.md index 8a76e9348..405bee172 100644 --- a/documentation/bookmark/documentation.md +++ b/documentation/bookmark/documentation.md @@ -31,6 +31,7 @@ # Philosophy +0. [What Makes Documentation Bad?](https://arunkprasad.com/log/what-makes-documentation-bad/) 0. [Forget reusability, aim for perfection](https://www.openbsd.org/papers/bsdcan18-mandoc.pdf) 0. https://increment.com/documentation/ 0. https://blog.stoplight.io/writing-documentation-when-you-arent-a-technical-writer-part-two-59997587cc2a diff --git a/documentation/bookmark/optics.md b/documentation/bookmark/optics.md index e3662b356..e47bfa6a8 100644 --- a/documentation/bookmark/optics.md +++ b/documentation/bookmark/optics.md @@ -1,25 +1,26 @@ # Reference -1. [Optics By Example](https://leanpub.com/optics-by-example) -1. [Profunctor optics, a categorical update](https://arxiv.org/abs/2001.07488) -1. [On Lawful Lenses](https://blog.statebox.org/on-lawful-lenses-6e18a1e17bdf) -1. https://medium.com/urbint-engineering/haskell-lens-operator-onboarding-a235481e8fac -1. https://fstarlang.github.io/general/2018/01/12/lens-indexed-lenses.html -1. [Jeremy Gibbons - Profunctor Optics Modular Data Accessors](https://www.youtube.com/watch?v=sfWzUMViP0M &&& http://www.cs.ox.ac.uk/people/jeremy.gibbons/publications/poptics.pdf) -1. http://hackage.haskell.org/package/profunctors-3.3.0.1/docs/Data-Profunctor.html -1. https://github.com/purescript-contrib/purescript-profunctor-lenses -1. https://hackage.haskell.org/package/lens-4.16/docs/Control-Lens-Indexed.html -1. http://oleg.fi/gists/posts/2017-04-18-glassery.html -1. http://oleg.fi/gists/posts/2017-12-23-functor-optics.html -1. [Edward Kmett - Monad Transformer Lenses](https://www.youtube.com/watch?v=Bxcz23GOJqc) -1. [Brian McKenna - Productionisation of Functional Optics](https://www.youtube.com/watch?v=H01dw-BMmlE) -1. [YOW! Lambda Jam 2017 Ken Scambler - Lenses for the Masses – Introducing Goggles](https://www.youtube.com/watch?v=oIhdOqaKSEg) -1. https://bartoszmilewski.com/2017/07/07/profunctor-optics-the-categorical-view/ -1. [Profunctor Optics: The Categorical Approach - Bartosz Milewski](https://www.youtube.com/watch?v=l1FCXUi6Vlw) -1. https://calmm-js.github.io/partial.lenses/ -1. http://evincarofautumn.blogspot.com/2016/01/thoughts-on-using-fractional-types-to.html -1. https://www.slideshare.net/davidoverton/comonad -1. http://codingismycraft.com/index.php/2017/10/04/adding-descriptors-to-your-python-arsenal/ -1. [Lenses embody Products, Prisms embody Sums](https://blog.jle.im/entry/lenses-products-prisms-sums.html) -1. http://www.philipzucker.com/lens-as-a-divisibility-relation-goofin-off-with-the-algebra-of-types/ +0. [Optics vs Lenses, Operationally](https://www.brunogavranovic.com/posts/2022-02-10-optics-vs-lenses-operationally.html) +0. [Optics By Example](https://leanpub.com/optics-by-example) +0. [Profunctor optics, a categorical update](https://arxiv.org/abs/2001.07488) +0. [On Lawful Lenses](https://blog.statebox.org/on-lawful-lenses-6e18a1e17bdf) +0. https://medium.com/urbint-engineering/haskell-lens-operator-onboarding-a235481e8fac +0. https://fstarlang.github.io/general/2018/01/12/lens-indexed-lenses.html +0. [Jeremy Gibbons - Profunctor Optics Modular Data Accessors](https://www.youtube.com/watch?v=sfWzUMViP0M &&& http://www.cs.ox.ac.uk/people/jeremy.gibbons/publications/poptics.pdf) +0. http://hackage.haskell.org/package/profunctors-3.3.0.1/docs/Data-Profunctor.html +0. https://github.com/purescript-contrib/purescript-profunctor-lenses +0. https://hackage.haskell.org/package/lens-4.16/docs/Control-Lens-Indexed.html +0. http://oleg.fi/gists/posts/2017-04-18-glassery.html +0. http://oleg.fi/gists/posts/2017-12-23-functor-optics.html +0. [Edward Kmett - Monad Transformer Lenses](https://www.youtube.com/watch?v=Bxcz23GOJqc) +0. [Brian McKenna - Productionisation of Functional Optics](https://www.youtube.com/watch?v=H01dw-BMmlE) +0. [YOW! Lambda Jam 2017 Ken Scambler - Lenses for the Masses – Introducing Goggles](https://www.youtube.com/watch?v=oIhdOqaKSEg) +0. https://bartoszmilewski.com/2017/07/07/profunctor-optics-the-categorical-view/ +0. [Profunctor Optics: The Categorical Approach - Bartosz Milewski](https://www.youtube.com/watch?v=l1FCXUi6Vlw) +0. https://calmm-js.github.io/partial.lenses/ +0. http://evincarofautumn.blogspot.com/2016/01/thoughts-on-using-fractional-types-to.html +0. https://www.slideshare.net/davidoverton/comonad +0. http://codingismycraft.com/index.php/2017/10/04/adding-descriptors-to-your-python-arsenal/ +0. [Lenses embody Products, Prisms embody Sums](https://blog.jle.im/entry/lenses-products-prisms-sums.html) +0. http://www.philipzucker.com/lens-as-a-divisibility-relation-goofin-off-with-the-algebra-of-types/ diff --git a/documentation/bookmark/paradigm/object_oriented.md b/documentation/bookmark/paradigm/object_oriented.md new file mode 100644 index 000000000..1271c1f91 --- /dev/null +++ b/documentation/bookmark/paradigm/object_oriented.md @@ -0,0 +1,4 @@ +# Reference + +0. [The Impoliteness of Overriding Methods](http://journal.stuffwithstuff.com/2012/12/19/the-impoliteness-of-overriding-methods/) + diff --git a/documentation/bookmark/platform/node_js.md b/documentation/bookmark/platform/node_js.md new file mode 100644 index 000000000..2fcfcf3ac --- /dev/null +++ b/documentation/bookmark/platform/node_js.md @@ -0,0 +1,4 @@ +# Reference + +0. [pkg: Package your Node.js project into an executable](https://github.com/vercel/pkg) + diff --git a/documentation/bookmark/productivity.md b/documentation/bookmark/productivity.md new file mode 100644 index 000000000..8aca77642 --- /dev/null +++ b/documentation/bookmark/productivity.md @@ -0,0 +1,4 @@ +# Reference + +0. [Resumption Strategies for Interrupted Programming Tasks](https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.188.54&rep=rep1&type=pdf) + diff --git a/documentation/bookmark/reversible_computing.md b/documentation/bookmark/reversible_computing.md new file mode 100644 index 000000000..ce6ce34c7 --- /dev/null +++ b/documentation/bookmark/reversible_computing.md @@ -0,0 +1,4 @@ +# Reference + +0. [Stanford Seminar - Generalized Reversible Computing and the Unconventional Computing Landscape](https://www.youtube.com/watch?v=IQZ_bQbxSXk) + diff --git a/documentation/bookmark/security.md b/documentation/bookmark/security.md index 619a182d7..301a2e163 100644 --- a/documentation/bookmark/security.md +++ b/documentation/bookmark/security.md @@ -75,6 +75,7 @@ # Vulnerability +0. [Big List of Naughty Strings](https://github.com/minimaxir/big-list-of-naughty-strings) 0. [SAML is insecure by design](https://joonas.fi/2021/08/saml-is-insecure-by-design/) 0. [Against Cipher Agility in Cryptography Protocols](https://paragonie.com/blog/2019/10/against-agility-in-cryptography-protocols) 0. [Padding the struct: How a compiler optimization can disclose stack memory](https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2019/october/padding-the-struct-how-a-compiler-optimization-can-disclose-stack-memory/) diff --git a/documentation/bookmark/testing.md b/documentation/bookmark/testing.md index d81994e40..6d12ee5a2 100644 --- a/documentation/bookmark/testing.md +++ b/documentation/bookmark/testing.md @@ -1,25 +1,29 @@ # Concolic Testing -1. [Robby Findler: Concolic Testing with Higher-Order Inputs](https://www.youtube.com/watch?v=aO9nOCqNdfQ) +0. [Robby Findler: Concolic Testing with Higher-Order Inputs](https://www.youtube.com/watch?v=aO9nOCqNdfQ) # Symbolic -1. [Crux](https://crux.galois.com/) +0. [Crux](https://crux.galois.com/) # White box -1. [Ricardo Peña - White-Box Path Generation in Recursive Programs - Lambda Days 2020](https://www.youtube.com/watch?v=7RXJhPaQCkc) +0. [Ricardo Peña - White-Box Path Generation in Recursive Programs - Lambda Days 2020](https://www.youtube.com/watch?v=7RXJhPaQCkc) # Mocking -1. [Testing Without Mocks: A Pattern Language](https://www.jamesshore.com/Blog/Testing-Without-Mocks.html) +0. [Testing Without Mocks: A Pattern Language](https://www.jamesshore.com/Blog/Testing-Without-Mocks.html) # Visual Testing -1. [Stories are tests](https://storybook.js.org/blog/stories-are-tests/) -1. [Visual Testing Handbook](https://storybook.js.org/tutorials/visual-testing-handbook/) +0. [Stories are tests](https://storybook.js.org/blog/stories-are-tests/) +0. [Visual Testing Handbook](https://storybook.js.org/tutorials/visual-testing-handbook/) # Cross-Branch Testing -1. [Cross-Branch Testing](https://www.hillelwayne.com/post/cross-branch-testing/) +0. [Cross-Branch Testing](https://www.hillelwayne.com/post/cross-branch-testing/) + +# Reference + +0. [Test Anything Protocol](http://testanything.org/) diff --git a/documentation/bookmark/user_interface/graphic.md b/documentation/bookmark/user_interface/graphic.md index 43304c329..e3a964837 100644 --- a/documentation/bookmark/user_interface/graphic.md +++ b/documentation/bookmark/user_interface/graphic.md @@ -1,34 +1,34 @@ # User experience (UX) -1. https://lawsofux.com/ +0. https://lawsofux.com/ # Widget -1. [imask.js: vanilla javascript input mask](https://imask.js.org/) -1. [Progress bar.js](https://kimmobrunfeldt.github.io/progressbar.js/) +0. [imask.js: vanilla javascript input mask](https://imask.js.org/) +0. [Progress bar.js](https://kimmobrunfeldt.github.io/progressbar.js/) # Design -1. [Zero-Width Space](https://css-tricks.com/zero-width-space/) -1. [Ant Design](https://ant.design/) -1. [7 Practical Tips for Cheating at Design](https://medium.com/refactoring-ui/7-practical-tips-for-cheating-at-design-40c736799886) -1. [Smart progress bars](https://honeypot.net/post/smart-progress-bars/) +0. [Zero-Width Space](https://css-tricks.com/zero-width-space/) +0. [Ant Design](https://ant.design/) +0. [7 Practical Tips for Cheating at Design](https://medium.com/refactoring-ui/7-practical-tips-for-cheating-at-design-40c736799886) +0. [Smart progress bars](https://honeypot.net/post/smart-progress-bars/) # Dark Patterns -1. https://neal.fun/dark-patterns/ +0. https://neal.fun/dark-patterns/ # Immediate mode -1. [Sol on Immediate Mode GUIs (IMGUI)](http://sol.gfxile.net/imgui/) -1. [Immediate-Mode Graphical User Interfaces (2005)](https://caseymuratori.com/blog_0001) +0. [Sol on Immediate Mode GUIs (IMGUI)](http://sol.gfxile.net/imgui/) +0. [Immediate-Mode Graphical User Interfaces (2005)](https://caseymuratori.com/blog_0001) # Accessibility -1. [What I’ve learned about accessibility in SPAs](https://nolanlawson.com/2019/11/05/what-ive-learned-about-accessibility-in-spas/) +0. [What I’ve learned about accessibility in SPAs](https://nolanlawson.com/2019/11/05/what-ive-learned-about-accessibility-in-spas/) # Inspiratioon -1. [zircle ui: A frontend library to develop zoomable user interfaces](https://zircleui.github.io/docs/) -1. []() +0. [zircle ui: A frontend library to develop zoomable user interfaces](https://zircleui.github.io/docs/) +0. https://open-ui.org/ diff --git a/lux-js/commands.md b/lux-js/commands.md index 26296c771..a7859d1e0 100644 --- a/lux-js/commands.md +++ b/lux-js/commands.md @@ -1,45 +1,35 @@ -# Test - +# Develop ``` -cd ~/lux/lux-js/ && lein lux auto test -cd ~/lux/lux-js/ && lein clean && lein lux auto test +cd ~/lux/lux-js/ \ +&& lux clean \ +&& lux with js auto build ``` # Build ``` -cd ~/lux/lux-js/ \ -&& lux clean \ -&& lux with js auto build - cd ~/lux/lux-js/ \ && lux clean \ && lux with js build \ && mv target/program.js lux.js -## Develop -cd ~/lux/lux-js/ \ -&& lein clean \ -&& lein lux auto build - ## Build JVM-based compiler cd ~/lux/lux-js/ \ -&& lein clean \ -&& lein lux build \ +&& lux clean \ +&& lux with jvm build \ && mv target/program.jar jvm_based_compiler.jar ## Use JVM-based compiler to produce a JS/Node-based compiler. ## @ library/lux/data/text TODO: Comment/turn-off when generating a JS compiler using a JVM-based compiler because Nashorn's implementation of "replaceAll" is incorrect. cd ~/lux/lux-js/ \ -&& lein clean \ +&& lux clean \ && time java -jar jvm_based_compiler.jar build --source ~/lux/lux-js/source --target ~/lux/lux-js/target --module program \ && mv target/program.js node_based_compiler.js ## Use JS/Node-based compiler to produce another JS/Node-based compiler. cd ~/lux/lux-js/ \ -&& lein clean \ -&& node --stack_size=8192 node_based_compiler.js build --source ~/lux/lux-js/source --target ~/lux/lux-js/target --module program \ -&& mv target/program.js lux.js +&& lux clean \ +&& node --stack_size=8192 node_based_compiler.js build --source ~/lux/lux-js/source --target ~/lux/lux-js/target --module program ``` # Try @@ -47,7 +37,7 @@ cd ~/lux/lux-js/ \ ``` ## Compile Lux's Standard Library's tests using a JS/Node-based compiler. cd ~/lux/stdlib/ \ -&& lein clean \ +&& lux clean \ && node --stack_size=8192 ~/lux/lux-js/target/program.js build --source ~/lux/stdlib/source --target ~/lux/stdlib/target --module test/lux \ && node ~/lux/stdlib/target/program.js ``` @@ -56,6 +46,6 @@ cd ~/lux/stdlib/ \ ``` cd ~/lux/lux-js/ \ -&& mvn install:install-file -Dfile=target/program.js -DgroupId=com.github.luxlang -DartifactId=lux-js -Dversion=0.6.5-SNAPSHOT -Dpackaging=js +&& mvn install:install-file -Dfile=target/program.js -DgroupId=com.github.luxlang -DartifactId=lux-js -Dversion=0.6.6-SNAPSHOT -Dpackaging=js ``` diff --git a/lux-js/project.lux b/lux-js/project.lux index 493e3f37f..c7be34e6f 100644 --- a/lux-js/project.lux +++ b/lux-js/project.lux @@ -1,5 +1,5 @@ ["" - ["identity" ["com.github.luxlang" "lux-js" "0.6.5"] + ["identity" ["com.github.luxlang" "lux-js" "0.6.6-SNAPSHOT"] "info" ["url" "https://github.com/LuxLang/lux" "scm" "https://github.com/LuxLang/lux.git" "licenses" [["name" "Lux License v0.1.2" @@ -21,8 +21,8 @@ "program" "program"] "js" - ["compiler" ["com.github.luxlang" "lux-js" "0.6.4" "js"]] + ["lux" ["com.github.luxlang" "lux-js" "0.6.6-SNAPSHOT" "js"]] "jvm" - ["compiler" ["com.github.luxlang" "lux-jvm" "0.6.5" "jar"] + ["lux" ["com.github.luxlang" "lux-jvm" "0.6.6-SNAPSHOT" "jar"] "dependencies" [["org.openjdk.nashorn" "nashorn-core" "15.1" "jar"]]]] diff --git a/lux-js/source/program.lux b/lux-js/source/program.lux index b670da4fa..8993c1192 100644 --- a/lux-js/source/program.lux +++ b/lux-js/source/program.lux @@ -7,7 +7,7 @@ [abstract [monad {"+" do}]] [control - ["[0]" maybe] + ["[0]" maybe ("[1]#[0]" monad)] ["[0]" try {"+" Try}] ["[0]" exception {"+" exception:}] ["[0]" io {"+" IO io}] @@ -76,7 +76,7 @@ {.#None} "???")) -(for [@.old +(for [@.jvm (as_is (import: java/lang/String) (import: (java/lang/Class a)) @@ -88,7 +88,7 @@ (import: java/lang/Long ["[1]::[0]" - (intValue [] java/lang/Integer)]) + (intValue [] int)]) (import: java/lang/Integer ["[1]::[0]" @@ -96,7 +96,7 @@ (import: java/lang/Number ["[1]::[0]" - (intValue [] java/lang/Integer) + (intValue [] int) (longValue [] long) (doubleValue [] double)]) @@ -139,9 +139,9 @@ [(ffi.interface: (getValue [] java/lang/Object)) - (`` (import: (~~ (template.symbol ["program/" ])) - ["[1]::[0]" - (getValue [] java/lang/Object)]))] + (import: + ["[1]::[0]" + (getValue [] java/lang/Object)])] [IntValue] [StructureValue] @@ -155,60 +155,76 @@ (def: jvm_int (-> (I64 Any) java/lang/Integer) - (|>> (:as java/lang/Long) java/lang/Long::intValue)) + (|>> .int + ffi.as_long + java/lang/Long::intValue)) (def: (js_int value) (-> Int org/openjdk/nashorn/api/scripting/JSObject) - (ffi.object [] org/openjdk/nashorn/api/scripting/AbstractJSObject [program/IntValue] - [] - ... Methods - (program/IntValue - [] (getValue self []) java/lang/Object - (:as java/lang/Object value)) - (org/openjdk/nashorn/api/scripting/AbstractJSObject - [] (getMember self [member java/lang/String]) java/lang/Object - (case member - (^ (static runtime.i64_high_field)) - (|> value .nat runtime.high jvm_int) - - (^ (static runtime.i64_low_field)) - (|> value .nat runtime.low jvm_int) - - _ - (panic! (exception.error ..unknown_member [member (:as java/lang/Object value)])))) - )) + (<| (ffi.:as org/openjdk/nashorn/api/scripting/JSObject) + (ffi.object [] org/openjdk/nashorn/api/scripting/AbstractJSObject [IntValue] + [] + ... Methods + (IntValue + [] (getValue self []) java/lang/Object + (ffi.:as java/lang/Object (ffi.as_long value))) + (org/openjdk/nashorn/api/scripting/AbstractJSObject + [] (getMember self [member java/lang/String]) java/lang/Object + (case (ffi.of_string member) + (^ (static runtime.i64_high_field)) + (|> value .nat runtime.high jvm_int + (ffi.:as java/lang/Object)) + + (^ (static runtime.i64_low_field)) + (|> value .nat runtime.low jvm_int + (ffi.:as java/lang/Object)) + + _ + (panic! (exception.error ..unknown_member [(ffi.of_string member) + (ffi.:as java/lang/Object (ffi.as_long value))])))) + ))) (def: (::toString js_object) (-> Any org/openjdk/nashorn/api/scripting/JSObject) - (ffi.object [] org/openjdk/nashorn/api/scripting/AbstractJSObject [] - [] - (org/openjdk/nashorn/api/scripting/AbstractJSObject - [] (isFunction self []) boolean - #1) - (org/openjdk/nashorn/api/scripting/AbstractJSObject - [] (call self [this java/lang/Object - args [java/lang/Object]]) - java/lang/Object - (debug.inspection js_object)) - )) + (<| (ffi.:as org/openjdk/nashorn/api/scripting/JSObject) + (ffi.object [] org/openjdk/nashorn/api/scripting/AbstractJSObject [] + [] + (org/openjdk/nashorn/api/scripting/AbstractJSObject + [] (isFunction self []) boolean + (ffi.as_boolean #1)) + (org/openjdk/nashorn/api/scripting/AbstractJSObject + [] (call self [this java/lang/Object + args [java/lang/Object]]) + java/lang/Object + (|> js_object + debug.inspection + ffi.as_string + (ffi.:as java/lang/Object))) + ))) (def: (::slice js_object value) (-> (-> java/lang/Object org/openjdk/nashorn/api/scripting/JSObject) (Array java/lang/Object) org/openjdk/nashorn/api/scripting/JSObject) - (ffi.object [] org/openjdk/nashorn/api/scripting/AbstractJSObject [] - [] - (org/openjdk/nashorn/api/scripting/AbstractJSObject - [] (isFunction self []) boolean - #1) - (org/openjdk/nashorn/api/scripting/AbstractJSObject - [] (call self [this java/lang/Object - args [java/lang/Object]]) - java/lang/Object - (|> (java/util/Arrays::copyOfRange value - (|> args (array.read! 0) maybe.trusted (:as Int)) - (.int (array.size value))) - js_object - (:as java/lang/Object))) - )) + (<| (ffi.:as org/openjdk/nashorn/api/scripting/JSObject) + (ffi.object [] org/openjdk/nashorn/api/scripting/AbstractJSObject [] + [] + (org/openjdk/nashorn/api/scripting/AbstractJSObject + [] (isFunction self []) boolean + (ffi.as_boolean #1)) + (org/openjdk/nashorn/api/scripting/AbstractJSObject + [] (call self [this java/lang/Object + args [java/lang/Object]]) + java/lang/Object + (|> (java/util/Arrays::copyOfRange value + (|> args + (array.read! 0) + maybe.trusted + (:as Int) + ffi.as_int) + (ffi.as_int (.int (array.size value)))) + (:as java/lang/Object) + js_object + (ffi.:as java/lang/Object))) + ))) (def: (js_structure value) (-> (Array java/lang/Object) org/openjdk/nashorn/api/scripting/JSObject) @@ -221,90 +237,101 @@ {.#None}) (case (ffi.check java/lang/Long sub_value) {.#Some sub_value} - (|> sub_value (:as Int) js_int) + (|> sub_value ffi.of_long js_int) {.#None}) ... else (:as org/openjdk/nashorn/api/scripting/JSObject sub_value))))] - (ffi.object [] org/openjdk/nashorn/api/scripting/AbstractJSObject [program/StructureValue] - [] - ... Methods - (program/StructureValue - [] (getValue self []) java/lang/Object - (:as (Array java/lang/Object) value)) - (org/openjdk/nashorn/api/scripting/AbstractJSObject - [] (isArray self []) boolean - #1) - (org/openjdk/nashorn/api/scripting/AbstractJSObject - [] (getMember self [member java/lang/String]) - java/lang/Object - (case member - (^or "toJSON" "toString") - (:as java/lang/Object - (::toString value)) - - "length" - (jvm_int (array.size value)) - - "slice" - (:as java/lang/Object - (::slice js_object value)) - - (^ (static runtime.variant_tag_field)) - (|> value (array.read! 0) maybe.trusted) - - (^ (static runtime.variant_flag_field)) - (case (array.read! 1 value) - {.#Some set!} - set! + (<| (ffi.:as org/openjdk/nashorn/api/scripting/JSObject) + (ffi.object [] org/openjdk/nashorn/api/scripting/AbstractJSObject [StructureValue] + [] + ... Methods + (StructureValue + [] (getValue self []) java/lang/Object + (ffi.:as java/lang/Object value)) + (org/openjdk/nashorn/api/scripting/AbstractJSObject + [] (isArray self []) boolean + (ffi.as_boolean #1)) + (org/openjdk/nashorn/api/scripting/AbstractJSObject + [] (getMember self [member java/lang/String]) + java/lang/Object + (case (ffi.of_string member) + (^or "toJSON" "toString") + (|> (::toString value) + (ffi.:as java/lang/Object)) + + "length" + (|> value + array.size + jvm_int + (ffi.:as java/lang/Object)) + + "slice" + (|> (::slice js_object value) + (ffi.:as java/lang/Object)) + + (^ (static runtime.variant_tag_field)) + (|> value + (array.read! 0) + maybe.trusted) + + (^ (static runtime.variant_flag_field)) + (case (array.read! 1 value) + {.#Some set!} + set! - _ - (ffi.null)) - - (^ (static runtime.variant_value_field)) - (|> value (array.read! 2) maybe.trusted js_object (:as java/lang/Object)) - - _ - (panic! (exception.error ..unknown_member [(:as Text member) (:as java/lang/Object value)]))) - ) - (org/openjdk/nashorn/api/scripting/AbstractJSObject - [] (getSlot self [idx int]) java/lang/Object - (|> value - (array.read! (|> idx java/lang/Integer::longValue (:as Nat))) - maybe.trusted - js_object - (:as java/lang/Object))) - ))) + _ + (ffi.null)) + + (^ (static runtime.variant_value_field)) + (|> value + (array.read! 2) + maybe.trusted + js_object + (ffi.:as java/lang/Object)) + + _ + (panic! (exception.error ..unknown_member [(:as Text member) (:as java/lang/Object value)]))) + ) + (org/openjdk/nashorn/api/scripting/AbstractJSObject + [] (getSlot self [idx int]) java/lang/Object + (|> value + (array.read! (|> idx java/lang/Integer::longValue (:as Nat))) + maybe.trusted + js_object + (:as java/lang/Object))) + )))) (exception: undefined_has_no_lux_representation) (exception: (unknown_kind_of_host_object [object java/lang/Object]) (exception.report - ["Class" (java/lang/Object::toString (java/lang/Object::getClass object))] - ["Object" (java/lang/Object::toString object)] + ["Class" (ffi.of_string (java/lang/Object::toString (java/lang/Object::getClass object)))] + ["Object" (ffi.of_string (java/lang/Object::toString object))] ["Keys" (case (ffi.check org/openjdk/nashorn/api/scripting/ScriptObjectMirror object) {.#Some object} (|> object (org/openjdk/nashorn/api/scripting/ScriptObjectMirror::getOwnKeys true) - (:as (Array Text)) (array.list {.#None}) - (%.list %.text)) + (%.list (|>> ffi.of_string %.text))) {.#None} "???")])) + (def: (i32 half i64) + (-> Text org/openjdk/nashorn/api/scripting/ScriptObjectMirror (Maybe Int)) + (|> i64 + (org/openjdk/nashorn/api/scripting/JSObject::getMember [(ffi.as_string half)]) + (maybe#each (|>> (ffi.check java/lang/Number))) + maybe#conjoint + (maybe#each (|>> java/lang/Number::longValue ffi.of_long)))) + (def: (check_int js_object) (-> org/openjdk/nashorn/api/scripting/ScriptObjectMirror (Maybe Int)) - (case [(org/openjdk/nashorn/api/scripting/JSObject::getMember [runtime.i64_high_field] js_object) - (org/openjdk/nashorn/api/scripting/JSObject::getMember [runtime.i64_low_field] js_object)] - (^multi [{.#Some high} {.#Some low}] - [[(ffi.check java/lang/Number high) - (ffi.check java/lang/Number low)] - [{.#Some high} {.#Some low}]] - [[(java/lang/Number::longValue high) - (java/lang/Number::longValue low)] - [high low]]) + (case [(..i32 runtime.i64_high_field js_object) + (..i32 runtime.i64_low_field js_object)] + [{.#Some high} {.#Some low}] {.#Some (.int (n.+ (|> high .nat (i64.left_shifted 32)) (if (i.< +0 (.int low)) (|> low .nat (i64.left_shifted 32) (i64.right_shifted 32)) @@ -317,14 +344,12 @@ (-> (-> java/lang/Object (Try Any)) org/openjdk/nashorn/api/scripting/ScriptObjectMirror (Maybe Any)) - (case [(org/openjdk/nashorn/api/scripting/JSObject::getMember [runtime.variant_tag_field] js_object) - (org/openjdk/nashorn/api/scripting/JSObject::getMember [runtime.variant_flag_field] js_object) - (org/openjdk/nashorn/api/scripting/JSObject::getMember [runtime.variant_value_field] js_object)] + (case [(org/openjdk/nashorn/api/scripting/JSObject::getMember [(ffi.as_string runtime.variant_tag_field)] js_object) + (org/openjdk/nashorn/api/scripting/JSObject::getMember [(ffi.as_string runtime.variant_flag_field)] js_object) + (org/openjdk/nashorn/api/scripting/JSObject::getMember [(ffi.as_string runtime.variant_value_field)] js_object)] (^multi [{.#Some tag} ?flag {.#Some value}] - [(ffi.check java/lang/Number tag) - {.#Some tag}] - [(lux_object value) - {try.#Success value}]) + [[(ffi.check java/lang/Number tag) (lux_object value)] + [{.#Some tag} {try.#Success value}]]) {.#Some [(java/lang/Number::intValue (:as java/lang/Number tag)) (maybe.else (ffi.null) ?flag) value]} @@ -336,13 +361,13 @@ (-> (-> java/lang/Object (Try Any)) org/openjdk/nashorn/api/scripting/ScriptObjectMirror (Maybe (Array java/lang/Object))) - (if (org/openjdk/nashorn/api/scripting/JSObject::isArray js_object) - (let [num_keys (.nat (org/openjdk/nashorn/api/scripting/ScriptObjectMirror::size js_object))] + (if (ffi.of_boolean (org/openjdk/nashorn/api/scripting/JSObject::isArray js_object)) + (let [num_keys (.nat (ffi.of_int (org/openjdk/nashorn/api/scripting/ScriptObjectMirror::size js_object)))] (loop [idx 0 output (: (Array java/lang/Object) (array.empty num_keys))] (if (n.< num_keys idx) - (case (org/openjdk/nashorn/api/scripting/JSObject::getMember (%.nat idx) js_object) + (case (org/openjdk/nashorn/api/scripting/JSObject::getMember (ffi.as_string (%.nat idx)) js_object) {.#Some member} (case (ffi.check org/openjdk/nashorn/internal/runtime/Undefined member) {.#Some _} @@ -386,8 +411,8 @@ {.#None})] [java/lang/Number java/lang/Number::doubleValue] - [program/StructureValue program/StructureValue::getValue] - [program/IntValue program/IntValue::getValue])) + [StructureValue StructureValue::getValue] + [IntValue IntValue::getValue])) (case (ffi.check org/openjdk/nashorn/api/scripting/ScriptObjectMirror js_object) {.#Some js_object} (case (check_int js_object) @@ -405,7 +430,7 @@ {try.#Success value} {.#None} - (if (org/openjdk/nashorn/api/scripting/JSObject::isFunction js_object) + (if (ffi.of_boolean (org/openjdk/nashorn/api/scripting/JSObject::isFunction js_object)) {try.#Success js_object} ... (exception.except ..unknown_kind_of_host_object [(:as java/lang/Object js_object)]) {try.#Success js_object} @@ -422,7 +447,7 @@ [function (|> function (:as java/lang/Object) (ffi.check org/openjdk/nashorn/api/scripting/JSObject))] - (if (org/openjdk/nashorn/api/scripting/JSObject::isFunction function) + (if (ffi.of_boolean (org/openjdk/nashorn/api/scripting/JSObject::isFunction function)) {.#Some function} {.#None}))) ) @@ -430,7 +455,7 @@ @.js (as_is)]) -(for [@.old +(for [@.jvm (as_is (def: (call_macro inputs lux macro) (-> (List Code) Lux org/openjdk/nashorn/api/scripting/JSObject (Try (Try [Lux (List Code)]))) (let [to_js (: (-> Any java/lang/Object) @@ -445,7 +470,7 @@ (exception: (cannot_apply_a_non_function [object java/lang/Object]) (exception.report - ["Object" (java/lang/Object::toString object)])) + ["Object" (ffi.of_string (java/lang/Object::toString object))])) (def: (expander macro inputs lux) Expander @@ -471,11 +496,11 @@ {try.#Success ((:as Macro' macro) inputs lux)}) ]) -(for [@.old +(for [@.jvm (as_is (def: (evaluate! interpreter alias input) (-> javax/script/ScriptEngine unit.ID _.Expression (Try Any)) (do try.monad - [?output (javax/script/ScriptEngine::eval (_.code input) interpreter)] + [?output (javax/script/ScriptEngine::eval (ffi.as_string (_.code input)) interpreter)] (case ?output {.#Some output} (..lux_object output) @@ -486,7 +511,7 @@ (def: (execute! interpreter input) (-> javax/script/ScriptEngine _.Statement (Try Any)) (do try.monad - [?output (javax/script/ScriptEngine::eval (_.code input) interpreter)] + [?output (javax/script/ScriptEngine::eval (ffi.as_string (_.code input)) interpreter)] (in []))) (def: (define! interpreter context custom input) @@ -506,9 +531,9 @@ (org/openjdk/nashorn/api/scripting/NashornScriptEngineFactory::new))] (: (Host _.Expression _.Statement) (implementation - (def: evaluate (..evaluate! interpreter)) + (def: (evaluate alias [_ input]) (..evaluate! interpreter alias input)) (def: execute (..execute! interpreter)) - (def: define (..define! interpreter)) + (def: (define context custom [_ input]) (..define! interpreter context custom input)) (def: (ingest context content) (|> content (# utf8.codec decoded) try.trusted (:as _.Statement))) @@ -565,9 +590,9 @@ (IO (Host _.Expression _.Statement)) (io (: (Host _.Expression _.Statement) (implementation - (def: evaluate ..evaluate!) + (def: (evaluate alias [_ input]) (..evaluate! alias input)) (def: execute ..execute!) - (def: define ..define!) + (def: (define context custom [_ input]) (..define! context custom input)) (def: (ingest context content) (|> content (# utf8.codec decoded) try.trusted (:as _.Statement))) @@ -586,19 +611,19 @@ (do phase.monad [] (in (:as phase.Wrapper - (for [ ... The implementation for @.old is technically incorrect. + (for [ ... The implementation for @.jvm is technically incorrect. ... However, the JS compiler runs fast enough on Node to be fully hosted there. ... And running the JS compiler on the JVM (on top of Nashorn) is impractically slow. ... This means that in practice, only the @.js implementation matters. ... And since no cross-language boundary needs to be handled, it's a correct implementation. - @.old (|>>) + @.jvm (|>>) @.js (|>>)]))))) (def: platform (IO (Platform [Register Text] _.Expression _.Statement)) (do io.monad [host ..host] - (in [platform.#&file_system (for [@.old (file.async file.default) + (in [platform.#&file_system (for [@.jvm (file.async file.default) @.jvm (file.async file.default) ... TODO: Handle this in a safer manner. ... This would crash if the compiler was run on a browser. @@ -626,7 +651,7 @@ no_inputs))) (_.string ""))))) -(for [@.old +(for [@.jvm (def: (extender phase_wrapper) (-> phase.Wrapper Extender) ... TODO: Stop relying on coercions ASAP. @@ -670,12 +695,17 @@ (_.statement (_.apply/* (_.closure (list) body) (list)))) +(def: (lux_compiler it) + (-> Any platform.Custom) + (undefined)) + (program: [service cli.service] (let [context (context.js (cli.target service))] (exec (do async.monad [platform (async.future ..platform) - _ (/.compiler context + _ (/.compiler ..lux_compiler + context ..expander analysis.bundle (io.io platform) diff --git a/lux-lua/commands.md b/lux-lua/commands.md index 08fb948a1..6783b7b17 100644 --- a/lux-lua/commands.md +++ b/lux-lua/commands.md @@ -9,7 +9,6 @@ cd ~/lux/lux-lua/ && lein clean && lein lux auto test ``` ## Develop -## NOTE: Must set lux/control/concurrency/thread.parallelism = 1 before compiling to make sure Rembulan doesn't cause trouble. cd ~/lux/lux-lua/ \ && lux clean \ && lux auto build diff --git a/lux-lua/project.lux b/lux-lua/project.lux index 54739d3e2..f1b9c0c46 100644 --- a/lux-lua/project.lux +++ b/lux-lua/project.lux @@ -1,23 +1,33 @@ -{"" - [#identity ["com.github.luxlang" "lux-lua" "0.6.4"] +["" + ["identity" ["com.github.luxlang" "lux-lua" "0.6.6-SNAPSHOT"] + "description" "A Lua compiler for Lux." + "info" ["url" "https://github.com/LuxLang/lux" + "scm" "https://github.com/LuxLang/lux.git" + "licenses" [["name" "Lux License v0.1.2" + "url" "https://github.com/LuxLang/lux/blob/master/license.txt" + "type" "repo"]] + "developers" [["name" "Eduardo Julian" + "url" "https://github.com/eduardoejp"]]] - #deploy_repositories {"snapshots" "https://oss.sonatype.org/content/repositories/snapshots/" - "releases" "https://oss.sonatype.org/service/local/staging/deploy/maven2/"} + "deploy_repositories" ["snapshots" "https://oss.sonatype.org/content/repositories/snapshots/" + "releases" "https://oss.sonatype.org/service/local/staging/deploy/maven2/"] - #repositories ["https://oss.sonatype.org/content/repositories/snapshots/" - "https://oss.sonatype.org/service/local/staging/deploy/maven2/"] + "repositories" ["https://oss.sonatype.org/content/repositories/snapshots/" + "https://oss.sonatype.org/service/local/staging/deploy/maven2/"] - #compiler ["com.github.luxlang" "lux-jvm" "0.6.4" "jar"] - #dependencies [... ["com.github.luxlang" "stdlib" "0.6.4" "tar"] + "lux" ["com.github.luxlang" "lux-jvm" "0.6.6-SNAPSHOT" "jar"] + "dependencies" [... ["com.github.luxlang" "stdlib" "0.6.5" "tar"] + ... ["com.github.luxlang" "lux-jvm-function" "0.6.5" "jar"] - ["org.ow2.asm" "asm" "5.0.4" "jar"] - ["org.ow2.asm" "asm-commons" "5.0.4" "jar"] - ["org.ow2.asm" "asm-analysis" "5.0.4" "jar"] - ["org.ow2.asm" "asm-tree" "5.0.4" "jar"] - ["org.ow2.asm" "asm-util" "5.0.4" "jar"] - - ["com.github.luxlang" "rembulan-runtime" "0.1" "jar"] - ["com.github.luxlang" "rembulan-stdlib" "0.1" "jar"] - ["com.github.luxlang" "rembulan-compiler" "0.1" "jar"]] + ["org.ow2.asm" "asm" "5.0.4" "jar"] + ["org.ow2.asm" "asm-commons" "5.0.4" "jar"] + ["org.ow2.asm" "asm-analysis" "5.0.4" "jar"] + ["org.ow2.asm" "asm-tree" "5.0.4" "jar"] + ["org.ow2.asm" "asm-util" "5.0.4" "jar"] + + ["com.github.luxlang" "rembulan-runtime" "0.1" "jar"] + ["com.github.luxlang" "rembulan-stdlib" "0.1" "jar"] + ["com.github.luxlang" "rembulan-compiler" "0.1" "jar"]] - #program "program"]} + "program" "program" + "configuration" ["lua_compiler?" ""]]] diff --git a/lux-lua/source/program.lux b/lux-lua/source/program.lux index f1a759f2d..ae6f3af2f 100644 --- a/lux-lua/source/program.lux +++ b/lux-lua/source/program.lux @@ -866,11 +866,11 @@ (async.future (# world/program.default exit +0))) (def: (lux_compiler it) - (-> Any compiler.Custom) + (-> Any platform.Custom) (undefined)) (`` (program: [service cli.service] - (let [extension ".lua"] + (let [context (context.lua (cli.target service))] (do io.monad [(~~ (for [@.old [baggage platform] @.jvm [baggage platform] @@ -878,7 +878,7 @@ ..platform] (exec (do async.monad [_ (/.compiler ..lux_compiler - (context.lua (cli.target service)) + context (for [@.old (..expander ..to_host baggage) @.jvm (..expander ..to_host baggage) @.lua ..expander]) @@ -901,6 +901,6 @@ (format (cli.target service) (# file.default separator) "program" - extension)])] + (value@ context.#artifact_extension context))])] (..declare_success! [])) (io.io [])))))) diff --git a/lux-ruby/source/program.lux b/lux-ruby/source/program.lux index 123fa1285..bd3f1763e 100644 --- a/lux-ruby/source/program.lux +++ b/lux-ruby/source/program.lux @@ -972,27 +972,26 @@ (async.future (# world/program.default exit +0))) (def: (lux_compiler it) - (-> Any compiler.Custom) + (-> Any platform.Custom) (undefined)) (program: [service cli.service] - (let [extension ".rb"] - (exec - (do async.monad - [_ (/.compiler ..lux_compiler - (context.ruby (cli.target service)) - ..expander - analysis.bundle - ..platform - generation.bundle - (function.constant extension/bundle.empty) - ..program - [Register _.Expression _.Statement] - ..extender - service - [packager.package - (format (cli.target service) - (# file.default separator) - "program")])] - (..declare_success! [])) - (io.io [])))) + (exec + (do async.monad + [_ (/.compiler ..lux_compiler + (context.ruby (cli.target service)) + ..expander + analysis.bundle + ..platform + generation.bundle + (function.constant extension/bundle.empty) + ..program + [Register _.Expression _.Statement] + ..extender + service + [packager.package + (format (cli.target service) + (# file.default separator) + "program")])] + (..declare_success! [])) + (io.io []))) diff --git a/stdlib/project.lux b/stdlib/project.lux index 1f9e41d0e..40f8324f7 100644 --- a/stdlib/project.lux +++ b/stdlib/project.lux @@ -36,12 +36,16 @@ ... "sources" ["source"] ... The directory for storing the build artifacts. The default is described below. ... "target" "target" + + ... "compilers" [[experiment/compiler.dummy "some" "parameter"]] + "configuration" ["left" "<<<" + "right" ">>>"] ] ... The following are alternative profiles to use in various situations. "jvm" - [... "compiler" specifies the dependency to fetch and use as the compiler. - "compiler" ["com.github.luxlang" "lux-jvm" "0.6.5" "jar"] + [... "lux" specifies the dependency to fetch and use as the compiler. + "lux" ["com.github.luxlang" "lux-jvm" "0.6.6-SNAPSHOT" "jar"] ... "dependencies" is an optional list of dependencies to fetch. ... The dependencies have the same shape as when specifying the compiler. ... When omitting the packaging format of the dependency, "tar" will be assumed. @@ -52,25 +56,25 @@ ] "js" - ["compiler" ["com.github.luxlang" "lux-js" "0.6.5" "js"] + ["lux" ["com.github.luxlang" "lux-js" "0.6.6-SNAPSHOT" "js"] ... The OS command to use when running JS tests. The default is described below. ... "js" ["node" "--stack_size=8192"] ] "lua" - ["compiler" ["com.github.luxlang" "lux-lua" "0.6.5" "jar"] + ["lux" ["com.github.luxlang" "lux-lua" "0.6.6-SNAPSHOT" "jar"] ... The OS command to use when running Lua tests. The default is described below. ... "lua" ["lua"] ] "python" - ["compiler" ["com.github.luxlang" "lux-python" "0.6.5" "jar"] + ["lux" ["com.github.luxlang" "lux-python" "0.6.6-SNAPSHOT" "jar"] ... The OS command to use when running Python tests. The default is described below. ... "python" ["python3"] ] "ruby" - ["compiler" ["com.github.luxlang" "lux-ruby" "0.6.5" "jar"] + ["lux" ["com.github.luxlang" "lux-ruby" "0.6.6-SNAPSHOT" "jar"] ... The OS command to use when running Ruby tests. The default is described below. ... "ruby" ["ruby"] ] diff --git a/stdlib/source/library/lux/control/concurrency/thread.lux b/stdlib/source/library/lux/control/concurrency/thread.lux index 07de8c1c7..5e76521ed 100644 --- a/stdlib/source/library/lux/control/concurrency/thread.lux +++ b/stdlib/source/library/lux/control/concurrency/thread.lux @@ -17,6 +17,8 @@ [number ["n" nat] ["f" frac]]] + [meta + ["[0]" configuration]] [time ["[0]" instant]]]] [// @@ -68,14 +70,18 @@ (def: .public parallelism Nat - (with_expansions [ (|> (java/lang/Runtime::getRuntime) - (java/lang/Runtime::availableProcessors) - ffi.of_int - .nat)] + (with_expansions [ 1 + (<| (configuration.for [... TODO: Remove this when Rembulan is no longer being used. + ["lua_compiler?" ""] + ]) + (|> (java/lang/Runtime::getRuntime) + (java/lang/Runtime::availableProcessors) + ffi.of_int + .nat))] (for [@.old @.jvm ] ... Default - 1))) + ))) (with_expansions [ (as_is (def: runner java/util/concurrent/ScheduledThreadPoolExecutor diff --git a/stdlib/source/library/lux/control/parser/synthesis.lux b/stdlib/source/library/lux/control/parser/synthesis.lux index 894f7da68..d0cebbb12 100644 --- a/stdlib/source/library/lux/control/parser/synthesis.lux +++ b/stdlib/source/library/lux/control/parser/synthesis.lux @@ -111,7 +111,7 @@ (exception.except ..cannot_parse input)))))] [bit bit! /.bit Bit bit.equivalence] - [i64 i64! /.i64 (I64 Any) i64.equivalence] + [i64 i64! /.i64 I64 i64.equivalence] [f64 f64! /.f64 Frac frac.equivalence] [text text! /.text Text text.equivalence] [local local! /.variable/local Nat n.equivalence] diff --git a/stdlib/source/library/lux/control/parser/text.lux b/stdlib/source/library/lux/control/parser/text.lux index 72f97501b..de79a42b5 100644 --- a/stdlib/source/library/lux/control/parser/text.lux +++ b/stdlib/source/library/lux/control/parser/text.lux @@ -1,6 +1,6 @@ (.using [library - [lux {"-" or and not local} + [lux {"-" and not local} [abstract [monad {"+" Monad do}]] [control diff --git a/stdlib/source/library/lux/data/text.lux b/stdlib/source/library/lux/data/text.lux index 177192e95..01e39705f 100644 --- a/stdlib/source/library/lux/data/text.lux +++ b/stdlib/source/library/lux/data/text.lux @@ -1,23 +1,23 @@ (.using - [library - [lux {"-" char} - ["@" target] - [abstract - [hash {"+" Hash}] - [monoid {"+" Monoid}] - [equivalence {"+" Equivalence}] - [order {"+" Order}] - [monad {"+" do}] - [codec {"+" Codec}]] - [control - ["[0]" maybe]] - [data - [collection - ["[0]" list ("[1]#[0]" mix)]]] - [math - [number - ["n" nat] - ["[0]" i64]]]]]) + [library + [lux {"-" char} + ["@" target] + [abstract + [hash {"+" Hash}] + [monoid {"+" Monoid}] + [equivalence {"+" Equivalence}] + [order {"+" Order}] + [monad {"+" do}] + [codec {"+" Codec}]] + [control + ["[0]" maybe]] + [data + [collection + ["[0]" list ("[1]#[0]" mix)]]] + [math + [number + ["n" nat] + ["[0]" i64]]]]]) (type: .public Char Nat) @@ -182,48 +182,77 @@ [[pre post] (..split_by pattern template)] (in ($_ "lux text concat" pre replacement post))))) +(for [@.js (as_is (macro: (defined? tokens lux) + (case tokens + (^ (list it)) + {.#Right [lux (list (` (.case ("js type-of" ("js constant" (~ it))) + "undefined" + .false + + (~' _) + .true)))]} + + _ + {.#Left ""})) + (macro: (if_nashorn tokens lux) + (case tokens + (^ (list then else)) + {.#Right [lux (list (if (and (..defined? "java") + (..defined? "java.lang") + (..defined? "java.lang.Object")) + then + else))]} + + _ + {.#Left ""})))] + (as_is)) + (def: .public (replaced pattern replacement template) (-> Text Text Text Text) - (for [@.old - (:as Text - ("jvm invokevirtual:java.lang.String:replace:java.lang.CharSequence,java.lang.CharSequence" - (:as (Primitive "java.lang.String") template) - (:as (Primitive "java.lang.CharSequence") pattern) - (:as (Primitive "java.lang.CharSequence") replacement))) - @.jvm - (:as Text - ("jvm member invoke virtual" [] "java.lang.String" "replace" [] - (:as (Primitive "java.lang.String") template) - ["Ljava/lang/CharSequence;" (:as (Primitive "java.lang.CharSequence") pattern)] - ["Ljava/lang/CharSequence;" (:as (Primitive "java.lang.CharSequence") replacement)])) - ... TODO: Comment/turn-off when generating a JS compiler using a JVM-based compiler because Nashorn's implementation of "replaceAll" is incorrect. - @.js - (:as Text - ("js object do" "replaceAll" template [pattern replacement])) - @.python - (:as Text - ("python object do" "replace" template pattern replacement)) - ... TODO @.lua - @.ruby - (:as Text - ("ruby object do" "gsub" template pattern replacement)) - @.php - (:as Text - ("php apply" (:expected ("php constant" "str_replace")) - pattern replacement template)) - ... TODO @.scheme - ... TODO @.common_lisp - ... TODO @.r - ] - ... Inefficient default - (loop [left "" - right template] - (case (..split_by pattern right) - {.#Some [pre post]} - (again ($_ "lux text concat" left pre replacement) post) - - {.#None} - ("lux text concat" left right))))) + (with_expansions [... Inefficient default + (loop [left "" + right template] + (case (..split_by pattern right) + {.#Some [pre post]} + (again ($_ "lux text concat" left pre replacement) post) + + {.#None} + ("lux text concat" left right)))] + (for [@.old + (:as Text + ("jvm invokevirtual:java.lang.String:replace:java.lang.CharSequence,java.lang.CharSequence" + (:as (Primitive "java.lang.String") template) + (:as (Primitive "java.lang.CharSequence") pattern) + (:as (Primitive "java.lang.CharSequence") replacement))) + @.jvm + (:as Text + ("jvm member invoke virtual" [] "java.lang.String" "replace" [] + (:as (Primitive "java.lang.String") template) + ["Ljava/lang/CharSequence;" (:as (Primitive "java.lang.CharSequence") pattern)] + ["Ljava/lang/CharSequence;" (:as (Primitive "java.lang.CharSequence") replacement)])) + @.js + ... TODO: Remove this when Nashorn is no longer being used. + (..if_nashorn + + (:as Text + ("js object do" "replaceAll" template [pattern replacement]))) + @.python + (:as Text + ("python object do" "replace" template pattern replacement)) + ... TODO @.lua + @.ruby + (:as Text + ("ruby object do" "gsub" template pattern replacement)) + @.php + (:as Text + ("php apply" (:expected ("php constant" "str_replace")) + pattern replacement template)) + ... TODO @.scheme + ... TODO @.common_lisp + ... TODO @.r + ] + ... Inefficient default + ))) (implementation: .public equivalence (Equivalence Text) diff --git a/stdlib/source/library/lux/data/text/encoding/utf8.lux b/stdlib/source/library/lux/data/text/encoding/utf8.lux index bcc1a0ee2..ac4a452be 100644 --- a/stdlib/source/library/lux/data/text/encoding/utf8.lux +++ b/stdlib/source/library/lux/data/text/encoding/utf8.lux @@ -1,15 +1,15 @@ (.using - [library - [lux "*" - ["@" target] - ["[0]" ffi] - [abstract - [codec {"+" Codec}]] - [control - ["[0]" try {"+" Try}]] - [data - ["[0]" binary {"+" Binary}]]]] - ["[0]" //]) + [library + [lux "*" + ["@" target] + ["[0]" ffi] + [abstract + [codec {"+" Codec}]] + [control + ["[0]" try {"+" Try}]] + [data + ["[0]" binary {"+" Binary}]]]] + ["[0]" //]) (with_expansions [ (as_is (ffi.import: java/lang/String ["[1]::[0]" @@ -19,7 +19,8 @@ @.jvm (as_is ) @.js - (as_is (ffi.import: Uint8Array) + (as_is (ffi.import: Uint8Array + ["[1]::[0]"]) ... On Node (ffi.import: Buffer diff --git a/stdlib/source/library/lux/ffi.js.lux b/stdlib/source/library/lux/ffi.js.lux index ddcac1a30..8cae0a976 100644 --- a/stdlib/source/library/lux/ffi.js.lux +++ b/stdlib/source/library/lux/ffi.js.lux @@ -1,26 +1,26 @@ (.using - [library - [lux {"-" Symbol} - ["[0]" meta] - [abstract - [monad {"+" do}]] - [control - ["[0]" io] - ["[0]" maybe] - ["<>" parser ("[1]#[0]" monad) - ["<[0]>" code {"+" Parser}]]] - [data - ["[0]" product] - ["[0]" text - ["%" format]] - [collection - ["[0]" list ("[1]#[0]" functor)]]] - [type - abstract] - [macro {"+" with_symbols} - [syntax {"+" syntax:}] - ["[0]" code] - ["[0]" template]]]]) + [library + [lux {"-" Symbol} + ["[0]" meta] + [abstract + [monad {"+" do}]] + [control + ["[0]" io] + ["[0]" maybe] + ["<>" parser ("[1]#[0]" monad) + ["<[0]>" code {"+" Parser}]]] + [data + ["[0]" product] + ["[0]" text + ["%" format]] + [collection + ["[0]" list ("[1]#[0]" functor)]]] + [type + abstract] + [macro {"+" with_symbols} + [syntax {"+" syntax:}] + ["[0]" code] + ["[0]" template]]]]) (abstract: .public (Object brand) Any) @@ -79,6 +79,13 @@ .local_symbol ..nullable))) +(def: constant_import + (Parser Field) + (.form ($_ <>.and + (<>#in true) + .local_symbol + ..nullable))) + (type: Common_Method (Record [#name Text @@ -177,7 +184,8 @@ (type: Import (Variant {#Class [Class_Declaration Text (List Member)]} - {#Function Static_Method})) + {#Function Static_Method} + {#Constant Field})) (def: class_declaration (Parser Class_Declaration) @@ -188,11 +196,12 @@ (def: import (Parser Import) - (<>.or (<>.and ..class_declaration - (<>.else ["" (list)] - (.tuple (<>.and .text - (<>.some member))))) - (.form ..common_method))) + ($_ <>.or + (<>.and ..class_declaration + (.tuple (<>.and .text + (<>.some member)))) + (.form ..common_method) + ..constant_import)) (def: (with_io with? without) (-> Bit Code Code) @@ -320,6 +329,13 @@ io? try? outputT))) + + {#Constant [_ name :output:]} + (in (list (` (.def: (~ (code.local_symbol name)) + (~ (nullable_type :output:)) + (.:expected + (~ (<| (without_null g!temp :output:) + (` ("js constant" (~ (code.text name))))))))))) ))) (template: .public (type_of object) diff --git a/stdlib/source/library/lux/ffi.jvm.lux b/stdlib/source/library/lux/ffi.jvm.lux index a93701270..a1d5abe96 100644 --- a/stdlib/source/library/lux/ffi.jvm.lux +++ b/stdlib/source/library/lux/ffi.jvm.lux @@ -1,12 +1,10 @@ (.using [library - ["[0]" lux {"-" Primitive Type type int char :as function} + [lux {"-" Primitive Type type int char :as} ["[0]" meta] [abstract - ["[0]" monad {"+" Monad do}] - ["[0]" enum]] + ["[0]" monad {"+" do}]] [control - ["[0]" function] ["[0]" io] ["[0]" maybe] ["[0]" try {"+" Try}] @@ -26,17 +24,17 @@ ["[0]" code] ["[0]" template]] [target - [jvm + ["[0]" jvm "_" [encoding ["[0]" name {"+" External}]] - ["[0]" type {"+" Type Argument Typed} + ["[1]" type {"+" Type Argument Typed} ["[0]" category {"+" Void Value' Value Return' Return Method Primitive Object Class Array Var Parameter Declaration}] ["[0]" box] ["[0]" descriptor] ["[0]" signature] ["[0]" reflection] ["[0]" parser]]]] - ["[1]_[0]" type ("[1]#[0]" equivalence) + ["[0]" type ("[1]#[0]" equivalence) ["[0]" check]]]]) (def: internal @@ -47,12 +45,12 @@ (def: signature (All (_ category) (-> (Type category) Text)) - (|>> type.signature signature.signature)) + (|>> jvm.signature signature.signature)) (def: reflection (All (_ category) (-> (Type (<| Return' Value' category)) Text)) - (|>> type.reflection reflection.reflection)) + (|>> jvm.reflection reflection.reflection)) (template [ ] [(`` (def: .public @@ -101,15 +99,15 @@ (def: boxes (Dictionary (Type Value) Text) - (|> (list [type.boolean box.boolean] - [type.byte box.byte] - [type.short box.short] - [type.int box.int] - [type.long box.long] - [type.float box.float] - [type.double box.double] - [type.char box.char]) - (dictionary.of_list type.hash))) + (|> (list [jvm.boolean box.boolean] + [jvm.byte box.byte] + [jvm.short box.short] + [jvm.int box.int] + [jvm.long box.long] + [jvm.float box.float] + [jvm.double box.double] + [jvm.char box.char]) + (dictionary.of_list jvm.hash))) (template [
 ]
   [(def: ( unboxed boxed raw)
@@ -329,32 +327,32 @@
   (-> Primitive_Mode (Type Primitive) Code)
   (case mode
     {#ManualPrM}
-    (cond (# type.equivalence = type.boolean type) (` ..Boolean)
-          (# type.equivalence = type.byte type) (` ..Byte)
-          (# type.equivalence = type.short type) (` ..Short)
-          (# type.equivalence = type.int type) (` ..Integer)
-          (# type.equivalence = type.long type) (` ..Long)
-          (# type.equivalence = type.float type) (` ..Float)
-          (# type.equivalence = type.double type) (` ..Double)
-          (# type.equivalence = type.char type) (` ..Character)
+    (cond (# jvm.equivalence = jvm.boolean type) (` ..Boolean)
+          (# jvm.equivalence = jvm.byte type) (` ..Byte)
+          (# jvm.equivalence = jvm.short type) (` ..Short)
+          (# jvm.equivalence = jvm.int type) (` ..Integer)
+          (# jvm.equivalence = jvm.long type) (` ..Long)
+          (# jvm.equivalence = jvm.float type) (` ..Float)
+          (# jvm.equivalence = jvm.double type) (` ..Double)
+          (# jvm.equivalence = jvm.char type) (` ..Character)
           ... else
           (undefined))
     
     {#AutoPrM}
-    (cond (# type.equivalence = type.boolean type)
+    (cond (# jvm.equivalence = jvm.boolean type)
           (` .Bit)
           
-          (or (# type.equivalence = type.short type)
-              (# type.equivalence = type.byte type)
-              (# type.equivalence = type.int type)
-              (# type.equivalence = type.long type))
+          (or (# jvm.equivalence = jvm.short type)
+              (# jvm.equivalence = jvm.byte type)
+              (# jvm.equivalence = jvm.int type)
+              (# jvm.equivalence = jvm.long type))
           (` .Int)
           
-          (or (# type.equivalence = type.float type)
-              (# type.equivalence = type.double type))
+          (or (# jvm.equivalence = jvm.float type)
+              (# jvm.equivalence = jvm.double type))
           (` .Frac)
 
-          (# type.equivalence = type.char type)
+          (# jvm.equivalence = jvm.char type)
           (` .Nat)
 
           ... else
@@ -380,7 +378,7 @@
                 [parser.array? elementT
                  (case (parser.primitive? elementT)
                    {.#Some elementT}
-                   (` {.#Primitive (~ (code.text (..reflection (type.array elementT)))) {.#End}})
+                   (` {.#Primitive (~ (code.text (..reflection (jvm.array elementT)))) {.#End}})
                    
                    {.#None}
                    (` {.#Primitive (~ (code.text array.type_name))
@@ -587,7 +585,7 @@
                           ($_ <>.either
                               (<>.and class_name^ (<>#in (list)))
                               (.form (<>.and class_name^ (<>.some (parameter^ type_vars))))))]
-    (in (type.class (name.safe name) parameters))))
+    (in (jvm.class (name.safe name) parameters))))
 
 (exception: .public (unknown_type_variable [name Text
                                             type_vars (List (Type Var))])
@@ -601,13 +599,13 @@
     [name .local_symbol
      _ (..assertion ..unknown_type_variable [name options]
                     (list.member? text.equivalence (list#each parser.name options) name))]
-    (in (type.var name))))
+    (in (jvm.var name))))
 
 (def: wildcard^
   (Parser (Type Parameter))
   (do <>.monad
     [_ (.this! (' ?))]
-    (in type.wildcard)))
+    (in jvm.wildcard)))
 
 (template [  ]
   [(def: 
@@ -617,14 +615,14 @@
           .tuple
           (# <>.monad each )))]
 
-  [upper^ < type.upper]
-  [lower^ > type.lower]
+  [upper^ < jvm.upper]
+  [lower^ > jvm.lower]
   )
 
 (def: (parameter^ type_vars)
   (-> (List (Type Var)) (Parser (Type Parameter)))
   (<>.rec
-   (.function (_ _)
+   (function (_ _)
      (let [class^ (..class^' parameter^ type_vars)]
        ($_ <>.either
            (..type_variable type_vars)
@@ -645,25 +643,25 @@
 (def: primitive^
   (Parser (Type Primitive))
   ($_ <>.either
-      (itself^ type.boolean)
-      (itself^ type.byte)
-      (itself^ type.short)
-      (itself^ type.int)
-      (itself^ type.long)
-      (itself^ type.float)
-      (itself^ type.double)
-      (itself^ type.char)
+      (itself^ jvm.boolean)
+      (itself^ jvm.byte)
+      (itself^ jvm.short)
+      (itself^ jvm.int)
+      (itself^ jvm.long)
+      (itself^ jvm.float)
+      (itself^ jvm.double)
+      (itself^ jvm.char)
       ))
 
 (def: array^
   (-> (Parser (Type Value)) (Parser (Type Array)))
   (|>> .tuple
-       (# <>.monad each type.array)))
+       (# <>.monad each jvm.array)))
 
 (def: (type^ type_vars)
   (-> (List (Type Var)) (Parser (Type Value)))
   (<>.rec
-   (.function (_ type^)
+   (function (_ type^)
      ($_ <>.either
          ..primitive^
          (..parameter^ type_vars)
@@ -674,7 +672,7 @@
   (Parser (Type Void))
   (do <>.monad
     [_ (.symbol! ["" (reflection.reflection reflection.void)])]
-    (in type.void)))
+    (in jvm.void)))
 
 (def: (return^ type_vars)
   (-> (List (Type Var)) (Parser (Type Return)))
@@ -683,7 +681,7 @@
 
 (def: var^
   (Parser (Type Var))
-  (# <>.monad each type.var .local_symbol))
+  (# <>.monad each jvm.var .local_symbol))
 
 (def: vars^
   (Parser (List (Type Var)))
@@ -698,7 +696,7 @@
                                     (.form (<>.and (..valid_class_name (list))
                                                          (<>.some var^)))
                                     ))]
-    (in (type.declaration name variables))))
+    (in (jvm.declaration name variables))))
 
 (def: (class^ type_vars)
   (-> (List (Type Var)) (Parser (Type Class)))
@@ -1203,7 +1201,7 @@
 
 (def: $Object
   (Type Class)
-  (type.class "java.lang.Object" (list)))
+  (jvm.class "java.lang.Object" (list)))
 
 (syntax: .public (class: [.let [! <>.monad]
                           im inheritance_modifier^
@@ -1222,7 +1220,7 @@
                                 (list#each (method->parser class_vars fully_qualified_class_name))
                                 (list#mix <>.either (<>.failure ""))))]]
     (in (list (` ("jvm class"
-                  (~ (declaration$ (type.declaration full_class_name class_vars)))
+                  (~ (declaration$ (jvm.declaration full_class_name class_vars)))
                   (~ (class$ super))
                   [(~+ (list#each class$ interfaces))]
                   (~ (inheritance_modifier$ im))
@@ -1237,7 +1235,7 @@
                               annotations ..annotations^
                               members (<>.some (..method_decl^ class_vars))])
   (in (list (` ("jvm class interface"
-                (~ (declaration$ (type.declaration full_class_name class_vars)))
+                (~ (declaration$ (jvm.declaration full_class_name class_vars)))
                 [(~+ (list#each class$ supers))]
                 [(~+ (list#each annotation$ annotations))]
                 (~+ (list#each method_decl$ members)))))))
@@ -1297,7 +1295,7 @@
 
         {.#None}
         (in (list (` (: (-> (.Primitive "java.lang.Object") (~ check_type))
-                        (.function ((~ g!_) (~ g!unchecked))
+                        (function ((~ g!_) (~ g!unchecked))
                           (~ check_code))))))
         ))))
 
@@ -1349,13 +1347,13 @@
       (do [! meta.monad]
         [arg_inputs (monad.each !
                                 (: (-> [Bit (Type Value)] (Meta [Bit Code]))
-                                   (.function (_ [maybe? _])
+                                   (function (_ [maybe? _])
                                      (with_symbols [arg_name]
                                        (in [maybe? arg_name]))))
                                 #import_member_args)
          .let [input_jvm_types (list#each product.right #import_member_args)
                arg_types (list#each (: (-> [Bit (Type Value)] Code)
-                                       (.function (_ [maybe? arg])
+                                       (function (_ [maybe? arg])
                                          (let [arg_type (value_type (value@ #import_member_mode commons) arg)]
                                            (if maybe?
                                              (` (Maybe (~ arg_type)))
@@ -1415,7 +1413,7 @@
                                        {#AutoPrM}
                                        (with_expansions [' (template.spliced )
                                                           (template [ 
 ]
-                                                                        [(# type.equivalence =  unboxed)
+                                                                        [(# jvm.equivalence =  unboxed)
                                                                          (with_expansions [' (template.spliced )]
                                                                            [
                                                                             (` (.|> (~ raw) (~+ 
)))
@@ -1443,23 +1441,23 @@
          (` (.|> (~ unboxed/boxed) (~+ post))))))]
 
   [#1 with_automatic_input_conversion ..unbox
-   [[type.boolean (list (` (.:as (.Primitive (~ (code.text box.boolean)))))) []]
-    [type.byte (list (` (.:as (.Primitive (~ (code.text box.byte)))))) []]
-    [type.short (list (` (.:as (.Primitive (~ (code.text box.short)))))) []]
-    [type.int (list (` (.: (.Primitive (~ (code.text box.int)))))) []]
-    [type.long (list (` (.:as (.Primitive (~ (code.text box.long)))))) []]
-    [type.char (list (` (.:as (.Primitive (~ (code.text box.char)))))) []]
-    [type.float (list (` (.:as (.Primitive (~ (code.text box.float)))))) []]
-    [type.double (list (` (.:as (.Primitive (~ (code.text box.double)))))) []]]]
+   [[jvm.boolean (list (` (.:as (.Primitive (~ (code.text box.boolean)))))) []]
+    [jvm.byte (list (` (.:as (.Primitive (~ (code.text box.byte)))))) []]
+    [jvm.short (list (` (.:as (.Primitive (~ (code.text box.short)))))) []]
+    [jvm.int (list (` (.: (.Primitive (~ (code.text box.int)))))) []]
+    [jvm.long (list (` (.:as (.Primitive (~ (code.text box.long)))))) []]
+    [jvm.char (list (` (.:as (.Primitive (~ (code.text box.char)))))) []]
+    [jvm.float (list (` (.:as (.Primitive (~ (code.text box.float)))))) []]
+    [jvm.double (list (` (.:as (.Primitive (~ (code.text box.double)))))) []]]]
   [#0 with_automatic_output_conversion ..box
-   [[type.boolean (list) [(` (.: (.Primitive (~ (code.text box.boolean)))))]]
-    [type.byte (list) [(` (.: (.Primitive (~ (code.text box.byte)))))]]
-    [type.short (list) [(` (.: (.Primitive (~ (code.text box.short)))))]]
-    [type.int (list) [(` (.: (.Primitive (~ (code.text box.int)))))]]
-    [type.long (list) [(` (.: (.Primitive (~ (code.text box.long)))))]]
-    [type.char (list) [(` (.: (.Primitive (~ (code.text box.char)))))]]
-    [type.float (list) [(` (.: (.Primitive (~ (code.text box.float)))))]]
-    [type.double (list) [(` (.: (.Primitive (~ (code.text box.double)))))]]]]
+   [[jvm.boolean (list) [(` (.: (.Primitive (~ (code.text box.boolean)))))]]
+    [jvm.byte (list) [(` (.: (.Primitive (~ (code.text box.byte)))))]]
+    [jvm.short (list) [(` (.: (.Primitive (~ (code.text box.short)))))]]
+    [jvm.int (list) [(` (.: (.Primitive (~ (code.text box.int)))))]]
+    [jvm.long (list) [(` (.: (.Primitive (~ (code.text box.long)))))]]
+    [jvm.char (list) [(` (.: (.Primitive (~ (code.text box.char)))))]]
+    [jvm.float (list) [(` (.: (.Primitive (~ (code.text box.float)))))]]
+    [jvm.double (list) [(` (.: (.Primitive (~ (code.text box.double)))))]]]]
   )
 
 (def: (un_quoted quoted)
@@ -1470,7 +1468,7 @@
   (-> Primitive_Mode (List (Type Value)) (List [Bit Code]) (List Code))
   (|> inputs
       (list.zipped/2 classes)
-      (list#each (.function (_ [class [maybe? input]])
+      (list#each (function (_ [class [maybe? input]])
                    (|> (if maybe?
                          (` (: (.Primitive (~ (code.text (..reflection class))))
                                ((~! !!!) (~ (..un_quoted input)))))
@@ -1486,7 +1484,7 @@
 
 (def: syntax_inputs
   (-> (List Code) (List Code))
-  (|>> (list#each (.function (_ name)
+  (|>> (list#each (function (_ name)
                     (list name (` (~! .any)))))
        list#conjoint))
 
@@ -1507,7 +1505,7 @@
                                   (` (All ((~ g!_) (~+ =class_tvars))
                                        (.Primitive (~ (code.text full_name)) [(~+ =class_tvars)]))))))
                  getter_interop (: (-> Text Code)
-                                   (.function (_ name)
+                                   (function (_ name)
                                      (let [getter_name (code.symbol ["" (..import_name import_format method_prefix name)])]
                                        (` (def: (~ getter_name)
                                             (~ enum_type)
@@ -1516,7 +1514,7 @@
       
       {#ConstructorDecl [commons _]}
       (do meta.monad
-        [.let [classT (type.class full_name (list))
+        [.let [classT (jvm.class full_name (list))
                def_name (code.symbol ["" (..import_name import_format method_prefix (value@ #import_member_alias commons))])
                jvm_interop (|> [classT
                                 (` ("jvm member invoke constructor"
@@ -1564,13 +1562,13 @@
                               [(~+ (list#each ..var$ (value@ #import_member_tvars commons)))]
                               (~+ (|> object_ast
                                       (list#each ..un_quoted)
-                                      (list.zipped/2 (list (type.class full_name (list))))
+                                      (list.zipped/2 (list (jvm.class full_name (list))))
                                       (list#each (with_automatic_input_conversion (value@ #import_member_mode commons)))))
                               (~+ (|> (jvm_invoke_inputs (value@ #import_member_mode commons) input_jvm_types arg_function_inputs)
                                       (list.zipped/2 input_jvm_types)
                                       (list#each ..decorate_input))))))
                  jvm_interop (: Code
-                                (case (type.void? method_return)
+                                (case (jvm.void? method_return)
                                   {.#Left method_return}
                                   (|> [method_return
                                        callC]
@@ -1674,7 +1672,7 @@
   (do [! meta.monad]
     [kind (class_kind declaration)
      =members (|> bundles
-                  (list#each (.function (_ [import_format members])
+                  (list#each (function (_ [import_format members])
                                (list#each (|>> [import_format]) members)))
                   list.together
                   (monad.each ! (member_import$ class_type_vars kind declaration)))]
@@ -1688,19 +1686,19 @@
                       "jvm object cast"
                       "jvm conversion long-to-int"))]
     (`` (cond (~~ (template [ ]
-                    [(# type.equivalence =  type)
+                    [(# jvm.equivalence =  type)
                      (in (list (` ( (~ g!size)))))]
 
-                    [type.boolean "jvm array new boolean"]
-                    [type.byte    "jvm array new byte"]
-                    [type.short   "jvm array new short"]
-                    [type.int     "jvm array new int"]
-                    [type.long    "jvm array new long"]
-                    [type.float   "jvm array new float"]
-                    [type.double  "jvm array new double"]
-                    [type.char    "jvm array new char"]))
+                    [jvm.boolean "jvm array new boolean"]
+                    [jvm.byte    "jvm array new byte"]
+                    [jvm.short   "jvm array new short"]
+                    [jvm.int     "jvm array new int"]
+                    [jvm.long    "jvm array new long"]
+                    [jvm.float   "jvm array new float"]
+                    [jvm.double  "jvm array new double"]
+                    [jvm.char    "jvm array new char"]))
               ... else
-              (in (list (` (: (~ (value_type {#ManualPrM} (type.array type)))
+              (in (list (` (: (~ (value_type {#ManualPrM} (jvm.array type)))
                               ("jvm array new object" (~ g!size))))))))))
 
 (exception: .public (cannot_convert_to_jvm_type [type .Type])
@@ -1710,7 +1708,7 @@
 (with_expansions [ (as_is (meta.failure (exception.error ..cannot_convert_to_jvm_type [type])))]
   (def: (lux_type->jvm_type context type)
     (-> Type_Context .Type (Meta (Type Value)))
-    (if (lux_type#= .Any type)
+    (if (type#= .Any type)
       (# meta.monad in $Object)
       (case type
         {.#Primitive name params}
@@ -1723,37 +1721,37 @@
                            _
                            )]
                         
-                        [type.boolean]
-                        [type.byte]
-                        [type.short]
-                        [type.int]
-                        [type.long]
-                        [type.float]
-                        [type.double]
-                        [type.char]))
+                        [jvm.boolean]
+                        [jvm.byte]
+                        [jvm.short]
+                        [jvm.int]
+                        [jvm.long]
+                        [jvm.float]
+                        [jvm.double]
+                        [jvm.char]))
 
                   (~~ (template []
-                        [(text#= (..reflection (type.array )) name)
+                        [(text#= (..reflection (jvm.array )) name)
                          (case params
                            {.#End}
-                           (# meta.monad in (type.array ))
+                           (# meta.monad in (jvm.array ))
 
                            _
                            )]
                         
-                        [type.boolean]
-                        [type.byte]
-                        [type.short]
-                        [type.int]
-                        [type.long]
-                        [type.float]
-                        [type.double]
-                        [type.char]))
+                        [jvm.boolean]
+                        [jvm.byte]
+                        [jvm.short]
+                        [jvm.int]
+                        [jvm.long]
+                        [jvm.float]
+                        [jvm.double]
+                        [jvm.char]))
 
                   (text#= array.type_name name)
                   (case params
                     {.#Item elementLT {.#End}}
-                    (# meta.monad each type.array
+                    (# meta.monad each jvm.array
                        (lux_type->jvm_type context elementLT))
 
                     _
@@ -1763,17 +1761,17 @@
                   (case params
                     {.#End}
                     (let [[_ unprefixed] (maybe.trusted (text.split_by descriptor.array_prefix name))]
-                      (# meta.monad each type.array
+                      (# meta.monad each jvm.array
                          (lux_type->jvm_type context {.#Primitive unprefixed (list)})))
 
                     _
                     )
 
                   ... else
-                  (# meta.monad each (type.class name)
+                  (# meta.monad each (jvm.class name)
                      (: (Meta (List (Type Parameter)))
                         (monad.each meta.monad
-                                    (.function (_ paramLT)
+                                    (function (_ paramLT)
                                       (do meta.monad
                                         [paramJT (lux_type->jvm_type context paramLT)]
                                         (case (parser.parameter? paramJT)
@@ -1785,7 +1783,7 @@
                                     params)))))
 
         {.#Apply A F}
-        (case (lux_type.applied (list A) F)
+        (case (type.applied (list A) F)
           {.#None}
           
 
@@ -1814,19 +1812,19 @@
        context meta.type_context
        array_jvm_type (lux_type->jvm_type context array_type)
        .let [g!extension (code.text (`` (cond (~~ (template [ ]
-                                                    [(# type.equivalence =
-                                                        (type.array )
+                                                    [(# jvm.equivalence =
+                                                        (jvm.array )
                                                         array_jvm_type)
                                                      ]
 
-                                                    [type.boolean "jvm array length boolean"]
-                                                    [type.byte "jvm array length byte"]
-                                                    [type.short "jvm array length short"]
-                                                    [type.int "jvm array length int"]
-                                                    [type.long "jvm array length long"]
-                                                    [type.float "jvm array length float"]
-                                                    [type.double "jvm array length double"]
-                                                    [type.char "jvm array length char"]))
+                                                    [jvm.boolean "jvm array length boolean"]
+                                                    [jvm.byte "jvm array length byte"]
+                                                    [jvm.short "jvm array length short"]
+                                                    [jvm.int "jvm array length int"]
+                                                    [jvm.long "jvm array length long"]
+                                                    [jvm.float "jvm array length float"]
+                                                    [jvm.double "jvm array length double"]
+                                                    [jvm.char "jvm array length char"]))
                                               
                                               ... else
                                               "jvm array length object")))]]
@@ -1855,21 +1853,21 @@
                            "jvm object cast"
                            "jvm conversion long-to-int"))]]
       (`` (cond (~~ (template [  ]
-                      [(# type.equivalence =
-                          (type.array )
+                      [(# jvm.equivalence =
+                          (jvm.array )
                           array_jvm_type)
                        (in (list (` (.|> ( (~ g!idx) (~ array))
                                          "jvm object cast"
                                          (.: (.Primitive (~ (code.text ))))))))]
 
-                      [type.boolean "jvm array read boolean" box.boolean]
-                      [type.byte "jvm array read byte" box.byte]
-                      [type.short "jvm array read short" box.short]
-                      [type.int "jvm array read int" box.int]
-                      [type.long "jvm array read long" box.long]
-                      [type.float "jvm array read float" box.float]
-                      [type.double "jvm array read double" box.double]
-                      [type.char "jvm array read char" box.char]))
+                      [jvm.boolean "jvm array read boolean" box.boolean]
+                      [jvm.byte "jvm array read byte" box.byte]
+                      [jvm.short "jvm array read short" box.short]
+                      [jvm.int "jvm array read int" box.int]
+                      [jvm.long "jvm array read long" box.long]
+                      [jvm.float "jvm array read float" box.float]
+                      [jvm.double "jvm array read double" box.double]
+                      [jvm.char "jvm array read char" box.char]))
                 
                 ... else
                 (in (list (` ("jvm array read object" (~ g!idx) (~ array))))))))
@@ -1894,22 +1892,22 @@
                            "jvm object cast"
                            "jvm conversion long-to-int"))]]
       (`` (cond (~~ (template [  ]
-                      [(# type.equivalence =
-                          (type.array )
+                      [(# jvm.equivalence =
+                          (jvm.array )
                           array_jvm_type)
                        (let [g!value (` (.|> (~ value)
                                              (.:as (.Primitive (~ (code.text ))))
                                              "jvm object cast"))]
                          (in (list (` ( (~ g!idx) (~ g!value) (~ array))))))]
 
-                      [type.boolean "jvm array write boolean" box.boolean]
-                      [type.byte "jvm array write byte" box.byte]
-                      [type.short "jvm array write short" box.short]
-                      [type.int "jvm array write int" box.int]
-                      [type.long "jvm array write long" box.long]
-                      [type.float "jvm array write float" box.float]
-                      [type.double "jvm array write double" box.double]
-                      [type.char "jvm array write char" box.char]))
+                      [jvm.boolean "jvm array write boolean" box.boolean]
+                      [jvm.byte "jvm array write byte" box.byte]
+                      [jvm.short "jvm array write short" box.short]
+                      [jvm.int "jvm array write int" box.int]
+                      [jvm.long "jvm array write long" box.long]
+                      [jvm.float "jvm array write float" box.float]
+                      [jvm.double "jvm array write double" box.double]
+                      [jvm.char "jvm array write char" box.char]))
                 
                 ... else
                 (in (list (` ("jvm array write object" (~ g!idx) (~ value) (~ array))))))))
@@ -1967,96 +1965,3 @@
   [as_char .Int ..long_to_char ..Long ..char_to_long ..Character of_char]
   [as_float .Frac ..double_to_float ..Double ..float_to_double ..Float of_float]
   )
-
-(type: (API of)
-  (Record
-   [#interface of
-    #type Code
-    #term Code]))
-
-(def: (api of)
-  (All (_ of) (-> (Parser of) (Parser (API of))))
-  (.form
-   ($_ <>.and
-       of
-       .any
-       .any
-       )))
-
-(type: Constant
-  Text)
-
-(def: constant
-  (Parser Constant)
-  .local_symbol)
-
-(type: Function
-  (Record
-   [#variables (List Text)
-    #name Text
-    #requirements (List [Text Code])]))
-
-(def: function
-  (Parser Function)
-  (.form
-   ($_ <>.and
-       (<>.else (list) (.tuple (<>.some .local_symbol)))
-       .local_symbol
-       (.tuple (<>.some ($_ <>.and
-                                  .local_symbol
-                                  .any
-                                  )))
-       )))
-
-(type: Export
-  (Variant
-   {#Constant (API Constant)}
-   {#Function (API Function)}))
-
-(def: export
-  (Parser Export)
-  ($_ <>.or
-      (..api ..constant)
-      (..api ..function)
-      ))
-
-(syntax: .public (export: [api .local_symbol
-                           exports (<>.many ..export)])
-  (let [initialization (: (List (API Constant))
-                          (list.all (.function (_ it)
-                                      (case it
-                                        {#Constant it}
-                                        {.#Some it}
-                                        
-                                        _
-                                        {.#None}))
-                                    exports))]
-    (in (list (` (..class: "final" (~ (code.local_symbol api))
-                   (~+ (list#each (.function (_ it)
-                                    (case it
-                                      {#Constant [name type term]}
-                                      (` ("public" "final" "static" (~ (code.local_symbol name)) (~ type)))
-                                      
-                                      {#Function [[variables name requirements] type term]}
-                                      (` ("public" "strict" "static"
-                                          [(~+ (list#each code.local_symbol variables))]
-                                          ((~ (code.local_symbol name))
-                                           [(~+ (|> requirements
-                                                    (list#each (.function (_ [name type])
-                                                                 (list (code.local_symbol name)
-                                                                       type)))
-                                                    list#conjoint))])
-                                          (~ type)
-                                          (~ term)))))
-                                  exports))
-                   ... Useless constructor
-                   ("private" [] ((~' new) (~' self) []) [] [])
-                   ("public" "strict" "static" [] ((~' ) [])
-                    (~' void)
-                    [(~+ (list#each (.function (_ [name type term])
-                                      (` ("jvm member put static"
-                                          (~ (code.text api))
-                                          (~ (code.text name))
-                                          ("jvm object cast" (~ term)))))
-                                    initialization))])
-                   ))))))
diff --git a/stdlib/source/library/lux/ffi.py.lux b/stdlib/source/library/lux/ffi.py.lux
index 6f6bc2b96..440f8f68b 100644
--- a/stdlib/source/library/lux/ffi.py.lux
+++ b/stdlib/source/library/lux/ffi.py.lux
@@ -1,27 +1,27 @@
 (.using
-  [library
-   [lux "*"
-    ["[0]" meta]
-    ["@" target]
-    [abstract
-     [monad {"+" do}]]
-    [control
-     ["[0]" io]
-     ["[0]" maybe]
-     ["<>" parser
-      ["<[0]>" code {"+" Parser}]]]
-    [data
-     ["[0]" product]
-     ["[0]" text
-      ["%" format]]
-     [collection
-      ["[0]" list ("[1]#[0]" functor mix)]]]
-    [type
-     abstract]
-    [macro {"+" with_symbols}
-     [syntax {"+" syntax:}]
-     ["[0]" code]
-     ["[0]" template]]]])
+ [library
+  [lux {"-" Alias}
+   ["@" target]
+   ["[0]" meta]
+   [abstract
+    [monad {"+" do}]]
+   [control
+    ["[0]" io]
+    ["[0]" maybe]
+    ["<>" parser
+     ["<[0]>" code {"+" Parser}]]]
+   [data
+    ["[0]" product]
+    ["[0]" text
+     ["%" format]]
+    [collection
+     ["[0]" list ("[1]#[0]" monad mix)]]]
+   [macro {"+" with_symbols}
+    [syntax {"+" syntax:}]
+    ["[0]" code]
+    ["[0]" template]]
+   [type
+    abstract]]])
 
 (abstract: .public (Object brand) Any)
 
@@ -78,10 +78,31 @@
                    .local_symbol
                    ..noneable)))
 
+(type: Alias
+  (Maybe Text))
+
+(def: alias
+  (Parser Alias)
+  (<>.maybe (<>.after (.this! (' "as")) .local_symbol)))
+
+(type: Constant
+  [Text
+   Alias
+   Noneable])
+
+(def: constant
+  (Parser Constant)
+  (.form
+   ($_ <>.and
+       .local_symbol
+       ..alias
+       ..noneable
+       )))
+
 (type: Common_Method
   (Record
    [#name Text
-    #alias (Maybe Text)
+    #alias Alias
     #inputs (List Noneable)
     #io? Bit
     #try? Bit
@@ -99,7 +120,7 @@
   (Parser Common_Method)
   ($_ <>.and
       .local_symbol
-      (<>.maybe (<>.after (.this! (' "as")) .local_symbol))
+      ..alias
       (.tuple (<>.some ..noneable))
       (<>.parses? (.this! (' "io")))
       (<>.parses? (.this! (' "try")))
@@ -157,23 +178,26 @@
          (if ("python object none?" (~ g!temp))
            {.#None}
            {.#Some (~ g!temp)})))
-    (` (let [(~ g!temp) (~ output)]
-         (if (not ("python object none?" (~ g!temp)))
+    (` (.let [(~ g!temp) (~ output)]
+         (.if (.not ("python object none?" (~ g!temp)))
            (~ g!temp)
            (.panic! "None is an invalid value!"))))))
 
 (type: Import
   (Variant
    {#Class [Text Text (List Member)]}
-   {#Function Static_Method}))
+   {#Function Static_Method}
+   {#Constant Constant}))
 
 (def: import
   (Parser Import)
-  (<>.or (<>.and .local_symbol
-                 (<>.else ["" (list)]
-                          (.tuple (<>.and .text
-                                                (<>.some member)))))
-         (.form ..common_method)))
+  ($_ <>.or
+      (<>.and .local_symbol
+              (<>.else ["" (list)]
+                       (.tuple (<>.and .text
+                                             (<>.some member)))))
+      (.form ..common_method)
+      ..constant))
 
 (def: (with_io with? without)
   (-> Bit Code Code)
@@ -202,13 +226,13 @@
 (def: (make_function g!method g!temp source inputsT io? try? outputT)
   (-> Code Code Code (List Noneable) Bit Bit Noneable Code)
   (let [g!inputs (input_variables inputsT)]
-    (` (def: ((~ g!method)
-              [(~+ (list#each product.right g!inputs))])
+    (` (.def: ((~ g!method)
+               [(~+ (list#each product.right g!inputs))])
          (-> [(~+ (list#each noneable_type inputsT))]
              (~ (|> (noneable_type outputT)
                     (try_type try?)
                     (io_type io?))))
-         (:expected
+         (.:expected
           (~ (<| (with_io io?)
                  (with_try try?)
                  (without_none g!temp outputT)
@@ -233,25 +257,25 @@
                          {.#Item head tail}
                          (list#mix (function (_ sub super)
                                      (` ("python object get" (~ (code.text sub))
-                                         (:as (..Object .Any) (~ super)))))
+                                         (.:as (..Object .Any) (~ super)))))
                                    (` ("python import" (~ (code.text head))))
                                    tail)
                          
                          {.#End}
                          (` ("python import" (~ (code.text class)))))]
-          (in (list& (` (type: (~ g!type)
-                          (..Object (Primitive (~ (code.text real_class))))))
+          (in (list& (` (.type: (~ g!type)
+                          (..Object (.Primitive (~ (code.text real_class))))))
                      (list#each (function (_ member)
                                   (case member
                                     {#Constructor inputsT}
                                     (let [g!inputs (input_variables inputsT)]
-                                      (` (def: ((~ (qualify "new"))
-                                                [(~+ (list#each product.right g!inputs))])
-                                           (-> [(~+ (list#each noneable_type inputsT))]
-                                               (~ g!type))
-                                           (:expected
+                                      (` (.def: ((~ (qualify "new"))
+                                                 [(~+ (list#each product.right g!inputs))])
+                                           (.-> [(~+ (list#each noneable_type inputsT))]
+                                                (~ g!type))
+                                           (.:expected
                                             ("python apply"
-                                             (:as ..Function (~ imported))
+                                             (.:as ..Function (~ imported))
                                              (~+ (list#each (with_none g!temp) g!inputs)))))))
                                     
                                     {#Field [static? field fieldT]}
@@ -261,13 +285,13 @@
                                              (list (` (.:as (~ (noneable_type fieldT))
                                                             ("python object get" (~ (code.text field))
                                                              (:as (..Object .Any) (~ imported)))))))))
-                                      (` (def: ((~ (qualify field))
-                                                (~ g!object))
-                                           (-> (~ g!type)
-                                               (~ (noneable_type fieldT)))
-                                           (:expected
+                                      (` (.def: ((~ (qualify field))
+                                                 (~ g!object))
+                                           (.-> (~ g!type)
+                                                (~ (noneable_type fieldT)))
+                                           (.:expected
                                             (~ (without_none g!temp fieldT (` ("python object get" (~ (code.text field))
-                                                                               (:as (..Object .Any) (~ g!object))))))))))
+                                                                               (.:as (..Object .Any) (~ g!object))))))))))
                                     
                                     {#Method method}
                                     (case method
@@ -275,7 +299,7 @@
                                       (..make_function (qualify (maybe.else method alias))
                                                        g!temp
                                                        (` ("python object get" (~ (code.text method))
-                                                           (:as (..Object .Any) (~ imported))))
+                                                           (.:as (..Object .Any) (~ imported))))
                                                        inputsT
                                                        io?
                                                        try?
@@ -283,15 +307,15 @@
                                       
                                       {#Virtual [method alias inputsT io? try? outputT]}
                                       (let [g!inputs (input_variables inputsT)]
-                                        (` (def: ((~ (qualify (maybe.else method alias)))
-                                                  [(~+ (list#each product.right g!inputs))]
-                                                  (~ g!object))
-                                             (-> [(~+ (list#each noneable_type inputsT))]
-                                                 (~ g!type)
-                                                 (~ (|> (noneable_type outputT)
-                                                        (try_type try?)
-                                                        (io_type io?))))
-                                             (:expected
+                                        (` (.def: ((~ (qualify (maybe.else method alias)))
+                                                   [(~+ (list#each product.right g!inputs))]
+                                                   (~ g!object))
+                                             (.-> [(~+ (list#each noneable_type inputsT))]
+                                                  (~ g!type)
+                                                  (~ (|> (noneable_type outputT)
+                                                         (try_type try?)
+                                                         (io_type io?))))
+                                             (.:expected
                                               (~ (<| (with_io io?)
                                                      (with_try try?)
                                                      (without_none g!temp outputT)
@@ -309,6 +333,13 @@
                                  io?
                                  try?
                                  outputT)))
+
+      {#Constant [name alias :constant:]}
+      (in (list (` (.def: (~ (code.local_symbol (maybe.else name alias)))
+                     (~ (noneable_type :constant:))
+                     (.:expected
+                      (~ (without_none g!temp :constant:
+                                       (` ("python constant" (~ (code.text name)))))))))))
       )))
 
 (template: .public (lambda  )
diff --git a/stdlib/source/library/lux/ffi/export.js.lux b/stdlib/source/library/lux/ffi/export.js.lux
new file mode 100644
index 000000000..a73437f72
--- /dev/null
+++ b/stdlib/source/library/lux/ffi/export.js.lux
@@ -0,0 +1,96 @@
+(.using
+ [library
+  [lux "*"
+   [extension {"+" directive:}]
+   ["[0]" meta]
+   ["[0]" static]
+   [abstract
+    ["[0]" monad {"+" do}]]
+   [control
+    ["<>" parser
+     ["<[0]>" code]]]
+   [data
+    [text
+     ["%" format]]
+    [collection
+     ["[0]" list ("[1]#[0]" monad mix)]
+     ["[0]" set]]]
+   ["[0]" macro
+    [syntax {"+" syntax:}]
+    ["[0]" code]]
+   [math
+    ["[0]" random]]
+   [target
+    ["/" js]]
+   [tool
+    [compiler
+     ["[0]" phase]
+     [meta
+      [cache
+       ["[0]" dependency "_"
+        ["[1]" artifact]]]]
+     [language
+      [lux
+       ["[0]" generation]
+       ["[0]" directive]
+       [analysis
+        ["[0]" type]]]]]]]])
+
+(def: definition
+  (-> Code (Meta [Text Code]))
+  (|>> (list)
+       (.result (<| .form
+                          (<>.after (.text! "lux def"))
+                          (<>.before .any)
+                          ($_ <>.and
+                              .local_symbol
+                              .any)))
+       meta.lifted))
+
+(with_expansions [ (static.random (|>> %.nat (%.format "lua export ") code.text)
+                                             random.nat)]
+  (directive: ( self phase archive [name .text
+                                               term .any])
+    (do [! phase.monad]
+      [next directive.analysis
+       [_ term] (<| directive.lifted_analysis
+                    type.inferring
+                    (next archive term))
+
+       next directive.synthesis
+       term (directive.lifted_synthesis
+             (next archive term))
+
+       dependencies (directive.lifted_generation
+                     (dependency.dependencies archive term))
+
+       next directive.generation
+       [interim_artifacts term] (directive.lifted_generation
+                                 (generation.with_interim_artifacts archive
+                                   (next archive term)))
+
+       _ (directive.lifted_generation
+          (do !
+            [@self (generation.learn_custom name (list#mix set.has dependencies interim_artifacts))
+             .let [$module (/.var "module")
+                   $exports (/.the "exports" $module)
+                   definition (/.define (/.var name) term)
+                   export (/.when (/.not (/.= (/.string "undefined") (/.type_of $module)))
+                                  (/.set (/.the name $exports) (/.var name)))
+                   code ($_ /.then
+                            definition
+                            export)]
+             _ (generation.execute! definition)
+             _ (generation.save! @self {.#None} code)]
+            (generation.log! (%.format "Export " (%.text name)))))]
+      (in directive.no_requirements)))
+
+  (syntax: .public (export: [exports (<>.many .any)])
+    (let [! meta.monad]
+      (|> exports
+          (monad.each ! macro.expansion)
+          (# ! each (|>> list#conjoint
+                         (monad.each ! ..definition)))
+          (# ! conjoint)
+          (# ! each (list#each (function (_ [name term])
+                                 (` ( (~ (code.text name)) (~ term))))))))))
diff --git a/stdlib/source/library/lux/ffi/export.jvm.lux b/stdlib/source/library/lux/ffi/export.jvm.lux
new file mode 100644
index 000000000..7473ae233
--- /dev/null
+++ b/stdlib/source/library/lux/ffi/export.jvm.lux
@@ -0,0 +1,106 @@
+(.using
+ [library
+  [lux {"-" function}
+   [control
+    ["<>" parser
+     ["<[0]>" code {"+" Parser}]]]
+   [data
+    [collection
+     ["[0]" list ("[1]#[0]" monad)]]]
+   [macro
+    [syntax {"+" syntax:}]
+    ["[0]" code]]]]
+ ["[0]" //])
+
+(type: (API of)
+  (Record
+   [#interface of
+    #type Code
+    #term Code]))
+
+(def: (api of)
+  (All (_ of) (-> (Parser of) (Parser (API of))))
+  (.form
+   ($_ <>.and
+       of
+       .any
+       .any
+       )))
+
+(type: Constant
+  Text)
+
+(def: constant
+  (Parser Constant)
+  .local_symbol)
+
+(type: Function
+  (Record
+   [#variables (List Text)
+    #name Text
+    #requirements (List [Text Code])]))
+
+(def: function
+  (Parser Function)
+  (.form
+   ($_ <>.and
+       (<>.else (list) (.tuple (<>.some .local_symbol)))
+       .local_symbol
+       (.tuple (<>.some ($_ <>.and
+                                  .local_symbol
+                                  .any
+                                  )))
+       )))
+
+(type: Export
+  (Variant
+   {#Constant (API Constant)}
+   {#Function (API Function)}))
+
+(def: export
+  (Parser Export)
+  ($_ <>.or
+      (..api ..constant)
+      (..api ..function)
+      ))
+
+(syntax: .public (export: [api .local_symbol
+                           exports (<>.many ..export)])
+  (let [initialization (: (List (API Constant))
+                          (list.all (.function (_ it)
+                                      (case it
+                                        {#Constant it}
+                                        {.#Some it}
+                                        
+                                        _
+                                        {.#None}))
+                                    exports))]
+    (in (list (` (//.class: "final" (~ (code.local_symbol api))
+                   (~+ (list#each (.function (_ it)
+                                    (case it
+                                      {#Constant [name type term]}
+                                      (` ("public" "final" "static" (~ (code.local_symbol name)) (~ type)))
+                                      
+                                      {#Function [[variables name requirements] type term]}
+                                      (` ("public" "strict" "static"
+                                          [(~+ (list#each code.local_symbol variables))]
+                                          ((~ (code.local_symbol name))
+                                           [(~+ (|> requirements
+                                                    (list#each (.function (_ [name type])
+                                                                 (list (code.local_symbol name)
+                                                                       type)))
+                                                    list#conjoint))])
+                                          (~ type)
+                                          (~ term)))))
+                                  exports))
+                   ... Useless constructor
+                   ("private" [] ((~' new) (~' self) []) [] [])
+                   ("public" "strict" "static" [] ((~' ) [])
+                    (~' void)
+                    [(~+ (list#each (.function (_ [name type term])
+                                      (` ("jvm member put static"
+                                          (~ (code.text api))
+                                          (~ (code.text name))
+                                          ("jvm object cast" (~ term)))))
+                                    initialization))])
+                   ))))))
diff --git a/stdlib/source/library/lux/ffi/export.lua.lux b/stdlib/source/library/lux/ffi/export.lua.lux
new file mode 100644
index 000000000..1c53e9153
--- /dev/null
+++ b/stdlib/source/library/lux/ffi/export.lua.lux
@@ -0,0 +1,112 @@
+(.using
+ [library
+  [lux "*"
+   [extension {"+" directive:}]
+   ["[0]" meta]
+   ["[0]" static]
+   [abstract
+    ["[0]" monad {"+" do}]]
+   [control
+    ["<>" parser
+     ["<[0]>" code]]]
+   [data
+    [text
+     ["%" format]]
+    [collection
+     ["[0]" list ("[1]#[0]" monad mix)]
+     ["[0]" set]]]
+   ["[0]" macro
+    [syntax {"+" syntax:}]
+    ["[0]" code]]
+   [math
+    ["[0]" random]]
+   [target
+    ["/" lua]]
+   [tool
+    [compiler
+     ["[0]" phase]
+     [meta
+      [cache
+       ["[0]" dependency "_"
+        ["[1]" artifact]]]]
+     [language
+      [lux
+       ["[0]" generation]
+       ["[0]" directive]
+       [analysis
+        ["[0]" type]]]]]]]])
+
+(def: definition
+  (-> Code (Meta [Text Code]))
+  (|>> (list)
+       (.result (<| .form
+                          (<>.after (.text! "lux def"))
+                          (<>.before .any)
+                          ($_ <>.and
+                              .local_symbol
+                              .any)))
+       meta.lifted))
+
+... [15.2 – Privacy](https://www.lua.org/pil/15.2.html)
+... [15.3 – Packages and Files](https://www.lua.org/pil/15.3.html)
+... [15.4 – Using the Global Table](https://www.lua.org/pil/15.4.html)
+
+(with_expansions [ (static.random (|>> %.nat (%.format "lua export ") code.text)
+                                             random.nat)]
+  (directive: ( self phase archive [name .text
+                                               term .any])
+    (do [! phase.monad]
+      [next directive.analysis
+       [_ term] (<| directive.lifted_analysis
+                    type.inferring
+                    (next archive term))
+
+       next directive.synthesis
+       term (directive.lifted_synthesis
+             (next archive term))
+
+       dependencies (directive.lifted_generation
+                     (dependency.dependencies archive term))
+
+       next directive.generation
+       [interim_artifacts term] (directive.lifted_generation
+                                 (generation.with_interim_artifacts archive
+                                   (next archive term)))
+
+       _ (directive.lifted_generation
+          (do !
+            [@self (generation.learn_custom name (list#mix set.has dependencies interim_artifacts))
+             .let [$exports (/.var "_REQUIREDNAME")
+                   $global (/.var "_G")
+                   exporting? (/.not (/.= /.nil $exports))
+                   no_exports? (/.= /.nil (/.item $exports $global))
+                   initialize_exports! (/.set (list (/.item $exports $global)) (/.table (list)))
+                   export_definition! (/.set (|> $global
+                                                 (/.item $exports)
+                                                 (/.item (/.string name))
+                                                 (list))
+                                             (/.var name))
+                   export! (/.when exporting?
+                                   ($_ /.then
+                                       (/.when no_exports?
+                                               initialize_exports!)
+                                       export_definition!
+                                       ))]
+             _ (generation.execute! ($_ /.then
+                                        (/.set (list (/.var name)) term)
+                                        export!))
+             _ (generation.save! @self {.#None} ($_ /.then
+                                                    (/.local/1 (/.var name) term)
+                                                    export!))]
+            (generation.log! (%.format "Export " (%.text name)))))]
+      (in directive.no_requirements)))
+
+  (syntax: .public (export: [exports (<>.many .any)])
+    (let [! meta.monad]
+      (|> exports
+          (monad.each ! macro.expansion)
+          (# ! each (|>> list#conjoint
+                         (monad.each ! ..definition)))
+          (# ! conjoint)
+          (# ! each (list#each (function (_ [name term])
+                                 (` ( (~ (code.text name)) (~ term))))))))))
diff --git a/stdlib/source/library/lux/ffi/export.py.lux b/stdlib/source/library/lux/ffi/export.py.lux
new file mode 100644
index 000000000..4d820443e
--- /dev/null
+++ b/stdlib/source/library/lux/ffi/export.py.lux
@@ -0,0 +1,89 @@
+(.using
+ [library
+  [lux "*"
+   [extension {"+" directive:}]
+   ["[0]" meta]
+   ["[0]" static]
+   [abstract
+    ["[0]" monad {"+" do}]]
+   [control
+    ["<>" parser
+     ["<[0]>" code]]]
+   [data
+    [text
+     ["%" format]]
+    [collection
+     ["[0]" list ("[1]#[0]" monad mix)]
+     ["[0]" set]]]
+   ["[0]" macro
+    [syntax {"+" syntax:}]
+    ["[0]" code]]
+   [math
+    ["[0]" random]]
+   [target
+    ["/" python]]
+   [tool
+    [compiler
+     ["[0]" phase]
+     [meta
+      [cache
+       ["[0]" dependency "_"
+        ["[1]" artifact]]]]
+     [language
+      [lux
+       ["[0]" generation]
+       ["[0]" directive]
+       [analysis
+        ["[0]" type]]]]]]]])
+
+(def: definition
+  (-> Code (Meta [Text Code]))
+  (|>> (list)
+       (.result (<| .form
+                          (<>.after (.text! "lux def"))
+                          (<>.before .any)
+                          ($_ <>.and
+                              .local_symbol
+                              .any)))
+       meta.lifted))
+
+(with_expansions [ (static.random (|>> %.nat (%.format "python export ") code.text)
+                                             random.nat)]
+  (directive: ( self phase archive [name .text
+                                               term .any])
+    (do [! phase.monad]
+      [next directive.analysis
+       [_ term] (<| directive.lifted_analysis
+                    type.inferring
+                    (next archive term))
+
+       next directive.synthesis
+       term (directive.lifted_synthesis
+             (next archive term))
+
+       dependencies (directive.lifted_generation
+                     (dependency.dependencies archive term))
+
+       next directive.generation
+       [interim_artifacts term] (directive.lifted_generation
+                                 (generation.with_interim_artifacts archive
+                                   (next archive term)))
+
+       _ (directive.lifted_generation
+          (do !
+            [@self (generation.learn_custom name (list#mix set.has dependencies interim_artifacts))
+             .let [code (/.set (list (/.item (/.string name) /.globals/0)) term)]
+             _ (generation.execute! code)
+             _ (generation.save! @self {.#None} code)]
+            (generation.log! (%.format "Export " (%.text name)))))]
+      (in directive.no_requirements)))
+
+  (syntax: .public (export: [exports (<>.many .any)])
+    (let [! meta.monad]
+      (|> exports
+          (monad.each ! macro.expansion)
+          (# ! each (|>> list#conjoint
+                         (monad.each ! ..definition)))
+          (# ! conjoint)
+          (# ! each (list#each (function (_ [name term])
+                                 (` ( (~ (code.text name)) (~ term))))))))))
diff --git a/stdlib/source/library/lux/ffi/export.rb.lux b/stdlib/source/library/lux/ffi/export.rb.lux
new file mode 100644
index 000000000..51aab7008
--- /dev/null
+++ b/stdlib/source/library/lux/ffi/export.rb.lux
@@ -0,0 +1,144 @@
+(.using
+ [library
+  [lux {"-" global}
+   [extension {"+" directive:}]
+   ["[0]" meta]
+   ["[0]" static]
+   ["[0]" type]
+   [abstract
+    ["[0]" monad {"+" do}]]
+   [control
+    ["<>" parser
+     ["<[0]>" code]
+     ["<[0]>" text {"+" Parser}]]]
+   [data
+    [text
+     ["%" format]]
+    [collection
+     ["[0]" list ("[1]#[0]" monad mix)]
+     ["[0]" set]]]
+   ["[0]" macro
+    [syntax {"+" syntax:}]
+    ["[0]" code]]
+   [math
+    ["[0]" random]]
+   [target
+    ["/" ruby]]
+   [tool
+    [compiler
+     ["[0]" phase]
+     [meta
+      [cache
+       ["[0]" dependency "_"
+        ["[1]" artifact]]]]
+     [language
+      [lux
+       ["[0]" generation]
+       ["[0]" directive]
+       ["[0]" analysis "_"
+        ["[1]" type]]]]]]]])
+
+(def: upper! (.one_of! "ABCDEFGHIJKLMNOPQRSTUVWXYZ"))
+(def: lower! (.one_of! "abcdefghijklmnopqrstuvwxyz"))
+(def: decimal! (.one_of! "0123456789"))
+(def: sigil! (.one_of! "_"))
+
+(def: tail!
+  ($_ <>.either
+      ..upper!
+      ..lower!
+      ..decimal!
+      ..sigil!
+      ))
+
+(template [ ]
+  [(def: 
+     (Parser Text)
+     (<| .slice
+         (.and! )
+         (.some! ..tail!)))]
+
+  [method ..lower!]
+  [global (.one_of! "$")]
+  [constant ..upper!]
+  )
+
+(type: Name
+  (Variant
+   {#Method Text}
+   {#Global Text}))
+
+(def: name
+  (Parser Name)
+  (<>.or ..method
+         (<>.either ..global
+                    ..constant)))
+
+(def: definition
+  (-> Code (Meta [Name Code]))
+  (|>> (list)
+       (.result (<| .form
+                          (<>.after (.text! "lux def"))
+                          (<>.before .any)
+                          ($_ <>.and
+                              (.then ..name .local_symbol)
+                              .any)))
+       meta.lifted))
+
+(with_expansions [ (static.random (|>> %.nat (%.format "ruby export ") code.text)
+                                             random.nat)]
+  (directive: ( self phase archive [global? .bit
+                                               name .text
+                                               term .any])
+    (do [! phase.monad]
+      [next directive.analysis
+       [type term] (<| directive.lifted_analysis
+                       analysis.inferring
+                       (next archive term))
+
+       next directive.synthesis
+       term (directive.lifted_synthesis
+             (next archive term))
+
+       dependencies (directive.lifted_generation
+                     (dependency.dependencies archive term))
+
+       next directive.generation
+       [interim_artifacts term] (directive.lifted_generation
+                                 (generation.with_interim_artifacts archive
+                                   (next archive term)))
+
+       _ (directive.lifted_generation
+          (do !
+            [@self (generation.learn_custom name (list#mix set.has dependencies interim_artifacts))
+             .let [[:input:/* :output:] (type.flat_function type)
+                   code (if global?
+                          (/.set (list (/.manual name)) term)
+                          (case :input:/*
+                            {.#End}
+                            (/.function (/.manual name) (list)
+                              (/.return term))
+
+                            _
+                            (/.statement (/.apply/* (list (/.string name) term) {.#None}
+                                                    (/.manual "define_method")))))]
+             _ (generation.execute! code)
+             _ (generation.save! @self {.#None} code)]
+            (generation.log! (%.format "Export " (%.text name)))))]
+      (in directive.no_requirements)))
+
+  (syntax: .public (export: [exports (<>.many .any)])
+    (let [! meta.monad]
+      (|> exports
+          (monad.each ! macro.expansion)
+          (# ! each (|>> list#conjoint
+                         (monad.each ! ..definition)))
+          (# ! conjoint)
+          (# ! each (list#each (function (_ [name term])
+                                 (` ( (~+ (case name
+                                                       {#Method name}
+                                                       (list (code.bit #0) (code.text name))
+                                                       
+                                                       {#Global name}
+                                                       (list (code.bit #1) (code.text name))))
+                                                 (~ term))))))))))
diff --git a/stdlib/source/library/lux/static.lux b/stdlib/source/library/lux/static.lux
index 6de030bee..e8d213dd8 100644
--- a/stdlib/source/library/lux/static.lux
+++ b/stdlib/source/library/lux/static.lux
@@ -1,6 +1,6 @@
 (.using
  [library
-  [lux {"-" nat int rev}
+  [lux {"-" nat int rev if cond}
    ["[0]" meta]
    [abstract
     [monad {"+" do}]]
@@ -9,7 +9,7 @@
      ["<[0]>" code]]]
    [data
     [collection
-     ["[0]" list ("[1]#[0]" functor)]]]
+     ["[0]" list ("[1]#[0]" functor mix)]]]
    [macro
     [syntax {"+" syntax:}]
     ["[0]" code]]
@@ -99,3 +99,21 @@
        .let [[_ result] (random.result (random.pcg_32 [..pcg_32_magic_inc seed])
                                        random)]]
       (in (list#each format result)))))
+
+(syntax: .public (if [test .any
+                      then .any
+                      else .any])
+  (do meta.monad
+    [test (meta.eval .Bit test)]
+    (in (list (.if (:as .Bit test)
+                then
+                else)))))
+
+(syntax: .public (cond [test,then/* (<>.some (<>.and .any .any))
+                        else .any])
+  (in (list (list#mix (function (_ [test then] else)
+                        (` (..if (~ test)
+                             (~ then)
+                             (~ else))))
+                      else
+                      (list.reversed test,then/*)))))
diff --git a/stdlib/source/library/lux/tool/compiler/language/lux/phase/extension/directive/lux.lux b/stdlib/source/library/lux/tool/compiler/language/lux/phase/extension/directive/lux.lux
index 241b28a2b..889d400b0 100644
--- a/stdlib/source/library/lux/tool/compiler/language/lux/phase/extension/directive/lux.lux
+++ b/stdlib/source/library/lux/tool/compiler/language/lux/phase/extension/directive/lux.lux
@@ -72,10 +72,10 @@
       {try.#Failure error}
       (phase.except ///.invalid_syntax [extension_name %.code inputs]))))
 
-(def: (context [module_id artifact_id])
+(def: (context [@module @artifact])
   (-> unit.ID unit.ID)
   ... TODO: Find a better way that doesn't rely on clever tricks.
-  [module_id (n.- (++ artifact_id) 0)])
+  [@module (n.- (++ @artifact) 0)])
 
 ... TODO: Inline "evaluate!'" into "evaluate!" ASAP
 (def: (evaluate!' archive generate code//type codeS)
@@ -90,8 +90,8 @@
      [module /////generation.module
       id /////generation.next
       codeG (generate archive codeS)
-      module_id (/////generation.module_id module archive)
-      codeV (/////generation.evaluate! (..context [module_id id]) [{.#None} codeG])]
+      @module (/////generation.module_id module archive)
+      codeV (/////generation.evaluate! (..context [@module id]) [{.#None} codeG])]
      (in [code//type codeG codeV]))))
 
 (def: .public (evaluate! archive type codeC)
@@ -133,9 +133,9 @@
 
                            _
                            {.#None})]
-      module_id (phase.lifted (archive.id module archive))
+      @module (phase.lifted (archive.id module archive))
       @self (/////generation.learn [name @abstraction] false (list#mix set.has dependencies interim_artifacts))
-      [target_name value directive] (/////generation.define! [module_id @self] {.#None} [(maybe#each product.right @abstraction) codeG])
+      [target_name value directive] (/////generation.define! [@module @self] {.#None} [(maybe#each product.right @abstraction) codeG])
       _ (/////generation.save! @self {.#None} directive)]
      (in [code//type codeG value]))))
 
@@ -186,9 +186,9 @@
           [dependencies (cache/artifact.dependencies archive codeS)
            [interim_artifacts codeG] (/////generation.with_interim_artifacts archive
                                        (generate archive codeS))
-           module_id (phase.lifted (archive.id current_module archive))
+           @module (phase.lifted (archive.id current_module archive))
            @self ( extension (list#mix set.has dependencies interim_artifacts))
-           [target_name value directive] (/////generation.define! [module_id @self] {.#None} [{.#None} codeG])
+           [target_name value directive] (/////generation.define! [@module @self] {.#None} [{.#None} codeG])
            _ (/////generation.save! @self {.#None} directive)]
           (in [codeG value])))))
 
@@ -499,7 +499,7 @@
     (/////directive.lifted_synthesis
      (synthesize archive programA))))
 
-(def: (define_program archive module_id generate program programS)
+(def: (define_program archive @module generate program programS)
   (All (_ anchor expression directive output)
     (-> Archive
         module.ID
@@ -512,7 +512,7 @@
      [interim_artifacts programG] (/////generation.with_interim_artifacts archive
                                     (generate archive programS))
      @self (/////generation.learn [/////program.name {.#None}] true (list#mix set.has dependencies interim_artifacts))]
-    (/////generation.save! @self {.#None} (program [module_id @self] programG))))
+    (/////generation.save! @self {.#None} (program [@module @self] programG))))
 
 (def: (def::program program)
   (All (_ anchor expression directive)
@@ -528,9 +528,9 @@
          programS (prepare_program archive analyse synthesize programC)
          current_module (/////directive.lifted_analysis
                          (///.lifted meta.current_module_name))
-         module_id (phase.lifted (archive.id current_module archive))
+         @module (phase.lifted (archive.id current_module archive))
          _ (/////directive.lifted_generation
-            (define_program archive module_id generate program programS))]
+            (define_program archive @module generate program programS))]
         (in /////directive.no_requirements))
 
       _
diff --git a/stdlib/source/library/lux/tool/compiler/language/lux/phase/extension/generation/python/host.lux b/stdlib/source/library/lux/tool/compiler/language/lux/phase/extension/generation/python/host.lux
index dff13d37f..fa18710f9 100644
--- a/stdlib/source/library/lux/tool/compiler/language/lux/phase/extension/generation/python/host.lux
+++ b/stdlib/source/library/lux/tool/compiler/language/lux/phase/extension/generation/python/host.lux
@@ -1,34 +1,36 @@
 (.using
-  [library
-   [lux "*"
-    [abstract
-     ["[0]" monad {"+" do}]]
-    [control
-     ["[0]" function]
-     ["<>" parser
-      ["" synthesis {"+" Parser}]]]
-    [data
-     [collection
-      ["[0]" dictionary]
-      ["[0]" list]]]
-    [target
-     ["_" python {"+" Expression SVar}]]]]
-  ["[0]" // "_"
-   ["[1][0]" common {"+" custom}]
-   ["//[1]" /// "_"
-    ["/" bundle]
+ [library
+  [lux "*"
+   [abstract
+    ["[0]" monad {"+" do}]]
+   [control
+    ["[0]" function]
+    ["<>" parser
+     ["" synthesis {"+" Parser}]]]
+   [data
+    ["[0]" text
+     ["%" format]]
+    [collection
+     ["[0]" dictionary]
+     ["[0]" list]]]
+   [target
+    ["_" python {"+" Expression SVar}]]]]
+ ["[0]" // "_"
+  ["[1][0]" common {"+" custom}]
+  ["//[1]" /// "_"
+   ["/" bundle]
+   ["/[1]" // "_"
+    ["[0]" extension]
+    [generation
+     [extension {"+" Nullary Unary Binary Trinary
+                 nullary unary binary trinary}]
+     ["//" python "_"
+      ["[1][0]" runtime {"+" Operation Phase Handler Bundle
+                         with_vars}]]]
     ["/[1]" // "_"
-     ["[0]" extension]
-     [generation
-      [extension {"+" Nullary Unary Binary Trinary
-                  nullary unary binary trinary}]
-      ["//" python "_"
-       ["[1][0]" runtime {"+" Operation Phase Handler Bundle
-                          with_vars}]]]
-     ["/[1]" // "_"
-      ["[0]" generation]
-      ["//[1]" /// "_"
-       ["[1][0]" phase]]]]]])
+     ["[0]" generation]
+     ["//[1]" /// "_"
+      ["[1][0]" phase]]]]]])
 
 (def: (array::new size)
   (Unary (Expression Any))
diff --git a/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/js/case.lux b/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/js/case.lux
index b2d828de3..4a5ee59f0 100644
--- a/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/js/case.lux
+++ b/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/js/case.lux
@@ -1,36 +1,38 @@
 (.using
-  [library
-   [lux {"-" case exec let if}
-    [abstract
-     ["[0]" monad {"+" do}]]
-    [control
-     ["[0]" maybe]]
-    [data
-     ["[0]" text]
-     [collection
-      ["[0]" list ("[1]#[0]" functor mix)]]]
-    [math
-     [number
-      ["n" nat]]]
-    [target
-     ["_" js {"+" Expression Computation Var Statement}]]]]
-  ["[0]" // "_"
-   ["[1][0]" runtime {"+" Operation Phase Phase! Generator Generator!}]
+ [library
+  [lux {"-" case exec let if}
+   [abstract
+    ["[0]" monad {"+" do}]]
+   [control
+    ["[0]" maybe]]
+   [data
+    ["[0]" text]
+    [collection
+     ["[0]" list ("[1]#[0]" functor mix)]]]
+   [math
+    [number
+     ["n" nat]]]
+   [target
+    ["_" js {"+" Expression Computation Var Statement}]]]]
+ ["[0]" // "_"
+  ["[1][0]" runtime {"+" Operation Phase Phase! Generator Generator!}]
+  ["[1][0]" reference]
+  ["[1][0]" primitive]
+  ["/[1]" // "_"
    ["[1][0]" reference]
-   ["[1][0]" primitive]
    ["/[1]" // "_"
-    ["[1][0]" reference]
+    ["[1][0]" synthesis "_"
+     ["[1]/[0]" case]]
     ["/[1]" // "_"
-     ["[1][0]" synthesis "_"
-      ["[1]/[0]" case]]
-     ["/[1]" // "_"
-      ["[1][0]" synthesis {"+" Member Synthesis Path}]
-      ["//[1]" /// "_"
-       [reference
-        [variable {"+" Register}]]
-       ["[1][0]" phase ("[1]#[0]" monad)]
-       [meta
-        [archive {"+" Archive}]]]]]]])
+     ["[1][0]" synthesis {"+" Synthesis Path}
+      [access
+       ["[0]" member {"+" Member}]]]
+     ["//[1]" /// "_"
+      [reference
+       [variable {"+" Register}]]
+      ["[1][0]" phase ("[1]#[0]" monad)]
+      [meta
+       [archive {"+" Archive}]]]]]]])
 
 (def: .public register
   (-> Register Var)
@@ -95,12 +97,9 @@
   (do ///////phase.monad
     [valueO (expression archive valueS)]
     (in (list#mix (function (_ side source)
-                    (.let [method (.case side
-                                    (^template [ ]
-                                      [{ lefts}
-                                       ( (_.i32 (.int lefts)))])
-                                    ([.#Left  //runtime.tuple//left]
-                                     [.#Right //runtime.tuple//right]))]
+                    (.let [method (.if (value@ member.#right? side)
+                                    (//runtime.tuple//right (_.i32 (.int (value@ member.#lefts side))))
+                                    (//runtime.tuple//left (_.i32 (.int (value@ member.#lefts side)))))]
                       (method source)))
                   valueO
                   (list.reversed pathP)))))
diff --git a/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/js/function.lux b/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/js/function.lux
index 5461530f7..a3fa9317d 100644
--- a/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/js/function.lux
+++ b/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/js/function.lux
@@ -30,7 +30,8 @@
       [archive
        ["[0]" unit]]
       ["[0]" cache "_"
-       ["[1]" artifact]]]]]]])
+       [dependency
+        ["[1]" artifact]]]]]]]])
 
 (def: .public (apply expression archive [functionS argsS+])
   (Generator (Reification Synthesis))
diff --git a/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/js/runtime.lux b/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/js/runtime.lux
index 26f54c884..0f8cbef41 100644
--- a/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/js/runtime.lux
+++ b/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/js/runtime.lux
@@ -24,12 +24,7 @@
     [number {"+" hex}
      ["[0]" i64]]]
    [target
-    ["_" js {"+" Expression Var Computation Statement}]]
-   [tool
-    [compiler
-     [language
-      [lux
-       ["$" version]]]]]]]
+    ["_" js {"+" Expression Var Computation Statement}]]]]
  ["[0]" /// "_"
   ["[1][0]" reference]
   ["//[1]" /// "_"
diff --git a/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/lua/case.lux b/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/lua/case.lux
index dfb7908e7..1ad5f6df6 100644
--- a/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/lua/case.lux
+++ b/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/lua/case.lux
@@ -21,7 +21,9 @@
     ["[1][0]" synthesis "_"
      ["[1]/[0]" case]]
     ["/[1]" // "_"
-     ["[1][0]" synthesis {"+" Member Synthesis Path}]
+     ["[1][0]" synthesis {"+" Synthesis Path}
+      [access
+       ["[0]" member {"+" Member}]]]
      ["[1][0]" generation]
      ["//[1]" /// "_"
       [reference
@@ -81,12 +83,9 @@
   (do ///////phase.monad
     [valueO (expression archive valueS)]
     (in (list#mix (function (_ side source)
-                    (.let [method (.case side
-                                    (^template [ ]
-                                      [{ lefts}
-                                       ( (_.int (.int lefts)))])
-                                    ([.#Left  //runtime.tuple//left]
-                                     [.#Right //runtime.tuple//right]))]
+                    (.let [method (.if (value@ member.#right? side)
+                                    (//runtime.tuple//right (_.int (.int (value@ member.#lefts side))))
+                                    (//runtime.tuple//left (_.int (.int (value@ member.#lefts side)))))]
                       (method source)))
                   valueO
                   (list.reversed pathP)))))
diff --git a/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/ruby/case.lux b/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/ruby/case.lux
index f78fb404b..ec725005a 100644
--- a/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/ruby/case.lux
+++ b/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/ruby/case.lux
@@ -29,7 +29,8 @@
     ["/[1]" // "_"
      ["[1][0]" generation]
      ["[1][0]" synthesis {"+" Synthesis Path}
-      ["[0]" member {"+" Member}]]
+      [access
+       ["[0]" member {"+" Member}]]]
      ["//[1]" /// "_"
       [reference
        ["[1][0]" variable {"+" Register}]]
diff --git a/stdlib/source/library/lux/tool/compiler/language/lux/synthesis/simple.lux b/stdlib/source/library/lux/tool/compiler/language/lux/synthesis/simple.lux
index dbf435a6d..bd9463555 100644
--- a/stdlib/source/library/lux/tool/compiler/language/lux/synthesis/simple.lux
+++ b/stdlib/source/library/lux/tool/compiler/language/lux/synthesis/simple.lux
@@ -12,7 +12,7 @@
      ["%" format]]]
    [math
     [number
-     ["[0]" i64]
+     ["[0]" i64 ("[1]#[0]" equivalence)]
      ["n" nat]
      ["i" int]
      ["f" frac]]]]])
@@ -20,7 +20,7 @@
 (type: .public Simple
   (Variant
    {#Bit Bit}
-   {#I64 (I64 Any)}
+   {#I64 I64}
    {#F64 Frac}
    {#Text Text}))
 
@@ -50,7 +50,7 @@
        [#Text text#= %.text])
 
       [{#I64 reference'} {#I64 sample'}]
-      (i.= (.int reference') (.int sample'))
+      (i64#= reference' sample')
 
       _
       false)))
diff --git a/stdlib/source/library/lux/tool/compiler/phase.lux b/stdlib/source/library/lux/tool/compiler/phase.lux
index a52f8b796..e09552d2c 100644
--- a/stdlib/source/library/lux/tool/compiler/phase.lux
+++ b/stdlib/source/library/lux/tool/compiler/phase.lux
@@ -1,7 +1,6 @@
 (.using
  [library
   [lux "*"
-   ["[0]" debug]
    [abstract
     [functor {"+" Functor}]
     [monad {"+" Monad do}]]
diff --git a/stdlib/source/library/lux/world/file.lux b/stdlib/source/library/lux/world/file.lux
index 2f1d82a31..606cadc3f 100644
--- a/stdlib/source/library/lux/world/file.lux
+++ b/stdlib/source/library/lux/world/file.lux
@@ -306,7 +306,8 @@
                  ["[1]::[0]"
                   ("static" from [Binary] ..Buffer)])
                
-               (ffi.import: FileDescriptor)
+               (ffi.import: FileDescriptor
+                 ["[1]::[0]"])
 
                (ffi.import: Stats
                  ["[1]::[0]"
diff --git a/stdlib/source/program/aedifex/artifact/extension.lux b/stdlib/source/program/aedifex/artifact/extension.lux
index 3f934db23..65d336585 100644
--- a/stdlib/source/program/aedifex/artifact/extension.lux
+++ b/stdlib/source/program/aedifex/artifact/extension.lux
@@ -30,6 +30,7 @@
 
   [lux_library]
   [jvm_library]
+  [js_library]
   [pom]
   [sha-1]
   [md5]
diff --git a/stdlib/source/test/lux/ffi.js.lux b/stdlib/source/test/lux/ffi.js.lux
index a3c827d26..2b3cb7f96 100644
--- a/stdlib/source/test/lux/ffi.js.lux
+++ b/stdlib/source/test/lux/ffi.js.lux
@@ -1,23 +1,26 @@
 (.using
-  [library
-   [lux "*"
-    ["_" test {"+" Test}]
-    [abstract
-     [monad {"+" do}]]
-    [control
-     ["[0]" try]]
-    [data
-     ["[0]" bit ("[1]#[0]" equivalence)]
-     ["[0]" text ("[1]#[0]" equivalence)]]
-    [math
-     ["[0]" random {"+" Random}]
-     [number
-      ["[0]" nat]
-      ["[0]" frac]]]]]
-  [\\library
-   ["[0]" /]])
+ [library
+  [lux "*"
+   ["_" test {"+" Test}]
+   [abstract
+    [monad {"+" do}]]
+   [control
+    ["[0]" try]]
+   [data
+    ["[0]" bit ("[1]#[0]" equivalence)]
+    ["[0]" text ("[1]#[0]" equivalence)]]
+   [math
+    ["[0]" random {"+" Random}]
+    [number
+     ["[0]" nat]
+     ["[0]" frac]]]]]
+ [\\library
+  ["[0]" /]]
+ ["$[0]" / "_"
+  ["[1][0]" export]])
 
-(/.import: Uint8Array)
+(/.import: Uint8Array
+  ["[1]::[0]"])
 
 ... On Nashorn
 (/.import: java/lang/String
@@ -138,4 +141,6 @@
                                            (|> (TextDecoder::new [encoding])
                                                (TextDecoder::decode [binary])))
                                          ))))
+
+                $/export.test
                 )))))
diff --git a/stdlib/source/test/lux/ffi.jvm.lux b/stdlib/source/test/lux/ffi.jvm.lux
index 9eb52d393..2a988f398 100644
--- a/stdlib/source/test/lux/ffi.jvm.lux
+++ b/stdlib/source/test/lux/ffi.jvm.lux
@@ -35,7 +35,9 @@
     ["[0]" jvm "_"
      ["[1]" type ("[1]#[0]" equivalence)]]]]]
  [\\library
-  ["[0]" /]])
+  ["[0]" /]]
+ ["$[0]" / "_"
+  ["[1][0]" export]])
 
 (/.import: java/lang/Boolean)
 (/.import: java/lang/Long)
@@ -654,166 +656,6 @@
                                    false)))))
         )))
 
-(def: expected_boolean (/.as_boolean (static.random_bit)))
-(def: expected_byte (/.as_byte (static.random_int)))
-(def: expected_short (/.as_short (static.random_int)))
-(def: expected_int (/.as_int (static.random_int)))
-(def: expected_long (/.as_long (static.random_int)))
-(def: expected_char (/.as_char (static.random_int)))
-(def: expected_float (/.as_float (static.random_frac)))
-(def: expected_double (/.as_double (static.random_frac)))
-(def: expected_string (/.as_string (static.random code.text (random.ascii/lower 2))))
-
-(`` (`` (/.export: Primitives
-          ... Constants
-          (actual_boolean boolean ..expected_boolean)
-          (actual_byte byte ..expected_byte)
-          (actual_short short ..expected_short)
-          (actual_int int ..expected_int)
-          (actual_long long ..expected_long)
-          (actual_char char ..expected_char)
-          (actual_float float ..expected_float)
-          (actual_double double ..expected_double)
-
-          ... Methods
-          (~~ (template [ <+>]
-                [(((~~ (template.symbol [ "_method"]))
-                   [left 
-                    right ])
-                  
-                  ((~~ (template.symbol [/._] ["as_" ]))
-                   (<+> ((~~ (template.symbol [/._] ["of_" ])) left)
-                        ((~~ (template.symbol [/._] ["of_" ])) right))))]
-
-                [boolean and]
-                [byte i.+]
-                [short i.+]
-                [int i.+]
-                [long i.+]
-                [char i.+]
-                [float f.+]
-                [double f.+]
-                ))
-          )))
-
-(`` (`` (/.import: Primitives
-          ["[1]::[0]"
-           ("static" actual_boolean boolean)
-           ("static" actual_byte byte)
-           ("static" actual_short short)
-           ("static" actual_int int)
-           ("static" actual_long long)
-           ("static" actual_char char)
-           ("static" actual_float float)
-           ("static" actual_double double)
-
-           (~~ (template []
-                 [("static" (~~ (template.symbol [ "_method"])) [ ] )]
-
-                 [boolean]
-                 [byte]
-                 [short]
-                 [int]
-                 [long]
-                 [char]
-                 [float]
-                 [double]
-                 ))
-           ])))
-
-(/.export: Objects
-  (actual_string java/lang/String ..expected_string)
-
-  ((string_method [left java/lang/String right java/lang/String])
-   java/lang/String
-   (/.as_string (%.format (/.of_string left) (/.of_string right))))
-
-  (([a] left [left a right a]) a left)
-  (([a] right [left a right a]) a right))
-
-(/.import: Objects
-  ["[1]::[0]"
-   ("static" actual_string java/lang/String)
-
-   ("static" string_method [java/lang/String java/lang/String] java/lang/String)
-   
-   ("static" [a] left [a a] a)
-   ("static" [a] right [a a] a)])
-
-(def: tiny_int
-  (Random Int)
-  (random#each (|>> (i64.and (hex "F")) .int)
-               random.nat))
-
-(def: tiny_frac
-  (Random Frac)
-  (random#each (|>> (i64.and (hex "FFFF"))
-                    .int
-                    i.frac)
-               random.nat))
-
-(`` (`` (def: test|export
-          Test
-          (do [! random.monad]
-            [(~~ (template [  ]
-                   [(~~ (template.symbol [left_ ])) (# ! each (|>> ) )
-                    (~~ (template.symbol [right_ ])) (# ! each (|>> ) )]
-
-                   [boolean /.as_boolean random.bit]
-                   [byte /.as_byte ..tiny_int]
-                   [short /.as_short ..tiny_int]
-                   [int /.as_int ..tiny_int]
-                   [long /.as_long ..tiny_int]
-                   [char /.as_char ..tiny_int]
-                   [float /.as_float ..tiny_frac]
-                   [double /.as_double ..tiny_frac]
-                   [string /.as_string (random.ascii/lower 1)]
-                   ))]
-            ($_ _.and
-                (_.cover [/.export:]
-                         (and (bit#= (/.of_boolean ..expected_boolean) (/.of_boolean (Primitives::actual_boolean)))
-                              (i#= (/.of_byte ..expected_byte) (/.of_byte (Primitives::actual_byte)))
-                              (i#= (/.of_short ..expected_short) (/.of_short (Primitives::actual_short)))
-                              (i#= (/.of_int ..expected_int) (/.of_int (Primitives::actual_int)))
-                              (i#= (/.of_long ..expected_long) (/.of_long (Primitives::actual_long)))
-                              (i#= (/.of_char ..expected_char) (/.of_char (Primitives::actual_char)))
-                              (f#= (/.of_float ..expected_float) (/.of_float (Primitives::actual_float)))
-                              (f#= (/.of_double ..expected_double) (/.of_double (Primitives::actual_double)))
-
-                              (~~ (template [<=> <+> ]
-                                    [(with_expansions [ (template.symbol ["left_" ])
-                                                        (template.symbol ["right_" ])
-                                                        (template.symbol [/._] ["of_" ])
-                                                        (template.symbol ["Primitives::"  "_method"])]
-                                       (<=> (<+> ( ) ( ))
-                                            ( (  ))))]
-
-                                    [bit#= and boolean]
-                                    [i#= i.+ byte]
-                                    [i#= i.+ short]
-                                    [i#= i.+ int]
-                                    [i#= i.+ long]
-                                    [i#= i.+ char]
-                                    [f#= f.+ float]
-                                    [f#= f.+ double]
-                                    ))
-
-                              (text#= (/.of_string ..expected_string) (/.of_string (Objects::actual_string)))
-                              
-                              (text#= (%.format (/.of_string left_string) (/.of_string right_string))
-                                      (/.of_string (Objects::string_method left_string right_string)))
-
-                              (text#= (/.of_string left_string)
-                                      (/.of_string (Objects::left left_string right_string)))
-                              (text#= (/.of_string right_string)
-                                      (/.of_string (Objects::right left_string right_string)))
-                              (i#= (/.of_long left_long)
-                                   (/.of_long (Objects::left left_long right_long)))
-                              (i#= (/.of_long right_long)
-                                   (/.of_long (Objects::right left_long right_long)))
-                              ))
-                )))))
-
 (def: .public test
   (<| (_.covering /._)
       ($_ _.and
@@ -823,5 +665,6 @@
           ..for_interface
           ..for_class
           ..for_exception
-          ..test|export
+
+          $/export.test
           )))
diff --git a/stdlib/source/test/lux/ffi.lua.lux b/stdlib/source/test/lux/ffi.lua.lux
index e4b83e8ad..682e34763 100644
--- a/stdlib/source/test/lux/ffi.lua.lux
+++ b/stdlib/source/test/lux/ffi.lua.lux
@@ -1,15 +1,17 @@
 (.using
-  [library
-   [lux "*"
-    ["_" test {"+" Test}]
-    [abstract
-     [monad {"+" do}]]
-    [control
-     ["[0]" io]]
-    [math
-     ["[0]" random]]]]
-  [\\library
-   ["[0]" /]])
+ [library
+  [lux "*"
+   ["_" test {"+" Test}]
+   [abstract
+    [monad {"+" do}]]
+   [control
+    ["[0]" io]]
+   [math
+    ["[0]" random]]]]
+ [\\library
+  ["[0]" /]]
+ ["$[0]" / "_"
+  ["[1][0]" export]])
 
 (/.import: (os/getenv [/.String] "io" "?" /.String))
 
@@ -56,4 +58,6 @@
                          (case (io.run! (..os/getenv string))
                            {.#Some _} true
                            {.#None} true))
+
+                $/export.test
                 )))))
diff --git a/stdlib/source/test/lux/ffi.py.lux b/stdlib/source/test/lux/ffi.py.lux
index d2eb3f293..efa966c7d 100644
--- a/stdlib/source/test/lux/ffi.py.lux
+++ b/stdlib/source/test/lux/ffi.py.lux
@@ -1,15 +1,17 @@
 (.using
-  [library
-   [lux "*"
-    ["_" test {"+" Test}]
-    [abstract
-     [monad {"+" do}]]
-    [math
-     ["[0]" random]
-     [number
-      ["i" int]]]]]
-  [\\library
-   ["[0]" /]])
+ [library
+  [lux "*"
+   ["_" test {"+" Test}]
+   [abstract
+    [monad {"+" do}]]
+   [math
+    ["[0]" random]
+    [number
+     ["i" int]]]]]
+ [\\library
+  ["[0]" /]]
+ ["$[0]" / "_"
+  ["[1][0]" export]])
 
 (/.import: os
   ["[1]::[0]"
@@ -58,4 +60,6 @@
                 (_.cover [/.import:]
                          (and (i.= (os::R_OK) (os::R_OK))
                               (not (i.= (os::W_OK) (os::R_OK)))))
+
+                $/export.test
                 )))))
diff --git a/stdlib/source/test/lux/ffi.rb.lux b/stdlib/source/test/lux/ffi.rb.lux
index b2bc3f369..b7e488547 100644
--- a/stdlib/source/test/lux/ffi.rb.lux
+++ b/stdlib/source/test/lux/ffi.rb.lux
@@ -1,13 +1,15 @@
 (.using
-  [library
-   [lux "*"
-    ["_" test {"+" Test}]
-    [abstract
-     [monad {"+" do}]]
-    [math
-     ["[0]" random]]]]
-  [\\library
-   ["[0]" /]])
+ [library
+  [lux "*"
+   ["_" test {"+" Test}]
+   [abstract
+    [monad {"+" do}]]
+   [math
+    ["[0]" random]]]]
+ [\\library
+  ["[0]" /]]
+ ["$[0]" / "_"
+  ["[1][0]" export]])
 
 (/.import: File
   ["[1]::[0]"
@@ -49,4 +51,6 @@
                 (_.cover [/.import:]
                          (same? (..File::SEPARATOR)
                                 (..File::SEPARATOR)))
+
+                $/export.test
                 )))))
diff --git a/stdlib/source/test/lux/ffi/export.js.lux b/stdlib/source/test/lux/ffi/export.js.lux
new file mode 100644
index 000000000..67e276b8c
--- /dev/null
+++ b/stdlib/source/test/lux/ffi/export.js.lux
@@ -0,0 +1,33 @@
+(.using
+ [library
+  [lux "*"
+   ["_" test {"+" Test}]
+   ["[0]" static]
+   [math
+    [number
+     ["n" nat]]]]]
+ [\\library
+  ["[0]" /
+   ["/[1]" //]]])
+
+(with_expansions [ (static.random_nat)]
+  (/.export:
+    (def: constant
+      Nat
+      )
+    (def: shift
+      (-> Nat Nat)
+      (|>> (n.+ ))))
+
+  (//.import: (constant Nat))
+  (//.import: (shift (-> Nat Nat)))
+
+  (def: .public test
+    Test
+    (<| (_.covering /._)
+        ($_ _.and
+            (_.cover [/.export:]
+                     (and (n.=  ..constant)
+                          (n.= (n.+  ) (..shift ))))
+            )))
+  )
diff --git a/stdlib/source/test/lux/ffi/export.jvm.lux b/stdlib/source/test/lux/ffi/export.jvm.lux
new file mode 100644
index 000000000..24ef68929
--- /dev/null
+++ b/stdlib/source/test/lux/ffi/export.jvm.lux
@@ -0,0 +1,186 @@
+(.using
+ [library
+  [lux "*"
+   ["_" test {"+" Test}]
+   ["[0]" meta]
+   ["[0]" debug]
+   ["[0]" static]
+   [abstract
+    [monad {"+" do}]]
+   [data
+    ["[0]" bit ("[1]#[0]" equivalence)]
+    ["[0]" text ("[1]#[0]" equivalence)
+     ["%" format]]]
+   [macro
+    ["[0]" code]
+    ["[0]" template]]
+   [math
+    ["[0]" random {"+" Random} ("[1]#[0]" monad)]
+    [number {"+" hex}
+     ["[0]" i64]
+     ["[0]" int ("[1]#[0]" equivalence)]
+     ["[0]" frac ("[1]#[0]" equivalence)]]]]]
+ [\\library
+  ["[0]" /
+   ["/[1]" //]]])
+
+(def: expected_boolean (//.as_boolean (static.random_bit)))
+(def: expected_byte (//.as_byte (static.random_int)))
+(def: expected_short (//.as_short (static.random_int)))
+(def: expected_int (//.as_int (static.random_int)))
+(def: expected_long (//.as_long (static.random_int)))
+(def: expected_char (//.as_char (static.random_int)))
+(def: expected_float (//.as_float (static.random_frac)))
+(def: expected_double (//.as_double (static.random_frac)))
+(def: expected_string (//.as_string (static.random code.text (random.ascii/lower 2))))
+
+(`` (`` (/.export: Primitives
+          ... Constants
+          (actual_boolean boolean ..expected_boolean)
+          (actual_byte byte ..expected_byte)
+          (actual_short short ..expected_short)
+          (actual_int int ..expected_int)
+          (actual_long long ..expected_long)
+          (actual_char char ..expected_char)
+          (actual_float float ..expected_float)
+          (actual_double double ..expected_double)
+
+          ... Methods
+          (~~ (template [ <+>]
+                [(((~~ (template.symbol [ "_method"]))
+                   [left 
+                    right ])
+                  
+                  ((~~ (template.symbol [//._] ["as_" ]))
+                   (<+> ((~~ (template.symbol [//._] ["of_" ])) left)
+                        ((~~ (template.symbol [//._] ["of_" ])) right))))]
+
+                [boolean and]
+                [byte int.+]
+                [short int.+]
+                [int int.+]
+                [long int.+]
+                [char int.+]
+                [float frac.+]
+                [double frac.+]
+                ))
+          )))
+
+(`` (`` (//.import: Primitives
+          ["[1]::[0]"
+           ("static" actual_boolean boolean)
+           ("static" actual_byte byte)
+           ("static" actual_short short)
+           ("static" actual_int int)
+           ("static" actual_long long)
+           ("static" actual_char char)
+           ("static" actual_float float)
+           ("static" actual_double double)
+
+           (~~ (template []
+                 [("static" (~~ (template.symbol [ "_method"])) [ ] )]
+
+                 [boolean]
+                 [byte]
+                 [short]
+                 [int]
+                 [long]
+                 [char]
+                 [float]
+                 [double]
+                 ))
+           ])))
+
+(/.export: Objects
+  (actual_string java/lang/String ..expected_string)
+
+  ((string_method [left java/lang/String right java/lang/String])
+   java/lang/String
+   (//.as_string (%.format (//.of_string left) (//.of_string right))))
+
+  (([a] left [left a right a]) a left)
+  (([a] right [left a right a]) a right))
+
+(//.import: Objects
+  ["[1]::[0]"
+   ("static" actual_string java/lang/String)
+
+   ("static" string_method [java/lang/String java/lang/String] java/lang/String)
+   
+   ("static" [a] left [a a] a)
+   ("static" [a] right [a a] a)])
+
+(def: tiny_int
+  (Random Int)
+  (random#each (|>> (i64.and (hex "F")) .int)
+               random.nat))
+
+(def: tiny_frac
+  (Random Frac)
+  (random#each (|>> (i64.and (hex "FFFF"))
+                    .int
+                    int.frac)
+               random.nat))
+
+(`` (`` (def: .public test
+          Test
+          (<| (_.covering /._)
+              (do [! random.monad]
+                [(~~ (template [  ]
+                       [(~~ (template.symbol [left_ ])) (# ! each (|>> ) )
+                        (~~ (template.symbol [right_ ])) (# ! each (|>> ) )]
+
+                       [boolean //.as_boolean random.bit]
+                       [byte //.as_byte ..tiny_int]
+                       [short //.as_short ..tiny_int]
+                       [int //.as_int ..tiny_int]
+                       [long //.as_long ..tiny_int]
+                       [char //.as_char ..tiny_int]
+                       [float //.as_float ..tiny_frac]
+                       [double //.as_double ..tiny_frac]
+                       [string //.as_string (random.ascii/lower 1)]
+                       ))]
+                ($_ _.and
+                    (_.cover [/.export:]
+                             (and (bit#= (//.of_boolean ..expected_boolean) (//.of_boolean (Primitives::actual_boolean)))
+                                  (int#= (//.of_byte ..expected_byte) (//.of_byte (Primitives::actual_byte)))
+                                  (int#= (//.of_short ..expected_short) (//.of_short (Primitives::actual_short)))
+                                  (int#= (//.of_int ..expected_int) (//.of_int (Primitives::actual_int)))
+                                  (int#= (//.of_long ..expected_long) (//.of_long (Primitives::actual_long)))
+                                  (int#= (//.of_char ..expected_char) (//.of_char (Primitives::actual_char)))
+                                  (frac#= (//.of_float ..expected_float) (//.of_float (Primitives::actual_float)))
+                                  (frac#= (//.of_double ..expected_double) (//.of_double (Primitives::actual_double)))
+
+                                  (~~ (template [<=> <+> ]
+                                        [(with_expansions [ (template.symbol ["left_" ])
+                                                            (template.symbol ["right_" ])
+                                                            (template.symbol [//._] ["of_" ])
+                                                            (template.symbol ["Primitives::"  "_method"])]
+                                           (<=> (<+> ( ) ( ))
+                                                ( (  ))))]
+
+                                        [bit#= and boolean]
+                                        [int#= int.+ byte]
+                                        [int#= int.+ short]
+                                        [int#= int.+ int]
+                                        [int#= int.+ long]
+                                        [int#= int.+ char]
+                                        [frac#= frac.+ float]
+                                        [frac#= frac.+ double]
+                                        ))
+
+                                  (text#= (//.of_string ..expected_string) (//.of_string (Objects::actual_string)))
+                                  
+                                  (text#= (%.format (//.of_string left_string) (//.of_string right_string))
+                                          (//.of_string (Objects::string_method left_string right_string)))
+
+                                  (text#= (//.of_string left_string)
+                                          (//.of_string (Objects::left left_string right_string)))
+                                  (text#= (//.of_string right_string)
+                                          (//.of_string (Objects::right left_string right_string)))
+                                  (int#= (//.of_long left_long)
+                                         (//.of_long (Objects::left left_long right_long)))
+                                  (int#= (//.of_long right_long)
+                                         (//.of_long (Objects::right left_long right_long)))
+                                  ))
+                    ))))))
diff --git a/stdlib/source/test/lux/ffi/export.lua.lux b/stdlib/source/test/lux/ffi/export.lua.lux
new file mode 100644
index 000000000..63cc558ef
--- /dev/null
+++ b/stdlib/source/test/lux/ffi/export.lua.lux
@@ -0,0 +1,33 @@
+(.using
+ [library
+  [lux "*"
+   ["_" test {"+" Test}]
+   ["[0]" static]
+   [math
+    [number
+     ["n" nat]]]]]
+ [\\library
+  ["[0]" /
+   ["/[1]" //]]])
+
+(with_expansions [ (static.random_nat)]
+  (/.export:
+    (def: constant
+      Nat
+      )
+    (def: shift
+      (-> Nat Nat)
+      (|>> (n.+ ))))
+
+  (//.import: (constant Nat))
+  (//.import: (shift (-> Nat Nat)))
+
+  (def: .public test
+    Test
+    (<| (_.covering /._)
+        ($_ _.and
+            (_.cover [/.export:]
+                     (and (n.=  (..constant))
+                          (n.= (n.+  ) ((..shift) ))))
+            )))
+  )
diff --git a/stdlib/source/test/lux/ffi/export.py.lux b/stdlib/source/test/lux/ffi/export.py.lux
new file mode 100644
index 000000000..67e276b8c
--- /dev/null
+++ b/stdlib/source/test/lux/ffi/export.py.lux
@@ -0,0 +1,33 @@
+(.using
+ [library
+  [lux "*"
+   ["_" test {"+" Test}]
+   ["[0]" static]
+   [math
+    [number
+     ["n" nat]]]]]
+ [\\library
+  ["[0]" /
+   ["/[1]" //]]])
+
+(with_expansions [ (static.random_nat)]
+  (/.export:
+    (def: constant
+      Nat
+      )
+    (def: shift
+      (-> Nat Nat)
+      (|>> (n.+ ))))
+
+  (//.import: (constant Nat))
+  (//.import: (shift (-> Nat Nat)))
+
+  (def: .public test
+    Test
+    (<| (_.covering /._)
+        ($_ _.and
+            (_.cover [/.export:]
+                     (and (n.=  ..constant)
+                          (n.= (n.+  ) (..shift ))))
+            )))
+  )
diff --git a/stdlib/source/test/lux/ffi/export.rb.lux b/stdlib/source/test/lux/ffi/export.rb.lux
new file mode 100644
index 000000000..0ceaf7e00
--- /dev/null
+++ b/stdlib/source/test/lux/ffi/export.rb.lux
@@ -0,0 +1,43 @@
+(.using
+ [library
+  [lux "*"
+   ["_" test {"+" Test}]
+   ["[0]" static]
+   [math
+    [number
+     ["n" nat]]]]]
+ [\\library
+  ["[0]" /
+   ["/[1]" //]]])
+
+(with_expansions [ (static.random_nat)]
+  (/.export:
+    (def: nullary
+      Nat
+      )
+    (def: unary
+      (-> Nat Nat)
+      (|>> (n.+ )))
+    (def: CONSTANT
+      Nat
+      )
+    (def: $global
+      (-> Nat Nat)
+      (|>> (n.+ ))))
+
+  (//.import: (nullary [] Nat))
+  (//.import: (unary [Nat] Nat))
+  (//.import: (CONSTANT Nat))
+  (//.import: ($global (-> Nat Nat)))
+
+  (def: .public test
+    Test
+    (<| (_.covering /._)
+        ($_ _.and
+            (_.cover [/.export:]
+                     (and (n.=  (..nullary []))
+                          (n.= (n.+  ) (..unary ))
+                          (n.=  (..CONSTANT))
+                          (n.= (n.+  ) ((..$global) ))))
+            )))
+  )
diff --git a/stdlib/source/unsafe/lux/data/binary.lux b/stdlib/source/unsafe/lux/data/binary.lux
index f5e4d5b4e..cf25b655f 100644
--- a/stdlib/source/unsafe/lux/data/binary.lux
+++ b/stdlib/source/unsafe/lux/data/binary.lux
@@ -31,8 +31,10 @@
         @.jvm (as_is )
 
         @.js
-        (as_is (ffi.import: ArrayBuffer)
-               (ffi.import: Uint8Array)
+        (as_is (ffi.import: ArrayBuffer
+                 ["[1]::[0]"])
+               (ffi.import: Uint8Array
+                 ["[1]::[0]"])
                
                (type: .public Binary
                  Uint8Array))
-- 
cgit v1.2.3