From 1643be20cb10baf3cabcab502f0013b7faebe322 Mon Sep 17 00:00:00 2001 From: Eduardo Julian Date: Sun, 12 Jun 2022 20:05:43 -0400 Subject: Generalized macro-let. --- .gitignore | 5 +++ lux-jvm/source/program.lux | 4 +- lux-lua/source/program.lux | 30 +++++++-------- lux-python/source/program.lux | 6 +-- lux-ruby/source/program.lux | 10 ++--- stdlib/source/library/lux/macro/local.lux | 45 ++++++++++++++++++++-- stdlib/source/library/lux/macro/template.lux | 1 + .../source/library/lux/target/jvm/type/parser.lux | 2 +- .../language/lux/phase/extension/analysis/js.lux | 6 +-- .../language/lux/phase/extension/analysis/lua.lux | 6 +-- .../lux/phase/extension/analysis/python.lux | 6 +-- .../language/lux/phase/extension/analysis/ruby.lux | 6 +-- .../language/lux/phase/generation/jvm/case.lux | 2 +- .../language/lux/phase/generation/jvm/function.lux | 2 +- .../lux/phase/generation/jvm/reference.lux | 2 +- .../compiler/language/lux/phase/generation/lua.lux | 2 +- .../language/lux/phase/generation/lua/runtime.lux | 2 +- .../language/lux/phase/generation/python.lux | 2 +- .../lux/phase/generation/python/runtime.lux | 2 +- stdlib/source/test/lux/macro/local.lux | 37 ++++++++++++++++++ 20 files changed, 127 insertions(+), 51 deletions(-) diff --git a/.gitignore b/.gitignore index 40d60ba10..606ff0d0a 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,7 @@ aedifex.jar /lux-jvm/source/unsafe /lux-jvm/source/program /lux-jvm/source/spec +/lux-jvm/source/parser /lux-js/RELEASE /lux-js/target @@ -32,6 +33,7 @@ aedifex.jar /lux-js/source/unsafe /lux-js/source/program /lux-js/source/spec +/lux-js/source/parser /lux-js/node_based_compiler.js /lux-js/lux.js @@ -41,6 +43,7 @@ aedifex.jar /lux-python/source/unsafe /lux-python/source/program /lux-python/source/spec +/lux-python/source/parser /lux-lua/RELEASE /lux-lua/target @@ -48,6 +51,7 @@ aedifex.jar /lux-lua/source/unsafe /lux-lua/source/program /lux-lua/source/spec +/lux-lua/source/parser /lux-ruby/RELEASE /lux-ruby/target @@ -55,6 +59,7 @@ aedifex.jar /lux-ruby/source/unsafe /lux-ruby/source/program /lux-ruby/source/spec +/lux-ruby/source/parser /stdlib/RELEASE /stdlib/target diff --git a/lux-jvm/source/program.lux b/lux-jvm/source/program.lux index 82e5f400b..a22211aad 100644 --- a/lux-jvm/source/program.lux +++ b/lux-jvm/source/program.lux @@ -42,7 +42,7 @@ [analysis [macro (.only Expander)]] [phase - ["[0]" extension + ["[0]" extension (.only) ["[0]" analysis ["[1]" jvm]] ["[0]" generation @@ -50,7 +50,7 @@ ["[0]" directive ["[1]" jvm]]] [generation - ["/" jvm + ["/" jvm (.only) ["[1][0]" runtime (.only Anchor Definition)] ["[1][0]" host] ["[1][0]" program]]]]]]]]]] diff --git a/lux-lua/source/program.lux b/lux-lua/source/program.lux index ab567ae31..b3af368bb 100644 --- a/lux-lua/source/program.lux +++ b/lux-lua/source/program.lux @@ -24,7 +24,7 @@ ["[0]" list (.open: "[1]#[0]" monad)]]] [macro ["^" pattern] - ["[0]" template] + ["[0]" local] ["[0]" code]] [math [number (.only hex) @@ -33,7 +33,7 @@ ["[0]" world ["[0]" file] ["[1]/[0]" program]] - ["@" target + ["@" target (.only) ["_" lua]] [tool ["[0]" compiler @@ -55,7 +55,7 @@ ["[1]" lua]]] [generation ["[0]" reference] - ["[0]" lua + ["[0]" lua (.only) ["[0]" runtime]]]]]] [default ["[0]" platform (.only Platform)]] @@ -502,19 +502,17 @@ (with_expansions [ (these (with_expansions [$var_args (_.var "...") $str_rel_to_abs (_.var "_utf8_str_rel_to_abs") $decode (_.var "_utf8_decode")] - (template.let [(!int ) - [(_.int (.int (hex )))] - - (!&| ) - [(|> - (_.bit_and (!int )) - (_.bit_or (!int )))] - - (!&|< ) - [(|> - (_.bit_shr (_.int )) - (_.bit_and (!int )) - (_.bit_or (!int )))]] + (local.let [!int (template (_ ) + [(_.int (.int (hex )))]) + !&| (template (_ ) + [(|> + (_.bit_and (!int )) + (_.bit_or (!int )))]) + !&|< (template (_ ) + [(|> + (_.bit_shr (_.int )) + (_.bit_and (!int )) + (_.bit_or (!int )))])] (these (def: rembulan//char (let [$buffer (_.var "buffer") $k (_.var "k") diff --git a/lux-python/source/program.lux b/lux-python/source/program.lux index 64139ca38..2368323f7 100644 --- a/lux-python/source/program.lux +++ b/lux-python/source/program.lux @@ -24,7 +24,7 @@ [collection ["[0]" array (.only Array)] ["[0]" list (.open: "[1]#[0]" functor)]]] - ["[0]" macro + [macro ["^" pattern] ["[0]" template] ["[0]" code]] @@ -35,7 +35,7 @@ ["[0]" world ["[0]" file] ["[1]/[0]" program]] - ["@" target + ["@" target (.only) ["_" python]] [tool ["[0]" compiler @@ -58,7 +58,7 @@ ["[1]" python]]] [generation ["[0]" reference] - ["[0]" python + ["[0]" python (.only) ["[0]" runtime]]]]]] [default ["[0]" platform (.only Platform)]] diff --git a/lux-ruby/source/program.lux b/lux-ruby/source/program.lux index 5e06719fa..128e5d720 100644 --- a/lux-ruby/source/program.lux +++ b/lux-ruby/source/program.lux @@ -14,9 +14,7 @@ ["[0]" io (.only IO io)] ["[0]" function] [concurrency - ["[0]" async (.only Async)]] - ["<>" parser - ["<[0]>" code]]] + ["[0]" async (.only Async)]]] [data ["[0]" text (.open: "[1]#[0]" hash) ["%" format (.only format)] @@ -25,7 +23,7 @@ [collection ["[0]" array (.only Array)] ["[0]" list (.open: "[1]#[0]" functor)]]] - ["[0]" macro + [macro ["^" pattern] ["[0]" template]] [math @@ -36,7 +34,7 @@ ["[0]" world ["[0]" file] ["[1]/[0]" program]] - ["@" target + ["@" target (.only) ["_" ruby]] [tool ["[0]" compiler @@ -59,7 +57,7 @@ ["[1]" ruby]]] [generation ["[0]" reference] - ["[0]" ruby + ["[0]" ruby (.only) ["[0]" runtime]]]]]] [default ["[0]" platform (.only Platform)]] diff --git a/stdlib/source/library/lux/macro/local.lux b/stdlib/source/library/lux/macro/local.lux index a921afee1..5a07b4a48 100644 --- a/stdlib/source/library/lux/macro/local.lux +++ b/stdlib/source/library/lux/macro/local.lux @@ -1,12 +1,14 @@ (.using [library - [lux (.except) + [lux (.except with let) ["[0]" meta] [abstract ["[0]" monad (.only do)]] [control ["[0]" try (.only Try)] - ["[0]" exception (.only exception:)]] + ["[0]" exception (.only exception:)] + ["<>" parser (.only) + ["<[0]>" code]]] [data ["[0]" product] ["[0]" text] @@ -15,6 +17,7 @@ [dictionary ["[0]" plist (.only PList)]]]]]] ["[0]" // (.only) + [syntax (.only syntax)] ["[1][0]" code]]) (exception: .public (unknown_module [module Text]) @@ -102,7 +105,41 @@ [_ (monad.each meta.monad ..push_one macros) seed meta.seed g!pop (//.symbol "pop") - _ (let [g!pop (is Symbol - ["" (//code.format g!pop)])] + _ (.let [g!pop (is Symbol + ["" (//code.format g!pop)])] (..push_one [g!pop (..pop_all (list#each product.left macros) g!pop)]))] (in (` ((~ g!pop)))))) + +(def: .public (with macros body) + (-> (List [Symbol Macro]) Code (Meta (List Code))) + (do [! meta.monad] + [expression? (is (Meta Bit) + (function (_ lux) + {try.#Success [lux (case (the .#expected lux) + {.#None} + false + + {.#Some _} + true)]})) + g!pop (..push macros)] + (.if expression? + (//.with_symbols [g!body] + (in (list (` (.let [(~ g!body) (~ body)] + (exec + (~ g!pop) + (~ g!body))))))) + (in (list body + g!pop))))) + +(def: .public let + (syntax (_ [locals (.tuple (<>.some (<>.and .local .any))) + body .any]) + (do [! meta.monad] + [here_name meta.current_module_name + locals (monad.each ! (function (_ [name value]) + (|> value + (meta.eval .Macro) + (at ! each (|>> (as .Macro) + [[here_name name]])))) + locals)] + (..with locals body)))) diff --git a/stdlib/source/library/lux/macro/template.lux b/stdlib/source/library/lux/macro/template.lux index 439c99a3a..2251051d5 100644 --- a/stdlib/source/library/lux/macro/template.lux +++ b/stdlib/source/library/lux/macro/template.lux @@ -157,6 +157,7 @@ #parameters parameters #template template]))) +... TODO: Get rid of this (and any local definitions it depends on) once the bootstrapping compiler is gone. (def: .public let (syntax (_ [locals (.tuple (<>.some ..local)) body .any]) diff --git a/stdlib/source/library/lux/target/jvm/type/parser.lux b/stdlib/source/library/lux/target/jvm/type/parser.lux index 53bd29aa0..aa64e4334 100644 --- a/stdlib/source/library/lux/target/jvm/type/parser.lux +++ b/stdlib/source/library/lux/target/jvm/type/parser.lux @@ -18,7 +18,7 @@ [category (.only Void Value Return Method Primitive Object Class Array Var Parameter Declaration)] ["[1][0]" signature] ["[1][0]" descriptor] - ["[0]" // (.only) + [// [encoding ["[1][0]" name (.only External)]]]]) diff --git a/stdlib/source/library/lux/tool/compiler/language/lux/phase/extension/analysis/js.lux b/stdlib/source/library/lux/tool/compiler/language/lux/phase/extension/analysis/js.lux index d477f443e..8342ce912 100644 --- a/stdlib/source/library/lux/tool/compiler/language/lux/phase/extension/analysis/js.lux +++ b/stdlib/source/library/lux/tool/compiler/language/lux/phase/extension/analysis/js.lux @@ -5,16 +5,16 @@ [abstract ["[0]" monad (.only do)]] [control - ["<>" parser + ["<>" parser (.only) ["<[0]>" code (.only Parser)]]] [data [collection ["[0]" array] ["[0]" dictionary] ["[0]" list]]] - ["[0]" type + ["[0]" type (.only) ["[0]" check]] - ["@" target + ["@" target (.only) ["_" js]]]] [// ["/" lux (.only custom)] diff --git a/stdlib/source/library/lux/tool/compiler/language/lux/phase/extension/analysis/lua.lux b/stdlib/source/library/lux/tool/compiler/language/lux/phase/extension/analysis/lua.lux index 428ea1068..fa08d5be0 100644 --- a/stdlib/source/library/lux/tool/compiler/language/lux/phase/extension/analysis/lua.lux +++ b/stdlib/source/library/lux/tool/compiler/language/lux/phase/extension/analysis/lua.lux @@ -5,16 +5,16 @@ [abstract ["[0]" monad (.only do)]] [control - ["<>" parser + ["<>" parser (.only) ["<[0]>" code (.only Parser)]]] [data [collection ["[0]" array] ["[0]" dictionary] ["[0]" list]]] - ["[0]" type + ["[0]" type (.only) ["[0]" check]] - ["@" target + ["@" target (.only) ["_" lua]]]] [// ["/" lux (.only custom)] diff --git a/stdlib/source/library/lux/tool/compiler/language/lux/phase/extension/analysis/python.lux b/stdlib/source/library/lux/tool/compiler/language/lux/phase/extension/analysis/python.lux index 3defef9c9..aa2944967 100644 --- a/stdlib/source/library/lux/tool/compiler/language/lux/phase/extension/analysis/python.lux +++ b/stdlib/source/library/lux/tool/compiler/language/lux/phase/extension/analysis/python.lux @@ -5,16 +5,16 @@ [abstract ["[0]" monad (.only do)]] [control - ["<>" parser + ["<>" parser (.only) ["<[0]>" code (.only Parser)]]] [data [collection ["[0]" array] ["[0]" dictionary] ["[0]" list]]] - ["[0]" type + ["[0]" type (.only) ["[0]" check]] - ["@" target + ["@" target (.only) ["_" python]]]] [// ["/" lux (.only custom)] diff --git a/stdlib/source/library/lux/tool/compiler/language/lux/phase/extension/analysis/ruby.lux b/stdlib/source/library/lux/tool/compiler/language/lux/phase/extension/analysis/ruby.lux index 4678fe9e1..01895a3e7 100644 --- a/stdlib/source/library/lux/tool/compiler/language/lux/phase/extension/analysis/ruby.lux +++ b/stdlib/source/library/lux/tool/compiler/language/lux/phase/extension/analysis/ruby.lux @@ -5,16 +5,16 @@ [abstract ["[0]" monad (.only do)]] [control - ["<>" parser + ["<>" parser (.only) ["<[0]>" code (.only Parser)]]] [data [collection ["[0]" array] ["[0]" dictionary] ["[0]" list]]] - ["[0]" type + ["[0]" type (.only) ["[0]" check]] - ["@" target + ["@" target (.only) ["_" ruby]]]] [// ["/" lux (.only custom)] diff --git a/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/jvm/case.lux b/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/jvm/case.lux index e96a88889..3ab3c67f7 100644 --- a/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/jvm/case.lux +++ b/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/jvm/case.lux @@ -35,7 +35,7 @@ [access ["[0]" member (.only Member)]]] [/// - ["[0]" phase ("operation#[0]" monad)] + ["[0]" phase (.open: "operation#[0]" monad)] [reference [variable (.only Register)]]]]]) diff --git a/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/jvm/function.lux b/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/jvm/function.lux index e9f9b5800..3de519160 100644 --- a/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/jvm/function.lux +++ b/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/jvm/function.lux @@ -1,6 +1,6 @@ (.using [library - [lux (.except Type Label) + [lux (.except Type Label with) [abstract ["[0]" monad (.only do)]] [data diff --git a/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/jvm/reference.lux b/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/jvm/reference.lux index 7f6ade8c6..21b5a57b4 100644 --- a/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/jvm/reference.lux +++ b/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/jvm/reference.lux @@ -20,7 +20,7 @@ [// ["[0]" generation] [/// - ["[1]" phase ("operation#[0]" monad)] + ["[1]" phase (.open: "operation#[0]" monad)] [reference ["[0]" variable (.only Register Variable)]] [meta diff --git a/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/lua.lux b/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/lua.lux index e14772296..669e1667b 100644 --- a/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/lua.lux +++ b/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/lua.lux @@ -20,7 +20,7 @@ ["/[1]" // ["[1][0]" reference] ["/[1]" // - ["[1][0]" extension + ["[1][0]" extension (.only) [generation [lua ["[1]/[0]" common]]]] diff --git a/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/lua/runtime.lux b/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/lua/runtime.lux index 503638aeb..8898da66d 100644 --- a/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/lua/runtime.lux +++ b/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/lua/runtime.lux @@ -1,6 +1,6 @@ (.using [library - [lux (.except Label Location) + [lux (.except Label Location left right) ["[0]" meta] [abstract ["[0]" monad (.only do)]] diff --git a/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/python.lux b/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/python.lux index 054e84344..a0c15f71e 100644 --- a/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/python.lux +++ b/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/python.lux @@ -20,7 +20,7 @@ ["/[1]" // ["[1][0]" reference] ["/[1]" // - ["[1][0]" extension + ["[1][0]" extension (.only) [generation [python ["[1]/[0]" common]]]] diff --git a/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/python/runtime.lux b/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/python/runtime.lux index 12d1f65c7..c0101452a 100644 --- a/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/python/runtime.lux +++ b/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/python/runtime.lux @@ -1,6 +1,6 @@ (.using [library - [lux (.except ++) + [lux (.except ++ left right) [abstract ["[0]" monad (.only do)]] [control diff --git a/stdlib/source/test/lux/macro/local.lux b/stdlib/source/test/lux/macro/local.lux index de1073f55..bb03574a1 100644 --- a/stdlib/source/test/lux/macro/local.lux +++ b/stdlib/source/test/lux/macro/local.lux @@ -27,6 +27,12 @@ [\\library ["[0]" /]]) +(/.let [!pow/2 (template (_ ) + [(n.* )])] + (def: pow/2 + (-> Nat Nat) + (|>> !pow/2))) + (def: macro_error (syntax (_ [macro .any]) (function (_ compiler) @@ -90,4 +96,35 @@ (<| ..macro_error (..with ["" "actual"] expected #1) (n.= expected (..actual))))) + (do ! + [scalar random.nat] + (_.coverage [/.let] + (let [can_use_with_statements! + (n.= (all n.* scalar scalar) + (..pow/2 scalar))] + (and can_use_with_statements! + (/.let [pow/3 (template (_ ) + [(all n.* )]) + pow/9 (template (_ ) + [(pow/3 (pow/3 ))])] + (let [can_use_with_expressions! + (n.= (all n.* scalar scalar scalar) + (pow/3 scalar)) + + can_refer! + (n.= (all n.* + scalar scalar scalar + scalar scalar scalar + scalar scalar scalar) + (pow/9 scalar)) + + can_shadow! + (let [pow/3 (function (_ scalar) + (all n.+ scalar scalar scalar))] + (n.= (all n.+ scalar scalar scalar) + (pow/3 scalar)))] + (and can_use_with_expressions! + can_refer! + can_shadow!))) + )))) )))) -- cgit v1.2.3