aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/library
diff options
context:
space:
mode:
authorEduardo Julian2022-07-08 19:15:02 -0400
committerEduardo Julian2022-07-08 19:15:02 -0400
commitfc2737b5226eda69c12bc593e83e22ed54e4d3af (patch)
treecc3c8bfd5b96a235ebc37f3b3a17d37533f8ded2 /stdlib/source/library
parent6a052144968df9b441df53f6aa08cbb515ff2654 (diff)
Extracted macro-expansion machinery into its own module.
Diffstat (limited to 'stdlib/source/library')
-rw-r--r--stdlib/source/library/lux/meta/macro.lux133
-rw-r--r--stdlib/source/library/lux/meta/macro/expansion.lux140
-rw-r--r--stdlib/source/library/lux/meta/macro/syntax/definition.lux5
-rw-r--r--stdlib/source/library/lux/meta/type.lux5
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")))