(.using
  [library
   [lux {"-" type macro}
    ["$" documentation {"+" documentation:}]
    [data
     ["[0]" text {"+" \n}
      ["%" format {"+" format}]]]
    [macro
     ["[0]" template]]]]
  [\\library
   ["[0]" /]]
  ["[0]" / "_"
   ["[1][0]" location]
   ["[1][0]" symbol]])

(documentation: /.result'
  (format "Evaluates a computation that depends on Lux's compiler state."
          \n "Also returns a (potentially modified) compiler state.")
  [(result' lux action)])

(documentation: /.result
  "Evaluates a computation that depends on Lux's compiler state."
  [(result lux action)])

(documentation: /.either
  "Pick whichever computation succeeds."
  [(either left right)])

(documentation: /.assertion
  "Fails with the given message if the test is #0."
  [(assertion message test)])

(documentation: /.failure
  "Fails with the given error message."
  [(failure error)])

(documentation: /.module
  "Looks-up a module with the given name."
  [(module name)])

(documentation: /.current_module_name
  "The name of the module currently being compiled, if any.")

(documentation: /.current_module
  "The module currently being compiled, if any.")

(documentation: /.normal
  (format "If given a name without a module prefix, gives it the current module's name as prefix."
          \n "Otherwise, returns the name as-is.")
  [(normal name)])

(documentation: /.macro
  "Looks-up a macro known by the given name."
  [(macro full_name)])

(documentation: /.seed
  (format "The current value of a number tracked by the compiler."
          \n "Also increases the value, so it's different next time it is seen."
          \n "This number can be used for generating data 'randomly' during compilation."))

(documentation: /.module_exists?
  ""
  [(module_exists? module)])

(documentation: /.var_type
  "Looks-up the type of a local variable somewhere in the environment."
  [(var_type name)])

(documentation: /.definition
  "Looks-up a definition's whole data in the available modules (including the current one)."
  [(definition name)])

(documentation: /.export
  (format "Looks-up a definition in the available modules (including the current one)."
          \n "The look-up only succeeds if the definition has been exported.")
  [(export name)])

(documentation: /.definition_type
  "Looks-up a definition's type in the available modules (including the current one)."
  [(definition_type name)])

(documentation: /.type
  "Looks-up the type of either a local variable or a definition."
  [(type name)])

(documentation: /.type_definition
  "Finds the value of a type definition (such as Int, Any or Lux)."
  [(type_definition name)])

(documentation: /.globals
  "The entire list of globals in a module (including the non-exported/private ones)."
  [(globals module)])

(documentation: /.definitions
  "The entire list of definitions in a module (including the non-exported/private ones)."
  [(definitions module)])

(documentation: /.exports
  "All the exported definitions in a module."
  [(exports module_name)])

(documentation: /.modules
  "All the available modules (including the current one).")

(documentation: /.tags_of
  "All the tags associated with a type definition."
  [(tags_of type_name)])

(documentation: /.location
  "The location of the current expression being analyzed.")

(documentation: /.expected_type
  "The expected type of the current expression being analyzed.")

(documentation: /.imported_modules
  "All the modules imported by a specified module."
  [(imported_modules module_name)])

(documentation: /.imported_by?
  ""
  [(imported_by? import module)])

(documentation: /.imported?
  "Checks if the given module has been imported by the current module."
  [(imported? import)])

(documentation: /.tag
  "Given a tag, finds out what is its index, its related tag-list and its associated type."
  [(tag tag_name)])

(documentation: /.slot
  "Given a slot, finds out what is its index, its related slot-list and its associated type."
  [(slot slot_name)])

(documentation: /.tag_lists
  "All the tag-lists defined in a module, with their associated types."
  [(tag_lists module)])

(documentation: /.locals
  "All the local variables currently in scope, separated in different scopes.")

(documentation: /.de_aliased
  "Given an aliased definition's name, returns the original definition being referenced."
  [(de_aliased def_name)])

(documentation: /.compiler_state
  "Obtains the current state of the compiler.")

(documentation: /.type_context
  "The current type-checking context.")

(documentation: /.eval
  ""
  [(eval type code)])

(.def: .public documentation
  (.List $.Module)
  ($.module /._
            "Functions for extracting information from the state of the compiler."
            [..result'
             ..result
             ..either
             ..assertion
             ..failure
             ..module
             ..current_module_name
             ..current_module
             ..normal
             ..macro
             ..seed
             ..module_exists?
             ..var_type
             ..definition
             ..export
             ..definition_type
             ..type
             ..type_definition
             ..globals
             ..definitions
             ..exports
             ..modules
             ..tags_of
             ..location
             ..expected_type
             ..imported_modules
             ..imported_by?
             ..imported?
             ..tag
             ..slot
             ..tag_lists
             ..locals
             ..de_aliased
             ..compiler_state
             ..type_context
             ..eval
             ($.default /.functor)
             ($.default /.apply)
             ($.default /.monad)
             ($.default /.lifted)
             ($.default /.try)]
            [/location.documentation
             /symbol.documentation]))
