diff options
author | Eduardo Julian | 2022-07-08 19:15:02 -0400 |
---|---|---|
committer | Eduardo Julian | 2022-07-08 19:15:02 -0400 |
commit | fc2737b5226eda69c12bc593e83e22ed54e4d3af (patch) | |
tree | cc3c8bfd5b96a235ebc37f3b3a17d37533f8ded2 /stdlib/source/library | |
parent | 6a052144968df9b441df53f6aa08cbb515ff2654 (diff) |
Extracted macro-expansion machinery into its own module.
Diffstat (limited to '')
-rw-r--r-- | stdlib/source/library/lux/meta/macro.lux | 133 | ||||
-rw-r--r-- | stdlib/source/library/lux/meta/macro/expansion.lux | 140 | ||||
-rw-r--r-- | stdlib/source/library/lux/meta/macro/syntax/definition.lux | 5 | ||||
-rw-r--r-- | stdlib/source/library/lux/meta/type.lux | 5 |
4 files changed, 152 insertions, 131 deletions
diff --git a/stdlib/source/library/lux/meta/macro.lux b/stdlib/source/library/lux/meta/macro.lux index 464329a25..c8c3a26fb 100644 --- a/stdlib/source/library/lux/meta/macro.lux +++ b/stdlib/source/library/lux/meta/macro.lux @@ -6,89 +6,16 @@ [data ["[0]" text (.use "[1]#[0]" monoid)] [collection - ["[0]" list (.use "[1]#[0]" monoid monad)]]] + ["[0]" list (.use "[1]#[0]" monad)]]] [math [number - ["[0]" nat] - ["[0]" int]]]]] + ["[0]" nat]]]]] + ["[0]" / + ["[1][0]" expansion]] ["[0]" // (.only) ["[0]" code] - ["[0]" location] ["[0]" symbol (.use "[1]#[0]" codec)]]) -(def .public (single_expansion syntax) - (-> Code (Meta (List Code))) - (case syntax - [_ {.#Form {.#Item [[_ {.#Symbol name}] args]}}] - (do //.monad - [?macro (//.macro name)] - (case ?macro - {.#Some macro} - ((as Macro' macro) args) - - {.#None} - (at //.monad in (list syntax)))) - - _ - (at //.monad in (list syntax)))) - -(def .public (expansion syntax) - (-> Code (Meta (List Code))) - (case syntax - [_ {.#Form {.#Item [[_ {.#Symbol name}] args]}}] - (do //.monad - [?macro (//.macro name)] - (case ?macro - {.#Some macro} - (do [! //.monad] - [top_level_expansion ((as Macro' macro) args)] - (|> top_level_expansion - (monad.each //.monad expansion) - (at ! each list#conjoint))) - - {.#None} - (at //.monad in (list syntax)))) - - _ - (at //.monad in (list syntax)))) - -(def .public (full_expansion syntax) - (-> Code (Meta (List Code))) - (case syntax - [_ {.#Form {.#Item [[_ {.#Symbol name}] args]}}] - (do //.monad - [?macro (//.macro name)] - (case ?macro - {.#Some macro} - (do //.monad - [expansion ((as Macro' macro) args) - expansion' (monad.each //.monad full_expansion expansion)] - (in (list#conjoint expansion'))) - - {.#None} - (do //.monad - [parts' (monad.each //.monad full_expansion (list.partial (code.symbol name) args))] - (in (list (code.form (list#conjoint parts'))))))) - - [_ {.#Form {.#Item [harg targs]}}] - (do //.monad - [harg+ (full_expansion harg) - targs+ (monad.each //.monad full_expansion targs)] - (in (list (code.form (list#composite harg+ (list#conjoint (is (List (List Code)) targs+))))))) - - [_ {.#Variant members}] - (do //.monad - [members' (monad.each //.monad full_expansion members)] - (in (list (code.variant (list#conjoint members'))))) - - [_ {.#Tuple members}] - (do //.monad - [members' (monad.each //.monad full_expansion members)] - (in (list (code.tuple (list#conjoint members'))))) - - _ - (at //.monad in (list syntax)))) - (def .public (symbol prefix) (-> Text (Meta Code)) (do //.monad @@ -129,54 +56,6 @@ _ (//.failure (..wrong_syntax_error (.symbol ..with_symbols)))))) -(def .public (one_expansion token) - (-> Code (Meta Code)) - (do //.monad - [token+ (..expansion token)] - (case token+ - (list token') - (in token') - - _ - (//.failure "Macro expanded to more than 1 element.")))) - -(with_template [<macro> <func>] - [(def .public <macro> - (.macro (_ tokens) - (let [[module _] (.symbol .._) - [_ short] (.symbol <macro>) - macro_name [module short]] - (case (is (Maybe [Bit Code]) - (case tokens - (list [_ {.#Text "omit"}] - token) - {.#Some [#1 token]} - - (list token) - {.#Some [#0 token]} - - _ - {.#None})) - {.#Some [omit? token]} - (do //.monad - [location //.location - output (<func> token) - .let [_ ("lux io log" (all text#composite (symbol#encoded macro_name) " " (location.format location))) - _ (list#each (|>> code.format "lux io log") - output) - _ ("lux io log" "")]] - (in (if omit? - (list) - output))) - - {.#None} - (//.failure (..wrong_syntax_error macro_name))))))] - - [log_single_expansion! ..single_expansion] - [log_expansion! ..expansion] - [log_full_expansion! ..full_expansion] - ) - (def .public times (.macro (_ tokens) (case tokens @@ -190,7 +69,7 @@ _ (do [! //.monad] [after (|> before - (monad.each ! ..single_expansion) + (monad.each ! /expansion.single) (at ! each list#conjoint))] (again (-- times) after)))) @@ -201,7 +80,7 @@ (.macro (_ it) (let [! //.monad] (|> it - (monad.each ! ..expansion) + (monad.each ! /expansion.complete) (at ! each list#conjoint))))) (def .public function diff --git a/stdlib/source/library/lux/meta/macro/expansion.lux b/stdlib/source/library/lux/meta/macro/expansion.lux new file mode 100644 index 000000000..781eb141b --- /dev/null +++ b/stdlib/source/library/lux/meta/macro/expansion.lux @@ -0,0 +1,140 @@ +(.require + [library + [lux (.except local symbol function macro) + [abstract + ["[0]" monad (.only do)]] + [data + ["[0]" text (.use "[1]#[0]" monoid)] + [collection + ["[0]" list (.use "[1]#[0]" monoid monad)]]]]] + ["[0]" /// (.only) + ["[0]" code] + ["[0]" location] + ["[0]" symbol (.use "[1]#[0]" codec)]]) + +(def wrong_syntax_error + (-> Symbol Text) + (|>> symbol#encoded + (text.prefix (text#composite "Wrong syntax for " text.\'')) + (text.suffix (text#composite text.\'' ".")))) + +(def .public (single syntax) + (-> Code (Meta (List Code))) + (case syntax + [_ {.#Form {.#Item [[_ {.#Symbol name}] args]}}] + (do ///.monad + [?macro (///.macro name)] + (case ?macro + {.#Some macro} + ((as Macro' macro) args) + + {.#None} + (at ///.monad in (list syntax)))) + + _ + (at ///.monad in (list syntax)))) + +(def .public (complete syntax) + (-> Code (Meta (List Code))) + (case syntax + [_ {.#Form {.#Item [[_ {.#Symbol name}] args]}}] + (do ///.monad + [?macro (///.macro name)] + (case ?macro + {.#Some macro} + (do [! ///.monad] + [top_level_complete ((as Macro' macro) args)] + (|> top_level_complete + (monad.each ///.monad complete) + (at ! each list#conjoint))) + + {.#None} + (at ///.monad in (list syntax)))) + + _ + (at ///.monad in (list syntax)))) + +(def .public (total syntax) + (-> Code (Meta (List Code))) + (case syntax + [_ {.#Form {.#Item [[_ {.#Symbol name}] args]}}] + (do ///.monad + [?macro (///.macro name)] + (case ?macro + {.#Some macro} + (do ///.monad + [complete ((as Macro' macro) args) + complete' (monad.each ///.monad total complete)] + (in (list#conjoint complete'))) + + {.#None} + (do ///.monad + [parts' (monad.each ///.monad total (list.partial (code.symbol name) args))] + (in (list (code.form (list#conjoint parts'))))))) + + [_ {.#Form {.#Item [harg targs]}}] + (do ///.monad + [harg+ (total harg) + targs+ (monad.each ///.monad total targs)] + (in (list (code.form (list#composite harg+ (list#conjoint (is (List (List Code)) targs+))))))) + + [_ {.#Variant members}] + (do ///.monad + [members' (monad.each ///.monad total members)] + (in (list (code.variant (list#conjoint members'))))) + + [_ {.#Tuple members}] + (do ///.monad + [members' (monad.each ///.monad total members)] + (in (list (code.tuple (list#conjoint members'))))) + + _ + (at ///.monad in (list syntax)))) + +(def .public (one token) + (-> Code (Meta Code)) + (do ///.monad + [token+ (..complete token)] + (case token+ + (list token') + (in token') + + _ + (///.failure "Macro expanded to more than 1 element.")))) + +(with_template [<macro> <func>] + [(def .public <macro> + (.macro (_ tokens) + (let [[module _] (.symbol .._) + [_ short] (.symbol <macro>) + macro_name [module short]] + (case (is (Maybe [Bit Code]) + (case tokens + (list [_ {.#Text "omit"}] + token) + {.#Some [#1 token]} + + (list token) + {.#Some [#0 token]} + + _ + {.#None})) + {.#Some [omit? token]} + (do ///.monad + [location ///.location + output (<func> token) + .let [_ ("lux io log" (all text#composite (symbol#encoded macro_name) " " (location.format location))) + _ (list#each (|>> code.format "lux io log") + output) + _ ("lux io log" "")]] + (in (if omit? + (list) + output))) + + {.#None} + (///.failure (..wrong_syntax_error macro_name))))))] + + [log_single! ..single] + [log_complete! ..complete] + [log_total! ..total] + ) diff --git a/stdlib/source/library/lux/meta/macro/syntax/definition.lux b/stdlib/source/library/lux/meta/macro/syntax/definition.lux index 44030c108..445068226 100644 --- a/stdlib/source/library/lux/meta/macro/syntax/definition.lux +++ b/stdlib/source/library/lux/meta/macro/syntax/definition.lux @@ -17,7 +17,8 @@ ["[0]" list]]] ["[0]" meta (.only) ["[0]" location] - ["[0]" macro] + [macro + ["[0]" expansion]] ["[0]" code (.only) ["<[1]>" \\parser (.only Parser)]]]]] ["[0]" // (.only) @@ -67,7 +68,7 @@ (do [! <>.monad] [raw <code>.any me_raw (|> raw - macro.full_expansion + expansion.total (meta.result compiler) <>.lifted)] (<| (<code>.locally me_raw) diff --git a/stdlib/source/library/lux/meta/type.lux b/stdlib/source/library/lux/meta/type.lux index 9af406098..42f9f2961 100644 --- a/stdlib/source/library/lux/meta/type.lux +++ b/stdlib/source/library/lux/meta/type.lux @@ -24,7 +24,8 @@ ["[0]" code (.only) ["<[1]>" \\parser (.only Parser)]] ["[0]" macro (.only) - [syntax (.only syntax)]]]]]) + [syntax (.only syntax)] + ["[0]" expansion]]]]]) (with_template [<name> <tag>] [(def .public (<name> type) @@ -474,7 +475,7 @@ (-> Lux (Parser Typed)) (do <>.monad [it <code>.any - type_check (<>.lifted (meta.result lux (macro.expansion it)))] + type_check (<>.lifted (meta.result lux (expansion.complete it)))] (<| (<code>.locally type_check) <code>.form (<>.after (<code>.this (` "lux type check"))) |