(.require
 [library
  [lux (.except)
   ["$" documentation]
   [data
    ["[0]" text (.only \n)
     ["%" \\format (.only format)]]]]]
 [\\library
  ["[0]" /]])

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

            ($.definition /.monad)
            ($.definition /.index_cannot_be_repeated)
            ($.definition /.amount_cannot_be_zero)

            ($.definition (/.Procedure monad input output value)
              (format "A computation that takes a sequence of resource access rights as inputs and yields a different sequence as outputs."
                      \n "A procedure yields a result value."
                      \n "A procedure can make use of monadic effects."))

            ($.definition (/.Linear monad value)
              (format "A procedure that is constant with regards to resource access rights."
                      \n "This means no additional resources will be available after the computation is over."
                      \n "This also means no previously available resources will have been consumed."))

            ($.definition (/.Affine monad permissions value)
              "A procedure which expands the number of available resources.")

            ($.definition (/.Relevant monad permissions value)
              "A procedure which reduces the number of available resources.")

            ($.definition /.run!
              ""
              [(run! monad procedure)])

            ($.definition /.lifted
              ""
              [(lifted monad procedure)])

            ($.definition /.Ordered
              "The mode of keys which CANNOT be swapped, and for whom order of release/consumption matters.")

            ($.definition /.Commutative
              "The mode of keys which CAN be swapped, and for whom order of release/consumption DOES NOT matters.")

            ($.definition (/.Key mode key)
              (format "The access right for a resource."
                      \n "Without the key for a resource existing somewhere among the available ambient rights, one cannot use a resource."))

            ($.definition (/.Res key value)
              (format "A resource locked by a key."
                      \n "The 'key' represents the right to access/consume a resource."))

            (,, (with_template [<name>]
                  [($.definition <name>
                     "Makes a value into a resource and adds the key/access-right to it to the ambient keyring for future use.")]

                  [/.ordered]
                  [/.commutative]
                  ))

            ($.definition /.read
              "Access the value of a resource, so long as its key is available."
              [(read monad resource)])

            ($.definition /.exchange
              (format "A function that can exchange the keys for resource, so long as they are commutative."
                      \n "This keys will be placed at the front of the keyring in the order they are specified."
                      \n "The specific keys must be specified based of their index into the current keyring.")
              [(do (monad !)
                 [res|left (commutative ! pre)
                  res|right (commutative ! post)
                  _ ((exchange [1 0]) !)
                  left (read ! res|left)
                  right (read ! res|right)]
                 (in (format left right)))])

            (,, (with_template [<name>]
                  [($.definition <name>
                     "Group/un-group keys in the keyring into/out-of tuples."
                     [(do (monad !)
                        [res|left (commutative ! pre)
                         res|right (commutative ! post)
                         _ ((group 2) !)
                         _ ((un_group 2) !)
                         right (read ! res|right)
                         left (read ! res|left)]
                        (in (format left right)))])]

                  [/.group]
                  [/.un_group]
                  ))
            )))
