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

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

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

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

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

                ($.definition /.symbol
                  (format "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.")
                  [(symbol prefix)])

                ($.definition /.wrong_syntax_error
                  "A generic error message for macro syntax failures.")

                ($.definition /.with_symbols
                  "Creates new symbols and offers them to the body expression."
                  [(def synchronized
                     (syntax (_ [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."
                ...   [(one_expansion token)])

                ... ($.definition /.log_single_expansion!
                ...   (format "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).")
                ...   [(log_single_expansion!
                ...     (def (foo bar baz)
                ...       (-> Int Int Int)
                ...       (int.+ bar baz)))
                ...    (log_single_expansion! "omit"
                ...                           (def (foo bar baz)
                ...                             (-> Int Int Int)
                ...                             (int.+ bar baz)))])

                ... ($.definition /.log_expansion!
                ...   (format "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).")
                ...   [(log_expansion!
                ...     (def (foo bar baz)
                ...       (-> Int Int Int)
                ...       (int.+ bar baz)))
                ...    (log_expansion! "omit"
                ...                    (def (foo bar baz)
                ...                      (-> Int Int Int)
                ...                      (int.+ bar baz)))])

                ... ($.definition /.log_full_expansion!
                ...   (format "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).")
                ...   [(log_full_expansion!
                ...     (def (foo bar baz)
                ...       (-> Int Int Int)
                ...       (int.+ bar baz)))
                ...    (log_full_expansion! "omit"
                ...                         (def (foo bar baz)
                ...                           (-> Int Int Int)
                ...                           (int.+ bar baz)))])

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