%%
%% This is file `stex.sty',
%% generated with the docstrip utility.
%%
%% The original source files were:
%%
%% stex.dtx  (with options: `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}
\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 }
\input{stex-en.ldf}
\cs_set_eq:NN \stex_undefined: \undefined
\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
}
\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}
  }
}
\cs_new_protected:Nn \stex_debug:nn {
  \exp_args:NNo \clist_if_in:NnTF \c_stex_debug_clist { \tl_to_str:n{all} }{
    \__stex_debug_:nn{#1}{#2}
  }{
    \exp_args:NNo \clist_if_in:NnT \c_stex_debug_clist { \tl_to_str:n{#1} }{
      \__stex_debug_:nn{#1}{#2}
    }
  }
}

\cs_new_protected:Nn \__stex_debug_:nn {
  \msg_set:nnn{stex}{debug / #1}{
    \\Debug~#1:~#2\\
  }
  \msg_none:nn{stex}{debug / #1}
}

\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}
\stex_get_env:Nn\__stex_debug_env_str{STEX_DEBUG}
\str_if_empty:NTF\__stex_debug_env_str {
  \clist_set_eq:NN \l__stex_debug_cl \c_stex_debug_clist
}{
  \clist_set:No \l__stex_debug_cl {\__stex_debug_env_str}
}
\clist_clear:N \c_stex_debug_clist
\clist_map_inline:Nn \l__stex_debug_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}
  }
}
\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
}}
\str_new:N \l_stex_current_language_str
\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__stex_lang_lang_str {}{\prop_item:Nn \c_stex_languages_prop {#1}}
    \cs_if_eq:NNTF\@onlypreamble\@notprerr{
      \ltx@ifpackageloaded{babel}{
        \exp_args:No\selectlanguage\l__stex_lang_lang_str
      }{}
    }{
      \ltx@ifpackageloaded{babel}{}{
        \str_if_eq:nnTF {#1} {tr} {
          \RequirePackage[turkish,shorthands=:!]{babel}
        }{
          \RequirePackage[\l__stex_lang_lang_str]{babel}
        }
      }
    }
  }{
    \msg_error:nnx{stex}{error/unknownlanguage}{#1}
  }
}
\cs_generate_variant:Nn \stex_set_language:n {x,o}
\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__stex_lang_str
    \str_if_eq:NNF \l__stex_lang_str \l_stex_current_language_str {
      \exp_args:NNo \prop_if_in:NnT \c_stex_languages_prop \l__stex_lang_str {
        \stex_set_language:o \l__stex_lang_str
      }
    }
    \stex_debug:nn{lang} {Language~\l_stex_current_language_str~
      inferred~from~file~name}
  }
}
\clist_if_empty:NF \c_stex_languages_clist {
  \bool_set_false:N \l__stex_lang_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__stex_lang_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__stex_lang_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}
  }
}
\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
  }
}
\cs_new_protected:Nn \stex_pseudogroup_with:nn {
  \tl_map_inline:nn{#1}{
    \cs_set_eq:cN{__stex_groups_\tl_to_str:n{##1}}##1
  }
  #2
  \tl_map_inline:nn{#1}{
    \cs_set_eq:Nc##1{__stex_groups_\tl_to_str:n{##1}}
    \cs_undefine:c{__stex_groups_\tl_to_str:n{##1}}
  }
}
\seq_new:N \l__stex_groups_ids_seq
\cs_new_protected:Nn \stex_metagroup_new:n {
    \str_set:cx{l__stex_groups_#1_int} {\int_use:N\currentgrouplevel}
    \seq_put_right:Nn \l__stex_groups_ids_seq {#1}
}
\cs_generate_variant:Nn \stex_metagroup_new:n {o}
\prg_new_conditional:Nnn \__stex_groups_exists:n {TF} {
    \str_if_exist:cTF{l__stex_groups_#1_int}
        \prg_return_true: \prg_return_false:
}

\cs_new_protected:Nn \stex_metagroup_do_in:nn {
    \__stex_groups_exists:nTF{#1}{
        \__stex_groups_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 \__stex_groups_do_in:nn {
  \exp_args:Nnx\stex_debug:nn{metagroup}{adding~to~\detokenize{#1}:^^J\tl_to_str:n{#2}}
  \tl_set:Nn\__stex_groups_tmp{#2}
  \exp_args:Nx \int_compare:nNnF {\use:c{l__stex_groups_#1_int}}
      = \currentgrouplevel {
      \tl_if_exist:cTF{g__stex_groups_#1_\the\currentgrouplevel _content}{
        \exp_args:Nno \tl_gput_right:cn{g__stex_groups_#1_\the\currentgrouplevel _content}
      }{
        \exp_args:Nno \tl_gset:cn{g__stex_groups_#1_\the\currentgrouplevel _content}
      }\__stex_groups_tmp
      \bool_if_exist:cF {l__stex_groups_\the\currentgrouplevel _bool} {
          \group_insert_after:N \__stex_groups_do:
          \bool_set_true:c {l__stex_groups_\the\currentgrouplevel _bool}
      }
  }
  \__stex_groups_tmp
}

\cs_new_protected:Nn \__stex_groups_do: {
  \seq_map_inline:Nn \l__stex_groups_ids_seq {
    \tl_if_exist:cT{g__stex_groups_##1_\int_eval:n{\currentgrouplevel+1}_content}{
      \exp_args:NNno \exp_args:Nno \__stex_groups_do_in:nn{##1}{
        \csname g__stex_groups_##1_\int_eval:n{\currentgrouplevel+1}_content\endcsname
      }
      \cs_undefine:c{g__stex_groups_##1_\int_eval:n{\currentgrouplevel+1}_content}
    }
    \bool_if_exist:cF {l__stex_groups_\int_eval:n\currentgrouplevel _bool} {
      \group_insert_after:N \__stex_groups_do:
      \bool_set_true:c {l__stex_groups_\int_eval:n\currentgrouplevel _bool}
    }
  }
}
\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:
}
\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
    }
  }
}
\ifcsname if@rustex\endcsname\else
  \expandafter\newif\csname if@rustex\endcsname
  \@rustexfalse
\fi

\stex_get_env:Nn\__stex_annotate_env_str{STEX_FORCE_PDF}
\exp_args:No \str_if_eq:nnTF \__stex_annotate_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
}
\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 }
}
\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 }
}

\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
}
\protected\def\stex_ignore_spaces_and_pars:{
  \begingroup\catcode13=10\relax
  \@ifnextchar\par{
    \endgroup\expandafter\stex_ignore_spaces_and_pars:\@gobble
  }{
    \endgroup
  }
}
\cs_new_nopar:Nn \stex_keys_define:nnnn {
  \tl_gset:cn {__stex_aux_keys_#1_pre_tl}{#2}
  \tl_gset:cn {__stex_aux_keys_#1_def_tl}{#3}
  \tl_if_empty:nF{#4}{
    \clist_map_inline:nn{#4}{
      \tl_set_eq:Nc \l__stex_aux_tl {__stex_aux_keys_##1_pre_tl}
      \tl_gput_left:co{__stex_aux_keys_#1_pre_tl} \l__stex_aux_tl
      \tl_set_eq:Nc \l__stex_aux_tl {__stex_aux_keys_##1_def_tl}
      \tl_gput_left:cn{__stex_aux_keys_#1_def_tl} ,
      \tl_gput_left:co{__stex_aux_keys_#1_def_tl} \l__stex_aux_tl
    }
  }
  \tl_set_eq:Nc \l__stex_aux_tl {__stex_aux_keys_#1_def_tl}
  \exp_args:Nno \keys_define:nn {stex / #1} {\l__stex_aux_tl}
}
\cs_new_nopar:Nn \stex_keys_set:nn {
  \use:c{__stex_aux_keys_#1_pre_tl}
  \keys_set:nn {stex / #1} { #2 }
}
\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}[{
        \__stex_aux_split_at_bracket:w ##1 \_stex_end:
      }{
        \usemodule{##1}
      }
    }
  }
}{}

\cs_new_protected:Npn \__stex_aux_split_at_bracket:w [ #1 ] #2 \_stex_end: {
  \usemodule[#1]{#2}
}
\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}
  }
}
\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
    }
  }
}
\cs_new_protected:Nn \stex_new_stylable_cmd:nnnn {
  \exp_after:wN \newcommand \cs:w stexstyle#1 \cs_end:[2][]{
    \__stex_aux_patch:nnn{#1}{##1}{##2}
  }
  \exp_after:wN \NewDocumentCommand\cs:w #1\cs_end:{#2}{
    \cs_set:Npn \stex_style_apply: {
      \__stex_aux_apply_patch:n{#1}
    }
    #3
  }
  \tl_set:cn {__stex_aux_style_#1:} { #4 }
}

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

\cs_new_protected:Nn \__stex_aux_patch:nnn {
  \str_if_empty:nTF {#2}{
    \tl_set:cn{__stex_aux_style_#1:}{#3}
  }{
    \tl_set:cn{__stex_aux_style_#1_#2:}{#3}
  }
}

\cs_new_protected:Nn \stex_new_stylable_env:nnnnnnn {
  \exp_after:wN \newcommand \cs:w stexstyle#1 \cs_end:[3][]{
    \__stex_aux_patch:nnnn{#1}{##1}{##2}{##3}
  }
  \NewDocumentEnvironment{#7#1}{#2}{
    \cs_set:Npn \stex_style_apply: {
      \__stex_aux_apply_patch_begin:n{#1}
    }
    #3
  }{
    \cs_set:Npn \stex_style_apply: {
      \__stex_aux_apply_patch_end:n{#1}
    }
    #4
  }
  \tl_set:cn {__stex_aux_style_#1_start:} { #5 }
  \tl_set:cn {__stex_aux_style_#1_end:} { #6 }
}

\cs_new_protected:Nn \__stex_aux_patch:nnnn {
  \str_if_empty:nTF {#2}{
    \tl_set:cn{__stex_aux_style_#1_start:}{#3}
    \tl_set:cn{__stex_aux_style_#1_end:}{#4}
  }{
    \tl_set:cn{__stex_aux_style_#1_#2_start:}{#3}
    \tl_set:cn{__stex_aux_style_#1_#2_end:}{#4}
  }
}

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

\cs_new_protected:Nn \__stex_aux_apply_patch_end:n {
  \tl_if_empty:NTF \thisstyle {
    \use:c{__stex_aux_style_#1_end:}
  }{
    \tl_if_exist:cTF{__stex_aux_style_#1_\thisstyle _end:}{
      \use:c{__stex_aux_style_#1_\thisstyle _end:}
    }{
      \use:c{__stex_aux_style_#1_end:}
    }
  }
}
\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:
}
\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:
}
\cs_new:Npn \__stex_aux_start:#1\__stex_aux_end: {\exp_not:n{#1}}
\cs_new_protected:Nn \__stex_aux_end: {}
\cs_new:Nn \stex_macro_body:N {
  \exp_args:Nne\use:nn{\exp_after:wN \__stex_aux_start: #1}{
    \__stex_aux_args:e {\cs_parameter_spec:N #1}\__stex_aux_end:
  }
}

\cs_new:Nn \__stex_aux_args:n {
  \tl_if_empty:nF{#1}{
      {##\exp_args:Ne \tl_head:n {\tl_tail:n {#1}}}
      \__stex_aux_args:e {\exp_args:Ne\tl_tail:n{\tl_tail:n{#1}}}
  }
}
\cs_generate_variant:Nn \__stex_aux_args:n {e}
\cs_new:Nn \stex_macro_definition:N {
  \__stex_aux_prefix:e {\cs_prefix_spec:N #1}
  \def\exp_not:N #1
  \__stex_aux_params:e {\cs_parameter_spec:N #1}
  {
    \stex_macro_body:N #1
  }
}

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

\cs_new:Nn \__stex_aux_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 \__stex_aux_prefix_long:n {e}

\cs_new:Nn \__stex_aux_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}
    }
    \__stex_aux_params:e {\tl_tail:n{#1}}
  }
}
\cs_generate_variant:Nn \__stex_aux_params:n {e}
\stex_get_env:Nn\__stex_persist_env_str{STEX_USESMS}
\str_if_empty:NF\__stex_persist_env_str{
  \exp_args:No \str_if_eq:nnF \__stex_persist_env_str{false}{
    \bool_set_true:N \c_stex_persist_mode_bool
  }
}
\stex_get_env:Nn\__stex_persist_env_str{STEX_WRITESMS}
\str_if_empty:NF\__stex_persist_env_str{
  \exp_args:No \str_if_eq:nnF \__stex_persist_env_str{false}{
    \bool_set_true:N \c_stex_persist_write_mode_bool
  }
}
\iow_new:N \c__stex_persist_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__stex_persist_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 {}
}

\cs_new_protected:Nn \__stex_persist_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 \__stex_persist_write_only: {
  \iow_open:Nn \c__stex_persist_sms_iow {\jobname.sms}
  \AtEndDocument{ \iow_close:N \c__stex_persist_sms_iow }
}

\cs_new_protected:Nn \__stex_persist_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
    \__stex_persist_write_only:
    \ior_open:Nn \g_tmpa_ior {\jobname.sms2}
    \ior_str_map_inline:Nn \g_tmpa_ior {
      \iow_now:Nn \c__stex_persist_sms_iow {##1}
    }
    \ior_close:N \g_tmpa_ior
    \__stex_persist_load_file:n{\jobname.sms2}
  }\__stex_persist_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
      \__stex_persist_read_and_write:
      {
        \__stex_persist_load_file:n{\jobname.sms}
      }
  }{
    \bool_if:NT \c_stex_persist_write_mode_bool \__stex_persist_write_only:
  }
}
\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}
\sys_if_platform_windows:TF{
  \cs_new_protected:Npn \__stex_path_win_take:w #1#2#3 \__stex_path_: {
    \str_set:Nn \l__stex_path_win_drive {#1#2}
    \str_set:Nn \l__stex_path_str{#3}
  }
  \cs_new_protected:Nn \stex_file_resolve:Nn {
    \str_set:Nn \l__stex_path_str {#2}
    \str_clear:N \l__stex_path_win_drive
    \exp_args:NNo \str_replace_all:Nnn \l__stex_path_str \c_backslash_str /
    \exp_args:Nx \str_if_eq:nnT {\str_item:Nn \l__stex_path_str 2} : {
      \exp_after:wN \__stex_path_win_take:w \l__stex_path_str \__stex_path_:
    }
    \stex_file_set:No #1 \l__stex_path_str
    \__stex_path_canonicalize:N #1
    \str_if_empty:NF \l__stex_path_win_drive {
      \seq_pop_left:NN #1 \l__stex_path_str
      \seq_put_left:No #1 \l__stex_path_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__stex_path_str {#2}
    \stex_file_set:No #1 \l__stex_path_str
    \__stex_path_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 \__stex_path_canonicalize:N {
  \seq_if_empty:NF #1 {
    \seq_pop:NN #1 \l__stex_path_str
    \seq_clear:N \l__stex_path_seq
    \str_if_empty:NTF \l__stex_path_str {
      \seq_map_function:NN #1 \__stex_path_dodots:n
      \seq_put_left:Nn \l__stex_path_seq {}
    }{
      \seq_push:No #1 \l__stex_path_str
      \seq_map_function:NN #1 \__stex_path_dodots:n
    }
    \seq_set_eq:NN #1 \l__stex_path_seq
  }
}

\cs_new_protected:Nn \__stex_path_dodots:n {
  \str_if_empty:nF{#1}{
    \str_if_eq:nnF {#1} {.} {
      \str_if_eq:nnTF {#1} {..} {
        \seq_if_empty:NF \l__stex_path_seq {
          \seq_pop_right:NN \l__stex_path_seq \l__stex_path_str
        }
      }{
        \seq_put_right:Nn \l__stex_path_seq {#1}
      }
    }
  }
}

\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__stex_path_maybewin_str {\seq_item:Nn #1 1}
      \exp_args:No \tl_if_empty:nTF \l__stex_path_maybewin_str \prg_return_true: {
        \exp_args:Nx \str_if_eq:nnTF {\str_item:Nn \l__stex_path_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:
    }
  }
}
\cs_new:Nn \stex_file_use:N {
  \seq_use:Nn #1 /
}
\prg_new_protected_conditional:Nnn \stex_if_file_starts_with:NN {T,F,TF} {
  \seq_set_eq:NN \l__stex_path_a_seq #1
  \seq_set_eq:NN \l__stex_path_b_seq #2
  \tl_clear:N \l__stex_path_return_tl
  \bool_while_do:nn{
    \bool_not_p:n{
      \bool_lazy_any_p:n{
        {\seq_if_empty_p:N \l__stex_path_a_seq}
        {\seq_if_empty_p:N \l__stex_path_b_seq}
        {\bool_not_p:n{\tl_if_empty_p:N \l__stex_path_return_tl}}
      }
    }
  }{
    \seq_pop_left:NN \l__stex_path_a_seq \l__stex_path_a_tl
    \seq_pop_left:NN \l__stex_path_b_seq \l__stex_path_b_tl
    \str_if_eq:NNF \l__stex_path_a_tl \l__stex_path_b_tl {
      \tl_set:Nn \l__stex_path_return_tl {\prg_return_false:}
    }
  }
  \tl_if_empty:NTF \l__stex_path_return_tl {
    \seq_if_empty:NTF \l__stex_path_b_seq \prg_return_true: \prg_return_false:
  } \l__stex_path_return_tl
}
\cs_new_protected:Nn \stex_file_split_off_ext:NN {
  \seq_set_eq:NN #1 #2
  \seq_pop_right:NN #1 \l__stex_path_str
  \seq_set_split:NnV \l__stex_path_seq . \l__stex_path_str
  \seq_pop_right:NN \l__stex_path_seq \l__stex_path_str
  \seq_put_right:Nx #1 {\seq_use:Nn \l__stex_path_seq .}
}
\cs_new_protected:Nn \stex_file_split_off_lang:NN {
  \seq_set_eq:NN #1 #2
  \seq_pop_right:NN #1 \l__stex_path_str
  \seq_set_split:NnV \l__stex_path_seq . \l__stex_path_str
  \seq_pop_right:NN \l__stex_path_seq \l__stex_path_str

  \seq_pop_right:NN \l__stex_path_seq \l__stex_path_str
  \exp_args:NNo \prop_if_in:NnF \c_stex_languages_prop \l__stex_path_str {
    \seq_put_right:No \l__stex_path_seq \l__stex_path_str
  }

  \seq_put_right:Nx #1 {\seq_use:Nn \l__stex_path_seq .}
}
\cs_set_protected:Nn \__stex_path_auth:n {
  \msg_error:nnx{stex}{error/misused-uri}{\tl_to_str:n{#1}}
}
\cs_set_eq:NN \__stex_path_path:n \__stex_path_auth:n
\cs_set_eq:NN \__stex_path_module:n \__stex_path_auth:n
\cs_set_eq:NN \__stex_path_name:n \__stex_path_auth:n

\cs_set_protected:Nn \stex_map_uri:Nnnnn{
  \stex_pseudogroup_with:nn{\__stex_path_auth:n\__stex_path_path:n\__stex_path_module:n\__stex_path_name:n}{
    \cs_set:Npn \__stex_path_auth:n ##1 {#2}
    \cs_set:Npn \__stex_path_path:n ##1 {#3}
    \cs_set:Npn \__stex_path_module:n ##1 {#4}
    \cs_set:Npn \__stex_path_name:n ##1 {#5}
    #1
  }
}
\str_set:Nx\__stex_path_colonslash{\c_colon_str/}
\cs_new_protected:Nn \__stex_path_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 \__stex_path_colonslash { \tl_to_str:n{#2} }
    \seq_pop_left:NN #1 \l__stex_path_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 \__stex_path_colonslash }
      \seq_pop_left:NN #1 \l__stex_path_path
      #3 \l__stex_path_path \l__stex_path_path
      \seq_if_empty:NTF #1 {
        \exp_args:NNo \__stex_path_uri_set:Nnxnn #1 \l__stex_path_auth_str
          {\stex_file_use:N \l__stex_path_path} {} {}
      }{
        \seq_pop_left:NN #1 \l__stex_path_mod
        \seq_if_empty:NTF #1 {
          \exp_args:NNo \__stex_path_uri_set:Nnxon #1 \l__stex_path_auth_str
            {\stex_file_use:N \l__stex_path_path} \l__stex_path_mod {}
        }{
          \seq_pop_left:NN #1 \l__stex_path_name
          \seq_if_empty:NTF #1 {
            \exp_args:NNo \__stex_path_uri_set:Nnxon #2 \l__stex_path_auth_str
              {\stex_file_use:N \l__stex_path_path} \l__stex_path_mod \l__stex_path_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 \__stex_path_uri_set:Nnnnn{
  \tl_set:Nn #1 {
    \__stex_path_auth:n{ #2 }
    \__stex_path_path:n{ #3 }
    \__stex_path_module:n{ #4 }
    \__stex_path_name:n{ #5 }
  }
}
\cs_generate_variant:Nn\__stex_path_uri_set:Nnnnn {Nnxnn,Nnxon,Nnxoo}

\cs_new_protected:Nn \stex_uri_set:Nn {
  \__stex_path_uri_set:NnN #1 {#2} \stex_file_set:No
}
\cs_generate_variant:Nn \stex_uri_set:Nn {No, Nx}
\cs_new_protected:Nn \stex_uri_resolve:Nn {
  \__stex_path_uri_set:NnN #1 {#2} \stex_file_resolve:No
}
\cs_generate_variant:Nn \stex_uri_resolve:Nn {No, Nx}
\cs_new:Npn \__stex_path_uri_use:w \__stex_path_auth:n #1 \__stex_path_path:n #2 \__stex_path_module:n #3 \__stex_path_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 } \__stex_path_auth:n {
    \exp_after:wN \__stex_path_uri_use:w #1
  }{
    \msg_error:nnnn{stex}{error/invalid-uri}{#1}{Not~a~URI}
  }
}
\cs_new_protected:Npn \stex_uri_from_repo_file_nolang:NNNn {
  \__stex_path_from_repo_file:NNNNn \stex_file_split_off_lang:NN
}
\cs_new_protected:Npn \stex_uri_from_repo_file:NNNn {
  \__stex_path_from_repo_file:NNNNn \stex_file_split_off_ext:NN
}

\cs_new_protected:Nn \__stex_path_from_repo_file:NNNNn {
  #1 \l__stex_path_file #4
  \prop_if_exist:NTF #3 {
    \str_clear:N \l__stex_path_uri
    \prop_get:NnNF #3 {#5} \l__stex_path_uri {
      \prop_get:NnNF #3 {ns} \l__stex_path_uri {
        \__stex_path_uri_set:Nnxnn #2 {file}
          {\stex_file_use:N \l__stex_path_file} {} {}
      }
    }
    \str_if_empty:NF \l__stex_path_uri {\__stex_path_relativize:N #2}
  }{
    \exp_args:NNx \__stex_path_uri_set:Nnxnn #2 {\tl_to_str:n{file}}
      {\stex_file_use:N \l__stex_path_file} {} {}
  }
}

\cs_new_protected:Nn \__stex_path_relativize:N {
  \seq_set_eq:NN \l__stex_path_seq \l__stex_path_file
  \seq_map_inline:Nn \c_stex_mathhub_file { % mathhub path
    \seq_pop_left:NN \l__stex_path_seq \l__stex_path_tl
  }
  \stex_file_set:Nx \l__stex_path_path {\prop_item:Nn \l_stex_current_archive_prop {id} }
  \seq_map_inline:Nn \l__stex_path_path { % id
    \seq_pop_left:NN \l__stex_path_seq \l__stex_path_tl
  }
  \seq_pop_left:NN \l__stex_path_seq \l__stex_path_tl % source

  \stex_uri_set:Nx #1 { \l__stex_path_uri / \stex_file_use:N \l__stex_path_seq }
}
\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}
}
\cs_new_protected:Nn \stex_uri_add_module:NNn {
  \exp_args:Ne \cs_if_eq:NNTF { \tl_head:N #2 } \__stex_path_auth:n {
    \stex_pseudogroup_with:nn
      {\__stex_path_auth:n\__stex_path_path:n\__stex_path_module:n\__stex_path_name:n}
      {
        \cs_set:Npn \__stex_path_module:n ##1 {
          \tl_if_empty:nTF{##1}{
            \exp_not:N \__stex_path_module:n {#3}
          }{
            \msg_error:nnn{stex}{error/invalid-dpath}{#2}
          }
        }
        \cs_set:Npn \__stex_path_name:n ##1 {
          \tl_if_empty:nTF{##1}{
            \exp_not:N \__stex_path_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}
\tl_new:N \l_stex_current_doc_uri
\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}
}
\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}
}
\sys_if_platform_windows:TF{
  \stex_get_env:Nn\l__stex_path_str{CD}
}{
  \stex_get_env:Nn\l__stex_path_str{PWD}
}
\stex_file_resolve:No \c_stex_pwd_file \l__stex_path_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}
\seq_gclear_new:N\g__stex_path_stack
\seq_gclear_new:N\g_stex_current_file
\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__stex_path_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:
}
\cs_new_protected:Nn \stex_filestack_pop: {
  \seq_if_empty:NF \g__stex_path_stack {
    \seq_gpop:NN \g__stex_path_stack \l__stex_path_str
  }
  \seq_if_empty:NTF \g__stex_path_stack {
    \seq_gset_eq:NN \g_stex_current_file \c_stex_main_file
  }{
    \seq_get:NN \g__stex_path_stack \l__stex_path_str
    \exp_args:NNo \stex_file_set:Nn \g_stex_current_file \l__stex_path_str
    \seq_gset_eq:NN \g_stex_current_file \g_stex_current_file
  }
  \_stex_every_file:
}

\cs_new_protected:Nn \stex_input_with_hooks:n {
  \tl_set:Nn \l__stex_path_do_hooks_pre_tl {
    \tl_gset:Nn \l__stex_path_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__stex_path_do_hooks_pre_tl {}

\AddToHook{file/before}{
  \l__stex_path_do_hooks_pre_tl
}

\sys_if_platform_windows:TF{
  \stex_get_env:Nn \l__stex_mathhub_str {homedrive\c_percent_str\c_percent_str homepath}
}{
  \stex_get_env:Nn \l__stex_mathhub_str {HOME}
}
\stex_file_resolve:No \c_stex_home_file \l__stex_mathhub_str

\str_if_empty:NTF\mathhub{
  \stex_get_env:Nn \l__stex_mathhub_str {MATHHUB}
  \str_if_empty:NTF \l__stex_mathhub_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__stex_mathhub_str
        \str_gset_eq:NN \l__stex_mathhub_str \l__stex_mathhub_str
      \group_end:
      \ior_close:N \g_tmpa_ior
      \stex_debug:nn{mathhub}{MathHub~directory~determined~from~home~directory}
    }{
      \str_clear:N \l__stex_mathhub_str
    }
  }{
    \stex_debug:nn{mathhub}{MathHub~directory~determined~from~environment~variable}
  }
}{
  \str_set_eq:NN \l__stex_mathhub_str \mathhub
}

\str_if_empty:NTF \l__stex_mathhub_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__stex_mathhub_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__stex_mathhub_str
    }
  }
}

\exp_args:NNe \str_set:Nn \mathhub {\stex_file_use:N \c_stex_mathhub_file}
\stex_debug:nn{mathhub}{MATHHUB:~\mathhub}
\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
  }
}
\cs_new_protected:Nn \stex_in_archive:nn {
  \cs_if_exist:NF \l__stex_mathhub_cs {
    \cs_set:Npn \l__stex_mathhub_cs ##1 {}
  }
  \stex_pseudogroup:nn{
    \cs_set:Npn \l__stex_mathhub_cs ##1 {#2}
    \tl_if_empty:nTF{#1}{
      \prop_if_exist:NTF \l_stex_current_archive_prop {
        \exp_args:Ne \l__stex_mathhub_cs {\prop_item:Nn \l_stex_current_archive_prop { id } }
      }{
        \l__stex_mathhub_cs {}
      }
    }{
      \stex_set_current_archive:n{#1}
      \l__stex_mathhub_cs {#1}
    }
  }{
    \stex_pseudogroup_restore:N \l_stex_current_archive_prop
    \cs_set:Npn \exp_not:N \l__stex_mathhub_cs ##1 {
      \exp_args:No \exp_not:n {\l__stex_mathhub_cs {##1}}
    }
  }
}
\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}
      \__stex_mathhub_do_manifest:n { #1 }
    }
  }
}
\cs_generate_variant:Nn \stex_require_archive:n {o}
\cs_new_protected:Nn \__stex_mathhub_do_manifest:n {
  \exp_args:Ne \__stex_mathhub_find_manifest:n {\stex_file_use:N \c_stex_mathhub_file / #1}
  \str_if_empty:NT \l__stex_mathhub_manifest_str {
    \stex_fatal_error:nxx{error/noarchive}
      {#1}{\stex_file_use:N \c_stex_mathhub_file}
  }
  \__stex_mathhub_parse_manifest:n {#1}
}

\cs_new_protected:Nn \__stex_mathhub_find_manifest:n {
  \str_clear:N \l__stex_mathhub_manifest_str
  \seq_set_split:Nnn \l__stex_mathhub_seq / {#1}
  \bool_set_true:N \l__stex_mathhub_bool
  \bool_while_do:Nn \l__stex_mathhub_bool {
    \tl_if_eq:NNTF \l__stex_mathhub_seq \c_stex_mathhub_file {
      \bool_set_false:N \l__stex_mathhub_bool
    }{
      \__stex_mathhub_check_manifest:
      \bool_if:NT \l__stex_mathhub_bool {
        \seq_pop_right:NN \l__stex_mathhub_seq \l__stex_mathhub_tl
      }
    }
  }
}
\cs_generate_variant:Nn \__stex_mathhub_find_manifest:n {x}

\cs_new_protected:Nn \__stex_mathhub_check_manifest: {
  \__stex_mathhub_check_manifest:n {MANIFEST.MF}
  \bool_if:NT \l__stex_mathhub_bool {
    \__stex_mathhub_check_manifest:n {META-INF/MANIFEST.MF}
    \bool_if:NT \l__stex_mathhub_bool {
      \__stex_mathhub_check_manifest:n {meta-inf/MANIFEST.MF}
    }
  }
}

\cs_new_protected:Nn \__stex_mathhub_check_manifest:n {
  \stex_debug:nn{mathhub}{Checking~\stex_file_use:N \l__stex_mathhub_seq / #1}
  \file_if_exist:nT {\stex_file_use:N \l__stex_mathhub_seq / #1} {
    \bool_set_false:N \l__stex_mathhub_bool
    \str_set:Nx \l__stex_mathhub_manifest_str {\stex_file_use:N \l__stex_mathhub_seq / #1}
  }
}

\ior_new:N \c__stex_mathhub_manifest_ior
\cs_new_protected:Nn \__stex_mathhub_parse_manifest:n {
  \ior_open:Nn \c__stex_mathhub_manifest_ior \l__stex_mathhub_manifest_str
  \prop_clear:N \l__stex_mathhub_prop
  \ior_map_inline:Nn \c__stex_mathhub_manifest_ior {
    \exp_args:NNNo \exp_args:NNNx
      \seq_set_split:Nnn \l__stex_mathhub_seq \c_colon_str {\tl_to_str:n{##1}}
    \seq_pop_left:NNT \l__stex_mathhub_seq \l__stex_mathhub_key {
      \exp_args:NNo \str_set:Nn \l__stex_mathhub_key \l__stex_mathhub_key
      \str_set:Nx \l__stex_mathhub_val {\seq_use:Nn \l__stex_mathhub_seq :}
      \str_case:Nn \l__stex_mathhub_key {
        {id}              {\prop_put:Nno \l__stex_mathhub_prop { id }      \l__stex_mathhub_val }
        {narration-base}  {\prop_put:Nno \l__stex_mathhub_prop { narr }    \l__stex_mathhub_val }
        {url-base}        {\prop_put:Nno \l__stex_mathhub_prop { docurl }  \l__stex_mathhub_val }
        {source-base}     {\prop_put:Nno \l__stex_mathhub_prop { ns }      \l__stex_mathhub_val }
        {ns}              {\prop_put:Nno \l__stex_mathhub_prop { ns }      \l__stex_mathhub_val }
      }
    }
  }
  \ior_close:N \c__stex_mathhub_manifest_ior
  \prop_gset_eq:cN { c_stex_mathhub_#1_manifest_prop } \l__stex_mathhub_prop
  \stex_debug:nn{mathhub}{Result:~\prop_to_keyval:N \l__stex_mathhub_prop}
  \stex_persist:e {
    \prop_gset_from_keyval:cn {c_stex_mathhub_#1_manifest_prop}{
      \prop_to_keyval:N \l__stex_mathhub_prop
    }
  }
}
\cs_new_protected:Nn \_stex_main_archive: {
  \stex_if_file_starts_with:NNTF \c_stex_pwd_file \c_stex_mathhub_file {
    \__stex_mathhub_find_manifest:x { \stex_file_use:N \c_stex_pwd_file }
    \str_if_empty:NTF \l__stex_mathhub_manifest_str {
      \stex_debug:nn{mathhub}{Not~currently~in~a~MathHub~archive}
    }{
      \__stex_mathhub_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__stex_mathhub_str
      \prop_set_eq:cN { c_stex_mathhub_\l__stex_mathhub_str _manifest_prop }
        \c_stex_main_archive_prop
      \exp_args:No \stex_set_current_archive:n { \l__stex_mathhub_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__stex_mathhub_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__stex_mathhub_str _manifest_prop
            }
            \prop_gset_eq:Nc \exp_not:N \c_stex_main_archive_prop {
              c_stex_mathhub_\l__stex_mathhub_str _manifest_prop
            }
          }
        }
      }
    }
  }{
    \stex_debug:nn{mathhub}{Not~currently~in~the~MathHub~directory}
  }
}

  \_stex_main_archive:
\tl_new:N \g__stex_doc_title_tl
\cs_new_protected:Npn \stexdoctitle #1 {
  \tl_gset:Nn \g__stex_doc_title_tl { #1 }
  \global\def\stexdoctitle##1{}
}
\cs_new_protected:Nn \__stex_doc_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__stex_doc_title_tl { #1 }
    \__stex_doc_title_html:
  }
}
\cs_new_protected:Nn \__stex_doc_title_html: {
  \stex_if_do_html:T{\stex_if_html_backend:T{
    \stex_annotate_invisible:nn{shtml:doctitle={}}{ \hbox{\g__stex_doc_title_tl} }
  }}
}

\AtBeginDocument {
  \tl_if_empty:NTF \g__stex_doc_title_tl {
    \cs_set_eq:NN \stexdoctitle \__stex_doc_set_title:n
  }{
    \stex_debug:nn{title}{Setting~title~to:\exp_args:No\tl_to_str:n\g__stex_doc_title_tl}
    \global\def\stexdoctitle#1{}
    \__stex_doc_title_html:
  }

  \cs_set_eq:NN \__stex_doc_maketitle: \maketitle
  \global\protected\def\maketitle{
    \tl_if_empty:NF \@title {
      \exp_args:No \stexdoctitle \@title
    }
    \__stex_doc_maketitle:
  }
}
\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 \__stex_doc_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
      \__stex_doc_do_section:n
    }}
    {1}{\cs_if_exist:NTF \thechapter {\_sfragment_do_level:nn{chapter}}{
      \int_incr:N \l_stex_docheader_sect
      \__stex_doc_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}
  \__stex_doc_do_section:n{#2}
  \_stex_do_id:
}{
  \_sfragment_end:
}

\NewDocumentEnvironment{blindfragment}{}{
  \__stex_doc_skip_section:
}{
  \stex_if_html_backend:T{
    \stex_annotate_invisible:n{~}
    \end{stex_annotate_env}
  }
}

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

\stex_if_html_backend:TF {
  \cs_new_protected:Nn \__stex_doc_skip_section: {
    \__stex_doc_skip_section_i:
    \begin{stex_annotate_env}{shtml:skipsection={\int_use:N \l_stex_docheader_sect}}
    \stex_annotate_invisible:n{~}
  }
}{
  \cs_set_eq:NN \__stex_doc_skip_section: \__stex_doc_skip_section_i:
}

\cs_new_protected:Nn \__stex_doc_skip_fragment:n {
  \stepcounter{#1}
}

\cs_new_protected:Npn \skipfragment {
  \int_case:nnF \l_stex_docheader_sect {
    {0}{\cs_if_exist:NTF \thepart {\__stex_doc_skip_fragment:n{part}}{
      \int_incr:N \l_stex_docheader_sect
      \skipfragment
    }}
    {1}{\cs_if_exist:NTF \thechapter {\__stex_doc_skip_fragment:n{chapter}}{
      \int_incr:N \l_stex_docheader_sect
      \skipfragment
    }}
    {2}{\__stex_doc_skip_fragment:n{section}}
    {3}{\__stex_doc_skip_fragment:n{subsection}}
    {4}{\__stex_doc_skip_fragment:n{subsubsection}}
    {5}{\__stex_doc_skip_fragment:n{paragraph}}
  }{\__stex_doc_skip_fragment:n{subparagraph}}
}
\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 \__stex_doc_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
        \__stex_doc_check_topsect:
      }}
      {1}{\cs_if_exist:NTF \thechapter {
        \stex_annotate_invisible:nn{shtml:sectionlevel=1}{}
      }{
        \int_incr:N \l_stex_docheader_sect
        \__stex_doc_check_topsect:
      }}
    }{
      \stex_annotate_invisible:nn{shtml:sectionlevel={\int_use:N\l_stex_docheader_sect}}{}
    }
  }
  \AtBeginDocument{\__stex_doc_check_topsect:}
}

\AtBeginDocument{
  \bool_if:NF \c_stex_no_frontmatter_bool {
    \cs_if_exist:NTF\frontmatter{
      \let\__stex_doc_orig_frontmatter\frontmatter
      \let\frontmatter\relax
    }{
      \tl_set:Nn\__stex_doc_orig_frontmatter{
        \clearpage
        %\@mainmatterfalse
        \pagenumbering{roman}
      }
    }
    \cs_if_exist:NTF\backmatter{
      \let\__stex_doc_orig_backmatter\backmatter
      \let\backmatter\relax
    }{
      \tl_set:Nn\__stex_doc_orig_backmatter{
        \clearpage
        %\@mainmatterfalse
        \pagenumbering{roman}
      }
    }
    \newenvironment{frontmatter}{
      \__stex_doc_orig_frontmatter
    }{
      \cs_if_exist:NTF\mainmatter{
        \mainmatter
      }{
        \clearpage
        %\@mainmattertrue
        \pagenumbering{arabic}
      }
    }
    \newenvironment{backmatter}{
      \__stex_doc_orig_backmatter
    }{
      \cs_if_exist:NTF\mainmatter{
        \mainmatter
      }{
        \clearpage
        %\@mainmattertrue
        \pagenumbering{arabic}
      }
    }
  }
}
\iow_new:N \c__stex_refs_iow
\AtBeginDocument{\iow_open:Nn \c__stex_refs_iow {\jobname.sref}}
\AtEndDocument{\iow_close:N \c__stex_refs_iow}
\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}
}

\seq_new:N \g__stex_refs_files_seq
\int_new:N \l__stex_refs_unnamed_counter_int

\cs_new_protected:Nn \_stex_ref_new_id:n {
  \str_if_empty:nTF {#1}{
    \int_gincr:N \l__stex_refs_unnamed_counter_int
    \str_set:Nx \l__stex_refs_str {REF\int_use:N \l__stex_refs_unnamed_counter_int}
  }{
    \str_set:Nn \l__stex_refs_str {#1}
  }
  \str_set:Nx \l_stex_ref_url_str {\stex_uri_use:N \l_stex_current_doc_uri ? \l__stex_refs_str}
}

\cs_new_protected:Nn \stex_ref_new_doc_target:n {
  \_stex_ref_new_id:n{#1}
  %\stex_uri_add_module:NNo \l__stex_refs_uri \l_stex_current_doc_uri \l__stex_refs_str
  %\stex_debug:nn{sref}{New~document~target:~\stex_uri_use:N \l__stex_refs_uri}
  \__stex_refs_add_doc_ref:xo {\stex_uri_use:N \l_stex_current_doc_uri} \l__stex_refs_str
  \stex_if_smsmode:F {
    \iow_now:Nx \c__stex_refs_iow {
      \STEXInternalSrefRestoreTarget
      {\stex_uri_use:N \l_stex_current_doc_uri}
      {\l__stex_refs_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 \__stex_refs_add_doc_ref:nn {
  \seq_if_in:NnTF \g__stex_refs_files_seq {#1} {
    \seq_if_in:cnF {g__stex_refs_#1_seq}{#2}{
      \seq_gput_left:cn{g__stex_refs_#1_seq}{#2}
    }
  }{
    \seq_gput_right:Nn \g__stex_refs_files_seq {#1}
    \seq_new:c{g__stex_refs_#1_seq}
    \seq_gput_left:cn{g__stex_refs_#1_seq}{#2}
  }
}
\cs_generate_variant:Nn \__stex_refs_add_doc_ref:nn {xo,xx}
\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__stex_refs_default_archive_str
\str_new:N \l__stex_refs_default_file_str
\tl_new:N \l__stex_refs_default_title_tl

\cs_set_protected:Nn \__stex_refs_set_keys_b:n {
  \tl_if_empty:nTF{#1}{
    \str_set_eq:NN \l_stex_key_archive_str \l__stex_refs_default_archive_str
    \str_set_eq:NN \l_stex_key_file_str \l__stex_refs_default_file_str
    \tl_set_eq:NN \l_stex_key_title_tl \l__stex_refs_default_title_tl
  }{
    \stex_keys_set:nn{ sref / 2 }{ #1 }
  }
}

\newcommand\srefsetin[3][]{
  \str_set:Nx \l__stex_refs_default_archive_str {#1}
  \str_set:Nx \l__stex_refs_default_file_str {#2}
  \tl_set:Nn \l__stex_refs_default_title_tl {#3}
}

\cs_new_protected:Nn \__stex_refs_find_uri:n {
  \str_clear:N \l__stex_refs_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_refs_\stex_uri_use:N \l_stex_current_doc_uri _seq}{
      \exp_args:Nnx \__stex_refs_find_uri_in_file:nnn{#1}
        {\stex_uri_use:N \l_stex_current_doc_uri}\seq_map_break:
    }
    \str_if_empty:NT \l__stex_refs_uri_str {
      \seq_map_inline:Nn \g__stex_refs_files_seq {
        \__stex_refs_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 {
        \__stex_refs_find_uri_in_prop_file:N \l_stex_current_archive_prop
      }{
        \stex_file_resolve:Nx \l__stex_refs_file
          { \stex_file_use:N \g_stex_current_file / .. / \l_stex_key_file_str }
        \str_set:Nx \l__stex_refs_uri_str { file:/ \stex_file_use:N \l__stex_refs_file }
      }
    }{
      \stex_require_archive:o \l_stex_key_archive_str
      \prop_set_eq:Nc \l__stex_refs_prop { c_stex_mathhub_\l_stex_key_archive_str _manifest_prop }
      \__stex_refs_find_uri_in_prop_file:N \l__stex_refs_prop
    }
  }
}

\cs_new_protected:Nn \__stex_refs_find_uri_in_prop_file:N {
  \str_set:Nx \l__stex_refs_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__stex_refs_file \l__stex_refs_uri_str
  \stex_uri_from_repo_file:NNNn \l__stex_refs_uri #1
    \l__stex_refs_file {narr}
  \str_set:Nx \l__stex_refs_uri_str {\stex_uri_use:N \l__stex_refs_uri}
}

\cs_new_protected:Nn \__stex_refs_find_uri_in_file:nnn {
  \stex_debug:nn{sref}{Checking~file~#2}
  \seq_map_inline:cn{g__stex_refs_#2_seq}{
    \str_if_eq:nnT{#1}{##1}{
      \str_set:Nx \l__stex_refs_uri_str {\stex_uri_use:N \l_stex_current_doc_uri}
      \stex_debug:nn{sref}{Found.}
      #3
    }
  }
}
\cs_new_protected:Nn \__stex_refs_do_autoref:n {
  \cs_if_exist:cTF{autoref}{
     \exp_args:Nx\autoref{sref@#1}
   }{
     \exp_args:Nx\ref{sref@#1}
   }
}

\cs_new_protected:Nn \__stex_refs_do_sref:nn {
  \str_if_empty:NTF \l__stex_refs_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 \__stex_refs_do_autoref:n{\stex_uri_use:N \l_stex_current_doc_uri ? #1}
    }{
      \stex_debug:nn{sref}{srefin~on~#1}
      \__stex_refs_set_keys_b:n{ #2 }
      \__stex_refs_do_sref_in:n{#1}
    }
  }{
    \exp_args:NNo \seq_if_in:NnTF \g__stex_refs_files_seq \l__stex_refs_uri_str {
      \stex_debug:nn{sref}{Using~ref~file~\l__stex_refs_uri_str}
      \exp_args:Nnx \seq_if_in:cnTF{g_stex_ref_\l__stex_refs_uri_str _seq}{\detokenize{#1}}{
        \stex_debug:nn{sref}{Reference~found~in~ref~files;~autoref~on~\l__stex_refs_uri_str?#1}
        \__stex_refs_do_autoref:n{\l__stex_refs_uri_str?#1}
      }{
        \str_if_empty:NTF \l_stex_key_file_str {
          \stex_debug:nn{sref}{in~empty;~autoref~on~\l__stex_refs_uri_str?#1}
          \__stex_refs_do_autoref:n{\l__stex_refs_uri_str?#1}
        }{
          \stex_debug:nn{sref}{in~non-empty;~srefin~on~\l__stex_refs_uri_str?#1}
          \__stex_refs_set_keys_b:n{ #2 }
          \__stex_refs_do_sref_in:n{#1}
        }
      }
    }{
      \stex_debug:nn{sref}{No~ref~file~found~for~\l__stex_refs_uri_str}
      \str_if_empty:NTF \l_stex_key_file_str {
        \stex_debug:nn{sref}{in~empty;~autoref~on~\l__stex_refs_uri_str?#1}
        \__stex_refs_do_autoref:n{\l__stex_refs_uri_str?#1}
      }{
        \stex_debug:nn{sref}{in~non-empty;~srefin~on~\l__stex_refs_uri_str?#1}
        \__stex_refs_set_keys_b:n{ #2 }
        \__stex_refs_do_sref_in:n{#1}
      }
    }
  }
}

\cs_new_protected:Nn \__stex_refs_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__stex_refs_uri_str?#1}
  \tl_if_exist:cTF{r@sref@\l__stex_refs_uri_str?#1}{
    \__stex_refs_do_autoref:n{\l__stex_refs_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__stex_refs_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__stex_refs_file_str {
            \stex_file_use:N \g_stex_current_file / .. / \l_stex_key_file_str . sref
          }
        }
      }{
        \str_set:Nx \l__stex_refs_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__stex_refs_file \l__stex_refs_file_str
      \str_set:Nx \l__stex_refs_file_str {\stex_file_use:N \l__stex_refs_file }
      \stex_debug:nn{sref}{File: \l__stex_refs_file_str }
      \exp_args:NNNx \exp_args:No \str_if_eq:nnTF \l__stex_refs_file_str {\stex_file_use:N\c_stex_pwd_file / \jobname.sref}{
        \__stex_refs_do_autoref:n{
          \str_if_empty:NF\l__stex_refs_uri_str{\l__stex_refs_uri_str?}#1
        }
      }{
        \exp_args:No \IfFileExists \l__stex_refs_file_str {
          \tl_clear:N \l__stex_refs_return_tl
          \str_set:Nn \l__stex_refs_id_str {#1}
          \let\STEXInternalSrefRestoreTarget\__stex_refs_restore_target:nnnnn
          \use:c{@ @ input}{\l__stex_refs_file_str}
          \exp_args:No \tl_if_empty:nTF \l__stex_refs_return_tl {
            \exp_args:Nnno \msg_warning:nnnn{stex}{warning/smslabelmissing}\l__stex_refs_file_str{#1}
            \__stex_refs_do_autoref:n{
              \str_if_empty:NF\l__stex_refs_uri_str{\l__stex_refs_uri_str?}#1
            }
          }{
            \l__stex_refs_return_tl
          }
        }{
          \exp_args:Nnno \msg_warning:nnn{stex}{warning/smsmissing}\l__stex_refs_file_str
          \__stex_refs_do_autoref:n{
            \str_if_empty:NF\l__stex_refs_uri_str{\l__stex_refs_uri_str?}#1
          }
        }
      }
    \group_end:
  }
}

\cs_new_protected:Nn \__stex_refs_do_return:nnnn {
  \tl_set:Nn \l__stex_refs_return_tl {
    \stex_annotate:nn{shtml:sref={#4},shtml:srefin={\l__stex_refs_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 \__stex_refs_restore_target:nnnnn {
  \str_if_empty:NTF \l__stex_refs_uri_str {
    \exp_args:No \str_if_eq:nnT \l__stex_refs_id_str {#2}{
      \__stex_refs_do_return:nnnn{#4}{#5}{#3}{#1?#2}
    }
  }{
    \stex_debug:nn{sref}{\l__stex_refs_uri_str{}~ == ~ #1 ~ ?}
    \exp_args:No \str_if_eq:nnT \l__stex_refs_uri_str {#1}{
      \stex_debug:nn{sref}{\l__stex_refs_id_str~ == ~ #2 ~ ?}
      \exp_args:No \str_if_eq:nnT \l__stex_refs_id_str {#2}{
        \stex_debug:nn{sref}{success!}
        \__stex_refs_do_return:nnnn{#4}{#5}{#3}{#1?#2}
        \endinput
      }
    }
  }
}
\NewDocumentCommand \sref { O{} m O{}}{
  \stex_keys_set:nn { sref / 1 }{ #1 }
  \__stex_refs_find_uri:n { #2 }
  \__stex_refs_do_sref:nn{#2}{#3}
}
\NewDocumentCommand \extref { O{} m m}{
  \stex_keys_set:nn { sref / 1 }{ #1 }
  \__stex_refs_find_uri:n { #2 }
  \__stex_refs_set_keys_b:n{ #3 }
  \str_if_empty:NT \l_stex_key_file_str {
    \msg_error:nn{stex}{error/extrefmissing}
  }
  \__stex_refs_do_sref_in:n{#2}
}
\cs_new_protected:Nn \stex_ref_new_symbol:n {
  \cs_if_exist:cF{r@sref@sym@\tl_to_str:n{#1}}{
    \__stex_refs_new_symbol:n{#1}
  }
}

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

\cs_new_protected:Nn \__stex_refs_new_symbol:n {
  \prop_if_exist:NTF \l_stex_current_archive_prop {
    \prop_get:NnNTF \l_stex_current_archive_prop {docurl} \l__stex_refs_str {
      \exp_args:Ne \_stex_sref_do_aux:n {
        \STEXInternalSetSrefSymURL{#1}{\l__stex_refs_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}
  }
}
\NewDocumentCommand \srefsym { m m}{
  \stex_get_symbol:n { #1 }
  \exp_args:Ne
  \__stex_refs_sym_aux:nn{\l_stex_get_symbol_mod_str ? \l_stex_get_symbol_name_str}
}

\cs_new_protected:Npn \__stex_refs_do_internal_link:nn #1 {
  \cs_if_exist:NTF \hyperlink {
    \hyperlink{#1}
  }\use:n
}

\cs_new_protected:Npn \__stex_refs_do_url_link:nn {
  \cs_if_exist:NTF \href \href \use_ii:nn
}

\cs_new_protected:Npn \__stex_refs_sym_aux:nn #1 {
  \cs_if_exist:cTF{\tl_to_str:n{r@sref@sym@#1}}{
    \exp_args:Ne \__stex_refs_do_internal_link:nn{\tl_to_str:n{sref@sym@#1}}
  }{
    \str_if_exist:cTF{g_stex_sref_sym_#1_label}{
      \exp_args:Ne \__stex_refs_sym_aux:nn{\use:c{g_stex_sref_sym_#1_label}}
    }{
      \str_if_empty:cTF{g_stex_sref_sym_#1_target}{
        \exp_args:Ne \__stex_refs_do_internal_link:nn{\tl_to_str:n{sref@sym@#1}}
      }{
        \exp_args:Ne \__stex_refs_do_url_link:nn{\use:c{g_stex_sref_sym_#1_target}}
      }
    }
  }
}
\cs_new_protected:Npn \srefsymuri #1 {
  \__stex_refs_sym_aux:nn{#1}
}
\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}
\newif \ifinputref \inputreffalse

\cs_new_protected:Nn \__stex_inputs_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\__stex_inputs_mhinput:nn{ \tl_to_str:n{#1} }{ \tl_to_str:n{#2} }
}

\cs_new_protected:Nn \__stex_inputs_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 \__stex_inputs_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 \__stex_inputs_inputref:nn {
  \stex_in_archive:nn {#1} {
    \stex_if_html_backend:TF
      \__stex_inputs_inputref_html:nn
      \__stex_inputs_inputref_pdf:nn
    {##1}{#2}
  }
}

\NewDocumentCommand \inputref { O{} m}{
  \exp_args:NNx \exp_args:Nnx \__stex_inputs_inputref:nn{ \tl_to_str:n{#1} }{ \tl_to_str:n{#2} }
}
\cs_new_protected:Nn \__stex_inputs_bibresource:n {
  \__stex_inputs_up_archive:nn{#1}{bib}
  \seq_if_empty:NTF \l__stex_inputs_libinput_files_seq {
    \msg_error:nnxx{stex}{error/nofile}{\exp_not:N\addmhbibresource}{#1.bib}
  }{
    \seq_map_inline:Nn \l__stex_inputs_libinput_files_seq {
      \addbibresource{ ##1 }
    }
  }
}
\newcommand\addmhbibresource[2][]{
  \tl_if_empty:nTF{#1}{
    \__stex_inputs_bibresource:n{#2}
  }{
    \stex_in_archive:nn{#1}{\__stex_inputs_bibresource:n{#2}}
  }
}
\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
  }
}
\cs_new_protected:Nn \__stex_inputs_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__stex_inputs_id_str {
    \msg_error:nnn{stex}{error/notinarchive}\libinput
  }
  \seq_clear:N \l__stex_inputs_libinput_files_seq
  \seq_set_eq:NN \l__stex_inputs_path_seq \c_stex_mathhub_file
  \seq_set_split:NnV \l__stex_inputs_id_seq / \l__stex_inputs_id_str

  \bool_while_do:nn { ! \seq_if_empty_p:N \l__stex_inputs_id_seq }{
    \str_set:Nx \l__stex_inputs_path_str {\stex_file_use:N \l__stex_inputs_path_seq / meta-inf / lib / #1.#2}
    \IfFileExists{ \l__stex_inputs_path_str }{
      \exp_args:NNo \seq_if_in:NnF \l__stex_inputs_libinput_files_seq \l__stex_inputs_path_str {
        \seq_put_right:No \l__stex_inputs_libinput_files_seq \l__stex_inputs_path_str
      }
    }{}
    \seq_pop_left:NN \l__stex_inputs_id_seq \l__stex_inputs_path_str
    \seq_put_right:No \l__stex_inputs_path_seq \l__stex_inputs_path_str
  }

  \str_set:Nx \l__stex_inputs_path_str {\stex_file_use:N \l__stex_inputs_path_seq / lib / #1.#2}
  \IfFileExists{ \l__stex_inputs_path_str }{
    \exp_args:NNo \seq_if_in:NnF \l__stex_inputs_libinput_files_seq \l__stex_inputs_path_str {
      \seq_put_right:No \l__stex_inputs_libinput_files_seq \l__stex_inputs_path_str
    }
  }{}
}

\cs_new_protected:Nn \__stex_inputs_libinput:n {
  \__stex_inputs_up_archive:nn{#1}{tex}
  \seq_if_empty:NTF \l__stex_inputs_libinput_files_seq {
    \msg_error:nnxx{stex}{error/nofile}{\exp_not:N\libinput}{#1.tex}
  }{
    \seq_map_inline:Nn \l__stex_inputs_libinput_files_seq {
      \input{ ##1 }
    }
  }
}

\newcommand \libinput [2][] {
  \tl_if_empty:nTF{#1}{
    \__stex_inputs_libinput:n{#2}
  }{
    \stex_in_archive:nn{#1}{\__stex_inputs_libinput:n{#2}}
  }
}
\newcommand\libusepackage[2][]{
  \__stex_inputs_up_archive:nn{#2}{sty}
  \int_compare:nNnTF {\seq_count:N \l__stex_inputs_libinput_files_seq} = 1 {
    \str_set:Nx \l__stex_inputs_tmp_str {\seq_item:Nn \l__stex_inputs_libinput_files_seq 1}
    \exp_args:Nne \use:n {\usepackage[#1]} {
      \str_range:Nnn\l__stex_inputs_tmp_str 1 {-5}
    }
  }{
    \stex_fatal_error:nnn{error/nofile}{\libusepackage}{#1.sty}
  }
}
\str_new:N \l__stex_inputs_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__stex_inputs_gin_repo_str {#1}
    \def\Gin@mhrepos{\stex_file_use:N \c_stex_mathhub_file / #1 / source /}
  }
  \newcommand\mhtikzinput[2][]{%
    \str_clear:N \l__stex_inputs_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__stex_inputs_gin_repo_str {
      \tikzinput[#1]{\Gin@mhrepos #2}
    }
  }
  \newcommand\cmhtikzinput[2][]{\begin{center}\mhtikzinput[#1]{#2}\end{center}}
}
\cs_new_protected:Nn \__stex_inputs_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 \__stex_inputs_usetikzlibrary:n{
  \__stex_inputs_up_archive:nn{tikzlibrary#1}{code.tex}
  \int_compare:nNnTF {\seq_count:N \l__stex_inputs_libinput_files_seq} = 1 {
    \exp_args:Nne \__stex_inputs_usetikzlibrary_i:nn{#1}{ \seq_item:Nn \l__stex_inputs_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}{
    \__stex_inputs_usetikzlibrary:n{#2}
  }{
    \stex_in_archive:nn{#1}{\__stex_inputs_usetikzlibrary:n{#2}}
  }
}
\tl_new:N \g__stex_smsmode_allowed_tl
\tl_new:N \g__stex_smsmode_allowed_escape_tl
\seq_new:N \g__stex_smsmode_allowedenvs_seq
\cs_new_protected:Nn \stex_sms_allow:N {
  \tl_gput_right:Nn \g__stex_smsmode_allowed_tl {#1}
}

\cs_new_protected:Nn \stex_sms_allow_escape:N {
  \tl_gput_right:Nn \g__stex_smsmode_allowed_escape_tl {#1}
}

\cs_new_protected:Nn \stex_sms_allow_env:n {
  \exp_args:NNx \seq_gput_right:Nn \g__stex_smsmode_allowedenvs_seq {\tl_to_str:n{#1}}
}
\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
\bool_new:N \g__stex_smsmode_bool
\bool_set_false:N \g__stex_smsmode_bool
\prg_new_conditional:Nnn \stex_if_smsmode: { p, T, F, TF } {
  \bool_if:NTF \g__stex_smsmode_bool \prg_return_true: \prg_return_false:
}
\tl_new:N \g__stex_smsmode_allowed_import_tl
\seq_new:N \g__stex_smsmode_allowed_import_env_seq
\cs_new_protected:Nn \stex_sms_allow_import:Nn {
  \tl_gput_right:Nn \g__stex_smsmode_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__stex_smsmode_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
\cs_new_protected:Nn \__stex_smsmode_in_smsmode:n { \stex_suppress_html:n {
  \vbox_set:Nn \l_tmpa_box {
    \bool_set_true:N \g__stex_smsmode_bool
    \bool_set_false:N \_stex_html_do_output_bool
    #1
  }
  %\box_clear:N \l_tmpa_box
} }

\quark_new:N \q__stex_smsmode_break

\cs_new_protected:Nn \__stex_smsmode_start_smsmode:n {
  \everyeof{\q__stex_smsmode_break\exp_not:N}
  \let\stex_smsmode_do:\__stex_smsmode_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__stex_smsmode_importmodules_seq
  \seq_gclear:N \l__stex_smsmode_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}
    \__stex_smsmode_in_smsmode:n {
      \let \__stex_smsmode_do_aux_curr:N \__stex_smsmode_do_aux_imports:N
      \tl_map_inline:Nn \g__stex_smsmode_allowed_import_tl {
        \use:c{\tl_to_str:n{##1}~-~smsmode}
      }
      \seq_map_inline:Nn \g__stex_smsmode_allowed_import_env_seq {
        \use:c{\tl_to_str:n{##1}~-~env~-~smsmode}
      }
      \__stex_smsmode_start_smsmode:n{#1}
    }
    \__stex_smsmode_in_smsmode:n \g_stex_sms_import_code
    \__stex_smsmode_in_smsmode:n {
      \let \__stex_smsmode_do_aux_curr:N \__stex_smsmode_do_aux_normal:N
      \__stex_smsmode_start_smsmode:n{#1}
    }
    \stex_filestack_pop:
  \group_end:
}
\cs_generate_variant:Nn \stex_file_in_smsmode:nn {on}
\cs_new_protected:Nn \__stex_smsmode_smsmode_do: {
 %\stex_if_smsmode:T {
    \__stex_smsmode_do:w
  %}
}
\let\stex_smsmode_do:\relax

\cs_new:Nn \__stex_smsmode_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 \__stex_smsmode_do:w #1 {
  \exp_args:Nx \tl_if_empty:nTF { \tl_tail:n{ #1 }}{
    \__stex_smsmode_check_cs:NNn \__stex_smsmode_do_aux:N \__stex_smsmode_do:w { #1 }
  }{
    \__stex_smsmode_do:w
  }
}

\cs_new_protected:Nn \__stex_smsmode_do_aux:N {
  \cs_if_eq:NNF #1 \q__stex_smsmode_break {
    \__stex_smsmode_do_aux_curr:N #1
  }
}

\cs_new_protected:Nn \__stex_smsmode_do_aux_imports:N {
 % \stex_debug:nn{sms}{Checking~\tl_to_str:n{#1}~in~import}
  \tl_if_in:NnTF \g__stex_smsmode_allowed_import_tl {#1} {
    \stex_debug:nn{sms}{Executing~\tl_to_str:n{#1}~in~import}
    #1
  }{
    \cs_if_eq:NNTF \begin #1 {
      \__stex_smsmode_check_begin:Nn \g__stex_smsmode_allowed_import_env_seq
    }{
      \cs_if_eq:NNTF \end #1 {
        \__stex_smsmode_check_end:Nn \g__stex_smsmode_allowed_import_env_seq
      }{
        \__stex_smsmode_do:w
      }
    }
  }
}

\cs_new_protected:Nn \__stex_smsmode_do_aux_normal:N {
 % \stex_debug:nn{sms}{Checking~\tl_to_str:n{#1}~in~sms~mode}
  \tl_if_in:NnTF \g__stex_smsmode_allowed_tl {#1} {
    \stex_debug:nn{sms}{Executing~\tl_to_str:n{#1}}
    #1\__stex_smsmode_do:w
  }{
    \tl_if_in:NnTF \g__stex_smsmode_allowed_escape_tl {#1} {
      \stex_debug:nn{sms}{Executing~escaped~\tl_to_str:n{#1}}
      #1
    }{
      \cs_if_eq:NNTF \begin #1 {
        \__stex_smsmode_check_begin:Nn \g__stex_smsmode_allowedenvs_seq
      }{
        \cs_if_eq:NNTF \end #1 {
          \__stex_smsmode_check_end:Nn \g__stex_smsmode_allowedenvs_seq
        }{
          \__stex_smsmode_do:w
        }
      }
    }
  }
}

\cs_new_protected:Nn \__stex_smsmode_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}
  }{
    \__stex_smsmode_do:w
  }
}
\cs_new_protected:Nn \__stex_smsmode_check_end:Nn {
  \seq_if_in:NxTF #1 { \tl_to_str:n{#2} }{
    \stex_debug:nn{sms}{End~Environment~#2}
    \end{#2}\__stex_smsmode_do:w
  }{
    %\str_if_eq:nnTF{#2}{document} \endinput
    \__stex_smsmode_do:w
  }
}
\str_new:N \l_stex_current_module_str
\seq_new:N \l_stex_all_modules_seq
\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 }
}
\cs_new_protected:Npn \stex_module_setup:n {
  \stex_if_in_module:TF \__stex_module_setup_setup_nested:n \__stex_module_setup_setup_top:n
}

\cs_new_protected:Nn \__stex_module_setup_setup_top:n {
  \__stex_module_setup_get_uri_str:n{#1}
  \stex_debug:nn{module}{Module~URI:~\l__stex_module_setup_ns_str?#1}
  \str_if_empty:NTF \l_stex_key_sig_str
  \_stex_module_setup_top_nosig:n \__stex_module_setup_setup_top_sig:n {\l__stex_module_setup_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}
  }
  \__stex_module_setup_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 \__stex_module_setup_setup_top_sig:n {
  \stex_if_module_exists:nTF{#1}{
    \stex_debug:nn{modules}{(already exists)}
  }{
    \stex_debug:nn{modules}{(needs loading)}
    \__stex_module_setup_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 \__stex_module_setup_load_sig: {
  \stex_file_split_off_ext:NN \l__stex_module_setup_sigfile \g_stex_current_file
  \stex_file_split_off_lang:NN \l__stex_module_setup_sigfile \l__stex_module_setup_sigfile
  \exp_args:Ne \stex_file_in_smsmode:nn {
    \stex_file_use:N \l__stex_module_setup_sigfile . \l_stex_key_sig_str . tex
  }{}
}

\cs_new_protected:Nn \__stex_module_setup_setup_nested:n {
  \exp_after:wN
    \__stex_module_setup_split_module:n \l_stex_current_module_str \__stex_module_setup_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 \__stex_module_setup_get_uri_str:n {
  \str_clear:N \l__stex_module_setup_ns_str
  \stex_map_uri:Nnnnn \l_stex_current_ns_uri {
    \str_set:Nx \l__stex_module_setup_ns_str{##1\c_colon_str/}
  }{
    \seq_set_split:Nnn \l__stex_module_setup_seq / {##1}
    \seq_pop_right:NN \l__stex_module_setup_seq \l__stex_module_setup_seg
    \exp_args:No \str_if_eq:nnF \l__stex_module_setup_seg {#1} {
      \seq_put_right:No \l__stex_module_setup_seq \l__stex_module_setup_seg
    }
    \tl_put_right:Nx \l__stex_module_setup_ns_str {\seq_use:Nn \l__stex_module_setup_seq /}
  }{}{}
}

\cs_new_protected:Npn \__stex_module_setup_split_module:n #1?#2 \__stex_module_setup_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 \__stex_module_setup_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 }
      }
    }
  }
}

\cs_new:Nn \stex_close_module: {
  \bool_if:NT \c_stex_persist_write_mode_bool \__stex_modules_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 \__stex_modules_persist_module: {
  \stex_persist:e {
    \__stex_modules_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}
      \__stex_modules_persist_nots_i:nn
    \exp_not:N \STEXRestoreNotsEnd {}
  }
}

\cs_new_protected:Nn \__stex_modules_restore_module:nnnn {
  \prop_gset_from_keyval:cn{c_stex_module_\tl_to_str:n{#1}_morphisms_prop}{#2}
  \cs_set:Npn \__stex_modules_tl {#3}
  \exp_args:Nno \prop_gset_from_keyval:cn{c_stex_module_\tl_to_str:n{#1}_symbols_prop}\__stex_modules_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__stex_modules_restore_mod_str {#1}
  \group_begin:
    \catcode`_=8\relax
    \catcode`:=12\relax
    \__stex_modules_restore_nots:n
}

\cs_new:Nn \__stex_modules_persist_nots_i:nn {
  \exp_not:n{#2}
}

\quark_new:N \STEXRestoreNotsEnd

\cs_new_protected:Nn \__stex_modules_restore_nots:n {
  \__stex_modules_restore_nots_i:n
}

\cs_new_protected:Nn \__stex_modules_restore_nots_i:n {
  \tl_if_eq:nnTF{#1}{\STEXRestoreNotsEnd}{
    \group_end:
  }{
    \__stex_modules_restore_nots_ii:nnnnn {#1}
  }
}

\cs_new_protected:Nn \__stex_modules_restore_nots_ii:nnnnn {
  \cs_set:Npn \l__stex_modules_tl {{#4}{#5}}
  \exp_args:NNe\use:nn\prop_gput:cnn{
    {c_stex_module_\l__stex_modules_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__stex_modules_tl
    }
  }
  \__stex_modules_restore_nots_i:n
}
\tl_new:N \l_stex_metatheory_uri
\cs_new_protected:Nn \__stex_modules_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}{
  \__stex_modules_set_metatheory:nn { #1 }{ #2 }
  \stex_smsmode_do:
}
\stex_sms_allow_escape:N \setmetatheory
\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}
\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}
\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:
}
\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:
}
\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}
\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}
\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}
\NewDocumentCommand \STEXexport {} {
  \ExplSyntaxOn
  \__stex_modules_export:n
}
\cs_new_protected:Nn \__stex_modules_export:n {
  \stex_ignore_spaces_and_pars:#1\ExplSyntaxOff
  \stex_module_add_code:n { \stex_ignore_spaces_and_pars:#1}
  \stex_smsmode_do:
}
\stex_deactivate_macro:Nn \STEXexport {module~environments}
\stex_sms_allow_escape:N \STEXexport
\stex_every_module:n {\stex_reactivate_macro:N \STEXexport}
\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}
\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 {
      \__stex_modules_activate_sym:n {#2}
    }
  }
}

\cs_new_protected:Nn \__stex_modules_activate_sym:n {
  \prop_map_inline:cn{c_stex_module_\l_stex_current_module_str _symbols_prop}{
    \str_if_eq:nnT{#1}{##1}{
      \__stex_modules_activate_i:nnnnnnnn ##2
    }
  }
}
\cs_new_protected:Nn \__stex_modules_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:
}
\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 {
    \__stex_modules_activate_not:nn{#1}{#2}
  }
}
\cs_generate_variant:Nn \stex_module_add_notation:nnnnn {eoeoo}

\cs_new_protected:Nn \__stex_modules_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 }
    }
  }
}
\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}
\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}
\cs_new_protected:Nn \stex_iterate_symbols:n {
  \stex_pseudogroup_with:nn{\__stex_iterate_sym_cs:nnnnnnnnN\stex_iterate_break:\stex_iterate_break:n}{
    \cs_set:Npn \__stex_iterate_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}{
        \__stex_iterate_sym_cs:nnnnnnnnN {##1} ####2
      }
    }
  }
}
\cs_new_protected:Nn \stex_iterate_symbols:nn {
  \seq_clear:N \l__stex_iterate_mods_seq
  \stex_pseudogroup_with:nn{\__stex_iterate_sym_cs:nnnnnnnnN}{
    \cs_set:Npn \__stex_iterate_sym_cs:nnnnnnnnN
    ##1 ##2 ##3 ##4 ##5 ##6 ##7 ##8 ##9 { #2 }
    \clist_map_function:nN {#1} \__stex_iterate_it_decl_i:n
  }
}

\cs_new_protected:Nn \__stex_iterate_it_decl_i:n {
  \seq_if_in:NnF \l__stex_iterate_mods_seq {#1} {
    \seq_put_left:Nn \l__stex_iterate_mods_seq {#1}
    \prop_map_inline:cn{c_stex_module_#1_morphisms_prop}{
      \__stex_iterate_it_decl_check:nnnn ##2
    }
    \prop_map_inline:cn{c_stex_module_#1_symbols_prop}{
      \__stex_iterate_sym_cs:nnnnnnnnN {#1} ##2
    }
  }
}
\cs_new_protected:Nn \__stex_iterate_it_decl_check:nnnn {
  \tl_if_empty:nT{#1}{
    \__stex_iterate_it_decl_i:n {#2}
  }
}
\cs_new_protected:Nn \stex_iterate_notations:nn {
  \seq_clear:N \l__stex_iterate_mods_seq
  \stex_pseudogroup_with:nn{\__stex_iterate_not_cs:nnnnn}{
    \cs_set:Npn \__stex_iterate_not_cs:nnnnn
    ##1 ##2 ##3 ##4 ##5 { #2 }
    \clist_map_function:nN {#1} \__stex_iterate_it_not_i:n
  }
}

\cs_new_protected:Nn \__stex_iterate_it_not_i:n {
  \seq_if_in:NnF \l__stex_iterate_mods_seq {#1} {
    \seq_put_left:Nn \l__stex_iterate_mods_seq {#1}
    \prop_map_inline:cn{c_stex_module_#1_notations_prop}{
      \__stex_iterate_not_cs:nnnnn ##2
    }
    \prop_map_inline:cn{c_stex_module_#1_morphisms_prop}{
      \__stex_iterate_it_not_check:nnnn ##2
    }
  }
}
\cs_new_protected:Nn \__stex_iterate_it_not_check:nnnn {
  \tl_if_empty:nT{#1}{
    \__stex_iterate_it_not_i:n {#2}
  }
}
\cs_new_protected:Nn \stex_iterate_morphisms:nn {
  \seq_clear:N \l__stex_iterate_mods_seq
  \bool_set_true:N \l__stex_iterate_continue_bool
  \cs_set:Npn \__stex_iterate_morphism_cs:nnnn ##1 ##2 ##3 ##4 ##5 {
    #2
    \bool_if:NT \l__stex_iterate_continue_bool {
      \str_if_eq:nnTF{##1}{[##2]}{
        \tl_put_right:Nn \l__stex_iterate_todo_tl {
          \__stex_iterate_iterate_morphism:nn{##5}{##2}
        }
      }{
        \tl_put_right:Nn \l__stex_iterate_todo_tl {
          \__stex_iterate_iterate_morphism:nn{##5 / ##1}{##2}
        }
      }
    }
  }
  \cs_set:Npn \stex_iterate_break:n ##1 {
    \bool_set_false:N \l__stex_iterate_continue_bool
    \prop_map_break:n{##1}
  }
  \__stex_iterate_iterate_morphism:nn{}{#1}
}

\cs_new_protected:Nn \__stex_iterate_iterate_morphism:nn {
  \tl_clear:N \l__stex_iterate_todo_tl
  \seq_if_in:NnF \l__stex_iterate_mods_seq {#1 #2}{
    \seq_put_right:Nn \l__stex_iterate_mods_seq {#1 #2}
    \prop_map_inline:cn{c_stex_module_#2_morphisms_prop}{
      \__stex_iterate_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__stex_iterate_continue_bool \l__stex_iterate_todo_tl
  }
}
\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:
}
\bool_new:N \l__stex_features_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__stex_features_implicit_bool
    \str_set:Nx \l_tmpa_str {[\l_stex_current_domain_str]}
  }{
    \bool_set_false:N \l__stex_features_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__stex_features_feature_str {#2}
  \str_set_eq:NN \l_stex_feature_name_str \l_tmpa_str
  \__stex_features_setup:
  \__stex_features_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 \__stex_features_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 \__stex_features_add_definiens:nn {
  \__stex_features_set_definiens_macros: #1\__stex_features_break:
  \_stex_assign_do:n{#2}
  #2
}
\cs_new_protected:Npn \__stex_features_set_definiens_macros: #1?#2?#3\__stex_features_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{\__stex_features_set_definiens_macros_i:nnnnnnn}{
    \prop_item:Nn \l_stex_morphism_symbols_prop {[#1?#2]/[#3]}
  }
}
\cs_new_protected:Nn \__stex_features_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
  \__stex_features_do_elaboration:
  \stex_if_do_html:TF{
    \end{stex_annotate_env}
  }\group_end:
}

\cs_new_protected:Nn \__stex_features_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
  \__stex_features_do_decls:
  \exp_args:No \__stex_features_do_morphisms:n \l_stex_current_domain_str
}

\cs_new_protected:Nn \__stex_features_rename_all: {

}

\cs_new:Npn \__stex_features_clean:nnw [#1] / #2 \_stex_end: {
  [#1]/[#2]
}

\cs_new_protected:Nn \__stex_features_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 {
        \__stex_features_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 {
    \__stex_features_total_check: ##1 ##2
  }
}

\cs_new_protected:Npn \__stex_features_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 \__stex_features_split_qm:w #1 ? #2 ? #3 { #3 }
\cs_new_protected:Nn \__stex_features_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 {
    \__stex_features_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__stex_features_tmp {
      \exp_args:Ne \stex_module_add_notation:nnnnn
      {\l_stex_current_module_str ? \exp_after:wN \use_ii:nn \l__stex_features_tmp}
    }{
      \exp_args:Ne \stex_module_add_notation:nnnnn
      {\l_stex_current_module_str ? \l_stex_feature_name_str
       / \__stex_features_split_qm:w ##1}
    }{##2}{##3}{##4}{##5}
  }
  \stex_module_add_morphism:ooox
    \l_stex_feature_name_str
    \l_stex_current_domain_str
    \l__stex_features_feature_str
    {\prop_map_function:NN \l_stex_morphism_renames_prop \__stex_features_rename:nn}
}

\cs_new:Nn \__stex_features_rename:nn{
  {#1}{\use_ii:nn#2}
}

\cs_new_protected:Npn \__stex_features_elab_check: [#1]/[#2] #3 {
  \prop_get:NnNTF \l_stex_morphism_renames_prop {#1?#2} \l__stex_features_tmp {
    \stex_debug:nn{morphisms}{Generating~\l__stex_features_tmp}
    \exp_after:wN \stex_module_add_symbol:nnnnnnnN \l__stex_features_tmp
  }{
    \bool_if:NTF \l__stex_features_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 \__stex_features_do_morphisms:n {
    \prop_map_inline:cn {c_stex_module_#1_morphisms_prop}{
      \__stex_features_do_morph:nnnn ##2
    }
}

\cs_new_protected:Nn \__stex_features_do_morph:nnnn {
    \tl_if_empty:nF{#3}{
      \seq_put_right:Nn \l_stex_morphism_morphisms_seq {{#1}{#2}{#3}}
    }
    \__stex_features_do_morphisms:n{#2}
}

\cs_new_protected:Npn \__stex_features_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: \__stex_features_do_for_list:
  \cs_set_eq:NN \_stex_add_definiens:nn \__stex_features_add_definiens:nn
}
\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\__stex_features_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 {
      \__stex_features_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 \__stex_features_renamed_check:nnnnn #1#2?#3?#4=#5#6 {
  \str_if_eq:nnTF{#1}{#5}{
    \exp_args:Nnx \use:nn{\__stex_features_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{\__stex_features_check_break:nnnnnnnnn{#2?#3}{#4}}{
        \prop_item:Nn \l_stex_morphism_symbols_prop {[#2?#3]/[#4]}
      }
    }
  }
}

\cs_new_protected:Npn \__stex_features_get_check:nnnn #1[#2]/[#3]#4 {
  \str_if_eq:nnTF{#1}{#3}{
    \__stex_features_check_break:nnnnnnnnn{#2}{#3}{#4}
  }{
    \str_if_eq:nnTF{#1}{#4}{
      \__stex_features_check_break:nnnnnnnnn{#2}{#3}{#4}
    }{
      \use_none:nnnnnn
    }
  }
}

\cs_new_protected:Nn \__stex_features_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}
  }
}
\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:
  }
}{}
\cs_new_protected:Nn \stex_import_module_uri:nn {
  \stex_debug:nn{importmodule}{URI:~>#1<~>#2<}
  \exp_args:NNnx \seq_set_split:Nnn \__stex_importmodule_seq ? { \tl_to_str:n{ #2 } }
  \seq_pop_right:NN \__stex_importmodule_seq \l_stex_import_name_str
  \str_set:Nx \l_stex_import_path_str { \seq_use:Nn \__stex_importmodule_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__stex_importmodule_path_seq \g_stex_current_file
        \stex_file_split_off_lang:NN \l__stex_importmodule_path_seq \l__stex_importmodule_path_seq
        \str_set:Nx \l_stex_import_path_str {
          \stex_file_use:N \l__stex_importmodule_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__stex_importmodule_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__stex_importmodule_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 } }
  }
}
\cs_new_protected:Npn \stex_import_require_module:nnn #1 {
  \tl_if_empty:nTF { #1 } {
    \str_clear:N \l__stex_importmodule_archive_str
    \str_set:Nn \l_stex_import_uri_str {file:}
    \__stex_importmodule_get_module:nnn {}
  }{
    \stex_require_archive:n { #1 }
    \str_set:Nx \l__stex_importmodule_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__stex_importmodule_str { \stex_file_use:N \c_stex_mathhub_file / #1 / source }
    \exp_args:No \__stex_importmodule_get_module:nnn \l__stex_importmodule_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__stex_importmodule_archive_str
    \str_set:Nn \l_stex_import_uri_str {file:}
    \__stex_importmodule_get_module_safe:nnn {}
  }{
    \stex_require_archive:n { #1 }
    \str_set:Nx \l__stex_importmodule_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__stex_importmodule_str { \stex_file_use:N \c_stex_mathhub_file / #1 / source }
    \exp_args:No \__stex_importmodule_get_module_safe:nnn \l__stex_importmodule_str
  }
}

\cs_new_protected:Nn \__stex_importmodule_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}
    }{
      \__stex_importmodule_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 \__stex_importmodule_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}
    }{
      \__stex_importmodule_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 \__stex_importmodule_get_module:nnn {
  \stex_debug:nn{importmodule}{Requiring~>[#1]#2?#3<}
  \__stex_importmodule_get_module_uri:nnn{#1}{#2}{#3}
  \stex_activate_module:o \l_stex_import_ns_str
}

\cs_new_protected:Nn \__stex_importmodule_get_module_safe:nnn {
  \stex_debug:nn{importmodule}{Requiring~>[#1]#2?#3<}
  \__stex_importmodule_get_module_uri_safe:nnn{#1}{#2}{#3}
}

\cs_new_protected:Nn \__stex_importmodule_get_from_file:nnn {
  \stex_file_resolve:Nx \l__stex_importmodule_seq { \tl_if_empty:nF{ #1 }{ #1 / } #2 }
  \str_set:Nx \l__stex_importmodule_str {\stex_file_use:N \l__stex_importmodule_seq}
  \stex_debug:nn{imports}{Looking~for~\l_stex_import_uri_str?#3...}
  \__stex_importmodule_check_file:nn{ /#3.tex }{
    \__stex_importmodule_check_file:nn{/#3.\l_stex_current_language_str .tex}{
      \__stex_importmodule_check_file:nn{/#3.en.tex}{
        \__stex_importmodule_check_file:nn{.tex}{
          \__stex_importmodule_check_file:nn{.\l_stex_current_language_str .tex}{
            \__stex_importmodule_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__stex_importmodule_str}{\stex_file_use:N \g_stex_current_file}{
      \stex_debug:nn{imports}{Skipping~current~file}
    }{
      \__stex_importmodule_load_file:n{#3}
    }
  }{
    \__stex_importmodule_load_file:n{#3}
  }
}
\cs_new_protected:Nn \__stex_importmodule_get_from_file_safe:nnn {
  \stex_file_resolve:Nx \l__stex_importmodule_seq { \tl_if_empty:nF{ #1 }{ #1 / } #2 }
  \str_set:Nx \l__stex_importmodule_str {\stex_file_use:N \l__stex_importmodule_seq}
  \stex_debug:nn{imports}{Looking~for~\l_stex_import_uri_str?#3...}
  \__stex_importmodule_check_file:nn{ /#3.tex }{
    \__stex_importmodule_check_file:nn{/#3.\l_stex_current_language_str .tex}{
      \__stex_importmodule_check_file:nn{/#3.en.tex}{
        \__stex_importmodule_check_file:nn{.tex}{
          \__stex_importmodule_check_file:nn{.\l_stex_current_language_str .tex}{
            \__stex_importmodule_check_file:nn{.en.tex}{
            }
          }
        }
      }
    }
  }
  \stex_if_smsmode:TF{
    \exp_args:NNo \exp_args:Nnx \str_if_eq:nnTF{\l__stex_importmodule_str}{\stex_file_use:N \g_stex_current_file}{
      \stex_debug:nn{imports}{Skipping~current~file}
    }{
      \IfFileExists{ \l__stex_importmodule_str }{
      \__stex_importmodule_load_file:n{#3}
      }{}
    }
  }{
    \IfFileExists{ \l__stex_importmodule_str }{
    \__stex_importmodule_load_file:n{#3}
    }{}
  }
}

\cs_new_protected:Nn \__stex_importmodule_load_file:n {
  \stex_file_in_smsmode:on \l__stex_importmodule_str {
    \str_if_empty:NF \l__stex_importmodule_archive_str {
      \stex_set_current_archive:n \l__stex_importmodule_archive_str
    }
    \stex_debug:nn{modules}{Loading~\l__stex_importmodule_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 \__stex_importmodule_check_file:nn #1 {
  \stex_debug:nn{imports}{Checking~ \l__stex_importmodule_str #1}
  \IfFileExists{ \l__stex_importmodule_str #1 }{
    \stex_debug:nn{imports}{Success}
    \str_set:Nx \l__stex_importmodule_str { \l__stex_importmodule_str #1 }
  }
}
\stex_new_stylable_cmd:nnnn{importmodule} { O{} m } {
  \__stex_importmodule_import_module:nn {#1}{#2}
  \stex_smsmode_do:
}{}
\stex_deactivate_macro:Nn \importmodule {module~environments}

\cs_new_protected:Nn \__stex_importmodule_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 \__stex_importmodule_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 \__stex_importmodule_import_module:nn \__stex_importmodule_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}
\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__stex_morphisms_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}{
      \__stex_morphisms_do_morph_assign:nnn{##1}{##2}{##4}
    }{
      \stex_str_if_ends_with:nnT{##2}{#1}{
        \__stex_morphisms_do_morph_assign:nnn{##1}{##2}{##4}
      }
    }
  }
  \str_if_empty:NT \l__stex_morphisms_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__stex_morphisms_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__stex_morphisms_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 \__stex_morphisms_do_morph_assign:nnn {
  \stex_iterate_break:n{
    \str_set:Nx \l__stex_morphisms_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}
\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}
\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}
\cs_new_protected:Nn \__stex_morphisms_parse_assign:n {
  \str_clear:N \l__stex_morphisms_name_str
  \str_clear:N \l__stex_morphisms_newname_str
  \tl_clear:N \l__stex_morphisms_ass_tl
  \stex_debug:nn{morphisms}{Parsing~#1}
  \exp_args:NNe \seq_set_split:Nnn \l__stex_morphisms_seq {\tl_to_str:n{@}} {#1}
  \int_compare:nNnTF {\seq_count:N \l__stex_morphisms_seq} = 1 {
    \stex_debug:nn{morphisms}{No~@}
    \seq_pop_left:NN \l__stex_morphisms_seq \l__stex_morphisms_next_tl
  }{
    \seq_pop_left:NN \l__stex_morphisms_seq \l__stex_morphisms_name_str
    \stex_debug:nn{morphisms}{Name:~\l__stex_morphisms_name_str}
    \exp_args:NNo \str_set:Nn \l__stex_morphisms_name_str \l__stex_morphisms_name_str
    \tl_set:Nx \l__stex_morphisms_next_tl {\seq_use:Nn \l__stex_morphisms_seq @}
  }
  \exp_args:NNNo \seq_set_split:Nnn \l__stex_morphisms_seq = \l__stex_morphisms_next_tl
  \str_if_empty:NTF \l__stex_morphisms_name_str {
    \seq_pop_left:NN \l__stex_morphisms_seq \l__stex_morphisms_name_str
    \exp_args:NNo \str_set:Nn \l__stex_morphisms_name_str \l__stex_morphisms_name_str
    \tl_set:Nx \l__stex_morphisms_ass_tl {\seq_use:Nn \l__stex_morphisms_seq =}
  }{
    \seq_pop_left:NN \l__stex_morphisms_seq \l__stex_morphisms_newname_str
    \exp_args:NNo \str_set:Nn \l__stex_morphisms_newname_str \l__stex_morphisms_newname_str
    \tl_set:Nx \l__stex_morphisms_ass_tl {\seq_use:Nn \l__stex_morphisms_seq =}
  }
  \__stex_morphisms_do_parsed_assign:
}

\cs_new_protected:Nn \__stex_morphisms_do_parsed_assign: {
  \exp_args:No \stex_get_in_morphism:n \l__stex_morphisms_name_str
  \str_if_empty:NF \l__stex_morphisms_newname_str {
    \exp_after:wN \__stex_morphisms_do_parsed_newname: \l__stex_morphisms_newname_str \__stex_morphisms_end:
  }
  \tl_if_empty:NF \l__stex_morphisms_ass_tl {
    \exp_args:No \_stex_assign_do:n \l__stex_morphisms_ass_tl
  }
}

\cs_new_protected:Nn \__stex_morphisms_do_parsed_newname: {
  \peek_charcode:NTF [ {
    \__stex_morphisms_do_parsed_newname:w
  }{
    \__stex_morphisms_do_parsed_newname:w []
  }
}

\cs_new_protected:Npn \__stex_morphisms_do_parsed_newname:w [#1] #2 \__stex_morphisms_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}\__stex_morphisms_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}\__stex_morphisms_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}\__stex_morphisms_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
\stex_if_html_backend:TF {
  \prg_new_conditional:Nnn \stex_if_check_terms: {p, T, F, TF} {
    \prg_return_false:
  }
}{
  \stex_get_env:Nn\__stex_symdecl_env_str{STEX_CHECKTERMS}
  \str_if_empty:NF\__stex_symdecl_env_str{
    \exp_args:No \str_if_eq:nnF \__stex_symdecl_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:
    }
  }
}
\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 {}
}
\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}
\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
%% \begin{macro}{\stex_symdecl_top:n}
\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:
  \__stex_symdecl_add_decl:
  \stex_if_do_html:T {
    \_stex_symdecl_html:
  }
}

\cs_new_protected:Nn \__stex_symdecl_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__stex_symdecl_cs
        \cs_set:Npn \l_stex_get_symbol_arity_int} \l_stex_key_return_tl
        \tl_set:Nx \l__stex_symdecl_args_tl {\_stex_map_args:N \_stex_return_args:nn}
        $\stex_annotate:nn{shtml:returntype={}}{
          \exp_after:wN \l__stex_symdecl_cs \l__stex_symdecl_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}
}
\cs_new_protected:Nn \stex_symdecl_do: {
  \_stex_do_deprecation:n \l_stex_key_name_str
  \__stex_symdecl_parse_arity:
  \__stex_symdecl_do_args:
}

\int_new:N \l_stex_assoc_args_count

\cs_new_protected:Nn \__stex_symdecl_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 \__stex_symdecl_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}
    }
  }
}
\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:
  }
}

\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{
    \__stex_symdecl_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 \__stex_symdecl_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}
}
\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__stex_symdecl_cs { #1 }
    % command name
    \exp_args:Ne \tl_if_empty:nTF { \cs_argument_spec:N \l__stex_symdecl_cs }{
      % ...that takes no arguments
      \exp_args:Ne \cs_if_eq:NNTF {\tl_head:N \l__stex_symdecl_cs}
        \_stex_invoke_symbol:nnnnnnnN
        \__stex_symdecl_get_symbol_from_cs:
        {\__stex_symdecl_get_symbol_from_string:n { #1 }}
    }{
      \__stex_symdecl_get_symbol_from_string:n { #1 }
    }
  }{
    \__stex_symdecl_get_symbol_from_string:n { #1 }
  }
}

\int_new:N \l_stex_get_symbol_arity_int
\cs_new_protected:Nn \__stex_symdecl_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__stex_symdecl_cs
  }
}

\cs_new_protected:Nn \__stex_symdecl_get_symbol_from_string:n {
  \stex_debug:nn{symbols}{Getting~from~string~#1...}
  \seq_set_split:Nnn \l__stex_symdecl_seq ? {#1}
  \seq_pop_right:NN \l__stex_symdecl_seq \l__stex_symdecl_name
  \seq_if_empty:NTF \l__stex_symdecl_seq {
    \exp_args:No \__stex_symdecl_get_from_one_string:n {#1}
  }{
    \exp_args:NNe \exp_args:Nno \__stex_symdecl_get_symbol_from_modules:nn {
      \seq_use:Nn \l__stex_symdecl_seq ?
    } \l__stex_symdecl_name
  }
}

\cs_new_protected:Nn \__stex_symdecl_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}}
    }{
      \__stex_symdecl_sym_i_finish:nnnnnnnN{#1}{#4}
    }{
      \__stex_symdecl_sym_i_gobble:nnnnnn
    }
}
\cs_new_protected:Nn \__stex_symdecl_sym_i_gobble:nnnnnn {}

\cs_new_protected:Nn \__stex_symdecl_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 \__stex_symdecl_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}{
        \__stex_symdecl_sym_from_str_i:nnnn{##1}{#2} ####2
      }
    }
  }
}

\cs_new_protected:Nn \__stex_symdecl_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}
        }
    }
  }
}
\cs_new:Nn \_stex_map_args:N {
  \tl_if_empty:NF \l_stex_get_symbol_args_tl {
    \exp_after:wN \__stex_notations_map_args_i:w \exp_after:wN
    #1 \l_stex_get_symbol_args_tl \__stex_notations_args_end:
  }
}
\cs_new:Npn \__stex_notations_map_args_i:w #1 #2 #3 #4 \__stex_notations_args_end: {
  #1 #2 #3
  \tl_if_empty:nF{#4}{
    \__stex_notations_map_args_i:w #1 #4 \__stex_notations_args_end:
  }
}

\cs_new:Nn \_stex_map_notation_args:N {
  \tl_if_empty:NF \l_stex_notation_args_tl {
    \exp_after:wN \__stex_notations_map_args_ii:w \exp_after:wN
    #1 \l_stex_get_symbol_args_tl \__stex_notations_args_end:
  }
}
\cs_new:Npn \__stex_notations_map_args_ii:w #1 #2 #3 #4 #5 #6 \__stex_notations_args_end: {
  #1 #2 #3 #4 #5
  \tl_if_empty:nF{#6}{
    \__stex_notations_map_args_ii:w #1 #6 \__stex_notations_args_end:
  }
}
\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}
\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:
    \__stex_notations_styledefs:
    \stex_style_apply:
    \group_end:
  }
  \stex_smsmode_do:
}{}

\cs_new_protected:Nn \__stex_notations_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
\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__stex_notations_precs_seq
  \tl_clear:N \l_stex_notation_args_tl
  \int_compare:nNnTF \l_stex_get_symbol_arity_int = 0 {
    \__stex_notations_const_precs:
    \tl_if_empty:NT \l_stex_key_op_tl {
      \tl_set:Nn \l_stex_key_op_tl { \maincomp{#1} }
    }
  }{
    \__stex_notations_fun_precs:
    \str_set:Nn \l__stex_notations_missing_str {#1}
    \tl_clear:N \l__stex_notations_missing_tl
    \_stex_map_args:N \__stex_notations_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__stex_notations_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__stex_notations_missing_tl }
      }
  }
  \stex_debug:nn{notation}{Notation:~\meaning\l_stex_notation_macrocode_cs}
}

\cs_new_protected:Nn \__stex_notations_const_precs: {
  \str_if_empty:NTF \l_stex_key_prec_str {
    \tl_set:No \l__stex_notations_opprec_tl { \neginfprec }
  }{
    \str_if_eq:onTF \l_stex_key_prec_str {nobrackets}{
      \tl_set:No \l__stex_notations_opprec_tl { \neginfprec }
    }{
      \tl_set_eq:NN \l__stex_notations_opprec_tl \l_stex_key_prec_str
    }
  }
}

\cs_new_protected:Nn \__stex_notations_fun_precs: {
  \str_if_empty:NTF \l_stex_key_prec_str {
    \tl_set:No \l__stex_notations_opprec_tl { \neginfprec }
  }{
    \str_if_eq:onTF \l_stex_key_prec_str {nobrackets}{
      \tl_set:No \l__stex_notations_opprec_tl { \neginfprec }
    }{
      \tl_set_eq:NN \l__stex_notations_opprec_tl \l_stex_key_prec_str
    }
  }
  \str_if_empty:NTF \l_stex_key_prec_str {
    \tl_set:Nn \l__stex_notations_opprec_tl { 0 }
    \int_step_inline:nn \l_stex_get_symbol_arity_int {
      \seq_put_right:Nn \l__stex_notations_precs_seq {0}
    }
  }{
    \str_if_eq:onTF \l_stex_key_prec_str {nobrackets}{
      \stex_debug:nn{notation}{No~brackets}
      \tl_set:No \l__stex_notations_opprec_tl { \neginfprec }
      \int_step_inline:nn \l_stex_get_symbol_arity_int {
        \exp_args:NNo \seq_put_right:Nn \l__stex_notations_precs_seq \infprec
      }
    }\__stex_notations_parse_precs:
  }
  \__stex_notations_do_argnames:
}

\cs_new_protected:Nn \__stex_notations_parse_precs: {
  \stex_debug:nn{notation}{parsing~precedence~\l_stex_key_prec_str}
  \seq_set_split:NnV \l__stex_notations_seq ; \l_stex_key_prec_str
  \seq_pop_left:NNTF \l__stex_notations_seq \l__stex_notations_str {
    \tl_set_eq:NN \l__stex_notations_opprec_tl \l__stex_notations_str
    \seq_pop_left:NNT \l__stex_notations_seq \l__stex_notations_str {
      \exp_args:NNo \seq_set_split:NnV \l__stex_notations_seq
        {\tl_to_str:n{x}} \l__stex_notations_str
    }
  }{
    \tl_set:No \l__stex_notations_opprec_tl { 0 }
  }
  \int_step_inline:nn \l_stex_get_symbol_arity_int {
    \seq_pop_left:NNTF \l__stex_notations_seq \l__stex_notations_str {
      \seq_put_right:No \l__stex_notations_precs_seq \l__stex_notations_str
    }{
      \seq_put_right:No \l__stex_notations_precs_seq \l__stex_notations_opprec_tl
    }
  }
}

\cs_new_protected:Nn \__stex_notations_do_argnames: {
  \tl_clear:N \l_stex_notation_args_tl
  \_stex_map_args:N \__stex_notations_do_argname:nn
}

\cs_new_protected:Nn \__stex_notations_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__stex_notations_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__stex_notations_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 \__stex_notations_add_missing_args:nn {
  \exp_args:NNe \str_if_in:NnF \l__stex_notations_missing_str {\c_hash_str\c_hash_str#1}{
    \tl_put_right:Nn \l__stex_notations_missing_tl{\STEXinvisible{## #1}}
  }
}
\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__stex_notations_opprec_tl},
    shtml:argprecs={\seq_use:Nn \l__stex_notations_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 \__stex_notations_map_cs: ####1 { ##2 }
      \stex_annotate:nn{shtml:argmap={}}{
        \__stex_notations_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 \__stex_notations_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 \__stex_notations_make_arg_html:nn {
    {
      \stex_annotate:nn{shtml:argnum=#1}{x}
    }
}

\cs_new:Nn \_stex_notation_make_args: {
  \_stex_map_notation_args:N \__stex_notations_make_arg:nnnn
}

\cs_new:Nn \__stex_notations_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}}
  }
}
\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
    }
  }
}
\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:
}{}
\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
\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__stex_notations_args_tl
  }{
    \__stex_notations_make_name:
    \tl_set_eq:NN \l_stex_get_symbol_args_tl \l_stex_current_args_tl
    \tl_set:Nx \l__stex_notations_args_tl {
      \_stex_map_args:N \__stex_notations_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__stex_notations_args_tl}{
    \exp_args:No \exp_not:n \l_stex_default_notation
  }}
}

\cs_new:Nn \__stex_notations_augment_arg:nn {
  #1#2{0}{}
}

\cs_new_protected:Nn \__stex_notations_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__stex_notations_name_str
  \exp_args:NNNo \seq_set_split:Nnn \l_tmpa_seq / \l__stex_notations_name_str
  \seq_pop_right:NN \l_tmpa_seq \l__stex_notations_name_str
}

\cs_new_protected:Nn \stex_do_default_notation_op: {
  \__stex_notations_make_name:
  \tl_set:Nx \l_stex_default_notation {\exp_not:N \maincomp{ \exp_not:N \mathrm {\l__stex_notations_name_str} }}
}

\cs_new_protected:Npn \STEXInternalNotation #1 #2 #3 #4 #5 #6 {
  \__stex_notations_process_notation:nnnnnn{#1}{#2}{#3}{#4}{#5}{
    \l__stex_notations_code_tl
    #6
  }
}

\cs_new_protected:Npn \__stex_notations_process_notation:nnnnnn #1 #2 #3 #4 {
  \tl_if_empty:nTF{#4}{
    \__stex_notations_simple:nnnnn{#1}{#2}{#3}
  }{
    \__stex_notations_complex:nnnnnn{#1}{#2}{#3}{#4}
  }
}

\cs_new_protected:Nn \__stex_notations_simple:nnnnn {
  \stex_debug:nn{Notation~code}{\tl_to_str:n{#4}}
  \tl_set:Nn \l__stex_notations_code_tl {
    \cs_set:Npn \l__stex_notations_cs {
      \_stex_maybe_brackets:nn{#2}{
        \_stex_term_oms_or_omv:nnn{#1}{#3}{#4}
      }
    }
    \l__stex_notations_cs
  }
  \stex_debug:nn{Here:Notation}{\meaning \l__stex_notations_code_tl }
  #5
}

\cs_new_protected:Nn \__stex_notations_complex:nnnnnn {
  \stex_debug:nn{Notation~code}{\tl_to_str:n{#5}}
  \int_zero:N \l_tmpa_int
  \tl_set:Nn \l__stex_notations_pre_tl {\cs_set_eq:NN \_stex_term_oma_or_omb:nnn \_stex_term_oma:nnn}
  \tl_set:Nn \l__stex_notations_code_tl {
    \cs_generate_from_arg_count:NNnn \l__stex_notations_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__stex_notations_cs
  }
  \tl_set:Nn \l__stex_notations_after_tl{
    \exp_args:NNo
    \tl_put_left:Nn \l__stex_notations_code_tl \l__stex_notations_pre_tl
    \tl_put_left:Nx \l__stex_notations_code_tl {
      \int_set:Nn \l_tmpa_int {\int_use:N \l_tmpa_int}
    }
    \stex_debug:nn{Here:Notation}{\meaning \l__stex_notations_code_tl }
    #6
  }
  \__stex_notations_parse_notation_args:nnnnw #4 \__stex_notations_args_end:
}

\cs_new_protected:Npn \__stex_notations_parse_notation_args:nnnnw #1 #2 #3 #4 #5 \__stex_notations_args_end: {
  \tl_if_empty:nTF{#5}{
    \__stex_notations_add_last:nnnnn{#1}{#2}{#3}{#4}
  }{
    \__stex_notations_add_next:nnnnnn{#1}{#2}{#3}{#4}{#5}
  }
}

\cs_new_protected:Nn \__stex_notations_add_next:nnnnnn {
  \__stex_notations_add:nnnnn{#1}{#2}{#3}{#4}{#6}
  \__stex_notations_parse_notation_args:nnnnw #5 \__stex_notations_args_end:
}

\cs_new_protected:Nn \__stex_notations_add_last:nnnnn {
  \__stex_notations_add:nnnnn{#1}{#2}{#3}{#4}{#5}
  \l__stex_notations_after_tl
}

\cs_new_protected:Nn \__stex_notations_add:nnnnn {
  \int_incr:N \l_tmpa_int
  \str_case:nn{#2}{
    i {
      \tl_put_right:Nn \l__stex_notations_code_tl {
        {\_stex_term_arg:nnnnn{#1}{#2}{#3}{#4}{#5}}
      }
    }
    b {
      \tl_set:Nn \l__stex_notations_pre_tl {
        \cs_set_eq:NN \_stex_term_oma_or_omb:nnn \_stex_term_omb:nnn
      }
      \tl_put_right:Nn \l__stex_notations_code_tl {
        {\_stex_term_arg:nnnnn{#1}{#2}{#3}{#4}{#5}}
      }
    }
    a {
      \tl_put_right:Nn \l__stex_notations_code_tl {
        {\_stex_term_arg_aB:nnnnn{#1}{#2}{#3}{#4}{#5}}
      }
    }
    B  {
      \tl_set:Nn \l__stex_notations_pre_tl {
        \cs_set_eq:NN \_stex_term_oma_or_omb:nnn \_stex_term_omb:nnn
      }
      \tl_put_right:Nn \l__stex_notations_code_tl {
        {\_stex_term_arg_aB:nnnnn{#1}{#2}{#3}{#4}{#5}}
      }
    }
  }
}
\cs_new_protected:Nn \__stex_notations_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 {
  \__stex_notations_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
  }
}
\cs_new_protected:Npn \argmap #1 #2 #3 {
  \__stex_notations_check_aB_arg:Nn\argmap{#1}
  \stex_pseudogroup_with:nn{
    \_stex_term_do_aB_clist:
    \__stex_notations_map_cs:
  }{
    \cs_set:Npn \__stex_notations_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 { \__stex_notations_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
  }
}
\int_new:N \l__stex_notations_clist_count_int
\cs_new_protected:Npn \argarraymap #1 #2 #3 #4 {
  \__stex_notations_check_aB_arg:Nn\argarraymap{#1}
  \stex_pseudogroup_with:nn{
    \_stex_term_do_aB_clist:
    \__stex_notations_map_cs:
  }{
    \cs_set:Npn \__stex_notations_map_cs: ##1 { #3 }
    \int_set:Nn \l__stex_notations_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__stex_notations_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 { \__stex_notations_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
  }
}

\tl_new:N \l_stex_variables_prop
\bool_new:N \l__stex_vars_bind_bool
\cs_new_protected:Nn \_stex_variable:nnnnnnnN {}
\stex_keys_define:nnnn{vardef}{
  \bool_set_false:N \l__stex_vars_bind_bool
}{
  bind  .bool_set:N  = \l__stex_vars_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:
  \__stex_vars_add:
  \__stex_vars_macro:
  \stex_if_do_html:T \__stex_vars_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 \__stex_vars_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 \__stex_vars_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 \__stex_vars_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__stex_vars_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__stex_vars_cs
          \cs_set:Npn \l_stex_get_symbol_arity_int} \l_stex_key_return_tl
          \tl_set:Nx \l__stex_vars_args_tl {\_stex_map_args:N \_stex_return_args:nn}
          $\stex_annotate:nn{shtml:returntype={}}{
            \exp_after:wN \l__stex_vars_cs \l__stex_vars_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
  }
}
\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
    }
  }
}
\cs_new_protected:Nn \__stex_vars_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 \__stex_vars_get_var:n {
  \prop_map_inline:Nn \l_stex_variables_prop {
    \__stex_vars_check_var:nnnnnnnnN {#1} ##2
  }
}

\cs_new_protected:Nn \__stex_vars_check_var:nnnnnnnnN {
  \str_if_eq:nnTF{#1}{#2}{
    \prop_map_break:n{\__stex_vars_set_vars:nnnnnnN {#3}{#4}{#5}{#6}{#7}{#8}#9}
  }{
    \str_if_eq:nnT{#1}{#3}{
      \prop_map_break:n{\__stex_vars_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
  \__stex_vars_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
  \__stex_vars_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}
  }
}
\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:
}
\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__stex_seqs_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 \__stex_seqs_html:
  \stex_if_check_terms:T \__stex_seqs_check_terms:
  \__stex_seqs_add:
  \__stex_seqs_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{}}{
      \__stex_seqs_make_args:
    }$
  }
  \stex_style_apply:
  \group_end:\ignorespaces
}{}

\cs_new_protected:Nn \__stex_seqs_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_seqs_range_clist}
    {\exp_args:No \exp_not:n \l_stex_key_return_tl}
    \stex_invoke_sequence:
  }
}

\cs_new_protected:Nn \__stex_seqs_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_seqs_range_clist}
      {\exp_args:No \exp_not:n \l_stex_key_return_tl}
      \stex_invoke_sequence:
  }
}

\cs_new_protected:Nn \__stex_seqs_make_args: { \TODO }
\cs_new_protected:Nn \__stex_seqs_check_terms: { \TODO }

\cs_new_protected:Nn \__stex_seqs_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__stex_seqs_cs
          \cs_set:Npn \l_stex_get_symbol_arity_int} \l_stex_key_return_tl
          \tl_set:Nx \l__stex_seqs_args_tl {\_stex_map_args:N \_stex_return_args:nn}
          \stex_annotate:nn{shtml:returntype={}}{
            $\exp_after:wN \l__stex_seqs_cs \l__stex_seqs_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}
}
\cs_new_protected:Nn \stex_invoke_sequence: {
  \peek_charcode_remove:NTF ! {
    \peek_charcode:NTF [ \__stex_seqs_do_op:w { \__stex_seqs_do_op:w [] }
  }\__stex_seqs_do_first:
}

\cs_new_protected:Npn \__stex_seqs_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:
  }{
    \__stex_seqs_get_index_notation:n{#1}
    \peek_charcode:NTF [ \__stex_seqs_doop_range:w { \__stex_seqs_doop_range:w[] }
  }
}

\cs_new_protected:Npn \__stex_seqs_doop_range:w [#1] {
  \bool_set_true:N \l_stex_allow_semantic_bool
  \clist_clear:N \l__stex_seqs_clist
  \clist_map_function:NN \l_stex_current_type_tl \__stex_seqs_doop_arg:n
    \stex_annotate:nn{
      shtml:term=OMV,
      shtml:head={\l_stex_current_symbol_str},
      shtml:notationid={}
    }{
      \l__stex_seqs_clist
    }
    \group_end:
}

\cs_new_protected:Nn \__stex_seqs_doop_arg:n {
  \tl_if_eq:nnTF{#1}{\ellipses}{
    \clist_put_right:Nn \l__stex_seqs_clist {
        \ellipses
    }
  }{
    \clist_put_right:Nn \l__stex_seqs_clist {
      \exp_args:No \str_if_eq:nnTF \l_stex_current_arity_str {1}{
        \group_begin:
          \l__stex_seqs_cs \group_end: {#1}

      }{
        \group_begin:
          \l__stex_seqs_cs \group_end: #1
      }
    }
  }
}

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

\cs_new:Nn \__stex_seqs_do_first_arg:n {{\exp_not:n{## #1}}}

\cs_new_protected:Nn \__stex_seqs_do_first: {
  \exp_args:Nnx \use:nn{
  \cs_generate_from_arg_count:NNnn \l__stex_seqs_cs \cs_set:Npn
  \l_stex_current_arity_str} {{
    \tl_set:Nn \exp_not:N \l__stex_seqs_first_args_tl {
      \int_step_function:nN \l_stex_current_arity_str \__stex_seqs_do_first_arg:n
    }
    \exp_not:N \__stex_seqs_do_first_next:
  }}
  \l__stex_seqs_cs
}

\cs_new_protected:Nn \__stex_seqs_do_first_next: {
  \peek_charcode_remove:NTF ! {
    \peek_charcode:NTF [ \__stex_seqs_do_one:w {\__stex_seqs_do_one:w []}
  }{
    \peek_charcode:NTF [ \__stex_seqs_do_all:w {\__stex_seqs_do_all:w []}
  }
}

\cs_new_protected:Npn \__stex_seqs_do_one:w [#1] {
  \__stex_seqs_get_index_notation:n{#1}
  \stex_debug:nn{HERE~seq~one}{\meaning\l__stex_seqs_cs^^J\meaning\l__stex_seqs_first_args_tl}
  \exp_args:Nno\use:nn{\l__stex_seqs_cs\group_end:}\l__stex_seqs_first_args_tl
}

\cs_new_protected:Npn \__stex_seqs_do_all:w [#1] {
  \stex_debug:nn{HERE~seq~all}{\meaning\l__stex_seqs_first_args_tl}
  \exp_args:Nno\use:nn{\_stex_invoke_notation:w [#1]}\l__stex_seqs_first_args_tl
}
\cs_new_protected:Npn \seqmap #1 #2 {
  \symuse{Metatheory?sequence~expression}{\seqmap{#1}{#2}}%\l_tmpa_tl {#2}
}
\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
}
\tl_new:N \l__stex_expr_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__stex_expr_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__stex_expr_reset_tl {
        \exp_args:No \exp_not:n \l__stex_expr_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__stex_expr_reset_tl }
    \exp_not:N \l_stex_every_symbol_tl
    \exp_not:n{ #1 }
  }
}
\cs_generate_variant:Nn \_stex_next_symbol:n {e}
\cs_new_protected:Npn \STEXinvisible #1 {
  \stex_annotate_invisible:n { #1 }
}
\cs_new_protected:Nn \_stex_invoke_symbol:nnnnnnnN {
  \bool_if:NTF \l_stex_allow_semantic_bool{
    \stex_if_html_backend:T{\ifvmode\indent\fi}
    \__stex_expr_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 \__stex_expr_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
}
\cs_new_protected:Nn \_stex_invoke_variable:nnnnnnN {
  \bool_if:NTF \l_stex_allow_semantic_bool{
    \stex_if_html_backend:T{\ifvmode\indent\fi}
    \__stex_expr_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}
  }
}
\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
}
\cs_new_protected:Nn \stex_invoke_symbol: {
  \stex_debug:nn{expressions}{Invoking~\l_stex_current_symbol_str}
  \mode_if_math:TF \__stex_expr_invoke_math: \__stex_expr_invoke_text:
}

\cs_new_protected:Nn \__stex_expr_invoke_text: {
  \stex_debug:nn{expressions}{text~mode}
  \peek_charcode_remove:NTF ! \__stex_expr_invoke_op_custom:n \__stex_expr_invoke_custom:n
}

\cs_new_protected:Nn \__stex_expr_invoke_math: {
  \stex_debug:nn{expressions}{math~mode}
  \peek_charcode_remove:NTF ! {
    % operator
    \peek_charcode_remove:NTF * \__stex_expr_invoke_op_custom:n {
      % op notation
      \peek_charcode:NTF [ \__stex_expr_invoke_op_notation:w {
        \__stex_expr_invoke_op_notation:w []
      }
    }
  }{
    \peek_charcode_remove:NTF * \__stex_expr_invoke_custom:n {
      % normal
      \peek_charcode:NTF [ \_stex_invoke_notation:w {
        \_stex_invoke_notation:w []
      }
    }
  }
}
\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
      \__stex_expr_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
      \__stex_expr_invoke_return_maybe:n
      \exp_after:wN
      {\l_stex_default_notation {}}
    }
  }
}

\cs_new_protected:Npn \__stex_expr_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:
    }
  }
}
\cs_new_protected:Nn \__stex_expr_invoke_return_maybe:n {
  \tl_clear:N \l__stex_expr_return_args_tl
  \tl_set:Nn \l__stex_expr_return_this_tl {#1}
  \exp_args:Nnx \use:n {
  \cs_generate_from_arg_count:NNnn \__stex_expr_ret_cs
    \cs_set:Npn \l_stex_current_arity_str } {
      \int_step_function:nN \l_stex_current_arity_str \__stex_expr_return_arg:n
      \__stex_expr_invoke_return_next:
    }
  \__stex_expr_ret_cs
}

\cs_new:Nn \__stex_expr_return_arg:n {
  \tl_put_right:Nn \exp_not:N \l__stex_expr_return_args_tl {{#### #1}}
}

\cs_new_protected:Nn \__stex_expr_invoke_return_next: {
  \peek_charcode_remove:NTF ! {
    \exp_after:wN \l__stex_expr_return_this_tl \l__stex_expr_return_args_tl \group_end:
  }\__stex_expr_invoke_return:
}

\cs_new_protected:Nn \__stex_expr_invoke_return: {
  \tl_set:Nx \l__stex_expr_return_this_tl {
    \__stex_expr_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__stex_expr_return_this_tl \l__stex_expr_return_args_tl
      }
    }
  }
  \stex_debug:nn{return}{Notation:~\meaning\l__stex_expr_return_this_tl}
  \tl_put_left:Nx \l__stex_expr_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 \__stex_expr_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\__stex_expr_ret_cs^^J
    \meaning\l__stex_expr_return_this_tl^^J
    \exp_args:No \exp_not:n \l__stex_expr_return_args_tl^^J
  }
  \exp_args:Nnx \use:nn {
    \exp_after:wN \group_end: \__stex_expr_ret_cs
  }{
    \exp_args:No \exp_not:n \l__stex_expr_return_args_tl
    {
      \exp_args:No \exp_not:n \l__stex_expr_return_this_tl
      \group_end:
    }
  }
}

\cs_new_protected:Nn \__stex_expr_return_notation:n {
  \tl_if_empty:NTF \l_stex_return_notation_tl { #1 }{
    \l_stex_return_notation_tl
  }
}

\cs_new_protected:Nn \__stex_expr_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__stex_expr_arg_counter_int
\cs_new_protected:Nn \__stex_expr_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__stex_expr_customs_prop
    \seq_gclear:N \l__stex_expr_customs_seq
    \int_gzero:N \l__stex_expr_arg_counter_int
    \tl_if_empty:NF \l_stex_current_args_tl {
      \exp_after:wN \__stex_expr_add_prop_arg:nnw \l_stex_current_args_tl \_stex_args_end:
      \cs_set_eq:NN \arg \__stex_expr_arg:n
    }
    \tl_set_eq:NN \l_stex_get_symbol_args_tl \l_stex_current_args_tl
    \cs_set_eq:NN \__stex_expr_do_ab_next:nnn \_stex_term_oma:nnn
    \_stex_map_args:N \__stex_expr_check_b:nn
    \__stex_expr_do_ab_next:nnn{}{}{#1}
  }{
    \prop_if_exist:NT \l__stex_expr_customs_prop {
      \prop_gset_from_keyval:Nn \exp_not:N \l__stex_expr_customs_prop {
        \prop_to_keyval:N \l__stex_expr_customs_prop
      }
    }
    \int_gset:Nn \l__stex_expr_arg_counter_int { \int_use:N \l__stex_expr_arg_counter_int}
    \seq_if_exist:NT \l__stex_expr_customs_seq {
      \seq_gset_split:Nnn \exp_not:N \l__stex_expr_customs_seq , {
        \seq_use:Nn \l__stex_expr_customs_seq ,
      }
    }
  }
  % TODO check that all arguments are present
  \group_end:
}

\cs_new_protected:Npn \__stex_expr_add_prop_arg:nnw #1 #2 #3\_stex_args_end: {
  \prop_gput:Nnn \l__stex_expr_customs_prop {#1} {}
  \seq_gput_right:Nn \l__stex_expr_customs_seq {#2}
  \tl_if_empty:nF{#3}{\__stex_expr_add_prop_arg:nnw #3 \_stex_args_end:}
}

\cs_new:Nn \__stex_expr_check_b:nn {
  \str_case:nn #2 {
    b {\cs_set_eq:NN \__stex_expr_do_ab_next:nnn \_stex_term_omb:nnn}
    B {\cs_set_eq:NN \__stex_expr_do_ab_next:nnn \_stex_term_omb:nnn}
  }
}

\NewDocumentCommand \__stex_expr_arg:n {s O{} m} {
  \IfBooleanTF #1 {
    \stex_annotate_invisible:n{
      \__stex_expr_arg_inner:nn{#2}{#3}
    }
  }{
    \__stex_expr_arg_inner:nn{#2}{#3}
  }
}

\cs_new_protected:Nn \__stex_expr_arg_inner:nn {
  \tl_if_empty:nTF{#1}{
    \int_gincr:N \l__stex_expr_arg_counter_int
    \exp_args:Ne \__stex_expr_check:nTF{ \int_use:N \l__stex_expr_arg_counter_int }{
      \__stex_expr_arg_do:oon \l_tmpa_tl \l_tmpb_tl
    }{
      \__stex_expr_arg_inner:nn{}
    }{ #2 }
  }{
    \__stex_expr_check:nTF {#1}{
      \__stex_expr_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__stex_expr_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__stex_expr_customs_prop {#1}{
            \l_tmpa_tl X
          }
          \tl_set:Nx \l_tmpa_tl { #1 \int_eval:n {\tl_count:N \l_tmpa_tl + 1} }
        }
      }{
        \__stex_expr_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 \__stex_expr_check:n {TF} {
  \exp_args:NNe \prop_get:NnNTF \l__stex_expr_customs_prop {#1} \l_tmpa_tl {
    \tl_set:Nx \l_tmpb_tl {\seq_item:Nn \l__stex_expr_customs_seq {#1} }
    \tl_if_empty:NTF \l_tmpa_tl {
      \exp_args:NNe \prop_gput:Nnn \l__stex_expr_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:
  }
}

\cs_new_protected:Nn \__stex_expr_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 \__stex_expr_arg_do:nnn {oon}
\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 }
  }
}
\tl_set:Nn \__stex_expr_do_aB_clist: {
  \seq_use:Nn \l_stex_aB_args_seq {
    \mathpunct{\comp{,}}
  }
}
\tl_set_eq:NN \_stex_term_do_aB_clist: \__stex_expr_do_aB_clist:

\int_new:N \l__stex_expr_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__stex_expr_count_int
    \clist_map_inline:nn{#5}{
      \__stex_expr_aB_arg:nnnnn{##1}{#1}{#2}{#3}{#4}
    }
    \_stex_term_do_aB_clist:
  }
}

\cs_new_protected:Npn \__stex_expr_aB_arg:nnnnn #1 {
  \int_incr:N \l__stex_expr_count_int
  \__stex_expr_is_varseq:nTF{#1}{
    \exp_after:wN \exp_after:wN \exp_after:wN
    \__stex_expr_assoc_seq:nnnnnnn
    \exp_after:wN
    \__stex_expr_gobble:nnnnnnnn #1 \__stex_expr_end:
  }{
    \__stex_expr_is_seqmap:nTF{#1}{
      \exp_args:NNe \use:nn \__stex_expr_do_seqmap:nnnnnn {\tl_tail:n{#1}}
    }{
      \__stex_expr_aB_simple_arg:nnnnn{#1}
    }
  }
}

\cs_new:Npn \__stex_expr_gobble:nnnnnnnn #1 #2 #3 #4 #5 #6 #7 #8 #9 \__stex_expr_end: {
  {#2} #3 {#6}
}

\cs_new_protected:Nn \__stex_expr_aB_simple_arg:nnnnn{
  \seq_put_right:Nx \l_stex_aB_args_seq {
    \_stex_term_arg:nnnnn{#2\int_use:N\l__stex_expr_count_int}{#3}{#4}{#5}{
      \exp_not:n{
        \tl_set_eq:NN \_stex_term_do_aB_clist: \__stex_expr_do_aB_clist:
        #1
      }
    }
  }
}

\cs_new_protected:Nn \_stex_is_sequentialized:n {
  \group_begin: #1 \group_end:
}
\prg_new_conditional:Nnn \__stex_expr_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 \__stex_expr_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:
}
\cs_new_protected:Nn \__stex_expr_assoc_seq:nnnnnnn {
  \group_begin:
    \seq_clear:N \l_stex_aB_args_seq
    \__stex_expr_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__stex_expr_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:
            }
          }
        }
      }
    }
  }
}

\cs_new_protected:Nn \__stex_expr_assoc_make_seq:nnn {
  \cs_if_exist:cTF{l_stex_notation_#1__cs}{
    \cs_set_eq:Nc \l__stex_expr_cs {l_stex_notation_#1__cs}
  }{
    \stex_do_default_notation:
    \cs_set_eq:NN \l__stex_expr_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__stex_expr_iarg_tl { {##1} }
      }{
        \tl_set:Nn \l__stex_expr_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: \__stex_expr_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__stex_expr_cs \exp_after:wN \group_end: \l__stex_expr_iarg_tl
        }
      }
    }
  }
}
\cs_new_protected:Nn \__stex_expr_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}{
      \__stex_expr_is_varseq:nTF{##1}{
        \exp_after:wN
        \__stex_expr_varseq_in_map:nnnnnnnn ##1
      }{
        \seq_put_right:Nn \l_stex_aB_args_seq {##1}
      }
    }
    \seq_clear:N \l__stex_expr_old_seq
    \seq_map_inline:Nn \l_stex_aB_args_seq {
      \tl_if_eq:nnTF{##1}{\ellipses}{
        \seq_put_right:Nn \l__stex_expr_old_seq {##1}
      }
      % TODO \_stex_is_sequentialized:n
      {
        \exp_args:NNo \seq_put_right:Nn \l__stex_expr_old_seq {
          \l_tmpa_cs {##1}
        }
      }
    }
    \seq_set_eq:NN \l_stex_aB_args_seq \l__stex_expr_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__stex_expr_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:}
          }
          \__stex_expr_do_headterm:nn{}{
            \_stex_term_do_aB_clist:
          }
        }
      }
    }
  }
}

\cs_new_protected:Nn \__stex_expr_varseq_in_map:nnnnnnnn {
  \__stex_expr_assoc_make_seq:nnn{#2}{#6}{#3}
}
\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}
      }
    }{
      \__stex_expr_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}
      }
    }{
      \__stex_expr_do_headterm:nn{#1}{#3}
    }
  }
  \cs_new_protected:Nn \__stex_expr_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 \__stex_expr_do_headterm:nn { #2 }
}
\cs_set_eq:NN \_stex_term_oms_or_omv:nnn \_stex_term_oms:nnn
\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}
}
\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 }
}
\tl_const:Nx \infprec {\int_use:N \c_max_int}
\tl_const:Nx \neginfprec {-\int_use:N \c_max_int}
\int_new:N \l_stex_notation_downprec
\int_set:Nn \l_stex_notation_downprec \infprec
\tl_set:Nn \l__stex_expr_left_bracket_str (
\tl_set:Nn \l__stex_expr_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
    }
  }
}

\cs_new_protected:Npn \dobrackets #1 {
  %\ThisStyle{\if D\m@switch
  %    \exp_args:Nnx \use:nn
  %    { \exp_after:wN \left\l__stex_expr_left_bracket_str #1 }
  %    { \exp_not:N\right\l__stex_expr_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__stex_expr_left_bracket_str
    }
    #1
  \group_end:%}
  \mathclose{\cs_if_exist:NT\l_stex_current_symbol_str\comp
    \l__stex_expr_right_bracket_str
  }
  %\fi}
}
\cs_new_protected:Npn \withbrackets #1 #2 #3 {
  \stex_pseudogroup_with:nn{\l__stex_expr_left_bracket_str\l__stex_expr_right_bracket_str}{
    \tl_set:Nn \l__stex_expr_left_bracket_str { #1 }
    \tl_set:Nn \l__stex_expr_right_bracket_str { #2 }
    #3
  }
}
\cs_new_protected:Npn \dowithbrackets #1 #2 #3 {
  \withbrackets{#1}{#2}{\dobrackets{#3}}
}
\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}
  \__stex_expr_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}
  \__stex_expr_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}
  \__stex_expr_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}
  \__stex_expr_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}
  \__stex_expr_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}
  \__stex_expr_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 \__stex_expr_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:
}
\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
}
\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__stex_structures_name_str
      }
      \maincomp{\l_stex_current_this_tl}
    }
  }
}
\let \this \stex_current_this:
\stex_new_stylable_env:nnnnnnn {mathstructure}{m O{}}{
  \__stex_structures_begin:nn{#1}{#2}
  \stex_smsmode_do:
}{
  \stex_structural_feature_module_end:
  \__stex_structures_do_externals:
}{}{}{}

\stex_keys_define:nnnn{mathstructure}{
  \tl_clear:N \l_stex_current_this_tl
  \str_clear:N \l__stex_structures_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__stex_structures_name_str {\l_keys_key_tl}
    }{
      \str_set_eq:NN \l__stex_structures_name_str \l_keys_key_str
    }
  }
}{}

\cs_new_protected:Nn \__stex_structures_begin:nn {
  \stex_keys_set:nn {mathstructure}{#2}
  \str_if_empty:NT \l__stex_structures_name_str {
    \str_set:Nn \l__stex_structures_name_str {#1}
  }
  \def\comp{\_comp}

  \exp_args:Nne \use:nn { \stex_module_add_symbol:nnnnnnnN }
    { {#1}{\l__stex_structures_name_str}{0}{}{defed}{
      \l_stex_current_module_str / \l__stex_structures_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__stex_structures_name_str-module_seq}
    \seq_put_right:cn{l_stex_structure_macros_\l_stex_current_module_str / \l__stex_structures_name_str-module_seq}{#1}
  }
  \exp_args:No \stex_structural_feature_module:nn
    {\l__stex_structures_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 \__stex_structures_do_externals: {
  \tl_set:Nn \l__stex_structures_replace_this_tl {####1}
  \exp_args:No \stex_iterate_symbols:nn{\g_stex_last_feature_str}{
    \__stex_structures_external_decl:nnnn{##5}{##4}{##3}{##8}
  }
}

\cs_new_protected:Nn \__stex_structures_external_decl:nnnn {
  %\stex_debug:nn{structure}{
  %  Generating~external~declaration~\l__stex_structures_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__stex_structures_name_str/#3}{\int_eval:n{#2 + 1}}
  %  {1i\tl_if_empty:nF{#1}{\_stex_map_args:N \__stex_structures_shift_argls:nn}}
  %  {defed}{typed}
  %}{#4}\stex_invoke_outer_field:
}

\cs_new:Nn \__stex_structures_shift_argls:nn {
  \int_eval:n{#1+1}#2
}
\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
    }
  }
}
\stex_new_stylable_env:nnnnnnn {extstructure}{m O{} m}{
  \seq_clear:N \l__stex_structures_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__stex_structures_imports_seq{####1}
      }
    }
    \stex_execute_in_module:x{
      \seq_put_right:cn{l_stex_structure_macros_\l_stex_get_structure_module_str _seq}{#1}
    }
  }
  \__stex_structures_begin:nn{#1}{#2}
  \seq_map_inline:Nn\l__stex_structures_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:
  \__stex_structures_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 \__stex_structures_extend_structure_i:NnnnnnnnN {
  \exp_not:n{#1{#2}{#3}{#4}{#5}{defed}}{\l__stex_structures_extmod_str,#7}\exp_not:n{{#8}#9}
}
\cs_new_protected:Nn \__stex_structures_extend_structure:nn {
  \stex_debug:nn{ext}{Extending~#1~by~#2}
  \str_set:Nn \l__stex_structures_extmod_str{#2}
  \tl_set:cx{#1}{
    \exp_after:wN \exp_after:wN \exp_after:wN
    \__stex_structures_extend_structure_i:NnnnnnnnN \cs:w #1 \cs_end:
  }
}

\stex_new_stylable_env:nnnnnnn {extstructure*}{m}{
  \__stex_structures_new_extstruct_name:
  \seq_clear:N \l__stex_structures_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__stex_structures_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}{
        \__stex_structures_extend_structure:nn{####1}{\l_stex_current_module_str/\l__stex_structures_exstruct_name_str -module}
      }
    }
  }

  \exp_args:No \__stex_structures_begin:nn\l__stex_structures_exstruct_name_str{}

  \seq_map_inline:Nn \l__stex_structures_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
  }{
    \__stex_structures_check_def:nnnnnnnn ##2
  }
  \stex_structural_feature_module_end:
  \__stex_structures_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 \__stex_structures_check_def:nnnnnnnn {
  \tl_if_empty:nT{#5}{
    \msg_error:nnnn{stex}{error/needsdefiniens}{#2}{extstructure*}
  }
}

\stex_every_module:n{ \str_set:Nn \l__stex_structures_extname_count 0}

\cs_new_protected:Nn \__stex_structures_new_extstruct_name: {
  \stex_do_up_to_module:n {
    \str_set:Nx \l__stex_structures_extname_count {\int_eval:n{\l__stex_structures_extname_count+1}}
  }
  \str_set:Nx \l__stex_structures_exstruct_name_str {EXTSTRUCT_\l__stex_structures_extname_count}
}

\cs_new_protected:Nn \stex_invoke_structure: {
  \tl_set:Nn \l__stex_structures_set_comp_tl {\__stex_structures_set_thiscomp:}
  \__stex_structures_invoke_top:n {}
}

\cs_new_protected:Nn \__stex_structures_invoke_top:n {
  \stex_debug:nn{structure}{
    invoking~structure~{\l_stex_current_type_tl}<\tl_to_str:n{#1}>
  }
  \peek_charcode:NTF [ {
    \__stex_structures_merge:nw{#1}
  }{
    \__stex_structures_invokation_type:n {#1}
    \tl_set:Nn \l__stex_structures_this_tl {}
    \peek_charcode_remove:NTF ! {
      \peek_charcode:NTF [ {
        \__stex_structures_maybe_notation:w
      }{
        \__stex_structures_maybe_notation:w []
      }
    }{
      \__stex_structures_invoke_this:n
    }
  }
}

\cs_new_protected:Npn \__stex_structures_merge:nw #1 [ #2 ] {
  \exp_args:Ne \stex_str_if_starts_with:nnTF {\tl_to_str:n{#2}}{comp=}{
    \__stex_structures_set_customcomp: #2 \__stex_structures_end:
    \__stex_structures_invoke_top:n{#1}
  }{
    \exp_args:Ne \stex_str_if_starts_with:nnTF {\tl_to_str:n{#2}}{this=}{
      \__stex_structures_set_thisnotation: #2 \__stex_structures_end:
      \__stex_structures_invoke_top:n{#1}
    }{
      \tl_if_empty:nTF{#1}{
        \__stex_structures_invoke_top:n{#2}
      }{
        \tl_if_empty:nTF{#2}{
          \__stex_structures_invoke_top:n{#1}
        }{
          \__stex_structures_invoke_top:n{#1,#2}
        }
      }
    }
  }
}

\cs_new_protected:Npn \__stex_structures_set_thisnotation: this= #1 \__stex_structures_end: {
  \tl_set:Nn \l_stex_return_notation_tl { \comp{#1} }
  \tl_set:Nn \l__stex_structures_set_comp_tl {}
}

\cs_new_protected:Npn \__stex_structures_set_customcomp: comp= #1 \__stex_structures_end: {
  \tl_set:Nn \l__stex_structures_set_comp_tl {
    \__stex_structures_set_custom_comp:n{#1}
  }
  \tl_set:Nn \l_stex_return_notation_tl { \comp{} }
}
\cs_new_protected:Nn \__stex_structures_invokation_type:n {
  \__stex_structures_do_assign_list:n{#1}
  \clist_if_empty:NTF \l__stex_structures_fields_clist {
    \int_compare:nNnTF {\clist_count:N \l_stex_current_type_tl}
      = 1 {
        \tl_set:Nx \l__stex_structures_current_type_tl {
          \exp_args:No \exp_not:n \l_stex_current_redo_tl
          \_stex_term_oms_or_omv:nnn{}{}{}
        }
      }{
        \exp_args:No \__stex_structures_make_type:n \l_stex_current_type_tl
    }
  }{
    \int_compare:nNnTF {\clist_count:N \l_stex_current_type_tl}
      = 1 {
        \__stex_structures_make_type:n {}
      }{
        \exp_args:No \__stex_structures_make_type:n \l_stex_current_type_tl
    }
  }
}

\cs_new_protected:Nn \__stex_structures_do_assign_list:n {
  \clist_clear:N \l__stex_structures_fields_clist
  \tl_if_empty:nF {#1} {
    \keyval_parse:NNn\TODO\__stex_structures_do_assign:nn{#1}
  }
}

\cs_new_protected:Nn \__stex_structures_do_assign:nn {
  \clist_put_right:Nn \l__stex_structures_fields_clist {{#1}{#2}}
}

\cs_new_protected:Nn \__stex_structures_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__stex_structures_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 \__stex_structures_make_mod:n
      \clist_if_empty:NF \l__stex_structures_fields_clist {
        ,\symuse{Metatheory?anonymous~record}{
          \exp_args:Ne \tl_tail:n{
            \clist_map_function:NN \l__stex_structures_fields_clist \__stex_structures_make_oml:n
          }
        }
      }
    }
  }
}

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

\cs_new:Nn \__stex_structures_make_oml:n {
  \__stex_structures_make_oml:nn #1
}
\cs_new:Nn \__stex_structures_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!}}
    }
  }
}
\cs_new:Nn \__stex_structures_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__stex_structures_current_type_tl
  }
  \_stex_term_oms_or_omv:nnn{}{}{}
}
\cs_new_protected:Npn \__stex_structures_maybe_notation:w [ #1 ] {
  \tl_set_eq:NN \l_stex_current_term_tl \l__stex_structures_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:
  }{
    \__stex_structures_make_prop:
    \__stex_structures_make_prop_assign:
    \__stex_structures_present_i:w [#1]
  }
}

\cs_new_protected:Nn \__stex_structures_present: {
  \peek_charcode:NTF [ {
    \__stex_structures_present_i:w
  }{
    \__stex_structures_present:nn{}{}
  }
}

\cs_new_protected:Npn \__stex_structures_present_i:w [#1] {
  \int_compare:nNnTF{\clist_count:n{#1}} = 1 {
    \__stex_structures_present:nn{}{#1}
  }{
    \peek_charcode:NTF [ {
      \__stex_structures_present_ii:nw{#1}
    }{
      \__stex_structures_present:nn{#1}{}
    }
  }
}

\cs_new_protected:Npn \__stex_structures_present_ii:nw #1 [#2] {
  \__stex_structures_present:nn{#1}{#2}
}

\cs_new_protected:Nn \__stex_structures_present:nn {
  \clist_clear:N \l__stex_structures_clist
  \tl_if_empty:nTF{#1}{
    \cs_set:Npn \l__stex_structures_cs ##1 ##2 ##3 {
      \tl_if_empty:nF{##2}{
        \__stex_structures_present_entry:nn {##1}{##3}
      }
    }
  }{
    \cs_set:Npn \l__stex_structures_cs ##1 ##2 ##3 {
      \exp_args:Ne \clist_if_in:nnT{\tl_to_str:n{#1}}{##1}{
        \__stex_structures_present_entry:nn {##1}{##3}
      }
    }
  }
  \prop_map_inline:Nn \l__stex_structures_prop {
    \l__stex_structures_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__stex_structures_clist}
  }\group_end:
}

\cs_new_protected:Nn \__stex_structures_present_entry:nn {
  \seq_if_in:NnTF \l__stex_structures_assigned_seq {#1}{
    \clist_put_right:Nn \l__stex_structures_clist {#2!}
  }{
    \exp_args:NNe \clist_put_right:Nn \l__stex_structures_clist {
      \_stex_next_symbol:n {
        \exp_args:No \exp_not:n \l__stex_structures_set_comp_tl
        \tl_set:Nn \exp_not:N \l__stex_structures_this_tl {
          \exp_args:No \exp_not:n \l__stex_structures_this_tl
        }
        \exp_not:n {
          \tl_set_eq:NN \this \l__stex_structures_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__stex_structures_this_tl
    \group_end:
  }
  }
}

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

\cs_new_protected:Nn \__stex_structures_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__stex_structures_comp_cs ##1  {
            #1
          }
          \def\maincomp
        }{\comp}
        \exp_not:N\l__stex_structures_comp_cs{\comp{##1}}
      \group_end:
    }
    \def\maincomp {\_customthiscomp}
  }
}


\cs_new_protected:Nn \__stex_structures_invoke_this:n {
  \peek_charcode_remove:NTF ! {
    \exp_args:Nne\use:nn{
      \group_end:\symuse{Metatheory?of~type}[invisible]{#1}
    }{
      {\__stex_structures_current_type:}
    }
  }{
    \__stex_structures_invoke_maybe_field:nn{#1}
  }
}

\cs_new_protected:Nn \__stex_structures_invoke_maybe_field:nn {
  \__stex_structures_make_prop:
  \__stex_structures_set_this:n{#1}
  \tl_if_empty:nTF{#2}{
    \__stex_structures_make_prop_assign:
    \__stex_structures_present:
  }{
    \__stex_structures_invoke_field:n{#2}
  }
}

\cs_new_protected:Nn \__stex_structures_set_this:n {
  \tl_if_empty:nTF{#1}{
    %\tl_put_right:Nn \l_stex_current_redo_tl {
    %  \tl_clear:N \l__stex_structures_this_tl
    %}
  }{
    \tl_set:Nx \l__stex_structures_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__stex_structures_this_tl
    % \l_stex_return_notation_tl
  }
}

\cs_new_protected:Nn \__stex_structures_get_field_name:n {
  \str_set:Nx \l__stex_structures_field_name_str {
    \exp_args:Nne \use:n {\exp_after:wN \use_i:nn \use:n}
    {\prop_item:Nn \l__stex_structures_prop {#1}}
  }
  \str_if_empty:NT \l__stex_structures_field_name_str {
    \str_set:Nn \l__stex_structures_field_name_str {#1}
  }
}

\cs_new_protected:Nn \__stex_structures_invoke_field:n {
  \prop_if_in:NnTF \l__stex_structures_prop {#1}{
    \__stex_structures_get_field_name:n{#1}
    \tl_clear:N \l__stex_structures_more_nextsymbol_tl
    %\exp_args:NNe \seq_if_in:NnF \l__stex_structures_assigned_seq {\tl_to_str:n{#1}}{
      \tl_set:Nx \l__stex_structures_more_nextsymbol_tl {
        \tl_set:Nn \exp_not:N \l__stex_structures_this_tl {
          \exp_args:No \exp_not:n \l__stex_structures_this_tl
        }
        \exp_not:n {
          \tl_set_eq:NN \this \l__stex_structures_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__stex_structures_set_comp_tl
      }
    %}
    \exp_args:NNx \use:nn \group_end: {
      \_stex_next_symbol:n {
        \exp_args:No \exp_not:n \l__stex_structures_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__stex_structures_this_tl
            }{  \__stex_structures_current_type: }
          }{
            \stex_annotate:nn{shtml:term=OML,shtml:head={\l__stex_structures_field_name_str}}{}
          }
        }
        \exp_args:No \exp_not:n \l__stex_structures_more_nextsymbol_tl
      }
      \exp_not:N \use_ii:nn
      \prop_item:Nn \l__stex_structures_prop {#1}
    }
  }{
    \msg_error:nnn{stex}{error/unknownfield}{#1}
  }
}

\cs_new_protected:Nn \__stex_structures_make_prop: {
  \prop_clear:N \l__stex_structures_prop
  \seq_clear:N \l__stex_structures_seq
  \seq_clear:N \l__stex_structures_assigned_seq
  \tl_clear:N \l__stex_structures_redo_tl
  \__stex_structures_prop_do_decls:
  \__stex_structures_prop_do_notations:
}

\cs_new_protected:Nn \__stex_structures_make_prop_assign: {
  \clist_if_empty:NF \l__stex_structures_fields_clist {
    \clist_map_inline:Nn \l__stex_structures_fields_clist {
      \__stex_structures_make_prop_assign:nn ##1
    }
  }
}

\cs_new_protected:Nn \__stex_structures_make_prop_assign:nn {
  \prop_if_in:NnTF \l__stex_structures_prop {#1}{
    \exp_args:NNe \seq_put_right:Nn \l__stex_structures_assigned_seq {\tl_to_str:n{#1}}
    \exp_args:Nne \use:nn {\__stex_structures_make_prop_assign_replace:nnnn {#1}{#2}}
    {\prop_item:Nn \l__stex_structures_prop {#1}}
  }{
    \msg_error:nnn{stex}{error/unknownfieldass}{#1}
  }
}
\cs_new_protected:Nn \__stex_structures_make_prop_assign_replace:nnnn {
  \prop_put:Nnn \l__stex_structures_prop {#1}{{#3}{#2}}
  \tl_if_empty:nF{#3}{
    \tl_set:cn{#1}{ #2 }
    \tl_put_right:Nn \l__stex_structures_redo_tl {
      \tl_set:cn{#1}{ #2 }
    }
  }
}

\cs_new_protected:Nn \__stex_structures_prop_do_decls: {
  \exp_args:No \stex_iterate_symbols:nn \l_stex_current_type_tl {
    \tl_if_empty:nTF{##2}{
      \__stex_structures_do_decl_nomacro:nnnnnnnnn{##3}
    }{
      \__stex_structures_do_decl:nnnnnnnnn{##2}
    }
    {##1}{##3}{##4}{##5}{##6}{##7}{##8}{##9}
  }
}

\cs_new_protected:Nn \__stex_structures_do_decl_nomacro:nnnnnnnnn {
  \prop_if_in:NnF \l__stex_structures_prop {#1} {
    \seq_put_left:Nx \l__stex_structures_seq {\tl_to_str:n{#2?#3}}
    \prop_put:Nnn \l__stex_structures_prop {#1}{
      {}{
        \_stex_invoke_symbol:nnnnnnnN
        {#2}
        {#3}
        {#4}{#5}{#6}{#7}{#8}#9
      }
    }
  }
}

\cs_new_protected:Nn \__stex_structures_do_decl:nnnnnnnnn {
  \prop_if_in:NnF \l__stex_structures_prop {#1} {
    \seq_put_left:Nx \l__stex_structures_seq {\tl_to_str:n{#2?#3}}
    \prop_put:Nnn \l__stex_structures_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__stex_structures_redo_tl {
  %  \tl_set:cn{#1}{
  %    \_stex_invoke_symbol:nnnnnnnN
  %    {#2}{#3}{#4}{#5}{#6}{#7}{#8}#9
  %  }
  %}
}

\cs_new_protected:Nn \__stex_structures_prop_do_notations: {
  \exp_args:No \stex_iterate_notations:nn\l_stex_current_type_tl{
    \exp_args:NNe \seq_if_in:NnT \l__stex_structures_seq {\tl_to_str:n{##1}}{
      \tl_put_right:Nn \l__stex_structures_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__stex_structures_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}
        }
      }
    }
  }
}
\cs_new_protected:Npn \usestructure #1 {
  \stex_get_mathstructure:n{ #1 }
  \seq_clear:N \l__stex_structures_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__stex_structures_imports_seq{##1}
    }
  }
  \seq_map_inline:Nn \l__stex_structures_imports_seq {
    \stex_if_do_html:T {
      \hbox{\stex_annotate_invisible:nn
        {shtml:usemodule=##1} {}}
    }
    \stex_activate_module:n {##1}
  }
}

\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}
\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 \__stex_statements_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 {
    \__stex_statements_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__stex_statements_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__stex_statements_uri_str {\seq_item:Nn \l_stex_fors_seq 1}
      \stex_debug:nn{statement}{for:~\l__stex_statements_uri_str}
    }{
      \stex_debug:nn{statement}{no~for}
    }
  }{
    \str_set:Nx \l__stex_statements_uri_str {\l_stex_current_module_str ? \l_stex_key_name_str}
    \stex_debug:nn{statement}{name:~\l__stex_statements_uri_str}
  }
}

\cs_new:Nn \__stex_statements_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}{
        \__stex_statements_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{\__stex_statements_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 \__stex_statements_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 \__stex_statements_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}{
  \__stex_statements_force_id:
  \__stex_statements_setup:nn{}{}
  \__stex_statements_setup_def:
  \stex_reactivate_macro:N \definiens
}
\stex_new_statement:nnn{assertion}{ass}{
  \__stex_statements_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}{\__stex_statements_setup:nn{}{example}}
\stex_new_statement:nnn{paragraph}{}{
  \clist_if_in:NnTF \l_stex_key_style_clist {symdoc}{
    \__stex_statements_force_id:
    \__stex_statements_setup:nn{}{}
    \__stex_statements_setup_def:
  }{
    \__stex_statements_setup:nn{}{}
  }
}

\cs_new_protected:Nn \__stex_statements_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 }
  \__stex_statements_do_defref:nn{#2}{#3}
}
\stex_deactivate_macro:Nn \definiendum {definition~environments}

\NewDocumentCommand \definame { O{} m } {
  \stex_keys_set:nn{symname}{#1}
  \__stex_statements_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}
  \__stex_statements_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__stex_statements_uri_str
      {\l_stex_get_symbol_mod_str ? \l_stex_get_symbol_name_str}
  }
  \str_if_empty:NT \l__stex_statements_uri_str {
    \msg_error:nn{stex}{error/definiensfor}
  }
  \stex_debug:nn{definiens}{Checking~\l__stex_statements_uri_str}

  \exp_args:No \_stex_add_definiens:nn \l__stex_statements_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__stex_statements_uri_str
      {\l_stex_get_symbol_mod_str ? \l_stex_get_symbol_name_str}
  }
  \str_if_empty:NT \l__stex_statements_uri_str {
    \msg_error:nn{stex}{error/conclusionfor}
  }
  \stex_annotate:nn{ shtml:conclusion=\l__stex_statements_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}
\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 \__stex_proof_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__stex_proof_inc_counter_bool
\intarray_new:Nn\l__stex_proof_counter_intarray{50}
\cs_new_protected:Npn \__stex_proof_insert_number: {
  \int_set:Nn \l_tmpa_int {1}
  \bool_while_do:nn {
    \int_compare_p:nNn {
      \intarray_item:Nn \l__stex_proof_counter_intarray \l_tmpa_int
    } > 0
  }{
    \intarray_item:Nn \l__stex_proof_counter_intarray \l_tmpa_int .
    \int_incr:N \l_tmpa_int
  }
}
\cs_new_protected:Nn \__stex_proof_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__stex_proof_counter_intarray \l_tmpa_int
    } > 0
  }{
    \str_put_right:Nx #1 {\intarray_item:Nn \l__stex_proof_counter_intarray \l_tmpa_int .}
    \int_incr:N \l_tmpa_int
  }
}

\cs_new_protected:Npn \__stex_proof_inc_counter: {
  \int_set:Nn \l_tmpa_int {1}
  \bool_while_do:nn {
    \int_compare_p:nNn {
      \intarray_item:Nn \l__stex_proof_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__stex_proof_counter_intarray \l_tmpa_int {
    \intarray_item:Nn \l__stex_proof_counter_intarray \l_tmpa_int + 1
  }
}

\cs_new_protected:Npn \__stex_proof_add_counter: {
  \int_set:Nn \l_tmpa_int {1}
  \bool_while_do:nn {
    \int_compare_p:nNn {
      \intarray_item:Nn \l__stex_proof_counter_intarray \l_tmpa_int
    } > 0
  }{
    \int_incr:N \l_tmpa_int
  }
  \intarray_gset:Nnn \l__stex_proof_counter_intarray \l_tmpa_int { 1 }
}

\cs_new_protected:Npn \__stex_proof_remove_counter: {
  \int_set:Nn \l_tmpa_int {1}
  \bool_while_do:nn {
    \int_compare_p:nNn {
      \intarray_item:Nn \l__stex_proof_counter_intarray \l_tmpa_int
    } > 0
  }{
    \int_incr:N \l_tmpa_int
  }
  \int_decr:N \l_tmpa_int
  \intarray_gset:Nnn \l__stex_proof_counter_intarray \l_tmpa_int { 0 }
}
\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 :}~
}
\tl_set:Nn \__stex_proof_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
  }
}
\cs_new_protected:Npn \stexcommentfont {
  \small\itshape
}
\cs_new_protected:Nn \__stex_proof_start_list:n {
  \begin{list}{}{
    \setlength\topsep{0pt}
    \setlength\parsep{0pt}
    \setlength\rightmargin{0pt}
  }\item[#1]
}
\cs_new_protected:Nn \__stex_proof_end_list: {
  \end{list}
}

\cs_new_protected:Nn \__stex_proof_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 \__stex_proof_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
    }
  }
  \__stex_proof_html:
}

\bool_set_false:N \l__stex_proof_in_spfblock_bool
\cs_new_protected:Nn \__stex_proof_begin_proof:nn {\par
  \intarray_gzero:N \l__stex_proof_counter_intarray
  \intarray_gset:Nnn \l__stex_proof_counter_intarray 1 1
  \stex_keys_set:nn{spfsteps}{#1}
  \_stex_do_for_list:
  \stex_if_do_html:T {
    \__stex_proof_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}{
  \__stex_proof_begin_proof:nn{#1}{#2}
  \bool_set_true:N\l__stex_proof_in_spfblock_bool\__stex_proof_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__stex_proof_in_spfblock_bool {
    \group_end:\__stex_proof_end_list:
  }
}

\stex_new_stylable_env:nnnnnnn{proof*}{O{}}{
  \__stex_proof_begin_proof:nn{#1}{}
  \bool_set_false:N\l__stex_proof_in_spfblock_bool
}{
  \stex_style_apply:
  \stex_if_do_html:T{\end{stex_annotate_env}\end{stex_annotate_env}}
}{
  \emph{Proof:}~
}{
  \sproofend
}{s}
\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 {
    \__stex_proof_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 {
      \__stex_proof_number_as_string:N \@currentlabel
      \str_set:Nx \@currentHref{subproof.\@currentlabel}
      \_stex_do_id:
    }
    \bool_set_false:N \l__stex_proof_in_spfblock_bool
    \stex_annotate:nn{shtml:prooftitle={}}{#3}
  }{
    \bool_if:NTF \l__stex_proof_in_spfblock_bool {
      \str_if_empty:NF \l_stex_key_id_str {
        \__stex_proof_number_as_string:N \@currentlabel
        \str_set:Nx \@currentHref{subproof.\@currentlabel}
        \_stex_do_id:
      }
      \__stex_proof_start_list:n\__stex_proof_insert_number:
        \stex_annotate:nn{shtml:prooftitle={}}{#3}
        \__stex_proof_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__stex_proof_in_spfblock_bool {\group_begin:\stexcommentfont}
}{
  \stex_style_apply:
  \bool_if:NT \l__stex_proof_in_spfblock_bool \__stex_proof_inc_counter:
  \stex_if_do_html:T{\end{stex_annotate_env}}
  \bool_if:NT\l__stex_proof_in_spfblock_bool \__stex_proof_end_list:
  \stex_if_do_html:T{\end{stex_annotate_env}}
  \aftergroup \__stex_proof_inblock_restore:
}{}{}{}
\AddToHook{env/subproof/before}{
  \bool_if:NT \l__stex_proof_in_spfblock_bool \group_end:
}
\AddToHook{env/subproof/end}{
  \bool_if:NT\l__stex_proof_in_spfblock_bool {
    \group_end:\__stex_proof_remove_counter:
    %\__stex_proof_end_list:
  }
}
\stex_deactivate_macro:Nn \subproof {sproof~environments}

\cs_new_protected:Nn \__stex_proof_inblock_restore: {
  \bool_if:NT\l__stex_proof_in_spfblock_bool {
    \group_begin:\stexcommentfont
  }
}

\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 \__stex_proof_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}
      }
    }{
      \__stex_proof_html:
      #2
    }
  }{ #2 }
}

\cs_new_protected:Nn \__stex_proof_make_step_macro:Nnnnn {
  \NewDocumentCommand #1 {s O{} +m} {
    \bool_if:NT \l__stex_proof_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 {
        \__stex_proof_number_as_string:N \@currentlabel
        \str_set:Nx \@currentHref{spfstep.\@currentlabel}
        \_stex_do_id:
      }

    \bool_if:NTF \l__stex_proof_in_spfblock_bool {
      \IfBooleanTF ##1 {
        \__stex_proof_step_html:nn{#2}{##3}
      }{
        \__stex_proof_step_html:nn{#2}{\__stex_proof_start_list:n{#3} ##3 \__stex_proof_end_list:}
        #5
      }
      \end{spfstepenv}
      \group_begin:\stexcommentfont
    }{
      \__stex_proof_step_html:nn{#2}{##3}
      \end{spfstepenv}
    }
  }
  \stex_deactivate_macro:Nn #1 {sproof~environments}
}

\__stex_proof_make_step_macro:Nnnnn \assumption {assumption} \__stex_proof_insert_number: {} \__stex_proof_inc_counter:
\__stex_proof_make_step_macro:Nnnnn \conclude {conclusion} {$\Rightarrow$} {} {}
\__stex_proof_make_step_macro:Nnnnn \spfstep {step} \__stex_proof_insert_number: {} \__stex_proof_inc_counter:

\NewDocumentCommand \eqstep {s m}{
  \bool_if:NTF \l__stex_proof_in_spfblock_bool {
    \group_end:
    \IfBooleanTF #1 {
      \__stex_proof_step_html:nn{eqstep}{$= #2$}
    }{
      \__stex_proof_step_html:nn{eqstep}{\__stex_proof_start_list:n{$=$} $#2$ \__stex_proof_end_list:}
    }
    \group_begin:\stexcommentfont
  }{
    \__stex_proof_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__stex_proof_in_spfblock_bool
}{
  \aftergroup\__stex_proof_inblock_restore:
}
\stex_deactivate_macro:Nn \spfblock {sproof~environments}
\AddToHook{env/spfblock/before}{
  \bool_if:NT \l__stex_proof_in_spfblock_bool \group_end:
}

\newcommand\spfjust[1]{
  \stex_annotate:nn{spfjust={}}{ #1 }
}
\stex_deactivate_macro:Nn \spfjust {sproof~environments}
\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:
\cs_new_protected:Npn \MSC #1 {}
\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}
\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}
\NewDocumentEnvironment { mmtinterface } {  O{} m m } {
  \_stex_module_setup_top_nosig:n { #3 }
  \str_set_eq:NN \l__todo_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__todo_stex_module_str \l_stex_current_module_str
  \stex_debug:nn{mmt}{Interface~\l__todo_stex_module_str^^Jfor~\l__todo_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__todo_mmt_module_str} {}
  }
  \stex_module_add_code:x{
    \stex_activate_module:n{ \l__todo_mmt_module_str }
  }
  \stex_module_add_morphism:nonn
    {}{\l__todo_mmt_module_str}{import}{}
  \stex_reactivate_macro:N \mmtdef
  \stex_smsmode_do:
}{
    \str_set_eq:NN \l_stex_current_module_str \l__todo_mmt_module_str
    \stex_close_module:
    \str_set_eq:NN \l_stex_current_module_str \l__todo_stex_module_str
    \stex_close_module:
    \stex_if_do_html:T { \end{stex_annotate_env} }
}
\stex_sms_allow_env:n{mmtinterface}
\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__todo_mmt_module_str
  \cs_set_eq:NN \l__todo_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__todo_old_metagroup_cd
  \str_set_eq:NN \l_stex_current_module_str \l__todo_stex_module_str

  \str_set_eq:NN \l_stex_get_symbol_mod_str \l__todo_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
\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}}
    }
}
\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 \__todo_newlabel:n {
  \exp_args:Ne\__todo_old_newlabel:{\tl_to_str:n{#1}}
}
\AtBeginDocument{
  \iow_now:Nn \@auxout {
    \ExplSyntaxOn
    \let\__todo_old_newlabel:\newlabel
    \let\newlabel\__todo_newlabel:n
    \ExplSyntaxOff
  }
}
\endinput
%%
%% End of file `stex.sty'.
