... This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
... If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.

(.require
 [library
  [lux (.except)
   ["$" documentation]
   [data
    [text (.only \n)
     ["%" \\injection]]
    [collection
     ["[0]" list (.use "[1]#[0]" monoid)]]]]]
 ["[0]" /
  ["[1][0]" local]
  ["[1][0]" syntax]
  ["[1][0]" template]]
 [\\library
  ["[0]" /]])

(the .public documentation
  (List $.Documentation)
  (list.partial ($.module /._
                          "")

                ... ($.definition /.single_expansion
                ...   (%.message "Given code that requires applying a macro, does it once and returns the result."
                ...           \n "Otherwise, returns the code as-is.")
                ...   ($.example (' (single_expansion syntax))))

                ... ($.definition /.expansion
                ...   (%.message "Given code that requires applying a macro, expands repeatedly until no more direct macro-calls are left."
                ...           \n "Otherwise, returns the code as-is.")
                ...   ($.example (' (expansion syntax))))

                ... ($.definition /.full_expansion
                ...   "Expands all macro-calls everywhere recursively, until only primitive/base code remains."
                ...   ($.example (' (full_expansion syntax))))

                ($.definition /.symbol
                  (%.message "Generates a unique name as a Code node (ready to be used in code templates)."
                             \n "A prefix can be given (or just be empty text) to better identify the code for debugging purposes.")
                  ($.example (' (symbol prefix))))

                ($.definition /.with_symbols
                  "Creates new symbols and offers them to the body expression."
                  ($.example (' (the synchronized
                                  (syntax.macro (_ [lock any
                                                    body any])
                                    (with_symbols [g!lock g!body g!_]
                                      (in (list (` (let [(, g!lock) (, lock)
                                                         (, g!_) ("jvm monitorenter" (, g!lock))
                                                         (, g!body) (, body)
                                                         (, g!_) ("jvm monitorexit" (, g!lock))]
                                                     (, g!body)))))))))))

                ... ($.definition /.one_expansion
                ...   "Works just like expand, except that it ensures that the output is a single Code token."
                ...   ($.example (' (one_expansion token))))

                ... ($.definition /.log_single_expansion!
                ...   (%.message "Performs a macro-expansion and logs the resulting code."
                ...           \n "You can either use the resulting code, or omit them."
                ...           \n "By omitting them, this macro produces nothing (just like the lux.comment macro).")
                ...   ($.example (' (log_single_expansion!
                ...                  (the (foo bar baz)
                ...                    (-> Integer Integer Integer)
                ...                    (integer.+ bar baz)))))
                ...   ($.example (' (log_single_expansion! "omit"
                ...                                        (the (foo bar baz)
                ...                                          (-> Integer Integer Integer)
                ...                                          (integer.+ bar baz))))))

                ... ($.definition /.log_expansion!
                ...   (%.message "Performs a macro-expansion and logs the resulting code."
                ...           \n "You can either use the resulting code, or omit them."
                ...           \n "By omitting them, this macro produces nothing (just like the lux.comment macro).")

                ...   ($.example (' (log_expansion!
                ...                  (the (foo bar baz)
                ...                    (-> Integer Integer Integer)
                ...                    (integer.+ bar baz)))))
                ...   ($.example (' (log_expansion! "omit"
                ...                                 (the (foo bar baz)
                ...                                   (-> Integer Integer Integer)
                ...                                   (integer.+ bar baz))))))

                ... ($.definition /.log_full_expansion!
                ...   (%.message "Performs a macro-expansion and logs the resulting code."
                ...           \n "You can either use the resulting code, or omit them."
                ...           \n "By omitting them, this macro produces nothing (just like the lux.comment macro).")

                ...   ($.example (' (log_full_expansion!
                ...                  (the (foo bar baz)
                ...                    (-> Integer Integer Integer)
                ...                    (integer.+ bar baz)))))
                ...   ($.example (' (log_full_expansion! "omit"
                ...                                      (the (foo bar baz)
                ...                                        (-> Integer Integer Integer)
                ...                                        (integer.+ bar baz))))))

                (all list#composite
                     /local.documentation
                     /syntax.documentation
                     /template.documentation
                     )
                ))
