%^^A meta-comment
%^^A  An Infrastructure for Semantic Macros and Module Scoping
%^^A  Copyright (c) 2022 Michael Kohlhase, all rights reserved
%^^A                 this file is released under the
%^^A                 LaTeX Project Public License (LPPL)
%^^A  
%^^A  The original of this file is in the public archive at 
%^^A  http://github.com/sLaTeX/sTeX/
%^^A 
% \iffalse
%<*driver>
\def\stexdocpath{../doc}
\input{\stexdocpath/stex-docheader}
\stextoptitle{The \sTeX Package}{stex}
\docmodule
%</driver>
% \fi
%
%
% \begin{stexmanual}
% \end{stexmanual}
%
% \begin{documentation}
%    \begin{sfragment}{\sTeX Developer Manual}
%      \input{\stexdocpath/stex-devel}
%    \end{sfragment}
% \end{documentation}
%
% \begin{implementation}
%  \begin{sfragment}{The \sTeX Implementation}
%
%   \begin{sfragment}{Setting up}
% Setup code for the document class
%    \begin{macrocode}
%<*cls>
%%%%%%%%%%%%%   stex.dtx   %%%%%%%%%%%%%

\RequirePackage{expl3,l3keys2e}
\ProvidesExplClass{stex}{2023/10/13}{3.4.0}{sTeX document class}
\IfFileExists{stex-expl-compat.sty}{
  \usepackage{stex-expl-compat}
}{}

\DeclareOption*{\PassOptionsToPackage{\CurrentOption}{stex}}
\ProcessOptions

\RequirePackage{stex}

\LoadClass{article}
%</cls>
%    \end{macrocode}
%
% Setup code for the package
%
%    \begin{macrocode}
%<*package>
\RequirePackage{expl3,l3keys2e,ltxcmds}
\ProvidesExplPackage{stex}{2023/10/13}{3.4.0}{sTeX package}
\IfFileExists{stex-expl-compat.sty}{
  \usepackage{stex-expl-compat}
}{}
\RequirePackage{stex-logo} % externalized for backwards-compatibility reasons
\RequirePackage{standalone}

\message{^^J*~This~is~sTeX~version~3.4.0~*^^J}
%    \end{macrocode}
%
% Package options:
%
%    \begin{macrocode}
\keys_define:nn { stex / package } {
  debug      .str_set_x:N  = \c_stex_debug_clist ,
  lang       .clist_set:N  = \c_stex_languages_clist ,
  mathhub    .tl_set_x:N   = \mathhub ,
  usesms     .bool_set:N   = \c_stex_persist_mode_bool ,
  writesms   .bool_set:N   = \c_stex_persist_write_mode_bool ,
  checkterms .bool_set:N   = \c_stex_check_terms_bool ,
  image      .bool_set:N   = \c_tikzinput_image_bool,
  nofrontmatter .bool_set:N = \c_stex_no_frontmatter_bool,
  unknown    .code:n       = {}
}
\exp_args:NNo \clist_set:Nn \c_stex_debug_clist \c_stex_debug_clist
\ProcessKeysOptions { stex / package }
%    \end{macrocode}
%
% Error messages:
%    \begin{macrocode}
\input{stex-en.ldf}
%    \end{macrocode}
%
% \end{sfragment}
%
% \begin{sfragment}{Utilities}
%
%    \begin{macrocode}
\cs_set_eq:NN \stex_undefined: \undefined
%    \end{macrocode}
%
% \begin{sfragment}{Calling kpsewhich and Environment Variables}
%
%    \begin{macrocode}
%<@@=stex_envs>
%    \end{macrocode}
%
% \begin{macro}{\stex_kpsewhich:Nn}
%    \begin{macrocode}
\cs_new_protected:Nn \stex_kpsewhich:Nn {\group_begin:
  \catcode`\ =12
  \sys_get_shell:nnN { kpsewhich ~ #2 } { } \l_tmpa_tl
  \tl_gset_eq:NN \l_tmpa_tl \l_tmpa_tl
  \group_end:
  \exp_args:NNo\str_set:Nn #1 {\l_tmpa_tl}
  \tl_trim_spaces:N #1
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\stex_get_env:Nn}
%    \begin{macrocode}
\sys_if_platform_windows:TF{
  \cs_new_protected:Nn \stex_get_env:Nn {\group_begin:
    \escapechar=-1\catcode`\\=12
    \exp_args:NNe \stex_kpsewhich:Nn #1 {-expand-var~\c_percent_str#2\c_percent_str}
    \exp_args:NNx\use:nn\group_end:{
      \str_set:Nn \exp_not:N #1 { #1 }
    }
  }
}{
  \cs_new_protected:Nn \stex_get_env:Nn {
    \stex_kpsewhich:Nn #1 {-var-value~#2}
  }
}
%    \end{macrocode}
% \end{macro}
%
% \end{sfragment}
%
% \begin{sfragment}{Logging}
%    \begin{macrocode}
%<@@=stex_debug>
%    \end{macrocode}
%
% \begin{macro}{\stex_debug:nn}
%    \begin{macrocode}
\cs_new_protected:Nn \stex_debug:nn {
  \exp_args:NNo \clist_if_in:NnTF \c_stex_debug_clist { \tl_to_str:n{all} }{
    \_@@_:nn{#1}{#2}
  }{
    \exp_args:NNo \clist_if_in:NnT \c_stex_debug_clist { \tl_to_str:n{#1} }{
      \_@@_:nn{#1}{#2}
    }
  }
}

\cs_new_protected:Nn \_@@_:nn {
  \msg_set:nnn{stex}{debug / #1}{
    \\Debug~#1:~#2\\
  }
  \msg_none:nn{stex}{debug / #1}
}
%    \end{macrocode}
% \end{macro}

% \begin{macro}{\stex_fatal_error:n,\stex_fatal_error:nnn,\stex_fatal_error:nxx}
%   To avoid dead locks etc., we throw errors and make tex stop
%   entirely:
%    \begin{macrocode}
\cs_new_protected:Nn \stex_fatal_error:n {
  \msg_error:nn{stex}{#1}\input{Fatal~Error!!}
}
\cs_new_protected:Nn \stex_fatal_error:nnn {
  \msg_error:nnn{stex}{#1}{#2}{#3}\input{Fatal~Error!!}
}
\cs_generate_variant:Nn \stex_fatal_error:nnn {nxx}
%    \end{macrocode}
% \end{macro}
%
% We check an environment variable for debugging and 
% set things up:
%
%    \begin{macrocode}
\stex_get_env:Nn\_@@_env_str{STEX_DEBUG}
\str_if_empty:NTF\_@@_env_str {
  \clist_set_eq:NN \l_@@_cl \c_stex_debug_clist
}{
  \clist_set:No \l_@@_cl {\_@@_env_str}
}
\clist_clear:N \c_stex_debug_clist
\clist_map_inline:Nn \l_@@_cl {
  \exp_args:NNo \clist_put_right:Nn \c_stex_debug_clist
  { \tl_to_str:n{#1} }
}

\exp_args:NNo \clist_if_in:NnTF \c_stex_debug_clist {\tl_to_str:n{all}} {
    \msg_redirect_module:nnn{ stex }{ none }{ warning }
    \stex_debug:nn{all}{Logging~everything!}
}{
  \clist_map_inline:Nn \c_stex_debug_clist {
    \msg_redirect_name:nnn{ stex }{ debug / #1 }{ warning }
    \stex_debug:nn{#1}{Logging~#1}
  }
}
%    \end{macrocode}
%
% \end{sfragment}
%
% \begin{sfragment}{Languages}
%    \begin{macrocode}
%<@@=stex_lang>
%    \end{macrocode}
%   \begin{variable}{\c_stex_languages_prop,\c_stex_language_abbrevs_prop}
%
% We store language abbreviations in two (mutually inverse) 
% property lists:
%    \begin{macrocode}
\exp_args:NNx \prop_const_from_keyval:Nn \c_stex_languages_prop { \tl_to_str:n {
  en = english ,
  de = ngerman ,
  ar = arabic ,
  bg = bulgarian ,
  ru = russian ,
  fi = finnish ,
  ro = romanian ,
  tr = turkish ,
  fr = french
}}

\exp_args:NNx \prop_const_from_keyval:Nn \c_stex_language_abbrevs_prop { \tl_to_str:n {
  english   = en ,
  ngerman   = de ,
  arabic    = ar ,
  bulgarian = bg ,
  russian   = ru ,
  finnish   = fi ,
  romanian  = ro ,
  turkish   = tr ,
  french    = fr
}}
% todo: chinese simplified (zhs)
%       chinese traditional (zht)
%    \end{macrocode}
% \end{variable}
%
% \begin{variable}{\l_stex_current_language_str}
%    \begin{macrocode}
\str_new:N \l_stex_current_language_str
%    \end{macrocode}
% \end{variable}
%
% we use the |lang|-package option to load the corresponding
% babel languages:
% \begin{macro}{\stex_set_language:n, \stex_set_language:x, \stex_set_language:o}
%    \begin{macrocode}
\cs_new_protected:Nn \stex_set_language:n {
  \str_set:Nn \l_stex_current_language_str { #1 }
  \prop_if_in:NnTF \c_stex_languages_prop {#1} {
    \tl_set_rescan:Nnx \l_@@_lang_str {}{\prop_item:Nn \c_stex_languages_prop {#1}}
    \cs_if_eq:NNTF\@onlypreamble\@notprerr{
      \ltx@ifpackageloaded{babel}{
        \exp_args:No\selectlanguage\l_@@_lang_str
      }{}
    }{
      \ltx@ifpackageloaded{babel}{}{
        \str_if_eq:nnTF {#1} {tr} {
          \RequirePackage[turkish,shorthands=:!]{babel}
        }{
          \RequirePackage[\l_@@_lang_str]{babel}
        }
      }
    }
  }{
    \msg_error:nnx{stex}{error/unknownlanguage}{#1}
  }
}
\cs_generate_variant:Nn \stex_set_language:n {x,o}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\stex_language_from_file:}
%    \begin{macrocode}
\cs_new_protected:Nn \stex_language_from_file: {
  \seq_get_right:NN \g_stex_current_file \l_tmpa_str
  \seq_set_split:NnV \l_tmpa_seq . \l_tmpa_str
  \seq_pop_right:NN \l_tmpa_seq \l_tmpa_str % = ".tex/.dtx/.sty"
  \exp_args:No \str_if_eq:nnF \l_tmpa_str {tex} {
    \exp_args:No \str_if_eq:nnF \l_tmpa_str {dtx} {
      \exp_args:No \str_if_eq:nnF \l_tmpa_str {ltx} {
        \exp_args:NNo \seq_put_right:Nn \l_tmpa_seq \l_tmpa_str
      }
    }
  }
  \seq_pop_left:NN \l_tmpa_seq \l_tmpa_str % <filename>
  \seq_if_empty:NF \l_tmpa_seq { %remaining element should be [<something>.]language
    \seq_pop_right:NN \l_tmpa_seq \l_@@_str
    \str_if_eq:NNF \l_@@_str \l_stex_current_language_str {
      \exp_args:NNo \prop_if_in:NnT \c_stex_languages_prop \l_@@_str {
        \stex_set_language:o \l_@@_str
      }
    }
    \stex_debug:nn{lang} {Language~\l_stex_current_language_str~
      inferred~from~file~name}
  }
}
%    \end{macrocode}
% \end{macro}
%
% Loading babel:
%    \begin{macrocode}
\clist_if_empty:NF \c_stex_languages_clist {
  \bool_set_false:N \l_@@_turkish_bool
  \seq_clear:N \l_tmpa_seq
  \clist_map_inline:Nn \c_stex_languages_clist {
    \str_set:Nx \l_tmpa_str {#1}
    \str_if_eq:nnT {#1}{tr}{
      \bool_set_true:N \l_@@_turkish_bool
    }
    \prop_get:NoNTF \c_stex_languages_prop \l_tmpa_str \l_tmpa_str {
      \tl_set_rescan:Nno \l_tmpa_str {} \l_tmpa_str
      \seq_put_right:No \l_tmpa_seq \l_tmpa_str
    } {
      \msg_error:nnx{stex}{error/unknownlanguage}{\l_tmpa_str}
    }
  }
  \stex_debug:nn{lang} {Languages:~\seq_use:Nn \l_tmpa_seq {,~} }
  \bool_if:NTF \l_@@_turkish_bool {
    \exp_args:NNe \use:nn \RequirePackage
      {[main=\seq_use:Nn \l_tmpa_seq, ,shorthands=:!]}{babel}
  }{
    \exp_args:NNe \use:nn \RequirePackage
      {[main=\seq_use:Nn \l_tmpa_seq, ]}{babel}
  }
}
%    \end{macrocode}
%
% \end{sfragment}
%
% \begin{sfragment}{Group-like Behaviours}
%    \begin{macrocode}
%<@@=stex_groups>
%    \end{macrocode}
%
%   \begin{macro}{\stex_pseudogroup:nn,\stex_pseudogroup_restore:N}
%    \begin{macrocode}
\cs_new_protected:Npn \stex_pseudogroup:nn {
  \exp_args:Nne \use:nn
}
\cs_new:Nn \stex_pseudogroup_restore:N {
  \tl_if_exist:NTF #1 {
    \tl_set:Nn \exp_not:N #1 { \exp_args:No \exp_not:n #1 }
  }{
    \cs_undefine:N \exp_not:N #1
  }
}
%    \end{macrocode}
%   \end{macro}
%
%   \begin{macro}{\stex_pseudogroup_with:nn}
%    \begin{macrocode}
\cs_new_protected:Nn \stex_pseudogroup_with:nn {
  \tl_map_inline:nn{#1}{
    \cs_set_eq:cN{_@@_\tl_to_str:n{##1}}##1
  }
  #2
  \tl_map_inline:nn{#1}{
    \cs_set_eq:Nc##1{_@@_\tl_to_str:n{##1}}
    \cs_undefine:c{_@@_\tl_to_str:n{##1}}
  }
}
%    \end{macrocode}
%   \end{macro}
%
%   \begin{macro}{\stex_metagroup_new:n, \stex_metagroup_new:o}
% List of all currently existing metagroup identifiers
%    \begin{macrocode}
\seq_new:N \l_@@_ids_seq
%    \end{macrocode}
% start a new metagroup at the current group level with id \#1
%    \begin{macrocode}
\cs_new_protected:Nn \stex_metagroup_new:n {
    \str_set:cx{l_@@_#1_int} {\int_use:N\currentgrouplevel}
    \seq_put_right:Nn \l_@@_ids_seq {#1}
}
\cs_generate_variant:Nn \stex_metagroup_new:n {o}
%    \end{macrocode}
%   \end{macro}
%
%   \begin{macro}{\stex_metagroup_do_in:nn, \stex_metagroup_do_in:nx}
%    \begin{macrocode}
\prg_new_conditional:Nnn \_@@_exists:n {TF} {
    \str_if_exist:cTF{l_@@_#1_int}
        \prg_return_true: \prg_return_false:
}

\cs_new_protected:Nn \stex_metagroup_do_in:nn {
    \_@@_exists:nTF{#1}{
        \_@@_do_in:nn{#1}{#2}
    }{
      \msg_error:nnn{stex}{error/metagroup/missing}{#1}
    }
}
\cs_generate_variant:Nn \stex_metagroup_do_in:nn {nx}

\cs_new_protected:Nn \_@@_do_in:nn {
  \exp_args:Nnx\stex_debug:nn{metagroup}{adding~to~\detokenize{#1}:^^J\tl_to_str:n{#2}}
  \tl_set:Nn\_@@_tmp{#2}
  \exp_args:Nx \int_compare:nNnF {\use:c{l_@@_#1_int}}
      = \currentgrouplevel {
      \tl_if_exist:cTF{g_@@_#1_\the\currentgrouplevel _content}{
        \exp_args:Nno \tl_gput_right:cn{g_@@_#1_\the\currentgrouplevel _content}
      }{
        \exp_args:Nno \tl_gset:cn{g_@@_#1_\the\currentgrouplevel _content}
      }\_@@_tmp
      \bool_if_exist:cF {l_@@_\the\currentgrouplevel _bool} {
          \group_insert_after:N \_@@_do:
          \bool_set_true:c {l_@@_\the\currentgrouplevel _bool}
      }
  }
  \_@@_tmp
}

\cs_new_protected:Nn \_@@_do: {
  \seq_map_inline:Nn \l_@@_ids_seq {
    \tl_if_exist:cT{g_@@_##1_\int_eval:n{\currentgrouplevel+1}_content}{
      \exp_args:NNno \exp_args:Nno \_@@_do_in:nn{##1}{
        \csname g_@@_##1_\int_eval:n{\currentgrouplevel+1}_content\endcsname
      }
      \cs_undefine:c{g_@@_##1_\int_eval:n{\currentgrouplevel+1}_content}
    }
    \bool_if_exist:cF {l_@@_\int_eval:n\currentgrouplevel _bool} {
      \group_insert_after:N \_@@_do:
      \bool_set_true:c {l_@@_\int_eval:n\currentgrouplevel _bool}
    }
  }
}
%    \end{macrocode}
%   \end{macro}
%
% \end{sfragment}
%
% \begin{sfragment}{HTML Annotations}
%    \begin{macrocode}
%<@@=stex_annotate>
%    \end{macrocode}
%
% \begin{macro}[TF]{\stex_if_do_html:}
%  Whether to (locally) produce HTML output
%    \begin{macrocode}
\bool_new:N \_stex_html_do_output_bool
\bool_set_true:N \_stex_html_do_output_bool

\prg_new_conditional:Nnn \stex_if_do_html: {p,T,F,TF} {
  \bool_if:nTF \_stex_html_do_output_bool
    \prg_return_true: \prg_return_false:
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\stex_suppress_html:n}
%  Temporarily disable HTML output
%    \begin{macrocode}
\cs_new_protected:Nn \stex_suppress_html:n {
  \stex_pseudogroup:nn{
    \bool_set_false:N \_stex_html_do_output_bool
    #1
  }{
    \stex_if_do_html:T {
      \bool_set_true:N \_stex_html_do_output_bool
    }
  }
}
%    \end{macrocode}
% \end{macro} 
%
% We determine the backend:
% \begin{macro}[pTF]{\stex_if_html_backend:}
% \begin{macro}{\ifstexhtml}
% \begin{macro}{\stex@backend}
%    \begin{macrocode}
\ifcsname if@rustex\endcsname\else
  \expandafter\newif\csname if@rustex\endcsname
  \@rustexfalse
\fi

\stex_get_env:Nn\_@@_env_str{STEX_FORCE_PDF}
\exp_args:No \str_if_eq:nnTF \_@@_env_str {true} {
  \def\stex@backend{pdflatex}
}{
  \tl_if_exist:NF\stex@backend{
    \if@rustex
      \def\stex@backend{rustex}
    \else
      \cs_if_exist:NTF\HCode{
        \def\stex@backend{tex4ht}
      }{
        \def\stex@backend{pdflatex}
      }
    \fi
  }
}

\input{stex-backend-\stex@backend.cfg}

\newif\ifstexhtml
\stex_if_html_backend:TF {
  \stexhtmltrue
  \bool_set_true:N \_stex_html_do_output_bool
}{
  \stexhtmlfalse
  \bool_set_false:N \_stex_html_do_output_bool
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\_stex_annotate_force_break:n}
%    \begin{macrocode}
\stex_if_html_backend:TF {
  \cs_new_protected:Nn \_stex_annotate_force_break:n {
    \stex_annotate_invisible:n{~}
    #1
    \stex_annotate_invisible:n{~}
  }
}{
  \cs_new_protected:Nn \_stex_annotate_force_break:n { #1 }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\mmlintent,\mmlarg}
%    \begin{macrocode}
\stex_if_html_backend:TF {
  \cs_new_protected:Npn \mmlintent #1 #2 { 
    \stex_annotate:nn{mml:intent={#1}}{#2} 
  }
  \cs_new_protected:Npn \mmlarg #1 #2 { 
    \stex_annotate:nn{mml:arg={#1}}{#2}
  }
}{
  \cs_new_protected:Npn \mmlintent #1 #2 { #2 }
  \cs_new_protected:Npn \mmlarg #1 #2 { #2 }
}
%    \end{macrocode}
% \end{macro}
%
% \end{sfragment}
%
% \begin{sfragment}{Auxiliary Methods}
%    \begin{macrocode}
%<@@=stex_aux>
%    \end{macrocode}

% \begin{macro}{\stex_deactivate_macro:Nn, \stex_reactivate_macro:N}
%    \begin{macrocode}
\cs_new_protected:Nn \stex_deactivate_macro:Nn {
  \tl_set_eq:cN{\tl_to_str:n{#1}~-~orig}#1
  \cs_set_protected:Npn#1{
    \exp_args:Nnno\msg_error:nnnn{stex}{error/deactivated-macro}{#1}{#2}
  }
}
\cs_new_protected:Nn \stex_reactivate_macro:N {
  \exp_after:wN\let\exp_after:wN#1\csname \detokenize{#1}~-~orig\endcsname
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\stex_ignore_spaces_and_pars:}
%    \begin{macrocode}
\protected\def\stex_ignore_spaces_and_pars:{
  \begingroup\catcode13=10\relax
  \@ifnextchar\par{
    \endgroup\expandafter\stex_ignore_spaces_and_pars:\@gobble
  }{
    \endgroup
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\stex_keys_define:nnnn}
%    \begin{macrocode}
\cs_new_nopar:Nn \stex_keys_define:nnnn {
  \tl_gset:cn {_@@_keys_#1_pre_tl}{#2}
  \tl_gset:cn {_@@_keys_#1_def_tl}{#3}
  \tl_if_empty:nF{#4}{
    \clist_map_inline:nn{#4}{
      \tl_set_eq:Nc \l_@@_tl {_@@_keys_##1_pre_tl}
      \tl_gput_left:co{_@@_keys_#1_pre_tl} \l_@@_tl
      \tl_set_eq:Nc \l_@@_tl {_@@_keys_##1_def_tl}
      \tl_gput_left:cn{_@@_keys_#1_def_tl} ,
      \tl_gput_left:co{_@@_keys_#1_def_tl} \l_@@_tl
    }
  }
  \tl_set_eq:Nc \l_@@_tl {_@@_keys_#1_def_tl}
  \exp_args:Nno \keys_define:nn {stex / #1} {\l_@@_tl}
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\stex_keys_set:nn}
%    \begin{macrocode}
\cs_new_nopar:Nn \stex_keys_set:nn {
  \use:c{_@@_keys_#1_pre_tl}
  \keys_set:nn {stex / #1} { #2 }
}
%    \end{macrocode}
% \end{macro}
%
% Some ubiquitous key sets:
%    \begin{macrocode}
\stex_keys_define:nnnn{archive file}{
  \str_clear:N \l_stex_key_archive_str
  \str_clear:N \l_stex_key_file_str
}{
  archive .str_set_x:N = \l_stex_key_archive_str ,
  file    .str_set_x:N = \l_stex_key_file_str
}{}

\stex_keys_define:nnnn{id}{
  \str_clear:N \l_stex_key_id_str
}{
  id .str_set_x:N = \l_stex_key_id_str
}{}

\stex_keys_define:nnnn{title}{
  \tl_clear:N \l_stex_key_title_tl
}{
  title .tl_set:N = \l_stex_key_title_tl
}{}

\stex_keys_define:nnnn{style}{
  \clist_clear:N \l_stex_key_style_clist
}{
  style .clist_set:N = \l_stex_key_style_clist
}{}

\stex_keys_define:nnnn{deprecate}{
  \str_clear:N \l_stex_key_deprecate_str
}{
  deprecate     .str_set_x:N  = \l_stex_key_deprecate_str
}{}

\stex_keys_define:nnnn{uses}{}{
  uses .code:n = {
    \clist_map_inline:nn{#1}{
      \stex_str_if_starts_with:nnTF{##1}[{
        \_@@_split_at_bracket:w ##1 \_stex_end:
      }{
        \usemodule{##1}
      }
    }
  }
}{}

\cs_new_protected:Npn \_@@_split_at_bracket:w [ #1 ] #2 \_stex_end: {
  \usemodule[#1]{#2}
}
%    \end{macrocode}
%
% \begin{macro}{\_stex_do_deprecation:n}
%    \begin{macrocode}
\cs_new:Nn \_stex_do_deprecation:n {
  \str_if_empty:NF \l_stex_key_deprecate_str {
    \msg_warning:nnxx{stex}{warning/deprecated}{#1}{\l_stex_key_deprecate_str}
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\_stex_do_id:}
%    \begin{macrocode}
\cs_new_protected:Nn \_stex_do_id: {
  \stex_if_smsmode:F {
    \str_if_empty:NF \l_stex_key_id_str {
      \exp_args:No \stex_ref_new_doc_target:n \l_stex_key_id_str
    }
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\stex_new_stylable_env:nnnnnnn,\stex_new_stylable_cmd:nnnn,\stex_style_apply:}
%    \begin{macrocode}
\cs_new_protected:Nn \stex_new_stylable_cmd:nnnn {
  \exp_after:wN \newcommand \cs:w stexstyle#1 \cs_end:[2][]{
    \_@@_patch:nnn{#1}{##1}{##2}
  }
  \exp_after:wN \NewDocumentCommand\cs:w #1\cs_end:{#2}{
    \cs_set:Npn \stex_style_apply: {
      \_@@_apply_patch:n{#1}
    }
    #3
  }
  \tl_set:cn {_@@_style_#1:} { #4 }
}

\cs_new_protected:Nn \_@@_apply_patch:n {
  \clist_if_empty:NTF \l_stex_key_style_clist {
    \tl_clear:N \thisstyle
    \use:c{_@@_style_#1:}
  }{
    \clist_get:NN \l_stex_key_style_clist \thisstyle
    \tl_if_exist:cTF{_@@_style_#1_\thisstyle :}{
      \use:c{_@@_style_#1_\thisstyle :}
    }{
      \use:c{_@@_style_#1:}
    }
  }
}

\cs_new_protected:Nn \_@@_patch:nnn {
  \str_if_empty:nTF {#2}{
    \tl_set:cn{_@@_style_#1:}{#3}
  }{
    \tl_set:cn{_@@_style_#1_#2:}{#3}
  }
}

\cs_new_protected:Nn \stex_new_stylable_env:nnnnnnn {
  \exp_after:wN \newcommand \cs:w stexstyle#1 \cs_end:[3][]{
    \_@@_patch:nnnn{#1}{##1}{##2}{##3}
  }
  \NewDocumentEnvironment{#7#1}{#2}{
    \cs_set:Npn \stex_style_apply: {
      \_@@_apply_patch_begin:n{#1}
    }
    #3
  }{
    \cs_set:Npn \stex_style_apply: {
      \_@@_apply_patch_end:n{#1}
    }
    #4
  }
  \tl_set:cn {_@@_style_#1_start:} { #5 }
  \tl_set:cn {_@@_style_#1_end:} { #6 }
}

\cs_new_protected:Nn \_@@_patch:nnnn {
  \str_if_empty:nTF {#2}{
    \tl_set:cn{_@@_style_#1_start:}{#3}
    \tl_set:cn{_@@_style_#1_end:}{#4}
  }{
    \tl_set:cn{_@@_style_#1_#2_start:}{#3}
    \tl_set:cn{_@@_style_#1_#2_end:}{#4}
  }
}

\cs_new_protected:Nn \_@@_apply_patch_begin:n {
  \clist_if_empty:NTF \l_stex_key_style_clist {
    \tl_clear:N \thisstyle
    \use:c{_@@_style_#1_start:}
  }{
    \clist_get:NN \l_stex_key_style_clist \thisstyle
    \stex_debug:nn{styling}{dominant~style:~\thisstyle}
    \tl_if_exist:cTF{_@@_style_#1_\thisstyle _start:}{
      \use:c{_@@_style_#1_\thisstyle _start:}
    }{
      \use:c{_@@_style_#1_start:}
    }
  }
}

\cs_new_protected:Nn \_@@_apply_patch_end:n {
  \tl_if_empty:NTF \thisstyle {
    \use:c{_@@_style_#1_end:}
  }{
    \tl_if_exist:cTF{_@@_style_#1_\thisstyle _end:}{
      \use:c{_@@_style_#1_\thisstyle _end:}
    }{
      \use:c{_@@_style_#1_end:}
    }
  }
}
%    \end{macrocode}
%
% \end{macro}
%
% \begin{macro}[pTF]{\stex_str_if_ends_with:nn}
%    \begin{macrocode}
\prg_new_conditional:Nnn \stex_str_if_ends_with:nn {p,T,F,TF} {
  \exp_args:Ne \str_if_eq:nnTF {
    \str_range:nnn{#1}{- \str_count:n{#2}}{-1}
  }{#2}\prg_return_true: \prg_return_false:
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[pTF]{\stex_str_if_starts_with:nn}
%    \begin{macrocode}
\prg_new_conditional:Nnn \stex_str_if_starts_with:nn {p,T,F,TF} {
  \exp_args:Ne \str_if_eq:nnTF {
    \str_range:nnn{#1}{1}{\str_count:n{#2}}
  }{#2}\prg_return_true: \prg_return_false:
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[EXP]{\stex_macro_body:N}
%    \begin{macrocode}
\cs_new:Npn \_@@_start:#1\_@@_end: {\exp_not:n{#1}}
\cs_new_protected:Nn \_@@_end: {}
\cs_new:Nn \stex_macro_body:N {
  \exp_args:Nne\use:nn{\exp_after:wN \_@@_start: #1}{
    \_@@_args:e {\cs_parameter_spec:N #1}\_@@_end:
  }
}

\cs_new:Nn \_@@_args:n {
  \tl_if_empty:nF{#1}{
      {##\exp_args:Ne \tl_head:n {\tl_tail:n {#1}}}
      \_@@_args:e {\exp_args:Ne\tl_tail:n{\tl_tail:n{#1}}}
  }
}
\cs_generate_variant:Nn \_@@_args:n {e}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[EXP]{\stex_macro_definition:N}
%    \begin{macrocode}
\cs_new:Nn \stex_macro_definition:N {
  \_@@_prefix:e {\cs_prefix_spec:N #1}
  \def\exp_not:N #1
  \_@@_params:e {\cs_parameter_spec:N #1} 
  {
    \stex_macro_body:N #1
  }
}

\cs_new:Nn \_@@_prefix:n {
  \tl_if_empty:nF{#1}{
    \str_if_eq:eeTF {
      \tl_range:nnn{#1}{1}{10}~
    }{\tl_to_str:n{\protected}}{
      \protected
      \_@@_prefix_long:e {
          \str_range:nnn{#1}{11}{-1}
      }
    }{
      \_@@_prefix_long:n {#1}
    }
  }
}
\cs_generate_variant:Nn \_@@_prefix:n {e}

\cs_new:Nn \_@@_prefix_long:n {
  \tl_if_empty:nF{#1}{
    \str_if_eq:eeT {
      \tl_range:nnn{#1}{1}{10}~
    }{\tl_to_str:n{\long}}{\long}
  }
}
\cs_generate_variant:Nn \_@@_prefix_long:n {e}

\cs_new:Nn \_@@_params:n {
  \tl_if_empty:nF{#1}{
    \exp_args:NNe \str_if_eq:VnTF \c_hash_str {\tl_head:n{#1}}{
      ####
    }{
      \tl_head:n{#1}
    }
    \_@@_params:e {\tl_tail:n{#1}}
  }
}
\cs_generate_variant:Nn \_@@_params:n {e}
%    \end{macrocode}
% \end{macro}
%
% \end{sfragment}
%
% \begin{sfragment}{Persistence}
%    \begin{macrocode}
%<@@=stex_persist>
%    \end{macrocode}
%
% We check the environment variables:
%    \begin{macrocode}
\stex_get_env:Nn\_@@_env_str{STEX_USESMS}
\str_if_empty:NF\_@@_env_str{
  \exp_args:No \str_if_eq:nnF \_@@_env_str{false}{
    \bool_set_true:N \c_stex_persist_mode_bool
  }
}
\stex_get_env:Nn\_@@_env_str{STEX_WRITESMS}
\str_if_empty:NF\_@@_env_str{
  \exp_args:No \str_if_eq:nnF \_@@_env_str{false}{
    \bool_set_true:N \c_stex_persist_write_mode_bool
  }
}
%    \end{macrocode}
%
% \begin{macro}{\stex_persist:n,\stex_persist:e}
%    \begin{macrocode}
\iow_new:N \c_@@_sms_iow

\bool_if:NTF \c_stex_persist_write_mode_bool {
  \stex_if_html_backend:TF{
    \cs_new:Npn \stex_persist:n #1 {}
    \cs_new:Npn \stex_persist:e #1 {}
  }{
    \cs_new_protected:Nn \stex_persist:n {
      \iow_now:Nn \c_@@_sms_iow {#1}
    }
    \cs_generate_variant:Nn \stex_persist:n {e}
  }
}{
  \cs_new:Npn \stex_persist:n #1 {}
  \cs_new:Npn \stex_persist:e #1 {}
}
%    \end{macrocode}
% \end{macro}
%
% Is called at the end of the |.sty|-file:
%
%    \begin{macrocode}

\cs_new_protected:Nn \_@@_load_file:n {
  \file_if_exist:nT{#1}{
    \group_begin:
    \cs_set:Npn \stex_persist:n ##1 {}
    \cs_set:Npn \stex_persist:e ##1 {}
      \stex_debug:nn{persist}{restoring~from~sms~file}
      \catcode`\ =10\relax
      \cs:w @ @ input \cs_end:#1\relax
    \group_end:
  }
}

\cs_new_protected:Nn \_@@_write_only: {
  \iow_open:Nn \c_@@_sms_iow {\jobname.sms}
  \AtEndDocument{ \iow_close:N \c_@@_sms_iow }
}

\cs_new_protected:Nn \_@@_read_and_write: {
  \file_if_exist:nTF{\jobname.sms}{
    \ior_open:Nn \g_tmpa_ior {\jobname.sms}
    \iow_open:Nn \g_tmpa_iow {\jobname.sms2}
    \ior_str_map_inline:Nn \g_tmpa_ior {
      \iow_now:Nn \g_tmpa_iow {##1}
    }
    \iow_close:N \g_tmpa_iow
    \ior_close:N \g_tmpa_ior
    \_@@_write_only:
    \ior_open:Nn \g_tmpa_ior {\jobname.sms2}
    \ior_str_map_inline:Nn \g_tmpa_ior {
      \iow_now:Nn \c_@@_sms_iow {##1}
    }
    \ior_close:N \g_tmpa_ior
    \_@@_load_file:n{\jobname.sms2}
  }\_@@_write_only:
}

\cs_new_protected:Nn \_stex_persist_read_now: {
  \bool_if:NTF \c_stex_persist_mode_bool {
    \bool_if:NTF \c_stex_persist_write_mode_bool 
      \_@@_read_and_write: 
      {
        \_@@_load_file:n{\jobname.sms}
      }
  }{
    \bool_if:NT \c_stex_persist_write_mode_bool \_@@_write_only:
  }
}
%    \end{macrocode}
%
% \end{sfragment}
%
% \begin{sfragment}{Files, Paths and URIs}
%    \begin{macrocode}
%<@@=stex_path>
%    \end{macrocode}
%
% \begin{macro}{\stex_file_set:Nn, \stex_file_set:No, \stex_file_set:Nx}
%    \begin{macrocode}
\cs_new_protected:Nn \stex_file_set:Nn {
  \str_if_empty:nTF {#2} { \seq_clear:N #1 }{
    \exp_args:NNno \seq_set_split:Nnn #1 / { \tl_to_str:n{#2} }
  }
}
\cs_generate_variant:Nn \stex_file_set:Nn {No, Nx}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\stex_file_resolve:Nn, \stex_file_resolve:No, \stex_file_resolve:Nx}
%    \begin{macrocode}
\sys_if_platform_windows:TF{
  \cs_new_protected:Npn \_@@_win_take:w #1#2#3 \_@@_: {
    \str_set:Nn \l_@@_win_drive {#1#2}
    \str_set:Nn \l_@@_str{#3}
  }
  \cs_new_protected:Nn \stex_file_resolve:Nn {
    \str_set:Nn \l_@@_str {#2}
    \str_clear:N \l_@@_win_drive
    \exp_args:NNo \str_replace_all:Nnn \l_@@_str \c_backslash_str /
    \exp_args:Nx \str_if_eq:nnT {\str_item:Nn \l_@@_str 2} : {
      \exp_after:wN \_@@_win_take:w \l_@@_str \_@@_:
    }
    \stex_file_set:No #1 \l_@@_str
    \_@@_canonicalize:N #1
    \str_if_empty:NF \l_@@_win_drive {
      \seq_pop_left:NN #1 \l_@@_str
      \seq_put_left:No #1 \l_@@_win_drive
    }
    %\stex_debug:nn{files}{Set~\tl_to_str:n{#1}~to~\stex_file_use:N #1}
  }
}{
  \cs_new_protected:Nn \stex_file_resolve:Nn {
    \str_set:Nn \l_@@_str {#2}
    \stex_file_set:No #1 \l_@@_str
    \_@@_canonicalize:N #1
   % \stex_debug:nn{files}{Set~\tl_to_str:n{#1}~to~\stex_file_use:N #1}
  }
}
\cs_generate_variant:Nn \stex_file_resolve:Nn {No, Nx}

\cs_new_protected:Nn \_@@_canonicalize:N {
  \seq_if_empty:NF #1 {
    \seq_pop:NN #1 \l_@@_str
    \seq_clear:N \l_@@_seq
    \str_if_empty:NTF \l_@@_str {
      \seq_map_function:NN #1 \_@@_dodots:n
      \seq_put_left:Nn \l_@@_seq {}
    }{
      \seq_push:No #1 \l_@@_str
      \seq_map_function:NN #1 \_@@_dodots:n
    }
    \seq_set_eq:NN #1 \l_@@_seq
  }
}

\cs_new_protected:Nn \_@@_dodots:n {
  \str_if_empty:nF{#1}{
    \str_if_eq:nnF {#1} {.} {
      \str_if_eq:nnTF {#1} {..} {
        \seq_if_empty:NF \l_@@_seq {
          \seq_pop_right:NN \l_@@_seq \l_@@_str
        }
      }{
        \seq_put_right:Nn \l_@@_seq {#1}
      }
    }
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[pTF]{\stex_if_file_absolute:N}
%    \begin{macrocode}

\sys_if_platform_windows:TF {
  \prg_new_conditional:Nnn \stex_if_file_absolute:N {p, T, F, TF} {
    \seq_if_empty:NTF #1 \prg_return_false: {
      \tl_set:Nx \l_@@_maybewin_str {\seq_item:Nn #1 1}
      \exp_args:No \tl_if_empty:nTF \l_@@_maybewin_str \prg_return_true: {
        \exp_args:Nx \str_if_eq:nnTF {\str_item:Nn \l_@@_maybewin_str 2} :
          \prg_return_true: \prg_return_false:
      }
    }
  }
}{
  \prg_new_conditional:Nnn \stex_if_file_absolute:N {p, T, F, TF} {
    \seq_if_empty:NTF #1 \prg_return_false: {
      \exp_args:Nx \tl_if_empty:nTF {\seq_item:Nn #1 1}
        \prg_return_true: \prg_return_false:
    }
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[EXP]{\stex_file_use:N}
%    \begin{macrocode}
\cs_new:Nn \stex_file_use:N {
  \seq_use:Nn #1 /
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[TF]{\stex_if_file_starts_with:NN}
%    \begin{macrocode}
\prg_new_protected_conditional:Nnn \stex_if_file_starts_with:NN {T,F,TF} {
  \seq_set_eq:NN \l_@@_a_seq #1
  \seq_set_eq:NN \l_@@_b_seq #2
  \tl_clear:N \l_@@_return_tl
  \bool_while_do:nn{
    \bool_not_p:n{
      \bool_lazy_any_p:n{
        {\seq_if_empty_p:N \l_@@_a_seq}
        {\seq_if_empty_p:N \l_@@_b_seq}
        {\bool_not_p:n{\tl_if_empty_p:N \l_@@_return_tl}}
      }
    }
  }{
    \seq_pop_left:NN \l_@@_a_seq \l_@@_a_tl
    \seq_pop_left:NN \l_@@_b_seq \l_@@_b_tl
    \str_if_eq:NNF \l_@@_a_tl \l_@@_b_tl {
      \tl_set:Nn \l_@@_return_tl {\prg_return_false:}
    }
  }
  \tl_if_empty:NTF \l_@@_return_tl {
    \seq_if_empty:NTF \l_@@_b_seq \prg_return_true: \prg_return_false:
  } \l_@@_return_tl
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\stex_file_split_off_ext:NN,\stex_file_split_off_lang:NN}
%    \begin{macrocode}
\cs_new_protected:Nn \stex_file_split_off_ext:NN {
  \seq_set_eq:NN #1 #2
  \seq_pop_right:NN #1 \l_@@_str
  \seq_set_split:NnV \l_@@_seq . \l_@@_str
  \seq_pop_right:NN \l_@@_seq \l_@@_str
  \seq_put_right:Nx #1 {\seq_use:Nn \l_@@_seq .}
}
\cs_new_protected:Nn \stex_file_split_off_lang:NN {
  \seq_set_eq:NN #1 #2
  \seq_pop_right:NN #1 \l_@@_str
  \seq_set_split:NnV \l_@@_seq . \l_@@_str
  \seq_pop_right:NN \l_@@_seq \l_@@_str

  \seq_pop_right:NN \l_@@_seq \l_@@_str
  \exp_args:NNo \prop_if_in:NnF \c_stex_languages_prop \l_@@_str {
    \seq_put_right:No \l_@@_seq \l_@@_str
  }

  \seq_put_right:Nx #1 {\seq_use:Nn \l_@@_seq .}
}
%    \end{macrocode}
% \end{macro}
%
% URIs:
%
% \begin{macro}{\stex_map_uri:Nnnnn}
%    \begin{macrocode}
\cs_set_protected:Nn \_@@_auth:n {
  \msg_error:nnx{stex}{error/misused-uri}{\tl_to_str:n{#1}}
}
\cs_set_eq:NN \_@@_path:n \_@@_auth:n
\cs_set_eq:NN \_@@_module:n \_@@_auth:n
\cs_set_eq:NN \_@@_name:n \_@@_auth:n

\cs_set_protected:Nn \stex_map_uri:Nnnnn{
  \stex_pseudogroup_with:nn{\_@@_auth:n\_@@_path:n\_@@_module:n\_@@_name:n}{
    \cs_set:Npn \_@@_auth:n ##1 {#2}
    \cs_set:Npn \_@@_path:n ##1 {#3}
    \cs_set:Npn \_@@_module:n ##1 {#4}
    \cs_set:Npn \_@@_name:n ##1 {#5}
    #1
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\stex_uri_set:Nn, \stex_uri_set:No, \stex_uri_set:Nx}
%    \begin{macrocode}
\str_set:Nx\_@@_colonslash{\c_colon_str/}
\cs_new_protected:Nn \_@@_uri_set:NnN {
  \str_if_empty:nTF {#2} {
    \msg_error:nnxx{stex}{error/invalid-uri}{\tl_to_str:n{#2}}{empty}
  }{
    \exp_args:NNNo \exp_args:NNno \seq_set_split:Nnn #1 \_@@_colonslash { \tl_to_str:n{#2} }
    \seq_pop_left:NN #1 \l_@@_auth_str
    \seq_if_empty:NTF #1 {
      \msg_error:nnxx{stex}{error/invalid-uri}{\tl_to_str:n{#2}}{missing~authority}
    }{
      \exp_args:NNnx \seq_set_split:Nnn #1 ? {\exp_args:NNo \seq_use:Nn #1 \_@@_colonslash }
      \seq_pop_left:NN #1 \l_@@_path
      #3 \l_@@_path \l_@@_path
      \seq_if_empty:NTF #1 {
        \exp_args:NNo \_@@_uri_set:Nnxnn #1 \l_@@_auth_str 
          {\stex_file_use:N \l_@@_path} {} {}
      }{
        \seq_pop_left:NN #1 \l_@@_mod
        \seq_if_empty:NTF #1 {
          \exp_args:NNo \_@@_uri_set:Nnxon #1 \l_@@_auth_str 
            {\stex_file_use:N \l_@@_path} \l_@@_mod {}
        }{
          \seq_pop_left:NN #1 \l_@@_name
          \seq_if_empty:NTF #1 {
            \exp_args:NNo \_@@_uri_set:Nnxon #2 \l_@@_auth_str 
              {\stex_file_use:N \l_@@_path} \l_@@_mod \l_@@_name
          }{
            \msg_error:nnxx{stex}{error/invalid-uri}{\tl_to_str:n{#2}}{too~many~?s}
          }
        }
      }
    }
  }
  \stex_debug:nn{uris}{Set~\tl_to_str:n{#1}~to~\stex_uri_use:N #1}
}

\cs_new_protected:Nn \_@@_uri_set:Nnnnn{
  \tl_set:Nn #1 {
    \_@@_auth:n{ #2 }
    \_@@_path:n{ #3 }
    \_@@_module:n{ #4 }
    \_@@_name:n{ #5 }
  }
}
\cs_generate_variant:Nn\_@@_uri_set:Nnnnn {Nnxnn,Nnxon,Nnxoo}

\cs_new_protected:Nn \stex_uri_set:Nn {
  \_@@_uri_set:NnN #1 {#2} \stex_file_set:No
}
\cs_generate_variant:Nn \stex_uri_set:Nn {No, Nx}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\stex_uri_resolve:Nn, \stex_uri_resolve:No, \stex_uri_resolve:Nx}
%    \begin{macrocode}
\cs_new_protected:Nn \stex_uri_resolve:Nn {
  \_@@_uri_set:NnN #1 {#2} \stex_file_resolve:No
}
\cs_generate_variant:Nn \stex_uri_resolve:Nn {No, Nx}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[EXP]{\stex_uri_use:N}
%    \begin{macrocode}
\cs_new:Npn \_@@_uri_use:w \_@@_auth:n #1 \_@@_path:n #2 \_@@_module:n #3 \_@@_name:n #4 {
  #1\c_colon_str/ #2 \tl_if_empty:nF { #3 }{ ? #3 
    \tl_if_empty:nF { #4 }{ ? #4 } }
}
\cs_new:Nn \stex_uri_use:N {
  \exp_args:Ne \cs_if_eq:NNTF { \tl_head:N #1 } \_@@_auth:n {
    \exp_after:wN \_@@_uri_use:w #1
  }{
    \msg_error:nnnn{stex}{error/invalid-uri}{#1}{Not~a~URI}
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\stex_uri_from_repo_file:NNNn, \stex_uri_from_repo_file_nolang:NNNn}
%    \begin{macrocode}
\cs_new_protected:Npn \stex_uri_from_repo_file_nolang:NNNn {
  \_@@_from_repo_file:NNNNn \stex_file_split_off_lang:NN
}
\cs_new_protected:Npn \stex_uri_from_repo_file:NNNn {
  \_@@_from_repo_file:NNNNn \stex_file_split_off_ext:NN
}

\cs_new_protected:Nn \_@@_from_repo_file:NNNNn {
  #1 \l_@@_file #4
  \prop_if_exist:NTF #3 {
    \str_clear:N \l_@@_uri
    \prop_get:NnNF #3 {#5} \l_@@_uri {
      \prop_get:NnNF #3 {ns} \l_@@_uri {
        \_@@_uri_set:Nnxnn #2 {file} 
          {\stex_file_use:N \l_@@_file} {} {}
      }
    }
    \str_if_empty:NF \l_@@_uri {\_@@_relativize:N #2}
  }{
    \exp_args:NNx \_@@_uri_set:Nnxnn #2 {\tl_to_str:n{file}} 
      {\stex_file_use:N \l_@@_file} {} {}
  }
}

\cs_new_protected:Nn \_@@_relativize:N {
  \seq_set_eq:NN \l_@@_seq \l_@@_file 
  \seq_map_inline:Nn \c_stex_mathhub_file { % mathhub path
    \seq_pop_left:NN \l_@@_seq \l_@@_tl
  }
  \stex_file_set:Nx \l_@@_path {\prop_item:Nn \l_stex_current_archive_prop {id} }
  \seq_map_inline:Nn \l_@@_path { % id
    \seq_pop_left:NN \l_@@_seq \l_@@_tl
  }
  \seq_pop_left:NN \l_@@_seq \l_@@_tl % source

  \stex_uri_set:Nx #1 { \l_@@_uri / \stex_file_use:N \l_@@_seq }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\stex_uri_from_current_file:Nn, \stex_uri_from_current_file_nolang:Nn}
%    \begin{macrocode}
\cs_new_protected:Nn \stex_uri_from_current_file:Nn {
  \stex_debug:nn{docuri}{Here:~\stex_file_use:N \g_stex_current_file}
  \stex_uri_from_repo_file:NNNn #1 \l_stex_current_archive_prop
    \g_stex_current_file {#2}
  \stex_debug:nn{docuri}{resolved:~\stex_uri_use:N #1}
}
\cs_new_protected:Nn \stex_uri_from_current_file_nolang:Nn {
  \stex_uri_from_repo_file_nolang:NNNn #1 \l_stex_current_archive_prop
    \g_stex_current_file {#2}
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\stex_uri_add_module:NNn, \stex_uri_add_module:NNo}
%    \begin{macrocode}
\cs_new_protected:Nn \stex_uri_add_module:NNn {
  \exp_args:Ne \cs_if_eq:NNTF { \tl_head:N #2 } \_@@_auth:n {
    \stex_pseudogroup_with:nn
      {\_@@_auth:n\_@@_path:n\_@@_module:n\_@@_name:n}
      {
        \cs_set:Npn \_@@_module:n ##1 {
          \tl_if_empty:nTF{##1}{
            \exp_not:N \_@@_module:n {#3}
          }{
            \msg_error:nnn{stex}{error/invalid-dpath}{#2}
          }
        }
        \cs_set:Npn \_@@_name:n ##1 {
          \tl_if_empty:nTF{##1}{
            \exp_not:N \_@@_name:n {}
          }{
            \msg_error:nnn{stex}{error/invalid-dpath}{#2}
          }
        }
        \tl_set:Nx #1 {#2}
      }
  }{
    \msg_error:nnnn{stex}{error/invalid-uri}{#2}{Not~a~URI}
  }
}
\cs_generate_variant:Nn \stex_uri_add_module:NNn {NNo}
%    \end{macrocode}
% \end{macro}
%
% \begin{variable}{\l_stex_current_doc_uri}
%    \begin{macrocode}
\tl_new:N \l_stex_current_doc_uri
%    \end{macrocode}
% \end{variable}
%
% \begin{macro}{\stex_set_document_uri:}
%    \begin{macrocode}
\cs_new_protected:Nn \stex_set_document_uri: {
  \stex_uri_from_current_file:Nn \l_stex_current_doc_uri {narr}
  %\stex_debug:nn{sref}{Document~URI:~\stex_uri_use:N \l_stex_current_doc_uri}
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\stex_set_current_namespace:}
%    \begin{macrocode}
\cs_new_protected:Nn \stex_set_current_namespace: {
  \stex_uri_from_current_file_nolang:Nn \l_stex_current_ns_uri {source-base}
  %\stex_debug:nn{modules}{Namespace~URI:~\stex_uri_use:N \l_stex_current_ns_uri}
}
%    \end{macrocode}
% \end{macro}
%
% We determine the PWD
%
% \begin{variable}{\c_stex_pwd_file,\c_stex_main_file}
%    \begin{macrocode}
\sys_if_platform_windows:TF{
  \stex_get_env:Nn\l_@@_str{CD}
}{
  \stex_get_env:Nn\l_@@_str{PWD}
}
\stex_file_resolve:No \c_stex_pwd_file \l_@@_str
\seq_set_eq:NN \c_stex_main_file \c_stex_pwd_file
\seq_put_right:Nx \c_stex_main_file {\jobname\tl_to_str:n{.tex}}

\stex_debug:nn {files} {PWD:~\stex_file_use:N \c_stex_pwd_file}
%    \end{macrocode}
% \end{variable}
%
% \end{sfragment}
%
% \begin{sfragment}{File Hooks}
%
% keeps track of file changes:
%    \begin{macrocode}
\seq_gclear_new:N\g_@@_stack
\seq_gclear_new:N\g_stex_current_file
%    \end{macrocode}
%
% \begin{macro}{\stex_filestack_push:n}
%    \begin{macrocode}
\cs_new_protected:Nn \stex_filestack_push:n {
  \stex_str_if_ends_with:nnTF {#1}{.tex}{
    \stex_file_resolve:No \g_stex_current_file {#1}
  }{
    \stex_file_resolve:No \g_stex_current_file {#1.tex}
  }
  \stex_if_file_absolute:NF \g_stex_current_file {
    \stex_file_resolve:Nx \g_stex_current_file {
      \stex_file_use:N \c_stex_pwd_file / \stex_file_use:N \g_stex_current_file
    }
  }
  \seq_gset_eq:NN \g_stex_current_file \g_stex_current_file
  \exp_args:NNx \seq_gpush:Nn \g_@@_stack {\stex_file_use:N \g_stex_current_file}
  \_stex_every_file:
}

\cs_new_protected:Nn \_stex_every_file: {  
  \stex_set_document_uri:
  \stex_language_from_file:
  \stex_set_current_namespace:
}
%\AtBeginDocument{\_stex_every_file:}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\stex_filestack_pop:}
%    \begin{macrocode}
\cs_new_protected:Nn \stex_filestack_pop: {
  \seq_if_empty:NF \g_@@_stack {
    \seq_gpop:NN \g_@@_stack \l_@@_str
  }
  \seq_if_empty:NTF \g_@@_stack {
    \seq_gset_eq:NN \g_stex_current_file \c_stex_main_file
  }{
    \seq_get:NN \g_@@_stack \l_@@_str
    \exp_args:NNo \stex_file_set:Nn \g_stex_current_file \l_@@_str
    \seq_gset_eq:NN \g_stex_current_file \g_stex_current_file
  }
  \_stex_every_file:
}
%    \end{macrocode}
% \end{macro}

% Hooks for the current file:
%
%    \begin{macrocode}
\cs_new_protected:Nn \stex_input_with_hooks:n {
  \tl_set:Nn \l_@@_do_hooks_pre_tl {
    \tl_gset:Nn \l_@@_do_hooks_pre_tl {}
    \stex_debug:nn{HERE}{Hook~for~#1^^J\meaning\CurrentFilePath^^J\CurrentFile}
    \tl_if_empty:NTF\CurrentFilePath{
      \exp_args:No \stex_filestack_push:n {\CurrentFile}
    }{
      \exp_args:Ne \stex_filestack_push:n { \CurrentFilePath / \CurrentFile }
    }
  }
  \input{#1}
  \stex_debug:nn{HERE}{Hook~end~for~#1}
  \stex_filestack_pop:
}
\tl_new:N \l_@@_do_hooks_pre_tl {}

\AddToHook{file/before}{
  \l_@@_do_hooks_pre_tl
}
%\AddToHook{file/after}{ \stex_filestack_pop: }
%    \end{macrocode}
%
% \end{sfragment}
%
% \end{sfragment}
%
% \begin{sfragment}{Math Archives}
%    \begin{macrocode}
%<@@=stex_mathhub>
%    \end{macrocode}
%
% \begin{variable}{\mathhub, \c_stex_home_file,\c_stex_mathhub_file}
% The path to the mathhub directory. If the \cs{mathhub}-macro is not set,
% we query |kpsewhich| for the |MATHHUB| system variable.
%    \begin{macrocode}

\sys_if_platform_windows:TF{
  \stex_get_env:Nn \l_@@_str {homedrive\c_percent_str\c_percent_str homepath}
}{
  \stex_get_env:Nn \l_@@_str {HOME}
}
\stex_file_resolve:No \c_stex_home_file \l_@@_str

\str_if_empty:NTF\mathhub{
  \stex_get_env:Nn \l_@@_str {MATHHUB}
  \str_if_empty:NTF \l_@@_str {
    \ior_open:NnTF \g_tmpa_ior{\stex_file_use:N \c_stex_home_file/.stex/mathhub.path}{
      \group_begin:
        \escapechar=-1\catcode`\\=12
        \ior_str_get:NN \g_tmpa_ior \l_@@_str
        \str_gset_eq:NN \l_@@_str \l_@@_str
      \group_end:
      \ior_close:N \g_tmpa_ior
      \stex_debug:nn{mathhub}{MathHub~directory~determined~from~home~directory}
    }{
      \str_clear:N \l_@@_str
    }
  }{
    \stex_debug:nn{mathhub}{MathHub~directory~determined~from~environment~variable}
  }
}{
  \str_set_eq:NN \l_@@_str \mathhub
}

\str_if_empty:NTF \l_@@_str {
  \msg_warning:nn{stex}{warning/nomathhub}
  \exp_args:NNe \stex_file_set:Nn \c_stex_mathhub_file {\stex_file_use:N \c_stex_home_file \tl_to_str:n{/MathHub}}
  \seq_clear:N \c_stex_mathhub_file
}{
  \stex_file_resolve:No \c_stex_mathhub_file \l_@@_str
  \stex_if_file_absolute:NF \c_stex_mathhub_file {
    \exp_args:NNe \stex_file_resolve:Nn \c_stex_mathhub_file {
      \stex_file_use:N \c_stex_main_file / .. / \l_@@_str
    }
  }
}

\exp_args:NNe \str_set:Nn \mathhub {\stex_file_use:N \c_stex_mathhub_file}
\stex_debug:nn{mathhub}{MATHHUB:~\mathhub}
%    \end{macrocode}
% \end{variable}
%
% \begin{variable}{\l_stex_current_archive}
% \begin{macro}{\stex_set_current_archive:n}
%    \begin{macrocode}
\cs_new_protected:Nn \stex_set_current_archive:n {
  \stex_require_archive:n { #1 }
  \stex_debug:nn{mathhub}{switching~to~archive~#1}
  \prop_set_eq:Nc \l_stex_current_archive_prop { 
    c_stex_mathhub_#1_manifest_prop 
  }
}
%    \end{macrocode}
% \end{macro}
% \end{variable}
%
% \begin{macro}{\stex_in_archive:nn}
%    \begin{macrocode}
\cs_new_protected:Nn \stex_in_archive:nn {
  \cs_if_exist:NF \l_@@_cs {
    \cs_set:Npn \l_@@_cs ##1 {}
  }
  \stex_pseudogroup:nn{
    \cs_set:Npn \l_@@_cs ##1 {#2}
    \tl_if_empty:nTF{#1}{
      \prop_if_exist:NTF \l_stex_current_archive_prop {
        \exp_args:Ne \l_@@_cs {\prop_item:Nn \l_stex_current_archive_prop { id } }
      }{
        \l_@@_cs {}
      }
    }{
      \stex_set_current_archive:n{#1}
      \l_@@_cs {#1}
    }
  }{
    \stex_pseudogroup_restore:N \l_stex_current_archive_prop
    \cs_set:Npn \exp_not:N \l_@@_cs ##1 {
      \exp_args:No \exp_not:n {\l_@@_cs {##1}}
    }
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\stex_require_archive:n,\stex_require_archive:o}
%    \begin{macrocode}
\cs_new_protected:Nn \stex_require_archive:n {
  \prop_if_exist:cF { c_stex_mathhub_#1_manifest_prop } {
    \seq_if_empty:NTF \c_stex_mathhub_file {
      \stex_fatal_error:n{warning/nomathhub}
    }{
      \stex_debug:nn{mathhub}{Opening~archive:~#1}
      \_@@_do_manifest:n { #1 }
    }
  }
}
\cs_generate_variant:Nn \stex_require_archive:n {o}
%    \end{macrocode}
% \end{macro}
%
% Code for finding and parsing manifest files:
%
%    \begin{macrocode}
\cs_new_protected:Nn \_@@_do_manifest:n {
  \exp_args:Ne \_@@_find_manifest:n {\stex_file_use:N \c_stex_mathhub_file / #1}
  \str_if_empty:NT \l_@@_manifest_str {
    \stex_fatal_error:nxx{error/noarchive}
      {#1}{\stex_file_use:N \c_stex_mathhub_file}
  }
  \_@@_parse_manifest:n {#1}
}

\cs_new_protected:Nn \_@@_find_manifest:n {
  \str_clear:N \l_@@_manifest_str 
  \seq_set_split:Nnn \l_@@_seq / {#1}
  \bool_set_true:N \l_@@_bool
  \bool_while_do:Nn \l_@@_bool {
    \tl_if_eq:NNTF \l_@@_seq \c_stex_mathhub_file {
      \bool_set_false:N \l_@@_bool
    }{
      \_@@_check_manifest:
      \bool_if:NT \l_@@_bool {
        \seq_pop_right:NN \l_@@_seq \l_@@_tl
      }
    }
  }
}
\cs_generate_variant:Nn \_@@_find_manifest:n {x}

\cs_new_protected:Nn \_@@_check_manifest: {
  \_@@_check_manifest:n {MANIFEST.MF}
  \bool_if:NT \l_@@_bool {
    \_@@_check_manifest:n {META-INF/MANIFEST.MF}
    \bool_if:NT \l_@@_bool {
      \_@@_check_manifest:n {meta-inf/MANIFEST.MF}
    }
  }
}

\cs_new_protected:Nn \_@@_check_manifest:n {
  \stex_debug:nn{mathhub}{Checking~\stex_file_use:N \l_@@_seq / #1}
  \file_if_exist:nT {\stex_file_use:N \l_@@_seq / #1} {
    \bool_set_false:N \l_@@_bool
    \str_set:Nx \l_@@_manifest_str {\stex_file_use:N \l_@@_seq / #1}
  }
}

\ior_new:N \c_@@_manifest_ior
\cs_new_protected:Nn \_@@_parse_manifest:n {
  \ior_open:Nn \c_@@_manifest_ior \l_@@_manifest_str
  \prop_clear:N \l_@@_prop
  \ior_map_inline:Nn \c_@@_manifest_ior {
    \exp_args:NNNo \exp_args:NNNx 
      \seq_set_split:Nnn \l_@@_seq \c_colon_str {\tl_to_str:n{##1}}
    \seq_pop_left:NNT \l_@@_seq \l_@@_key {
      \exp_args:NNo \str_set:Nn \l_@@_key \l_@@_key
      \str_set:Nx \l_@@_val {\seq_use:Nn \l_@@_seq :}
      \str_case:Nn \l_@@_key {
        {id}              {\prop_put:Nno \l_@@_prop { id }      \l_@@_val }
        {narration-base}  {\prop_put:Nno \l_@@_prop { narr }    \l_@@_val }
        {url-base}        {\prop_put:Nno \l_@@_prop { docurl }  \l_@@_val }
        {source-base}     {\prop_put:Nno \l_@@_prop { ns }      \l_@@_val }
        {ns}              {\prop_put:Nno \l_@@_prop { ns }      \l_@@_val }
      }
    }
  }
  \ior_close:N \c_@@_manifest_ior
  \prop_gset_eq:cN { c_stex_mathhub_#1_manifest_prop } \l_@@_prop
  \stex_debug:nn{mathhub}{Result:~\prop_to_keyval:N \l_@@_prop}
  \stex_persist:e {
    \prop_gset_from_keyval:cn {c_stex_mathhub_#1_manifest_prop}{
      \prop_to_keyval:N \l_@@_prop
    }
  }
}
%    \end{macrocode}
%
% Current MathHub archive
% \begin{variable}{\c_stex_main_archive_prop, \l_stex_current_archive_prop}
%    \begin{macrocode}
\cs_new_protected:Nn \_stex_main_archive: {
  \stex_if_file_starts_with:NNTF \c_stex_pwd_file \c_stex_mathhub_file {
    \_@@_find_manifest:x { \stex_file_use:N \c_stex_pwd_file }
    \str_if_empty:NTF \l_@@_manifest_str {
      \stex_debug:nn{mathhub}{Not~currently~in~a~MathHub~archive}
    }{
      \_@@_parse_manifest:n { main }
      \prop_set_eq:NN \c_stex_main_archive_prop \c_stex_mathhub_main_manifest_prop
      \cs_undefine:N \c_stex_mathhub_main_manifest_prop
      \prop_get:NnN \c_stex_main_archive_prop {id} 
        \l_@@_str
      \prop_set_eq:cN { c_stex_mathhub_\l_@@_str _manifest_prop }
        \c_stex_main_archive_prop
      \exp_args:No \stex_set_current_archive:n { \l_@@_str }
      \stex_debug:nn{mathhub}{Current~archive:~
        \prop_item:Nn \l_stex_current_archive_prop {id}
      }
      \bool_if:NT \c_stex_persist_write_mode_bool {
        \tl_put_right:Nx \_stex_persist_read_now: {
          \stex_persist:n {
            \prop_gset_from_keyval:cn {c_stex_mathhub_\l_@@_str _manifest_prop}{
              \prop_to_keyval:N \c_stex_main_archive_prop
            }
            \prop_gset_eq:Nc \exp_not:N \l_stex_current_archive_prop { 
              c_stex_mathhub_\l_@@_str _manifest_prop 
            }
            \prop_gset_eq:Nc \exp_not:N \c_stex_main_archive_prop { 
              c_stex_mathhub_\l_@@_str _manifest_prop 
            }
          }
        }
      }
    }
  }{
    \stex_debug:nn{mathhub}{Not~currently~in~the~MathHub~directory}
  }
}

%\bool_if:NF \c_stex_persist_mode_bool {
  \_stex_main_archive:
%}
%    \end{macrocode}
% \end{variable}
%
% \end{sfragment}
%
% \begin{sfragment}{Documents}
%
% \begin{sfragment}{Title}
%
% Stores the title, if it exists:
%    \begin{macrocode}
%<@@=stex_doc>
\tl_new:N \g_@@_title_tl
%    \end{macrocode}
%
% \begin{macro}{\stexdoctitle}
% Initital definition, will be changed at begin document:
%    \begin{macrocode}
\cs_new_protected:Npn \stexdoctitle #1 {
  \tl_gset:Nn \g_@@_title_tl { #1 }
  \global\def\stexdoctitle##1{}
}
%    \end{macrocode}
% At begin document, we switch to:
%    \begin{macrocode}
\cs_new_protected:Nn \_@@_set_title:n {
  \stex_if_smsmode:F{
    \global\def\stexdoctitle##1{}
    \stex_debug:nn{title}{Setting~title~to:\tl_to_str:n{#1}}
    \tl_gset:Nn \g_@@_title_tl { #1 }
    \_@@_title_html:
  }
}
%    \end{macrocode}
% Hooks, changes and HTML:
%    \begin{macrocode}
\cs_new_protected:Nn \_@@_title_html: {
  \stex_if_do_html:T{\stex_if_html_backend:T{
    \stex_annotate_invisible:nn{shtml:doctitle={}}{ \hbox{\g_@@_title_tl} }
  }}
}

\AtBeginDocument {
  \tl_if_empty:NTF \g_@@_title_tl {
    \cs_set_eq:NN \stexdoctitle \_@@_set_title:n
  }{
    \stex_debug:nn{title}{Setting~title~to:\exp_args:No\tl_to_str:n\g_@@_title_tl}
    \global\def\stexdoctitle#1{}
    \_@@_title_html:
  }

  \cs_set_eq:NN \_@@_maketitle: \maketitle
  \global\protected\def\maketitle{
    \tl_if_empty:NF \@title {
      \exp_args:No \stexdoctitle \@title
    }
    \_@@_maketitle:
  }
}
%    \end{macrocode}
% \end{macro}
%
% \end{sfragment}
%
% \begin{sfragment}{Sectioning}
%    \begin{macrocode}
\int_new:N \l_stex_docheader_sect

\tl_set:Nn \stex_current_section_level {document}

\cs_set_protected:Npn \currentsectionlevel {
  \stex_if_do_html:TF{
    \stex_annotate:nn{shtml:currentsectionlevel={},shtml:capitalize=false}{}
  }{
    \stex_current_section_level
  }
  \tl_if_exist:NT\xspace\xspace
}

\cs_set_protected:Npn \Currentsectionlevel {
  \stex_if_do_html:TF{
    \stex_annotate:nn{shtml:currentsectionlevel={},shtml:capitalize=true}{}
  }{
    \exp_args:No \_stex_capitalize:n \stex_current_section_level
  }
  \tl_if_exist:NT\xspace\xspace
}

\stex_if_html_backend:TF {
  \cs_new_protected:Nn \_sfragment_do_level:nn {
    \stexdoctitle{#2}
    \par
    \begin{stex_annotate_env}{shtml:section={\int_use:N \l_stex_docheader_sect}}
      \noindent\stex_annotate:nn{shtml:sectiontitle={}}{
        \_stex_annotate_force_break:n{#2}
      }\par
  }
  \cs_new_protected:Nn \_sfragment_end: {
    \end{stex_annotate_env}
  }
}{
  \cs_new_protected:Nn \_sfragment_do_level:nn {
    \stexdoctitle{#2}
    \tl_if_empty:NTF \l_stex_key_short_tl {
      \use:c{#1}
    }{
      \exp_args:Nnx \use:nn{\use:c{#1}}{[\exp_args:No \exp_not:n \l_stex_key_short_tl]}
    }{#2}
    \int_incr:N \l_stex_docheader_sect
    \tl_set:Nn \stex_current_section_level{#1}
  }
  \cs_new_protected:Nn \_sfragment_end: {}
}


\cs_new_protected:Npn \_@@_do_section:n {
  \int_case:nnF \l_stex_docheader_sect {
    {0}{\cs_if_exist:NTF \thepart {\_sfragment_do_level:nn{part}}{
      \int_incr:N \l_stex_docheader_sect
      \_@@_do_section:n 
    }}
    {1}{\cs_if_exist:NTF \thechapter {\_sfragment_do_level:nn{chapter}}{
      \int_incr:N \l_stex_docheader_sect
      \_@@_do_section:n
    }}
    {2}{\_sfragment_do_level:nn{section}}
    {3}{\_sfragment_do_level:nn{subsection}}
    {4}{\_sfragment_do_level:nn{subsubsection}}
    {5}{\_sfragment_do_level:nn{paragraph}}
  }{\_sfragment_do_level:nn{subparagraph}}
}

\stex_keys_define:nnnn{ sfragment }{
  \tl_clear:N \l_stex_key_short_tl
}{
  short   .tl_set:N   = \l_stex_key_short_tl
}{id}

\NewDocumentEnvironment{sfragment}{ O{} m}{
  \stex_keys_set:nn{sfragment}{#1}
  \_@@_do_section:n{#2}
  \_stex_do_id:
}{
  \_sfragment_end:
}

%\int_incr:N \l_stex_docheader_sect
\NewDocumentEnvironment{blindfragment}{}{
  \_@@_skip_section:
}{
  \stex_if_html_backend:T{
    \stex_annotate_invisible:n{~}
    \end{stex_annotate_env}
  }
}


\cs_new_protected:Nn \_@@_skip_section_i: {
  \int_case:nn \l_stex_docheader_sect {
    {0}{\cs_if_exist:NF \thepart {
      \int_incr:N \l_stex_docheader_sect \_@@_skip_section_i:
    }}
    {1}{\cs_if_exist:NF \thechapter {
      \int_incr:N \l_stex_docheader_sect \_@@_skip_section_i:
    }}
  }
  \int_incr:N \l_stex_docheader_sect
}

\stex_if_html_backend:TF {
  \cs_new_protected:Nn \_@@_skip_section: {
    \_@@_skip_section_i:
    \begin{stex_annotate_env}{shtml:skipsection={\int_use:N \l_stex_docheader_sect}}
    \stex_annotate_invisible:n{~}
  }
}{
  \cs_set_eq:NN \_@@_skip_section: \_@@_skip_section_i:
}


\cs_new_protected:Nn \_@@_skip_fragment:n {
  \stepcounter{#1}
}

\cs_new_protected:Npn \skipfragment {
  \int_case:nnF \l_stex_docheader_sect {
    {0}{\cs_if_exist:NTF \thepart {\_@@_skip_fragment:n{part}}{
      \int_incr:N \l_stex_docheader_sect
      \skipfragment
    }}
    {1}{\cs_if_exist:NTF \thechapter {\_@@_skip_fragment:n{chapter}}{
      \int_incr:N \l_stex_docheader_sect
      \skipfragment
    }}
    {2}{\_@@_skip_fragment:n{section}}
    {3}{\_@@_skip_fragment:n{subsection}}
    {4}{\_@@_skip_fragment:n{subsubsection}}
    {5}{\_@@_skip_fragment:n{paragraph}}
  }{\_@@_skip_fragment:n{subparagraph}}
}
%    \end{macrocode}
%
% \begin{macro}{\setsectionlevel}
%    \begin{macrocode}
\cs_new_protected:Npn \setsectionlevel #1 {
  \str_case:nnF{#1}{
    {part}{\int_set:Nn \l_stex_docheader_sect 0}
    {chapter}{\int_set:Nn \l_stex_docheader_sect 1}
    {section}{\int_set:Nn \l_stex_docheader_sect 2}
    {subsection}{\int_set:Nn \l_stex_docheader_sect 3}
    {subsubsection}{\int_set:Nn \l_stex_docheader_sect 4}
    {paragraph}{\int_set:Nn \l_stex_docheader_sect 5}
  }{
    \int_set:Nn \l_stex_docheader_sect 6
  }
  \cs_if_eq:NNTF\@onlypreamble\@notprerr{
    \stex_annotate_invisible:nn{shtml:sectionlevel={\int_use:N\l_stex_docheader_sect}}{}
  }{}
}

\stex_if_html_backend:T{
  \cs_new_protected:Nn \_@@_check_topsect: {
    \int_case:nnF \l_stex_docheader_sect {
      {0}{\cs_if_exist:NTF \thepart {
        \stex_annotate_invisible:nn{shtml:sectionlevel=0}{}
      }{
        \int_incr:N \l_stex_docheader_sect
        \_@@_check_topsect:
      }}
      {1}{\cs_if_exist:NTF \thechapter {
        \stex_annotate_invisible:nn{shtml:sectionlevel=1}{}
      }{
        \int_incr:N \l_stex_docheader_sect
        \_@@_check_topsect:
      }}
    }{
      \stex_annotate_invisible:nn{shtml:sectionlevel={\int_use:N\l_stex_docheader_sect}}{}
    }
  }
  \AtBeginDocument{\_@@_check_topsect:}
}

\AtBeginDocument{
  \bool_if:NF \c_stex_no_frontmatter_bool {
    \cs_if_exist:NTF\frontmatter{
      \let\_@@_orig_frontmatter\frontmatter
      \let\frontmatter\relax
    }{
      \tl_set:Nn\_@@_orig_frontmatter{
        \clearpage
        %\@mainmatterfalse
        \pagenumbering{roman}
      }
    }
    \cs_if_exist:NTF\backmatter{
      \let\_@@_orig_backmatter\backmatter
      \let\backmatter\relax
    }{
      \tl_set:Nn\_@@_orig_backmatter{
        \clearpage
        %\@mainmatterfalse
        \pagenumbering{roman}
      }
    }
    \newenvironment{frontmatter}{
      \_@@_orig_frontmatter
    }{
      \cs_if_exist:NTF\mainmatter{
        \mainmatter
      }{
        \clearpage
        %\@mainmattertrue
        \pagenumbering{arabic}
      }
    }
    \newenvironment{backmatter}{
      \_@@_orig_backmatter
    }{
      \cs_if_exist:NTF\mainmatter{
        \mainmatter
      }{
        \clearpage
        %\@mainmattertrue
        \pagenumbering{arabic}
      }
    }
  }
}
%    \end{macrocode}
% \end{macro}
% \end{sfragment}
%
%
% \begin{sfragment}{References}
%    \begin{macrocode}
%<@@=stex_refs>
%    \end{macrocode}
%
% References are stored in the file |\jobname.sref|, to enable
% cross-referencing external documents.
%    \begin{macrocode}
\iow_new:N \c_@@_iow
\AtBeginDocument{\iow_open:Nn \c_@@_iow {\jobname.sref}}
\AtEndDocument{\iow_close:N \c_@@_iow}
%    \end{macrocode}
%
% The following macros are written to the |.aux|-file, and hence
% use \LaTeX2e character code scheme:
%
%    \begin{macrocode}
\cs_new_protected:Npn \STEXInternalSrefRestoreTarget #1#2#3#4#5 {}

\cs_new_protected:Npn \STEXInternalSetSrefSymURL #1 #2 {
  \str_gset:cn{g_stex_sref_sym_\tl_to_str:n{#1}_target}{#2}
}

%    \end{macrocode}
%
% \begin{macro}{\stex_ref_new_doc_target:n,\sreflabel}
%    \begin{macrocode}
\seq_new:N \g_@@_files_seq
\int_new:N \l_@@_unnamed_counter_int

\cs_new_protected:Nn \_stex_ref_new_id:n {
  \str_if_empty:nTF {#1}{
    \int_gincr:N \l_@@_unnamed_counter_int
    \str_set:Nx \l_@@_str {REF\int_use:N \l_@@_unnamed_counter_int}
  }{
    \str_set:Nn \l_@@_str {#1}
  }
  \str_set:Nx \l_stex_ref_url_str {\stex_uri_use:N \l_stex_current_doc_uri ? \l_@@_str}
}

\cs_new_protected:Nn \stex_ref_new_doc_target:n {
  \_stex_ref_new_id:n{#1}
  %\stex_uri_add_module:NNo \l_@@_uri \l_stex_current_doc_uri \l_@@_str
  %\stex_debug:nn{sref}{New~document~target:~\stex_uri_use:N \l_@@_uri}
  \_@@_add_doc_ref:xo {\stex_uri_use:N \l_stex_current_doc_uri} \l_@@_str
  \stex_if_smsmode:F {
    \iow_now:Nx \c_@@_iow {
      \STEXInternalSrefRestoreTarget
      {\stex_uri_use:N \l_stex_current_doc_uri}
      {\l_@@_str}
      {\@currentcounter}
      {\@currentlabel}
      {
        \tl_if_exist:NT\@currentlabelname{
          \exp_args:No\exp_not:n\@currentlabelname
        }
      }
    }
    \exp_args:Nx \label {sref@\l_stex_ref_url_str}
    \stex_if_do_html:T {
      \pdfdest name "sref@\l_stex_ref_url_str" xyz\relax
    }
  }
}
\NewDocumentCommand \sreflabel {m} {\stex_ref_new_doc_target:n {#1}}

\cs_new_protected:Nn \_@@_add_doc_ref:nn {
  \seq_if_in:NnTF \g_@@_files_seq {#1} {
    \seq_if_in:cnF {g_@@_#1_seq}{#2}{
      \seq_gput_left:cn{g_@@_#1_seq}{#2}
    }
  }{
    \seq_gput_right:Nn \g_@@_files_seq {#1}
    \seq_new:c{g_@@_#1_seq}
    \seq_gput_left:cn{g_@@_#1_seq}{#2}
  }
}
\cs_generate_variant:Nn \_@@_add_doc_ref:nn {xo,xx}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\sref,\extref}
% Optional arguments:
%    \begin{macrocode}
\stex_keys_define:nnnn{sref / 1}{}{
  % TODO get rid of this
  fallback  .code:n = {},
  pre       .code:n = {},
  post      .code:n = {}
}{archive file}
\stex_keys_define:nnnn{sref / 2}{}{}{archive file, title}

\str_new:N \l_@@_default_archive_str
\str_new:N \l_@@_default_file_str
\tl_new:N \l_@@_default_title_tl

\cs_set_protected:Nn \_@@_set_keys_b:n {
  \tl_if_empty:nTF{#1}{
    \str_set_eq:NN \l_stex_key_archive_str \l_@@_default_archive_str
    \str_set_eq:NN \l_stex_key_file_str \l_@@_default_file_str
    \tl_set_eq:NN \l_stex_key_title_tl \l_@@_default_title_tl
  }{
    \stex_keys_set:nn{ sref / 2 }{ #1 }
  }
}

\newcommand\srefsetin[3][]{
  \str_set:Nx \l_@@_default_archive_str {#1}
  \str_set:Nx \l_@@_default_file_str {#2}
  \tl_set:Nn \l_@@_default_title_tl {#3}
}

%    \end{macrocode}
%
% Auxiliary methods:
%
%    \begin{macrocode}
\cs_new_protected:Nn \_@@_find_uri:n {
  \str_clear:N \l_@@_uri_str
  \stex_debug:nn{sref}{
    File:~\l_stex_key_file_str^^J
    Repo:\l_stex_key_archive_str
  }
  \str_if_empty:NTF \l_stex_key_file_str {
    \stex_debug:nn{sref}{Empty.~Checking~current~file~for~#1}
    \seq_if_exist:cT{g_@@_\stex_uri_use:N \l_stex_current_doc_uri _seq}{
      \exp_args:Nnx \_@@_find_uri_in_file:nnn{#1}
        {\stex_uri_use:N \l_stex_current_doc_uri}\seq_map_break:
    }
    \str_if_empty:NT \l_@@_uri_str {
      \seq_map_inline:Nn \g_@@_files_seq {
        \_@@_find_uri_in_file:nnn{#1}{##1}{\seq_map_break:n{\seq_map_break:}}
      }
    }
  }{
    \str_if_empty:NTF \l_stex_key_archive_str {
      \prop_if_exist:NTF \l_stex_current_archive_prop {
        \_@@_find_uri_in_prop_file:N \l_stex_current_archive_prop
      }{
        \stex_file_resolve:Nx \l_@@_file 
          { \stex_file_use:N \g_stex_current_file / .. / \l_stex_key_file_str }
        \str_set:Nx \l_@@_uri_str { file:/ \stex_file_use:N \l_@@_file }
      }
    }{
      \stex_require_archive:o \l_stex_key_archive_str
      \prop_set_eq:Nc \l_@@_prop { c_stex_mathhub_\l_stex_key_archive_str _manifest_prop }
      \_@@_find_uri_in_prop_file:N \l_@@_prop
    }
  }
}

\cs_new_protected:Nn \_@@_find_uri_in_prop_file:N {
  \str_set:Nx \l_@@_uri_str {
    \stex_file_use:N \c_stex_mathhub_file / 
    \prop_item:Nn #1 {id} /
      source / \l_stex_key_file_str .sref
  }
  \stex_file_resolve:No \l_@@_file \l_@@_uri_str
  \stex_uri_from_repo_file:NNNn \l_@@_uri #1
    \l_@@_file {narr}
  \str_set:Nx \l_@@_uri_str {\stex_uri_use:N \l_@@_uri}
}

\cs_new_protected:Nn \_@@_find_uri_in_file:nnn {
  \stex_debug:nn{sref}{Checking~file~#2}
  \seq_map_inline:cn{g_@@_#2_seq}{
    \str_if_eq:nnT{#1}{##1}{
      \str_set:Nx \l_@@_uri_str {\stex_uri_use:N \l_stex_current_doc_uri}
      \stex_debug:nn{sref}{Found.}
      #3
    }
  }
}
%    \end{macrocode}
% Doing the actual referencing:
%    \begin{macrocode}
\cs_new_protected:Nn \_@@_do_autoref:n {
  \cs_if_exist:cTF{autoref}{
     \exp_args:Nx\autoref{sref@#1}
   }{
     \exp_args:Nx\ref{sref@#1}
   }
}

\cs_new_protected:Nn \_@@_do_sref:nn {
  \str_if_empty:NTF \l_@@_uri_str {
    \str_if_empty:NTF \l_stex_key_file_str {
      \stex_debug:nn{sref}{autoref~on~\stex_uri_use:N \l_stex_current_doc_uri?#1}
      \exp_args:Ne \_@@_do_autoref:n{\stex_uri_use:N \l_stex_current_doc_uri ? #1}
    }{
      \stex_debug:nn{sref}{srefin~on~#1}
      \_@@_set_keys_b:n{ #2 }
      \_@@_do_sref_in:n{#1}
    }
  }{
    \exp_args:NNo \seq_if_in:NnTF \g_@@_files_seq \l_@@_uri_str {
      \stex_debug:nn{sref}{Using~ref~file~\l_@@_uri_str}
      \exp_args:Nnx \seq_if_in:cnTF{g_stex_ref_\l_@@_uri_str _seq}{\detokenize{#1}}{
        \stex_debug:nn{sref}{Reference~found~in~ref~files;~autoref~on~\l_@@_uri_str?#1}
        \_@@_do_autoref:n{\l_@@_uri_str?#1}
      }{
        \str_if_empty:NTF \l_stex_key_file_str {
          \stex_debug:nn{sref}{in~empty;~autoref~on~\l_@@_uri_str?#1}
          \_@@_do_autoref:n{\l_@@_uri_str?#1}
        }{
          \stex_debug:nn{sref}{in~non-empty;~srefin~on~\l_@@_uri_str?#1}
          \_@@_set_keys_b:n{ #2 }
          \_@@_do_sref_in:n{#1}
        }
      }
    }{
      \stex_debug:nn{sref}{No~ref~file~found~for~\l_@@_uri_str}
      \str_if_empty:NTF \l_stex_key_file_str {
        \stex_debug:nn{sref}{in~empty;~autoref~on~\l_@@_uri_str?#1}
        \_@@_do_autoref:n{\l_@@_uri_str?#1}
      }{
        \stex_debug:nn{sref}{in~non-empty;~srefin~on~\l_@@_uri_str?#1}
        \_@@_set_keys_b:n{ #2 }
        \_@@_do_sref_in:n{#1}
      }
    }
  }
}

\cs_new_protected:Nn \_@@_do_sref_in:n {
  \stex_debug:nn{sref}{In: \l_stex_key_file_str^^JRepo:\l_stex_key_archive_str}
  \stex_debug:nn{sref}{URI: \l_@@_uri_str?#1}
  \tl_if_exist:cTF{r@sref@\l_@@_uri_str?#1}{
    \_@@_do_autoref:n{\l_@@_uri_str?#1}
  }{
    %\msg_warning:nnn{stex}{warning/smsmissing}{<filename>}
    \group_begin:\catcode13=9\relax\catcode10=9\relax
      \str_if_empty:NTF \l_stex_key_archive_str {
        \prop_if_exist:NTF \l_stex_current_archive_prop {
          \str_set:Nx \l_@@_file_str {
            \stex_file_use:N \c_stex_mathhub_file /
            \prop_item:Nn \l_stex_current_archive_prop { id }
            / source / \l_stex_key_file_str .sref
          }
        }{
          \str_set:Nx \l_@@_file_str {
            \stex_file_use:N \g_stex_current_file / .. / \l_stex_key_file_str . sref
          }
        }
      }{
        \str_set:Nx \l_@@_file_str {
          \stex_file_use:N \c_stex_mathhub_file / \l_stex_key_archive_str
          / source / \l_stex_key_file_str . sref
        }
      }
      \stex_file_resolve:No \l_@@_file \l_@@_file_str
      \str_set:Nx \l_@@_file_str {\stex_file_use:N \l_@@_file }
      \stex_debug:nn{sref}{File: \l_@@_file_str }
      \exp_args:NNNx \exp_args:No \str_if_eq:nnTF \l_@@_file_str {\stex_file_use:N\c_stex_pwd_file / \jobname.sref}{
        \_@@_do_autoref:n{
          \str_if_empty:NF\l_@@_uri_str{\l_@@_uri_str?}#1
        }
      }{
        \exp_args:No \IfFileExists \l_@@_file_str {
          \tl_clear:N \l_@@_return_tl
          \str_set:Nn \l_@@_id_str {#1}
          \let\STEXInternalSrefRestoreTarget\_@@_restore_target:nnnnn
          \use:c{@ @ input}{\l_@@_file_str}
          \exp_args:No \tl_if_empty:nTF \l_@@_return_tl {
            \exp_args:Nnno \msg_warning:nnnn{stex}{warning/smslabelmissing}\l_@@_file_str{#1}
            \_@@_do_autoref:n{
              \str_if_empty:NF\l_@@_uri_str{\l_@@_uri_str?}#1
            }
          }{
            \l_@@_return_tl
          }
        }{
          \exp_args:Nnno \msg_warning:nnn{stex}{warning/smsmissing}\l_@@_file_str
          \_@@_do_autoref:n{
            \str_if_empty:NF\l_@@_uri_str{\l_@@_uri_str?}#1
          }
        }
      }
    \group_end:
  }
}

\cs_new_protected:Nn \_@@_do_return:nnnn {
  \tl_set:Nn \l_@@_return_tl {
    \stex_annotate:nn{shtml:sref={#4},shtml:srefin={\l_@@_file_str}}{
      \use:c{#3autorefname}~#1\tl_if_empty:nF{#2}{~(#2)}
      \tl_if_empty:NF\l_stex_key_title_tl{
        {}~in~\l_stex_key_title_tl
      }
    }
  }
}

\cs_new_protected:Nn \_@@_restore_target:nnnnn {
  \str_if_empty:NTF \l_@@_uri_str {
    \exp_args:No \str_if_eq:nnT \l_@@_id_str {#2}{
      \_@@_do_return:nnnn{#4}{#5}{#3}{#1?#2}
    }
  }{
    \stex_debug:nn{sref}{\l_@@_uri_str{}~ == ~ #1 ~ ?}
    \exp_args:No \str_if_eq:nnT \l_@@_uri_str {#1}{
      \stex_debug:nn{sref}{\l_@@_id_str~ == ~ #2 ~ ?}
      \exp_args:No \str_if_eq:nnT \l_@@_id_str {#2}{
        \stex_debug:nn{sref}{success!}
        \_@@_do_return:nnnn{#4}{#5}{#3}{#1?#2}
        \endinput
      }
    }
  }
}
%    \end{macrocode}
% The actual macros:
%    \begin{macrocode}
\NewDocumentCommand \sref { O{} m O{}}{
  \stex_keys_set:nn { sref / 1 }{ #1 }
  \_@@_find_uri:n { #2 }
  \_@@_do_sref:nn{#2}{#3}
}
\NewDocumentCommand \extref { O{} m m}{
  \stex_keys_set:nn { sref / 1 }{ #1 }
  \_@@_find_uri:n { #2 }
  \_@@_set_keys_b:n{ #3 }
  \str_if_empty:NT \l_stex_key_file_str {
    \msg_error:nn{stex}{error/extrefmissing}
  }
  \_@@_do_sref_in:n{#2}
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\stex_ref_new_sym_target:n}
%    \begin{macrocode}
\cs_new_protected:Nn \stex_ref_new_symbol:n {
  \cs_if_exist:cF{r@sref@sym@\tl_to_str:n{#1}}{
    \_@@_new_symbol:n{#1}
  }
}

\cs_new_protected:Nn \_stex_sref_do_aux:n {
  #1 \iow_now:Nn \@auxout {#1}
}

\cs_new_protected:Nn \_@@_new_symbol:n {
  \prop_if_exist:NTF \l_stex_current_archive_prop {
    \prop_get:NnNTF \l_stex_current_archive_prop {docurl} \l_@@_str {
      \exp_args:Ne \_stex_sref_do_aux:n {
        \STEXInternalSetSrefSymURL{#1}{\l_@@_str / symbol? #1}
      }
    }{
      \_stex_sref_do_aux:n { \STEXInternalSetSrefSymURL{#1}{} }
    }
  }{
    \_stex_sref_do_aux:n { \STEXInternalSetSrefSymURL{#1}{} }
  }
}

\cs_new_protected:Nn \stex_ref_new_sym_target:n {
  \cs_if_exist:NT \hypertarget{
    \exp_args:Ne \hypertarget{\tl_to_str:n{sref@sym@ #1}}{}
    \str_gset:cx{\tl_to_str:n{r@sref@sym@ #1}}{\tl_to_str:n{sref@sym@ #1}}
  }
}

\cs_new_protected:Nn \stex_ref_new_sym_target:nn {
  \str_if_eq:nnTF{#1}{#2}{
    \stex_ref_new_sym_target:n{#1}
  }{
    \str_gset:cn{g_stex_sref_sym_ #1 _label}{#2}
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\srefsym}
%    \begin{macrocode}
\NewDocumentCommand \srefsym { m m}{
  \stex_get_symbol:n { #1 }
  \exp_args:Ne 
  \_@@_sym_aux:nn{\l_stex_get_symbol_mod_str ? \l_stex_get_symbol_name_str}
}

\cs_new_protected:Npn \_@@_do_internal_link:nn #1 {
  \cs_if_exist:NTF \hyperlink {
    \hyperlink{#1}
  }\use:n
}

\cs_new_protected:Npn \_@@_do_url_link:nn {
  \cs_if_exist:NTF \href \href \use_ii:nn
}

\cs_new_protected:Npn \_@@_sym_aux:nn #1 {
  \cs_if_exist:cTF{\tl_to_str:n{r@sref@sym@#1}}{
    \exp_args:Ne \_@@_do_internal_link:nn{\tl_to_str:n{sref@sym@#1}}
  }{
    \str_if_exist:cTF{g_stex_sref_sym_#1_label}{
      \exp_args:Ne \_@@_sym_aux:nn{\use:c{g_stex_sref_sym_#1_label}}
    }{
      \str_if_empty:cTF{g_stex_sref_sym_#1_target}{
        \exp_args:Ne \_@@_do_internal_link:nn{\tl_to_str:n{sref@sym@#1}}
      }{
        \exp_args:Ne \_@@_do_url_link:nn{\use:c{g_stex_sref_sym_#1_target}}
      }
    }
  }
}
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\srefsymuri}
%    \begin{macrocode}
\cs_new_protected:Npn \srefsymuri #1 {
  \_@@_sym_aux:nn{#1}
}
%    \end{macrocode}
% \end{macro}
%
% \end{sfragment}
%
% \begin{sfragment}{Inputs}
%    \begin{macrocode}
%<@@=stex_inputs>
%    \end{macrocode}
%
% \begin{macro}{\stex_resolve_path_pair:Nnn,\stex_resolve_path_pair:Nxx}
%    \begin{macrocode}
\cs_new_protected:Nn \stex_resolve_path_pair:Nnn {
  \stex_debug:nn{resolving~path}{#3~in~[#2]}
  \str_if_empty:nTF{#2}{
    \prop_if_exist:NTF \l_stex_current_archive_prop {
      \str_set:Nx #1 {\stex_file_use:N \c_stex_mathhub_file / 
      \prop_item:Nn \l_stex_current_archive_prop { id } / source /
      #3}
      \stex_debug:nn{resolving~path}{In~current~archive~
        \prop_item:Nn \l_stex_current_archive_prop { id }
        ;~result:~#1}
    }{
      \str_set:Nx #1 {\stex_file_use:N \c_stex_pwd_file / .. / #3 }
      \stex_debug:nn{resolving~path}{No~current~archive;~result:~#1}
    }
  }{
    \stex_require_archive:n { #2 }
    \str_set:Nx #1 {\stex_file_use:N \c_stex_mathhub_file / 
    \prop_item:cn {c_stex_mathhub_#2_manifest_prop} { id } / source /
    #3}
    \stex_debug:nn{resolving~path}{result:~#1}
  }
}
\cs_generate_variant:Nn \stex_resolve_path_pair:Nnn {Nxx}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\inputref,\mhinput,\ifinputref}
%    \begin{macrocode}
\newif \ifinputref \inputreffalse

\cs_new_protected:Nn \_@@_mhinput:nn {
  \stex_in_archive:nn {#1} {
    \ifinputref
      \stex_input_with_hooks:n{ \stex_file_use:N \c_stex_mathhub_file / ##1 / source / #2 }
    \else
      \inputreftrue
        \stex_input_with_hooks:n{ \stex_file_use:N \c_stex_mathhub_file / ##1 / source / #2 }
      \inputreffalse
    \fi
  }
}

\NewDocumentCommand \mhinput { O{} m}{
  \exp_args:NNx\exp_args:Nnx\_@@_mhinput:nn{ \tl_to_str:n{#1} }{ \tl_to_str:n{#2} }
}

\cs_new_protected:Nn \_@@_inputref_html:nn {
  \str_clear:N \l_tmpa_str
  \prop_get:NnNF \l_stex_current_archive_prop { narr } \l_tmpa_str {
    \prop_get:NnNF \l_stex_current_archive_prop { ns } \l_tmpa_str {}
  }
  \tl_if_empty:nTF{ #1 }{
    \IfFileExists{#2}{
      \ifvmode\noindent\fi\stex_annotate_invisible:nn{shtml:inputref={
        \l_tmpa_str / #2
      }}{}
    }{
      \stex_input_with_hooks:n{#2}
    }
  }{
    \IfFileExists{ \stex_file_use:N \c_stex_mathhub_file / #1 / source / #2 }{
      \ifvmode\noindent\fi\stex_annotate_invisible:nn{shtml:inputref={
        \l_tmpa_str / #2
      }}{}
    }{
      \input{ \stex_file_use:N \c_stex_mathhub_file / #1 / source / #2 }
    }
  }
}

\cs_new_protected:Nn \_@@_inputref_pdf:nn {
  \begingroup
    \inputreftrue
    \tl_if_empty:nTF{ #1 }{
      \stex_input_with_hooks:n{#2}
    }{
      \stex_input_with_hooks:n{ \stex_file_use:N \c_stex_mathhub_file / #1 / source / #2 }
    }
  \endgroup
}

\cs_new_protected:Nn \_@@_inputref:nn {
  \stex_in_archive:nn {#1} {
    \stex_if_html_backend:TF 
      \_@@_inputref_html:nn
      \_@@_inputref_pdf:nn
    {##1}{#2}
  }
}

\NewDocumentCommand \inputref { O{} m}{
  \exp_args:NNx \exp_args:Nnx \_@@_inputref:nn{ \tl_to_str:n{#1} }{ \tl_to_str:n{#2} }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\addmhbibresource}
%    \begin{macrocode}
\cs_new_protected:Nn \_@@_bibresource:n {
  \_@@_up_archive:nn{#1}{bib}
  \seq_if_empty:NTF \l_@@_libinput_files_seq {
    \msg_error:nnxx{stex}{error/nofile}{\exp_not:N\addmhbibresource}{#1.bib}
  }{
    \seq_map_inline:Nn \l_@@_libinput_files_seq {
      \addbibresource{ ##1 }
    }
  }
}
\newcommand\addmhbibresource[2][]{
  \tl_if_empty:nTF{#1}{
    \_@@_bibresource:n{#2}
  }{
    \stex_in_archive:nn{#1}{\_@@_bibresource:n{#2}}
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\IfInputref}
%    \begin{macrocode}
\stex_if_html_backend:TF{
  \newcommand \IfInputref[2]{
    \stex_annotate:nn{shtml:ifinputref=true}{#1}
    \stex_annotate:nn{shtml:ifinputref=false}{#2}
  }
}{
  \newcommand \IfInputref[2]{
    \ifinputref #1 \else #2 \fi
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\libinput}
%    \begin{macrocode}
\cs_new_protected:Nn \_@@_up_archive:nn {
  \prop_if_exist:NF \l_stex_current_archive_prop {
    \msg_error:nnn{stex}{error/notinarchive}\libinput
  } 
  \prop_get:NnNF \l_stex_current_archive_prop {id} \l_@@_id_str {
    \msg_error:nnn{stex}{error/notinarchive}\libinput
  }
  \seq_clear:N \l_@@_libinput_files_seq
  \seq_set_eq:NN \l_@@_path_seq \c_stex_mathhub_file
  \seq_set_split:NnV \l_@@_id_seq / \l_@@_id_str

  \bool_while_do:nn { ! \seq_if_empty_p:N \l_@@_id_seq }{
    \str_set:Nx \l_@@_path_str {\stex_file_use:N \l_@@_path_seq / meta-inf / lib / #1.#2}
    \IfFileExists{ \l_@@_path_str }{
      \exp_args:NNo \seq_if_in:NnF \l_@@_libinput_files_seq \l_@@_path_str {
        \seq_put_right:No \l_@@_libinput_files_seq \l_@@_path_str
      }
    }{}
    \seq_pop_left:NN \l_@@_id_seq \l_@@_path_str
    \seq_put_right:No \l_@@_path_seq \l_@@_path_str
  }

  \str_set:Nx \l_@@_path_str {\stex_file_use:N \l_@@_path_seq / lib / #1.#2}
  \IfFileExists{ \l_@@_path_str }{
    \exp_args:NNo \seq_if_in:NnF \l_@@_libinput_files_seq \l_@@_path_str {
      \seq_put_right:No \l_@@_libinput_files_seq \l_@@_path_str
    }
  }{}
}

\cs_new_protected:Nn \_@@_libinput:n {
  \_@@_up_archive:nn{#1}{tex}
  \seq_if_empty:NTF \l_@@_libinput_files_seq {
    \msg_error:nnxx{stex}{error/nofile}{\exp_not:N\libinput}{#1.tex}
  }{
    \seq_map_inline:Nn \l_@@_libinput_files_seq {
      \input{ ##1 }
    }
  }
}

\newcommand \libinput [2][] {
  \tl_if_empty:nTF{#1}{
    \_@@_libinput:n{#2}
  }{
    \stex_in_archive:nn{#1}{\_@@_libinput:n{#2}}
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\libusepackage}
%    \begin{macrocode}
\newcommand\libusepackage[2][]{
  \_@@_up_archive:nn{#2}{sty}
  \int_compare:nNnTF {\seq_count:N \l_@@_libinput_files_seq} = 1 {
    \str_set:Nx \l_@@_tmp_str {\seq_item:Nn \l_@@_libinput_files_seq 1}
    \exp_args:Nne \use:n {\usepackage[#1]} {
      \str_range:Nnn\l_@@_tmp_str 1 {-5}
    }
  }{
    \stex_fatal_error:nnn{error/nofile}{\libusepackage}{#1.sty}
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\mhgraphics,\cmhgraphics,\lstinputmhlisting,\clstinputmhlisting,\mhtikzinput,\cmhtikzinput}
%    \begin{macrocode}
\str_new:N \l_@@_gin_repo_str
\ltx@ifpackageloaded{graphicx}{\use:n}{\AtEndOfPackageFile{graphicx}}{
  \define@key{Gin}{archive}{
    \tl_set:Nx\Gin@mhrepos{\stex_file_use:N \c_stex_mathhub_file / #1 / source /}
  }
  \providecommand\mhgraphics[2][]{
    \tl_set:Nx\Gin@mhrepos{
      \stex_file_use:N \c_stex_mathhub_file / \prop_item:Nn \l_stex_current_archive_prop {id} / source /
    }
    \setkeys{Gin}{#1}
    \includegraphics[#1]{ \Gin@mhrepos #2 }
  }
  \providecommand\cmhgraphics[2][]{\begin{center}\mhgraphics[#1]{#2}\end{center}}    
}

\ltx@ifpackageloaded{listings}{\use:n}{\AtEndOfPackageFile{listings}}{
  \define@key{lst}{archive}{
    \def\lst@mhrepos{\stex_file_use:N \c_stex_mathhub_file / #1 / source /}
  }
  \newcommand\lstinputmhlisting[2][]{%
    \def\lst@mhrepos{
      \stex_file_use:N \c_stex_mathhub_file / \prop_item:Nn \l_stex_current_archive_prop {id} / source /
    }
    \setkeys{lst}{#1}%
    \lstinputlisting[#1]{\lst@mhrepos #2}}
  \newcommand\clstinputmhlisting[2][]{\begin{center}\lstinputmhlisting[#1]{#2}\end{center}}
}

\ltx@ifpackageloaded{tikzinput}{\use:n}{\AtEndOfPackageFile{tikzinput}}{  
  \define@key{Gin}{archive}{
    \str_set:Nn \l_@@_gin_repo_str {#1}
    \def\Gin@mhrepos{\stex_file_use:N \c_stex_mathhub_file / #1 / source /}
  }
  \newcommand\mhtikzinput[2][]{%
    \str_clear:N \l_@@_gin_repo_str
    \def\Gin@mhrepos{
      \stex_file_use:N \c_stex_mathhub_file / \prop_item:Nn \l_stex_current_archive_prop {id} / source /
    }
    \setkeys{Gin}{#1}%
    \exp_args:No \stex_in_archive:nn \l_@@_gin_repo_str {
      \tikzinput[#1]{\Gin@mhrepos #2}
    }
  }
  \newcommand\cmhtikzinput[2][]{\begin{center}\mhtikzinput[#1]{#2}\end{center}}
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\libusetikzlibrary}
%    \begin{macrocode}
\cs_new_protected:Nn \_@@_usetikzlibrary_i:nn {
  \pgfkeys@spdef\pgf@temp{#1}
  \expandafter\ifx\csname tikz@library@\pgf@temp @loaded\endcsname\relax%
  \expandafter\global\expandafter\let\csname tikz@library@\pgf@temp @loaded\endcsname=\pgfutil@empty%
  \expandafter\edef\csname tikz@library@#1@atcode\endcsname{\the\catcode`\@}
  \expandafter\edef\csname tikz@library@#1@barcode\endcsname{\the\catcode`\|}
  \expandafter\edef\csname tikz@library@#1@dollarcode\endcsname{\the\catcode`\$}
  \catcode`\@=11
  \catcode`\|=12
  \catcode`\$=3
  \pgfutil@InputIfFileExists{#2}{}{}
  \catcode`\@=\csname tikz@library@#1@atcode\endcsname
  \catcode`\|=\csname tikz@library@#1@barcode\endcsname
  \catcode`\$=\csname tikz@library@#1@dollarcode\endcsname
}

\cs_new_protected:Nn \_@@_usetikzlibrary:n{
  \_@@_up_archive:nn{tikzlibrary#1}{code.tex}
  \int_compare:nNnTF {\seq_count:N \l_@@_libinput_files_seq} = 1 {
    \exp_args:Nne \_@@_usetikzlibrary_i:nn{#1}{ \seq_item:Nn \l_@@_libinput_files_seq 1 }
  }{
    \stex_fatal_error:nnn{error/nofile}{\libusetikzlibrary}{tikzlibrary#1.code.tex}
  }
}

\newcommand \libusetikzlibrary [2][] {
  \cs_if_exist:NF \usetikzlibrary {
    \msg_error:nnx{stex}{error/notikz}{\tl_to_str:n{\libusetikzlibrary}}
  }
  \tl_if_empty:nTF{#1}{
    \_@@_usetikzlibrary:n{#2}
  }{
    \stex_in_archive:nn{#1}{\_@@_usetikzlibrary:n{#2}}
  }
}
%    \end{macrocode}
% \end{macro}
%
% \end{sfragment}
%
% \end{sfragment}
%
% \begin{sfragment}{SMS Mode}
%    \begin{macrocode}
%<@@=stex_smsmode>
%    \end{macrocode}
%
% Macros and environments allowed in sms mode:
%    \begin{macrocode}
\tl_new:N \g_@@_allowed_tl
\tl_new:N \g_@@_allowed_escape_tl
\seq_new:N \g_@@_allowedenvs_seq
%    \end{macrocode}
%
% \begin{macro}{\stex_sms_allow:N,\stex_sms_allow_escape:N,\stex_sms_allow_env:n}
%    \begin{macrocode}
\cs_new_protected:Nn \stex_sms_allow:N {
  \tl_gput_right:Nn \g_@@_allowed_tl {#1}
}

\cs_new_protected:Nn \stex_sms_allow_escape:N {
  \tl_gput_right:Nn \g_@@_allowed_escape_tl {#1}
}

\cs_new_protected:Nn \stex_sms_allow_env:n {
  \exp_args:NNx \seq_gput_right:Nn \g_@@_allowedenvs_seq {\tl_to_str:n{#1}}
}
%    \end{macrocode}
% \end{macro}
% Some initial allowed macros:
%    \begin{macrocode}
\stex_sms_allow:N \makeatletter
\stex_sms_allow:N \makeatother
\stex_sms_allow:N \ExplSyntaxOn
\stex_sms_allow:N \ExplSyntaxOff
\stex_sms_allow:N \rustexBREAK
%    \end{macrocode}
%
% \begin{macro}[pTF]{\stex_if_smsmode:}
%    \begin{macrocode}
\bool_new:N \g_@@_bool
\bool_set_false:N \g_@@_bool
\prg_new_conditional:Nnn \stex_if_smsmode: { p, T, F, TF } {
  \bool_if:NTF \g_@@_bool \prg_return_true: \prg_return_false:
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\stex_sms_allow_import:Nn, \stex_sms_allow_import_env:nn}
%    \begin{macrocode}
\tl_new:N \g_@@_allowed_import_tl
\seq_new:N \g_@@_allowed_import_env_seq
\cs_new_protected:Nn \stex_sms_allow_import:Nn {
  \tl_gput_right:Nn \g_@@_allowed_import_tl {#1}
  \tl_gset:cn{\tl_to_str:n{#1}~-~smsmode} {#2}
}
\cs_new_protected:Nn \stex_sms_allow_import_env:nn {
  \exp_args:NNx \seq_gput_right:Nn \g_@@_allowed_import_env_seq {\tl_to_str:n{#1}}
  \tl_gset:cn{\tl_to_str:n{#1}~-~env~-~smsmode} {#2}
}

\tl_new:N \g_stex_sms_import_code
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\stex_file_in_smsmode:nn,\stex_file_in_smsmode:on}
%    \begin{macrocode}
\cs_new_protected:Nn \_@@_in_smsmode:n { \stex_suppress_html:n {
  \vbox_set:Nn \l_tmpa_box {
    \bool_set_true:N \g_@@_bool
    \bool_set_false:N \_stex_html_do_output_bool
    #1
  }
  %\box_clear:N \l_tmpa_box
} }

\quark_new:N \q_@@_break

\cs_new_protected:Nn \_@@_start_smsmode:n {
  \everyeof{\q_@@_break\exp_not:N}
  \let\stex_smsmode_do:\_@@_smsmode_do:
  \exp_after:wN \exp_after:wN \exp_after:wN
  \stex_smsmode_do:
  \cs:w @ @ input\cs_end: "#1" \relax
}

\cs_new_protected:Nn \stex_file_in_smsmode:nn {
  \seq_gclear:N \l_@@_importmodules_seq
  \seq_gclear:N \l_@@_sigmodules_seq
  \tl_clear:N \g_stex_sms_import_code
  \group_begin:
    \let \l_stex_metatheory_uri \c_stex_default_metatheory
    \cs_set:Npn \stex_check_term:n ##1 {}
    \seq_clear:N \l_stex_all_modules_seq
    \str_clear:N \l_stex_current_module_str
    #2
    \stex_filestack_push:n{#1}
    \_@@_in_smsmode:n {
      \let \_@@_do_aux_curr:N \_@@_do_aux_imports:N
      \tl_map_inline:Nn \g_@@_allowed_import_tl {
        \use:c{\tl_to_str:n{##1}~-~smsmode}
      }
      \seq_map_inline:Nn \g_@@_allowed_import_env_seq {
        \use:c{\tl_to_str:n{##1}~-~env~-~smsmode}
      }
      \_@@_start_smsmode:n{#1}
    }
    \_@@_in_smsmode:n \g_stex_sms_import_code
    \_@@_in_smsmode:n {
      \let \_@@_do_aux_curr:N \_@@_do_aux_normal:N
      \_@@_start_smsmode:n{#1}
    }
    \stex_filestack_pop:
  \group_end:
}
\cs_generate_variant:Nn \stex_file_in_smsmode:nn {on}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\stex_smsmode_do:}
%    \begin{macrocode}
\cs_new_protected:Nn \_@@_smsmode_do: {
 %\stex_if_smsmode:T {
    \_@@_do:w
  %}
}
\let\stex_smsmode_do:\relax


\cs_new:Nn \_@@_check_cs:NNn {
  \exp_after:wN\if\exp_after:wN\relax\exp_not:N#3
  \exp_after:wN#1\exp_after:wN#3\else
  \exp_after:wN#2\fi
}

\cs_new_protected:Npn \_@@_do:w #1 {
  \exp_args:Nx \tl_if_empty:nTF { \tl_tail:n{ #1 }}{
    \_@@_check_cs:NNn \_@@_do_aux:N \_@@_do:w { #1 }
  }{
    \_@@_do:w
  }
}

\cs_new_protected:Nn \_@@_do_aux:N {
  \cs_if_eq:NNF #1 \q_@@_break {
    \_@@_do_aux_curr:N #1
  }
}

\cs_new_protected:Nn \_@@_do_aux_imports:N {
 % \stex_debug:nn{sms}{Checking~\tl_to_str:n{#1}~in~import}
  \tl_if_in:NnTF \g_@@_allowed_import_tl {#1} {
    \stex_debug:nn{sms}{Executing~\tl_to_str:n{#1}~in~import}
    #1
  }{
    \cs_if_eq:NNTF \begin #1 {
      \_@@_check_begin:Nn \g_@@_allowed_import_env_seq
    }{
      \cs_if_eq:NNTF \end #1 {
        \_@@_check_end:Nn \g_@@_allowed_import_env_seq
      }{
        \_@@_do:w
      }
    }
  }
}

\cs_new_protected:Nn \_@@_do_aux_normal:N {
 % \stex_debug:nn{sms}{Checking~\tl_to_str:n{#1}~in~sms~mode}
  \tl_if_in:NnTF \g_@@_allowed_tl {#1} {
    \stex_debug:nn{sms}{Executing~\tl_to_str:n{#1}}
    #1\_@@_do:w
  }{
    \tl_if_in:NnTF \g_@@_allowed_escape_tl {#1} {
      \stex_debug:nn{sms}{Executing~escaped~\tl_to_str:n{#1}}
      #1
    }{
      \cs_if_eq:NNTF \begin #1 {
        \_@@_check_begin:Nn \g_@@_allowedenvs_seq
      }{
        \cs_if_eq:NNTF \end #1 {
          \_@@_check_end:Nn \g_@@_allowedenvs_seq
        }{
          \_@@_do:w
        }
      }
    }
  }
}

\cs_new_protected:Nn \_@@_check_begin:Nn {
 % \stex_debug:nn{sms}{Checking~environment~#2}
  \seq_if_in:NxTF #1 { \tl_to_str:n{#2} }{
    \stex_debug:nn{sms}{Environment~#2}
    \begin{#2}
  }{
    \_@@_do:w
  }
}
\cs_new_protected:Nn \_@@_check_end:Nn {
%  \stex_debug:nn{sms}{Checking~end~environment~#2}
  \seq_if_in:NxTF #1 { \tl_to_str:n{#2} }{
    \stex_debug:nn{sms}{End~Environment~#2}
    \end{#2}\_@@_do:w
  }{
    %\str_if_eq:nnTF{#2}{document} \endinput 
    \_@@_do:w
  }
}
%    \end{macrocode}
% \end{macro}
%
% \end{sfragment}
%
% \begin{sfragment}{Modules}
%
% \begin{sfragment}{The smodule-environment}
%    \begin{macrocode}
%<@@=stex_modules>
%    \end{macrocode}
%
% \begin{variable}{\l_stex_current_module_str}
%  The current module:
%    \begin{macrocode}
\str_new:N \l_stex_current_module_str
%    \end{macrocode}
% \end{variable}
%
% \begin{variable}{\l_stex_all_modules_seq}
%   Stores all modules currently in scope
%    \begin{macrocode}
\seq_new:N \l_stex_all_modules_seq
%    \end{macrocode}
% \end{variable}
%
%
% \begin{macro}{\stex_every_module:n}
%    \begin{macrocode}
%<@@=stex_module_setup>
\tl_clear:N \g_stex_every_module_tl {
}
\cs_new_protected:Nn \stex_every_module:n {
  \tl_gput_right:Nn \g_stex_every_module_tl { #1 }
}
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\stex_module_setup:n}
% Sets up a new module:
%    \begin{macrocode}
\cs_new_protected:Npn \stex_module_setup:n {
  \stex_if_in_module:TF \_@@_setup_nested:n \_@@_setup_top:n
}

\cs_new_protected:Nn \_@@_setup_top:n {
  \_@@_get_uri_str:n{#1}
  \stex_debug:nn{module}{Module~URI:~\l_@@_ns_str?#1}
  \str_if_empty:NTF \l_stex_key_sig_str
  \_stex_module_setup_top_nosig:n \_@@_setup_top_sig:n {\l_@@_ns_str?#1}
  \stex_metagroup_new:o \l_stex_current_module_str
  \g_stex_every_module_tl
  \stex_execute_in_module:x {
    \_stex_do_deprecation:n{#1}
  }
  \_@@_load_meta:
}

\cs_new_protected:Nn \_stex_module_setup_top_nosig:n {  
  \stex_if_module_exists:nTF{#1}{
    \stex_debug:nn{modules}{(already exists)}
  }{
    \tl_gclear:c{c_stex_module_ #1 _code}
    \prop_gclear:c{c_stex_module_ #1 _morphisms_prop }
    \prop_gclear:c{c_stex_module_ #1 _symbols_prop }
    \prop_gclear:c{c_stex_module_ #1 _notations_prop }
  }
  \str_set:Nx \l_stex_current_module_str {#1}
  \seq_put_right:No \l_stex_all_modules_seq \l_stex_current_module_str
}

\cs_new_protected:Nn \_@@_setup_top_sig:n {
  \stex_if_module_exists:nTF{#1}{
    \stex_debug:nn{modules}{(already exists)}
  }{
    \stex_debug:nn{modules}{(needs loading)}
    \_@@_load_sig:
  }    
  %\stex_if_smsmode:F { % WHY?
    \stex_activate_module:x {
      #1
    }
  %}
  \str_set:Nx\l_stex_current_module_str{#1}
}

\cs_new_protected:Nn \_@@_load_sig: {
  \stex_file_split_off_ext:NN \l_@@_sigfile \g_stex_current_file
  \stex_file_split_off_lang:NN \l_@@_sigfile \l_@@_sigfile
  \exp_args:Ne \stex_file_in_smsmode:nn {
    \stex_file_use:N \l_@@_sigfile . \l_stex_key_sig_str . tex
  }{}
}

\cs_new_protected:Nn \_@@_setup_nested:n {
  \exp_after:wN 
    \_@@_split_module:n \l_stex_current_module_str \_@@_end: {#1}
  \stex_debug:nn{module}{Nested~Module~URI:~\l_stex_current_module_str}
  \seq_put_right:No \l_stex_all_modules_seq \l_stex_current_module_str
  \stex_metagroup_new:o \l_stex_current_module_str
}


\cs_new_protected:Nn \_@@_get_uri_str:n {
  \str_clear:N \l_@@_ns_str
  \stex_map_uri:Nnnnn \l_stex_current_ns_uri {
    \str_set:Nx \l_@@_ns_str{##1\c_colon_str/}
  }{
    \seq_set_split:Nnn \l_@@_seq / {##1}
    \seq_pop_right:NN \l_@@_seq \l_@@_seg
    \exp_args:No \str_if_eq:nnF \l_@@_seg {#1} {
      \seq_put_right:No \l_@@_seq \l_@@_seg
    }
    \tl_put_right:Nx \l_@@_ns_str {\seq_use:Nn \l_@@_seq /}
  }{}{}
}

\cs_new_protected:Npn \_@@_split_module:n #1?#2 \_@@_end: #3 {
  \_stex_module_setup_top_nosig:n { #1 ? #2 / #3}
}

\bool_new:N \l_stex_in_meta_bool
\bool_set_false:N \l_stex_in_meta_bool

\cs_new_protected:Nn \_@@_load_meta: {
  \tl_if_empty:NF \l_stex_metatheory_uri {
    \stex_execute_in_module:x{
      \stex_pseudogroup_with:nn{\l_stex_in_meta_bool}{
        \stex_activate_module:n {\stex_uri_use:N \l_stex_metatheory_uri }
      }
    }
  }
}

%<@@=stex_modules>
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\stex_close_module:}
%    \begin{macrocode}
\cs_new:Nn \stex_close_module: {
  \bool_if:NT \c_stex_persist_write_mode_bool \_@@_persist_module:
  \stex_debug:nn{module}{
    Closing~module~\l_stex_current_module_str^^J
    Code:~\expandafter\meaning\csname c_stex_module_\l_stex_current_module_str _code\endcsname^^J
    Imports:\exp_after:wN \prop_to_keyval:N \cs:w c_stex_module_\l_stex_current_module_str _morphisms_prop\cs_end:^^J
    Declarations:\exp_after:wN \prop_to_keyval:N \cs:w c_stex_module_\l_stex_current_module_str _symbols_prop\cs_end:^^J
    Notations:\exp_after:wN \prop_to_keyval:N \cs:w c_stex_module_\l_stex_current_module_str _notations_prop\cs_end:^^J
  }
}

\cs_new_protected:Nn \_@@_persist_module: {
  \stex_persist:e {
    \_@@_restore_module:nnnn {\l_stex_current_module_str}{
      \exp_after:wN \prop_to_keyval:N \cs:w 
        c_stex_module_\l_stex_current_module_str _morphisms_prop
      \cs_end:
    }{
      \exp_after:wN \prop_to_keyval:N \cs:w 
        c_stex_module_\l_stex_current_module_str _symbols_prop
      \cs_end:
    }{
      \exp_after:wN \exp_after:wN \exp_after:wN \exp_not:n
      \exp_after:wN \exp_after:wN \exp_after:wN
      { \cs:w c_stex_module_\l_stex_current_module_str _code \cs_end: }
    }{}
    \prop_map_function:cN{c_stex_module_\l_stex_current_module_str _notations_prop}
      \_@@_persist_nots_i:nn
    \exp_not:N \STEXRestoreNotsEnd {}
  }
}

\cs_new_protected:Nn \_@@_restore_module:nnnn {
  \prop_gset_from_keyval:cn{c_stex_module_\tl_to_str:n{#1}_morphisms_prop}{#2}
  \cs_set:Npn \_@@_tl {#3}
  \exp_args:Nno \prop_gset_from_keyval:cn{c_stex_module_\tl_to_str:n{#1}_symbols_prop}\_@@_tl
  \prop_map_inline:cn{c_stex_module_\tl_to_str:n{#1}_symbols_prop}{
    \stex_ref_new_symbol:n{#1?##1}
  }
  \cs_gset:cpn{c_stex_module_\tl_to_str:n{#1}_code}{#4}
  \prop_gclear:c{c_stex_module_\tl_to_str:n{#1} _notations_prop}
  \str_set:Nn \l_@@_restore_mod_str {#1}
  \group_begin:
    \catcode`_=8\relax
    \catcode`:=12\relax
    \_@@_restore_nots:n
}

\cs_new:Nn \_@@_persist_nots_i:nn {
  \exp_not:n{#2}
}

\quark_new:N \STEXRestoreNotsEnd

\cs_new_protected:Nn \_@@_restore_nots:n {
  \_@@_restore_nots_i:n
}

\cs_new_protected:Nn \_@@_restore_nots_i:n {
  \tl_if_eq:nnTF{#1}{\STEXRestoreNotsEnd}{
    \group_end:
  }{
    \_@@_restore_nots_ii:nnnnn {#1}
  }
}

\cs_new_protected:Nn \_@@_restore_nots_ii:nnnnn {
  \cs_set:Npn \l_@@_tl {{#4}{#5}}
  \exp_args:NNe\use:nn\prop_gput:cnn{
    {c_stex_module_\l_@@_restore_mod_str _notations_prop}
    {\tl_to_str:n{#1!#2}}{
      {\tl_to_str:n{#1}}{\tl_to_str:n{#2}}{#3}
      \exp_args:No \exp_not:n \l_@@_tl
    }
  }
  \_@@_restore_nots_i:n
}
%    \end{macrocode}
% \end{macro}
%
% \begin{variable}{\l_stex_metatheory_uri}
%    \begin{macrocode}
\tl_new:N \l_stex_metatheory_uri
%    \end{macrocode}
% \end{variable}
%
% \begin{macro}{\setmetatheory}
%    \begin{macrocode}
\cs_new_protected:Nn \_@@_set_metatheory:nn {
  \group_begin:
    \stex_debug:nn{metatheory}{Setting~metatheory~[#1]#2}
    \stex_import_module_uri:nn { #1 } { #2 }
    \stex_debug:nn{metatheory}{Here:^^J
      \l_stex_import_archive_str^^J
      \l_stex_import_path_str^^J
      \l_stex_import_name_str^^J
    }
    \stex_import_require_module:ooo
      \l_stex_import_archive_str
      \l_stex_import_path_str
      \l_stex_import_name_str
    \stex_debug:nn{metatheory}{Found:~\l_stex_import_ns_str}
    \exp_args:Nne \use:nn {
      \group_end: \stex_uri_resolve:Nn \l_stex_metatheory_uri
    }{{\l_stex_import_ns_str}}
}

\NewDocumentCommand \setmetatheory {O{} m}{
  \_@@_set_metatheory:nn { #1 }{ #2 }
  \stex_smsmode_do:
}
\stex_sms_allow_escape:N \setmetatheory
%    \end{macrocode}
% \end{macro}
%
% Keys and key handling:
%
%    \begin{macrocode}
\stex_keys_define:nnnn{smodule}{
  \str_clear:N \l_stex_key_sig_str
}{
  meta          .code:n       = {
    \str_if_empty:nTF {#1}{
      \tl_clear:N \l_stex_metatheory_uri
    }{
      \stex_uri_resolve:Nx \l_stex_metatheory_uri { #1 }
    }
  },
  ns            .code:n       = {
    \stex_uri_resolve:Nx \l_stex_current_ns_uri { #1 }
  } ,
  lang          .code:n       = {
    \stex_set_language:n { #1 }
  } ,
  sig           .str_set_x:N  = \l_stex_key_sig_str ,
  creators      .code:n       = {} , % todo ?
  contributors  .code:n       = {} , % todo ?
  srccite       .code:n       = {}   % todo ?
}{id, title, style, deprecate}
%    \end{macrocode}
%
% \begin{environment}{smodule}
%    \begin{macrocode}
\stex_new_stylable_env:nnnnnnn {module} {O{} m}{
  \stex_keys_set:nn { smodule }{ #1 }
  \tl_set_eq:NN \thistitle \l_stex_key_title_tl
  \tl_if_empty:NF \thistitle {
    \exp_args:No \stexdoctitle \thistitle
  }
  \exp_args:Nx \stex_module_setup:n { \tl_to_str:n{ #2 } }

  \stex_if_do_html:T {
    \exp_args:Nne \begin{stex_annotate_env} {
      shtml:theory={\l_stex_current_module_str},
      shtml:language={ \l_stex_current_language_str},
      shtml:signature={\l_stex_key_sig_str}
      \tl_if_empty:NF \l_stex_metatheory_uri {,
        shtml:metatheory={\stex_uri_use:N \l_stex_metatheory_uri}
      }
    }
    \stex_annotate_invisible:n{}
  }
  \stex_if_smsmode:F {
    \str_set_eq:NN \thismoduleuri \l_stex_current_module_str
    \tl_set:Nn \thismodulename {#2}
    \stex_style_apply:
  }
  \stex_smsmode_do:
}{
  \stex_close_module:
  \stex_if_smsmode:F \stex_style_apply:
  \stex_if_do_html:T{ \end{stex_annotate_env} }
}{}{}{s}

\stex_sms_allow_env:n{smodule}
%    \end{macrocode}
% \end{environment}
%
%
% \begin{macro}[pTF]{\stex_if_in_module:}
% Are we currently in a module?
%    \begin{macrocode}
\prg_new_conditional:Nnn \stex_if_in_module: {p, T, F, TF} {
  \str_if_empty:NTF \l_stex_current_module_str
    \prg_return_false: \prg_return_true:
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[pTF]{\stex_if_module_exists:n}
% Does a module with this URI exist?
%    \begin{macrocode}
\prg_new_conditional:Nnn \stex_if_module_exists:n {p, T, F, TF} {
  \tl_if_exist:cTF { c_stex_module_#1_code }
    \prg_return_true: \prg_return_false:
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\stex_do_up_to_module:n,\stex_do_up_to_module:x}
% Execute code in the current module (i.e. as if the \cs{begin}\Arg{smodule}
% was the current tex group)
%    \begin{macrocode}
\cs_new_protected:Nn \stex_do_up_to_module:n {
  \exp_args:No \stex_metagroup_do_in:nn \l_stex_current_module_str {#1}
}
\cs_generate_variant:Nn \stex_do_up_to_module:n {x}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\stex_module_add_code:n,\stex_module_add_code:x}
%    \begin{macrocode}
\cs_new_protected:Nn \stex_module_add_code:n {
  \tl_gput_right:cn {c_stex_module_\l_stex_current_module_str _code} { #1 }
}
\cs_generate_variant:Nn \stex_module_add_code:n {x}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\stex_execute_in_module:n,\stex_execute_in_module:x}
%    \begin{macrocode}
\cs_new_protected:Nn \stex_execute_in_module:n { \stex_if_in_module:TF {
  \stex_module_add_code:n { #1 }
  \stex_do_up_to_module:n { #1 }
}{ #1 }}
\cs_generate_variant:Nn \stex_execute_in_module:n {x}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\STEXexport}
%    \begin{macrocode}
\NewDocumentCommand \STEXexport {} {
  \ExplSyntaxOn
  \_@@_export:n
}
\cs_new_protected:Nn \_@@_export:n {
  \stex_ignore_spaces_and_pars:#1\ExplSyntaxOff
  \stex_module_add_code:n { \stex_ignore_spaces_and_pars:#1}
  \stex_smsmode_do:
}
%    \end{macrocode}
% Only allowed in modules, and allowed (escaped) in sms mode:
%    \begin{macrocode}
\stex_deactivate_macro:Nn \STEXexport {module~environments}
\stex_sms_allow_escape:N \STEXexport
\stex_every_module:n {\stex_reactivate_macro:N \STEXexport}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\stex_module_add_morphism:nnnn, \stex_module_add_morphism:nonn, \stex_module_add_morphism:ooox}
%    \begin{macrocode}
\cs_new_protected:Nn \stex_module_add_morphism:nnnn {
  \exp_args:Nne \prop_gput:cnn{c_stex_module_\l_stex_current_module_str _morphisms_prop}{
    \tl_if_empty:nTF{#1}{[#2]}{#1}
  }{{#1}{#2}{#3}{#4}}
}
\cs_generate_variant:Nn \stex_module_add_morphism:nnnn {nonn,ooox}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\stex_module_add_symbol:nnnnnnN}
% \begin{arguments}
%   \item \Arg{Macro name}
%   \item \Arg{Name}
%   \item \Arg{arity}
%   \item \{(\Arg{Arg num}\Arg{Arg str})$^\ast$\}
%   \item Definiens
%   \item type
%   \item Return
%   \item Command
% \end{arguments}
%    \begin{macrocode}
\cs_new_protected:Nn \stex_module_add_symbol:nnnnnnnN {
  \stex_debug:nn{declaration}{New~declaration:~\l_stex_current_module_str?#2^^J
    Macro:#1^^JArity:#3~(#4)^^J
    Def:~\tl_to_str:n{#5}^^J
    Type:~\tl_to_str:n{#6}^^J
    Returns:~\tl_to_str:n{#7}
  }
  %\prop_gput:cnx{c_stex_module_\l_stex_current_module_str _symbols_prop}
  %{#2}{\exp_not:n{{#1}{#2}{#3}{#4}{#5}{#6}}{#7}\exp_not:n{#8}}
  \prop_gput:cnn{c_stex_module_\l_stex_current_module_str _symbols_prop}
  {#2}{{#1}{#2}{#3}{#4}{#5}{#6}{#7}{#8}}
  \tl_if_empty:nF{#1}{
    \stex_execute_in_module:n {
      \_@@_activate_sym:n {#2}
    }
  }
}

\cs_new_protected:Nn \_@@_activate_sym:n {
  \prop_map_inline:cn{c_stex_module_\l_stex_current_module_str _symbols_prop}{
    \str_if_eq:nnT{#1}{##1}{
      \_@@_activate_i:nnnnnnnn ##2
    }
  }
}
\cs_new_protected:Nn \_@@_activate_i:nnnnnnnn {
  \stex_debug:nn{activating}{#1:\l_stex_current_module_str^^J
    \tl_to_str:n{{#2}{#3}{#4}{#5}{#6}{#7}#8}
  }
  \cs_set:cpx{#1} {
    \_stex_invoke_symbol:nnnnnnnN 
    {\l_stex_current_module_str}
    \exp_not:n{{#2}{#3}{#4}{#5}{#6}{#7}{#8}}
  }
  \stex_debug:nn{activating}{done}
  \prop_map_break:
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\stex_module_add_notation:nnnnn, \stex_module_add_notation:eoeoo,\stex_set_notation_macro:nnnnn}
%   \begin{arguments}
%     \item URI
%     \item variant
%     \item arity
%     \item macro body
%     \item op
%   \end{arguments}
%    \begin{macrocode}
\cs_new_protected:Nn \stex_module_add_notation:nnnnn {
  \stex_debug:nn{notations}{Adding~notation:^^J
    #1~\c_hash_str#2~#3^^J
    to~\l_stex_current_module_str
  }
  \prop_gput:cnn{c_stex_module_\l_stex_current_module_str _notations_prop}
  {#1!#2}{{#1}{#2}{#3}{#4}{#5}}
  \stex_execute_in_module:n {
    \_@@_activate_not:nn{#1}{#2}
  }
}
\cs_generate_variant:Nn \stex_module_add_notation:nnnnn {eoeoo}


\cs_new_protected:Nn \_@@_activate_not:nn {
  \prop_map_inline:cn{c_stex_module_\l_stex_current_module_str _notations_prop}{
    \str_if_eq:nnT{#1!#2}{##1}{
      \prop_map_break:n{\stex_set_notation_macro:nnnnn ##2 }
    }
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\stex_set_notation_macro:nnnnn,\stex_set_notation_macro:eoexo}
%    \begin{macrocode}
\cs_new_protected:Nn \stex_set_notation_macro:nnnnn {
  \tl_set:cn {l_stex_notation_#1_#2_cs}{#4}
  \cs_if_exist:cF{l_stex_notation_#1__cs}{
    \tl_set:cn {l_stex_notation_#1__cs}{#4}
  }
  \tl_if_empty:nF{#5}{
    \tl_set:cn{l_stex_notation_#1_op_#2_cs}{#5}
    \cs_if_exist:cF{l_stex_notation_#1_op__cs}{
      \cs_set_eq:cc {l_stex_notation_#1_op__cs}{l_stex_notation_#1_op_#2_cs}
    }
  }
}
\cs_generate_variant:Nn \stex_set_notation_macro:nnnnn {eoexo}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\stex_activate_module:n,\stex_activate_module:o,\stex_activate_module:x}
%    \begin{macrocode}
\cs_new_protected:Nn \stex_activate_module:n {
  \seq_if_in:NnF \l_stex_all_modules_seq { #1 } {
    \stex_debug:nn{modules}{Activating~module~#1^^J\expandafter\meaning\csname c_stex_module_#1_code\endcsname}
    \seq_put_right:Nn \l_stex_all_modules_seq { #1 }
    \stex_pseudogroup:nn{
      \str_set:Nn \l_stex_current_module_str {#1}
      \use:c{ c_stex_module_#1_code }
    }{
      \stex_pseudogroup_restore:N \l_stex_current_module_str
    }
  }
}
\cs_generate_variant:Nn \stex_activate_module:n {o,x}
%    \end{macrocode}
% \end{macro}
%
% Iterating:
%    \begin{macrocode}
%<@@=stex_iterate>
%    \end{macrocode}
%
% \begin{macro}{\stex_iterate_symbols:n}
%    \begin{macrocode}
\cs_new_protected:Nn \stex_iterate_symbols:n {
  \stex_pseudogroup_with:nn{\_@@_sym_cs:nnnnnnnnN\stex_iterate_break:\stex_iterate_break:n}{
    \cs_set:Npn \_@@_sym_cs:nnnnnnnnN 
    ##1 ##2 ##3 ##4 ##5 ##6 ##7 ##8 ##9 { #1 }
    \cs_set:Npn \stex_iterate_break: {
      \prop_map_break:n{\seq_map_break:}
    }
    \cs_set:Npn \stex_iterate_break:n ##1 {
      \prop_map_break:n{\seq_map_break:n{##1}}
    }
    \seq_map_inline:Nn \l_stex_all_modules_seq {
      \prop_map_inline:cn{c_stex_module_##1_symbols_prop}{
        \_@@_sym_cs:nnnnnnnnN {##1} ####2
      }
    }
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\stex_iterate_symbols:nn}
%    \begin{macrocode}
\cs_new_protected:Nn \stex_iterate_symbols:nn {
  \seq_clear:N \l_@@_mods_seq
  \stex_pseudogroup_with:nn{\_@@_sym_cs:nnnnnnnnN}{
    \cs_set:Npn \_@@_sym_cs:nnnnnnnnN 
    ##1 ##2 ##3 ##4 ##5 ##6 ##7 ##8 ##9 { #2 }
    \clist_map_function:nN {#1} \_@@_it_decl_i:n
  }
}

\cs_new_protected:Nn \_@@_it_decl_i:n {
  \seq_if_in:NnF \l_@@_mods_seq {#1} {
    \seq_put_left:Nn \l_@@_mods_seq {#1}
    \prop_map_inline:cn{c_stex_module_#1_morphisms_prop}{
      \_@@_it_decl_check:nnnn ##2
    }
    \prop_map_inline:cn{c_stex_module_#1_symbols_prop}{
      \_@@_sym_cs:nnnnnnnnN {#1} ##2
    }
  }
}
\cs_new_protected:Nn \_@@_it_decl_check:nnnn {
  \tl_if_empty:nT{#1}{
    \_@@_it_decl_i:n {#2}
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\stex_iterate_notations:nn}
%    \begin{macrocode}
\cs_new_protected:Nn \stex_iterate_notations:nn {
  \seq_clear:N \l_@@_mods_seq
  \stex_pseudogroup_with:nn{\_@@_not_cs:nnnnn}{
    \cs_set:Npn \_@@_not_cs:nnnnn 
    ##1 ##2 ##3 ##4 ##5 { #2 }
    \clist_map_function:nN {#1} \_@@_it_not_i:n
  }
}

\cs_new_protected:Nn \_@@_it_not_i:n {
  \seq_if_in:NnF \l_@@_mods_seq {#1} {
    \seq_put_left:Nn \l_@@_mods_seq {#1}
    \prop_map_inline:cn{c_stex_module_#1_notations_prop}{
      \_@@_not_cs:nnnnn ##2
    }
    \prop_map_inline:cn{c_stex_module_#1_morphisms_prop}{
      \_@@_it_not_check:nnnn ##2
    }
  }
}
\cs_new_protected:Nn \_@@_it_not_check:nnnn {
  \tl_if_empty:nT{#1}{
    \_@@_it_not_i:n {#2}
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\stex_iterate_morphisms:nn}
%    \begin{macrocode}
\cs_new_protected:Nn \stex_iterate_morphisms:nn {
  \seq_clear:N \l_@@_mods_seq
  \bool_set_true:N \l_@@_continue_bool
  \cs_set:Npn \_@@_morphism_cs:nnnn ##1 ##2 ##3 ##4 ##5 { 
    #2 
    \bool_if:NT \l_@@_continue_bool {
      \str_if_eq:nnTF{##1}{[##2]}{
        \tl_put_right:Nn \l_@@_todo_tl {
          \_@@_iterate_morphism:nn{##5}{##2}
        }
      }{
        \tl_put_right:Nn \l_@@_todo_tl {
          \_@@_iterate_morphism:nn{##5 / ##1}{##2}
        }
      }
    }
  }
  \cs_set:Npn \stex_iterate_break:n ##1 {
    \bool_set_false:N \l_@@_continue_bool
    \prop_map_break:n{##1}
  }
  \_@@_iterate_morphism:nn{}{#1}
}

\cs_new_protected:Nn \_@@_iterate_morphism:nn {
  \tl_clear:N \l_@@_todo_tl
  \seq_if_in:NnF \l_@@_mods_seq {#1 #2}{
    \seq_put_right:Nn \l_@@_mods_seq {#1 #2}
    \prop_map_inline:cn{c_stex_module_#2_morphisms_prop}{
      \_@@_morphism_cs:nnnn ##2 {#1}
      % TODO
      % ##1: name or [mpath]
      % ##2 = {####1}{####2}{####3}{####4}
      % ####1 = name
      % ####2 = mpath
      % ####3 = type
      % ####4 = {origname}{newname}*
    }
    \bool_if:NT \l_@@_continue_bool \l_@@_todo_tl
  }
}
%    \end{macrocode}
% \end{macro}
%
% \end{sfragment}
%
% \begin{sfragment}{Structural Features}
%    \begin{macrocode}
%<@@=stex_features>
%    \end{macrocode}
%
% \begin{macro}{\stex_structural_feature_module:nn,\stex_structural_feature_module_end:}
%    \begin{macrocode}
\cs_new_protected:Nn \stex_structural_feature_module:nn {
  \stex_if_do_html:TF {
    \exp_args:Nne \begin{stex_annotate_env} {
      shtml:feature-#2={
       \l_stex_current_module_str/#1}
      \str_if_empty:NF \l_stex_macroname_str {,
        shtml:macroname={\l_stex_macroname_str}
      }
    }
    \stex_annotate_invisible:n{}
  }\group_begin:
  \stex_module_setup:n {#1-module}
}

\cs_new_protected:Nn \stex_structural_feature_module_end: {
  \tl_gset_eq:NN \g_stex_last_feature_str \l_stex_current_module_str
  \stex_close_module:
  \stex_if_do_html:TF{
    \end{stex_annotate_env}
  }\group_end:
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\stex_structural_feature_morphism:nnn,\stex_structural_feature_morphism_end:}
%    \begin{macrocode}
\bool_new:N \l_@@_implicit_bool
\cs_new_protected:Nn \stex_structural_feature_morphism:nnnnn {
  \str_clear:N \l_stex_current_domain_str
  \tl_if_empty:nT{#3}{
    \_stex_get_mathstructure:n{#4}
    \str_set_eq:NN \l_stex_current_domain_str \l_stex_get_structure_module_str
  }
  \str_if_empty:NT \l_stex_current_domain_str {
    \stex_import_module_uri:nn { #3 }{ #4 }
    \group_begin:
    \stex_import_require_module:ooo
      \l_stex_import_archive_str
      \l_stex_import_path_str
      \l_stex_import_name_str
    \exp_args:Nnx \use:nn \group_end: {
      \str_set:Nn \exp_not:N\l_stex_current_domain_str {\l_stex_import_ns_str}
    }
  }
  \tl_if_empty:nTF{#1}{
    \bool_set_true:N \l_@@_implicit_bool
    \str_set:Nx \l_tmpa_str {[\l_stex_current_domain_str]}
  }{
    \bool_set_false:N \l_@@_implicit_bool
    \str_set:Nn \l_tmpa_str {#1}
  }

  \stex_if_do_html:TF {
    \begin{stex_annotate_env} {
      shtml:feature-#2={\l_stex_current_module_str?\l_tmpa_str},
      shtml:domain={\l_stex_current_domain_str}
      #5
    }
    \stex_annotate_invisible:n{}
  }\group_begin:
  \str_set:Nn \l_@@_feature_str {#2}
  \str_set_eq:NN \l_stex_feature_name_str \l_tmpa_str
  \_@@_setup:
  \_@@_reactivate:
  %^^A\stex_activate_module:o \l_stex_current_domain_str
  \exp_args:Ne \stex_metagroup_new:n {\l_stex_current_module_str / \l_stex_feature_name_str}
}

\cs_new_protected:Nn \_@@_do_for_list: {
  \seq_clear:N \l_stex_fors_seq
  \clist_map_inline:Nn \l_stex_key_for_clist {
    \exp_args:Ne\stex_get_in_morphism:n{\tl_to_str:n{##1}}
    \seq_put_right:Nx \l_stex_fors_seq 
      {\l_stex_get_symbol_mod_str ? \l_stex_get_symbol_name_str}
  }
}

\cs_new_protected:Nn \_@@_add_definiens:nn {
  \_@@_set_definiens_macros: #1\_@@_break:
  \_stex_assign_do:n{#2}
  #2
}
\cs_new_protected:Npn \_@@_set_definiens_macros: #1?#2?#3\_@@_break: {
  \str_set:Nn \l_stex_get_symbol_mod_str {#1?#2}
  \str_set:Nn \l_stex_get_symbol_name_str {#3}
  \exp_args:Nne\use:nn{\_@@_set_definiens_macros_i:nnnnnnn}{
    \prop_item:Nn \l_stex_morphism_symbols_prop {[#1?#2]/[#3]}
  }
}
\cs_new_protected:Nn \_@@_set_definiens_macros_i:nnnnnnn {
  \tl_set:Nn \l_stex_get_symbol_def_tl{#4}
}

\cs_new_protected:Nn \stex_structural_feature_morphism_end: {
  \str_gset_eq:NN \l_stex_feature_name_str \l_stex_feature_name_str
  \str_gset_eq:NN \l_stex_current_domain_str \l_stex_current_domain_str
  \seq_gset_eq:NN \l_stex_morphism_symbols_prop \l_stex_morphism_symbols_prop
  \seq_gset_eq:NN \l_stex_morphism_renames_prop \l_stex_morphism_renames_prop
  \seq_gset_eq:NN \l_stex_morphism_morphisms_seq \l_stex_morphism_morphisms_seq
  \_@@_do_elaboration:
  \stex_if_do_html:TF{
    \end{stex_annotate_env}
  }\group_end:
}

\cs_new_protected:Nn \_@@_setup: {
  \prop_clear:N \l_stex_morphism_symbols_prop
  \prop_clear:N \l_stex_morphism_renames_prop
  \seq_clear:N \l_stex_morphism_morphisms_seq
  \_@@_do_decls:
  \exp_args:No \_@@_do_morphisms:n \l_stex_current_domain_str
}

\cs_new_protected:Nn \_@@_rename_all: {

}

\cs_new:Npn \_@@_clean:nnw [#1] / #2 \_stex_end: {
  [#1]/[#2]
}

\cs_new_protected:Nn \_@@_do_decls: {
  \exp_args:No \stex_iterate_symbols:nn \l_stex_current_domain_str {
    \stex_str_if_starts_with:nnTF{##3}[{
      \exp_args:NNe \prop_put:Nnn \l_stex_morphism_symbols_prop {
        \_@@_clean:nnw ##3 \_stex_end:
      }
    }{
    \prop_put:Nnn \l_stex_morphism_symbols_prop 
      {[##1]/[##3]}
    }{
      {##2}{##4}{##5}{##6}{##7}{##8}##9
    }
  }
}

\cs_new_protected:Nn \stex_structural_feature_morphism_check_total: {
  \prop_map_inline:Nn \l_stex_morphism_symbols_prop {
    \_@@_total_check: ##1 ##2
  }
}

\cs_new_protected:Npn \_@@_total_check: [#1]/[#2] #3 #4 #5 #6 #7 #8 #9 {
  \tl_if_empty:nT{#6}{
    \msg_error:nnxx{stex}{error/needsdefiniens}{#1?#2}{total~morphism}
  }
}

\cs_new:Npn \_@@_split_qm:w #1 ? #2 ? #3 { #3 }
\cs_new_protected:Nn \_@@_do_elaboration: {
  \stex_debug:nn{morphisms}{
    Elaborating:^^J\prop_to_keyval:N \l_stex_morphism_symbols_prop
    ^^J
    Renamings:^^J
    \prop_to_keyval:N \l_stex_morphism_renames_prop
  }
  \prop_map_inline:Nn \l_stex_morphism_symbols_prop {
    \_@@_elab_check: ##1 ##2
  }
  \exp_args:No\stex_iterate_notations:nn\l_stex_current_domain_str{
    \prop_get:NnNTF \l_stex_morphism_renames_prop {##1}\l_@@_tmp {
      \exp_args:Ne \stex_module_add_notation:nnnnn 
      {\l_stex_current_module_str ? \exp_after:wN \use_ii:nn \l_@@_tmp}
    }{
      \exp_args:Ne \stex_module_add_notation:nnnnn 
      {\l_stex_current_module_str ? \l_stex_feature_name_str
       / \_@@_split_qm:w ##1}
    }{##2}{##3}{##4}{##5}
  }
  \stex_module_add_morphism:ooox
    \l_stex_feature_name_str
    \l_stex_current_domain_str
    \l_@@_feature_str
    {\prop_map_function:NN \l_stex_morphism_renames_prop \_@@_rename:nn}
}

\cs_new:Nn \_@@_rename:nn{
  {#1}{\use_ii:nn#2}
}

\cs_new_protected:Npn \_@@_elab_check: [#1]/[#2] #3 {
  \prop_get:NnNTF \l_stex_morphism_renames_prop {#1?#2} \l_@@_tmp {
    \stex_debug:nn{morphisms}{Generating~\l_@@_tmp}
    \exp_after:wN \stex_module_add_symbol:nnnnnnnN \l_@@_tmp
  }{
    \bool_if:NTF \l_@@_implicit_bool {
      \stex_debug:nn{morphisms}{Generating~#3:~\l_stex_feature_name_str / #2}
      \exp_args:Nno \stex_module_add_symbol:nnnnnnnN {#3}{\l_stex_feature_name_str / #2}
    }{
      \stex_debug:nn{morphisms}{Generating~\l_stex_feature_name_str / #2}
      \exp_args:Nno \stex_module_add_symbol:nnnnnnnN {}{\l_stex_feature_name_str / #2}
    }
  }
}

\cs_new_protected:Nn \_@@_do_morphisms:n {
    \prop_map_inline:cn {c_stex_module_#1_morphisms_prop}{
      \_@@_do_morph:nnnn ##2
    }
}

\cs_new_protected:Nn \_@@_do_morph:nnnn {
    \tl_if_empty:nF{#3}{
      \seq_put_right:Nn \l_stex_morphism_morphisms_seq {{#1}{#2}{#3}}
    }
    \_@@_do_morphisms:n{#2}
}

\cs_new_protected:Npn \_@@_reactivate: {
  \stex_deactivate_macro:Nn \symdecl {module~environments}
  \stex_deactivate_macro:Nn \textsymdecl {module~environments}
  \stex_deactivate_macro:Nn \symdef {module~environments}
  \stex_deactivate_macro:Nn \notation {module~environments}
  \stex_deactivate_macro:Nn \importmodule {module~environments}
  \stex_deactivate_macro:Nn \requiremodule {module~environments}
  \stex_deactivate_macro:Nn \smodule {outside~of~morphisms}
  \stex_reactivate_macro:N \assign
  \stex_reactivate_macro:N \assignMorphism
  \stex_reactivate_macro:N \renamedecl
  \cs_set_eq:NN \_stex_do_for_list: \_@@_do_for_list:
  \cs_set_eq:NN \_stex_add_definiens:nn \_@@_add_definiens:nn
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\stex_get_in_morphism:n}
%    \begin{macrocode}
\cs_new_protected:Nn \stex_get_in_morphism:n {
  \str_clear:N \l_stex_get_symbol_name_str
  \prop_map_inline:Nn \l_stex_morphism_symbols_prop {
    \exp_args:Nx\_@@_get_check:nnnn{\tl_to_str:n{#1}}##1##2
  }
  \str_if_empty:NT \l_stex_get_symbol_name_str {
    \prop_map_inline:Nn \l_stex_morphism_renames_prop {
      \_@@_renamed_check:nnnnn{#1}##1=##2
    }
    \str_if_empty:NT \l_stex_get_symbol_name_str {
      \msg_error:nnxx{stex}{error/unknownsymbolin}{#1}{
        morphism~\l_stex_feature_name_str
      }
    }
  }
}

\cs_new_protected:Npn \_@@_renamed_check:nnnnn #1#2?#3?#4=#5#6 {
  \str_if_eq:nnTF{#1}{#5}{
    \exp_args:Nnx \use:nn{\_@@_check_break:nnnnnnnnn{#2?#3}{#4}}{
      \prop_item:Nn \l_stex_morphism_symbols_prop {[#2?#3]/[#4]}
    }
  }{
    \str_if_eq:nnT{#1}{#6}{
      \exp_args:Nnx \use:nn{\_@@_check_break:nnnnnnnnn{#2?#3}{#4}}{
        \prop_item:Nn \l_stex_morphism_symbols_prop {[#2?#3]/[#4]}
      }
    }
  }
}

\cs_new_protected:Npn \_@@_get_check:nnnn #1[#2]/[#3]#4 {
  \str_if_eq:nnTF{#1}{#3}{
    \_@@_check_break:nnnnnnnnn{#2}{#3}{#4}
  }{
    \str_if_eq:nnTF{#1}{#4}{
      \_@@_check_break:nnnnnnnnn{#2}{#3}{#4}
    }{
      \use_none:nnnnnn
    }
  }
}

\cs_new_protected:Nn \_@@_check_break:nnnnnnnnn {
  \prop_map_break:n{
    \str_set:Nn \l_stex_get_symbol_mod_str{#1}
    \str_set:Nn \l_stex_get_symbol_name_str{#2}
    \str_set:Nn \l_stex_get_symbol_macro_str{#3}
    \int_set:Nn \l_stex_get_symbol_arity_int {#4}
    \tl_set:Nn \l_stex_get_symbol_args_tl {#5}
    \tl_set:Nn \l_stex_get_symbol_def_tl {#6}
    \tl_set:Nn \l_stex_get_symbol_type_tl {#7}
    \tl_set:Nn \l_stex_get_symbol_return_tl {#8}
    \tl_set:Nn \l_stex_get_symbol_invoke_cs {#9}
  }
}
%    \end{macrocode}
% \end{macro}
%
% \end{sfragment}
%
% \end{sfragment}
%
%
% \begin{sfragment}{Inheritance}
%
% \begin{sfragment}{\cs{importmodule}/\cs{usemodule}}
%    \begin{macrocode}
%<@@=stex_importmodule>
%    \end{macrocode}
%
% \begin{macro}{\usemodule}
%    \begin{macrocode}
\stex_new_stylable_cmd:nnnn {usemodule} { O{} m } {
  \stex_import_module_uri:nn { #1 }{ #2 }
  \stex_import_require_module:ooo
    \l_stex_import_archive_str
    \l_stex_import_path_str
    \l_stex_import_name_str
  \stex_if_do_html:T {
    \hbox{\stex_annotate_invisible:nn 
      {shtml:usemodule=\l_stex_import_ns_str} {}}
  }
  \stex_if_smsmode:F{
    \group_begin:
    \tl_set_eq:NN \thismoduleuri \l_stex_import_ns_str
    \tl_set_eq:NN \thismodulename \l_stex_import_name_str
    \tl_clear:N \thisstyle
    \stex_style_apply:
    \group_end:
  }
}{}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\stex_import_module_uri:nn}
%    \begin{macrocode}
\cs_new_protected:Nn \stex_import_module_uri:nn {
  \stex_debug:nn{importmodule}{URI:~>#1<~>#2<}
  \exp_args:NNnx \seq_set_split:Nnn \_@@_seq ? { \tl_to_str:n{ #2 } }
  \seq_pop_right:NN \_@@_seq \l_stex_import_name_str
  \str_set:Nx \l_stex_import_path_str { \seq_use:Nn \_@@_seq ? }
  \tl_if_empty:nTF { #1 } {
    \stex_debug:nn{importmodule}{No~archive}
    \prop_if_exist:NTF \l_stex_current_archive_prop {
      \stex_debug:nn{importmodule}{Picking~current~archive}
      \str_set:Nx \l_stex_import_archive_str {
        \prop_item:Nn \l_stex_current_archive_prop { id }
      }
    }{
      \str_clear:N \l_stex_import_archive_str
      \str_set:Nn \l_stex_import_uri_str {file:}
      \str_if_empty:NTF \l_stex_import_path_str {
        \stex_debug:nn{importmodule}{Empty~Path}
        \stex_file_split_off_ext:NN \l_@@_path_seq \g_stex_current_file
        \stex_file_split_off_lang:NN \l_@@_path_seq \l_@@_path_seq
        \str_set:Nx \l_stex_import_path_str {
          \stex_file_use:N \l_@@_path_seq
        }
      }{
        \stex_debug:nn{importmodule}{Resolving~path~\l_stex_import_path_str~relative~to~\stex_file_use:N \g_stex_current_file}
        \stex_file_resolve:Nx \l_@@_seq { \stex_file_use:N \g_stex_current_file / .. / \l_stex_import_path_str}
        \str_set:Nx \l_stex_import_path_str {
          \stex_file_use:N \l_@@_seq
        }
        \stex_debug:nn{importmodule}{...yields~\l_stex_import_path_str}
      }
    }
  } {
    \stex_debug:nn{importmodule}{Archive~#1}
    \str_set:Nx \l_stex_import_archive_str { #1 }
    \stex_require_archive:o \l_stex_import_archive_str
    \str_set:Nx \l_stex_import_uri_str { \prop_item:cn{ c_stex_mathhub_ \l_stex_import_archive_str _manifest_prop}{ ns } }
  }
}
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\stex_import_require_module:nnn,\stex_import_require_module:ooo}
%    \begin{macrocode}
\cs_new_protected:Npn \stex_import_require_module:nnn #1 {
  \tl_if_empty:nTF { #1 } {
    \str_clear:N \l_@@_archive_str
    \str_set:Nn \l_stex_import_uri_str {file:}
    \_@@_get_module:nnn {}
  }{
    \stex_require_archive:n { #1 }
    \str_set:Nx \l_@@_archive_str {#1}
    \str_set:Nx \l_stex_import_uri_str { \prop_item:cn{ c_stex_mathhub_ #1 _manifest_prop}{ ns } }
    \str_set:Nx \l_@@_str { \stex_file_use:N \c_stex_mathhub_file / #1 / source }
    \exp_args:No \_@@_get_module:nnn \l_@@_str
  }
}
\cs_generate_variant:Nn \stex_import_require_module:nnn {ooo}

\cs_new_protected:Npn \stex_import_require_module_safe:nnn #1 {
  \tl_if_empty:nTF { #1 } {
    \str_clear:N \l_@@_archive_str
    \str_set:Nn \l_stex_import_uri_str {file:}
    \_@@_get_module_safe:nnn {}
  }{
    \stex_require_archive:n { #1 }
    \str_set:Nx \l_@@_archive_str {#1}
    \str_set:Nx \l_stex_import_uri_str { \prop_item:cn{ c_stex_mathhub_ #1 _manifest_prop}{ ns } }
    \str_set:Nx \l_@@_str { \stex_file_use:N \c_stex_mathhub_file / #1 / source }
    \exp_args:No \_@@_get_module_safe:nnn \l_@@_str
  }
}

\cs_new_protected:Nn \_@@_get_module_uri:nnn {
  \tl_if_empty:nF {#2}{
    \str_set:Nx \l_stex_import_uri_str {\l_stex_import_uri_str / #2}
  }
  \stex_debug:nn{importmodule}{~>#1<^^J>#2<^^J>#3<^^J>\l_stex_import_uri_str<^^J
    Current~file:\stex_file_use:N \g_stex_current_file^^J
    Current~namespace:\stex_uri_use:N \l_stex_current_ns_uri
  }
  \stex_if_module_exists:nTF {\l_stex_import_uri_str?#3} {
    \str_set:Nx \l_stex_import_ns_str {\l_stex_import_uri_str?#3}
  }{
    \stex_if_module_exists:nTF{\stex_uri_use:N \l_stex_current_ns_uri ? #3}{
      \str_set:Nx \l_stex_import_ns_str {\stex_uri_use:N \l_stex_current_ns_uri ? #3}
    }{
      \_@@_get_from_file:nnn{#1}{#2}{#3}
      \str_set:Nx \l_stex_import_ns_str {\l_stex_import_uri_str?#3}
    }
  }
}
\cs_new_protected:Nn \_@@_get_module_uri_safe:nnn {
  \tl_if_empty:nF {#2}{
    \str_set:Nx \l_stex_import_uri_str {\l_stex_import_uri_str / #2}
  }
  \stex_debug:nn{importmodule}{~>#1<^^J>#2<^^J>#3<^^J>\l_stex_import_uri_str<^^J
    Current~file:\stex_file_use:N \g_stex_current_file^^J
    Current~namespace:\stex_uri_use:N \l_stex_current_ns_uri
  }
  \stex_if_module_exists:nTF {\l_stex_import_uri_str?#3} {
    \str_set:Nx \l_stex_import_ns_str {\l_stex_import_uri_str?#3}
  }{
    \stex_if_module_exists:nTF{\stex_uri_use:N \l_stex_current_ns_uri ? #3}{
      \str_set:Nx \l_stex_import_ns_str {\stex_uri_use:N \l_stex_current_ns_uri ? #3}
    }{
      \_@@_get_from_file_safe:nnn{#1}{#2}{#3}
      \str_set:Nx \l_stex_import_ns_str {\l_stex_import_uri_str?#3}
    }
  }
}

\cs_new_protected:Nn \_@@_get_module:nnn {
  \stex_debug:nn{importmodule}{Requiring~>[#1]#2?#3<}
  \_@@_get_module_uri:nnn{#1}{#2}{#3}
  \stex_activate_module:o \l_stex_import_ns_str
}

\cs_new_protected:Nn \_@@_get_module_safe:nnn {
  \stex_debug:nn{importmodule}{Requiring~>[#1]#2?#3<}
  \_@@_get_module_uri_safe:nnn{#1}{#2}{#3}
}

\cs_new_protected:Nn \_@@_get_from_file:nnn {
  \stex_file_resolve:Nx \l_@@_seq { \tl_if_empty:nF{ #1 }{ #1 / } #2 }
  \str_set:Nx \l_@@_str {\stex_file_use:N \l_@@_seq}
  \stex_debug:nn{imports}{Looking~for~\l_stex_import_uri_str?#3...}
  \_@@_check_file:nn{ /#3.tex }{
    \_@@_check_file:nn{/#3.\l_stex_current_language_str .tex}{
      \_@@_check_file:nn{/#3.en.tex}{
        \_@@_check_file:nn{.tex}{
          \_@@_check_file:nn{.\l_stex_current_language_str .tex}{
            \_@@_check_file:nn{.en.tex}{
              \msg_error:nnx{stex}{error/unknownmodule}{\l_stex_import_uri_str?#3}
            }
          }
        }
      }
    }
  }
  \stex_if_smsmode:TF{
    \exp_args:NNo \exp_args:Nnx \str_if_eq:nnTF{\l_@@_str}{\stex_file_use:N \g_stex_current_file}{
      \stex_debug:nn{imports}{Skipping~current~file}
    }{
      \_@@_load_file:n{#3}
    }
  }{
    \_@@_load_file:n{#3}
  }
}
\cs_new_protected:Nn \_@@_get_from_file_safe:nnn {
  \stex_file_resolve:Nx \l_@@_seq { \tl_if_empty:nF{ #1 }{ #1 / } #2 }
  \str_set:Nx \l_@@_str {\stex_file_use:N \l_@@_seq}
  \stex_debug:nn{imports}{Looking~for~\l_stex_import_uri_str?#3...}
  \_@@_check_file:nn{ /#3.tex }{
    \_@@_check_file:nn{/#3.\l_stex_current_language_str .tex}{
      \_@@_check_file:nn{/#3.en.tex}{
        \_@@_check_file:nn{.tex}{
          \_@@_check_file:nn{.\l_stex_current_language_str .tex}{
            \_@@_check_file:nn{.en.tex}{
            }
          }
        }
      }
    }
  }
  \stex_if_smsmode:TF{
    \exp_args:NNo \exp_args:Nnx \str_if_eq:nnTF{\l_@@_str}{\stex_file_use:N \g_stex_current_file}{
      \stex_debug:nn{imports}{Skipping~current~file}
    }{
      \IfFileExists{ \l_@@_str }{
      \_@@_load_file:n{#3}
      }{}
    }
  }{
    \IfFileExists{ \l_@@_str }{
    \_@@_load_file:n{#3}
    }{}
  }
}

\cs_new_protected:Nn \_@@_load_file:n {
  \stex_file_in_smsmode:on \l_@@_str {
    \str_if_empty:NF \l_@@_archive_str {
      \stex_set_current_archive:n \l_@@_archive_str
    }
    \stex_debug:nn{modules}{Loading~\l_@@_str}
  }
  \stex_if_module_exists:nF {\l_stex_import_uri_str?#1} {
    \msg_error:nnx{stex}{error/unknownmodule}{\l_stex_import_uri_str?#1}
  }
}

\cs_new_protected:Npn \_@@_check_file:nn #1 {
  \stex_debug:nn{imports}{Checking~ \l_@@_str #1}
  \IfFileExists{ \l_@@_str #1 }{
    \stex_debug:nn{imports}{Success}
    \str_set:Nx \l_@@_str { \l_@@_str #1 }
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\importmodule}
%    \begin{macrocode}
\stex_new_stylable_cmd:nnnn{importmodule} { O{} m } {
  \_@@_import_module:nn {#1}{#2}
  \stex_smsmode_do:
}{}
\stex_deactivate_macro:Nn \importmodule {module~environments}

\cs_new_protected:Nn \_@@_import_module:nn {
  \stex_import_module_uri:nn { #1 }{ #2 }
  \stex_import_require_module:ooo
    \l_stex_import_archive_str
    \l_stex_import_path_str
    \l_stex_import_name_str
  \stex_execute_in_module:x{ 
    \stex_activate_module:n{\l_stex_import_ns_str}
  }
  \stex_module_add_morphism:nonn
    {}{\l_stex_import_ns_str}{import}{}
  \stex_if_do_html:T {
    \stex_annotate_invisible:nn 
      {shtml:import=\l_stex_import_ns_str} {}
  }
  \stex_if_smsmode:F{
    \group_begin:
    \tl_set:Nn \thisarchive {#1}
    \tl_set_eq:NN \thismoduleuri \l_stex_import_ns_str
    \tl_set_eq:NN \thismodulename \l_stex_import_name_str
    \tl_clear:N \thisstyle
    \stex_style_apply:
    \group_end:
  }
}

\cs_new_protected:Nn \_@@_import_module_presms:nn {
  \stex_import_module_uri:nn { #1 }{ #2 }
  \tl_gput_right:Nx \g_stex_sms_import_code {
    \stex_import_require_module_safe:nnn 
      {\l_stex_import_archive_str}
      {\l_stex_import_path_str}
      {\l_stex_import_name_str}
  }
}

\stex_sms_allow_escape:N \importmodule
\stex_every_module:n {\stex_reactivate_macro:N \importmodule}
\stex_sms_allow_import:Nn \importmodule {
  \stex_reactivate_macro:N \importmodule
  \let \_@@_import_module:nn \_@@_import_module_presms:nn
}

\stex_new_stylable_cmd:nnnn{requiremodule} { O{} m } {
  \stex_import_module_uri:nn { #1 }{ #2 }
  \stex_import_require_module:ooo
    \l_stex_import_archive_str
    \l_stex_import_path_str
    \l_stex_import_name_str
  \stex_do_up_to_module:x{ 
    \stex_activate_module:n{\l_stex_import_ns_str}
  }
  \stex_if_do_html:T {
    \stex_annotate_invisible:nn 
      {shtml:import=\l_stex_import_ns_str} {}
  }
  \stex_if_smsmode:F{
    \group_begin:
    \tl_set:Nn \thisarchive {#1}
    \tl_set_eq:NN \thismoduleuri \l_stex_import_ns_str
    \tl_set_eq:NN \thismodulename \l_stex_import_name_str
    \tl_clear:N \thisstyle
    \stex_style_apply:
    \group_end:
  }
  \stex_smsmode_do:
}{}
\stex_deactivate_macro:Nn \requiremodule {module~environments}
%    \end{macrocode}
% \end{macro}
%
% \end{sfragment}
%
% \begin{sfragment}{Theory Morphisms}
%    \begin{macrocode}
%<@@=stex_morphisms>
%    \end{macrocode}
%
%    \begin{macrocode}
\stex_new_stylable_cmd:nnnn {assign} { m m }{
  \stex_get_in_morphism:n{#1}
  \_stex_assign_do:n{#2}
  \stex_smsmode_do:
}{}
\stex_sms_allow_escape:N\assign

\cs_new_protected:Nn \_stex_assign_do:n{
  \stex_debug:nn{assign}{Assigning~\l_stex_get_symbol_name_str~to~\tl_to_str:n{#1}}
  \tl_if_empty:NF \l_stex_get_symbol_def_tl {
    %\msg_error:nnxx{stex}{error/symbolalreadydefined}{\l_stex_get_symbol_name_str}{
    %  morphism~\l_stex_feature_name_str
    %}
  }
  \stex_check_term:n{#1}
  \stex_debug:nn{HERE!}{
    \l_stex_get_symbol_mod_str?\l_stex_get_symbol_name_str^^J
    \tl_to_str:n{#1}
  }
  \stex_if_do_html:T{
    \stex_annotate_invisible:nn{shtml:assign={\l_stex_get_symbol_mod_str?\l_stex_get_symbol_name_str}}{
      \_stex_annotate_force_break:n{
        \mode_if_math:T\hbox{$\stex_annotate:nn{shtml:definiens={}}{#1}$}
      }
    }
  }
  \exp_args:Ne \stex_metagroup_do_in:nx{
    \l_stex_current_module_str / \l_stex_feature_name_str
  }{
    \prop_put:Nnn \exp_not:N \l_stex_morphism_symbols_prop
    {[\l_stex_get_symbol_mod_str]/[\l_stex_get_symbol_name_str]}
    {
      {\l_stex_get_symbol_macro_str}
      {\int_use:N \l_stex_get_symbol_arity_int}
      {\l_stex_get_symbol_args_tl}
      {\exp_not:n{#1}}
      {\exp_args:No\exp_not:n\l_stex_get_symbol_type_tl}
      {\exp_args:No\exp_not:n\l_stex_get_symbol_return_tl}
      {\l_stex_get_symbol_invoke_cs}
    }
  }
}


\stex_new_stylable_cmd:nnnn {renamedecl} { m O{} m }{
  \stex_get_in_morphism:n{#1}
  \_stex_renamedecl_do:nn{#2}{#3}
  \stex_smsmode_do:
}{}
\stex_sms_allow_escape:N\renamedecl

\cs_new_protected:Nn \_stex_renamedecl_do:nn {
  \stex_debug:nn{renamedecl}{Renaming~\l_stex_get_symbol_name_str~to~[#1]{#2}}
  \stex_if_do_html:T{
    \exp_args:Ne \stex_annotate_invisible:nn{
      shtml:rename={\l_stex_get_symbol_mod_str?\l_stex_get_symbol_name_str},
      shtml:macroname={#2}
      \str_if_empty:nF{#1}{ ,shtml:to={#1} }
    }{}
  }
  \exp_args:Ne \stex_metagroup_do_in:nx{
    \l_stex_current_module_str / \l_stex_feature_name_str
  }{
    \prop_put:Nnn \exp_not:N \l_stex_morphism_renames_prop 
    {\l_stex_get_symbol_mod_str?\l_stex_get_symbol_name_str}{{#2}{
      \tl_if_empty:nTF{#1}{\l_stex_feature_name_str/\l_stex_get_symbol_name_str}{#1}
    }}
  }
}

\stex_new_stylable_cmd:nnnn {assignMorphism} { m m }{
  \str_clear:N \l_@@_morphism_dom_str
  \stex_iterate_morphisms:nn\l_stex_current_domain_str{
    \stex_debug:nn{assignMorphism}{
      Checking:~#1~vs:^^J##1^^J##2^^J##3^^J##4
    }
    \str_if_eq:nnTF{#1}{##1}{
      \_@@_do_morph_assign:nnn{##1}{##2}{##4}
    }{
      \stex_str_if_ends_with:nnT{##2}{#1}{
        \_@@_do_morph_assign:nnn{##1}{##2}{##4}
      }
    }
  }
  \str_if_empty:NT \l_@@_morphism_dom_str {
    \msg_error:nnn{stex}{error/nomorphism}{#1}
  }
  \bool_set_false:N \l_tmpa_bool
  \stex_iterate_morphisms:nn \l_stex_current_module_str {
    \stex_debug:nn{assignMorphism}{
      Checking:~#2~vs:^^J##1^^J##2^^J##3^^J##4
    }
    \str_if_eq:nnTF{#2}{##1}{
      \stex_debug:nn{assignMorphism}{match!}
      \stex_iterate_break:n{
        \stex_annotate_invisible:nn{
          shtml:assignMorphismFrom={\l_@@_morphism_dom_str}
          ahtml:assignMorphismTo={\l_stex_current_module_str?##1}
        }{}
        \bool_set_true:N \l_tmpa_bool
      }
    }{
      \stex_str_if_ends_with:nnT{##2}{#2}{
        \stex_debug:nn{assignMorphism}{match!}
        \stex_iterate_break:n{
          \stex_annotate_invisible:nn{
            shtml:assignMorphismFrom={\l_@@_morphism_dom_str},
            shtml:assignMorphismTo={\l_stex_current_module_str?##1}
          }{}
          \bool_set_true:N \l_tmpa_bool
        }
      }
    }
  }
  \bool_if:NF \l_tmpa_bool {
    \msg_error:nnn{stex}{error/nomorphism}{#2}
  }
}{}
\cs_new_protected:Nn \_@@_do_morph_assign:nnn {
  \stex_iterate_break:n{
    \str_set:Nx \l_@@_morphism_dom_str { \l_stex_current_domain_str ? #1 }
    \stex_debug:nn{assignMorphism}{match!}
    \stex_iterate_symbols:nn{#2}{
      \stex_debug:nn{assignMorphism}{removing~##1?##3}
      % TODO: non-trivial assignments
      \prop_remove:Nn \l_stex_morphism_symbols_prop {
        [##1]/[##3]
      }
    }
  }
}

\stex_deactivate_macro:Nn \assign {morphism~environments}
\stex_deactivate_macro:Nn \renamedecl {morphism~environments}
\stex_deactivate_macro:Nn \assignMorphism {morphism~environments}
%    \end{macrocode}
%
%    \begin{macrocode}
\stex_new_stylable_env:nnnnnnn {copymodule}{m O{} m}{

  \stex_structural_feature_morphism:nnnnn{#1}{morphism}{#2}{#3}{,shtml:total=false}
  
  \stex_if_smsmode:F {
    \tl_set:Nn \thiscopyname { #1 }
    \tl_set_eq:NN \thismoduleuri \l_stex_current_domain_str
    \stex_style_apply:
  }
  \stex_smsmode_do:
}{
  \stex_if_smsmode:F {
    \stex_style_apply:
  }
  \stex_structural_feature_morphism_end:
}{}{}{}
\stex_deactivate_macro:Nn \copymodule {module~environments}
\stex_every_module:n {
  \stex_reactivate_macro:N \copymodule
}
\stex_sms_allow_env:n{copymodule}

\stex_new_stylable_env:nnnnnnn {interpretmodule}{m O{} m}{
  \stex_structural_feature_morphism:nnnnn{#1}{morphism}{#2}{#3}{,shtml:total=true}
  \stex_if_smsmode:F {
    \tl_set:Nn \thiscopyname { #1 }
    \tl_set_eq:NN \thismoduleuri \l_stex_current_domain_str
    \stex_style_apply:
  }
  \stex_smsmode_do:
}{
  \stex_structural_feature_morphism_check_total:
  \stex_if_smsmode:F {
    \stex_style_apply:
  }
  \stex_structural_feature_morphism_end:
}{}{}{}
\stex_deactivate_macro:Nn \interpretmodule {module~environments}
\stex_every_module:n {
  \stex_reactivate_macro:N \interpretmodule
}
\stex_sms_allow_env:n{interpretmodule}
%    \end{macrocode}
%
%    \begin{macrocode}
\stex_new_stylable_env:nnnnnnn {realization}{O{} m}{

  \stex_structural_feature_morphism:nnnnn{}{morphism}{#1}{#2}{,shtml:total=true}
  %\stex_execute_in_module:x{
  %  \stex_activate_module:n{\l_stex_current_domain_str}
  %}
  \stex_if_smsmode:F {
    \tl_set:Nn \thiscopyname { #2 }
    \tl_set_eq:NN \thismoduleuri \l_stex_current_domain_str
    \stex_style_apply:
  }
  \stex_smsmode_do:
}{
  \stex_structural_feature_morphism_check_total:
  \stex_if_smsmode:F {
    \stex_style_apply:
  }
  \stex_structural_feature_morphism_end:
}{}{}{}
\stex_deactivate_macro:Nn \realization {module~environments}
\stex_every_module:n {
  \stex_reactivate_macro:N \realization
}
\stex_sms_allow_env:n{realization}
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new_protected:Nn \_@@_parse_assign:n {
  \str_clear:N \l_@@_name_str
  \str_clear:N \l_@@_newname_str
  \tl_clear:N \l_@@_ass_tl
  \stex_debug:nn{morphisms}{Parsing~#1}
  \exp_args:NNe \seq_set_split:Nnn \l_@@_seq {\tl_to_str:n{@}} {#1}
  \int_compare:nNnTF {\seq_count:N \l_@@_seq} = 1 {
    \stex_debug:nn{morphisms}{No~@}
    \seq_pop_left:NN \l_@@_seq \l_@@_next_tl
  }{
    \seq_pop_left:NN \l_@@_seq \l_@@_name_str
    \stex_debug:nn{morphisms}{Name:~\l_@@_name_str}
    \exp_args:NNo \str_set:Nn \l_@@_name_str \l_@@_name_str
    \tl_set:Nx \l_@@_next_tl {\seq_use:Nn \l_@@_seq @}
  }
  \exp_args:NNNo \seq_set_split:Nnn \l_@@_seq = \l_@@_next_tl
  \str_if_empty:NTF \l_@@_name_str {
    \seq_pop_left:NN \l_@@_seq \l_@@_name_str
    \exp_args:NNo \str_set:Nn \l_@@_name_str \l_@@_name_str
    \tl_set:Nx \l_@@_ass_tl {\seq_use:Nn \l_@@_seq =}
  }{
    \seq_pop_left:NN \l_@@_seq \l_@@_newname_str
    \exp_args:NNo \str_set:Nn \l_@@_newname_str \l_@@_newname_str
    \tl_set:Nx \l_@@_ass_tl {\seq_use:Nn \l_@@_seq =}
  }
  \_@@_do_parsed_assign:
}

\cs_new_protected:Nn \_@@_do_parsed_assign: {
  \exp_args:No \stex_get_in_morphism:n \l_@@_name_str
  \str_if_empty:NF \l_@@_newname_str {
    \exp_after:wN \_@@_do_parsed_newname: \l_@@_newname_str \_@@_end:
  }
  \tl_if_empty:NF \l_@@_ass_tl {
    \exp_args:No \_stex_assign_do:n \l_@@_ass_tl
  }
}

\cs_new_protected:Nn \_@@_do_parsed_newname: {
  \peek_charcode:NTF [ {
    \_@@_do_parsed_newname:w
  }{
    \_@@_do_parsed_newname:w []
  }
}

\cs_new_protected:Npn \_@@_do_parsed_newname:w [#1] #2 \_@@_end: {
  \_stex_renamedecl_do:nn{#1}{#2}
}

\stex_new_stylable_cmd:nnnn{copymod}{m O{} m m}{
  \stex_structural_feature_morphism:nnnnn{#1}{morphism}{#2}{#3}{,shtml:total=false}
  
  \clist_map_function:nN{#4}\_@@_parse_assign:n
  
  \stex_if_smsmode:F {
    \tl_set:Nn \thiscopyname { #1 }
    \tl_set_eq:NN \thismoduleuri \l_stex_current_domain_str
    \stex_style_apply:
  }
  \stex_structural_feature_morphism_end:
  \stex_smsmode_do:
}{}
\stex_deactivate_macro:Nn \copymod {module~environments}
\stex_every_module:n {
  \stex_reactivate_macro:N \copymod
}
\stex_sms_allow_escape:N\copymod


\stex_new_stylable_cmd:nnnn{interpretmod}{m O{} m m}{
  \stex_structural_feature_morphism:nnnnn{#1}{morphism}{#2}{#3}{,shtml:total=true}
  
  \clist_map_function:nN{#4}\_@@_parse_assign:n
  
  \stex_if_smsmode:F {
    \tl_set:Nn \thiscopyname { #1 }
    \tl_set_eq:NN \thismoduleuri \l_stex_current_domain_str
    \stex_style_apply:
  }
  \stex_structural_feature_morphism_check_total:
  \stex_structural_feature_morphism_end:
  \stex_smsmode_do:
}{}
\stex_deactivate_macro:Nn \interpretmod {module~environments}
\stex_every_module:n {
  \stex_reactivate_macro:N \interpretmod
}
\stex_sms_allow_escape:N\interpretmod


\stex_new_stylable_cmd:nnnn{realize}{O{} m m}{
  \stex_structural_feature_morphism:nnnnn{}{morphism}{#1}{#2}{,shtml:total=true}
  
  \clist_map_function:nN{#3}\_@@_parse_assign:n
  
  \stex_if_smsmode:F {
    \tl_set:Nn \thiscopyname { #1 }
    \tl_set_eq:NN \thismoduleuri \l_stex_current_domain_str
    \stex_style_apply:
  }
  \stex_structural_feature_morphism_check_total:
  \stex_structural_feature_morphism_end:
  \stex_smsmode_do:
}{}
\stex_deactivate_macro:Nn \realize {module~environments}
\stex_every_module:n {
  \stex_reactivate_macro:N \realize
}
\stex_sms_allow_escape:N\realize
%    \end{macrocode}
%
% \end{sfragment}
%
%
%
% \end{sfragment}
%
%
% \begin{sfragment}{Symbols}
%
% \begin{sfragment}{Declarations}
%    \begin{macrocode}
%<@@=stex_symdecl>
%    \end{macrocode}
% Some setup:
%
% \begin{macro}[pTF]{\stex_if_check_terms:}
%    \begin{macrocode}
\stex_if_html_backend:TF {
  \prg_new_conditional:Nnn \stex_if_check_terms: {p, T, F, TF} {
    \prg_return_false:
  }
}{
  \stex_get_env:Nn\_@@_env_str{STEX_CHECKTERMS}
  \str_if_empty:NF\_@@_env_str{
    \exp_args:No \str_if_eq:nnF \_@@_env_str{false}{
      \bool_set_true:N \c_stex_check_terms_bool
    }
  }
  \bool_if:NTF \c_stex_check_terms_bool {
    \prg_new_conditional:Nnn \stex_if_check_terms: {p, T, F, TF} {
      \prg_return_true:
    }
  }{
    \prg_new_conditional:Nnn \stex_if_check_terms: {p, T, F, TF} {
      \prg_return_false:
    }
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\stex_check_term:n}
%    \begin{macrocode}
\stex_if_check_terms:TF{
  \cs_new_protected:Nn \stex_check_term:n {
    \hbox_set:Nn \l_tmpa_box {
      \group_begin:
        $#1$
      \group_end:
    }
  }
}{
  \cs_new_protected:Nn \stex_check_term:n {}
}
%    \end{macrocode}
% \end{macro}
%
% |symdecl| arguments:
%    \begin{macrocode}
\stex_keys_define:nnnn{symargs}{
  \str_clear:N \l_stex_key_args_str
  \str_clear:N \l_stex_key_role_str
  \str_clear:N \l_stex_key_reorder_str
  \str_clear:N \l_stex_key_assoc_str
}{
  args      .str_set:N  = \l_stex_key_args_str ,
  reorder   .str_set:N  = \l_stex_key_reorder_str ,
  assoc     .choices:nn   = {bin,binl,binr,pre,conj,pwconj}
    {\str_set:Nx \l_stex_key_assoc_str \l_keys_choice_tl},
  role      .str_set:N     = \l_stex_key_role_str
}{}

\stex_keys_define:nnnn{decl}{
  \str_clear:N \l_stex_key_name_str
  \str_clear:N \l_stex_key_args_str
  \tl_clear:N \l_stex_key_type_tl
  \tl_clear:N \l_stex_key_def_tl
  \tl_clear:N \l_stex_key_return_tl
  \str_clear:N \l_stex_key_wikidata_str
  \clist_clear:N \l_stex_key_argtypes_clist
}{
  name      .str_set:N  = \l_stex_key_name_str ,

  return    .tl_set:N     = \l_stex_key_return_tl ,
  argtypes  .clist_set:N  = \l_stex_key_argtypes_clist ,
  wikidata  .str_set:N    = \l_stex_key_wikidata_str ,

  type      .tl_set:N     = \l_stex_key_type_tl  ,
  def       .tl_set:N     = \l_stex_key_def_tl   ,

  align     .code:n       = {},
  gfc       .code:n       = {}
}{style,deprecate,symargs}
% \_stex_do_deprecation:n{#2}
%    \end{macrocode}
%
% \begin{macro}{\symdecl}
%    \begin{macrocode}
\str_new:N \l_stex_macroname_str
\stex_new_stylable_cmd:nnnn {symdecl} { s m O{}} {
  \stex_keys_set:nn{decl}{#3}
  \IfBooleanTF #1 {
    \str_clear:N \l_stex_macroname_str
  }{
    \str_set:Nx \l_stex_macroname_str { #2 }
  }
  \stex_symdecl_top:n{#2}

  \stex_if_smsmode:F{
    \group_begin:
    \tl_set:Nx \thisdecluri {\l_stex_current_module_str ? \l_stex_key_name_str}
    \tl_set_eq:NN \thisdeclname \l_stex_key_name_str
    \tl_set_eq:NN \thistype \l_stex_key_type_tl
    \tl_set_eq:NN \thisdefiniens \l_stex_key_def_tl
    \tl_set_eq:NN \thisargs \l_stex_key_args_str
    \tl_clear:N \thisstyle
    \stex_style_apply:
    \group_end:
  }
  \stex_smsmode_do:
}{}
\stex_deactivate_macro:Nn \symdecl {module~environments}
\stex_every_module:n {\stex_reactivate_macro:N \symdecl}
\stex_sms_allow_escape:N \symdecl
%    \end{macrocode}
% \end{macro}
%
%% \begin{macro}{\stex_symdecl_top:n}
%    \begin{macrocode}
\cs_new_protected:Nn \stex_symdecl_top:n {
  \str_if_empty:NT \l_stex_key_name_str {
    \str_set:Nx \l_stex_key_name_str { #1 }
  }
  \stex_symdecl_do:
  \_stex_symdecl_check_terms:
  \_@@_add_decl:
  \stex_if_do_html:T {
    \_stex_symdecl_html:
  }
}

\cs_new_protected:Nn \_@@_add_decl: {
  \exp_args:Nnx \use:nn {\stex_module_add_symbol:nnnnnnnN}{
    {\l_stex_macroname_str}
    {\l_stex_key_name_str}
    {\int_use:N \l_stex_get_symbol_arity_int}
    {\l_stex_get_symbol_args_tl}
    {\tl_if_empty:NF \l_stex_key_def_tl{DEFED} }%{\exp_args:No \exp_not:n \l_stex_key_def_tl}
    {}%{\exp_args:No \exp_not:n \l_stex_key_type_tl}
    {\exp_args:No \exp_not:n \l_stex_key_return_tl}
    \stex_invoke_symbol:
  }
  \exp_args:Ne \stex_ref_new_symbol:n
    {\l_stex_current_module_str?\l_stex_key_name_str}
}

\cs_new:Nn \_stex_return_args:nn {
  {\svar{ARGUMENT_#1}\_stex_eat_exclamation_point:}
}

\cs_new_protected:Nn \_stex_symdecl_html: {
  \exp_args:Ne \stex_annotate_invisible:nn {
    shtml:symdecl = {\l_stex_current_module_str ? \l_stex_key_name_str},
    shtml:args = {\l_stex_key_args_str}
    \str_if_empty:NF \l_stex_macroname_str {,
      shtml:macroname={\l_stex_macroname_str}
    }
    \str_if_empty:NF \l_stex_key_wikidata_str {,
      shtml:wikidata={\l_stex_key_wikidata_str}
    }
    \str_if_empty:NF \l_stex_key_assoc_str {,
      shtml:assoctype={\l_stex_key_assoc_str}
    }
    \str_if_empty:NF \l_stex_key_reorder_str {,
      shtml:reorderargs={\l_stex_key_reorder_str}
    }
    \str_if_empty:NF \l_stex_key_role_str {,
      shtml:role={\l_stex_key_role_str}
    }
  }{\hbox\bgroup\_stex_annotate_force_break:n{
      \bool_set_true:N \stex_in_invisible_html_bool
      \tl_if_empty:NF \l_stex_key_type_tl {
        $\stex_annotate:nn{shtml:type={}}{\l_stex_key_type_tl}$
      }
      \tl_if_empty:NF \l_stex_key_def_tl {
        $\stex_annotate:nn{shtml:definiens={}}{\l_stex_key_def_tl}$
      }
      \tl_if_empty:NF \l_stex_key_return_tl{
        \exp_args:Nno \use:n{
        \cs_generate_from_arg_count:NNnn \l_@@_cs
        \cs_set:Npn \l_stex_get_symbol_arity_int} \l_stex_key_return_tl
        \tl_set:Nx \l_@@_args_tl {\_stex_map_args:N \_stex_return_args:nn}
        $\stex_annotate:nn{shtml:returntype={}}{
          \exp_after:wN \l_@@_cs \l_@@_args_tl!
        }$
      }
      \clist_if_empty:NF \l_stex_key_argtypes_clist {
        \stex_annotate:nn{shtml:argtypes={}}{\_stex_annotate_force_break:n{
          \clist_map_inline:Nn \l_stex_key_argtypes_clist {
              $\stex_annotate:nn{shtml:type={}}{##1}$
          }
        }}
      }
  }\egroup}
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\stex_symdecl_do:}
% Requires the above keys and \cs{l_stex_macroname_str} to be
% set first
%    \begin{macrocode}
\cs_new_protected:Nn \stex_symdecl_do: {
  \_stex_do_deprecation:n \l_stex_key_name_str
  \_@@_parse_arity:
  \_@@_do_args:
}

\int_new:N \l_stex_assoc_args_count

\cs_new_protected:Nn \_@@_parse_arity: {
  \int_zero:N \l_stex_get_symbol_arity_int
  \int_zero:N \l_stex_assoc_args_count
  \str_map_inline:Nn \l_stex_key_args_str {
    \str_case:nnF ##1 {
      0 { \str_map_break: }
      1 { \str_map_break:n{
        \int_set:Nn \l_stex_get_symbol_arity_int {1}
        \str_set:Nn \l_stex_key_args_str {i}
      } }
      2 { \str_map_break:n{
        \int_set:Nn \l_stex_get_symbol_arity_int {2}
        \str_set:Nn \l_stex_key_args_str {ii}
      } }
      3 { \str_map_break:n{
        \int_set:Nn \l_stex_get_symbol_arity_int {3}
        \str_set:Nn \l_stex_key_args_str {iii}
      } }
      4 { \str_map_break:n{
        \int_set:Nn \l_stex_get_symbol_arity_int {4}
        \str_set:Nn \l_stex_key_args_str {iiii}
      } }
      5 { \str_map_break:n{
        \int_set:Nn \l_stex_get_symbol_arity_int {5}
        \str_set:Nn \l_stex_key_args_str {iiiii}
      } }
      6 { \str_map_break:n{
        \int_set:Nn \l_stex_get_symbol_arity_int {6}
        \str_set:Nn \l_stex_key_args_str {iiiiii}
      } }
      7 { \str_map_break:n{
        \int_set:Nn \l_stex_get_symbol_arity_int {7}
        \str_set:Nn \l_stex_key_args_str {iiiiiii}
      } }
      8 { \str_map_break:n{
        \int_set:Nn \l_stex_get_symbol_arity_int {8}
        \str_set:Nn \l_stex_key_args_str {iiiiiiii}
      } }
      9 { \str_map_break:n{
        \int_set:Nn \l_stex_get_symbol_arity_int {9}
        \str_set:Nn \l_stex_key_args_str {iiiiiiiii}
      } }
      i {\int_incr:N \l_stex_get_symbol_arity_int}
      b {\int_incr:N \l_stex_get_symbol_arity_int}
      a {\int_incr:N \l_stex_get_symbol_arity_int \int_incr:N \l_stex_assoc_args_count}
      B {\int_incr:N \l_stex_get_symbol_arity_int \int_incr:N \l_stex_assoc_args_count}
    }{
      \msg_error:nnxx{stex}{error/wrongargs}{
        \l_stex_current_module_str ? \l_stex_key_name_str
      }{##1}
    }
  }
}

\cs_new_protected:Nn \_@@_do_args: {
  \tl_clear:N \l_stex_get_symbol_args_tl
  \int_step_inline:nn \l_stex_get_symbol_arity_int {
    \tl_put_right:Nn \l_stex_get_symbol_args_tl {##1}
    \tl_put_right:Nx \l_stex_get_symbol_args_tl {
      \str_item:Nn \l_stex_key_args_str {##1}
    }
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\_stex_symdecl_check_terms:}
%    \begin{macrocode}
\cs_new_protected:Nn \_stex_symdecl_check_terms: {
  \stex_check_term:n{
    \stex_debug:nn{check_terms}{Checking~type...}
    \group_begin:\l_stex_key_type_tl\group_end:
    \stex_debug:nn{check_terms}{Checking~definiens...}
    \group_begin:\l_stex_key_def_tl\group_end:
    \stex_debug:nn{check_terms}{Checking~return...}
    \group_begin:\l_stex_key_return_tl!\group_end:
    \stex_debug:nn{check_terms}{Checking~argument~types...}
    \group_begin:\l_stex_key_argtypes_clist\group_end:
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\textsymdecl}
%    \begin{macrocode}

\stex_keys_define:nnnn{textsymdecl}{
  \str_clear:N \l_stex_key_name_str
  \tl_clear:N \l_stex_key_type_tl
  \tl_clear:N \l_stex_key_def_tl
}{
  name      .str_set:N  = \l_stex_key_name_str ,
  type      .tl_set:N     = \l_stex_key_type_tl ,
  def       .tl_set:N     = \l_stex_key_def_tl
}{style,deprecate}

\stex_new_stylable_cmd:nnnn {textsymdecl} {m O{} m} {
  \stex_keys_set:nn{symdef}{}
  \stex_keys_set:nn{textsymdecl}{#2}
  \str_set:Nx \l_stex_macroname_str { #1 }
  \str_if_empty:NT \l_stex_key_name_str {
    \str_set:Nn \l_stex_key_name_str {#1}
  }%{
  %  \str_set:Nx \l_stex_key_name_str {\l_stex_key_name_str-sym}
  %}
  \str_set:Nn \l_stex_key_role_str {textsymdecl}
  
  \stex_symdecl_do:
  \_stex_symdecl_check_terms:
  \exp_args:Nnx \use:nn {\stex_module_add_symbol:nnnnnnnN}{
    {\l_stex_macroname_str}
    {\l_stex_key_name_str}
    {0}{}
    {\tl_if_empty:NF \l_stex_key_def_tl{DEFED} }
    {}% type
    {\use:c{#1name_nospace}}% return
    \stex_invoke_text_symbol:
  }
  \exp_args:Ne \stex_ref_new_symbol:n
    {\l_stex_current_module_str?\l_stex_key_name_str}
  \stex_if_do_html:T {
    \_stex_symdecl_html:
  }
  
  \int_set:Nn \l_stex_get_symbol_arity_int 0
  \tl_clear:N \l_stex_key_op_tl
  \str_clear:N \l_stex_key_intent_str
  \str_clear:N \l_stex_key_prec_str
  \str_set_eq:NN \l_stex_get_symbol_mod_str \l_stex_current_module_str
  \str_set_eq:NN \l_stex_get_symbol_name_str \l_stex_key_name_str
  \stex_notation_parse:n{\hbox{#3}}
  \_stex_notation_add:
  \stex_if_do_html:T {
    \def\comp{\_comp}
    \_stex_notation_do_html:n{\l_stex_get_symbol_mod_str ? \l_stex_get_symbol_name_str}
  }
  \stex_execute_in_module:x{
    \_@@_set_textsymdecl_macro:nnn{#1}{\l_stex_current_module_str?\l_stex_key_name_str}
    \exp_not:n{{#3}}
  }

  \stex_if_smsmode:F{
    \group_begin:
    \tl_set:Nx \thisdecluri {\l_stex_current_module_str ? \l_stex_key_name_str}
    \tl_set_eq:NN \thisdeclname \l_stex_key_name_str
    \tl_clear:N \thisstyle
    \stex_style_apply:
    \group_end:
  }
  \stex_smsmode_do:
}{}
\stex_deactivate_macro:Nn \textsymdecl {module~environments}
\stex_every_module:n {\stex_reactivate_macro:N \textsymdecl}
\stex_sms_allow_escape:N \textsymdecl

\cs_new_protected:Nn \_@@_set_textsymdecl_macro:nnn {
  \cs_set_protected:cpn{#1name_nospace}{#3}
  \cs_set_protected:cpn{#1name}{
    \mode_if_vertical:T{\hbox_unpack:N\c_empty_box}
    \mode_if_math:T\hbox{\let\xspace\relax #3}
    \mode_if_math:F{\cs_if_exist:NT\xspace\xspace}
  }
}

\cs_new_protected:Nn \stex_invoke_text_symbol: {
  \mode_if_vertical:T{\hbox_unpack:N\c_empty_box}
  \_stex_term_oms_or_omv:nnn{}{}{\maincomp{\let\xspace\relax\l_stex_current_return_tl}}
  \group_end:\mode_if_math:F{\cs_if_exist:NT\xspace\xspace}
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\stex_get_symbol:n}
%    \begin{macrocode}
\cs_new_protected:Nn \stex_get_symbol:n {
  \_stex_get_symbol:n{ #1 }
  \str_if_empty:NT \l_stex_get_symbol_name_str {
    \msg_error:nnn{stex}{error/unknownsymbol}{#1}
  }
}

\cs_new_protected:Nn \_stex_get_symbol:n {
  \str_clear:N \l_stex_get_symbol_mod_str
  \str_clear:N \l_stex_get_symbol_name_str
  \cs_if_exist:cTF { #1 }{
    \cs_set_eq:Nc \l_@@_cs { #1 }
    % command name
    \exp_args:Ne \tl_if_empty:nTF { \cs_argument_spec:N \l_@@_cs }{
      % ...that takes no arguments
      \exp_args:Ne \cs_if_eq:NNTF {\tl_head:N \l_@@_cs}
        \_stex_invoke_symbol:nnnnnnnN
        \_@@_get_symbol_from_cs:
        {\_@@_get_symbol_from_string:n { #1 }}
    }{
      \_@@_get_symbol_from_string:n { #1 }
    }
  }{
    \_@@_get_symbol_from_string:n { #1 }
  }
}

\int_new:N \l_stex_get_symbol_arity_int
\cs_new_protected:Nn \_@@_get_symbol_from_cs: {
  \stex_debug:nn{symbols}{Getting~from~cs...}
  \stex_pseudogroup_with:nn{\_stex_invoke_symbol:nnnnnnnN}{
    \cs_set:Npn \_stex_invoke_symbol:nnnnnnnN ##1 ##2 ##3 ##4 ##5 ##6 ##7 ##8 {
      \str_set:Nn \l_stex_get_symbol_mod_str {##1}
      \str_set:Nn \l_stex_get_symbol_name_str {##2}
      \int_set:Nn \l_stex_get_symbol_arity_int {##3}
      \tl_set:Nn \l_stex_get_symbol_args_tl {##4}
      \tl_set:Nn \l_stex_get_symbol_def_tl {##5}
      \tl_set:Nn \l_stex_get_symbol_type_tl {##6}
      \tl_set:Nn \l_stex_get_symbol_return_tl {##7}
      \tl_set:Nn \l_stex_get_symbol_invoke_cs {##8}
    }
    \l_@@_cs
  }
}

\cs_new_protected:Nn \_@@_get_symbol_from_string:n {
  \stex_debug:nn{symbols}{Getting~from~string~#1...}
  \seq_set_split:Nnn \l_@@_seq ? {#1}
  \seq_pop_right:NN \l_@@_seq \l_@@_name
  \seq_if_empty:NTF \l_@@_seq {
    \exp_args:No \_@@_get_from_one_string:n {#1}
  }{
    \exp_args:NNe \exp_args:Nno \_@@_get_symbol_from_modules:nn {
      \seq_use:Nn \l_@@_seq ?
    } \l_@@_name
  }
}

\cs_new_protected:Nn \_@@_sym_from_str_i:nnnn {
  \bool_lazy_any:nTF{
    {\str_if_eq_p:nn{#2}{#3}}
    {\str_if_eq_p:nn{#2}{#4}}
    {\stex_str_if_ends_with_p:nn{#4}{/#2}}
    }{
      \_@@_sym_i_finish:nnnnnnnN{#1}{#4}
    }{
      \_@@_sym_i_gobble:nnnnnn
    }
}
\cs_new_protected:Nn \_@@_sym_i_gobble:nnnnnn {}

\cs_new_protected:Nn \_@@_sym_i_finish:nnnnnnnN {
  \prop_map_break:n{\seq_map_break:n{
    \str_set:Nn \l_stex_get_symbol_mod_str {#1}
    \str_set:Nn \l_stex_get_symbol_name_str {#2}
    \int_set:Nn \l_stex_get_symbol_arity_int {#3}
    \tl_set:Nn \l_stex_get_symbol_args_tl {#4}
    \tl_set:Nn \l_stex_get_symbol_def_tl {#5}
    \tl_set:Nn \l_stex_get_symbol_type_tl {#6}
    \tl_set:Nn \l_stex_get_symbol_return_tl {#7}
    \tl_set:Nn \l_stex_get_symbol_invoke_cs {#8}
  }}
}

\cs_new_protected:Nn \_@@_get_symbol_from_modules:nn {
  \stex_debug:nn{symbols}{Getting~#2~in~#1...}
  \seq_map_inline:Nn \l_stex_all_modules_seq {
    \stex_str_if_ends_with:nnT{##1}{#1}{
      \prop_map_inline:cn{c_stex_module_##1_symbols_prop}{
        \_@@_sym_from_str_i:nnnn{##1}{#2} ####2
      }
    }
  }
}

\cs_new_protected:Nn \_@@_get_from_one_string:n {
  \stex_debug:nn{symbols}{Getting~#1~anywhere...}
  \stex_iterate_symbols:n{
    %\stex_debug:nn{symbols}{>#1==##2~|~#1==##3<...}
    \bool_lazy_any:nT{
      {\str_if_eq_p:nn{#1}{##2}}
      {\str_if_eq_p:nn{#1}{##3}}
      {\stex_str_if_ends_with_p:nn{##3}{/#1}}
      }{
        \stex_iterate_break:n{
          \str_set:Nn \l_stex_get_symbol_mod_str {##1}
          \str_set:Nn \l_stex_get_symbol_name_str {##3}
          \int_set:Nn \l_stex_get_symbol_arity_int {##4}
          \tl_set:Nn \l_stex_get_symbol_args_tl {##5}
          \tl_set:Nn \l_stex_get_symbol_def_tl {##6}
          \tl_set:Nn \l_stex_get_symbol_type_tl {##7}
          \tl_set:Nn \l_stex_get_symbol_return_tl {##8}
          \tl_set:Nn \l_stex_get_symbol_invoke_cs {##9}
        }
    }
  }
}
%    \end{macrocode}
% \end{macro}
%
% \end{sfragment}
%
% \begin{sfragment}{Notations}
%    \begin{macrocode}
%<@@=stex_notations>
%    \end{macrocode}
%
% \begin{macro}{\_stex_map_args:N,\_stex_map_notation_args:N}
%    \begin{macrocode}
\cs_new:Nn \_stex_map_args:N {
  \tl_if_empty:NF \l_stex_get_symbol_args_tl {
    \exp_after:wN \_@@_map_args_i:w \exp_after:wN 
    #1 \l_stex_get_symbol_args_tl \_@@_args_end:
  }
}
\cs_new:Npn \_@@_map_args_i:w #1 #2 #3 #4 \_@@_args_end: {
  #1 #2 #3
  \tl_if_empty:nF{#4}{
    \_@@_map_args_i:w #1 #4 \_@@_args_end:
  }
}

\cs_new:Nn \_stex_map_notation_args:N {
  \tl_if_empty:NF \l_stex_notation_args_tl {
    \exp_after:wN \_@@_map_args_ii:w \exp_after:wN 
    #1 \l_stex_get_symbol_args_tl \_@@_args_end:
  }
}
\cs_new:Npn \_@@_map_args_ii:w #1 #2 #3 #4 #5 #6 \_@@_args_end: {
  #1 #2 #3 #4 #5
  \tl_if_empty:nF{#6}{
    \_@@_map_args_ii:w #1 #6 \_@@_args_end:
  }
}
%    \end{macrocode}
% \end{macro}
%
% |notation| arguments:
%    \begin{macrocode}
\stex_keys_define:nnnn{notation}{
  \str_clear:N \l_stex_key_variant_str
  \str_clear:N \l_stex_key_prec_str
  \str_clear:N \l_stex_key_op_tl
  \str_clear:N \l_stex_key_intent_str
  \clist_clear:N \l_stex_key_intent_args_clist
}{
  variant    .str_set_x:N  = \l_stex_key_variant_str ,
  prec       .str_set_x:N  = \l_stex_key_prec_str ,
  op         .tl_set:N     = \l_stex_key_op_tl ,
  intent     .str_set:N    = \l_stex_key_intent_str ,
  argnames   .clist_set:N  = \l_stex_key_intent_args_clist , 
  unknown    .code:n       = {
    \str_if_empty:NTF \l_keys_key_str {
        \str_set:Nx \l_stex_key_variant_str {\l_keys_key_tl}
    }{
        \str_set_eq:NN \l_stex_key_variant_str \l_keys_key_str
    }
  }
}{style}
%    \end{macrocode}
%
% \begin{macro}{\notation}
%    \begin{macrocode}
\stex_new_stylable_cmd:nnnn {notation} { s m O{} m} {
  \stex_keys_set:nn{notation}{#3}
  \stex_get_symbol:n{#2}
  \stex_notation_parse:n{#4}
  \stex_if_check_terms:T{ \_stex_notation_check: }
  \_stex_notation_add:
  \stex_if_do_html:T {
    \def\comp{\_comp}
    \_stex_notation_do_html:n{\l_stex_get_symbol_mod_str ? \l_stex_get_symbol_name_str}
  }
  \IfBooleanTF#1{
    \_stex_notation_set_default:n{
      \l_stex_get_symbol_mod_str ? \l_stex_get_symbol_name_str
    }
  }{}
  \stex_if_smsmode:F{
    \group_begin:
    \_@@_styledefs:
    \stex_style_apply:
    \group_end:
  }
  \stex_smsmode_do:
}{}

\cs_new_protected:Nn \_@@_styledefs: {
  \str_set_eq:NN\thisnotationvariant\l_stex_key_variant_str
  \str_set:Nn \thisdeclname \l_stex_get_symbol_name_str
  \tl_set:Nx \thisdecluri {\l_stex_get_symbol_mod_str ? \l_stex_get_symbol_name_str}
  \def\thisnotation{
    $
    \tl_set_eq:NN \l_stex_current_symbol_str\thisdecluri
    \exp_args:Nne \use:nn{\l_stex_notation_macrocode_cs}{
      \_stex_notation_make_args:
    }$
  }
}

\stex_deactivate_macro:Nn \notation {module~environments}
\stex_every_module:n {\stex_reactivate_macro:N \notation}
\stex_sms_allow_escape:N \notation
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\stex_notation_parse:n}
% requires the above keys, \cs{l_stex_get_symbol_arity_int}, and
% \cs{l_stex_get_symbol_args_tl}
%    \begin{macrocode}
\cs_new_protected:Nn \stex_notation_parse:n {
  \tl_if_empty:NF \l_stex_key_op_tl {
    \tl_set:Nx \l_stex_key_op_tl { \exp_not:N\maincomp {
      \exp_args:No \exp_not:n \l_stex_key_op_tl
    } }
  }
  \seq_clear:N \l_@@_precs_seq
  \tl_clear:N \l_stex_notation_args_tl
  \int_compare:nNnTF \l_stex_get_symbol_arity_int = 0 {
    \_@@_const_precs: 
    \tl_if_empty:NT \l_stex_key_op_tl {
      \tl_set:Nn \l_stex_key_op_tl { \maincomp{#1} }
    }
  }{
    \_@@_fun_precs:
    \str_set:Nn \l_@@_missing_str {#1}
    \tl_clear:N \l_@@_missing_tl
    \_stex_map_args:N \_@@_add_missing_args:nn
    \tl_if_empty:NT \l_stex_key_op_tl {
      \hbox_set:Nn \l_tmpa_box {
        \str_set:Nn \l_stex_current_symbol_str {}
        \cs_set:Npn \l_tmpa_cs ##1 ##2 ##3 ##4 ##5 ##6 ##7 ##8 ##9 { #1 }
        \cs_set:Npn \maincomp ##1 {
          \tl_gset:Nn \l_stex_key_op_tl { \maincomp{##1} }
          ##1
        }
        \cs_set:Npn \argsep ##1 ##2 {##1 ##2}
        \cs_set:Npn \argmap ##1 ##2 ##3 {##1 ##3}
        \cs_set:Npn \argarraymap ##1 ##2 ##3 ##4 {
          ##1 ##2
        }
        \stex_suppress_html:n{$\l_tmpa_cs abcdefghj$}
      }
    }
  }
  \exp_args:NNe
  \tl_set:Nn \l_stex_notation_macrocode_cs {
    \STEXInternalNotation
      { \l_stex_key_variant_str }
      { \l_@@_opprec_tl }
      { \l_stex_key_intent_str }
      { \l_stex_notation_args_tl }
      { 
        \int_compare:nNnTF \l_stex_get_symbol_arity_int = 0
        { \exp_not:n { \maincomp{ #1 } } }
        { \exp_not:n { #1 } \l_@@_missing_tl }
      }
  }
  \stex_debug:nn{notation}{Notation:~\meaning\l_stex_notation_macrocode_cs}
}

\cs_new_protected:Nn \_@@_const_precs: {
  \str_if_empty:NTF \l_stex_key_prec_str {
    \tl_set:No \l_@@_opprec_tl { \neginfprec }
  }{
    \str_if_eq:onTF \l_stex_key_prec_str {nobrackets}{
      \tl_set:No \l_@@_opprec_tl { \neginfprec }
    }{
      \tl_set_eq:NN \l_@@_opprec_tl \l_stex_key_prec_str
    }
  }
}

\cs_new_protected:Nn \_@@_fun_precs: {
  \str_if_empty:NTF \l_stex_key_prec_str {
    \tl_set:No \l_@@_opprec_tl { \neginfprec }
  }{
    \str_if_eq:onTF \l_stex_key_prec_str {nobrackets}{
      \tl_set:No \l_@@_opprec_tl { \neginfprec }
    }{
      \tl_set_eq:NN \l_@@_opprec_tl \l_stex_key_prec_str
    }
  }
  \str_if_empty:NTF \l_stex_key_prec_str {
    \tl_set:Nn \l_@@_opprec_tl { 0 }
    \int_step_inline:nn \l_stex_get_symbol_arity_int {
      \seq_put_right:Nn \l_@@_precs_seq {0}
    }
  }{
    \str_if_eq:onTF \l_stex_key_prec_str {nobrackets}{
      \stex_debug:nn{notation}{No~brackets}
      \tl_set:No \l_@@_opprec_tl { \neginfprec }
      \int_step_inline:nn \l_stex_get_symbol_arity_int {
        \exp_args:NNo \seq_put_right:Nn \l_@@_precs_seq \infprec
      }
    }\_@@_parse_precs:
  }
  \_@@_do_argnames:
}

\cs_new_protected:Nn \_@@_parse_precs: {
  \stex_debug:nn{notation}{parsing~precedence~\l_stex_key_prec_str}
  \seq_set_split:NnV \l_@@_seq ; \l_stex_key_prec_str
  \seq_pop_left:NNTF \l_@@_seq \l_@@_str {
    \tl_set_eq:NN \l_@@_opprec_tl \l_@@_str
    \seq_pop_left:NNT \l_@@_seq \l_@@_str {
      \exp_args:NNo \seq_set_split:NnV \l_@@_seq 
        {\tl_to_str:n{x}} \l_@@_str
    }
  }{
    \tl_set:No \l_@@_opprec_tl { 0 }
  }
  \int_step_inline:nn \l_stex_get_symbol_arity_int {
    \seq_pop_left:NNTF \l_@@_seq \l_@@_str {
      \seq_put_right:No \l_@@_precs_seq \l_@@_str
    }{
      \seq_put_right:No \l_@@_precs_seq \l_@@_opprec_tl
    }
  }
}

\cs_new_protected:Nn \_@@_do_argnames: {
  \tl_clear:N \l_stex_notation_args_tl
  \_stex_map_args:N \_@@_do_argname:nn
}

\cs_new_protected:Nn \_@@_do_argname:nn {
  \clist_if_empty:NTF \l_stex_key_intent_args_clist {
    \tl_put_right:Nx \l_stex_notation_args_tl {
      #1#2{\seq_item:Nn \l_@@_precs_seq #1}{
        \str_if_empty:NF \l_stex_key_intent_str {#1}
      }
    }
  }{
    \tl_put_right:Nx \l_stex_notation_args_tl {
      #1#2{\seq_item:Nn \l_@@_precs_seq #1}
      {\c_dollar_str\clist_item:Nn \l_stex_key_intent_args_clist 1}
    }
    \clist_pop:NN \l_stex_key_intent_args_clist \l_tmpa_tl
  }
}

\cs_new:Nn \_@@_add_missing_args:nn {
  \exp_args:NNe \str_if_in:NnF \l_@@_missing_str {\c_hash_str\c_hash_str#1}{
    \tl_put_right:Nn \l_@@_missing_tl{\STEXinvisible{## #1}}
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\_stex_notation_check:,\_stex_notation_add:,\_stex_notation_do_html:n,\_stex_notation_make_args:}
%    \begin{macrocode}
\cs_new_protected:Nn \_stex_notation_check: {
  \stex_check_term:n{
    \str_set:Nn \l_stex_current_symbol_str {test}
    \cs_set:Npn \comp ##1 {##1}
    \stex_debug:nn{check_terms}{Checking~notation...}
    \exp_args:Nne \use:nn{\l_stex_notation_macrocode_cs{}}{
      \_stex_notation_make_args:
    }
  }
}

\cs_new_protected:Nn \_stex_notation_add: {
  \stex_module_add_notation:eoeoo{
    \l_stex_get_symbol_mod_str ? \l_stex_get_symbol_name_str
    }\l_stex_key_variant_str
    {\int_use:N \l_stex_get_symbol_arity_int}
    \l_stex_notation_macrocode_cs
    \l_stex_key_op_tl
}

\cs_new_protected:Nn \_stex_notation_do_html:n {
  \hbox{\stex_annotate_invisible:nn { 
    shtml:notation={#1},
    shtml:notationfragment={\l_stex_key_variant_str},
    shtml:precedence={\l_@@_opprec_tl},
    shtml:argprecs={\seq_use:Nn \l_@@_precs_seq ,}
  }{
    \cs_set_protected:Npn \argsep ##1 ##2 {
      \stex_annotate:nn{shtml:argsep={}}{
        ##1 ##2
      }
    }
    \cs_set_protected:Npn \argmap ##1 ##2 ##3 {
      \cs_set:Npn \_@@_map_cs: ####1 { ##2 }
      \stex_annotate:nn{shtml:argmap={}}{
        \_@@_map_cs:{##1} ##3
      }
    }
    \cs_set_protected:Npn \maincomp {
      \_do_comp:nNn {maincomp}\compemph@uri
    }
    $
      \str_set:Nx \l_stex_current_symbol_str {#1}
      \stex_annotate:nn{shtml:notationcomp={}}{
        \exp_args:Nne \use:nn {
          \l_stex_notation_macrocode_cs {}
        }{
          \_stex_map_args:N \_@@_make_arg_html:nn
        }
      }
    $
    \tl_if_empty:NF \l_stex_key_op_tl {
      $
      \str_set:Nx \l_stex_current_symbol_str {#1}
      \stex_annotate:nn{shtml:notationopcomp={}}{
        \_stex_term_oms:nnn{\l_stex_key_variant_str}{}{\l_stex_key_op_tl}
      }
      $
    }
  }}
}

\cs_new:Nn \_@@_make_arg_html:nn {
%  \str_case:nnF #2 {
%    a {{
%      \stex_annotate:nn{shtml:argnum=#1a}{x},
%      \stex_annotate:nn{shtml:argnum=#1b}{x}
%    }}
%    B {{
%      \stex_annotate:nn{shtml:argnum=#1a}{x},
%      \stex_annotate:nn{shtml:argnum=#1b}{x}
%    }}
%  }{
    {
      \stex_annotate:nn{shtml:argnum=#1}{x}
    }
%  }
}

\cs_new:Nn \_stex_notation_make_args: {
  \_stex_map_notation_args:N \_@@_make_arg:nnnn
}


\cs_new:Nn \_@@_make_arg:nnnn  {
  \str_case:nnF #2 {
    a {{
        a\c_math_subscript_token{#1,1},
        a\c_math_subscript_token{#1,2}
      }}
    B {{
        B\c_math_subscript_token{#1,1},
        B\c_math_subscript_token{#1,2}
      }}
  }{
    \_stex_term_arg:nnnnn{#1}{#2}{#3}{#4}
      {{#2}\c_math_subscript_token{#1}}
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\setnotation,\_stex_notation_set_default:n}
%    \begin{macrocode}
\cs_new_protected:Npn \setnotation #1 #2 {
  \stex_get_symbol:n{#1}
  \cs_if_exist:cTF{l_stex_notation_ 
    \l_stex_get_symbol_mod_str?\l_stex_get_symbol_name_str
    _#2_cs
  }{
    \tl_set_eq:Nc \l_stex_notation_macrocode_cs {l_stex_notation_ 
      \l_stex_get_symbol_mod_str?\l_stex_get_symbol_name_str
      _#2_cs
    }
    \cs_if_exist:cTF{l_stex_notation_ 
      \l_stex_get_symbol_mod_str?\l_stex_get_symbol_name_str
      _op_#2_cs
    }{
      \tl_set_eq:Nc \l_stex_key_op_tl {l_stex_notation_ 
        \l_stex_get_symbol_mod_str?\l_stex_get_symbol_name_str
        _op_#2_cs
      }
    }{
      \tl_clear:N \l_stex_key_op_tl
    }
    \_stex_notation_set_default:n{
      \l_stex_get_symbol_mod_str?\l_stex_get_symbol_name_str
    }
  }{
    \msg_error:nnxx{stex}{unknownnotation}{#2}{
      \l_stex_get_symbol_mod_str?\l_stex_get_symbol_name_str
    }
  }
}

\cs_new_protected:Nn \_stex_notation_set_default:n{
  \stex_if_in_module:TF{
    \stex_module_add_notation:eoeoo{#1}{}
      {\int_use:N \l_stex_get_symbol_arity_int}
      \l_stex_notation_macrocode_cs
      \l_stex_key_op_tl
  }{
    \cs_set_eq:cN {l_stex_notation_ 
      \l_stex_get_symbol_mod_str?\l_stex_get_symbol_name_str 
      __cs}\l_stex_notation_macrocode_cs
    \tl_if_empty:NF \l_stex_key_op_tl {
      \cs_set_eq:cN{l_stex_notation_ 
      \l_stex_get_symbol_mod_str?\l_stex_get_symbol_name_str 
      _op__cs}\l_stex_key_op_tl
    }
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\varnotation}
%    \begin{macrocode}
\stex_new_stylable_cmd:nnnn {varnotation} { s m O{} m} {
  \stex_keys_set:nn{notation}{#3}
  \stex_get_var:n{#2}
  \str_set_eq:NN \l_stex_key_name_str \l_stex_get_symbol_name_str
  \stex_notation_parse:n{#4}
  \stex_if_check_terms:T{ \_stex_notation_check: }
  \_stex_vardecl_notation_macro:
  \IfBooleanTF#1{
    \_stex_notation_set_default:n{\l_stex_get_symbol_name_str}
  }{}
  \group_begin:
  \tl_set_eq:NN \thisvarname \l_stex_get_symbol_name_str
  \tl_clear:N \thisstyle
  \str_set_eq:NN\thisnotationvariant\l_stex_key_variant_str
  \def\thisnotation{
    $\let\l_stex_current_symbol_str\thisvarname
      \def\comp{\_varcomp}\exp_args:Nne \use:nn{\l_stex_notation_macrocode_cs{}}{
      \_stex_notation_make_args:
    }$
  }
  \stex_style_apply:
  \group_end:
}{}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\symdef}
%    \begin{macrocode}
\stex_keys_define:nnnn{symdef}{}{}{decl,notation}

\cs_new_protected:Nn \_stex_symdef_styledefs: {
  \tl_set:Nx \thisdecluri {\l_stex_current_module_str ? \l_stex_key_name_str}
  \tl_set_eq:NN \thisdeclname \l_stex_key_name_str
  \tl_set_eq:NN \thistype \l_stex_key_type_tl
  \tl_set_eq:NN \thisdefiniens \l_stex_key_def_tl
  \tl_set_eq:NN \thisargs \l_stex_key_args_str
  \tl_clear:N \thisstyle
  \str_set_eq:NN\thisnotationvariant\l_stex_key_variant_str
  \def\thisnotation{
    $\let\l_stex_current_symbol_str\thisdecluri
      \def\comp{\_comp}\exp_args:Nne \use:nn{\l_stex_notation_macrocode_cs}{
      \_stex_notation_make_args:
    }$
  }
}

\stex_new_stylable_cmd:nnnn {symdef} { m O{} m} {
  \stex_keys_set:nn{symdef}{#2}
  \str_set:Nx \l_stex_macroname_str { #1 }
  \stex_symdecl_top:n{#1}
  \stex_debug:nn{symdef}{Doing~\l_stex_current_module_str ? \l_stex_key_name_str}
  \str_set_eq:NN \l_stex_get_symbol_mod_str \l_stex_current_module_str
  \str_set_eq:NN \l_stex_get_symbol_name_str \l_stex_key_name_str
  \stex_notation_parse:n{#3}
  \stex_debug:nn{Here!}{\meaning\l_stex_notation_args_tl}
  \_stex_notation_check:
  \_stex_notation_add:
  \stex_if_do_html:T{
    \_stex_notation_do_html:n{\l_stex_get_symbol_mod_str ? \l_stex_get_symbol_name_str}
  }
  \stex_if_smsmode:F{
    \group_begin:
    \_stex_symdef_styledefs:
    \stex_style_apply:
    \group_end:
  }
  \stex_smsmode_do:
}{}

\stex_deactivate_macro:Nn \symdef {module~environments}
\stex_every_module:n {\stex_reactivate_macro:N \symdef}
\stex_sms_allow_escape:N \symdef
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\stex_do_default_notation_op:}
%    \begin{macrocode}
\cs_new_protected:Nn \stex_do_default_notation: {
  \stex_do_default_notation_op:
  \tl_if_empty:NTF \l_stex_current_args_tl {
    \tl_clear:N \l_@@_args_tl
  }{
    \_@@_make_name:
    \tl_set_eq:NN \l_stex_get_symbol_args_tl \l_stex_current_args_tl
    \tl_set:Nx \l_@@_args_tl {
      \_stex_map_args:N \_@@_augment_arg:nn
    }
    \tl_put_right:Nn \l_stex_default_notation {\comp(}
    \seq_clear:N \l_tmpa_seq
    \int_step_inline:nn \l_stex_current_arity_str {
      \seq_put_right:Nn \l_tmpa_seq {#### ##1}
    }
    \tl_put_right:Nx \l_stex_default_notation {
      \seq_use:Nn \l_tmpa_seq {\mathpunct{\comp{,}}}
    }
    \tl_put_right:Nn \l_stex_default_notation {\comp)}
  }
  \tl_set:Nx \l_stex_default_notation {\STEXInternalNotation{}{0}{}{\l_@@_args_tl}{
    \exp_args:No \exp_not:n \l_stex_default_notation
  }}
}

\cs_new:Nn \_@@_augment_arg:nn {
  #1#2{0}{}
}

\cs_new_protected:Nn \_@@_make_name: {
  \exp_args:NNNo \seq_set_split:Nnn \l_tmpa_seq ? \l_stex_current_symbol_str
  \seq_pop_right:NN \l_tmpa_seq \l_@@_name_str
  \exp_args:NNNo \seq_set_split:Nnn \l_tmpa_seq / \l_@@_name_str
  \seq_pop_right:NN \l_tmpa_seq \l_@@_name_str 
}

\cs_new_protected:Nn \stex_do_default_notation_op: {
  \_@@_make_name:
  \tl_set:Nx \l_stex_default_notation {\exp_not:N \maincomp{ \exp_not:N \mathrm {\l_@@_name_str} }}
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\STEXInternalNotation}
%    \begin{macrocode}
% 1: variant 2: operator precedence 3: intent 4: arguments 5: code 6: next

\cs_new_protected:Npn \STEXInternalNotation #1 #2 #3 #4 #5 #6 {
  \_@@_process_notation:nnnnnn{#1}{#2}{#3}{#4}{#5}{
    \l_@@_code_tl
    #6
  }
}

\cs_new_protected:Npn \_@@_process_notation:nnnnnn #1 #2 #3 #4 {
  \tl_if_empty:nTF{#4}{
    \_@@_simple:nnnnn{#1}{#2}{#3}
  }{
    \_@@_complex:nnnnnn{#1}{#2}{#3}{#4}
  }
}

\cs_new_protected:Nn \_@@_simple:nnnnn {
  \stex_debug:nn{Notation~code}{\tl_to_str:n{#4}}
  \tl_set:Nn \l_@@_code_tl {
    \cs_set:Npn \l_@@_cs {
      \_stex_maybe_brackets:nn{#2}{
        \_stex_term_oms_or_omv:nnn{#1}{#3}{#4}
      }
    }
    \l_@@_cs
  }
  \stex_debug:nn{Here:Notation}{\meaning \l_@@_code_tl }
  #5
}

\cs_new_protected:Nn \_@@_complex:nnnnnn {
  \stex_debug:nn{Notation~code}{\tl_to_str:n{#5}}
  \int_zero:N \l_tmpa_int
  \tl_set:Nn \l_@@_pre_tl {\cs_set_eq:NN \_stex_term_oma_or_omb:nnn \_stex_term_oma:nnn}
  \tl_set:Nn \l_@@_code_tl {
    \cs_generate_from_arg_count:NNnn \l_@@_cs \cs_set:Npn \l_tmpa_int
    { 
      \_stex_maybe_brackets:nn{#2}{
        \_stex_term_oma_or_omb:nnn{#1}{#3}{
          \bool_set_false:N \l_stex_brackets_dones_bool
          #5
        }
      }
    }
    \l_@@_cs
  }
  \tl_set:Nn \l_@@_after_tl{
    \exp_args:NNo 
    \tl_put_left:Nn \l_@@_code_tl \l_@@_pre_tl 
    \tl_put_left:Nx \l_@@_code_tl {
      \int_set:Nn \l_tmpa_int {\int_use:N \l_tmpa_int}
    }
    \stex_debug:nn{Here:Notation}{\meaning \l_@@_code_tl }
    #6
  }
  \_@@_parse_notation_args:nnnnw #4 \_@@_args_end:
}

\cs_new_protected:Npn \_@@_parse_notation_args:nnnnw #1 #2 #3 #4 #5 \_@@_args_end: {
  \tl_if_empty:nTF{#5}{
    \_@@_add_last:nnnnn{#1}{#2}{#3}{#4}
  }{
    \_@@_add_next:nnnnnn{#1}{#2}{#3}{#4}{#5}
  }
}

\cs_new_protected:Nn \_@@_add_next:nnnnnn {
  \_@@_add:nnnnn{#1}{#2}{#3}{#4}{#6}
  \_@@_parse_notation_args:nnnnw #5 \_@@_args_end:
}

\cs_new_protected:Nn \_@@_add_last:nnnnn {
  \_@@_add:nnnnn{#1}{#2}{#3}{#4}{#5}
  \l_@@_after_tl
}

\cs_new_protected:Nn \_@@_add:nnnnn {
  \int_incr:N \l_tmpa_int
  \str_case:nn{#2}{
    i {
      \tl_put_right:Nn \l_@@_code_tl {
        {\_stex_term_arg:nnnnn{#1}{#2}{#3}{#4}{#5}}
      }
    }
    b {
      \tl_set:Nn \l_@@_pre_tl {
        \cs_set_eq:NN \_stex_term_oma_or_omb:nnn \_stex_term_omb:nnn
      }
      \tl_put_right:Nn \l_@@_code_tl {
        {\_stex_term_arg:nnnnn{#1}{#2}{#3}{#4}{#5}}
      }
    }
    a {
      \tl_put_right:Nn \l_@@_code_tl {
        {\_stex_term_arg_aB:nnnnn{#1}{#2}{#3}{#4}{#5}}
      }
    }
    B  {
      \tl_set:Nn \l_@@_pre_tl {
        \cs_set_eq:NN \_stex_term_oma_or_omb:nnn \_stex_term_omb:nnn
      }
      \tl_put_right:Nn \l_@@_code_tl {
        {\_stex_term_arg_aB:nnnnn{#1}{#2}{#3}{#4}{#5}}
      }
    }
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{sfragment}{a/B-mode argument handling}
%
% \begin{macro}{\argsep}
%    \begin{macrocode}
\cs_new_protected:Nn \_@@_check_aB_arg:Nn {
  \exp_args:Ne \cs_if_eq:NNF {\tl_head:n{#2}}
    \_stex_term_arg_aB:nnnnn {
    \msg_error:nnx{stex}{error/assocarg}{\tl_to_str:n{#1}}
  }
}

\cs_new_protected:Npn \argsep #1 #2 {
  \_@@_check_aB_arg:Nn\argsep{#1}
  \stex_pseudogroup_with:nn{\_stex_term_do_aB_clist:}{
    \tl_set:Nn \_stex_term_do_aB_clist: {
      \seq_use:Nn \l_stex_aB_args_seq {#2}
    }
    #1
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\argmap}
%    \begin{macrocode}
\cs_new_protected:Npn \argmap #1 #2 #3 {
  \_@@_check_aB_arg:Nn\argmap{#1}
  \stex_pseudogroup_with:nn{
    \_stex_term_do_aB_clist:
    \_@@_map_cs:
  }{
    \cs_set:Npn \_@@_map_cs: ##1 { #2 }
    \tl_set:Nn \_stex_term_do_aB_clist: {
      \seq_clear:N \l_tmpa_seq
      \seq_map_inline:Nn \l_stex_aB_args_seq {
        \tl_if_eq:nnTF{##1}{\ellipses}{
          \seq_put_right:Nn \l_tmpa_seq \ellipses
        }{
          \seq_put_right:Nx \l_tmpa_seq {
            \exp_after:wN \exp_not:n \exp_after:wN { \_@@_map_cs: {##1} }
          }
        }
      }
      \seq_set_eq:NN \l_stex_aB_args_seq \l_tmpa_seq
      \seq_use:Nn \l_stex_aB_args_seq {#3}
    }
    #1
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\argarraymap}
%    \begin{macrocode}
\int_new:N \l_@@_clist_count_int
\cs_new_protected:Npn \argarraymap #1 #2 #3 #4 {
  \_@@_check_aB_arg:Nn\argarraymap{#1}
  \stex_pseudogroup_with:nn{
    \_stex_term_do_aB_clist:
    \_@@_map_cs:
  }{
    \cs_set:Npn \_@@_map_cs: ##1 { #3 }
    \int_set:Nn \l_@@_clist_count_int {\exp_args:No\clist_count:n{\tl_to_str:n{#4}}}
    \tl_set:Nn \_stex_term_do_aB_clist: {
      \tl_clear:N \l_tmpa_tl
      \int_zero:N \l_tmpa_int
      \seq_map_inline:Nn \l_stex_aB_args_seq {
        \int_incr:N \l_tmpa_int
        \int_compare:nNnT \l_tmpa_int > \l_@@_clist_count_int {
          \int_set:Nn \l_tmpa_int 1
        }
        \tl_put_right:Nx \l_tmpa_tl {
          \exp_after:wN \exp_not:n \exp_after:wN { \_@@_map_cs: {##1} }
          \clist_item:nn{#4}\l_tmpa_int
        }
      }
      \seq_set_eq:NN \l_stex_aB_args_seq \l_tmpa_seq
      \begin{array}{#2}
          \l_tmpa_tl
      \end{array}
    }
    #1
  }
}
%    \end{macrocode}
% \end{macro}
%
% \end{sfragment}
%
% \end{sfragment}
%

% \begin{sfragment}{Variables}
%    \begin{macrocode}
%<@@=stex_vars>
%    \end{macrocode}
%
% \begin{macro}{\vardef}
%    \begin{macrocode}
\tl_new:N \l_stex_variables_prop
\bool_new:N \l_@@_bind_bool
\cs_new_protected:Nn \_stex_variable:nnnnnnnN {}
\stex_keys_define:nnnn{vardef}{
  \bool_set_false:N \l_@@_bind_bool
}{
  bind  .bool_set:N  = \l_@@_bind_bool
}{symdef}

\stex_new_stylable_cmd:nnnn {vardef} { m O{} m} {
  \stex_keys_set:nn{vardef}{#2}
  \str_set:Nx \l_stex_macroname_str { #1 }
  \str_if_empty:NT \l_stex_key_name_str {
    \str_set:Nx \l_stex_key_name_str { #1 }
  }

  \stex_symdecl_do:
  \_stex_symdecl_check_terms:
  \_@@_add:
  \_@@_macro:
  \stex_if_do_html:T \_@@_html:

  \int_set:Nn \l_stex_get_symbol_arity_int {\l_stex_get_symbol_arity_int}
  \stex_debug:nn{vardef}{Doing~\l_stex_key_name_str}
  \tl_set_eq:NN \l_stex_get_symbol_return_tl \l_stex_key_return_tl
  \stex_notation_parse:n{#3}
  \stex_if_check_terms:T{ \_stex_notation_check: }
  \_stex_vardecl_notation_macro:
  \stex_if_do_html:T {
    \def\comp{\_varcomp}
    \_stex_notation_do_html:n \l_stex_key_name_str
  }
  \group_begin:
  \tl_set_eq:NN \thisvarname \l_stex_key_name_str
  \tl_clear:N \thisstyle
  \str_set_eq:NN\thisnotationvariant\l_stex_key_variant_str
  \def\thisnotation{
    $\let\l_stex_current_symbol_str\thisvarname
      \def\comp{\_varcomp}\exp_args:Nne \use:nn{\l_stex_notation_macrocode_cs{}}{
      \_stex_notation_make_args:
    }$
  }
  \stex_style_apply:
  \group_end:\ignorespaces
}{}

\cs_new_protected:Nn \_@@_add: {
  \exp_args:NNNo \exp_args:NNnx 
  \prop_put:Nnn \l_stex_variables_prop \l_stex_key_name_str {
    {\l_stex_macroname_str}
    {\l_stex_key_name_str}
    {\int_use:N \l_stex_get_symbol_arity_int}
    {\l_stex_get_symbol_args_tl}
    {\exp_args:No \exp_not:n \l_stex_key_def_tl}
    {\exp_args:No \exp_not:n \l_stex_key_type_tl}
    {\exp_args:No \exp_not:n \l_stex_key_return_tl}
    \stex_invoke_symbol:
  }
}

\cs_new_protected:Nn \_@@_macro: {
  \tl_set:cx{\l_stex_macroname_str}{
    \_stex_invoke_variable:nnnnnnN
      {\l_stex_key_name_str}
      {\int_use:N \l_stex_get_symbol_arity_int}
      {\l_stex_get_symbol_args_tl}
      {\exp_args:No \exp_not:n \l_stex_key_def_tl}
      {\exp_args:No \exp_not:n \l_stex_key_type_tl}
      {\exp_args:No \exp_not:n \l_stex_key_return_tl}
      \stex_invoke_symbol:
  }
}

\cs_new_protected:Nn \_@@_html: {
  \stex_if_do_html:T {
    \hbox\bgroup\exp_args:Ne \stex_annotate_invisible:nn {
      shtml:vardef = {\l_stex_key_name_str},
      shtml:args = {\l_stex_key_args_str}
      \str_if_empty:NF \l_stex_macroname_str {,
        shtml:macroname={\l_stex_macroname_str}
      }
      \str_if_empty:NF \l_stex_key_assoc_str {,
        shtml:assoctype={\l_stex_key_assoc_str}
      }
      \str_if_empty:NF \l_stex_key_role_str {,
        shtml:role={\l_stex_key_role_str}
      }
      \str_if_empty:NF \l_stex_key_reorder_str {,
        shtml:reorderargs={\l_stex_key_reorder_str}
      }
      \bool_if:NT \l_@@_bind_bool {,
        shtml:bind={}
      }
    }{
      \_stex_annotate_force_break:n{
        \bool_set_true:N \stex_in_invisible_html_bool
        \tl_if_empty:NF \l_stex_key_type_tl {
          \stex_annotate:nn{shtml:type={}}{$\l_stex_key_type_tl$}
        }
        \tl_if_empty:NF \l_stex_key_def_tl {
          \stex_annotate:nn{shtml:definiens={}}{$\l_stex_key_def_tl$}
        }
        \tl_if_empty:NF \l_stex_key_return_tl{
          \exp_args:Nno \use:n{
          \cs_generate_from_arg_count:NNnn \l_@@_cs
          \cs_set:Npn \l_stex_get_symbol_arity_int} \l_stex_key_return_tl
          \tl_set:Nx \l_@@_args_tl {\_stex_map_args:N \_stex_return_args:nn}
          $\stex_annotate:nn{shtml:returntype={}}{
            \exp_after:wN \l_@@_cs \l_@@_args_tl!}$
        }
        \tl_if_empty:NF \l_stex_key_argtypes_clist {
          \stex_annotate:nn{shtml:argtypes={}}{
            \_stex_annotate_force_break:n{
              \clist_map_inline:Nn \l_stex_key_argtypes_clist {
                $\stex_annotate:nn{shtml:type={}}{##1}$
              }
            }
          }
        }
      }
    }\egroup
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\_stex_vardecl_notation_macro:}
%    \begin{macrocode}
\cs_new_protected:Nn \_stex_vardecl_notation_macro: {
  \tl_set_eq:cN {l_stex_notation_
    \l_stex_key_name_str _
    \l_stex_key_variant_str _cs
  }\l_stex_notation_macrocode_cs
  \cs_if_exist:cF {l_stex_notation_\l_stex_key_name_str __cs}{
    \tl_set_eq:cN{l_stex_notation_\l_stex_key_name_str __cs}
      \l_stex_notation_macrocode_cs
  }
  \tl_if_empty:NF \l_stex_key_op_tl {
    \tl_set_eq:cN {l_stex_notation_\l_stex_key_name_str _op_
    \l_stex_key_variant_str _cs}\l_stex_key_op_tl
    \cs_if_exist:cF {l_stex_notation_\l_stex_key_name_str _op__cs}{
      \cs_set_eq:cN{l_stex_notation_\l_stex_key_name_str _op__cs}
      \l_stex_key_op_tl
    }
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\stex_get_symbol_or_var:n,\stex_get_var:n}
%    \begin{macrocode}
\cs_new_protected:Nn \_@@_set_vars:nnnnnnN {
  \stex_debug:nn{symbols}{Variable~#1~found}
  \cs_set:Npn \_stex_variable:nnnnnnnN ##1 ##2 ##3 ##4 ##5 ##6 ##7 ##8 {}
  \str_clear:N \l_stex_get_symbol_mod_str
  \str_set:Nn \l_stex_get_symbol_name_str {#1}
  \int_set:Nn \l_stex_get_symbol_arity_int {#2}
  \tl_set:Nn \l_stex_get_symbol_args_tl {#3}
  \tl_set:Nn \l_stex_get_symbol_def_tl {#4}
  \tl_set:Nn \l_stex_get_symbol_type_tl {#5}
  \tl_set:Nn \l_stex_get_symbol_return_tl {#6}
  \tl_set:Nn \l_stex_get_symbol_invoke_cs {#7}
}

\cs_new_protected:Nn \_@@_get_var:n {
  \prop_map_inline:Nn \l_stex_variables_prop {
    \_@@_check_var:nnnnnnnnN {#1} ##2
  }
}

\cs_new_protected:Nn \_@@_check_var:nnnnnnnnN {
  \str_if_eq:nnTF{#1}{#2}{
    \prop_map_break:n{\_@@_set_vars:nnnnnnN {#3}{#4}{#5}{#6}{#7}{#8}#9}
  }{
    \str_if_eq:nnT{#1}{#3}{
      \prop_map_break:n{\_@@_set_vars:nnnnnnN {#3}{#4}{#5}{#6}{#7}{#8}#9}
    }
  }
}

\cs_new_protected:Nn \stex_get_var:n {
  \str_clear:N \l_stex_get_symbol_name_str
  \_@@_get_var:n{#1}
  \str_if_empty:NT \l_stex_get_symbol_name_str {
    \msg_error:nnn{stex}{error/unknownsymbol}{#1}
  }
}

\cs_new_protected:Nn \stex_get_symbol_or_var:n {
  \str_clear:N \l_stex_get_symbol_name_str
  \_@@_get_var:n{#1}
  \str_if_empty:NT \l_stex_get_symbol_name_str {
    \stex_debug:nn{symbols}{No~variable~#1~found}
    \stex_get_symbol:n{#1}
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\svar}
%    \begin{macrocode}
\NewDocumentCommand \svar {O{} m}{
  \group_begin:
    \tl_if_empty:nTF{#1}{
      \str_set:Nn \l_stex_current_symbol_str {#2}
    }{
      \str_set:Nn \l_stex_current_symbol_str {#1}
    }
    \bool_if:NTF \l_stex_allow_semantic_bool{
        \tl_clear:N \l_stex_current_term_tl
        \_stex_term_omv:nnn{}{}{\_varcomp{#2}}
    }{
      \msg_error:nnxx{stex}{error/notallowed}{Variable}{\l_stex_current_symbol_str}
    }
  \group_end:
}
%    \end{macrocode}
% \end{macro}
%
% \end{sfragment}
%
% \begin{sfragment}{Sequences}
%    \begin{macrocode}
%<@@=stex_seqs>
%    \end{macrocode}
%
% \begin{macro}{\varseq}
%    \begin{macrocode}
\stex_new_stylable_cmd:nnnn {varseq}{m O{} m m} {
  \stex_keys_set:nn{symdef}{#2}
  \str_set:Nx \l_stex_macroname_str { #1 }
  \str_if_empty:NT \l_stex_key_name_str {
    \str_set:Nx \l_stex_key_name_str { #1 }
  }
  \str_if_empty:NT \l_stex_key_args_str {
    \str_set:Nn \l_stex_key_args_str {1}
  }
  \stex_symdecl_do:

  \tl_set_eq:NN \l_stex_get_symbol_return_tl \l_stex_key_return_tl
  \clist_set:Nn \l_@@_range_clist {#3}
  \tl_if_empty:NTF \l_stex_key_op_tl {
    \stex_notation_parse:n{#4}
    \tl_clear:N \l_stex_key_op_tl
  }{
    \stex_notation_parse:n{#4}
  }
  \stex_if_do_html:T \_@@_html:
  \stex_if_check_terms:T \_@@_check_terms:
  \_@@_add:
  \_@@_macro:
  \stex_if_check_terms:T \_stex_notation_check:
  \_stex_vardecl_notation_macro:
  \group_begin:
  \tl_set_eq:NN \thisvarname \l_stex_key_name_str
  \tl_clear:N \thisstyle
  \str_set_eq:NN\thisnotationvariant\l_stex_key_variant_str
  \def\thisnotation{
    $\let\l_stex_current_symbol_str\thisvarname
      \def\comp{\_varcomp}\exp_args:Nne \use:nn{\l_stex_notation_macrocode_cs{}}{
      \_@@_make_args:
    }$
  }
  \stex_style_apply:
  \group_end:\ignorespaces
}{}

\cs_new_protected:Nn \_@@_add: { 
  \exp_args:NNNo \exp_args:NNnx 
  \prop_put:Nnn \l_stex_variables_prop \l_stex_key_name_str {
    {\l_stex_macroname_str}
    {\l_stex_key_name_str}
    {\int_use:N \l_stex_get_symbol_arity_int}
    {\l_stex_get_symbol_args_tl}
    {\exp_args:No \exp_not:n \l_stex_key_def_tl}
    {\exp_args:No \exp_not:n \l_@@_range_clist}
    {\exp_args:No \exp_not:n \l_stex_key_return_tl}
    \stex_invoke_sequence:
  }
}

\cs_new_protected:Nn \_@@_macro: { 
  \tl_set:cx{\l_stex_macroname_str}{
    \_stex_invoke_variable:nnnnnnN
      {\l_stex_key_name_str}
      {\int_use:N \l_stex_get_symbol_arity_int}
      {\l_stex_get_symbol_args_tl}
      {\exp_args:No \exp_not:n \l_stex_key_def_tl}
      {\exp_args:No \exp_not:n \l_@@_range_clist}
      {\exp_args:No \exp_not:n \l_stex_key_return_tl}
      \stex_invoke_sequence:
  }
}

\cs_new_protected:Nn \_@@_make_args: { \TODO }
\cs_new_protected:Nn \_@@_check_terms: { \TODO }

\cs_new_protected:Nn \_@@_html: {
    \exp_args:Ne \stex_annotate_invisible:nn {
      shtml:varseq = {\l_stex_key_name_str},
      shtml:args = {\l_stex_key_args_str}
      \str_if_empty:NF \l_stex_macroname_str {,
        shtml:macroname={\l_stex_macroname_str}
      }
      \str_if_empty:NF \l_stex_key_assoc_str {,
        shtml:assoctype={\l_stex_key_assoc_str}
      }
      \str_if_empty:NF \l_stex_key_role_str {,
        shtml:role={\l_stex_key_role_str}
      }
      \str_if_empty:NF \l_stex_key_reorder_str {,
        shtml:reorderargs={\l_stex_key_reorder_str}
      }
    }{\hbox\bgroup
      \_stex_annotate_force_break:n{
        \tl_if_empty:NF \l_stex_key_type_tl {
          \stex_annotate:nn{shtml:type={}}{$\l_stex_key_type_tl$}
        }
        \tl_if_empty:NF \l_stex_key_def_tl {
          \stex_annotate:nn{shtml:definiens={}}{$\l_stex_key_def_tl$}
        }
        \tl_if_empty:NF \l_stex_key_return_tl{
          \exp_args:Nno \use:n{
          \cs_generate_from_arg_count:NNnn \l_@@_cs
          \cs_set:Npn \l_stex_get_symbol_arity_int} \l_stex_key_return_tl
          \tl_set:Nx \l_@@_args_tl {\_stex_map_args:N \_stex_return_args:nn}
          \stex_annotate:nn{shtml:returntype={}}{
            $\exp_after:wN \l_@@_cs \l_@@_args_tl!$}
        }
        \tl_if_empty:NF \l_stex_key_argtypes_clist {
          \stex_annotate:nn{shtml:argtypes={}}{
            \_stex_annotate_force_break:n{
              \clist_map_inline:Nn \l_stex_key_argtypes_clist {
                \stex_annotate:nn{shtml:type={}}{$##1$}
              }
            }
          }
        }
      }
    \egroup}
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\stex_invoke_sequence:}
%    \begin{macrocode}
\cs_new_protected:Nn \stex_invoke_sequence: {
  \peek_charcode_remove:NTF ! {
    \peek_charcode:NTF [ \_@@_do_op:w { \_@@_do_op:w [] }
  }\_@@_do_first:
}

\cs_new_protected:Npn \_@@_do_op:w [#1] {
  \cs_if_exist:cTF {l_stex_notation_\l_stex_current_symbol_str _op_#1_cs}{
    \_stex_maybe_brackets:nn{\neginfprec}{
      \_stex_term_oms_or_omv:nnn{#1}{}
      {\use:c{l_stex_notation_\l_stex_current_symbol_str _op_#1_cs}}
    }
    \group_end:
  }{
    \_@@_get_index_notation:n{#1}
    \peek_charcode:NTF [ \_@@_doop_range:w { \_@@_doop_range:w[] }
  }
}

\cs_new_protected:Npn \_@@_doop_range:w [#1] {
  \bool_set_true:N \l_stex_allow_semantic_bool
  \clist_clear:N \l_@@_clist
  \clist_map_function:NN \l_stex_current_type_tl \_@@_doop_arg:n
    \stex_annotate:nn{
      shtml:term=OMV,
      shtml:head={\l_stex_current_symbol_str},
      shtml:notationid={}
    }{
      \l_@@_clist
    }
    \group_end:
}

\cs_new_protected:Nn \_@@_doop_arg:n {
  \tl_if_eq:nnTF{#1}{\ellipses}{
    \clist_put_right:Nn \l_@@_clist {
        \ellipses
    }
  }{
    \clist_put_right:Nn \l_@@_clist {
      \exp_args:No \str_if_eq:nnTF \l_stex_current_arity_str {1}{
        \group_begin:
          \l_@@_cs \group_end: {#1}

      }{
        \group_begin:
          \l_@@_cs \group_end: #1
      }
    }
  }
}

\cs_new_protected:Nn \_@@_get_index_notation:n {
  \cs_if_exist:cTF {l_stex_notation_\l_stex_current_symbol_str _#1_cs}{
    \cs_set_eq:Nc \l_@@_cs {l_stex_notation_\l_stex_current_symbol_str _#1_cs}
  }{
    \stex_do_default_notation:
    \cs_set_eq:NN \l_@@_cs \l_stex_default_notation
  }
}


\cs_new:Nn \_@@_do_first_arg:n {{\exp_not:n{## #1}}}

\cs_new_protected:Nn \_@@_do_first: {
  \exp_args:Nnx \use:nn{
  \cs_generate_from_arg_count:NNnn \l_@@_cs \cs_set:Npn
  \l_stex_current_arity_str} {{
    \tl_set:Nn \exp_not:N \l_@@_first_args_tl {
      \int_step_function:nN \l_stex_current_arity_str \_@@_do_first_arg:n
    }
    \exp_not:N \_@@_do_first_next:
  }}
  \l_@@_cs
}

\cs_new_protected:Nn \_@@_do_first_next: {
  \peek_charcode_remove:NTF ! {
    \peek_charcode:NTF [ \_@@_do_one:w {\_@@_do_one:w []}
  }{
    \peek_charcode:NTF [ \_@@_do_all:w {\_@@_do_all:w []}
  }
}

\cs_new_protected:Npn \_@@_do_one:w [#1] {
  \_@@_get_index_notation:n{#1}
  \stex_debug:nn{HERE~seq~one}{\meaning\l_@@_cs^^J\meaning\l_@@_first_args_tl}
  \exp_args:Nno\use:nn{\l_@@_cs\group_end:}\l_@@_first_args_tl
}

\cs_new_protected:Npn \_@@_do_all:w [#1] {
  \stex_debug:nn{HERE~seq~all}{\meaning\l_@@_first_args_tl}
  \exp_args:Nno\use:nn{\_stex_invoke_notation:w [#1]}\l_@@_first_args_tl
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\seqmap}
%    \begin{macrocode}
\cs_new_protected:Npn \seqmap #1 #2 {
  \symuse{Metatheory?sequence~expression}{\seqmap{#1}{#2}}%\l_tmpa_tl {#2}
}
%    \end{macrocode}
% \end{macro}
%
% \end{sfragment}
%
% \begin{sfragment}{Expressions}
%    \begin{macrocode}
%<@@=stex_expr>
%    \end{macrocode}
%
% Various variables:
%
%    \begin{macrocode}
\bool_new:N \l_stex_allow_semantic_bool
\bool_set_true:N \l_stex_allow_semantic_bool
\tl_new:N \l_stex_current_term_tl
\tl_set:Nn \l_stex_every_symbol_tl {
  \bool_set_false:N \l_stex_allow_semantic_bool
}
%    \end{macrocode}
%
% \begin{macro}{\_stex_next_symbol:n}
%    \begin{macrocode}
\tl_new:N \l_@@_reset_tl
\cs_new_protected:Nn \_stex_next_symbol:n {
  \tl_set:Nx \l_stex_every_symbol_tl {
    \tl_gset:Nn \exp_not:N \l_@@_reset_tl {
      \tl_set:Nn \exp_not:N \l_stex_every_symbol_tl  {
        \exp_args:No \exp_not:n \l_stex_every_symbol_tl
      }
      \tl_gset:Nn \exp_not:N \l_@@_reset_tl {
        \exp_args:No \exp_not:n \l_@@_reset_tl
      }
    }
    \tl_set:Nn \exp_not:N \l_stex_every_symbol_tl  {
      \exp_args:No \exp_not:n \l_stex_every_symbol_tl
    }
    \exp_not:n{ \aftergroup \l_@@_reset_tl }
    \exp_not:N \l_stex_every_symbol_tl
    \exp_not:n{ #1 }
  }
}
\cs_generate_variant:Nn \_stex_next_symbol:n {e}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\STEXinvisible}
%    \begin{macrocode}
\cs_new_protected:Npn \STEXinvisible #1 {
  \stex_annotate_invisible:n { #1 }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{sfragment}{Invoking Semantic Macros}
%
% \begin{macro}{\_stex_invoke_symbol:nnnnnnnN}
%    \begin{macrocode}
\cs_new_protected:Nn \_stex_invoke_symbol:nnnnnnnN {
  \bool_if:NTF \l_stex_allow_semantic_bool{
    \stex_if_html_backend:T{\ifvmode\indent\fi}
    \_@@_setup:nnnnnn{\_comp}{#1?#2}{#3}{#4}{#7}{#6}
    \cs_set_eq:NN \_stex_term_oms_or_omv:nnn \_stex_term_oms:nnn
    \tl_put_right:Nn \l_stex_current_redo_tl{
      \cs_set_eq:NN \_stex_term_oms_or_omv:nnn \_stex_term_oms:nnn
    }
    #8
  }{
    \msg_error:nnxx{stex}{error/notallowed}{#1?#2}{\l_stex_current_symbol_str}
  }
}
\cs_generate_variant:Nn \_stex_invoke_symbol:nnnnnnnN {ooxooooN}

\cs_new_protected:Nn \_@@_setup:nnnnnn {
  \group_begin:
  \tl_clear:N \l_stex_return_notation_tl
  \tl_set:Nn \l_stex_current_redo_tl {
    \let \this \stex_current_this:
    \def\comp{#1}
    \def\maincomp{\comp}
    \str_set:Nn \l_stex_current_symbol_str {#2} 
    \str_set:Nn \l_stex_current_arity_str{ #3 }
    \tl_set:Nn \l_stex_current_args_tl{ #4 }
    \tl_set:Nn \l_stex_current_return_tl{ #5 }
    \tl_set:Nn \l_stex_current_type_tl{ #6 }
    \tl_clear:N \l_stex_current_term_tl
  }
  \tl_put_right:Nx \l_stex_current_redo_tl {
    \exp_args:No \exp_not:n \l_stex_every_symbol_tl
  }
  \l_stex_current_redo_tl
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\_stex_invoke_variable:nnnnnn}
%    \begin{macrocode}
\cs_new_protected:Nn \_stex_invoke_variable:nnnnnnN {
  \bool_if:NTF \l_stex_allow_semantic_bool{
    \stex_if_html_backend:T{\ifvmode\indent\fi}
    \_@@_setup:nnnnnn{\_varcomp}{#1}{#2}{#3}{#6}{#5}
    \cs_set_eq:NN \_stex_term_oms_or_omv:nnn \_stex_term_omv:nnn
    \tl_put_right:Nn \l_stex_current_redo_tl {
      \cs_set_eq:NN \_stex_term_oms_or_omv:nnn \_stex_term_omv:nnn
    }
    #7
  }{
    \msg_error:nnxx{stex}{error/notallowed}{#1}{\l_stex_current_symbol_str}
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\symuse}
%    \begin{macrocode}
\cs_new_protected:Npn \symuse #1 {
  \stex_get_symbol:n{#1}
  \exp_args:Nno \use:n {\_stex_invoke_symbol:ooxooooN
  \l_stex_get_symbol_mod_str
  \l_stex_get_symbol_name_str
  {\int_use:N \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
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\stex_invoke_symbol:}
%
% Top-Level: Check whether text/math mode or custom notation, 
% whether delimited by !, return code etc.
%    \begin{macrocode}
\cs_new_protected:Nn \stex_invoke_symbol: {
  \stex_debug:nn{expressions}{Invoking~\l_stex_current_symbol_str}
  \mode_if_math:TF \@@_invoke_math: \@@_invoke_text:
}

\cs_new_protected:Nn \@@_invoke_text: {
  \stex_debug:nn{expressions}{text~mode}
  \peek_charcode_remove:NTF ! \@@_invoke_op_custom:n \@@_invoke_custom:n
}

\cs_new_protected:Nn \@@_invoke_math: {
  \stex_debug:nn{expressions}{math~mode}
  \peek_charcode_remove:NTF ! {
    % operator
    \peek_charcode_remove:NTF * \@@_invoke_op_custom:n {
      % op notation
      \peek_charcode:NTF [ \@@_invoke_op_notation:w {
        \@@_invoke_op_notation:w []
      }
    }
  }{
    \peek_charcode_remove:NTF * \@@_invoke_custom:n {
      % normal
      \peek_charcode:NTF [ \_stex_invoke_notation:w {
        \_stex_invoke_notation:w []
      }
    }
  }
}
%    \end{macrocode}
%
% Notations:
%
%    \begin{macrocode}
\cs_new_protected:Npn \_stex_invoke_notation:w [#1] {
  \stex_debug:nn{expressions}{using~notation~#1~for~\l_stex_current_symbol_str}
  \cs_if_exist:cTF{l_stex_notation_\l_stex_current_symbol_str _#1_cs}{
    \tl_if_empty:NTF \l_stex_current_return_tl {
      \stex_debug:nn{expressions}{return~empty}
      \use:c{l_stex_notation_\l_stex_current_symbol_str _#1_cs}{\group_end:\_stex_eat_exclamation_point:}
    }{
      \stex_debug:nn{expressions}{return?}
      \exp_after:wN\exp_after:wN\exp_after:wN
      \@@_invoke_return_maybe:n
      \exp_after:wN\exp_after:wN\exp_after:wN
      {\cs:w l_stex_notation_\l_stex_current_symbol_str _#1_cs \cs_end: {}}
    }
  }{
    \stex_do_default_notation:
    \tl_if_empty:NTF \l_stex_current_return_tl {
      \l_stex_default_notation{\group_end:\_stex_eat_exclamation_point:}
    }{
      \exp_after:wN
      \@@_invoke_return_maybe:n
      \exp_after:wN
      {\l_stex_default_notation {}}
    }
  }
}

\cs_new_protected:Npn \@@_invoke_op_notation:w [#1] {
  \stex_debug:nn{expressions}{op~notation~for~\l_stex_current_symbol_str}
  \cs_if_exist:cTF{l_stex_notation_\l_stex_current_symbol_str _op_#1_cs}{
    \_stex_maybe_brackets:nn{\neginfprec}{
      \_stex_term_oms_or_omv:nnn{#1}{}
      {\use:c{l_stex_notation_\l_stex_current_symbol_str _op_#1_cs}}
    }
    \group_end:
  }{
    \int_compare:nNnTF \l_stex_current_arity_str = 0 {
      \tl_clear:N \l_stex_current_return_tl
      \_stex_invoke_notation:w [#1]
    }{
      \stex_do_default_notation_op:    
      \_stex_maybe_brackets:nn{\neginfprec}{
        \_stex_term_oms_or_omv:nnn{#1}{}
        {\l_stex_default_notation}
      }
      \group_end:
    }
  }
}
%    \end{macrocode}
%
% Return:
%
%    \begin{macrocode}
\cs_new_protected:Nn \@@_invoke_return_maybe:n {
  \tl_clear:N \l_@@_return_args_tl
  \tl_set:Nn \l_@@_return_this_tl {#1}
  \exp_args:Nnx \use:n {
  \cs_generate_from_arg_count:NNnn \_@@_ret_cs
    \cs_set:Npn \l_stex_current_arity_str } {
      \int_step_function:nN \l_stex_current_arity_str \_@@_return_arg:n
      \_@@_invoke_return_next:
    }
  \_@@_ret_cs
}

\cs_new:Nn \_@@_return_arg:n {
  \tl_put_right:Nn \exp_not:N \l_@@_return_args_tl {{#### #1}}
}

\cs_new_protected:Nn \_@@_invoke_return_next: {
  \peek_charcode_remove:NTF ! {
    \exp_after:wN \l_@@_return_this_tl \l_@@_return_args_tl \group_end:
  }\_@@_invoke_return:
}

\cs_new_protected:Nn \_@@_invoke_return: {
  \tl_set:Nx \l_@@_return_this_tl {
    \_@@_return_notation:n {
      \exp_after:wN \exp_after:wN \exp_after:wN
      \exp_not:n \exp_after:wN \exp_after:wN \exp_after:wN {
        \exp_after:wN \l_@@_return_this_tl \l_@@_return_args_tl
      }
    }
  }
  \stex_debug:nn{return}{Notation:~\meaning\l_@@_return_this_tl}
  \tl_put_left:Nx \l_@@_return_this_tl {
    \group_begin:\exp_args:No \exp_not:n \l_stex_current_redo_tl
  }
  \exp_args:Nnx \use:n {
  \cs_generate_from_arg_count:NNnn \_@@_ret_cs
    \cs_set:Npn \l_stex_current_arity_str } {
      \exp_args:No \exp_not:n \l_stex_current_return_tl
    }
  \stex_debug:nn{return}{
    \meaning\_@@_ret_cs^^J
    \meaning\l_@@_return_this_tl^^J
    \exp_args:No \exp_not:n \l_@@_return_args_tl^^J
  }
  \exp_args:Nnx \use:nn {
    \exp_after:wN \group_end: \_@@_ret_cs
  }{
    \exp_args:No \exp_not:n \l_@@_return_args_tl
    {
      \exp_args:No \exp_not:n \l_@@_return_this_tl
      \group_end:
    }
  }
}


\cs_new_protected:Nn \_@@_return_notation:n {
  \tl_if_empty:NTF \l_stex_return_notation_tl { #1 }{
    \l_stex_return_notation_tl
  }
}

%    \end{macrocode}
%
% Custom Notations:
%
%    \begin{macrocode}
\cs_new_protected:Nn \@@_invoke_op_custom:n {
  \stex_debug:nn{expressions}{custom~op}
  \bool_set_true:N \l_stex_allow_semantic_bool
  \_stex_term_oms_or_omv:nnn{}{}{\maincomp{#1}}
  \group_end:
}

\int_new:N \l_@@_arg_counter_int
\cs_new_protected:Nn \@@_invoke_custom:n {
  \stex_debug:nn{custom}{custom~notation~for~\l_stex_current_symbol_str}
  \stex_pseudogroup:nn{
    \bool_set_true:N \l_stex_allow_semantic_bool
    \prop_gclear:N \l_@@_customs_prop
    \seq_gclear:N \l_@@_customs_seq
    \int_gzero:N \l_@@_arg_counter_int
    \tl_if_empty:NF \l_stex_current_args_tl {
      \exp_after:wN \_@@_add_prop_arg:nnw \l_stex_current_args_tl \_stex_args_end:
      \cs_set_eq:NN \arg \_@@_arg:n
    }
    \tl_set_eq:NN \l_stex_get_symbol_args_tl \l_stex_current_args_tl
    \cs_set_eq:NN \_@@_do_ab_next:nnn \_stex_term_oma:nnn
    \_stex_map_args:N \_@@_check_b:nn
    \_@@_do_ab_next:nnn{}{}{#1}
  }{
    \prop_if_exist:NT \l_@@_customs_prop {
      \prop_gset_from_keyval:Nn \exp_not:N \l_@@_customs_prop {
        \prop_to_keyval:N \l_@@_customs_prop
      }
    }
    \int_gset:Nn \l_@@_arg_counter_int { \int_use:N \l_@@_arg_counter_int}
    \seq_if_exist:NT \l_@@_customs_seq {
      \seq_gset_split:Nnn \exp_not:N \l_@@_customs_seq , {
        \seq_use:Nn \l_@@_customs_seq ,
      }
    }
  }
  % TODO check that all arguments are present
  \group_end:
}

\cs_new_protected:Npn \_@@_add_prop_arg:nnw #1 #2 #3\_stex_args_end: {
  \prop_gput:Nnn \l_@@_customs_prop {#1} {}
  \seq_gput_right:Nn \l_@@_customs_seq {#2}
  \tl_if_empty:nF{#3}{\_@@_add_prop_arg:nnw #3 \_stex_args_end:}
}

\cs_new:Nn \_@@_check_b:nn {
  \str_case:nn #2 {
    b {\cs_set_eq:NN \_@@_do_ab_next:nnn \_stex_term_omb:nnn}
    B {\cs_set_eq:NN \_@@_do_ab_next:nnn \_stex_term_omb:nnn}
  }
}

\NewDocumentCommand \_@@_arg:n {s O{} m} {
  \IfBooleanTF #1 {
    \stex_annotate_invisible:n{
      \_@@_arg_inner:nn{#2}{#3}
    }
  }{
    \_@@_arg_inner:nn{#2}{#3}
  }
}

\cs_new_protected:Nn \_@@_arg_inner:nn {
  \tl_if_empty:nTF{#1}{
    \int_gincr:N \l_@@_arg_counter_int
    \exp_args:Ne \_@@_check:nTF{ \int_use:N \l_@@_arg_counter_int }{
      \_@@_arg_do:oon \l_tmpa_tl \l_tmpb_tl
    }{
      \_@@_arg_inner:nn{}
    }{ #2 }
  }{
    \_@@_check:nTF {#1}{
      \_@@_arg_do:oon \l_tmpa_tl \l_tmpb_tl { #2 }
    }{
      \exp_args:No \str_case:nnTF \l_tmpb_tl {
        {a}{
          \exp_args:NNnx \prop_gput:Nnn \l_@@_customs_prop {#1}{
            \l_tmpa_tl X
          }
          \tl_set:Nx \l_tmpa_tl { #1 \int_eval:n {\tl_count:N \l_tmpa_tl + 1} }
        }
        {B}{
          \exp_args:NNnx \prop_gput:Nnn \l_@@_customs_prop {#1}{
            \l_tmpa_tl X
          }
          \tl_set:Nx \l_tmpa_tl { #1 \int_eval:n {\tl_count:N \l_tmpa_tl + 1} }
        }
      }{
        \_@@_arg_do:oon \l_tmpa_tl \l_tmpb_tl { #2 }
      }{
        \msg_error:nnxx{stex}{error/invalidarg}{#1}{\l_stex_current_symbol_str}
      }
    }
  }
}

\prg_new_conditional:Nnn \_@@_check:n {TF} {
  \exp_args:NNe \prop_get:NnNTF \l_@@_customs_prop {#1} \l_tmpa_tl {
    \tl_set:Nx \l_tmpb_tl {\seq_item:Nn \l_@@_customs_seq {#1} }
    \tl_if_empty:NTF \l_tmpa_tl {
      \exp_args:NNe \prop_gput:Nnn \l_@@_customs_prop 
        { #1 }{X}
      \exp_args:No \str_case:nnF \l_tmpb_tl {
        {a}{
          \tl_set:Nx \l_tmpa_tl{ #1 1 }
        }
        {B}{
          \tl_set:Nx \l_tmpa_tl{ #1 1 }
        }
      }{
        \tl_set:Nx \l_tmpa_tl{ #1 }
      }
      \prg_return_true:
    }{
      \prg_return_false:
    }
  }{
    \msg_error:nnxx{stex}{error/invalidarg}{#1}{\l_stex_current_symbol_str}
    \prg_return_false:
  }
}

% #1 argnum #2 argmode #3 code
\cs_new_protected:Nn \_@@_arg_do:nnn {
  \stex_debug:nn{custom}{Doing~argument~#1~of~mode~#2:~\tl_to_str:n{#3}}
  \group_begin:
    \bool_set_true:N \l_stex_allow_semantic_bool
    \_stex_term_arg:nnn {#2}{#1}{#3}
  \group_end:
}
\cs_generate_variant:Nn \_@@_arg_do:nnn {oon}
%    \end{macrocode}
% \end{macro}
%
% \end{sfragment}
%
% \begin{sfragment}{Argument Handling and Annotating}
%
% \begin{macro}{\_stex_term_arg:nnnnn,\_stex_term_arg:nnn}
%    \begin{macrocode}
% 1: argnum 2: argmode 3: precedence 4: argname 5: code
\cs_new_protected:Nn \_stex_term_arg:nnnnn {
  \group_begin:
    \str_clear:N \l_stex_current_symbol_str
    \tl_clear:N \l_stex_current_term_tl
    \int_set:Nn \l_stex_notation_downprec { #3 }
    \bool_set_true:N \l_stex_allow_semantic_bool
    \_stex_term_arg:nnn {#2}{#1}{
      \tl_if_empty:nTF{#4}{
        #5
      }{
        \stex_annotate:nn{mml:arg={#4}}{#5}
      }
    }
  \group_end:
}

\cs_new_protected:Nn \_stex_term_arg:nnn {
  \stex_annotate:nn{ shtml:arg={#2}, shtml:argmode={#1}}{
    \_stex_annotate_force_break:n{ #3 }
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\_stex_term_arg_aB:nnnnn}
%    \begin{macrocode}
\tl_set:Nn \_@@_do_aB_clist: {
  \seq_use:Nn \l_stex_aB_args_seq {
    \mathpunct{\comp{,}}
  }
}
\tl_set_eq:NN \_stex_term_do_aB_clist: \_@@_do_aB_clist:

\int_new:N \l_@@_count_int
\cs_new_protected:Nn \_stex_term_arg_aB:nnnnn {
  \tl_if_empty:nTF{#5}{
    \_stex_term_arg:nnnnn{#1}{#2}{#3}{#4}{}
  }{
    \seq_clear:N \l_stex_aB_args_seq
    \int_zero:N \l_@@_count_int
    \clist_map_inline:nn{#5}{
      \_@@_aB_arg:nnnnn{##1}{#1}{#2}{#3}{#4}
    }
    \_stex_term_do_aB_clist:
  }
}

% 1: code 2: argnum 3: argmode 4: precedence 5: argname 
\cs_new_protected:Npn \_@@_aB_arg:nnnnn #1 {
  \int_incr:N \l_@@_count_int
  \_@@_is_varseq:nTF{#1}{
    \exp_after:wN \exp_after:wN \exp_after:wN
    \_@@_assoc_seq:nnnnnnn
    \exp_after:wN
    \_@@_gobble:nnnnnnnn #1 \_@@_end:
  }{
    \_@@_is_seqmap:nTF{#1}{
      \exp_args:NNe \use:nn \_@@_do_seqmap:nnnnnn {\tl_tail:n{#1}}
    }{
      \_@@_aB_simple_arg:nnnnn{#1}
    }
  }
}

\cs_new:Npn \_@@_gobble:nnnnnnnn #1 #2 #3 #4 #5 #6 #7 #8 #9 \_@@_end: {
  {#2} #3 {#6}
}

\cs_new_protected:Nn \_@@_aB_simple_arg:nnnnn{
  \seq_put_right:Nx \l_stex_aB_args_seq {
    \_stex_term_arg:nnnnn{#2\int_use:N\l_@@_count_int}{#3}{#4}{#5}{
      \exp_not:n{ 
        \tl_set_eq:NN \_stex_term_do_aB_clist: \_@@_do_aB_clist:
        #1
      }
    }
  }
}

\cs_new_protected:Nn \_stex_is_sequentialized:n {
  \group_begin: #1 \group_end:
}
%    \end{macrocode}
%
% Conditionals: Is the argument a sequence variable or a |\seqmap|?
%
%    \begin{macrocode}
\prg_new_conditional:Nnn \_@@_is_varseq:n {TF} {
  \int_compare:nNnTF {\tl_count:n{#1}} = 1 {
    \exp_args:Ne \cs_if_eq:NNTF {\exp_args:No \tl_head:n{#1}}
    \_stex_invoke_variable:nnnnnnN {
      \exp_args:Ne \cs_if_eq:NNTF {\exp_args:No\tl_item:nn{#1}{8}}
        \stex_invoke_sequence: 
          \prg_return_true:\prg_return_false:
    }\prg_return_false:
  }\prg_return_false:
}

\prg_new_conditional:Nnn \_@@_is_seqmap:n {TF} {
  \int_compare:nNnTF {\tl_count:n{#1}} = 3 {
    \exp_args:Ne \tl_if_eq:nnTF {\tl_head:n{#1}} {\seqmap}
      \prg_return_true:\prg_return_false:
  }\prg_return_false:
}
%    \end{macrocode}
%
% Sequence variable:
%
%    \begin{macrocode}
% 1: name 2: arity 3: clist 4: argnum 5: argmode 6: precedence 7: argname 
\cs_new_protected:Nn \_@@_assoc_seq:nnnnnnn {
  \group_begin:
    \seq_clear:N \l_stex_aB_args_seq
    \_@@_assoc_make_seq:nnn{#1}{#3}{#2}
  \exp_args:NNe \use:nn \group_end: {
    \seq_put_right:Nn \exp_not:N \l_stex_aB_args_seq {
      \_stex_is_sequentialized:n{
        \_stex_term_arg:nnnnn{#4\int_use:N\l_@@_count_int}{#5}{#6}{#7}{
          \bool_set_true:N \l_stex_allow_semantic_bool
          \str_set:Nn \exp_not:N \l_stex_current_symbol_str
            {\l_stex_current_symbol_str}
          \tl_if_empty:NF \l_stex_current_term_tl {
            \tl_set:Nn \exp_not:N \l_stex_current_term_tl {
              \exp_args:No \exp_not:n \l_stex_current_term_tl
            }
          }
          \stex_annotate:nn{
            shtml:term=OMV,
            shtml:head={#1},
            shtml:notationid={}
          }{
            \_stex_annotate_force_break:n{
              \_stex_term_do_aB_clist:
            }
          }
        }
      }
    }
  }
}

% #1: name, #2: clist, #3:arity
\cs_new_protected:Nn \_@@_assoc_make_seq:nnn {
  \cs_if_exist:cTF{l_stex_notation_#1__cs}{
    \cs_set_eq:Nc \l_@@_cs {l_stex_notation_#1__cs}
  }{
    \stex_do_default_notation:
    \cs_set_eq:NN \l_@@_cs \l_stex_default_notation
  }
  \clist_map_inline:nn{#2}{
    \tl_if_eq:nnTF{##1}{\ellipses}{
      \seq_put_right:Nn \l_stex_aB_args_seq { ##1 }
    }{
      \int_compare:nNnTF {#3} = 1 {
        \tl_set:Nn \l_@@_iarg_tl { {##1} }
      }{
        \tl_set:Nn \l_@@_iarg_tl { ##1 }
      }
      \seq_put_right:Nx \l_stex_aB_args_seq {
        \group_begin:
        \exp_not:n {
          \tl_set_eq:NN \_stex_term_do_aB_clist: \_@@_do_aB_clist:
          \def\comp{\_varcomp}
          \str_set:Nn \l_stex_current_symbol_str{#1}
        }
        \exp_after:wN \exp_after:wN \exp_after:wN \exp_not:n 
        \exp_after:wN \exp_after:wN \exp_after:wN {
          \exp_after:wN \l_@@_cs \exp_after:wN \group_end: \l_@@_iarg_tl
        } 
      }
    }
  }
}
%    \end{macrocode}
%
% |\seqmap|:
%
%    \begin{macrocode}
% 1: fun 2: clist 3: argnum 4: argmode 5: precedence 6: argname 
\cs_new_protected:Nn \_@@_do_seqmap:nnnnnn {
  \group_begin:
    \cs_set:Npn \l_tmpa_cs ##1 {#1}
    \seq_clear:N \l_stex_aB_args_seq
    \clist_map_inline:nn{#2}{
      \_@@_is_varseq:nTF{##1}{
        \exp_after:wN
        \_@@_varseq_in_map:nnnnnnnn ##1
      }{
        \seq_put_right:Nn \l_stex_aB_args_seq {##1}
      }
    }
    \seq_clear:N \l_@@_old_seq
    \seq_map_inline:Nn \l_stex_aB_args_seq {
      \tl_if_eq:nnTF{##1}{\ellipses}{
        \seq_put_right:Nn \l_@@_old_seq {##1}
      }
      % TODO \_stex_is_sequentialized:n
      {
        \exp_args:NNo \seq_put_right:Nn \l_@@_old_seq {
          \l_tmpa_cs {##1}
        }
      }
    }
    \seq_set_eq:NN \l_stex_aB_args_seq \l_@@_old_seq
  \exp_args:NNe \use:nn \group_end: {
    \seq_put_right:Nn \exp_not:N \l_stex_aB_args_seq {
      \_stex_is_sequentialized:n{
        \_stex_term_arg:nnnnn{#4\int_use:N\l_@@_count_int}{#4}{#5}{#6}{
          \bool_set_true:N \l_stex_allow_semantic_bool
          \str_set:Nn \exp_not:N \l_stex_current_symbol_str
            {\l_stex_current_symbol_str}
          \tl_set:Nn \exp_not:N \l_stex_current_term_tl {
            \symuse{Metatheory?sequence~map}
            {\exp_args:No \exp_not:n \l_tmpa_tl}
            {\_stex_term_do_aB_clist:}
          }
          \_@@_do_headterm:nn{}{
            \_stex_term_do_aB_clist:
          }
        }
      }
    }
  }
}

\cs_new_protected:Nn \_@@_varseq_in_map:nnnnnnnn {
  \_@@_assoc_make_seq:nnn{#2}{#6}{#3}
}
%    \end{macrocode}
% \end{macro}
%
% \end{sfragment}
%
% \begin{sfragment}{Term HTML Annotations}
%
% \begin{macro}{\_stex_term_oms_or_omv:nnn,\_stex_term_oms:nnn,\_stex_term_omv:nnn}
%    \begin{macrocode}
\cs_new_protected:Nn \_stex_eat_exclamation_point: {
  \peek_charcode_remove:NT ! {
    \_stex_eat_exclamation_point:
  }
}

\bool_new:N \stex_in_invisible_html_bool
\bool_set_false:N \stex_in_invisible_html_bool
\stex_if_html_backend:TF {
  % 1: variant 2: intent 3: code
  \cs_new_protected:Nn \_stex_term_oms:nnn {
    \tl_if_empty:NTF \l_stex_current_term_tl {
      \stex_annotate:nn{
        shtml:term=OMID,
        shtml:head={\l_stex_current_symbol_str},
        shtml:notationid={#1},
      }{
        \_stex_annotate_force_break:n{#3}
      }
    }{
      \_@@_do_headterm:nn{#1}{#3}
    }
  }
  \cs_new_protected:Nn \_stex_term_omv:nnn {
    \tl_if_empty:NTF \l_stex_current_term_tl {
      \stex_annotate:nn{
        shtml:term=OMV,
        shtml:head={\l_stex_current_symbol_str},
        shtml:notationid={#1}
      }{
        \_stex_annotate_force_break:n{#3}
      }
    }{
      \_@@_do_headterm:nn{#1}{#3}
    }
  }
  \cs_new_protected:Nn \_@@_do_headterm:nn {
    \bool_if:NTF \stex_in_invisible_html_bool {
      {\bool_set_true:N \l_stex_allow_semantic_bool
        \ensuremath{\l_stex_current_term_tl}
      }
    }{
      \stex_annotate:nn{
        shtml:term=complex,
        shtml:head={\l_stex_current_symbol_str},
        shtml:notationid={#1}
      }{
        \_stex_annotate_force_break:n{
          \stex_annotate_invisible:nn{shtml:headterm={}}{
            {\bool_set_true:N \l_stex_allow_semantic_bool
              \ensuremath{\l_stex_current_term_tl}
            }
          }
        }
        #2
      }
    }
  }
}{
  \cs_new_protected:Nn \_stex_term_oms:nnn {#3}
  \cs_new_protected:Nn \_stex_term_omv:nnn {#3}
  \cs_new_protected:Nn \_@@_do_headterm:nn { #2 }
}
\cs_set_eq:NN \_stex_term_oms_or_omv:nnn \_stex_term_oms:nnn
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\_stex_term_oma:nnn}
%    \begin{macrocode}
\stex_if_html_backend:TF {
  \cs_new_protected:Nn \_stex_term_oma:nnn {
    \tl_if_empty:NTF \l_stex_current_term_tl {
      \stex_annotate:nn{
        shtml:term=OMA,
        shtml:head={\l_stex_current_symbol_str},
        shtml:notationid={#1}
      }{
        \_stex_annotate_force_break:n{#3}
      }
    }{
      \stex_annotate:nn{
        shtml:term=OMA,
        shtml:head={\l_stex_current_symbol_str},
        shtml:notationid={#1}
      }{
        \_stex_annotate_force_break:n{
          \stex_annotate_invisible:nn{shtml:headterm={}}{{
            \bool_set_true:N \l_stex_allow_semantic_bool
            \l_stex_current_term_tl
          }}
          #3
        }
      }
    }
  }
}{
  \cs_new_protected:Nn \_stex_term_oma:nnn {#3}
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\_stex_term_omb:nnn}
%    \begin{macrocode}
\stex_if_html_backend:TF {
  \cs_new_protected:Nn \_stex_term_omb:nnn {
    \tl_if_empty:NTF \l_stex_current_term_tl {
      \stex_annotate:nn{
        shtml:term=OMBIND,
        shtml:head={\l_stex_current_symbol_str},
        shtml:notationid={#1}
      }{
        \_stex_annotate_force_break:n{#3}
      }
    }{
      \stex_annotate:nn{
        shtml:term=OMBIND,
        shtml:head={\l_stex_current_symbol_str},
        shtml:notationid={#1}
      }{
        \_stex_annotate_force_break:n{
          \stex_annotate_invisible:nn{shtml:headterm={}}{{
            \bool_set_true:N \l_stex_allow_semantic_bool
            \l_stex_current_term_tl
          }}
          #3
        }
      }
    }
  }
}{
  \cs_new_protected:Nn \_stex_term_omb:nnn { #3 }
}
%    \end{macrocode}
% \end{macro}
%
% \end{sfragment}
%
% \begin{sfragment}{Automated Bracketing}
%
% \begin{macro}{\infprec,\neginfprec}
%    \begin{macrocode}
\tl_const:Nx \infprec {\int_use:N \c_max_int}
\tl_const:Nx \neginfprec {-\int_use:N \c_max_int}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\dobrackets}
%    \begin{macrocode}
\int_new:N \l_stex_notation_downprec
\int_set:Nn \l_stex_notation_downprec \infprec
\tl_set:Nn \l_@@_left_bracket_str (
\tl_set:Nn \l_@@_right_bracket_str )
\bool_new:N \l_stex_brackets_dones_bool

\cs_new_protected:Nn \_stex_maybe_brackets:nn {
  \bool_if:NTF \l_stex_brackets_dones_bool {
    \bool_set_false:N \l_stex_brackets_dones_bool
    #2
  } {
    \stex_debug:nn{brackets}{#1>\int_eval:n \l_stex_notation_downprec?}
    \int_compare:nNnTF { #1 } > \l_stex_notation_downprec {
      %\bool_if:NTF \l_stex_inparray_bool { #2 }{
        \dobrackets { 
          #2 
        }
      %}
    }{
      #2 
    }
  }
}

%\RequirePackage{scalerel}
\cs_new_protected:Npn \dobrackets #1 {
  %\ThisStyle{\if D\m@switch
  %    \exp_args:Nnx \use:nn
  %    { \exp_after:wN \left\l_@@_left_bracket_str #1 } 
  %    { \exp_not:N\right\l_@@_right_bracket_str }
  %  \else
  \group_begin:
  %\stex_pseudogroup_with:nn{\l_stex_brackets_dones_bool\l_stex_notation_downprec}{ 
    \bool_set_true:N \l_stex_brackets_dones_bool
    %\int_set:Nn \l_stex_notation_downprec \infprec
    \mathopen{\cs_if_exist:NT\l_stex_current_symbol_str\comp
      \l_@@_left_bracket_str
    } 
    #1
  \group_end:%}
  \mathclose{\cs_if_exist:NT\l_stex_current_symbol_str\comp
    \l_@@_right_bracket_str
  }
  %\fi}
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\withbrackets}
%    \begin{macrocode}
\cs_new_protected:Npn \withbrackets #1 #2 #3 {
  \stex_pseudogroup_with:nn{\l_@@_left_bracket_str\l_@@_right_bracket_str}{
    \tl_set:Nn \l_@@_left_bracket_str { #1 }
    \tl_set:Nn \l_@@_right_bracket_str { #2 }
    #3
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\dowithbrackets}
%    \begin{macrocode}
\cs_new_protected:Npn \dowithbrackets #1 #2 #3 {
  \withbrackets{#1}{#2}{\dobrackets{#3}}
}
%    \end{macrocode}
% \end{macro}
%
% \end{sfragment}
%
% \begin{sfragment}{Symname and Variants}
%
% \begin{macro}{\symname,\sn,\sns,\Symname,\Sn,\Sns,\symref,\sr,\varref,\varname,\Varname}
%    \begin{macrocode}
\def\maincomp{\comp}

\stex_keys_define:nnnn{symname}{
  \tl_clear:N \l_stex_key_pre_tl
  \tl_clear:N \l_stex_key_post_tl
  %\tl_clear:N \l_stex_key_proot_tl
}{
  pre    .tl_set:N   = \l_stex_key_pre_tl ,
  post   .tl_set:N   = \l_stex_key_post_tl ,
  root   .code:n     = {}%.tl_set:N   = \l_stex_key_root_tl
}{}

\NewDocumentCommand \symref { O{} m m} {
  \group_begin:
  \stex_keys_set:nn{symname}{#1}
  \stex_get_symbol:n{#2}
  \_@@_do_ref:nNn{#3}\symrefemph@uri\_stex_term_oms:nnn
}
\let\sr\symref

\NewDocumentCommand \symname { O{} m} {
  \group_begin:
  \stex_keys_set:nn{symname}{#1}
  \stex_get_symbol:n{#2}
  \_@@_do_ref:nNn{
    \l_stex_key_pre_tl\l_stex_get_symbol_name_str\l_stex_key_post_tl
  }\symrefemph@uri\_stex_term_oms:nnn
}
\let\sn\symname
\protected\def\sns{\symname[post=s]}

\NewDocumentCommand \Symname { O{} m} {
  \group_begin:
  \stex_keys_set:nn{symname}{#1}
  \stex_get_symbol:n{#2}
  \_@@_do_ref:nNn{
    \l_stex_key_pre_tl\exp_after:wN\_stex_capitalize:n\l_stex_get_symbol_name_str\l_stex_key_post_tl
  }\symrefemph@uri\_stex_term_oms:nnn
}
\cs_new_protected:Nn \_stex_capitalize:n {
  \uppercase{#1}
}
\let\Sn\Symname
\protected\def\Sns{\Symname[post=s]}

\cs_new:Npn \_stex_split_slash: #1/#2/#3\_stex_args_end: {
 \tl_if_empty:nTF{#3}{
  #2
 }{
  \_stex_split_slash: #2 / #3 \_stex_args_end:
 }
}

\NewDocumentCommand \varref { O{} m m} {
  \group_begin:
  \stex_keys_set:nn{symname}{#1}
  \stex_get_var:n{#2}
  \_@@_do_ref:nNn{#3}\varemph@uri{
    \str_set_eq:NN \l_stex_current_symbol_str\l_stex_get_symbol_name_str
    \def\comp{\_varcomp}
    \_stex_term_omv:nnn
  }
}

\NewDocumentCommand \varname { O{} m} {
  \group_begin:
  \stex_keys_set:nn{symname}{#1}
  \stex_get_var:n{#2}
  \_@@_do_ref:nNn{
    \l_stex_key_pre_tl\l_stex_get_symbol_name_str\l_stex_key_post_tl
  }\varemph@uri{
    \str_set_eq:NN \l_stex_current_symbol_str\l_stex_get_symbol_name_str
    \def\comp{\_varcomp}
    \_stex_term_omv:nnn
  }
}

\NewDocumentCommand \Varname { O{} m} {
  \group_begin:
  \stex_keys_set:nn{symname}{#1}
  \stex_get_var:n{#2}
  \_@@_do_ref:nNn{
    \l_stex_key_pre_tl\exp_after:wN\_stex_capitalize:n\l_stex_get_symbol_name_str\l_stex_key_post_tl
  }\varemph@uri{
    \str_set_eq:NN \l_stex_current_symbol_str\l_stex_get_symbol_name_str
    \def\comp{\_varcomp}
    \_stex_term_omv:nnn
  }
}


\cs_new_protected:Nn \_@@_do_ref:nNn {
  \stex_if_html_backend:T{\ifvmode\indent\fi}
  \bool_if:NTF \l_stex_allow_semantic_bool{
    \str_set:Nx\l_stex_current_symbol_str
      {\l_stex_get_symbol_mod_str ? \l_stex_get_symbol_name_str}
    \str_if_in:NnT \l_stex_get_symbol_name_str / {
      \str_set:Nx \l_stex_get_symbol_name_str {
        \exp_after:wN \_stex_split_slash: \l_stex_get_symbol_name_str
        /\_stex_args_end:
      }
    }
    \tl_clear:N \l_stex_current_term_tl
    \def\comp{\_comp}
    \let\compemph@uri#2
    #3{}{}{\comp{#1}}
  }{
    \msg_error:nnxx{stex}{error/notallowed}{#1}{\l_stex_current_symbol_str}
  }
  \group_end:
}
%    \end{macrocode}
% \end{macro}
%
% \end{sfragment}
%
% \begin{sfragment}{Highlighting}
%    \begin{macrocode}
%<@@=stex_notationcomps>
%    \end{macrocode}
%
% \begin{macro}{\comp,\compemph@uri,\compemph,\defemph,\defemph@uri,\symrefemph,\symrefemph@uri,\varemph,\varemph@uri}
%    \begin{macrocode}
\cs_new_protected:Nn \_do_comp:nNn {
  \stex_pseudogroup_with:nn{\comp}{
    \def\comp##1{##1}
    \str_if_empty:NTF \l_stex_current_symbol_str {
      #3
    }{
      \stex_if_html_backend:TF {
        \stex_annotate:nn { shtml:#1 = \l_stex_current_symbol_str}{ #3 }
      }{
        \exp_args:Nno #2 { #3 } \l_stex_current_symbol_str
      }
    }
  }
}

\cs_new_protected:Npn \_comp {
  \_do_comp:nNn {comp}\compemph@uri
}

\cs_new_protected:Npn \_varcomp {
  \_do_comp:nNn {varcomp}\varemph@uri
}

\cs_new_protected:Npn \_defcomp {
  \_do_comp:nNn {definiendum}\defemph@uri
}

\cs_set_protected:Npn \comp {}

\cs_new_protected:Npn \compemph@uri #1 #2 {
    \compemph{ #1 }
}

\cs_new_protected:Npn \compemph #1 {
    #1
}

\cs_new_protected:Npn \defemph@uri #1 #2 {
    \defemph{#1}
}

\cs_new_protected:Npn \defemph #1 {
    \ifmmode\else\expandafter\textbf\fi{#1}
}

\cs_new_protected:Npn \symrefemph@uri #1 #2 {
    \symrefemph{#1}
}

\cs_new_protected:Npn \symrefemph #1 {
    \emph{#1}
}

\cs_new_protected:Npn \varemph@uri #1 #2 {
    \varemph{#1}
}

\cs_new_protected:Npn \varemph #1 {
    #1
}
%    \end{macrocode}
% \end{macro}
%
% \end{sfragment}
%
% \end{sfragment}
%
% \end{sfragment}
%
% \begin{sfragment}{Mathematical Structures}
%    \begin{macrocode}
%<@@=stex_structures>
%    \end{macrocode}
%
% \begin{macro}{\this}
%    \begin{macrocode}
\cs_new_protected:Npn \stex_current_this: {
  { \bool_set_true:N \l_stex_allow_semantic_bool
    \tl_if_empty:NTF \l_stex_current_this_tl {{}}{
      \str_set:Nx \l_stex_current_symbol_str {
        \l_stex_current_module_str ? \l_@@_name_str
      }
      \maincomp{\l_stex_current_this_tl}
    }
  }
}
\let \this \stex_current_this:
%    \end{macrocode}
% \end{macro}
%
% \begin{environment}{mathstructure}
%    \begin{macrocode}
\stex_new_stylable_env:nnnnnnn {mathstructure}{m O{}}{
  \_@@_begin:nn{#1}{#2}
  \stex_smsmode_do:
}{
  \stex_structural_feature_module_end:
  \_@@_do_externals:
}{}{}{}

\stex_keys_define:nnnn{mathstructure}{
  \tl_clear:N \l_stex_current_this_tl
  \str_clear:N \l_@@_name_str
}{
  this    .tl_set:N = \l_stex_current_this_tl ,
  unknown .code:n   = {
    \str_if_empty:NTF \l_keys_key_str {
      \str_set:Nx \l_@@_name_str {\l_keys_key_tl}
    }{
      \str_set_eq:NN \l_@@_name_str \l_keys_key_str
    }
  }
}{}

\cs_new_protected:Nn \_@@_begin:nn {
  \stex_keys_set:nn {mathstructure}{#2}
  \str_if_empty:NT \l_@@_name_str {
    \str_set:Nn \l_@@_name_str {#1}
  }
  \def\comp{\_comp}

  \exp_args:Nne \use:nn { \stex_module_add_symbol:nnnnnnnN }
    { {#1}{\l_@@_name_str}{0}{}{defed}{
      \l_stex_current_module_str / \l_@@_name_str-module
    }}
    {}\stex_invoke_structure:
  \str_set:Nx \l_stex_macroname_str {#1}
  \stex_execute_in_module:x{
    \seq_clear:c{l_stex_structure_macros_\l_stex_current_module_str / \l_@@_name_str-module_seq}
    \seq_put_right:cn{l_stex_structure_macros_\l_stex_current_module_str / \l_@@_name_str-module_seq}{#1}
  }
  \exp_args:No \stex_structural_feature_module:nn
    {\l_@@_name_str}{structure}
}

\stex_sms_allow_env:n{mathstructure}
\stex_deactivate_macro:Nn \mathstructure {module~environments}
\stex_every_module:n {\stex_reactivate_macro:N \mathstructure}

\cs_new_protected:Nn \_@@_do_externals: {
  \tl_set:Nn \l_@@_replace_this_tl {####1}
  \exp_args:No \stex_iterate_symbols:nn{\g_stex_last_feature_str}{
    \_@@_external_decl:nnnn{##5}{##4}{##3}{##8}
  }
}

\cs_new_protected:Nn \_@@_external_decl:nnnn {
  %\stex_debug:nn{structure}{
  %  Generating~external~declaration~\l_@@_name_str/#3~in~
  %  \l_stex_current_module_str^^J
  %  \tl_to_str:n{#1}^^J\tl_to_str:n{#2}^^J\tl_to_str:n{#4}
  %}
  %\tl_set:Nn \l_stex_get_symbol_args_tl {#1}
  %\exp_args:Nnx \use:nn {\stex_module_add_symbol:nnnnnnnN} {
  %  {}{\l_@@_name_str/#3}{\int_eval:n{#2 + 1}}
  %  {1i\tl_if_empty:nF{#1}{\_stex_map_args:N \_@@_shift_argls:nn}}
  %  {defed}{typed}
  %}{#4}\stex_invoke_outer_field:
}

\cs_new:Nn \_@@_shift_argls:nn {
  \int_eval:n{#1+1}#2
}
%    \end{macrocode}
% \end{environment}
%
% \begin{macro}{\stex_get_mathstructure:n}
%    \begin{macrocode}
\cs_new_protected:Nn \stex_get_mathstructure:n {
  \_stex_get_mathstructure:n{#1}
  \str_if_empty:NT \l_stex_get_structure_module_str {
    \msg_error:nnn{stex}{error/unknownstructure}{#1}
  }
}
\cs_new_protected:Nn \_stex_get_mathstructure:n {
  \str_clear:N \l_stex_get_structure_module_str
  \_stex_get_symbol:n{#1}
  \str_if_empty:NF \l_stex_get_symbol_name_str {
    \exp_args:No \tl_if_eq:NNT \l_stex_get_symbol_invoke_cs \stex_invoke_structure: {
      \str_set_eq:NN \l_stex_get_structure_module_str \l_stex_get_symbol_type_tl
    }
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{environment}{extstructure}
%    \begin{macrocode}
\stex_new_stylable_env:nnnnnnn {extstructure}{m O{} m}{
  \seq_clear:N \l_@@_imports_seq
  \clist_map_inline:nn{#3}{
    \stex_get_mathstructure:n{##1}
    \clist_map_inline:Nn \l_stex_get_symbol_type_tl {
      \exp_args:Ne \stex_if_module_exists:nT{\tl_to_str:n{####1}}{
        \seq_put_right:Nn \l_@@_imports_seq{####1}
      }
    }
    \stex_execute_in_module:x{
      \seq_put_right:cn{l_stex_structure_macros_\l_stex_get_structure_module_str _seq}{#1}
    }
  }
  \_@@_begin:nn{#1}{#2}
  \seq_map_inline:Nn\l_@@_imports_seq{
    \stex_if_do_html:T {
      \hbox{\stex_annotate_invisible:nn 
        {shtml:import={##1}} {}}
    }
    \stex_module_add_morphism:nonn
      {}{##1}{import}{}
    \stex_execute_in_module:x{ 
      \stex_activate_module:n{##1}
    }
  }
  \stex_smsmode_do:
}{
  \stex_structural_feature_module_end:
  \_@@_do_externals:
}{}{}{}

\stex_sms_allow_env:n{extstructure}
\stex_deactivate_macro:Nn \extstructure {module~environments}
\stex_every_module:n {
  \stex_reactivate_macro:N \extstructure
}

\cs_new:Nn \_@@_extend_structure_i:NnnnnnnnN {
  \exp_not:n{#1{#2}{#3}{#4}{#5}{defed}}{\l_@@_extmod_str,#7}\exp_not:n{{#8}#9}
}
\cs_new_protected:Nn \_@@_extend_structure:nn {
  \stex_debug:nn{ext}{Extending~#1~by~#2}
  \str_set:Nn \l_@@_extmod_str{#2}
  \tl_set:cx{#1}{
    \exp_after:wN \exp_after:wN \exp_after:wN
    \_@@_extend_structure_i:NnnnnnnnN \cs:w #1 \cs_end:
  }
}

\stex_new_stylable_env:nnnnnnn {extstructure*}{m}{
  \_@@_new_extstruct_name:
  \seq_clear:N \l_@@_imports_seq
  \stex_get_mathstructure:n{#1}
  
  \clist_map_inline:Nn \l_stex_get_symbol_type_tl {
    \exp_args:Ne \stex_if_module_exists:nT{\tl_to_str:n{##1}}{
      \seq_put_right:Nn \l_@@_imports_seq{##1}
    }
  }

  \stex_execute_in_module:x{
    \seq_map_inline:cn{l_stex_structure_macros_\l_stex_get_structure_module_str _seq}{
      \exp_not:N \tl_if_exist:cT{####1}{
        \_@@_extend_structure:nn{####1}{\l_stex_current_module_str/\l_@@_exstruct_name_str -module}
      }
    }
  }

  \exp_args:No \_@@_begin:nn\l_@@_exstruct_name_str{}

  \seq_map_inline:Nn \l_@@_imports_seq {
    \stex_if_do_html:T {
      \stex_annotate_invisible:nn 
        {shtml:import= {##1}} {}
    }
    \stex_module_add_morphism:nonn
      {}{##1}{import}{}
    \stex_execute_in_module:x{ 
      \stex_activate_module:n{##1}
    }
  }

  \stex_smsmode_do:
}{
  \prop_map_inline:cn{
    c_stex_module_ \l_stex_current_module_str _symbols_prop
  }{
    \_@@_check_def:nnnnnnnn ##2
  }
  \stex_structural_feature_module_end:
  \_@@_do_externals:
}{}{}{}

\stex_sms_allow_env:n{extstructure*}
\exp_after:wN \stex_deactivate_macro:Nn 
  \cs:w extstructure*\cs_end: {module~environments}
\stex_every_module:n {
  \exp_after:wN \stex_reactivate_macro:N \cs:w extstructure*\cs_end:
}

\cs_new_protected:Nn \_@@_check_def:nnnnnnnn {
  \tl_if_empty:nT{#5}{
    \msg_error:nnnn{stex}{error/needsdefiniens}{#2}{extstructure*}
  }
}

\stex_every_module:n{ \str_set:Nn \l_@@_extname_count 0}

\cs_new_protected:Nn \_@@_new_extstruct_name: {
  \stex_do_up_to_module:n {
    \str_set:Nx \l_@@_extname_count {\int_eval:n{\l_@@_extname_count+1}}
  }
  \str_set:Nx \l_@@_exstruct_name_str {EXTSTRUCT_\l_@@_extname_count}
}

%    \end{macrocode}
% \end{environment}
%
% Invoking structures:
%    \begin{macrocode}
\cs_new_protected:Nn \stex_invoke_structure: {
  \tl_set:Nn \l_@@_set_comp_tl {\_@@_set_thiscomp:}
  \_@@_invoke_top:n {}
}

\cs_new_protected:Nn \_@@_invoke_top:n {
  \stex_debug:nn{structure}{
    invoking~structure~{\l_stex_current_type_tl}<\tl_to_str:n{#1}>
  }
  \peek_charcode:NTF [ {
    \_@@_merge:nw{#1}
  }{
    \_@@_invokation_type:n {#1}
    \tl_set:Nn \l_@@_this_tl {}
    \peek_charcode_remove:NTF ! {
      \peek_charcode:NTF [ {
        \_@@_maybe_notation:w
      }{
        \_@@_maybe_notation:w []
      }
    }{
      \_@@_invoke_this:n
    }
  }
}

\cs_new_protected:Npn \_@@_merge:nw #1 [ #2 ] {
  \exp_args:Ne \stex_str_if_starts_with:nnTF {\tl_to_str:n{#2}}{comp=}{
    \_@@_set_customcomp: #2 \_@@_end:
    \_@@_invoke_top:n{#1}
  }{
    \exp_args:Ne \stex_str_if_starts_with:nnTF {\tl_to_str:n{#2}}{this=}{
      \_@@_set_thisnotation: #2 \_@@_end:
      \_@@_invoke_top:n{#1}
    }{
      \tl_if_empty:nTF{#1}{
        \_@@_invoke_top:n{#2}
      }{
        \tl_if_empty:nTF{#2}{
          \_@@_invoke_top:n{#1}
        }{
          \_@@_invoke_top:n{#1,#2}
        }
      }
    }
  }
}

\cs_new_protected:Npn \_@@_set_thisnotation: this= #1 \_@@_end: {
  \tl_set:Nn \l_stex_return_notation_tl { \comp{#1} }
  \tl_set:Nn \l_@@_set_comp_tl {}
}

\cs_new_protected:Npn \_@@_set_customcomp: comp= #1 \_@@_end: {
  \tl_set:Nn \l_@@_set_comp_tl {
    \_@@_set_custom_comp:n{#1}
  }
  \tl_set:Nn \l_stex_return_notation_tl { \comp{} }
}
%    \end{macrocode}
% The structure type:
%    \begin{macrocode}
\cs_new_protected:Nn \_@@_invokation_type:n {
  \_@@_do_assign_list:n{#1}
  \clist_if_empty:NTF \l_@@_fields_clist {
    \int_compare:nNnTF {\clist_count:N \l_stex_current_type_tl}
      = 1 {
        \tl_set:Nx \l_@@_current_type_tl {
          \exp_args:No \exp_not:n \l_stex_current_redo_tl
          \_stex_term_oms_or_omv:nnn{}{}{}
        }
      }{
        \exp_args:No \_@@_make_type:n \l_stex_current_type_tl
    }
  }{
    \int_compare:nNnTF {\clist_count:N \l_stex_current_type_tl}
      = 1 {
        \_@@_make_type:n {}
      }{
        \exp_args:No \_@@_make_type:n \l_stex_current_type_tl
    }
  }
}

\cs_new_protected:Nn \_@@_do_assign_list:n {
  \clist_clear:N \l_@@_fields_clist
  \tl_if_empty:nF {#1} {
    \keyval_parse:NNn\TODO\_@@_do_assign:nn{#1}
  }
}

\cs_new_protected:Nn \_@@_do_assign:nn {
  \clist_put_right:Nn \l_@@_fields_clist {{#1}{#2}}
}

\cs_new_protected:Nn \_@@_make_type:n {
  \tl_if_empty:nTF{#1}{
    \seq_clear:N \l_tmpa_seq
  }{
    \seq_set_split:Nnn \l_tmpa_seq ,{#1}
    \seq_pop_right:NN \l_tmpa_seq \l_tmpa_tl
    \seq_reverse:N \l_tmpa_seq
  }
  \tl_set:Nx \l_@@_current_type_tl {
    \symuse{Metatheory?module~type~merge}{
      {
        \exp_args:No \exp_not:n \l_stex_current_redo_tl
        \_stex_term_oms_or_omv:nnn{}{}{}
      }
      \seq_map_function:NN \l_tmpa_seq \_@@_make_mod:n
      \clist_if_empty:NF \l_@@_fields_clist {
        ,\symuse{Metatheory?anonymous~record}{
          \exp_args:Ne \tl_tail:n{
            \clist_map_function:NN \l_@@_fields_clist \_@@_make_oml:n
          }
        }
      }
    }
  }
}

\cs_new:Nn \_@@_make_mod:n {
  ,\symuse{Metatheory?module~type}{
    \stex_annotate:nn{shtml:term=OMMOD,shtml:head={#1}}{}
  }
}

\cs_new:Nn \_@@_make_oml:n {
  \_@@_make_oml:nn #1
}
\cs_new:Nn \_@@_make_oml:nn {
  ,\stex_annotate:nn{
    shtml:term=OML,
    shtml:head={#1}
  }{
    \_stex_annotate_force_break:n{
      \stex_annotate:nn{shtml:definiens={}}{\exp_not:n{#2!}}
    }
  }
}
%    \end{macrocode}
% Insert the structure type as a term:
%    \begin{macrocode}
\cs_new:Nn \_@@_current_type: {
  %\exp_args:No \exp_not:n \l_stex_current_redo_tl
  \tl_set:Nn \exp_not:N \l_stex_current_term_tl {
    \exp_args:No\exp_not:n\l_@@_current_type_tl
  }
  \_stex_term_oms_or_omv:nnn{}{}{}
}
%    \end{macrocode}
% The structure type itself:
%    \begin{macrocode}
\cs_new_protected:Npn \_@@_maybe_notation:w [ #1 ] {
  \tl_set_eq:NN \l_stex_current_term_tl \l_@@_current_type_tl
  \cs_if_exist:cTF{l_stex_notation_\l_stex_current_symbol_str _#1_cs}{
    \use:c{l_stex_notation_\l_stex_current_symbol_str _#1_cs}\group_end:
  }{
    \_@@_make_prop:
    \_@@_make_prop_assign:
    \_@@_present_i:w [#1]
  }
}

\cs_new_protected:Nn \_@@_present: {
  \peek_charcode:NTF [ {
    \_@@_present_i:w
  }{
    \_@@_present:nn{}{}
  }
}

\cs_new_protected:Npn \_@@_present_i:w [#1] {
  \int_compare:nNnTF{\clist_count:n{#1}} = 1 {
    \_@@_present:nn{}{#1}
  }{
    \peek_charcode:NTF [ {
      \_@@_present_ii:nw{#1}
    }{
      \_@@_present:nn{#1}{}
    }
  }
}

%First: clist, second:notation-id
\cs_new_protected:Npn \_@@_present_ii:nw #1 [#2] {
  \_@@_present:nn{#1}{#2}
}

\cs_new_protected:Nn \_@@_present:nn {
  \clist_clear:N \l_@@_clist
  \tl_if_empty:nTF{#1}{
    \cs_set:Npn \l_@@_cs ##1 ##2 ##3 {
      \tl_if_empty:nF{##2}{
        \_@@_present_entry:nn {##1}{##3}
      }
    }
  }{
    \cs_set:Npn \l_@@_cs ##1 ##2 ##3 {
      \exp_args:Ne \clist_if_in:nnT{\tl_to_str:n{#1}}{##1}{
        \_@@_present_entry:nn {##1}{##3}
      }
    }
  }
  \prop_map_inline:Nn \l_@@_prop {
    \l_@@_cs {##1} ##2
  }
  \_stex_term_oms_or_omv:nnn{}{}{
    \exp_args:Nno \use:n{
      \bool_set_true:N \l_stex_allow_semantic_bool
      \symuse{Metatheory?mathematical~structure}[#2]
    }{\l_@@_clist}
  }\group_end:
}

\cs_new_protected:Nn \_@@_present_entry:nn {
  \seq_if_in:NnTF \l_@@_assigned_seq {#1}{
    \clist_put_right:Nn \l_@@_clist {#2!}
  }{
    \exp_args:NNe \clist_put_right:Nn \l_@@_clist {
      \_stex_next_symbol:n { 
        \exp_args:No \exp_not:n \l_@@_set_comp_tl 
        \tl_set:Nn \exp_not:N \l_@@_this_tl {
          \exp_args:No \exp_not:n \l_@@_this_tl
        }
        \exp_not:n {
          \tl_set_eq:NN \this \l_@@_this_tl
        }
        \tl_set:Nn \exp_not:N \l_stex_return_notation_tl {
          \exp_args:No \exp_not:n \l_stex_return_notation_tl
        }
      }
      \exp_not:n{#2!}
    }
  }
}

\cs_new_protected:Npn \_thiscomp #1 #2 {
  {\tl_set:cn{this}{{}}#1{#2}\c_math_subscript_token{
    \group_begin:
    \bool_set_true:N \l_stex_allow_semantic_bool
    \l_@@_this_tl
    \group_end:
  }
  }
}

\cs_new_protected:Nn \_@@_set_thiscomp: {
  \exp_args:Ne \tl_if_eq:NNF {\tl_head:N \maincomp} \_thiscomp {
    \edef\maincomp {\_thiscomp{\comp}}
  }
}

\cs_new_protected:Nn \_@@_set_custom_comp:n {
  \exp_args:Ne \tl_if_eq:NNF {\tl_head:N \maincomp} \_customthiscomp {
    \cs_set_protected:Npx \_customthiscomp ##1 {
      \group_begin:
        \bool_set_true:N \l_stex_allow_semantic_bool
        \exp_not:n{
          \cs_set:Npn \l_@@_comp_cs ##1  {
            #1
          }
          \def\maincomp
        }{\comp}
        \exp_not:N\l_@@_comp_cs{\comp{##1}}
      \group_end:
    }
    \def\maincomp {\_customthiscomp}
  }
}

%    \end{macrocode}
% |this| (of type |structure|):
%    \begin{macrocode}

\cs_new_protected:Nn \_@@_invoke_this:n {
  \peek_charcode_remove:NTF ! {
    \exp_args:Nne\use:nn{
      \group_end:\symuse{Metatheory?of~type}[invisible]{#1}
    }{
      {\_@@_current_type:}
    }
  }{
    \_@@_invoke_maybe_field:nn{#1}
  }
}

\cs_new_protected:Nn \_@@_invoke_maybe_field:nn {
  \_@@_make_prop:
  \_@@_set_this:n{#1}
  \tl_if_empty:nTF{#2}{
    \_@@_make_prop_assign:
    \_@@_present:
  }{
    \_@@_invoke_field:n{#2}
  }
}

\cs_new_protected:Nn \_@@_set_this:n {
  \tl_if_empty:nTF{#1}{
    %\tl_put_right:Nn \l_stex_current_redo_tl {
    %  \tl_clear:N \l_@@_this_tl
    %}
  }{
    \tl_set:Nx \l_@@_this_tl {{
      \bool_set_true:N \l_stex_allow_semantic_bool
      \tl_set:Nn \exp_not:N \this {
        \exp_args:No \exp_not:n \this
      }
      \exp_not:n{#1}
    }}
    \tl_set_eq:NN \this \l_@@_this_tl
    % \l_stex_return_notation_tl
  }
}

\cs_new_protected:Nn \_@@_get_field_name:n {
  \str_set:Nx \l_@@_field_name_str {
    \exp_args:Nne \use:n {\exp_after:wN \use_i:nn \use:n}
    {\prop_item:Nn \l_@@_prop {#1}}
  }
  \str_if_empty:NT \l_@@_field_name_str {
    \str_set:Nn \l_@@_field_name_str {#1}
  }
}

\cs_new_protected:Nn \_@@_invoke_field:n {
  \prop_if_in:NnTF \l_@@_prop {#1}{
    \_@@_get_field_name:n{#1}
    \tl_clear:N \l_@@_more_nextsymbol_tl
    %\exp_args:NNe \seq_if_in:NnF \l_@@_assigned_seq {\tl_to_str:n{#1}}{
      \tl_set:Nx \l_@@_more_nextsymbol_tl {
        \tl_set:Nn \exp_not:N \l_@@_this_tl {
          \exp_args:No \exp_not:n \l_@@_this_tl
        }
        \exp_not:n {
          \tl_set_eq:NN \this \l_@@_this_tl
        }
        \tl_set:Nn \exp_not:N \l_stex_return_notation_tl {
          \exp_args:No \exp_not:n \l_stex_return_notation_tl
        }
        \exp_args:No \exp_not:n \l_@@_set_comp_tl
      }
    %}
    \exp_args:NNx \use:nn \group_end: {
      \_stex_next_symbol:n {
        \exp_args:No \exp_not:n \l_@@_redo_tl
        \tl_set:Nn \exp_not:N \l_stex_current_term_tl {
          \symuse{Metatheory?record~field}{
            \symuse{Metatheory?of~type}{
              \exp_args:No \exp_not:n \l_@@_this_tl
            }{  \_@@_current_type: }
          }{
            \stex_annotate:nn{shtml:term=OML,shtml:head={\l_@@_field_name_str}}{}
          }
        }
        \exp_args:No \exp_not:n \l_@@_more_nextsymbol_tl
      }
      \exp_not:N \use_ii:nn
      \prop_item:Nn \l_@@_prop {#1}
    }
  }{
    \msg_error:nnn{stex}{error/unknownfield}{#1}
  }
}

\cs_new_protected:Nn \_@@_make_prop: {
  \prop_clear:N \l_@@_prop
  \seq_clear:N \l_@@_seq
  \seq_clear:N \l_@@_assigned_seq
  \tl_clear:N \l_@@_redo_tl
  \_@@_prop_do_decls:
  \_@@_prop_do_notations:
}

\cs_new_protected:Nn \_@@_make_prop_assign: {
  \clist_if_empty:NF \l_@@_fields_clist {
    \clist_map_inline:Nn \l_@@_fields_clist {
      \_@@_make_prop_assign:nn ##1
    }
  }
}

\cs_new_protected:Nn \_@@_make_prop_assign:nn {
  \prop_if_in:NnTF \l_@@_prop {#1}{
    \exp_args:NNe \seq_put_right:Nn \l_@@_assigned_seq {\tl_to_str:n{#1}}
    \exp_args:Nne \use:nn {\_@@_make_prop_assign_replace:nnnn {#1}{#2}}
    {\prop_item:Nn \l_@@_prop {#1}}
  }{
    \msg_error:nnn{stex}{error/unknownfieldass}{#1}
  }
}
\cs_new_protected:Nn \_@@_make_prop_assign_replace:nnnn {
  \prop_put:Nnn \l_@@_prop {#1}{{#3}{#2}}
  \tl_if_empty:nF{#3}{
    \tl_set:cn{#1}{ #2 }
    \tl_put_right:Nn \l_@@_redo_tl {
      \tl_set:cn{#1}{ #2 }
    }
  }
}

\cs_new_protected:Nn \_@@_prop_do_decls: {
  \exp_args:No \stex_iterate_symbols:nn \l_stex_current_type_tl {
    \tl_if_empty:nTF{##2}{
      \_@@_do_decl_nomacro:nnnnnnnnn{##3}
    }{
      \_@@_do_decl:nnnnnnnnn{##2}
    }
    {##1}{##3}{##4}{##5}{##6}{##7}{##8}{##9}
  }
}

\cs_new_protected:Nn \_@@_do_decl_nomacro:nnnnnnnnn {
  \prop_if_in:NnF \l_@@_prop {#1} {
    \seq_put_left:Nx \l_@@_seq {\tl_to_str:n{#2?#3}}
    \prop_put:Nnn \l_@@_prop {#1}{
      {}{
        \_stex_invoke_symbol:nnnnnnnN
        {#2}
        {#3}
        {#4}{#5}{#6}{#7}{#8}#9
      }
    }
  }
}

\cs_new_protected:Nn \_@@_do_decl:nnnnnnnnn {
  \prop_if_in:NnF \l_@@_prop {#1} {
    \seq_put_left:Nx \l_@@_seq {\tl_to_str:n{#2?#3}}
    \prop_put:Nnn \l_@@_prop {#1}{
      {#3}{
        \_stex_invoke_symbol:nnnnnnnN
        {#2}
        {#3}
        {#4}{#5}{#6}{#7}{#8}#9
      }
    }
  }
  %\tl_set:cn{#1}{
  %  \_stex_invoke_symbol:nnnnnnnN
  %  {#2}{#3}{#4}{#5}{#6}{#7}{#8}#9
  %}
  %\tl_put_right:Nn \l_@@_redo_tl {
  %  \tl_set:cn{#1}{
  %    \_stex_invoke_symbol:nnnnnnnN
  %    {#2}{#3}{#4}{#5}{#6}{#7}{#8}#9
  %  }
  %}
}

\cs_new_protected:Nn \_@@_prop_do_notations: {
  \exp_args:No \stex_iterate_notations:nn\l_stex_current_type_tl{
    \exp_args:NNe \seq_if_in:NnT \l_@@_seq {\tl_to_str:n{##1}}{
      \tl_put_right:Nn \l_@@_redo_tl {
        \cs_if_exist:cF{l_stex_notation_##1 _##2_cs}{
          \tl_set:cn{l_stex_notation_##1 _##2_cs}{##4}
        }
        \cs_if_exist:cF{l_stex_notation_##1 __cs}{
          \tl_set:cn{l_stex_notation_##1 __cs}{##4}
        }
      }
      \cs_if_exist:cF{l_stex_notation_##1 _##2_cs}{
        \tl_set:cn{l_stex_notation_##1 _##2_cs}{##4}
      }
      \cs_if_exist:cF{l_stex_notation_##1 __cs}{
        \tl_set:cn{l_stex_notation_##1 __cs}{##4}
      }
      \tl_if_empty:nF{##5}{
        \tl_put_right:Nn \l_@@_redo_tl {
          \cs_if_exist:cF{l_stex_notation_##1 _op_##2_cs}{
            \tl_set:cn{l_stex_notation_##1 _op_##2_cs}{##5}
          }
          \cs_if_exist:cF{l_stex_notation_##1 _op__cs}{
            \tl_set:cn{l_stex_notation_##1 _op__cs}{##5}
          }
        }
        \cs_if_exist:cF{l_stex_notation_##1 _op_##2_cs}{
          \tl_set:cn{l_stex_notation_##1 _op_##2_cs}{##5}
        }
        \cs_if_exist:cF{l_stex_notation_##1 _op__cs}{
          \tl_set:cn{l_stex_notation_##1 _op__cs}{##5}
        }
      }
    }
  }
}
%    \end{macrocode}
%
% \begin{macro}{\usestructure}
%    \begin{macrocode}
\cs_new_protected:Npn \usestructure #1 {
  \stex_get_mathstructure:n{ #1 }
  \seq_clear:N \l_@@_imports_seq
  \clist_map_inline:Nn \l_stex_get_symbol_type_tl {
    \exp_args:Ne \stex_if_module_exists:nT{\tl_to_str:n{##1}}{
      \seq_put_right:Nn \l_@@_imports_seq{##1}
    }
  }
  \seq_map_inline:Nn \l_@@_imports_seq {
    \stex_if_do_html:T {
      \hbox{\stex_annotate_invisible:nn 
        {shtml:usemodule=##1} {}}
    }
    \stex_activate_module:n {##1}
  }
}
%    \end{macrocode}
%
% \end{macro}
%
% \end{sfragment}
%
% \begin{sfragment}{Statements}
%    \begin{macrocode}
%<@@=stex_statements>

\stex_keys_define:nnnn{statement}{
  \str_clear:N \l_stex_key_name_str
  \str_clear:N \l_stex_key_macroname_str
  \clist_clear:N \l_stex_key_for_clist
  \str_clear:N \l_stex_key_args_str
  \tl_clear:N \l_stex_key_type_tl
  \tl_clear:N \l_stex_key_def_tl
  \tl_clear:N \l_stex_key_return_tl
  \clist_clear:N \l_stex_key_argtypes_clist
}{
  name    .str_set:N = \l_stex_key_name_str ,
  for     .clist_set:N = \l_stex_key_for_clist ,
  macro   .str_set:N = \l_stex_key_macroname_str ,
  % start   .str_set:N = \l_stex_key_title_str , % TODO remove
  type  .tl_set:N = \l_stex_key_type_tl ,
  judgment .code:n = {},
  from .code:n= {}, % TODO remove
  to .code:n={} % TODO remove
}{id,title,style,symargs}
%    \end{macrocode}
%
% \begin{macro}{\stex_new_statement:nn}
%    \begin{macrocode}
\cs_new_protected:Npn \_stex_do_for_list: {
  \seq_clear:N \l_stex_fors_seq
  \clist_map_inline:Nn \l_stex_key_for_clist {
    \exp_args:Ne\stex_get_symbol:n{\tl_to_str:n{##1}}
    \seq_put_right:Nx \l_stex_fors_seq 
      {\l_stex_get_symbol_mod_str ? \l_stex_get_symbol_name_str}
  }
}

\cs_new_protected:Nn \_@@_setup:nn {
  \str_if_empty:NF \l_stex_key_macroname_str {
    \str_if_empty:NT \l_stex_key_name_str {
      \str_set_eq:NN \l_stex_key_name_str \l_stex_key_macroname_str
    }
  }
  \_stex_do_for_list:
  \str_if_empty:NF \l_stex_key_name_str {
    \_@@_force_id:
    \seq_put_right:Nx \l_stex_fors_seq {
      \l_stex_current_module_str ? \l_stex_key_name_str
    }
    \str_set_eq:NN \l_stex_macroname_str \l_stex_key_macroname_str
    \str_set:Nn \l_stex_key_role_str {#2}
    \stex_symdecl_do:
    \exp_args:Nnx \use:nn {\stex_module_add_symbol:nnnnnnnN}{
      {\l_stex_key_macroname_str}{\l_stex_key_name_str}
      {\int_use:N \l_stex_get_symbol_arity_int}
      {\l_stex_get_symbol_args_tl}
      {#1}{}{}\stex_invoke_symbol:
    }
    \stex_if_do_html:T \_stex_symdecl_html:
  }
  \str_clear:N \l_@@_uri_str
  \str_if_empty:NTF \l_stex_key_name_str {
    \stex_debug:nn{statement}{no~name}
    \int_compare:nNnTF {\seq_count:N \l_stex_fors_seq} = 1 {
      \str_set:Nx \l_@@_uri_str {\seq_item:Nn \l_stex_fors_seq 1}
      \stex_debug:nn{statement}{for:~\l_@@_uri_str}
    }{
      \stex_debug:nn{statement}{no~for}
    }
  }{
    \str_set:Nx \l_@@_uri_str {\l_stex_current_module_str ? \l_stex_key_name_str}
    \stex_debug:nn{statement}{name:~\l_@@_uri_str}
  }
}

\cs_new:Nn \_@@_html_keyvals:nn {
  shtml:#1={},
  shtml:inline={#2},
  \seq_if_empty:NF \l_stex_fors_seq {,
    shtml:fors={\seq_use:Nn \l_stex_fors_seq ,}
  }
  \str_if_empty:NF \l_stex_key_id_str {,
    shtml:id={\stex_uri_use:N \l_stex_current_doc_uri ? \l_stex_key_id_str}
  }
  \clist_if_empty:NF \l_stex_key_style_clist {,
    shtml:styles={\l_stex_key_style_clist}
  }
}

\cs_new_protected:Nn \stex_new_statement:nnn {
  \stex_new_stylable_env:nnnnnnn {#1}{O{}}{
    \stex_keys_set:nn{statement}{##1}
    #3

    \stex_if_smsmode:F {
      \exp_args:Nne \begin{stex_annotate_env}{
        \_@@_html_keyvals:nn{#1}{false}
      }
      \tl_set_eq:NN \thistitle \l_stex_key_title_tl
      \str_set_eq:NN \thisname \l_stex_key_name_str
      \clist_set_eq:NN \thisfor \l_stex_key_for_str
      \stex_if_html_backend:TF {
        \noindent
        \stex_annotate:nn{shtml:statementtitle={}}{\_stex_annotate_force_break:n\l_stex_key_title_tl}
      }
      \stex_style_apply:
    }
    \_stex_do_id:
    \stex_smsmode_do:
  }{
    \stex_if_smsmode:F {
      \stex_if_html_backend:F \stex_style_apply:
      \end{stex_annotate_env}
    }
  }{}{}{s}
  \stex_sms_allow_env:n{s#1}
  
  \tl_if_empty:nF{#2}{
    \exp_after:wN \NewDocumentCommand \cs:w inline#2\cs_end: { O{} m}{
      \group_begin:
        \stex_keys_set:nn{statement}{##1}
        #3
        \_stex_do_id:
        \stex_if_smsmode:F{
          \exp_args:Ne \stex_annotate:nn{\_@@_html_keyvals:nn{#1}{true}}{
            \_stex_annotate_force_break:n{##2}
          }
        }
      \group_end:
      \stex_smsmode_do:
    }
    \exp_after:wN \stex_sms_allow_escape:N\cs:w inline#2\cs_end:
  }
}

\cs_new_protected:Nn \_@@_setup_def: {
  \stex_if_smsmode:F{
    \seq_map_inline:Nn \l_stex_fors_seq {
      \stex_ref_new_sym_target:n{##1}
    }
  }
  \stex_reactivate_macro:N \definiendum
  \stex_reactivate_macro:N \defnotation
  \stex_reactivate_macro:N \definame
  \stex_reactivate_macro:N \Definame
  \stex_reactivate_macro:N \varbind
}

\cs_new_protected:Nn \_@@_force_id: {
  \str_if_empty:NT \l_stex_key_id_str {
    \_stex_ref_new_id:n{}
    \str_set_eq:NN \l_stex_key_id_str \l__stex_refs_str
  }
}

\stex_new_statement:nnn{definition}{def}{
  \_@@_force_id:
  \_@@_setup:nn{}{}
  \_@@_setup_def:
  \stex_reactivate_macro:N \definiens
}
\stex_new_statement:nnn{assertion}{ass}{
  \_@@_setup:nn{}{assertion}
  \stex_if_smsmode:F{
    \seq_map_inline:Nn \l_stex_fors_seq {
      \stex_ref_new_sym_target:n{##1}
    }
  }
  \stex_reactivate_macro:N \varbind
  \stex_reactivate_macro:N \conclusion
  \stex_reactivate_macro:N \premise
  \stex_reactivate_macro:N \definiendum
  \stex_reactivate_macro:N \defnotation
  \stex_reactivate_macro:N \definame
  \stex_reactivate_macro:N \Definame
}
\stex_new_statement:nnn{example}{ex}{\_@@_setup:nn{}{example}}
\stex_new_statement:nnn{paragraph}{}{
  \clist_if_in:NnTF \l_stex_key_style_clist {symdoc}{
    \_@@_force_id:
    \_@@_setup:nn{}{}
    \_@@_setup_def:
  }{
    \_@@_setup:nn{}{}
  }
}
%    \end{macrocode}
% \end{macro}
%

% \begin{macro}{definiendum}
%    \begin{macrocode}
\cs_new_protected:Nn \_@@_do_defref:nn {
  \stex_if_html_backend:T{\ifvmode\indent\fi}
  \group_begin:
  \stex_get_symbol:n{#1}
  \bool_if:NTF \l_stex_allow_semantic_bool{
    \str_set:Nx\l_stex_current_symbol_str
      {\l_stex_get_symbol_mod_str ? \l_stex_get_symbol_name_str}
    \str_if_in:NnT \l_stex_get_symbol_name_str / {
      \str_set:Nx \l_stex_get_symbol_name_str {
        \exp_after:wN \_stex_split_slash: \l_stex_get_symbol_name_str
        /\_stex_args_end:
      }
    }
    \exp_args:No \stex_ref_new_sym_target:n \l_stex_current_symbol_str
    \def\comp{\_defcomp}
    \stex_annotate:nn{shtml:definiendum=\l_stex_current_symbol_str}{\comp{#2}}
  }{
    \msg_error:nnxx{stex}{error/notallowed}{#1}{\l_stex_current_symbol_str}
  }
  \group_end:
}

\NewDocumentCommand \defnotation{ m } {
  \_stex_next_symbol:n { \def\comp{\_defcomp}}#1
}
\stex_deactivate_macro:Nn \defnotation {definition~environments}

\NewDocumentCommand \definiendum { O{} m m} {
  \stex_keys_set:nn{symname}{ #1 }
  \_@@_do_defref:nn{#2}{#3}
}
\stex_deactivate_macro:Nn \definiendum {definition~environments}

\NewDocumentCommand \definame { O{} m } {
  \stex_keys_set:nn{symname}{#1}
  \_@@_do_defref:nn{#2}{
    \l_stex_key_pre_tl\l_stex_get_symbol_name_str\l_stex_key_post_tl
  }
}
\stex_deactivate_macro:Nn \definame {definition~environments}

\NewDocumentCommand \Definame { O{} m } {
  \stex_keys_set:nn{symname}{#1}
  \_@@_do_defref:nn{#2}{
    \l_stex_key_pre_tl\exp_after:wN\_stex_capitalize:n\l_stex_get_symbol_name_str\l_stex_key_post_tl
  }
}
\stex_deactivate_macro:Nn \Definame {definition~environments}


\NewDocumentCommand \definiens { O{} m }{
  \group_begin:
  \str_clear:N \l_stex_get_symbol_name_str
  \tl_if_empty:nF {#1} {
    \stex_get_symbol:n { #1 }
    \str_set:Nx \l_@@_uri_str
      {\l_stex_get_symbol_mod_str ? \l_stex_get_symbol_name_str}
  }
  \str_if_empty:NT \l_@@_uri_str {
    \msg_error:nn{stex}{error/definiensfor}
  } 
  \stex_debug:nn{definiens}{Checking~\l_@@_uri_str}

  \exp_args:No \_stex_add_definiens:nn \l_@@_uri_str{#2}

  \group_end:
  \stex_smsmode_do:
}
\stex_deactivate_macro:Nn \definiens {definition~environments}
\stex_sms_allow_escape:N \definiens

\cs_new_protected:Nn \_stex_add_definiens:nn {
  \exp_args:Nno \stex_str_if_starts_with:nnT{#1} \l_stex_current_module_str {
    \prop_map_inline:cn{c_stex_module_\l_stex_current_module_str _symbols_prop}{
      \stex_debug:nn{definiens}{#1 == \l_stex_current_module_str?##1}
      \str_if_eq:noT {#1} {\l_stex_current_module_str?##1}{
        \prop_map_break:n{\_stex_add_definiens_inner:nnnnnnnn ##2}
      }
    }
  }
  \stex_if_smsmode:F{
    \stex_annotate:nn{ shtml:definiens={#1}}{ 
      #2 %\_stex_annotate_force_break:n{ #2 }
    }
  }
}

\cs_new_protected:Nn \_stex_add_definiens_inner:nnnnnnnn {
  \stex_debug:nn{definiens}{Adding~definiens~to~\l_stex_current_module_str?#2}
  \prop_gput:cnn{c_stex_module_\l_stex_current_module_str _symbols_prop}
    {#2}{{#1}{#2}{#3}{#4}{defed}{#6}{#7}{#8}}
}

\NewDocumentCommand \varbind {m} {
  \clist_map_inline:nn {#1} {
    \stex_get_var:n {##1}
    \stex_if_do_html:T {
      \stex_annotate_invisible:nn {shtml:bind=\l_stex_get_symbol_name_str}{}
    }
  }
}
\stex_deactivate_macro:Nn \varbind {definition~or~assertion~environments}

\NewDocumentCommand \conclusion { O{} m} {
  \group_begin:
  \str_clear:N \l_stex_get_symbol_name_str
  \tl_if_empty:nF {#1} {
    \stex_get_symbol:n { #1 }
    \str_set:Nx \l_@@_uri_str
      {\l_stex_get_symbol_mod_str ? \l_stex_get_symbol_name_str}
  }
  \str_if_empty:NT \l_@@_uri_str {
    \msg_error:nn{stex}{error/conclusionfor}
  } 
  \stex_annotate:nn{ shtml:conclusion=\l_@@_uri_str}{ 
    #2 %\_stex_annotate_force_break:n{ #2 }
  }
  \group_end:
}
\stex_deactivate_macro:Nn \conclusion {assertion~environments}

\NewDocumentCommand \premise {O{} m} {
  \tl_if_empty:nF {#1} {
    \stex_debug:nn{Here:}{Variable~#1}
    \exp_args:Nne\use:nn{\vardef}{{v#1}[name=#1]{#1}}
  }
  \stex_annotate:nn{shtml:premise={#1}}{#2}
}
\stex_deactivate_macro:Nn \premise {assertion~environments}
%    \end{macrocode}
% \end{macro}
%
% \end{sfragment}
%
% \begin{sfragment}{Proofs}
%
% We first define some keys for the \env{sproof} environment.
%    \begin{macrocode}
%<@@=stex_proof>
\stex_keys_define:nnnn{ spf }{
	\tl_clear:N \l_stex_key_for_clist
	\tl_clear:N \l_stex_key_from_tl
	\tl_set_eq:NN \l_stex_key_proofend_tl \_@@_proof_box_tl
	\tl_clear:N \l_stex_key_continues_tl
	\tl_clear:N \l_stex_key_term_tl
	\tl_clear:N \l_stex_key_functions_tl
	\tl_clear:N \l_stex_key_method_tl
  \bool_set_false:N \l_stex_key_hide_bool
}{
  for         .clist_set:N  = \l_stex_key_for_clist ,
  from        .tl_set:N     = \l_stex_key_from_tl ,
  proofend    .tl_set:N     = \l_stex_key_proofend_tl,
  continues   .tl_set:N     = \l_stex_key_continues_tl,
  functions   .tl_set:N     = \l_stex_key_functions_tl,
  term        .tl_set:N     = \l_stex_key_term_tl,
  method      .tl_set:N     = \l_stex_key_method_tl,
  hide        .bool_set:N   = \l_stex_key_hide_bool
}{id,style,title}

\bool_set_true:N \l_@@_inc_counter_bool
%    \end{macrocode}
%
% For proofs, we will have to have deeply nested structures of enumerated list-like
% environments. However, {\LaTeX} only allows |enumerate| environments up to nesting depth
% 4 and general list environments up to listing depth 6. This is not enough for us.
% Therefore we have decided to go along the route proposed by Leslie Lamport to use a
% single top-level list with dotted sequences of numbers to identify the position in the
% proof tree. Unfortunately, we could not use his |pf.sty| package directly, since it does
% not do automatic numbering, and we have to add keyword arguments all over the place, to
% accomodate semantic information.
%
%    \begin{macrocode}
\intarray_new:Nn\l_@@_counter_intarray{50}
\cs_new_protected:Npn \_@@_insert_number: {
  \int_set:Nn \l_tmpa_int {1}
  \bool_while_do:nn {
    \int_compare_p:nNn {
      \intarray_item:Nn \l_@@_counter_intarray \l_tmpa_int
    } > 0
  }{
    \intarray_item:Nn \l_@@_counter_intarray \l_tmpa_int .
    \int_incr:N \l_tmpa_int
  }
}
\cs_new_protected:Nn \_@@_number_as_string:N {
  \str_clear:N #1
  \int_set:Nn \l_tmpa_int {1}
  \bool_while_do:nn {
    \int_compare_p:nNn {
      \intarray_item:Nn \l_@@_counter_intarray \l_tmpa_int
    } > 0
  }{
    \str_put_right:Nx #1 {\intarray_item:Nn \l_@@_counter_intarray \l_tmpa_int .}
    \int_incr:N \l_tmpa_int
  }
}

\cs_new_protected:Npn \_@@_inc_counter: {
  \int_set:Nn \l_tmpa_int {1}
  \bool_while_do:nn {
    \int_compare_p:nNn {
      \intarray_item:Nn \l_@@_counter_intarray \l_tmpa_int
    } > 0
  }{
    \int_incr:N \l_tmpa_int
  }
  \int_compare:nNnF \l_tmpa_int = 1 {
    \int_decr:N \l_tmpa_int
  }
  \intarray_gset:Nnn \l_@@_counter_intarray \l_tmpa_int {
    \intarray_item:Nn \l_@@_counter_intarray \l_tmpa_int + 1
  }
}

\cs_new_protected:Npn \_@@_add_counter: {
  \int_set:Nn \l_tmpa_int {1}
  \bool_while_do:nn {
    \int_compare_p:nNn {
      \intarray_item:Nn \l_@@_counter_intarray \l_tmpa_int
    } > 0
  }{
    \int_incr:N \l_tmpa_int
  }
  \intarray_gset:Nnn \l_@@_counter_intarray \l_tmpa_int { 1 }
}

\cs_new_protected:Npn \_@@_remove_counter: {
  \int_set:Nn \l_tmpa_int {1}
  \bool_while_do:nn {
    \int_compare_p:nNn {
      \intarray_item:Nn \l_@@_counter_intarray \l_tmpa_int
    } > 0
  }{
    \int_incr:N \l_tmpa_int
  }
  \int_decr:N \l_tmpa_int
  \intarray_gset:Nnn \l_@@_counter_intarray \l_tmpa_int { 0 }
}
%    \end{macrocode}
%
% \begin{macro}{spfsketch}
%    \begin{macrocode}
\newenvironment{spfsketchenv}{}{}
\stex_new_stylable_cmd:nnnn{spfsketch}{O{} m}{\par
  \begin{spfsketchenv}
  \stex_keys_set:nn{spf}{#1}
  \_stex_do_for_list:
  \_stex_do_id:
  \exp_args:Ne \stex_annotate:nn{
    shtml:proofsketch={
      \seq_if_empty:NF \l_stex_fors_seq {
        \seq_use:Nn \l_stex_fors_seq ,
      }
    }
  }{
    \stex_style_apply:
    #2
  }
  \end{spfsketchenv}
}{
  \noindent\emph{\spfsketchenvautorefname :}~
}
%    \end{macrocode}
% \end{macro}
%
%\begin{macro}{\sproofend}
%    This macro places a little box at the end of the line if there is space, or at the
%    end of the next line if there isn't
%    \begin{macrocode}
\tl_set:Nn \_@@_proof_box_tl {
  \ltx@ifpackageloaded{amssymb}{$\square$}{
    \hbox{\vrule\vbox{\hrule width 6 pt\vskip 6pt\hrule}\vrule}
  }
}

\tl_set:Nn \sproofend {
  \tl_if_empty:NF \l_stex_key_proofend_tl {
    \hfil\null\nobreak\hfill\l_stex_key_proofend_tl\par\smallskip
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\stexcommentfont}
%    \begin{macrocode}
\cs_new_protected:Npn \stexcommentfont {
  \small\itshape
}
%    \end{macrocode}
% \end{macro}
%
% \begin{environment}{sproof}
%    \begin{macrocode}
\cs_new_protected:Nn \_@@_start_list:n {
  \begin{list}{}{
    \setlength\topsep{0pt}
    \setlength\parsep{0pt}
    \setlength\rightmargin{0pt}
  }\item[#1]
}
\cs_new_protected:Nn \_@@_end_list: {
  \end{list}
}

\cs_new_protected:Nn \_@@_html: {
  \stex_annotate_invisible:n{\hbox{
    \tl_if_empty:NF \l_stex_key_term_tl {
      $\stex_annotate:nn{shtml:proofterm={}}{\l_stex_key_term_tl}$
    }
    \tl_if_empty:NF \l_stex_key_method_tl {
      \stex_annotate:nn{shtml:proofmethod={}}{\l_stex_key_method_tl}
    }
  }}
}

\cs_new_protected:Nn \_@@_html_env:n {
  \exp_args:Nne \begin{stex_annotate_env}{
    shtml:#1={
      \seq_if_empty:NF \l_stex_fors_seq {
        \seq_use:Nn \l_stex_fors_seq ,
      }
    }
    \bool_if:NT \l_stex_key_hide_bool {,
      shtml:proofhide=true
    }
  }
  \_@@_html:
}

\bool_set_false:N \l_@@_in_spfblock_bool
\cs_new_protected:Nn \_@@_begin_proof:nn {\par
  \intarray_gzero:N \l_@@_counter_intarray
  \intarray_gset:Nnn \l_@@_counter_intarray 1 1
  \stex_keys_set:nn{spfsteps}{#1}
  \_stex_do_for_list:
  \stex_if_do_html:T {
    \_@@_html_env:n{proof}
  }
  \seq_map_inline:Nn \l_stex_fors_seq {
    \stex_debug:nn{definiens}{Adding~definiens~to~##1}
    \_stex_add_definiens:nn {##1}{\STEXinvisible{proven}}
  }
  \stex_style_apply:
  \_stex_do_id:
  \stex_reactivate_macro:N \subproof
  \stex_reactivate_macro:N \spfstep
  \stex_reactivate_macro:N \conclude
  \stex_reactivate_macro:N \assumption
  \stex_reactivate_macro:N \eqstep
  \stex_reactivate_macro:N \yield
  \stex_reactivate_macro:N \spfblock
  \stex_reactivate_macro:N \spfjust
  \stex_annotate:nn{shtml:prooftitle={}}{#2}
  \stex_if_do_html:T{
    \begin{stex_annotate_env}{shtml:proofbody={}}
  }
}
\stex_new_stylable_env:nnnnnnn{proof}{O{} m}{
  \_@@_begin_proof:nn{#1}{#2}
  \bool_set_true:N\l_@@_in_spfblock_bool\_@@_start_list:n{}
  \group_begin:\stexcommentfont
}{
  \stex_style_apply:
  \stex_if_do_html:T{\end{stex_annotate_env}\end{stex_annotate_env}}
}{
  \emph{\sproofautorefname :}~
}{
  \sproofend
}{s}
\AddToHook{env/sproof/end}{
  \bool_if:NT\l_@@_in_spfblock_bool {
    \group_end:\_@@_end_list:
  }
}

\stex_new_stylable_env:nnnnnnn{proof*}{O{}}{
  \_@@_begin_proof:nn{#1}{}
  \bool_set_false:N\l_@@_in_spfblock_bool
}{
  \stex_style_apply:
  \stex_if_do_html:T{\end{stex_annotate_env}\end{stex_annotate_env}}
}{
  \emph{Proof:}~
}{
  \sproofend
}{s}
%    \end{macrocode}
% \end{environment}
%
% \begin{environment}{subproof}
%    \begin{macrocode}
\str_set_eq:NN \subproofautorefname \spfstepautorefname
\stex_new_stylable_env:nnnnnnn{subproof}{s O{} m}{\par
  \stex_keys_set:nn{spf}{#2}
  \_stex_do_for_list:
  \stex_if_do_html:T {
    \_@@_html_env:n{subproof}
  }
  \seq_map_inline:Nn \l_stex_fors_seq {
    \stex_debug:nn{definiens}{Adding~definiens~to~##1}
    \_stex_add_definiens:nn {##1}{\STEXinvisible{proven}}
  }

  \IfBooleanTF #1 {
    \stex_style_apply:
    \str_if_empty:NF \l_stex_key_id_str {
      \_@@_number_as_string:N \@currentlabel
      \str_set:Nx \@currentHref{subproof.\@currentlabel}
      \_stex_do_id:
    }
    \bool_set_false:N \l_@@_in_spfblock_bool
    \stex_annotate:nn{shtml:prooftitle={}}{#3}
  }{
    \bool_if:NTF \l_@@_in_spfblock_bool {
      \str_if_empty:NF \l_stex_key_id_str {
        \_@@_number_as_string:N \@currentlabel
        \str_set:Nx \@currentHref{subproof.\@currentlabel}
        \_stex_do_id:
      }
      \_@@_start_list:n\_@@_insert_number:
        \stex_annotate:nn{shtml:prooftitle={}}{#3}
        \_@@_add_counter:
        \stex_style_apply:
    }{
      \stex_annotate:nn{shtml:prooftitle={}}{#3}
      \stex_style_apply:
      \_stex_do_id:
    }
  }
  \stex_if_do_html:T{
    \begin{stex_annotate_env}{shtml:proofbody={}}
  }
  \bool_if:NT \l_@@_in_spfblock_bool {\group_begin:\stexcommentfont}
}{
  \stex_style_apply:
  \bool_if:NT \l_@@_in_spfblock_bool \_@@_inc_counter:
  \stex_if_do_html:T{\end{stex_annotate_env}}
  \bool_if:NT\l_@@_in_spfblock_bool \_@@_end_list:
  \stex_if_do_html:T{\end{stex_annotate_env}}
  \aftergroup \_@@_inblock_restore: 
}{}{}{}
\AddToHook{env/subproof/before}{
  \bool_if:NT \l_@@_in_spfblock_bool \group_end:
}
\AddToHook{env/subproof/end}{
  \bool_if:NT\l_@@_in_spfblock_bool {
    \group_end:\_@@_remove_counter:
    %\_@@_end_list:
  }
}
\stex_deactivate_macro:Nn \subproof {sproof~environments}

\cs_new_protected:Nn \_@@_inblock_restore: {
  \bool_if:NT\l_@@_in_spfblock_bool {
    \group_begin:\stexcommentfont
  }
}
%    \end{macrocode}
% \end{environment}
%
% \begin{macro}{\spfstep,\conclude,\assumption,\have,\eqstep}
%    \begin{macrocode}

\stex_keys_define:nnnn { spfsteps } {
	\clist_clear:N \l_stex_key_for_clist
  \str_clear:N \l_stex_key_name_str
	\tl_clear:N \l_stex_key_method_tl
	\tl_clear:N \l_stex_key_term_tl
}{
  for         .clist_set:N  = \l_stex_key_for_clist ,
  method      .tl_set:N     = \l_stex_key_method_tl,
  term        .tl_set:N     = \l_stex_key_term_tl,
  name        .str_set_x:N  = \l_stex_key_name_str
  % todo: style=inline
}{id,style,title}

\newenvironment{spfstepenv}{
  \str_set_eq:NN \spfstepenvautorefname \spfstepautorefname
}{}

\cs_new_protected:Nn \_@@_step_html:nn {
  \stex_if_do_html:TF{
    \exp_args:Ne \stex_annotate:nn{
      shtml:spf#1={
        \seq_if_empty:NF \l_stex_fors_seq {
          \seq_use:Nn \l_stex_fors_seq ,
        }
      }
      \str_if_empty:NF \l_stex_key_name_str {,
        shtml:stepname={\l_stex_key_name_str}
      }
    }{
      \_@@_html:
      #2
    }
  }{ #2 }
}

\cs_new_protected:Nn \_@@_make_step_macro:Nnnnn {
  \NewDocumentCommand #1 {s O{} +m} {
    \bool_if:NT \l_@@_in_spfblock_bool \group_end:
    \stex_keys_set:nn{spfsteps}{##2}
    \str_if_empty:NF \l_stex_key_name_str {
      \stex_debug:nn{Here:}{Variable~\l_stex_key_name_str}
      \exp_args:Nne\use:nn{\vardef}{{v\l_stex_key_name_str}[name=\l_stex_key_name_str]{\l_stex_key_name_str}}
    }

    \begin{spfstepenv}
      \str_if_empty:NF \l_stex_key_id_str {
        \_@@_number_as_string:N \@currentlabel
        \str_set:Nx \@currentHref{spfstep.\@currentlabel}
        \_stex_do_id:
      }

    \bool_if:NTF \l_@@_in_spfblock_bool { 
      \IfBooleanTF ##1 {
        \_@@_step_html:nn{#2}{##3}
      }{
        \_@@_step_html:nn{#2}{\_@@_start_list:n{#3} ##3 \_@@_end_list:}
        #5
      }
      \end{spfstepenv}
      \group_begin:\stexcommentfont
    }{
      \_@@_step_html:nn{#2}{##3}
      \end{spfstepenv}
    }
  }
  \stex_deactivate_macro:Nn #1 {sproof~environments}
}

\_@@_make_step_macro:Nnnnn \assumption {assumption} \_@@_insert_number: {} \_@@_inc_counter:
\_@@_make_step_macro:Nnnnn \conclude {conclusion} {$\Rightarrow$} {} {}
\_@@_make_step_macro:Nnnnn \spfstep {step} \_@@_insert_number: {} \_@@_inc_counter:

\NewDocumentCommand \eqstep {s m}{
  \bool_if:NTF \l_@@_in_spfblock_bool {
    \group_end:
    \IfBooleanTF #1 {
      \_@@_step_html:nn{eqstep}{$= #2$}
    }{
      \_@@_step_html:nn{eqstep}{\_@@_start_list:n{$=$} $#2$ \_@@_end_list:}
    }
    \group_begin:\stexcommentfont
  }{
    \_@@_step_html:nn{eqstep}{$= #2$}
  }
}
\stex_deactivate_macro:Nn \eqstep {sproof~environments}

\NewDocumentCommand \yield {+m}{
  \stex_annotate:nn{shtml:proofterm={}}{ #1 }
}
\stex_deactivate_macro:Nn \yield {sproof~environments}

\NewDocumentEnvironment{spfblock}{}{
  \bool_set_false:N \l_@@_in_spfblock_bool
}{
  \aftergroup\_@@_inblock_restore:
}
\stex_deactivate_macro:Nn \spfblock {sproof~environments}
\AddToHook{env/spfblock/before}{
  \bool_if:NT \l_@@_in_spfblock_bool \group_end:
}


\newcommand\spfjust[1]{
  \stex_annotate:nn{spfjust={}}{ #1 }
}
\stex_deactivate_macro:Nn \spfjust {sproof~environments}
%    \end{macrocode}
% \end{macro}
%
% \end{sfragment}
%
% \begin{sfragment}{Metatheory}
%    \begin{macrocode}
%<@@=stex_meta>
\group_begin:
  \cs_set:Npn \__stex_modules_persist_module: {}
  \cs_set:Npn \stex_check_term:n #1 {}
  \cs_set:Npn \_stex_sref_do_aux:n #1 { #1 }
  \bool_set_false:N \_stex_html_do_output_bool
  \bool_set_false:N \c_stex_check_terms_bool
  \stex_uri_resolve:Nn \l_stex_current_ns_uri {http://mathhub.info/sTeX/meta}
  \stex_module_setup:n{Metatheory}

  \symdef{of~type}[args=ii,invisible]{#1}
  \notation{of~type}[colon]{#1 \mathbin{\comp{:}} #2}

  \symdef{apply}[args=ia,prec=0;\infprec x\infprec]{#1\mathopen{\comp(} #2 \mathclose{\comp)}}
  \notation{apply}[lambda]{#1\; \argsep{#2}{\;}}
  \notation{apply}[infixop]{\argsep{#2}{\mathbin{#1}}}
  \notation{apply}[infixrel]{\argsep{#2}{\mathrel{#1}}}
  
  % structures
  \symdef{module~type}[args=i,op=\mathtt{MOD}]
  {\mathopen{\comp{\mathtt{MOD}(}}#1\mathclose{\comp{)}}}
  \symdef{module~type~merge}[args=a,op=\oplus]
    {\argsep{#1}{\mathbin{\comp{\oplus}}}}
  \symdef{anonymous~record}[args=a]
    {\mathopen{\comp{[[}}#1\mathclose{\comp{]]}}}
  \symdef{record~field}[args=2]{#1\comp{.}#2}
  \symdecl*{record~type}

  \symdecl{mathstruct}[name=mathematical~structure,args=a] % TODO
  \notation{mathstruct}[angle,prec=nobrackets]
    {\mathopen{\comp\langle} #1 \mathclose{\comp\rangle}}
  \notation{mathstruct}[parens,prec=nobrackets]
    {\mathopen{\comp(} #1 \mathclose{\comp)}}

  % sequences
  \symdef{ellipses}[ldots]{\ldots}
  \symdef{sequence~expression}[comma,args=a]{#1}
  \symdef{sequence~type}[args=1]{#1^{\comp\ast}}
  \symdef{sequence~map}[args=ia]{
    \comp{\mathrm{map}}\mathopen{\comp{(}}#1\mathpunct{\comp{,}}
    #2\mathclose{\comp{)}}
  }
\iffalse
  % binder (\forall, \Pi, \lambda etc.)
  \symdef{pibind}[name=dependent function type,prec=nobrackets,
    op=(\cdot)\;\to\;\cdot,args=Bi,assoc=pre]
    {\argmap{#1}{
      \mathopen{\comp(} ##1 \mathclose{\comp{)}}
      }{\mathbin{\comp{\to}}} \mathbin{\comp{\to}} #2}
  \notation{pibind}[forall]{\comp\forall #1\mathpunct{\comp.} #2}
  \notation{pibind}[Pi]{\mathop{\comp\prod}\c_math_subscript_token{#1}#2}

  \symdef{mapbind}[name=lambda,mapsto,prec=nobrackets,op=\mapsto,args=Bi,assoc=pre]
    { #1 \mathrel{\comp\mapsto} #2}
  \notation{mapbind}[lambda,prec=nobrackets,op=\lambda]
    {\comp\lambda #1 \mathpunct{\comp.} #2}
\fi
  \symdecl{bind}[args=Bi,assoc=pre]
  \notation{bind}[depfun,prec=nobrackets,op=(\cdot)\;\to\;\cdot]
    {\mathopen{\comp(} #1 \mathclose{\comp{)}\mathbin{\comp{\to}}} #2}
  \notation{bind}[forall]{\comp\forall #1.\;#2}
  \notation{bind}[Pi]{\mathop{\comp\prod}\c_math_subscript_token{#1}#2}

  \symdef{implicit~bind}[args=Bi,assoc=pre]{\mathopen{\comp\{} #1 \mathclose{\comp{\}\c_math_subscript_token I}} #2}

  \symdecl*{integer~literal}
  \notation{integer~literal}{\mathbb Z}

  \symdecl*{ordinal}
  \notation{ordinal}{\mathtt{Ord}}

  % propositions
  \symdef{prop}[name=proposition]{\mathtt{Prop}}
  \symdef{judgment~holds}[args=i,role=judgment]{\comp\vdash\;#1}

  % any object
  \symdef{object}{\mathtt{Obj}}

  % TODO DELETE
  \symdef{aseqdots}[args=a,prec=nobrackets]
    {#1\comp{,\ldots}}%{##1\comp,##2}
  \symdef{aseqfromto}[args=ai,prec=nobrackets]
    {#1\comp{,\ldots,}#2}%{##1\comp,##2}
  \symdef{aseqfromtovia}[args=aii,prec=nobrackets]
    {#1\comp{,\ldots,}#2\comp{,\ldots,}#3}%{##1\comp,##2}


  \stex_close_module:
  \stex_uri_add_module:NNn \l_stex_metatheory_uri \l_stex_current_ns_uri {Metatheory}
  \global \let \l_stex_metatheory_uri \l_stex_metatheory_uri
  \global \let \c_stex_default_metatheory \l_stex_metatheory_uri
\group_end:
%    \end{macrocode}
%
% \end{sfragment}
%
%
% \begin{sfragment}{MMT Interfaces}
%    \begin{macrocode}
%<@@=todo>
\cs_new_protected:Npn \MSC #1 {}
%    \end{macrocode}
% \end{sfragment}
%
% \begin{macro}{\MMTinclude}
%    \begin{macrocode}
\stex_new_stylable_cmd:nnnn{MMTinclude}{m}{
  \stex_annotate_invisible:nn{shtml:import={#1}}{}
}{}
\stex_deactivate_macro:Nn \MMTinclude {module~environments}
\stex_every_module:n {\stex_reactivate_macro:N \MMTinclude}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\MMTrule}
%    \begin{macrocode}
\NewDocumentCommand \MMTrule {m m}{
  \tl_if_empty:nTF{#2}{\seq_clear:N \l_tmpa_seq}{
    \seq_set_split:Nnn \l_tmpa_seq , {#2}
  }
  \int_zero:N \l_tmpa_int
  \stex_annotate_invisible:n{
    $
    \stex_annotate:nn{shtml:rule={scala://#1}}{
      \_stex_annotate_force_break:n{
        \seq_if_empty:NF \l_tmpa_seq {
          \seq_map_inline:Nn \l_tmpa_seq {
            \int_incr:N \l_tmpa_int
            \stex_annotate:nn{
              shtml:argmode=i,
              shtml:arg={\int_use:N \l_tmpa_int}
            }{ ##1 }
          }
        }
      }
    }$
  }
}
\stex_deactivate_macro:Nn \MMTrule {module~environments}
\stex_every_module:n{\stex_reactivate_macro:N \MMTrule}
%    \end{macrocode}
% \end{macro}
%
% \begin{environment}{mmtinterface}
%    \begin{macrocode}
\NewDocumentEnvironment { mmtinterface } {  O{} m m } {
  \_stex_module_setup_top_nosig:n { #3 }
  \str_set_eq:NN \l_@@_mmt_module_str \l_stex_current_module_str
  \str_clear:N \l_stex_current_module_str
  \stex_keys_set:nn { smodule }{ #1 }
  \stex_module_setup:n{ #2 }
  \str_set_eq:NN \l_@@_stex_module_str \l_stex_current_module_str
  \stex_debug:nn{mmt}{Interface~\l_@@_stex_module_str^^Jfor~\l_@@_mmt_module_str}

  \stex_if_do_html:T {
    \exp_args:Nne \begin{stex_annotate_env} {
      shtml:theory={\l_stex_current_module_str},
      shtml:language={ \l_stex_current_language_str},
      shtml:signature={}
      \tl_if_empty:NF \l_stex_metatheory_uri {,
        shtml:metatheory={\stex_uri_use:N \l_stex_metatheory_uri}
      }
    }
    \stex_annotate_invisible:n{}
    \stex_annotate_invisible:nn 
      {shtml:import=\l_@@_mmt_module_str} {}
  }
  \stex_module_add_code:x{
    \stex_activate_module:n{ \l_@@_mmt_module_str }
  }
  \stex_module_add_morphism:nonn
    {}{\l_@@_mmt_module_str}{import}{}
  \stex_reactivate_macro:N \mmtdef
  \stex_smsmode_do:
}{
    \str_set_eq:NN \l_stex_current_module_str \l_@@_mmt_module_str
    \stex_close_module:
    \str_set_eq:NN \l_stex_current_module_str \l_@@_stex_module_str
    \stex_close_module:
    \stex_if_do_html:T { \end{stex_annotate_env} }
}
\stex_sms_allow_env:n{mmtinterface}
%    \end{macrocode}
% \end{environment}
%
% \begin{macro}{\mmtdef}
%    \begin{macrocode}
\NewDocumentCommand \mmtdef {m O{} m} {
  \stex_keys_set:nn{symdef}{#2}
  \str_set:Nx \l_stex_macroname_str { #1 }
  \str_if_empty:NT \l_stex_key_name_str {
    \str_set:Nx \l_stex_key_name_str { #1 }
  }
  \stex_symdecl_do:

  \str_set_eq:NN \l_stex_current_module_str \l_@@_mmt_module_str
  \cs_set_eq:NN \l_@@_old_metagroup_cd \stex_metagroup_do_in:nn
  \cs_set_protected:Npn \stex_metagroup_do_in:nn ##1 ##2 {##2}
  \exp_args:Nnx \use:nn {\stex_module_add_symbol:nnnnnnnN}{
    {\l_stex_macroname_str}
    {\l_stex_key_name_str}
    {\int_use:N \l_stex_get_symbol_arity_int}
    {\l_stex_get_symbol_args_tl}
    {}
    {}
    {}
    \stex_invoke_symbol:
  }
  \cs_set_eq:NN \stex_metagroup_do_in:nn \l_@@_old_metagroup_cd
  \str_set_eq:NN \l_stex_current_module_str \l_@@_stex_module_str

  \str_set_eq:NN \l_stex_get_symbol_mod_str \l_@@_mmt_module_str
  \str_set_eq:NN \l_stex_get_symbol_name_str \l_stex_key_name_str
  \stex_notation_parse:n{#3}
  \_stex_notation_check:
  \_stex_notation_add:
  \stex_if_do_html:T{
    \_stex_notation_do_html:n{\l_stex_get_symbol_mod_str ? \l_stex_get_symbol_name_str}
  }
  \stex_smsmode_do:
}
\stex_deactivate_macro:Nn \mmtdef {mmtinterface~environments}
\stex_sms_allow_escape:N \mmtdef
%    \end{macrocode}
% \end{macro}
%
% VoLL-KI Annotations
%    \begin{macrocode}
\newcommand\precondition[2]{
    \str_clear:N \l_stex_get_symbol_name_str
    \stex_get_symbol:n{#2}
    \str_if_empty:NTF \l_stex_get_symbol_name_str{
        \errmessage{Unknown~symbol~#2}
    }{
		  \str_case:nnTF {#1}{
		      {remember}{}
		      {understand}{}
		      {analyze}{}
		      {evaluate}{}
		      {apply}{}
		      {create}{}
		  }{
		  	\stex_annotate_invisible:nn{
		  		shtml:preconditionsymbol={\l_stex_get_symbol_mod_str ? \l_stex_get_symbol_name_str},
		  		shtml:preconditiondimension={#1}
		  	}{}
		  }{\errmessage{Unknown~cognitive~dimension~#1}}
    }
}
\newcommand\objective[2]{
    \str_clear:N \l_stex_get_symbol_name_str
    \stex_get_symbol:n{#2}
    \str_if_empty:NTF \l_stex_get_symbol_name_str{
        \errmessage{Unknown~symbol~#2}
    }{
		  \str_case:nnTF {#1}{
				{remember}{}
				{understand}{}
				{analyze}{}
				{evaluate}{}
				{apply}{}
				{create}{}
		  }{
		  	\stex_annotate_invisible:nn{
		  		shtml:objectivesymbol={\l_stex_get_symbol_mod_str ? \l_stex_get_symbol_name_str},
		  		shtml:objectivedimension={#1}
		  	}{}
		  }{\errmessage{Unknown~cognitive~dimension~#1}}
    }
}
%    \end{macrocode}
%
%    \begin{macrocode}
\seq_if_empty:NT \g_stex_current_file {
  \seq_gset_eq:NN \g_stex_current_file \c_stex_main_file
}
\_stex_persist_read_now:
\_stex_every_file:
\cs_new_protected:Nn \_@@_newlabel:n {
  \exp_args:Ne\_@@_old_newlabel:{\tl_to_str:n{#1}}
}
\AtBeginDocument{
  \iow_now:Nn \@auxout {
    \ExplSyntaxOn
    \let\_@@_old_newlabel:\newlabel
    \let\newlabel\_@@_newlabel:n
    \ExplSyntaxOff
  }
}
%</package>
%    \end{macrocode}
% \end{sfragment}
% \end{implementation}
\endinput