\begin{smodule}{Aux Macros}

  \begin{dangerbox}
    Keeping the implementation properly up-to-date is pretty much
    incompatible with the kinds of workflows systemically enforced
    in academia. Any of the following may be out of date.
  \end{dangerbox}

  \STEXexport{
      \stex_sms_allow_escape:N \stexmacro
      \protected\def\stexmacro#1{
          \stex_execute_in_module:x{\tl_set:cn{l_stex_stexmacro_\tl_to_str:n{#1}_path}{\l_stex_current_module_str?\tl_to_str:n{#1}}}
          \exp_args:NNx\symdecl*{\tl_to_str:n{#1}}
          \exp_args:Nx\notation{\tl_to_str:n{#1}}{\comp{\texttt{\textbackslash\detokenize{#1}}}}
      }
      \protected\def\stexvarmacro#1{
        \tl_set:cx{l_stex_stexvarmacro_\tl_to_str:n{#1}_var}{\tl_to_str:n{#1}}
        \exp_args:Nnx\use:nn{\vardef}{
          {\tl_to_str:n{varmacro_#1}}[name={\tl_to_str:n{#1}}]{
            \noexpand\comp{\hbox{\noexpand\texttt{\noexpand\textbackslash\noexpand\detokenize{#1}}}}
          }
        }
      }
      \stex_sms_allow_escape:N \stexenv
      \protected\def\stexenv#1{
          \stex_execute_in_module:x{\tl_set:cn{l_stex_stexenv_\tl_to_str:n{#1}_path}{\l_stex_current_module_str?\tl_to_str:n{#1}}}
          \exp_args:NNx\symdecl*{\tl_to_str:n{#1}}
          \exp_args:Nx\notation{\tl_to_str:n{#1}}{\noexpand\texttt{\noexpand\detokenize{#1}}}
      }

      \cs_set_nopar:Nn \_stexdoc_do_cs:nn {
        \tl_if_exist:cTF{l_stex_stexvarmacro_\tl_to_str:n{#1}_var}{
          \exp_args:Nx \varref{\use:c{l_stex_stexvarmacro_\tl_to_str:n{#1}_var}}{#2}
        }{
          \tl_if_exist:cTF{l_stex_stexmacro_\tl_to_str:n{#1}_path}{
            \exp_args:Nx \symref{\use:c{l_stex_stexmacro_\tl_to_str:n{#1}_path}}{#2}
          }{#2}
        }
      }

      \RenewDocumentCommand\cmd { O{} m }
        { \_stexdoc_do_cs:nn{#2}{\__codedoc_cmd:no {#1} { \token_to_str:N #2 }} }
      \RenewDocumentCommand \cs  { O{} m }
        { \_stexdoc_do_cs:nn{#2}{\__codedoc_cmd:no {#1} { \c_backslash_str #2 }} }
      \RenewDocumentCommand \tn  { O{} m }
      { \_stexdoc_do_cs:nn{#2}{
        \@@_cmd:no
          { module = TeX , replace = false , #1 }
          { \c_backslash_str #2 }
      }}
      \protected\def\env#1{
        \tl_if_exist:cTF{l_stex_stexenv_\tl_to_str:n{#1}_path}{
          \exp_args:Nx \symref{\use:c{l_stex_stexenv_\tl_to_str:n{#1}_path}}{\texttt{\tl_to_str:n{#1}}}
        }{\texttt{\tl_to_str:n{#1}}}
      }

      \cs_set_protected:Nn \_stexdoc_dcs: {
        \peek_charcode:NTF [ {
          \_stexdoc_dcs:w
        }{
          \exp_args:NNe \use:nn \_stexdoc_dcs:w {[\seq_item:Nn \_stexdoc_sfunction_seq 1]}
        }
      }

      \cs_set_protected:Npn \_stexdoc_dcs:w [#1] {
        \exp_args:Ne \definiendum{\tl_to_str:n{#1}}{\exp_args:Nne \__codedoc_cmd:nn {} { \c_backslash_str \tl_to_str:n{ #1 } }}
        \xspace
      }

      \ProvideDocumentEnvironment {sfunction}{m O{} +v}{
        \seq_set_split:Nnn \_stexdoc_sfunction_seq , {#1}
        \seq_map_inline:Nn \_stexdoc_sfunction_seq {
          \stex_pseudogroup_with:nn{\stex_smsmode_do:}{\def\stex_smsmode_do:{}\stexmacro{##1}}
        }
        \cs_set_eq:NN \dcs \_stexdoc_dcs:
        \ifstexhtml 
          \def\box_move_up:nn##1##2{\tex_raise:D\__box_dim_eval:n{0pt}##2}
          \renewenvironment{syntax}{\noindent}{\par}
        \fi
        \begin{sparagraph}[style=symdoc,for={#1}]
          \__codedoc_function:nnw{#2}{#3}
      }{
        \stex_if_smsmode:F{\__codedoc_function_end:}
        \end{sparagraph}
      }
      \stex_sms_allow_env:n{sfunction}

      \ProvideDocumentEnvironment { svariable } { m +v }
      {
        \seq_set_split:Nnn \_stexdoc_sfunction_seq , {#1}
        \seq_map_inline:Nn \_stexdoc_sfunction_seq {
          \stex_pseudogroup_with:nn{\stex_smsmode_do:}{\def\stex_smsmode_do:{}\stexmacro{##1}}
        }
        \cs_set_eq:NN \dcs \_stexdoc_dcs:
        \ifstexhtml
          \def\box_move_up:nn##1##2{\tex_raise:D\__box_dim_eval:n{0pt}##2}
          \renewenvironment{syntax}{\noindent}{\par}
        \fi
        \begin{sparagraph}[style=symdoc,for={#1}]
        \bool_if:NTF \l__codedoc_in_implementation_bool
          { \__codedoc_macro:nnw { var , } {#2} }
          { \__codedoc_function:nnw {} {#2} }
      }
      {
        \bool_if:NTF \l__codedoc_in_implementation_bool
          { \__codedoc_macro_end: }
          { \__codedoc_function_end: }
        \end{sparagraph}
      }
      \stex_sms_allow_env:n{svariable}

      \ProvideDocumentEnvironment {senv} {m} {
        \def\denv{\exp_args:Ne\definiendum{\tl_to_str:n{#1}}{\texttt{\tl_to_str:n{#1}}}}
        \stex_pseudogroup_with:nn{\stex_smsmode_do:}{\def\stex_smsmode_do:{}\stexenv{#1}}
        \begin{sparagraph}[style=symdoc,for={#1}]
        \exp_args:Ne\DescribeEnv{\tl_to_str:n{#1}}
      }{
        \end{sparagraph}\par\smallskip
      }
      \stex_sms_allow_env:n{senv}
    }

  \CodedocExplain

  %^^A\CodedocExplainEXP
  %^^A\CodedocExplainREXP
  %^^A\CodedocExplainTF

  \begin{sfunction}{stex_debug:nn}{\stex_debug:nn}
    \begin{syntax}
      \dcs \marg{prefix} \marg{msg}
    \end{syntax}
    Logs the debug message \marg{msg} under the prefix
    \marg{prefix}. A message is shown if its prefix
    is in a list of prefixes given either via the
    package option |debug=|\meta{prefixes} or
    the environment variable |STEX_DEBUG=|\meta{prefixes},
    where the latter overrides the former.
  \end{sfunction}

  \begin{sfunction}{_stex_do_deprecation:n}{\_stex_do_deprecation:n}
    TODO \dcs
  \end{sfunction}

\begin{sfragment}{Documents}

  \begin{svariable}{l_stex_docheader_sect}{\l_stex_docheader_sect}
    integer register keeping track of the current sectioning level:
    \begin{itemize}
      \item[0] part
      \item[1] chapter
      \item[2] section
      \item[3] subsection
      \item[4] subsubsection
      \item[5] paragraph
      \item[$>5$] subparagraph
    \end{itemize}
    \cs{setsectionlevel} sets \cs{l_stex_docheader_sect} to the corresponding
    integer value.
  \end{svariable}

  \begin{sfunction}{stex_ref_new_doc_target:n}{\stex_ref_new_doc_target:n}
    internal variant of \cs{sreflabel}. If the argument is empty,
    the label is determined to be |REF|\meta{counter}
    and \meta{counter} is increased.
  \end{sfunction}

  \begin{sfunction}{stex_ref_new_symbol:n}{\stex_ref_new_symbol:n}
    registers a new link target for the symbol with the given full uri 
    (as string), using the |url-base|-field of the current
    archive's manifest file to link the symbol to
    \meta{url-base}|/symbol?|\meta{uri}.
  \end{sfunction}

  \begin{sfunction}{stex_ref_new_sym_target:n}{\stex_ref_new_sym_target:n}
    sets a new label for the symbol with the given full uri (as string).
    If called in sms-mode, defers to \cs{stex_ref_new_symbol:n},
    if not already registered. 
    Otherwise, sets a \cs{label} for the symbol.
  \end{sfunction}

  \begin{sfunction}{stex_ref_new_sym_target:nn}{\stex_ref_new_sym_target:nn}
    \begin{syntax}\dcs\marg{symbol}\marg{target}
    \end{syntax}
    redirects links for \meta{symbol} to the one for the symbol
    \meta{target}. Useful for e.g. symbols elaborated from
    structural features. Note that this acts as a \emph{default},
    in that previous or subsequent 
    calls of \cs{stex_ref_new_sym_target:n}\marg{symbol}
    are prioritized.

    Requires that either \cs{stex_ref_new_sym_target:n}\marg{target}
    or
    \cs{stex_ref_new_sym_target:nn}\marg{target}\marg{other-target}
    have been called previously.
  \end{sfunction}

\end{sfragment}

\begin{sfragment}{Modules}

  \stexmacro{stex_module_add_symbol:nnnnnnN}
  \stexmacro{stex_add_module_notation:nnnnn}
  \stexmacro{stex_module_add_morphism:nnn}

  The contents of a module with full URI
  \meta{uri} are represented as four macros:
  \begin{itemize}
    \item |\c_stex_module_|\meta{uri}|_code|: code to be executed
      every time the module is \emph{activated}; e.g. the contents
      of \cs{STEXexport}, defines semantic macros and macros for
      notations, activates dependency modules, etc.
    \item |\c_stex_module_|\meta{uri}|_morphisms_prop|: property list
      containing all module dependencies of this module 
      (see \cs{stex_module_add_morphism:nnn}).
    \item |\c_stex_module_|\meta{uri}|symbols_prop|: property list
      containing all declarations in this module (see \cs{stex_module_add_symbol:nnnnnnN}).
    \item |\c_stex_module_|\meta{uri}|_notations_prop|: property list
      containing all notations introduced in this module
      (see \cs{stex_add_module_notation:nnnnn}).
  \end{itemize}

  \begin{svariable}{l_stex_current_module_str}{\l_stex_current_module_str}
    contains the full URI of the current module.
  \end{svariable}

  \begin{svariable}{l_stex_all_modules_seq}{\l_stex_all_modules_seq}
    contains the full URIs of all modules currently in scope.
  \end{svariable}

  \stexvarmacro{l_stex_key_sig_str}
  \begin{sfunction}{stex_module_setup:n}{\stex_module_setup:n}
    \begin{syntax} \dcs\marg{name} \end{syntax}
    Computes the full URI of a new module with name \meta{name}
    in the current namespace, initializes the
    four macros above and sets \cs{l_stex_current_module_str}
    accordingly. Also takes care of correct naming for nested
    modules, activates the meta theory and loads the signature module 
    if |sig=| was provided (according to \cs{l_stex_key_sig_str}).
  \end{sfunction}

  \stexmacro{stex_persist:n}
  \begin{sfunction}{stex_close_module:}{\stex_close_module:}
    closes the current module; checks whether we are currently in
    sms mode, and if so, calls \cs{stex_persist:n} 
    to write the module contents to the sms-file.
  \end{sfunction}

  \begin{sfunction}{stex_every_module:n}{\stex_every_module:n}
    \begin{syntax}\dcs\marg{code}\end{syntax}
    executes \meta{code} every time a new module is opened.
  \end{sfunction}

  \begin{sfunction}{stex_if_in_module:}[pTF]{\stex_if_in_module:}
    tests whether we are currently in a module.
  \end{sfunction}

  \begin{sfunction}{stex_if_module_exists:n}[pTF]{\stex_if_module_exists:n}
    tests whether a module with the given full URI exists, in the sense
    of \emph{has been parsed at some point in the current document}.
  \end{sfunction}

  \begin{sfunction}{stex_activate_module:n}{\stex_activate_module:n,\stex_activate_module:o,\stex_activate_module:x}
    activates the module with the given full URI \emph{if and only if}
    it has not already been activated in the current scope.
  \end{sfunction}

  \stexmacro{stex_metagroup_do_in:nn}

  \begin{sfunction}{stex_execute_in_module:n}{\stex_execute_in_module:n,\stex_execute_in_module:x}
    executes the provided code, adds it to the current module
    activation code, and makes
    sure the macros defined in it are valid in the current module 
    \TeX\ group level.
  \end{sfunction}

  This macro is a combination of the following two macros:

  \begin{sfunction}{stex_do_up_to_module:n}{\stex_do_up_to_module:n,\stex_do_up_to_module:x}
    executes the provided code such that all definitions in it
    are valid in the current module regardless of \TeX\ group level
    (using \cs{stex_metagroup_do_in:nn}).
  \end{sfunction}

  \begin{sfunction}{stex_module_add_code:n}{\stex_module_add_code:n,\stex_module_add_code:x}
    adds the provided code to the module's
    |\c_stex_module_|\meta{uri}|_code|-macro.
  \end{sfunction}

\end{sfragment}

\begin{sfragment}{Symbols}

  A symbol in \stex is represented as a tuple of several components:

  \stexvarmacro{id}
  \stexvarmacro{invokation_macro}
  \stexmacro{_stex_invoke_symbol:nnnnnnnN}

  \begin{sfunction}{stex_module_add_symbol:nnnnnnnN}{\stex_module_add_symbol:nnnnnnnN}
    \begin{arguments}
      \item \meta{id}: An \emph{identifier} (possibly empty) that determines its
        semantic macro name, or e.g. in \env{mathstructure} its
        accessor-identifier (if empty, the name is used for that),
      \item \meta{name} a unique \emph{name}, which in combination with the
        containing module determines its URI as \meta{module-URI}|?|\meta{name},
      \item \meta{arity} a numeric string in the range |0..9|,
      \item \meta{args} a list of argument specifiers of the form
        \meta{i}\meta{mode}|{|\meta{argname}|}| (the length of \meta{args}
        must be $3\cdot$\meta{arity}),
      \item \meta{definiens} (or empty),
      \item \meta{type} (or empty),
      \item \meta{return code} (or empty), and
      \item \meta{\cs{invokation_macro}}.
    \end{arguments}

    the arguments are stored in the property list 
    \cs{c_stex_module_}\meta{\cs{l_stex_current_module}}|_symbols_prop|
    under key \meta{name}.

    If the identifier \meta{id} is non-empty, the macro
    \cs{id} is defined as |{|\cs{_stex_invoke_symbol:nnnnnnnN}|}|
    with the arguments described there.

    \begin{texnote} \cs{invokation_macro} must be \cs{protected}.
    \end{texnote}
  \end{sfunction}

  \begin{sfunction}{stex_iterate_symbols:n,stex_iterate_break:,stex_iterate_break:n}{\stex_iterate_symbols:n,\stex_iterate_break:,\stex_iterate_break:n}
    \begin{syntax}\dcs\marg{code}\end{syntax}
    iterates over all symbols currently in scope and calls
    \meta{code} for all of them with arguments
    \marg{module}\marg{name}\marg{arity}\meta{args}\marg{definiens}
    \marg{type}\marg{return code}\marg{\cs{invokation_macro}}.

    Iteration can be stopped prematurely with
    \dcs[stex_iterate_break:] and can stop and return code
    with \dcs[stex_iterate_break:n].
  \end{sfunction}

  \begin{sfunction}{stex_iterate_symbols:nn}{\stex_iterate_symbols:nn}
    \begin{syntax}\dcs\marg{csl}\marg{code}\end{syntax}
    iterates over all symbols in the provided \meta{csl}
    of full module URIs. \meta{code} 
    receives the same arguments as \cs{stex_iterate_symbols:n},
    but iteration can not be stopped early.
  \end{sfunction}

  \begin{sfunction}{
    stex_get_symbol:n,
    l_stex_get_symbol_mod_str,
    l_stex_get_symbol_name_str,
    l_stex_get_symbol_arity_int,
    l_stex_get_symbol_args_tl,
    l_stex_get_symbol_def_tl,
    l_stex_get_symbol_type_tl,
    l_stex_get_symbol_return_tl,
    l_stex_get_symbol_invoke_cs
    }{\stex_get_symbol:n,
    \l_stex_get_symbol_mod_str,
    \l_stex_get_symbol_name_str,
    \l_stex_get_symbol_arity_int,
    \l_stex_get_symbol_args_tl,
    \l_stex_get_symbol_def_tl,
    \l_stex_get_symbol_type_tl,
    \l_stex_get_symbol_return_tl,
    \l_stex_get_symbol_invoke_cs
    }
    \dcs attemps to find a symbol with the given name or id
    that is currently in scope.
    A name may be prefixed with a module name/path separated by |?|.

    Throws an error if no such symbol is found; otherwise, sets the
    listed |\l_stex_get_symbol_...|-macros to the components of the
    found symbol.
  \end{sfunction}

  \begin{sfunction}{stex_if_check_terms:}[pTF]{\stex_if_check_terms:}
    whether to typeset declaration components (notations, types,
    definientia etc.) in a throwaway box. Is true iff
    the backend is |pdflatex| and
    either the |STEX_CHECKTERMS| environment variable
    or |checkterms| package option is set.
  \end{sfunction}

  \begin{sfunction}{stex_check_term:n}{\stex_check_term:n}
      typesets the argument in a throwaway box in math mode
      iff \cs{stex_if_check_terms:} is true.

      Is deactivated in sms-mode.
  \end{sfunction}

  \begin{sfunction}{
    stex_symdecl_do:,
    l_stex_key_name_str,
    l_stex_key_args_str,
    l_stex_key_argnames_clist,
    l_stex_assoc_args_count,
    l_stex_argnames_seq
    }{\stex_symdecl_do:,
    \l_stex_key_name_str,
    \l_stex_key_args_str,
    \l_stex_key_argnames_clist,
    \l_stex_assoc_args_count,
    \l_stex_argnames_seq
    }
      \dcs processes the shared (mandatory and optional) arguments
      of e.g. \cs{symdecl}, \cs{symdef}, \cs{vardef} etc.

      Requires the following macros to be set
      \begin{itemize}
        \item \dcs[l_stex_key_name_str]: the name of the symbol,
        \item \dcs[l_stex_key_args_str]: the |args|-string (e.g.
        |3| or |ai|)
        \item \dcs[l_stex_key_argnames_clist]: a list of \emph{names}
          for the arguments, the length of which should be $\leq$ the
          arity of the symbol
      \end{itemize}

      and will generate the following macros:
      \begin{itemize}
        \item \cs{l_stex_get_symbol_arity_int}: the arity of the symbol,
        \item \dcs[l_stex_key_args_str]: the args string as a
          definite sequence of argument-mode characters, whose
          length is the arity of the symbol; e.g.
          |3| is turned into |iii|,
        \item \dcs[l_stex_assoc_args_count]: the number of
          sequence arguments (i.e. |a| or |B| mode),
        \item \dcs[l_stex_argnames_seq]: the full sequence of
          argument names; those not provided by
          \cs{l_stex_key_argnames_clist} are set to be
          |$j|\iffalse$\fi, where |j| is the index of the
          argument,
        \item \cs{l_stex_get_symbol_args_tl}: a token list of
          triples |jm{|\meta{argname}|}|, where |j| is the index and
          |m| the respective argument mode character (i.e. |i|, |a|,
          |b| or |B|). 
      \end{itemize}
  \end{sfunction}

  \begin{sfunction}{_stex_symdecl_check_terms:,
    l_stex_key_type_tl,l_stex_key_def_tl}{\_stex_symdecl_check_terms:}
    calls \cs{stex_check_term:n} for
    the type and definiens stored in \cs{l_stex_key_type_tl} and
    \cs{l_stex_key_def_tl}
  \end{sfunction}

  \stexmacro{stex_invoke_symbol:}
  \begin{sfunction}{stex_symdecl_top:n,l_stex_macroname_str}{\stex_symdecl_top:n}
    \begin{syntax}\dcs\marg{maybename}\end{syntax}
    checks whether \cs{l_stex_key_name_str} is empty,
    and if so, sets it to be \meta{maybename}.
    Then calls \cs{stex_symdecl_do:} and
    \cs{_stex_symdecl_check_terms:}, writes the components to the HTML
    (if applicable) and adds the symbol to the current module
    with invokation macro \cs{stex_invoke_symbol:} and id/macroname
    \cs{l_stex_macroname_str}.
  \end{sfunction}\bigskip
  
  Variables work very similar to symbols, except that their declarations
  are local to the current \TeX-group rather than the
  current module, and they are not exported in modules.

  \begin{svariable}{l_stex_variables_prop}{\l_stex_variables_prop}
    stores all variables currently in scope as a property list
    with key \meta{name} and value
    \marg{id}\marg{name}\marg{arity}\meta{args}\marg{definiens}
    \marg{type}\marg{return code}\marg{\cs{invokation_macro}}.

    The invokation macro for ``normal'' variables declared with
    \cs{vardef} is \cs{stex_invoke_symbol:}.
  \end{svariable}

  \begin{sfunction}{_stex_vardecl_notation_macro:}{\_stex_vardecl_notation_macro:}
    generates the notation macro for a variable, based on the
    values of the |\l_stex_key|-macros und \cs{l_stex_notation_macrocode_cs}.
  \end{sfunction}

  \begin{sfunction}{stex_get_var:n}{\stex_get_var:n}
    like \cs{stex_get_symbol:n}, but attempts to retrieve a
    variables and throws an error if none is found.
  \end{sfunction}

  \begin{sfunction}{stex_get_symbol_or_var:n}{\stex_get_symbol_or_var:n}
    like \cs{stex_get_symbol:n}, but first attempts
    to find a \emph{variable}, and if none is found,
    defers to \cs{stex_get_symbol:n}.
  \end{sfunction}

\end{sfragment}


\begin{sfragment}{Notations}

  \stexmacro{stex_set_notation_macro:nnnnn}
  \begin{sfunction}{stex_module_add_notation:nnnnn}{\stex_module_add_notation:nnnnn, \stex_module_add_notation:eoexo}
    \begin{syntax}\dcs
      \marg{symboluri}\marg{id}\marg{arity}\meta{code}\meta{op code}
    \end{syntax}
    stores the arguments in the property list 
    \cs{c_stex_module_}\meta{\cs{l_stex_current_module}}|_notations_prop|
    under key \meta{symboluri}|!|\meta{id} and calls
    \cs{stex_set_notation_macro:nnnnn}.
  \end{sfunction}

  \begin{sfunction}{stex_set_notation_macro:nnnnn}{\stex_set_notation_macro:nnnnn,\stex_set_notation_macro:eoexo}
    \begin{syntax}\dcs
      \marg{symboluri}\marg{id}\marg{arity}\meta{code}\meta{op code}
    \end{syntax}
    Declares the following macros:

    An active notation for a symbol with uri \meta{symboluri} and id
    \meta{id} is represented as
    a macro \cs{l_stex_notation_}\meta{symboluri}|_|\meta{id}|_cs|,
    that takes \meta{arity} many argument
    and expands to \meta{code},
    and (if nonempty) an \emph{operator} notation as
    a macro \cs{l_stex_notation_}\meta{symboluri}|_op_|\meta{id}|_cs|
    that expands to \meta{op code}.

    The default notation is represented as the \emph{empty} id.
    If the correponding macros
    \cs{l_stex_notation_}\meta{symboluri}|__cs|,
    and \cs{l_stex_notation_}\meta{symboluri}|_op__cs| do not yet exist,
    they are now defined as \meta{id}.
  \end{sfunction}

  \begin{sfunction}{stex_iterate_notations:nn}{\stex_iterate_notations:nn}
    \begin{syntax}\dcs\marg{csl}\marg{code}\end{syntax}
    iterates over all notations in the provided \meta{csl}
    of full module URIs and calls \meta{code} on each of them with
    arguments
    \marg{symboluri}\marg{id}\marg{arity}\meta{code}\meta{op code}.
  \end{sfunction}

  \begin{sfunction}{
    stex_notation_parse_and_then:nw,
    l_stex_key_prec_str,
    l_stex_key_variant_str,
    l_stex_notation_macrocode_cs
    }{\stex_notation_parse_and_then:nw,
    \l_stex_key_prec_str,
    \l_stex_key_variant_str,
    \l_stex_notation_macrocode_cs
    }
    \begin{syntax}\dcs\marg{code}\meta{notations}
    \end{syntax}

    parses a notation (which may consist of multiple
    braced components, depending on the argument modes)
    and subsequently calls \meta{code}.

    Requires the following macros to be set:
    \begin{itemize}
      \item \cs{l_stex_get_symbol_arity_int},
      \item \cs{l_stex_get_symbol_args_tl},
      \item \dcs[l_stex_key_prec_str]: The precedence string
        as provided by a user in the optional |precs|-argument,
      \item \dcs[l_stex_key_variant_str]: the id of the
        notation variant.
    \end{itemize}

    Stores the final notation in the macro 
    \dcs[l_stex_notation_macrocode_cs] taking 
    \cs{l_stex_get_symbol_arity_int} many arguments.
  \end{sfunction}\bigskip


  Some thing to consider when we generate a notation macro:
  \begin{itemize}
    \item The notation macro generated by the \cs{notation}-command
      should contain the variant identifier and the precedences,
      as these are intrinsic parts of the notation. 
    \item It should
      \emph{not} contain the symbol itself however, so that
      notations can be copied between symbols.
    \item Notations as provided by users will largely adhere
      to the standard \LaTeX\ category code scheme, and
    \item notations need to be ``persistable'' in |.deps|-files.
  \end{itemize}

  We therefore want to augment the simple code provided by
  a user by various ``annotations'' that contain the
  relevant information (such as precedences) and to mark
  the argument positions for semantic extractions, but we should
  adhere to the default \LaTeX\ category code scheme in doing
  so.

  \begin{sfunction}{
    STEXInternalTermMathArgiii,
    STEXInternalTermMathOMSOrOMViii,
    STEXInternalTermMathAssocArgiiiii,
    STEXInternalAssocArgMarkerI,
    STEXInternalAssocArgMarkerII,
    STEXInternalTermMathOMAiii,
    STEXInternalTermMathOMBiii,
    STEXInternalSymbolAfterInvokationTL
  }{
    \STEXInternalTermMathArgiii,
    \STEXInternalTermMathAssocArgiiiii,
    \STEXInternalAssocArgMarkerI,
    \STEXInternalAssocArgMarkerII,
    \STEXInternalTermMathOMSOrOMViii,
    \STEXInternalTermMathOMAiii,
    \STEXInternalTermMathOMBiii,
    \STEXInternalSymbolAfterInvokationTL
  }

  In \openmath/\OMDoc, there are (for our purposes) 
  three kinds of expressions that an application of a semantic macro
  -- and hence a notation macro -- can represent, each of which
  corresponds to a macro taking care of the semantic annotations:
  \begin{itemize}
    \item |OMS/OMV|: a simple symbol (arity 0) (\dcs[STEXInternalTermMathOMSOrOMViii])
    \item |OMA|: an application of a symbol to argument (arity $>0$,
      \dcs[STEXInternalTermMathOMAiii])
    \item |OMB|: a binding application of a symbol that
      binds/declares one or more variables (argument string contains
      |b| or |B|, \dcs[STEXInternalTermMathOMBiii]).
  \end{itemize}

  The arguments are marked with \dcs[STEXInternalTermMathArgiii]
  (|i| or |b|) or \dcs[STEXInternalTermMathAssocArgiiiii] (|a|
  or |B|). Finally, the notation is closed with 
  \dcs[STEXInternalSymbolAfterInvokationTL].
  
  How this works is best explained by example.
  \end{sfunction}


  \begin{sexample}
    Assume we have a symbol and notation:
    \begin{stexcode}
\symdecl{somesymbol}[args=iai]
\notation{somesymbol}[prec=10;20x30x40,variant=foo]
{First: #1; Second: #2; Third: #3; End}
{(#1 -- ##1 split ##2 -- #3)}
    \end{stexcode}

    Since the symbol corresponds to an |OMA|, the whole notation
    is wrapped in \cs{STEXInternalTermMathOMAiii}, taking as
    arguments the variant identifier (|foo|), 
    the operator precedence (|10|) and the body of the notation.

    The second argument in the notation, being associative,
    is wrapped in a \cs{STEXInternalTermMathAssocArgiiiii},
    taking as arguments the argument number (|2|), the
    precedence (|30|), the \TeX\ parameter token (|#2|)
    the notation body (|(#1 -- ##1 split ##2 -- #3)|), and finally
    the argument mode (|a|). Additionally, the markers |##1|
    and |##2| are replaced by \cs{STEXInternalAssocArgMarkerI}
    and \cs{STEXInternalAssocArgMarkerII}, respectively.

    Subsequently, the non-sequence parameter tokens
    are wrapped in \cs{STEXInternalTermMathArgiii} with
    arguments |mj| (where |m| is the mode und |j| the index),
    the precedence (|20| or |40| respectively), and the
    parameter token.

    Finally, a \cs{STEXInternalSymbolAfterInvokationTL}
    is inserted.

    The final expansion of \cs{l_stex_notation_macrocode_cs}
    is thus:
    \begin{stexcode}
\STEXInternalTermMathOMAiii{foo}{10}{
  First: \STEXInternalTermMathArgiii{i1}{20}{#1};
  Second: \STEXInternalTermMathAssocArgiiiii{2}{30}{#2}{
    (\STEXInternalTermMathArgiii{i1}{20}{##1} -- 
      \STEXInternalAssocArgMarkerI  split
      \STEXInternalAssocArgMarkerII  -- 
      \STEXInternalTermMathArgiii{i3}{40}{##3})
  }{a}; 
  Third: \STEXInternalTermMathArgiii {i3}{40}{#3}; End
}\STEXInternalSymbolAfterInvokationTL 
    \end{stexcode}
  \end{sexample}

  \begin{sfunction}{stex_notation_top:nnw}{\stex_notation_top:nnw}
    \begin{syntax}\dcs\marg{symboluri}\marg{code}\end{syntax}
    calls \cs{stex_notation_parse_and_then:nw}\marg{code}
    and, adds the notation for the symbol with
    URI \meta{symboluri} to the current module and
    exports it to the HTML (if applicable).
  \end{sfunction}

\end{sfragment}

\begin{sfragment}{Structural Features}

  \begin{sfunction}{stex_structural_feature_module:nn,
    stex_structural_feature_module_end:,
    g_stex_last_feature_str
  }{\stex_structural_feature_module:nn,
  \stex_structural_feature_module_end:,
  \g_stex_last_feature_str
  }
    \begin{syntax}\dcs\marg{name}\marg{typeid}\end{syntax}
    opens a new module-like structural feature of type \meta{typeid} 
    with name \meta{name}, which needs to be closed with
    \dcs[stex_structural_feature_module_end:].

    Its body behaves like a nested module with name
    \meta{modulename}|/|\meta{name}, the full URI of which is
    stored in \dcs[g_stex_last_feature_str] for 
    subsequent elaboration.
  \end{sfunction}

  \begin{sfunction}{
    stex_structural_feature_morphism:nnnnn,
    stex_structural_feature_morphism_end:,
    l_stex_current_domain_str,
    l_stex_feature_name_str,
    l_stex_morphism_symbols_prop,
    l_stex_morphism_renames_prop,
    l_stex_morphism_morphisms_seq
    }{
      \stex_structural_feature_morphism:nnnnn,
      \stex_structural_feature_morphism_end:,
      \l_stex_current_domain_str,
      \l_stex_feature_name_str,
      \l_stex_morphism_symbols_prop,
      \l_stex_morphism_renames_prop,
      \l_stex_morphism_morphisms_seq
    }
    \begin{syntax}\dcs\marg{moprhismname}\marg{typeid}\marg{archive}\marg{domain}\marg{annotations}\end{syntax}
    opens a new morphism-like structural feature of type \meta{typeid} 
    with name \meta{morphismname} and the module
    |[|\meta{archive}|]|\marg{domain} as domain, which needs to be closed with
    \dcs[stex_structural_feature_morphism_end:].

    Deactivates \cs{symdecl}, \cs{textsymdecl},
    \cs{symdef}, \cs{notation} and \env{smodule}, and activates
    \cs{assign}, \cs{assignMorphism} and \cs{renamedecl}.

    Defines the following macros:
    \begin{itemize}
      \item \dcs[l_stex_feature_name_str]|=|\marg{name}.
      \item \dcs[l_stex_current_domain_str]|=| the full uri of \meta{domain}.
      \item \dcs[l_stex_morphism_symbols_prop]: This property list is
        initialized as follows: For every symbol 
        transitively included in \meta{domain} with data
        \meta{module}, \meta{name}, \meta{id}, \meta{arity}, \meta{args},
        \meta{definiens}, \meta{type}, and \meta{return code},
        the property list contains an entry with key
        |[|\meta{module}|]/[|\meta{name}|]|
        and value \marg{id}\marg{arity}\marg{args}\marg{definiens}
        \marg{type}\marg{return code}.
      \item \dcs[l_stex_morphism_renames_prop]: An initially empty
        property list.
      \item \dcs[l_stex_morphism_morphisms_seq]: TODO
    \end{itemize}

    At \dcs[stex_structural_feature_morphism_end:], the elaboration
    is computed from the above data thusly:

    For every entry in \dcs[l_stex_morphism_symbols_prop],
    a new symbol is created with the values \meta{arity}, \meta{args},
    \meta{definiens}, \meta{type} and \meta{return code} from that
    property list, and either:
    \begin{itemize}
      \item if \dcs[l_stex_morphism_renames_prop] does \emph{not}
        contain an entry with key \meta{module}|?|\meta{name},
        then the elaborated name is \meta{morphismname}|/|\meta{name}
        and its \meta{id} is empty (no semantic macro is generated), or
      \item if \dcs[l_stex_morphism_renames_prop] contains an
        entry with key \meta{module}|?|\meta{name}, then its value
        needs to be of the form \marg{id}\marg{name}, which are
        used for the elaborated symbol.
    \end{itemize}
    All notations of the symbols transitively included in the domain
    are copied over to their elaborations.
  \end{sfunction}

\end{sfragment}

\begin{sfragment}{Imports and Morphisms}

  \begin{sfunction}{stex_module_add_morphism:nnnn}{\stex_module_add_morphism:nnnn, \stex_module_add_morphism:nonn, \stex_module_add_morphism:ooox}
    adds a new module morphism (i.e. inheritance, possibly with 
    modification) to the current module
    \begin{arguments}
      \item The name of the morphism (may be empty for e.g. \cs{importmodule},
        but may be named for e.g. \env{copymodule}),
      \item the URI of the module being ``imported'',
      \item the ``type'' of the morphism (e.g. |import| or |copymodule|),
      \item a list of assignments as pairs 
        |{|\meta{source}|}{|\meta{target}|}| that signify that
        the symbol with full URI \meta{source} is being mapped or elaborated to
        the new symbol with name \meta{target} in the current module.
        May be empty for e.g. \cs{importmodule}.
    \end{arguments}
    The provided arguments are stored in 
    |\c_stex_module_|\meta{uri}|_morphisms_prop|
    with key |#1| (if non-empty) or |[#2]| (if |#1| is empty)
    and value |{#1}{#2}{#3}{#4}|
  \end{sfunction}\bigskip

  Import-like statements in \sTeX are usually given
  as pairs |[|\meta{archive}|]{|\meta{path}|?|\meta{module}|}|,
  which be relative to the current archive and/or
  file path. For persistence and sms-mode, these
  pairs first need to be resolved into an \emph{absolute}
  specification:

  \begin{sfunction}{
    stex_import_module_uri:nn,
    l_stex_import_archive_str,
    l_stex_import_name_str,
    l_stex_import_uri_str,
    l_stex_import_path_str
  }{
    \stex_import_module_uri:nn,
    \l_stex_import_archive_str,
    \l_stex_import_name_str,
    \l_stex_import_uri_str,
    \l_stex_import_path_str
  }
    \begin{syntax}\dcs\marg{archive}\marg{pathstring}\end{syntax}
    (where \meta{archive} may be empty) resolves the given arguments
    into:
    \begin{itemize}
      \item \dcs[l_stex_import_archive_str] the given archive id
        (in which case \cs{stex_require_archive:n} is called),
        or the id of the current archive (if existent and \meta{archive}
        empty), or empty,
      \item \dcs[l_stex_import_uri_str] if an archive id is given,
        or we currently are in an archive, its corresponding
        namespace; otherwise |{file:}|,
      \item \dcs[l_stex_import_path_str] the path of the URI
        relative to the given (or current) archive, or (if not existent)
        the absolute path of \meta{pathstring} (without a module name) 
        resolved relative to the current file's parent directory, and
      \item \dcs[l_stex_import_name_str] the name of the module.
    \end{itemize}
    If \meta{pathstring} does not contain the character |?|,
    the whole pathstring is assumed to be the name of the module
    and the path is empty (or the current file's parent directory, 
    depending on the above).
  \end{sfunction}

  \begin{sfunction}{stex_import_require_module:nnn}{\stex_import_require_module:nnn}
    takes as arguments values
    \cs{l_stex_import_archive_str}, \cs{l_stex_import_path_str}
    and \cs{l_stex_import_name_str} as computed by
    \cs{stex_import_module_uri:nn} and
    (optionally loads and) activates the corresponding
    module (or throws an error if it does not exist).
  \end{sfunction}\bigskip

  Most complex morphisms (\env{copymodule} et al) are implemented
  as structural features
  using \cs{stex_structural_feature_morphism:nnnn}.

  \begin{sfunction}{stex_get_in_morphism:n,
    l_stex_get_symbol_macro_str}{\stex_get_in_morphism:n,
    \l_stex_get_symbol_macro_str}
    finds a symbol with the provided name or id in the domain
    of the current morphism. Sets the same macros as
    \cs{stex_get_symbol:n}, and additionaly
    \dcs[l_stex_get_symbol_macro_str] to the \meta{id}
    of the symbol. Throws an error if no such symbol is found.
  \end{sfunction}

\end{sfragment}

\begin{sfragment}{Expressions and Semantic Macros}

  \begin{sfunction}{_stex_invoke_symbol:nnnnnnnN,
    l_stex_current_symbol_str,
    l_stex_current_arity_str,
    l_stex_current_args_tl,
    l_stex_current_return_tl,
    l_stex_current_type_tl
    }{\_stex_invoke_symbol:nnnnnnnN
    \l_stex_current_symbol_str,
    \l_stex_current_arity_str,
    \l_stex_current_args_tl,
    \l_stex_current_return_tl,
    \l_stex_current_type_tl
    }
    \begin{syntax}\dcs
      \marg{module}\marg{name}\marg{arity}\marg{args}\marg{definiens}
      \marg{type}
      \marg{return code}
      \marg{\cs{invokation_macro}}
    \end{syntax}
    is how a semantic macro is/should be defined.
    \dcs first checks whether semantic macros are currently allowed,
    and throws an error if not. Otherwise, it
    sets the \cs{comp}-controlled highlighting to \cs{compemph@uri},
    initializes \cs{STEXInternalSymbolAfterInvokationTL},
    defines the following macros for all of its arguments, and subsequently
    calls the \cs{invokation_macro}:
    \begin{itemize}
      \item \dcs[l_stex_current_symbol_str]|={|\meta{module}|?|\meta{name}|}|
      \item \dcs[l_stex_current_arity_str]|=|\marg{arity}
      \item \dcs[l_stex_current_args_tl]|=|\marg{args}
      \item \dcs[l_stex_current_type_tl]|=|\marg{type}
      \item \dcs[l_stex_current_return_tl]|=|\marg{return code}
    \end{itemize}

    The simplest example for an \cs{invokation_macro} is
    \cs{stex_invoke_symbol:}.
  \end{sfunction}

  \begin{sfunction}{_stex_invoke_variable:nnnnnnN}{\_stex_invoke_variable:nnnnnnN}
    analogous to \cs{_stex_invoke_symbol:nnnnnnnN}, but for variables;
    sets the \cs{comp}-controlled highlighting to \cs{varemph@uri}.
  \end{sfunction}

  \begin{sfunction}{stex_invoke_symbol:}{\stex_invoke_symbol:}
    branches based on the mode and following characters:
    \begin{itemize}
      \item If math, check next character:
        \begin{itemize}
          \item[!] operator; defer to operator notation
          \item[else] defer to notation and check the value of
            \cs{l_stex_current_return_tl}=\meta{return}.
            \begin{itemize}
              \item If \meta{return} is empty, call the notation macro,
              \item otherwise, call \meta{return}|{|\cs{stex_invoke_symbol}|!}|.
            \end{itemize}
        \end{itemize}
      \item If text:
    \end{itemize}
  \end{sfunction}

  \begin{sfunction}{stex_invoke_sequence_range:,
    stex_invoke_sequence_in:
    }{
      \stex_invoke_sequence_range:,
      \stex_invoke_sequence_in:
    }
    TODO
  \end{sfunction}

\end{sfragment}


\begin{sfragment}{Optional (Key-Value) Argument Handling}
  \LaTeX3 is surprisingly weak when it comes to handling
  optional (key-val) arguments in such a manner that
  \emph{only} the freshly set macros are defined, and to modularly
  build up sets of argument keys. The following macros attempt
  to fix that:

  \begin{sfunction}{stex_keys_define:nnnn,stex_keys_set:nn}{\stex_keys_define:nnnn,\stex_keys_set:nn}
    \begin{syntax}
      \dcs\marg{id}\marg{setup code}
        \marg{keyval setup code}\marg{parents}
    \end{syntax}
    Defines a set of keys and their allowed values with 
    identifier |stex/|\meta{id}, that inherits from
    the sets with identifiers in \meta{parents}.

    \dcs[stex_keys_set:nn]\marg{id}\marg{CSL} first executes
    \meta{setup code} (e.g. to empty the macros holding the values) 
    and then sets the keys in
    set \meta{id} with the values provided in \meta{CSL}.
  \end{sfunction}

  \stexvarmacro{l_stex_key_id_str}

  \begin{sfunction}{_stex_do_id:}{\_stex_do_id:}
    should be called whenever a macro or environment has a label id,
    i.e. calls \cs{stex_keys_set:nn}|{id}{...}|, after
    the title has been typeset. Sets a \cs{label} by calling
    \cs{stex_ref_new_doc_target:n}\marg{id}.
  \end{sfunction}

  \begin{sexample}
    If we define a set of keys with:
    \stexvarmacro{l_stex_key_archive_str}
    \stexvarmacro{l_stex_key_file_str}
    \begin{stexcode}[gobble=6]
      |\cs{stex_keys_define:nnnn}|{archive file}{
        \str_clear:N |\cs{l_stex_key_archive_str}|
        \str_clear:N |\cs{l_stex_key_file_str}|
      }{
        archive .str_set_x:N = |\cs{l_stex_key_archive_str}| ,
        file    .str_set_x:N = |\cs{l_stex_key_file_str}|
      }{id}
    \end{stexcode}
    then calling \cs{stex_keys_set:nn}|{archive file}{id=foo,file=bar}|
    sets \cs{l_stex_key_file_str}|={bar}|, assures that
    \cs{l_stex_key_archive_str} is empty, and executes the
    code associated with |id|, i.e. it sets
    \cs{l_stex_key_id_str}|={foo}|.
  \end{sexample}

\end{sfragment}

\begin{sfragment}{Stylable Commands and Environments}

  \stexmacro{stex_style_apply:}

  \begin{sfunction}{stex_new_stylable_cmd:nnnn,l_stex_key_style_clist}{\stex_new_stylable_cmd:nnnn}
    \begin{syntax}
      \dcs\marg{name}\marg{arity}\marg{code}
        \marg{default}
    \end{syntax}
    Creates a new macro \cs{}\meta{name} with expansion \meta{code} taking 
    \meta{arity} many arguments, that is customizable in presentation 
    by a user by calling \cs{stexstyle}\meta{name}.
    On calling
    \cs{stex_style_apply:} executes the presentation code provided
    by a user.

    \meta{code} should:
    \begin{itemize}
      \item Call \cs{stex_keys_set:nn}|{style}{...}| (or a keyset inheriting
        from |style|),
      \item set macros with prefix |\this...| that a user might want
        to use for presentation (e.g. \cs{thistitle}),
      \item call \cs{stex_style_apply:} at some point.
    \end{itemize}
  \end{sfunction}

  \begin{sfunction}{stex_new_stylable_env:nnnnnnn}{\stex_new_stylable_env:nnnnnnn}
    \begin{syntax}
      \dcs\marg{name}\marg{arity}\marg{begincode}
        \marg{endcode}\marg{default begin}\marg{default end}\marg{prefix}
    \end{syntax}

    Like \cs{stex_new_stylable_cmd:nnnn}, but defines a new environment
    |{|\meta{prefix}\meta{name}|}| stylable via
    \cs{stexstyle}\meta{name}. Should call \cs{stex_style_apply:} twice;
    once in the \meta{begincode} and once in \meta{endcode}.
  \end{sfunction}

  \begin{sfunction}{stex_style_apply:}{\stex_style_apply:}
    Sets \cs{thisstyle} to be the head of the CSL
    \cs{l_stex_key_style_clist} and checks whether a style
    for the current stylable macro/environment has been defined;
    if not, executes the code for the default style.
  \end{sfunction}

  \begin{sexample}
    \cs{importmodule} is defined something like the following:
    \begin{stexcode}[gobble=6]
      |\cs{stex_new_stylable_cmd:nnnn}|{importmodule}{O{} m}{
        ... 
        \def|\cs{thismoduleuri}|{...}
        \def|\cs{thismodulename}|{...}
        |\cs{stex_style_apply:}|
        ...
      }{}
    \end{stexcode}
    A user can then customize the output generated by \cs{importmodule}
    (by default none) via 
    \cs{stexstyleimportmodule}|{...|\cs{thismodulename}|...}|.
  \end{sexample}

  \begin{sexample}
    \env{smodule} does something like
    \begin{stexcode}[gobble=6]
      |\cs{stex_new_stylable_env:nnnnnnn}|{module}{O{} m}{
        ... 
        \def|\cs{thismoduleuri}|{...}
        \def|\cs{thismodulename}|{...}
        |\cs{stex_style_apply:}|
        ...
      }{
        ...
        |\cs{stex_style_apply:}|
        ...
      }{}{}{s}
    \end{stexcode}
    which defines the environment name to be \env{smodule} and
    generates \cs{stexstylemodule}.
  \end{sexample}

\end{sfragment}

\begin{sfragment}{Math Archives}
  Math archives are represented as \LaTeX3 property lists,
  the keys/values of which correspond to the entries in the
  archive's manifest file. The most important fields are
  \begin{itemize}
    \item |id|,
    \item |narr| the document namespace,
    \item |ns| the content namespace, and
    \item |docurl| the document URL base.
  \end{itemize}

  \stexvarmacro{target}
  \begin{sfunction}{stex_resolve_path_pair:Nnn}{\stex_resolve_path_pair:Nnn,\stex_resolve_path_pair:Nxx}
      \begin{syntax}\dcs\marg{\cs{target}}\marg{archive-id}\marg{pathstring}
      \end{syntax}
      computes the absolute file path of
      \meta{pathstring} relative
      to the |source|-folder of \meta{archive-id} (if non-empty), 
      or the current archive (if existent) or the parent working 
      directory (otherwise), and stores the result in \cs{target}.
  \end{sfunction}

  \begin{svariable}{l_stex_current_archive_prop}{\l_stex_current_archive_prop}
    \dcs always points to the current math archive or is \cs{undefined},
    if the current file is not part of a math archive.
  \end{svariable}

  \begin{svariable}{c_stex_main_archive_prop}{\c_stex_main_archive_prop}
    \dcs represents the math archive in which the main file
    resides (if existent).
  \end{svariable}

  \begin{sfunction}{stex_require_archive:n}{\stex_require_archive:n,\stex_require_archive:o}
    \begin{syntax}\dcs\marg{id}
    \end{syntax}
    looks for a math archive \meta{id} in the MathHub directory,
    parses its manifest file, creates the corresponding property
    list |\c_stex_mathhub_|\meta{id}|_manifest_prop|,
    and throws a fatal error if the archive is not found.

    If the archive has been found and parsed before, does nothing,
    so it is cheap and safe to call repeatedly for the same id.
  \end{sfunction}

  \begin{sfunction}{stex_set_current_archive:n}{\stex_set_current_archive:n}
    \begin{syntax}\dcs\marg{id}
    \end{syntax}
    Calls \cs{stex_require_archive:n}\marg{id} and sets
    \cs{l_stex_current_archive_prop}.
  \end{sfunction}

  \begin{sfunction}{stex_in_archive:nn}{\stex_in_archive:nn}
    \begin{syntax}\dcs\marg{opt-id}\marg{code}
    \end{syntax}
    Executes \meta{code} in the context of math archive \meta{opt-id}
    (using \cs{stex_require_archive:n}), i.e.
    iff \meta{opt-id} is non-empty, changes the current archive
    to the one with id \meta{opt-id},
    call \meta{code} with \meta{opt-id} as argument (in |#1|) and changes
    it back afterwards.

    If \meta{opt-id} is empty, \meta{code} is called with the id
    of the \emph{current} math archive as |#1|, or with |#1| empty
    if there is no current math archive.
  \end{sfunction}

\end{sfragment}

\begin{sfragment}{SMS-Mode}
  \stex has to extract formal content (i.e. modules and their symbols)
  from \LaTeX-files, that may otherwise contain arbitrary
  code, including macros that may not be defined unless
  the file is fully processed by \TeX. Those
  modules and symbols also may depend on other modules that have not yet
  been loaded. The naive way to achieve this, which would
  be to just suppress output (e.g. by storing it in a box register)
  and then \cs{input} the required file, does not work thanks to
  \TeX's limited \emph{file stack}, which would overflow quickly
  for modules that have a deeply nested list of dependencies.

  To solve those problems, \sTeX reads dependencies in what we call
  \emph{sms mode}, which can be summarized thusly:
  \begin{itemize}
    \item In a first pass, we parse the file token by token, ignoring everything
      other than a select list of macros and environments that
      introduce dependencies (such as \cs{importmodule} and
      \cs{begin}|{|\env{smodule}|}[sig=...]|). Instead of loading
      those, we remember them for later.
    \item After the file as been fully parsed thusly, the
      dependencies found are loaded, again in sms-mode.
    \item In a second pass, we parse the file \emph{again} in the same way, but
      this time execute all macros that are explicitly allowed
      in sms mode, such as \cs{importmodule}, \cs{symdecl},
      \cs{notation}, \cs{symdef}, etc.
    \item all this parsing happens additionally in a
      \cs{setbox}\cs{throwaway}\cs{vbox}|{...}|-block to
      suppress any accidental output.
  \end{itemize}
  This means that \TeX's input stack never grows by more
  than $+1$, but still behaves \emph{as if} the dependencies
  were loaded recursively, at the detriment of being somewhat slow.

  \begin{sfunction}{stex_if_smsmode:}[pTF]{\stex_if_smsmode:}
    tests for whether we are currently in sms-mode.
  \end{sfunction}

  \begin{sfunction}{stex_file_in_smsmode:nn}{\stex_file_in_smsmode:nn,\stex_file_in_smsmode:on}
    \begin{syntax}\dcs\marg{filestring}\marg{setup-code}\end{syntax}
    sets up sms-mode and internal grouping, calls 
    \meta{setup-code} and subsequently processes the file
    \meta{filestring} in sms-mode as described above.
  \end{sfunction}

  \begin{sfragment}{Second Pass}

  \stexvarmacro{macro}

  \begin{sfunction}{stex_sms_allow:N}{\stex_sms_allow:N}
    \begin{syntax}\dcs\marg{\cs{macro}}\end{syntax}
    registers the \cs{macro}-command to be allowed in sms mode.

    This only works, if \cs{macro} takes no arguments and/or
    does not touch the subsequent tokens.
  \end{sfunction}

  For macros taking arguments, we can use

  \stexmacro{stex_smsmode_do:}

  \begin{sfunction}{stex_sms_allow_escape:N}{\stex_sms_allow_escape:N}
    \begin{syntax}\dcs\marg{\cs{macro}}\end{syntax}
    registers the \cs{macro}-command to be allowed in sms mode.

    If \cs{macro} is subsequently encountered in sms-mode,
    parsing is halted and \cs{macro} can process arguments as desired.
    It then needs to continue parsing manually though, by calling
    \cs{stex_smsmode_do:} as (usually) its last token.
  \end{sfunction}

  \begin{sfunction}{stex_sms_allow_env:n}{\stex_sms_allow_env:n}
    \begin{syntax}\dcs\marg{envname}\end{syntax}
    registers the environment \meta{envname} to be allowed in sms mode.

    As with \cs{stex_sms_allow_escape:N}, the \cs{begin}|{|\meta{envname}|}|
    is escaped, hence the begin-code of the environment needs to call
    \cs{stex_smsmode_do:}. Since 
    \cs{end}|{|\meta{envname}|}| never takes arguments, it does not
    need to be escaped.
  \end{sfunction}

  \begin{sfunction}{stex_smsmode_do:}{\stex_smsmode_do:}
    continues with sms-mode-style parsing. Does nothing if not in
    sms-mode, and is therefore safe to be called ``just in case''.
  \end{sfunction}

  \end{sfragment}
  \begin{sfragment}{First Pass}

  \stexmacro{g_stex_sms_import_code}
  \begin{sfunction}{stex_sms_allow_import:Nn,stex_sms_allow_import_env:nn}{\stex_sms_allow_import:Nn,\stex_sms_allow_import_env:nn}
    behave like \cs{stex_sms_allow_escape:N} and
    \cs{stex_sms_allow_env:n} respectively, but the macro or environment
    provided is now allowed in the \emph{first} pass of sms-mode.

    This macro should process arguments, add content to
    \cs{g_stex_sms_import_code}, and finally call \cs{stex_smsmode_do:}.

    The code provided in the \emph{second} argument is called
    before the first pass of sms-mode, as to set up functionality
    for these macros. For example, \cs{importmodule}
    provides code that redefines \cs{importmodule} to
    store the identified dependency in 
    \cs{g_stex_sms_import_code} instead of activating it directly.
  \end{sfunction}

  \begin{svariable}{g_stex_sms_import_code}{\g_stex_sms_import_code}
    is built up in the first pass of sms mode and called subsequently;
    before the second pass.

    Code in this token list should load and activate dependencies
    found in the first pass.
  \end{svariable}

  \end{sfragment}

\end{sfragment}

\begin{sfragment}{Strings, File Paths, URIs}

  \begin{sfunction}{stex_str_if_starts_with:nn}[pTF]{\stex_str_if_starts_with:nn}
    \begin{syntax}\dcs\marg{first}\marg{second}
    \end{syntax}
      Checks whether the string \meta{first} starts with the string
      \meta{second} (i.e. \meta{second} is a prefix of \meta{first}).
  \end{sfunction}

  \begin{sfunction}{stex_str_if_ends_with:nn}[pTF]{\stex_str_if_ends_with:nn}
    \begin{syntax}\dcs\marg{first}\marg{second}
    \end{syntax}
      Checks whether the string \meta{first} ends with the string
      \meta{second} (i.e. \meta{second} is a suffix of \meta{first}).
  \end{sfunction}

  \begin{sfragment}{File Paths}

  \emph{File paths} are represented as \LaTeX3 sequences. The following
  methods make sure to
  \begin{itemize}
    \item canonicalize paths, i.e. resolve |..| and |.| segments,
    \item set all category codes to 12 (other), and
    \item tranform windows file paths containing |\| uniformly to |/|.
  \end{itemize}

  \stexvarmacro{macro}
  \begin{sfunction}{stex_file_resolve:Nn}{\stex_file_resolve:Nn, \stex_file_resolve:No, \stex_file_resolve:Nx}
    \begin{syntax}\dcs\marg{\cs{macro}}\marg{string}
    \end{syntax}
    resolves and canonicalizes the file path string \meta{string} and
    stores the result in \cs{macro}. 
  \end{sfunction}

  \begin{sfunction}{stex_file_set:Nn}{\stex_file_set:Nn, \stex_file_set:No, \stex_file_set:Nx}
    \begin{syntax}\dcs\marg{\cs{macro}}\marg{string}
    \end{syntax}
    represents an already canonicalized file path string as a
    \LaTeX3 sequence and stores it in \cs{macro}.
  \end{sfunction}

  \begin{sfunction}{stex_if_file_absolute:N}[pTF]{\stex_if_file_absolute:N}
    \dcs tests whether the given file path (represented as a canonicalized
    \LaTeX3 sequence) is an absolute file path.
  \end{sfunction}

  \begin{sfunction}{stex_file_use:N}[EXP]{\stex_file_use:N}
    \dcs expands to a string representation of the given file path.
  \end{sfunction}

  \stexvarmacro{first}
  \stexvarmacro{second}
  \begin{sfunction}{stex_if_file_starts_with:NN}[TF]{\stex_if_file_starts_with:NN}
    \begin{syntax}\dcs\marg{\cs{first}}\marg{\cs{second}}
    \end{syntax}
    tests whether the file path \cs{first} is a child of \cs{second}.
    \emph{(Not expandable)}
  \end{sfunction}

  \stexvarmacro{source}
  \stexvarmacro{target}
  \begin{sfunction}{stex_file_split_off_ext:NN}{\stex_file_split_off_ext:NN}
    \begin{syntax}\dcs\marg{\cs{target}}\marg{\cs{source}}
    \end{syntax}
    splits off the file extension of \cs{source} and stores the resulting
    file path in \cs{target}
  \end{sfunction}

  \begin{sfunction}{stex_file_split_off_lang:NN}{\stex_file_split_off_lang:NN}
    \begin{syntax}\dcs\marg{\cs{target}}\marg{\cs{source}}
    \end{syntax}
    checks whether the file path \cs{source} ends with a language
    abbreviation (e.g. |.en|), if so removes it, and stores the result
    in \cs{target}.
  \end{sfunction}

  The following are primarily used in file hooks,
  but might occasionally be useful to call manually:

  \stexmacro{g_stex_current_file}
  \stexmacro{c_stex_main_file}

  \begin{sfunction}{stex_filestack_push:n}{\stex_filestack_push:n}
    pushes the given file to the file stack, recomputing
    \cs{g_stex_current_file}, the current language,
    document URI and namespace.
  \end{sfunction}

  \begin{sfunction}{stex_filestack_pop:}{\stex_filestack_pop:}
    pops the current top entry of the file stack. If the file stack
    is empty, resets to \cs{c_stex_main_file}.
  \end{sfunction}

  \begin{sfragment}{File Path Constants and Variables}

    \begin{svariable}{c_stex_pwd_file,c_stex_main_file}{\c_stex_pwd_file,\c_stex_main_file}
      store the parent working directory and
      the absolute path of the main file being processed
      (with guessed file extension |.tex|).
    \end{svariable}
  
    \begin{svariable}{c_stex_home_file}{\c_stex_home_file}
      stores the user's home directory.
    \end{svariable}
  
    \begin{svariable}{c_stex_mathhub_file}{\c_stex_mathhub_file}
      stores the user's MathHub directory;
      its string representation is stored in \cs{mathhub}.
    \end{svariable}
  
    \begin{svariable}{g_stex_current_file}{\g_stex_current_file}
      always points to the \emph{current} file.
    \end{svariable}

  \end{sfragment}

  \end{sfragment}

  \begin{sfragment}{URIs}

    \stexmacro{__stex_path_auth:n}
    \stexmacro{__stex_path_path:n}
    \stexmacro{__stex_path_module:n}
    \stexmacro{__stex_path_name:n}
    \stexmacro{stex_uri_resolve:Nn}
    \begin{sparagraph}[style=symdoc,for={__stex_path_auth:n,%
      __stex_path_path:n,__stex_path_module:n,__stex_path_name:n}]
      \mmt URIs are represented
      as token lists of the form

      |{|\cs{__stex_path_auth:n}\marg{authority}
      \cs{__stex_path_path:n}\marg{path}
      \cs{__stex_path_module:n}\marg{modulename}
      \cs{__stex_path_name:n}\marg{declname}|}|,

      all of which may be empty. Largely, URIs are used as strings only,
      but the above representation is used in \cs{stex_uri_resolve:Nn}
      to canonicalize URIs when they are computed the first time.

    \end{sparagraph}

    \stexvarmacro{uri}
    \begin{sfunction}{stex_map_uri:Nnnnn}{\stex_map_uri:Nnnnn}
      \begin{syntax}
        \dcs\marg{\cs{uri}}\marg{authority code}
        \marg{path code}\marg{modulename code}\marg{declname code}
      \end{syntax}
      executes the provided \meta{code}s with the components
      of the \cs{uri} as arguments.
    \end{sfunction}

    \begin{sfunction}{stex_uri_resolve:Nn}{\stex_uri_resolve:Nn, \stex_uri_resolve:No, \stex_uri_resolve:Nx}
      behaves analogously to \cs{stex_file_resolve:Nn}.
    \end{sfunction}

    \begin{sfunction}{stex_uri_set:Nn}{\stex_uri_set:Nn, \stex_uri_set:No, \stex_uri_set:Nx}
      behaves analogously to \cs{stex_file_set:Nn}.
    \end{sfunction}

    \begin{sfunction}{stex_uri_use:N}[EXP]{\stex_uri_use:N}
      behaves analogously to \cs{stex_file_use:N}.
    \end{sfunction}

    A common usage of URIs is computing the namespace of content
    elements (modules or documents) from the namespace of a math
    archive and some relative file path within that archive.

    \stexvarmacro{target}
    \stexvarmacro{repo_prop}
    \stexvarmacro{filepath}
    \begin{sfunction}{stex_uri_from_repo_file:NNNn}{\stex_uri_from_repo_file:NNNn}
      \begin{syntax}
        \dcs\marg{\cs{target}}\marg{\cs{repo_prop}}\marg{\cs{filepath}}
        \marg{ns\_field}
      \end{syntax}
      computes the namespace URI from the property list
      \cs{repo_prop} of some math archive, the file path
      \cs{filepath} and the archive field \marg{ns\_field}
      (|narr| or |ns|), and stores the result in \cs{target}.
    \end{sfunction}

    \begin{sfunction}{stex_uri_from_repo_file_nolang:NNNn}{\stex_uri_from_repo_file_nolang:NNNn}
      behaves like \cs{stex_uri_from_repo_file:NNNn}, but makes 
      sure
      to split off language abbreviations from the file name
      (e.g. |.en|).
    \end{sfunction}

    \begin{sfunction}{stex_uri_from_current_file:Nn, stex_uri_from_current_file_nolang:Nn}{\stex_uri_from_current_file:Nn, \stex_uri_from_current_file_nolang:Nn}
      Special cases for \cs{stex_uri_from_repo_file}|[_nolang]:NNNn|,
      for \cs{repo_prop}|=|\cs{l_stex_current_archive_prop} and
      \cs{filepath}|=|\cs{g_stex_current_file}.
    \end{sfunction}

    \stexmacro{l_stex_current_doc_uri}
    \begin{sfunction}{stex_set_document_uri:}{\stex_set_document_uri:}
      sets the current value of \cs{l_stex_current_doc_uri} based
      on the current file and archive.
    \end{sfunction}

    \stexmacro{l_stex_current_ns_uri}
    \begin{sfunction}{stex_set_current_namespace:}{\stex_set_current_namespace:}
      sets the current value of \cs{l_stex_current_ns_uri} based
      on the current file and archive.
    \end{sfunction}

    \begin{sfunction}{stex_uri_add_module:NNn}{\stex_uri_add_module:NNn, \stex_uri_add_module:NNo}
      \begin{syntax}
        \dcs\marg{\cs{target}}\marg{\cs{uri}}
          \marg{name}
      \end{syntax}
      Checks that URI \cs{uri} has no module name, adds the provided
      \meta{name} and stores the result in \cs{target}.
    \end{sfunction}

  \begin{sfragment}{URI Constants and Variables}

    \begin{svariable}{l_stex_current_doc_uri}{\l_stex_current_doc_uri}
      always points to the current document URI.
    \end{svariable}

    \begin{svariable}{l_stex_current_ns_uri}{\l_stex_current_ns_uri}
      always points to the current content namespace.
    \end{svariable}

  \end{sfragment}
    
  \end{sfragment}

\end{sfragment}

\begin{sfragment}{Language Handling}
  \begin{svariable}{c_stex_languages_prop,c_stex_language_abbrevs_prop}{\c_stex_languages_prop,\c_stex_language_abbrevs_prop}
    Property lists converting babel languages to/from their abreviations;
    e.g.
    \begin{itemize}
      \item |\prop_item:Nn |\cs{c_stex_languages_prop}| {de}| yields |ngerman|, and 
      \item \cs{c_stex_language_abbrevs_prop}| {ngerman}| yields |de|.
    \end{itemize}  
  \end{svariable}

  \begin{svariable}{l_stex_current_language_str}{\l_stex_current_language_str}
    always stores the current language.
  \end{svariable}

  \begin{sfunction}{stex_set_language:n}{\stex_set_language:n, \stex_set_language:x, \stex_set_language:o}
    \begin{syntax}\dcs\marg{abbrev}\end{syntax}
    Sets \cs{l_stex_current_language_str}, and, if the \pkg{babel}
    package is loaded, calls \cs{selectlanguage} on the
    language corresponding to \marg{abbrev}.

    Note that the package option |lang=| automatically loads the
    \pkg{babel} package.

    If \meta{abbrev}|=tr|, additionally call \cs{selectlanguage}
    with the option |shorthands=:!|.

    Throws |error/unknownlanguage| if no language with abbreviation
    \marg{abbrev} is known.
  \end{sfunction}

  \begin{sfunction}{stex_language_from_file:}{\stex_language_from_file:}
    infers the current language from file ending (e.g. |.en.tex|)
    and sets it appropriately.

    Is called in a file hook, i.e. always switches language when inputting
    a file |.<lang>.<ext>|.
  \end{sfunction}

\end{sfragment}

\begin{sfragment}{Inserting Annotations}
  \stex can be used to produce either \HTML or \PDF. In \HTML-mode,
  multiple macros exist to insert annotations. The same macros
  are also valid in \PDF mode but implemented as null operations.

  \begin{sfunction}{stex_suppress_html:n}{\stex_suppress_html:n}
    \begin{syntax}\dcs\marg{code}\end{syntax}
    turns annotations off temporarily in \meta{code} (e.g. as to not 
    generate additional annotations for elaborated declarations, 
    or in sms-mode).
  \end{sfunction}

  For that to work, code that inserts annotations should use
  \begin{sfunction}{stex_if_do_html:}[pTF]{\stex_if_do_html:}
    tests whether to generate \HTML annotations.
  \end{sfunction}

  \begin{sfunction}{stex@backend}{\stex@backend}
    should be set by a backend engine, such that a file
    |stex-backend-|\dcs{}|.cfg| exists.
  \end{sfunction}

  \begin{sfragment}{Backend macros}

  Such a backend config file should provide the following:

  \begin{sfunction}{stex_if_html_backend:}[pTF]{\stex_if_html_backend:}
    can be used to determine whether the backend produces \HTML (e.g.
    \rustex or \LaTeXML) or not (e.g. |pdflatex|).
    
    \cs{ifstexhtml} is set accordingly.
  \end{sfunction}

  \begin{sfunction}{stex_annotate:nnn}{\stex_annotate:nnn}
    \begin{syntax} \dcs\marg{attr}\marg{value}\marg{code}
    \end{syntax}
    In \HTML mode, annotates the output of \meta{code} with the 
    \XML-attribute \meta{attr}|="|\meta{value}|"|. In \PDF mode, just
    calls \meta{code}.
  \end{sfunction}

  \begin{sfunction}{stex_annotate_invisible:nnn,stex_annotate_invisible:n}{\stex_annotate_invisible:nnn,\stex_annotate_invisible:n}
    \begin{syntax} \dcs[stex_annotate_invisible:n]\marg{code}
    \end{syntax}

    Should annotate \meta{code} with
    |shtml:visible="false" style="display:none;"|. In \PDF mode, does 
    nothing.

    \dcs combines \cs{stex_annotate_invisible:n}
    and \cs{stex_annotate:nnn}.
  \end{sfunction}


  \begin{senv}{stex_annotate_env}
    \cs{begin}|{|\denv|}|\marg{attr}\marg{value}
    \meta{code}
    \cs{end}|{|\denv|}| should behave
    like \cs{stex_annotate:nnn}\marg{attr}\marg{value}\marg{code}
  \end{senv}

  \begin{sfunction}{stex_mathml_intent:nn,stex_mathml_arg:nn}{\stex_mathml_intent:nn,\stex_mathml_arg:nn}
    MathML Intent (TODO)
  \end{sfunction}

  \end{sfragment}

\end{sfragment}

\begin{sfragment}{Persisting Content from Math Archives in sms-Files}

  \begin{sfunction}{stex_persist:n}{\stex_persist:n,\stex_persist:e}
    \begin{syntax}\dcs\marg{code}\end{syntax}
    writes \meta{code} to the \cs{jobname}|.sms|-file, if
    |writesms| is active.

    \begin{texnote}
      \meta{code} is being read with \pkg{expl3} category
      codes (except for spaces having catcode 10), 
      but not pretokenized; i.e. \meta{code} can safely
      change the current catcode scheme.
    \end{texnote}
  \end{sfunction}


  \begin{svariable}{c_stex_persist_mode_bool,c_stex_persist_write_mode_bool}{
    \c_stex_persist_mode_bool,\c_stex_persist_write_mode_bool
  }
    whether |usesms| or |writesms| are active.
  \end{svariable}

\end{sfragment}


\begin{sfragment}{Utility Methods}

  \stexvarmacro{foo}
  \begin{sfunction}{stex_macro_body:N}[EXP]{\stex_macro_body:N}
    expands to the \emph{expansion} of the provided macro,
    including parameter tokens, with the original category codes intact; 
    e.g. if \cs{def}\cs{foo}|#1{First #1}|,
    then \dcs\cs{foo} expands to
    |First #1|.
  \end{sfunction}

  \begin{sfunction}{stex_macro_definition:N}[EXP]{\stex_macro_definition:N}
    expands to the token list \emph{defining} the provided macro,
    including parameters, command attributes (i.e. \cs{long}, 
    \cs{protected}), with the original category codes intact; 
    e.g. if \cs{protected}\cs{def}\cs{foo}|#1{First #1}|,
    then \dcs\cs{foo} expands to
    \cs{protected}\cs{def}\cs{foo}|#1{First #1}|.

    \begin{texnote} Does not work with ``higher'' parameter
    tokens, i.e. |##1|, |####1| etc.\end{texnote}
  \end{sfunction}

  \stexvarmacro{macro}
  \begin{sfunction}{stex_deactivate_macro:Nn, stex_reactivate_macro:N}{\stex_deactivate_macro:Nn, \stex_reactivate_macro:N}
    \begin{syntax}\dcs \marg{\cs{macro}} \marg{msg}
    \end{syntax}
    Makes \cs{macro} throw an error message |error/deactivated-macro|\marg{msg},
    notifying an author that the macro is only allowed in certain environments.

    \dcs[stex_reactivate_macro:N] restores the functionality of the macro.
  \end{sfunction}

  \begin{sfunction}{stex_kpsewhich:Nn}{\stex_kpsewhich:Nn}
    \begin{syntax}
      \dcs \marg{\cs{macro}} \marg{args}
    \end{syntax}
    Calls ``|kpsewhich| \meta{args}'' and stores the result
    in \cs{macro},
%^^A     Foo
    \begin{texnote} 
      Does not require |shell-escape|
    \end{texnote}
%^^A
%^^A
%^^A     \begin{arguments}
%^^A       \item Narf?
%^^A     \end{arguments}
%^^A
  \end{sfunction}

  \begin{sfunction}{stex_get_env:Nn}{\stex_get_env:Nn}
    \begin{syntax}
      \dcs \marg{\cs{macro}} \marg{envvar}
    \end{syntax}
    Stores the value of the environment variable \meta{envvar}
    in \cs{macro}.
  \end{sfunction}

  \begin{sfunction}{stex_fatal_error:n}{\stex_fatal_error:n,\stex_fatal_error:nnn,\stex_fatal_error:nxx}
    Mimic the \cs{msg_error:}-macros, but make sure that \TeX\ stops
    processing.
    \begin{texnote} 
      Calls |\input{non-existent file}|.
    \end{texnote}
  \end{sfunction}

  \begin{sfunction}{stex_ignore_spaces_and_pars:}{\stex_ignore_spaces_and_pars:}
    As the name suggests, ignores all subsequent spaces and \cs{par}s
    until the first non-expandable macro is encountered.

    Useful for e.g. ending \cs{symdecl} and related macros with,
    so that formatting sources with empty lines does not cause 
    paragraph breaks.
  \end{sfunction}

  \begin{sfragment}{Group-like Behaviours}

    \begin{sfunction}{stex_pseudogroup_with:nn}{\stex_pseudogroup_with:nn}
      \begin{syntax}\dcs\marg{macros}\marg{code}
      \end{syntax}
      Calls \meta{code} and subsequently restores the values of the
      \meta{macros} given.
      \begin{texnote}
        Does \emph{not} work recursively!
      \end{texnote} 
    \end{sfunction}

    \stexmacro{stex_pseudogroup_restore:N}

    \begin{sfunction}{stex_pseudogroup:nn}{\stex_pseudogroup:nn}
      \begin{syntax}\dcs\marg{code1}\marg{code2}
      \end{syntax}
      Expands \meta{code2}, and inserts the result after \meta{code1}. 
      Works recursively and
      allows for restoring the values of macros in combination with
      \cs{stex_pseudogroup_restore:N}, but \emph{only for macros
      that take no arguments}:
    \end{sfunction}

    \begin{sfunction}{stex_pseudogroup_restore:N}[EXP]{\stex_pseudogroup_restore:N}
      \begin{syntax}\dcs\marg{\cs{macro}}
      \end{syntax}
    \end{sfunction}

    \begin{sexample}
      \stexvarmacro{foo}
      \stexvarmacro{num}
      \begin{stexcode}[gobble=8]
        |\cs{stex_pseudogroup:nn}|{
          something changing |\cs{foo}|
          something changing |\cs{num}|
        }{
          |\cs{stex_pseudogroup_restore:N}\cs{foo}|
          \int_set:Nn |\cs{num}| {\int_use:N |\cs{num}|}
        }
      \end{stexcode}
      restores the values of macro \cs{foo} and register \cs{num}
      after calling the first block.
    \end{sexample}

    Commands like \cs{symdecl} and \cs{importmodule} that generate
    (semantic) macros should be local \emph{to the current module},
    e.g. \env{smodule}. For that purpose, we open a new ``metagroup''
    with some identifier (e.g. \cs{l_stex_current_module_str})
    and then execute the relevant code \emph{in the metagroup with that
    identifier}:
    
    \begin{sfunction}{stex_metagroup_new:n}{\stex_metagroup_new:n, \stex_metagroup_new:o}
      \begin{syntax}\dcs \marg{id}\end{syntax}
      Opens a new metagroup at the current \TeX\ group level with
      identifier \meta{id}.
    \end{sfunction}

    \begin{sfunction}{stex_metagroup_do_in:nn}{\stex_metagroup_do_in:nn, \stex_metagroup_do_in:nx}
      \begin{syntax}\dcs \marg{id}\marg{code}\end{syntax}
      Executes \meta{code} and adds its content to \cs{aftergroup} up
      until the \TeX\ group level of the metagroup with identifier 
      \meta{id}.
    \end{sfunction}

  \end{sfragment}

\end{sfragment}

\end{smodule}

%^^A^^A   \begin{TemplateInterfaceDescription}{foo}
%^^A^^A     \TemplateArgument{1}{Something Here}
%^^A^^A     \TemplateSemantics{Some Narf Here}
%^^A^^A   \end{TemplateInterfaceDescription}
%^^A^^A   \begin{TemplateDescription}{foo}{bar}
%^^A^^A     \TemplateKey{narf}{Something Here}
%^^A^^A     \TemplateSemantics{Some Narf Here}
%^^A^^A   \end{TemplateDescription}
%^^A^^A   \begin{InstanceDescription}{foo}{newinst}{bar}
%^^A^^A     \InstanceKey{narf}{Something Here}
%^^A^^A     \InstanceSemantics{Some Narf Here}
%^^A^^A   \end{InstanceDescription}
%^^A^^A   \cs{stex_kpsewhich:Nn}
%^^A   \begin{function}{\stex_kpsewhich:Nn}
%^^A     Foo
%^^A     \begin{texnote} Foo! \end{texnote}
%^^A
%^^A     \begin{syntax} \cs{stex_kpsewhich:Nn} \meta{something} \Arg{argh}
%^^A     \end{syntax}
%^^A
%^^A     \begin{arguments}
%^^A       \item Narf?
%^^A     \end{arguments}
%^^A
%^^A   \end{function}