% \iffalse meta-comment
% An Infrastructure for Semantic Macros and Module Scoping
% Copyright (c) 2019 Michael Kohlhase, all rights reserved
%                this file is released under the
%                LaTeX Project Public License (LPPL)
% 
% The original of this file is in the public repository at 
% http://github.com/sLaTeX/sTeX/
%
% TODO update copyright  
%
%<*driver>
\providecommand\bibfolder{../../lib/bib}
\input{../../doc/stex-docheader}

\begin{document}
  \DocInput{\jobname.dtx}
\end{document}
%</driver>
% \fi
%
% \title{ \sTeX-Symbols
% 	\thanks{Version {\fileversion} (last revised {\filedate})} 
% }
%
% \author{Michael Kohlhase, Dennis Müller\\
% 	FAU Erlangen-Nürnberg\\
% 	\url{http://kwarc.info/}
% }
%
% \maketitle
%
%\ifinfulldoc\else
% This is the documentation for the \pkg{stex-symbols} package.
% For a more high-level introduction, 
%  see \href{\basedocurl/manual.pdf}{the \sTeX Manual} or the
% \href{\basedocurl/stex.pdf}{full \sTeX documentation}.
%
% \input{../../doc/packages/stex-symbols}
% \fi
%
% \begin{documentation}\label{pkg:symbols:doc}
%
% Code related to symbol declarations and notations
%
% \section{Macros and Environments}\label{pkg:symbols:doc:macros}
%
% \begin{function}{\symdecl}
%   \begin{syntax} \cs{symdecl}\Arg{macroname}|[|\meta{args}|]| \end{syntax}
%   Declares a new symbol with semantic macro \cs{macroname}. Optional
%   arguments are:
%   \begin{itemize}
%     \item |name|: An (\omdoc) name. By default equal to \meta{macroname}.
%     \item |type|: An (ideally semantic) term. Not used by \sTeX, but
%         passed on to \mmt for semantic services.
%     \item |local|: A boolean (by default false). If set, this declaration
%         will not be added to the module content, i.e. importing
%         the current module will not make this declaration available.
%     \item |args|: Specifies the ``signature'' of the semantic macro.
%       Can be either an integer $0 \leq n \leq 9$, or a (more precise)
%       sequence of the following characters:
%         \begin{itemize}
%           \item[|i|] a ``normal'' argument, e.g.
%             |\symdecl{plus}[args=ii]| allows for |\plus{2}{2}|.
%           \item[|a|] an \emph{associative} argument; i.e. a sequence of
%             arbitrarily many arguments provided as a comma-separated list,
%             e.g.
%             |\symdecl{plus}[args=a]| allows for |\plus{2,2,2}|.
%           \item[|b|] a \emph{variable} argument. Is treated by \sTeX
%             like an |i|-argument, but an application is turned into
%             an |OMBind| in \omdoc, binding the provided variable
%             in the subsequent arguments of the operator; e.g.
%             |\symdecl{forall}[args=bi]| allows for |\forall{x\in\Nat}{x\geq0}|.
%         \end{itemize}
%   \end{itemize}
% \end{function}
%
% \begin{function}{\stex_symdecl_do:n}
%   Implements the core functionality of \cs{symdecl}, and is
%   called by \cs{symdecl} and \cs{symdef}.
%
%   Ultimately stores the symbol \meta{URI} in the property
%   list |\l_stex_symdecl_|\meta{URI}|_prop| with fields:
%   \begin{itemize}
%     \item |name| (string),
%     \item |module| (string),
%     \item |notations| (sequence of strings; initially empty),
%     \item |local| (boolean),
%     \item |type| (token list),
%     \item |args| (string of |i|s, |a|s and |b|s),
%     \item |arity| (integer string),
%     \item |assocs| (integer string; number of associative arguments),
%   \end{itemize}
% \end{function}
%
% \begin{function}{\stex_all_symbols:n}
%   Iterates over all currently available symbols.
%   Requires two |\seq_map_break:| to break fully.
% \end{function}
%
% \begin{function}{\stex_get_symbol:n}
%   Computes the full URI of a symbol from a macro argument, e.g.
%   the macro name, the macro itself, the full URI...
% \end{function}
%
% \begin{function}{\notation}
%   \begin{syntax} \cs{notation}|[|\meta{args}|]|\Arg{symbol}\Arg{notations$^+$} \end{syntax}
%   Introduces a new notation for \meta{symbol}, see \cs{stex_notation_do:nn}
% \end{function}
%
% \begin{function}{\stex_notation_do:nn}
%   \begin{syntax} \cs{stex_notation_do:nn}\Arg{URI}\Arg{notations$^+$}\end{syntax}
%
%   Implements the core functionality of \cs{notation}, and is
%   called by \cs{notation} and \cs{symdef}.
%
%   Ultimately stores the notation in the property
%   list\\ |\g_stex_notation_|\meta{URI}|#|\meta{variant}|#|^^A
%   \meta{lang}|_prop| with fields:
%   \begin{itemize}
%     \item |symbol| (URI string),
%     \item |language| (string),
%     \item |variant| (string),
%     \item |opprec| (integer string),
%     \item |argprecs| (sequence of integer strings)
%   \end{itemize}
% \end{function}
%
% \begin{function}{\symdef}
%   \begin{syntax} \cs{symdef}|[|\meta{args}|]|\Arg{symbol}\Arg{notations$^+$} \end{syntax}
%   Combines \cs{symdecl} and \cs{notation} by introducing a new
%   symbol and assigning a new notation for it.
% \end{function}
%
% \end{documentation}
%
% \begin{implementation}\label{pkg:symbols:impl}
%
% \section{\sTeX-Symbols Implementation}
%
%    \begin{macrocode}
%<*package>

%%%%%%%%%%%%%   symbols.dtx   %%%%%%%%%%%%%

%    \end{macrocode}
%
% Warnings and error messages
%
%    \begin{macrocode}
\msg_new:nnn{stex}{error/wrongargs}{
  args~value~in~symbol~declaration~for~#1~
  needs~to~be~i,~a,~b~or~B,~but~#2~given
}
%    \end{macrocode}
%
% \subsection{Symbol Declarations}
%    \begin{macrocode}
%<@@=stex_symdecl>
%    \end{macrocode}
%
% \begin{macro}{\stex_all_symbols:n}
%   Map over all available symbols
%    \begin{macrocode}
\cs_new_protected:Nn \stex_all_symbols:n {
  \def \_@@_all_symbols_cs ##1 {#1}
  \seq_map_inline:Nn \l_stex_all_modules_seq {
    \seq_map_inline:cn{c_stex_module_##1_constants}{
      \_@@_all_symbols_cs{##1?####1}
    }
  } 
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\STEXsymbol}
%    \begin{macrocode}
\NewDocumentCommand \STEXsymbol { m } {
  \stex_get_symbol:n { #1 }
  \exp_args:No
  \stex_invoke_symbol:n { \l_stex_get_symbol_uri_str }
}
%    \end{macrocode}
% \end{macro}
%
% |symdecl| arguments:
%
%    \begin{macrocode}
\keys_define:nn { stex / symdecl } {
  name        .str_set_x:N  = \l_stex_symdecl_name_str ,
  local       .bool_set:N   = \l_stex_symdecl_local_bool ,
  args        .str_set_x:N  = \l_stex_symdecl_args_str ,
  type        .tl_set:N     = \l_stex_symdecl_type_tl ,
  deprecate   .str_set_x:N  = \l_stex_symdecl_deprecate_str ,
  align       .str_set:N    = \l_stex_symdecl_align_str , % TODO(?)
  gfc         .str_set:N    = \l_stex_symdecl_gfc_str , % TODO(?)
  specializes .str_set:N    = \l_stex_symdecl_specializes_str , % TODO(?)
  def         .tl_set:N     = \l_stex_symdecl_definiens_tl ,
  assoc       .choices:nn   = 
      {bin,binl,binr,pre,conj,pwconj}
      {\str_set:Nx \l_stex_symdecl_assoctype_str {\l_keys_choice_tl}}
}

\bool_new:N \l_stex_symdecl_make_macro_bool

\cs_new_protected:Nn \_@@_args:n {
  \str_clear:N \l_stex_symdecl_name_str
  \str_clear:N \l_stex_symdecl_args_str
  \str_clear:N \l_stex_symdecl_deprecate_str
  \str_clear:N \l_stex_symdecl_assoctype_str
  \bool_set_false:N \l_stex_symdecl_local_bool
  \tl_clear:N \l_stex_symdecl_type_tl
  \tl_clear:N \l_stex_symdecl_definiens_tl
  
  \keys_set:nn { stex / symdecl } { #1 }
}
%    \end{macrocode}
%
% \begin{macro}{\symdecl}
%
% Parses the optional arguments and passes them on to
% \cs{stex_symdecl_do:} (so that \cs{symdef}
% can do the same)
%
%    \begin{macrocode}

\NewDocumentCommand \symdecl { s m O{}} {
  \_@@_args:n { #3 }
  \IfBooleanTF #1 {
    \bool_set_false:N \l_stex_symdecl_make_macro_bool
  } {
    \bool_set_true:N \l_stex_symdecl_make_macro_bool
  }
  \stex_symdecl_do:n { #2 }
  \stex_smsmode_do:
}

\cs_new_protected:Nn \stex_symdecl_do:nn {
  \_@@_args:n{#1}
  \bool_set_false:N \l_stex_symdecl_make_macro_bool
  \stex_symdecl_do:n{#2}
}

\stex_deactivate_macro:Nn \symdecl {module~environments}
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\stex_symdecl_do:n}
%    \begin{macrocode}
\cs_new_protected:Nn \stex_symdecl_do:n {
  \stex_if_in_module:F {
    % TODO throw error? some default namespace?
  }
  
  \str_if_empty:NT \l_stex_symdecl_name_str {
    \str_set:Nx \l_stex_symdecl_name_str { #1 }
  }

  \prop_if_exist:cT { l_stex_symdecl_ 
      \l_stex_current_module_str ?
      \l_stex_symdecl_name_str
    _prop
  }{
    % TODO throw error (beware of circular dependencies)
  }

  \prop_clear:N \l_tmpa_prop
  \prop_put:Nnx \l_tmpa_prop { module } { \l_stex_current_module_str }
  \seq_clear:N \l_tmpa_seq
  \prop_put:Nno \l_tmpa_prop { name } \l_stex_symdecl_name_str
  \prop_put:Nno \l_tmpa_prop { type } \l_stex_symdecl_type_tl

  \str_if_empty:NT \l_stex_symdecl_deprecate_str {
    \str_if_empty:NF \l_stex_module_deprecate_str {
      \str_set_eq:NN \l_stex_symdecl_deprecate_str \l_stex_module_deprecate_str
    }
  }
  \prop_put:Nno \l_tmpa_prop { deprecate } \l_stex_symdecl_deprecate_str

  \exp_args:No \stex_add_constant_to_current_module:n {
    \l_stex_symdecl_name_str
  }

  % arity/args
  \int_zero:N \l_tmpb_int

  \bool_set_true:N \l_tmpa_bool
  \str_map_inline:Nn \l_stex_symdecl_args_str {
    \token_case_meaning:NnF ##1 {
      0 {} 1 {} 2 {} 3 {} 4 {} 5 {} 6 {} 7 {} 8 {} 9 {}
      {\tl_to_str:n i} { \bool_set_false:N \l_tmpa_bool }
      {\tl_to_str:n b} { \bool_set_false:N \l_tmpa_bool }
      {\tl_to_str:n a} { 
        \bool_set_false:N \l_tmpa_bool
        \int_incr:N \l_tmpb_int
      }
      {\tl_to_str:n B} { 
        \bool_set_false:N \l_tmpa_bool
        \int_incr:N \l_tmpb_int
      }
    }{
      \msg_error:nnxx{stex}{error/wrongargs}{
        \l_stex_current_module_str ?
        \l_stex_symdecl_name_str
      }{##1}
    }
  }
  \bool_if:NTF \l_tmpa_bool {
    % possibly numeric
    \str_if_empty:NTF \l_stex_symdecl_args_str {
      \prop_put:Nnn \l_tmpa_prop { args } {}
      \prop_put:Nnn \l_tmpa_prop { arity } { 0 }
    }{
      \int_set:Nn \l_tmpa_int { \l_stex_symdecl_args_str }
      \prop_put:Nnx \l_tmpa_prop { arity } { \int_use:N \l_tmpa_int }
      \str_clear:N \l_tmpa_str
      \int_step_inline:nn \l_tmpa_int {
        \str_put_right:Nn \l_tmpa_str i
      }
      \prop_put:Nnx \l_tmpa_prop { args } { \l_tmpa_str }
    }
  } {
    \prop_put:Nnx \l_tmpa_prop { args } { \l_stex_symdecl_args_str }
    \prop_put:Nnx \l_tmpa_prop { arity }
      { \str_count:N \l_stex_symdecl_args_str }
  }
  \prop_put:Nnx \l_tmpa_prop { assocs } { \int_use:N \l_tmpb_int }
  

  % semantic macro

  \bool_if:NT \l_stex_symdecl_make_macro_bool {
    \exp_args:Nx \stex_do_up_to_module:n {
      \tl_set:cn { #1 } { \stex_invoke_symbol:n {
        \l_stex_current_module_str ? \l_stex_symdecl_name_str
      }}
    }

    \bool_if:NF \l_stex_symdecl_local_bool {
      \exp_args:Nx \stex_add_to_current_module:n {
        \tl_set:cn { #1 } { \stex_invoke_symbol:n {
          \l_stex_current_module_str ? \l_stex_symdecl_name_str
        } }
      }
    }
  }

  \stex_debug:nn{symbols}{New~symbol:~
    \l_stex_current_module_str ? \l_stex_symdecl_name_str^^J
    Type:~\exp_not:o { \l_stex_symdecl_type_tl }^^J
    Args:~\prop_item:Nn \l_tmpa_prop { args }
  }

  % circular dependencies require this:

  \prop_if_exist:cF {
    l_stex_symdecl_ 
    \l_stex_current_module_str ? \l_stex_symdecl_name_str
    _prop 
  } {
    \prop_set_eq:cN {
      l_stex_symdecl_ 
      \l_stex_current_module_str ? \l_stex_symdecl_name_str
      _prop 
    } \l_tmpa_prop
  }

  \seq_clear:c {
    l_stex_symdecl_ 
    \l_stex_current_module_str ? \l_stex_symdecl_name_str
    _notations
  }

  \bool_if:NF \l_stex_symdecl_local_bool {
    \exp_args:Nx
    \stex_add_to_current_module:n {
      \seq_clear:c {
        l_stex_symdecl_ 
        \l_stex_current_module_str ? \l_stex_symdecl_name_str
        _notations
      }
      \prop_set_from_keyval:cn {
        l_stex_symdecl_ 
        \l_stex_current_module_str ? \l_stex_symdecl_name_str
        _prop 
      } {
        name      = \prop_item:Nn \l_tmpa_prop { name }       ,
        module    = \prop_item:Nn \l_tmpa_prop { module }     ,
        type      = \prop_item:Nn \l_tmpa_prop { type }       ,
        args      = \prop_item:Nn \l_tmpa_prop { args }       ,
        arity     = \prop_item:Nn \l_tmpa_prop { arity }      ,
        assocs    = \prop_item:Nn \l_tmpa_prop { assocs }
      }
    }
  }

  \stex_if_smsmode:F {
%    \exp_args:Nx \stex_do_up_to_module:n {
%        \seq_put_right:Nn \exp_not:N \l_stex_all_symbols_seq {
%        \l_stex_current_module_str ? \l_stex_symdecl_name_str
%      }
%    }
    \stex_if_do_html:T {
      \stex_annotate_invisible:nnn {symdecl} {
        \l_stex_current_module_str ? \l_stex_symdecl_name_str
      } {
        \tl_if_empty:NF \l_stex_symdecl_type_tl {\stex_annotate_invisible:nnn{type}{}{$\l_stex_symdecl_type_tl$}}
        \stex_annotate_invisible:nnn{args}{}{
          \prop_item:Nn \l_tmpa_prop { args }
        }
        \stex_annotate_invisible:nnn{macroname}{#1}{}
        \tl_if_empty:NF \l_stex_symdecl_definiens_tl {
          \stex_annotate_invisible:nnn{definiens}{}
            {$\l_stex_symdecl_definiens_tl$}
        }
        \str_if_empty:NF \l_stex_symdecl_assoctype_str {
          \stex_annotate_invisible:nnn{assoctype}{\l_stex_symdecl_assoctype_str}{}
        }
      }
    }
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\stex_get_symbol:n}
%
%    \begin{macrocode}
\str_new:N \l_stex_get_symbol_uri_str

\cs_new_protected:Nn \stex_get_symbol:n {
  \tl_if_head_eq_catcode:nNTF { #1 } \relax {
    \_@@_get_symbol_from_cs:n { #1 }
  }{
    % argument is a string
    % is it a command name?
    \cs_if_exist:cTF { #1 }{
      \cs_set_eq:Nc \l_tmpa_tl { #1 }
      \str_set:Nx \l_tmpa_str { \cs_argument_spec:N \l_tmpa_tl }
      \str_if_empty:NTF \l_tmpa_str {
        \exp_args:Nx \cs_if_eq:NNTF {
          \tl_head:N \l_tmpa_tl
        } \stex_invoke_symbol:n {
          \exp_args:No \_@@_get_symbol_from_cs:n { \use:c { #1 } }
        }{
          \_@@_get_symbol_from_string:n { #1 }
        }
      } {
        \_@@_get_symbol_from_string:n { #1 }
      }
    }{
      % argument is not a command name
      \_@@_get_symbol_from_string:n { #1 }
      % \l_stex_all_symbols_seq
    }
  }
  \str_if_eq:eeF {
    \prop_item:cn {
      l_stex_symdecl_\l_stex_get_symbol_uri_str _prop
    }{ deprecate }
  }{}{
    \msg_warning:nnxx{stex}{warning/deprecated}{
      Symbol~\l_stex_get_symbol_uri_str
    }{
      \prop_item:cn {l_stex_symdecl_\l_stex_get_symbol_uri_str _prop}{ deprecate }
    }
  }
}

\cs_new_protected:Nn \_@@_get_symbol_from_string:n {
  \tl_set:Nn \l_tmpa_tl {
    \msg_set:nnn{stex}{error/unknownsymbol}{
      No~symbol~#1~found!
    }
    \msg_error:nn{stex}{error/unknownsymbol}
  }
  \str_set:Nn \l_tmpa_str { #1 }
  \int_set:Nn \l_tmpa_int { \str_count:N \l_tmpa_str }

  \stex_all_symbols:n {
    \str_if_eq:eeT { \l_tmpa_str }{ \str_range:nnn {##1}{-\l_tmpa_int}{-1}}{
      \seq_map_break:n{\seq_map_break:n{
        \tl_set:Nn \l_tmpa_tl {
          \str_set:Nn \l_stex_get_symbol_uri_str { ##1 }
        }
      }}
    }
  }

  \l_tmpa_tl
}

\cs_new_protected:Nn \_@@_get_symbol_from_cs:n {
  \exp_args:NNx \tl_set:Nn \l_tmpa_tl 
    { \tl_tail:N \l_tmpa_tl }
  \tl_if_single:NTF \l_tmpa_tl {
    \exp_args:No \tl_if_head_is_group:nTF \l_tmpa_tl {
      \exp_after:wN \str_set:Nn \exp_after:wN
        \l_stex_get_symbol_uri_str \l_tmpa_tl
    }{
      % TODO
      % tail is not a single group
    }
  }{
    % TODO
    % tail is not a single group
  }
}
%    \end{macrocode}
% \end{macro}
%
% \subsection{Notations}
%    \begin{macrocode}
%<@@=stex_notation>
%    \end{macrocode}
%
% |notation| arguments:
%
%    \begin{macrocode}
\keys_define:nn { stex / notation } {
  lang    .tl_set_x:N  = \l_@@_lang_str ,
  variant .tl_set_x:N  = \l_@@_variant_str ,
  prec    .str_set_x:N = \l_@@_prec_str ,
  op      .tl_set:N    = \l_@@_op_tl ,
  primary .bool_set:N  = \l_@@_primary_bool ,
  primary .default:n   = {true} ,
  unknown .code:n      = \str_set:Nx 
      \l_@@_variant_str \l_keys_key_str
}

\cs_new_protected:Nn \_stex_notation_args:n {
  \str_clear:N \l_@@_lang_str
  \str_clear:N \l_@@_variant_str
  \str_clear:N \l_@@_prec_str
  \tl_clear:N \l_@@_op_tl
  \bool_set_false:N \l_@@_primary_bool
  
  \keys_set:nn { stex / notation } { #1 }
}
%    \end{macrocode}
%
%
%
% \begin{macro}{\notation}
%    \begin{macrocode}
\NewDocumentCommand \notation { s m O{}} {
  \_stex_notation_args:n { #3 }
  \tl_clear:N \l_stex_symdecl_definiens_tl
  \stex_get_symbol:n { #2 }
  \tl_set:Nn \l_stex_notation_after_do_tl {
    \_@@_final:
    \IfBooleanTF#1{
      \stex_setnotation:n {\l_stex_get_symbol_uri_str}
    }{}
    \stex_smsmode_do:
  }
  \stex_notation_do:nnnn
    { \prop_item:cn {l_stex_symdecl_\l_stex_get_symbol_uri_str _prop } { args } }
    { \prop_item:cn { l_stex_symdecl_\l_stex_get_symbol_uri_str _prop } { arity } }
    { \l_@@_variant_str \c_hash_str \l_@@_lang_str }
}
\stex_deactivate_macro:Nn \notation {module~environments}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\stex_notation_do:nnnn}
%    \begin{macrocode}
\seq_new:N \l_@@_precedences_seq
\tl_new:N \l_@@_opprec_tl
\int_new:N \l_@@_currarg_int
\tl_new:N \stex_symbol_after_invocation_tl

\cs_new_protected:Nn \stex_notation_do:nnnn {
  \let\l_stex_current_symbol_str\relax
  \seq_clear:N \l_@@_precedences_seq
  \tl_clear:N \l_@@_opprec_tl
  \str_set:Nx \l_@@_args_str { #1 }
  \str_set:Nx \l_@@_arity_str { #2 }
  \str_set:Nx \_@@_suffix_str { #3 }

  % precedences
  \str_if_empty:NTF \l_@@_prec_str {
    \int_compare:nNnTF \l_@@_arity_str = 0 {
      \tl_set:No \l_@@_opprec_tl { \neginfprec }
    }{
      \tl_set:Nn \l_@@_opprec_tl { 0 }
    }
  } {
    \str_if_eq:onTF \l_@@_prec_str {nobrackets}{
      \tl_set:No \l_@@_opprec_tl { \neginfprec }
      \int_step_inline:nn { \l_@@_arity_str } {
        \exp_args:NNo
        \seq_put_right:Nn \l_@@_precedences_seq { \infprec }
      }
    }{
      \seq_set_split:NnV \l_tmpa_seq ; \l_@@_prec_str
      \seq_pop_left:NNTF \l_tmpa_seq \l_tmpa_str {
        \tl_set:No \l_@@_opprec_tl { \l_tmpa_str }
        \seq_pop_left:NNT \l_tmpa_seq \l_tmpa_str {
          \exp_args:NNNo \exp_args:NNno \seq_set_split:Nnn 
            \l_tmpa_seq {\tl_to_str:n{x} } { \l_tmpa_str }
          \seq_map_inline:Nn \l_tmpa_seq {
            \seq_put_right:Nn \l_tmpb_seq { ##1 }
          }
        }
      }{
        \int_compare:nNnTF \l_@@_arity_str = 0 {
          \tl_set:No \l_@@_opprec_tl { \infprec }
        }{
          \tl_set:No \l_@@_opprec_tl { 0 }
        }
      }
    }
  }

  \seq_set_eq:NN \l_tmpa_seq \l_@@_precedences_seq
  \int_step_inline:nn { \l_@@_arity_str } {
    \seq_pop_left:NNF \l_tmpa_seq \l_tmpb_str {
      \exp_args:NNo
      \seq_put_right:No \l_@@_precedences_seq { 
        \l_@@_opprec_tl
      }
    }
  }
  \tl_clear:N \l_stex_notation_dummyargs_tl

  \int_compare:nNnTF \l_@@_arity_str = 0 {
    \exp_args:NNe
    \cs_set:Npn \l_stex_notation_macrocode_cs {
      \_stex_term_math_oms:nnnn { \l_stex_current_symbol_str } 
        { \_@@_suffix_str }
        { \l_@@_opprec_tl } 
        { \exp_not:n { #4 } }
    }
    \l_stex_notation_after_do_tl
  }{
    \str_if_in:NnTF \l_@@_args_str b {
      \exp_args:Nne \use:nn
      {
      \cs_generate_from_arg_count:NNnn \l_stex_notation_macrocode_cs
      \cs_set:Npn \l_@@_arity_str } { {
        \_stex_term_math_omb:nnnn { \l_stex_current_symbol_str } 
          { \_@@_suffix_str }
          { \l_@@_opprec_tl } 
          { \exp_not:n { #4 } }
      }}
    }{
      \str_if_in:NnTF \l_@@_args_str B {
        \exp_args:Nne \use:nn
        {
        \cs_generate_from_arg_count:NNnn \l_stex_notation_macrocode_cs
        \cs_set:Npn \l_@@_arity_str } { {
          \_stex_term_math_omb:nnnn { \l_stex_current_symbol_str } 
            { \_@@_suffix_str }
            { \l_@@_opprec_tl } 
            { \exp_not:n { #4 } }
        } }
      }{
        \exp_args:Nne \use:nn
        {
        \cs_generate_from_arg_count:NNnn \l_stex_notation_macrocode_cs
        \cs_set:Npn \l_@@_arity_str } { {
          \_stex_term_math_oma:nnnn { \l_stex_current_symbol_str } 
            { \_@@_suffix_str }
            { \l_@@_opprec_tl } 
            { \exp_not:n { #4 } }
        } }
      }
    }

    \str_set_eq:NN \l_@@_remaining_args_str \l_@@_args_str
    \int_zero:N \l_@@_currarg_int
    \seq_set_eq:NN \l_@@_remaining_precs_seq \l_@@_precedences_seq
    \_@@_arguments:
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\_@@_arguments:}
%
% Takes care of annotating the arguments in a
% notation macro
%
%    \begin{macrocode}
\cs_new_protected:Nn \_@@_arguments: {
  \int_incr:N \l_@@_currarg_int
  \str_if_empty:NTF \l_@@_remaining_args_str {
    \l_stex_notation_after_do_tl
  }{
    \str_set:Nx \l_tmpa_str { \str_head:N \l_@@_remaining_args_str }
    \str_set:Nx \l_@@_remaining_args_str { \str_tail:N \l_@@_remaining_args_str }
    \str_if_eq:VnTF \l_tmpa_str a {
      \_@@_argument_assoc:n
    }{
      \str_if_eq:VnTF \l_tmpa_str B {
        \_@@_argument_assoc:n
      }{
        \seq_pop_left:NN \l_@@_remaining_precs_seq \l_tmpa_str
        \tl_put_right:Nx \l_stex_notation_dummyargs_tl {
          { \_stex_term_math_arg:nnn
            { \int_use:N \l_@@_currarg_int }
            { \l_tmpa_str }
            { ####\int_use:N \l_@@_currarg_int }
          }
        }
        \_@@_arguments:
      }
    }
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\_@@_argument_assoc:n}
%    \begin{macrocode}
\cs_new_protected:Nn \_@@_argument_assoc:n {

  \cs_generate_from_arg_count:NNnn \l_tmpa_cs \cs_set:Npn 
    {\l_@@_arity_str}{
    #1
  }
  \int_zero:N \l_tmpa_int
  \tl_clear:N \l_tmpa_tl
  \str_map_inline:Nn \l_@@_args_str {
    \int_incr:N \l_tmpa_int
    \tl_put_right:Nx \l_tmpa_tl {
      \str_if_eq:nnTF {##1}{a}{ {} }{
        \str_if_eq:nnTF {##1}{B}{ {} }{
          {\_stex_term_arg:nn{\int_use:N \l_tmpa_int}{################ \int_use:N \l_tmpa_int}}
        }
      }
    }
  }
  \exp_after:wN\exp_after:wN\exp_after:wN \def 
  \exp_after:wN\exp_after:wN\exp_after:wN \l_tmpa_cs 
  \exp_after:wN\exp_after:wN\exp_after:wN ## 
  \exp_after:wN\exp_after:wN\exp_after:wN 1 
  \exp_after:wN\exp_after:wN\exp_after:wN ## 
  \exp_after:wN\exp_after:wN\exp_after:wN 2 
  \exp_after:wN\exp_after:wN\exp_after:wN {
    \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_tmpa_cs \l_tmpa_tl
    }
  }

  \seq_pop_left:NN \l_@@_remaining_precs_seq \l_tmpa_str
  \tl_put_right:Nx \l_stex_notation_dummyargs_tl { {
    \_stex_term_math_assoc_arg:nnnn
      { \int_use:N \l_@@_currarg_int }
      { \l_tmpa_str }
      { ####\int_use:N \l_@@_currarg_int }
      { \l_tmpa_cs {####1} {####2} }
  } }
  \_@@_arguments:
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\_@@_final:}
%
% Called after processing all notation arguments
%
%    \begin{macrocode}
\cs_new_protected:Nn \_@@_final: {
  \exp_args:Nne \use:nn
  {
  \cs_generate_from_arg_count:cNnn {
      stex_notation_ \l_stex_get_symbol_uri_str \c_hash_str 
      \_@@_suffix_str
      _cs
    }
    \cs_set:Npn \l_@@_arity_str } { {
      \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_notation_macrocode_cs \l_stex_notation_dummyargs_tl \stex_symbol_after_invocation_tl}
  } }

  \tl_if_empty:NF \l_@@_op_tl {
    \cs_set:cpx {
      stex_op_notation_ \l_stex_get_symbol_uri_str \c_hash_str
      \_@@_suffix_str
      _cs
    } {
      \_stex_term_oms:nnn {
        \l_stex_get_symbol_uri_str \c_hash_str \_@@_suffix_str
      }{
        \l_stex_get_symbol_uri_str
      }{ \comp{ \exp_args:No \exp_not:n { \l_@@_op_tl } } }
    }
  }

  \exp_args:Ne
  \stex_add_to_current_module:n {
    \cs_generate_from_arg_count:cNnn {
      stex_notation_ \l_stex_get_symbol_uri_str \c_hash_str 
      \_@@_suffix_str
      _cs
    } \cs_set:Npn {\l_@@_arity_str} {
        \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_notation_macrocode_cs \l_stex_notation_dummyargs_tl \stex_symbol_after_invocation_tl}
    }
    \tl_if_empty:NF \l_@@_op_tl {
      \cs_set:cpn {
        stex_op_notation_\l_stex_get_symbol_uri_str \c_hash_str
        \_@@_suffix_str
        _cs
      } {
        \_stex_term_oms:nnn {
          \l_stex_get_symbol_uri_str\c_hash_str \_@@_suffix_str
        }{
          \l_stex_get_symbol_uri_str
        }{ \comp{ \exp_args:No \exp_not:n { \l_@@_op_tl } } }
      }
    }
  }
  %\exp_args:Nx
 % \stex_do_up_to_module:n {
    \seq_put_right:cx {
      l_stex_symdecl_ \l_stex_get_symbol_uri_str
      _notations
    } {
      \_@@_suffix_str
    }
 % }

  \stex_debug:nn{symbols}{
    Notation~\_@@_suffix_str
    ~for~\l_stex_get_symbol_uri_str^^J
    Operator~precedence:~\l_@@_opprec_tl^^J
    Argument~precedences:~
      \seq_use:Nn \l_@@_precedences_seq {,~}^^J
    Notation: \cs_meaning:c {
      stex_notation_ \l_stex_get_symbol_uri_str \c_hash_str 
      \_@@_suffix_str
      _cs
    }
  }
  
  \exp_args:Ne
  \stex_add_to_current_module:n {
    \seq_put_right:cn {
      l_stex_symdecl_\l_stex_get_symbol_uri_str
      _notations
    } { \_@@_suffix_str }
  }

  \stex_if_smsmode:F {

    % HTML annotations
    \stex_if_do_html:T {
      \stex_annotate_invisible:nnn { notation }
      { \l_stex_get_symbol_uri_str } {
        \stex_annotate_invisible:nnn { notationfragment }
          { \_@@_suffix_str }{}
        \stex_annotate_invisible:nnn { precedence }
          { \l_@@_prec_str }{}

        \int_zero:N \l_tmpa_int
        \str_set_eq:NN \l_@@_remaining_args_str \l_@@_args_str
        \tl_clear:N \l_tmpa_tl
        \int_step_inline:nn { \l_@@_arity_str }{
          \int_incr:N \l_tmpa_int
          \str_set:Nx \l_tmpb_str { \str_head:N \l_@@_remaining_args_str }
          \str_set:Nx \l_@@_remaining_args_str { \str_tail:N \l_@@_remaining_args_str }
          \str_if_eq:VnTF \l_tmpb_str a {
            \tl_set:Nx \l_tmpa_tl { \l_tmpa_tl { 
              \c_hash_str \c_hash_str \int_use:N \l_tmpa_int a ,
              \c_hash_str \c_hash_str \int_use:N \l_tmpa_int b
            } }
          }{
            \str_if_eq:VnTF \l_tmpb_str B {
              \tl_set:Nx \l_tmpa_tl { \l_tmpa_tl { 
                \c_hash_str \c_hash_str \int_use:N \l_tmpa_int a ,
                \c_hash_str \c_hash_str \int_use:N \l_tmpa_int b
              } }
            }{
              \tl_set:Nx \l_tmpa_tl { \l_tmpa_tl { 
                \c_hash_str \c_hash_str \int_use:N \l_tmpa_int
              } }
            }
          }
        }
        \stex_annotate_invisible:nnn { notationcomp }{}{
          \str_set:Nx \l_stex_current_symbol_str {\l_stex_get_symbol_uri_str }
          $ \exp_args:Nno \use:nn { \use:c {
            stex_notation_ \l_stex_current_symbol_str
            \c_hash_str \_@@_suffix_str _cs
          } } { \l_tmpa_tl } $
        }
      }
    }
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\setnotation}
%    \begin{macrocode}
\keys_define:nn { stex / setnotation } {
  lang    .tl_set_x:N  = \l_@@_lang_str ,
  variant .tl_set_x:N  = \l_@@_variant_str ,
  unknown .code:n      = \str_set:Nx 
      \l_@@_variant_str \l_keys_key_str
}

\cs_new_protected:Nn \_stex_setnotation_args:n {
  \str_clear:N \l_@@_lang_str
  \str_clear:N \l_@@_variant_str
  \keys_set:nn { stex / setnotation } { #1 }
}

\cs_new_protected:Nn \stex_setnotation:n {
  \exp_args:Nnx \seq_if_in:cnTF { l_stex_symdecl_#1 _notations }
    { \l_@@_variant_str \c_hash_str \l_@@_lang_str }{
      \exp_args:Nnx \seq_remove_all:cn { l_stex_symdecl_#1 _notations }
        { \l_@@_variant_str \c_hash_str \l_@@_lang_str }
      \exp_args:Nnx \seq_remove_all:cn { l_stex_symdecl_#1 _notations }
        { \c_hash_str }
      \exp_args:Nnx \seq_put_left:cn { l_stex_symdecl_#1 _notations }
        { \l_@@_variant_str \c_hash_str \l_@@_lang_str }
      \exp_args:Nx \stex_add_to_current_module:n {
        \exp_args:Nnx \seq_remove_all:cn { l_stex_symdecl_#1 _notations }
          { \l_@@_variant_str \c_hash_str \l_@@_lang_str }
        \exp_args:Nnx \seq_put_left:cn { l_stex_symdecl_#1 _notations }
          { \l_@@_variant_str \c_hash_str \l_@@_lang_str }
        \exp_args:Nnx \seq_remove_all:cn { l_stex_symdecl_#1 _notations }
          { \c_hash_str }
      }
      \stex_debug:nn {notations}{
        Setting~default~notation~
        {\l_@@_variant_str \c_hash_str \l_@@_lang_str}~for~
        #1 \\
        \expandafter\meaning\csname
        l_stex_symdecl_#1 _notations\endcsname
      }
    }{
      % todo throw error
    }
}

\NewDocumentCommand \setnotation {m m} {
  \stex_get_symbol:n { #1 }
  \_stex_setnotation_args:n { #2 }
  \stex_setnotation:n{\l_stex_get_symbol_uri_str}
  \stex_smsmode_do:
}

\cs_new_protected:Nn \stex_copy_notations:nn {
  \stex_debug:nn {notations}{
    Copying~notations~from~#2~to~#1\\
    \seq_use:cn{l_stex_symdecl_#2_notations}{,~}
  }
  \tl_clear:N \l_tmpa_tl
  \int_step_inline:nn { \prop_item:cn {l_stex_symdecl_#2_prop}{ arity } } {
    \tl_put_right:Nn \l_tmpa_tl { {## ##1} }
  }
  \seq_map_inline:cn {l_stex_symdecl_#2_notations}{
    \cs_set_eq:Nc \l_tmpa_cs { stex_notation_ #2 \c_hash_str ##1 _cs }
    \edef \l_tmpa_tl {
      \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_tmpa_cs \l_tmpa_tl
      }
    }
    \exp_args:Nx
    \stex_do_up_to_module:n {
      \seq_put_right:cn{l_stex_symdecl_#1_notations}{##1}
      \cs_generate_from_arg_count:cNnn {
        stex_notation_ #1 \c_hash_str ##1 _cs
      } \cs_set:Npn { \prop_item:cn {l_stex_symdecl_#2_prop}{ arity } }{
        \exp_after:wN\exp_not:n\exp_after:wN{\l_tmpa_tl}
      }
    }
  }
}

\NewDocumentCommand \copynotation {m m} {
  \stex_get_symbol:n { #1 }
  \str_set_eq:NN \l_tmpa_str \l_stex_get_symbol_uri_str
  \stex_get_symbol:n { #2 }
  \exp_args:Noo
  \stex_copy_notations:nn \l_tmpa_str \l_stex_get_symbol_uri_str
  \exp_args:Nx \stex_add_import_to_current_module:n{
    \stex_copy_notations:nn {\l_tmpa_str} {\l_stex_get_symbol_uri_str}
  }
  \stex_smsmode_do:
}

%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\symdef}
%    \begin{macrocode}
\keys_define:nn { stex / symdef } {
  name    .str_set_x:N = \l_stex_symdecl_name_str ,
  local   .bool_set:N  = \l_stex_symdecl_local_bool ,
  args    .str_set_x:N = \l_stex_symdecl_args_str ,
  type    .tl_set:N    = \l_stex_symdecl_type_tl ,
  def     .tl_set:N    = \l_stex_symdecl_definiens_tl ,
  op      .tl_set:N    = \l_@@_op_tl ,
  lang    .str_set_x:N = \l_@@_lang_str ,
  variant .str_set_x:N = \l_@@_variant_str ,
  prec    .str_set_x:N = \l_@@_prec_str ,
  assoc   .choices:nn  = 
      {bin,binl,binr,pre,conj,pwconj}
      {\str_set:Nx \l_stex_symdecl_assoctype_str {\l_keys_choice_tl}},
  unknown .code:n      = \str_set:Nx 
      \l_@@_variant_str \l_keys_key_str
}

\cs_new_protected:Nn \_@@_symdef_args:n {
  \str_clear:N \l_stex_symdecl_name_str
  \str_clear:N \l_stex_symdecl_args_str
  \str_clear:N \l_stex_symdecl_assoctype_str
  \bool_set_false:N \l_stex_symdecl_local_bool
  \tl_clear:N \l_stex_symdecl_type_tl
  \tl_clear:N \l_stex_symdecl_definiens_tl
  \str_clear:N \l_@@_lang_str
  \str_clear:N \l_@@_variant_str
  \str_clear:N \l_@@_prec_str
  \tl_clear:N \l_@@_op_tl
  
  \keys_set:nn { stex / symdef } { #1 }
}

\NewDocumentCommand \symdef { m O{} } {
  \_@@_symdef_args:n { #2 }
  \bool_set_true:N \l_stex_symdecl_make_macro_bool
  \stex_symdecl_do:n { #1 }
  \tl_set:Nn \l_stex_notation_after_do_tl {
    \_@@_final:
    \stex_smsmode_do:
  }
  \str_set:Nx \l_stex_get_symbol_uri_str {
    \l_stex_current_module_str ? \l_stex_symdecl_name_str
  }
  \exp_args:Nx \stex_notation_do:nnnn
    { \prop_item:cn {l_stex_symdecl_\l_stex_get_symbol_uri_str _prop } { args } }
    { \prop_item:cn { l_stex_symdecl_\l_stex_get_symbol_uri_str _prop } { arity } }
    { \l_@@_variant_str \c_hash_str \l_@@_lang_str }
}
\stex_deactivate_macro:Nn \symdef {module~environments}
%    \end{macrocode}
% \end{macro}
%
% \subsection{Variables}
%
%    \begin{macrocode}
%<@@=stex_variables>

\keys_define:nn { stex / vardef } {
  name    .str_set_x:N  = \l_@@_name_str ,
  args    .str_set_x:N  = \l_@@_args_str ,
  type    .tl_set:N     = \l_@@_type_tl ,
  def     .tl_set:N     = \l_@@_def_tl ,
  op      .tl_set:N     = \l_@@_op_tl ,
  prec    .str_set_x:N  = \l_@@_prec_str ,
  assoc   .choices:nn   = 
      {bin,binl,binr,pre,conj,pwconj}
      {\str_set:Nx \l_@@_assoctype_str {\l_keys_choice_tl}},
  bind    .choices:nn   =
      {forall,exists}
      {\str_set:Nx \l_@@_bind_str {\l_keys_choice_tl}}
}

\cs_new_protected:Nn \_@@_args:n {
  \str_clear:N \l_@@_name_str
  \str_clear:N \l_@@_args_str
  \str_clear:N \l_@@_prec_str
  \str_clear:N \l_@@_assoctype_str
  \str_clear:N \l_@@_bind_str
  \tl_clear:N \l_@@_type_tl
  \tl_clear:N \l_@@_def_tl
  \tl_clear:N \l_@@_op_tl

  \keys_set:nn { stex / vardef } { #1 }
}

\NewDocumentCommand \_@@_do_simple:nnn { m O{}} {
  \_@@_args:n {#2}
  \str_if_empty:NT \l_@@_name_str {
    \str_set:Nx \l_@@_name_str { #1 }
  }
  \prop_clear:N \l_tmpa_prop
  \prop_put:Nno \l_tmpa_prop { name } \l_@@_name_str
  
  \int_zero:N \l_tmpb_int
  \bool_set_true:N \l_tmpa_bool
  \str_map_inline:Nn \l_@@_args_str {
    \token_case_meaning:NnF ##1 {
      0 {} 1 {} 2 {} 3 {} 4 {} 5 {} 6 {} 7 {} 8 {} 9 {}
      {\tl_to_str:n i} { \bool_set_false:N \l_tmpa_bool }
      {\tl_to_str:n b} { \bool_set_false:N \l_tmpa_bool }
      {\tl_to_str:n a} { 
        \bool_set_false:N \l_tmpa_bool
        \int_incr:N \l_tmpb_int
      }
      {\tl_to_str:n B} { 
        \bool_set_false:N \l_tmpa_bool
        \int_incr:N \l_tmpb_int
      }
    }{
      \msg_error:nnxx{stex}{error/wrongargs}{
        variable~\l_@@_name_str
      }{##1}
    }
  }
  \bool_if:NTF \l_tmpa_bool {
    % possibly numeric
    \str_if_empty:NTF \l_@@_args_str {
      \prop_put:Nnn \l_tmpa_prop { args } {}
      \prop_put:Nnn \l_tmpa_prop { arity } { 0 }
    }{
      \int_set:Nn \l_tmpa_int { \l_@@_args_str }
      \prop_put:Nnx \l_tmpa_prop { arity } { \int_use:N \l_tmpa_int }
      \str_clear:N \l_tmpa_str
      \int_step_inline:nn \l_tmpa_int {
        \str_put_right:Nn \l_tmpa_str i
      }
      \str_set_eq:NN \l_@@_args_str \l_tmpa_str
      \prop_put:Nnx \l_tmpa_prop { args } { \l_@@_args_str }
    }
  } {
    \prop_put:Nnx \l_tmpa_prop { args } { \l_@@_args_str }
    \prop_put:Nnx \l_tmpa_prop { arity }
      { \str_count:N \l_@@_args_str }
  }
  \prop_put:Nnx \l_tmpa_prop { assocs } { \int_use:N \l_tmpb_int }
  \tl_set:cx { #1 }{ \stex_invoke_variable:n { \l_@@_name_str } }

  \prop_set_eq:cN { l_stex_variable_\l_@@_name_str _prop} \l_tmpa_prop

  \tl_if_empty:NF \l_@@_op_tl {
    \cs_set:cpx {
      stex_var_op_notation_ \l_@@_name_str _cs
    } {
      \_stex_term_omv:nn {
        var://\l_@@_name_str
      }{ \comp{ \exp_args:No \exp_not:n { \l_@@_op_tl } } }
    }
  }

  \tl_set:Nn \l_stex_notation_after_do_tl {
    \exp_args:Nne \use:nn {
      \cs_generate_from_arg_count:cNnn { stex_var_notation_\l_@@_name_str _cs }
        \cs_set:Npn { \prop_item:Nn \l_tmpa_prop { arity } }
    } {{
      \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_notation_macrocode_cs \l_stex_notation_dummyargs_tl \stex_symbol_after_invocation_tl}
    }}
    \stex_if_do_html:T {
      \stex_annotate_invisible:nnn {vardecl}{\l_@@_name_str}{
        \stex_annotate_invisible:nnn { precedence }
          { \l_@@_prec_str }{}
        \tl_if_empty:NF \l_@@_type_tl {\stex_annotate_invisible:nnn{type}{}{$\l_@@_type_tl$}}
        \stex_annotate_invisible:nnn{args}{}{ \l_@@_args_str }
        \stex_annotate_invisible:nnn{macroname}{#1}{}
        \tl_if_empty:NF \l_@@_def_tl {
          \stex_annotate_invisible:nnn{definiens}{}
            {$\l_@@_def_tl$}
        }
        \str_if_empty:NF \l_@@_assoctype_str {
          \stex_annotate_invisible:nnn{assoctype}{\l_@@_assoctype_str}{}
        }
        \int_zero:N \l_tmpa_int
        \str_set_eq:NN \l_@@_remaining_args_str \l_@@_args_str
        \tl_clear:N \l_tmpa_tl
        \int_step_inline:nn { \prop_item:Nn \l_tmpa_prop { arity } }{
          \int_incr:N \l_tmpa_int
          \str_set:Nx \l_tmpb_str { \str_head:N \l_@@_remaining_args_str }
          \str_set:Nx \l_@@_remaining_args_str { \str_tail:N \l_@@_remaining_args_str }
          \str_if_eq:VnTF \l_tmpb_str a {
            \tl_set:Nx \l_tmpa_tl { \l_tmpa_tl { 
              \c_hash_str \c_hash_str \int_use:N \l_tmpa_int a ,
              \c_hash_str \c_hash_str \int_use:N \l_tmpa_int b
            } }
          }{
            \str_if_eq:VnTF \l_tmpb_str B {
              \tl_set:Nx \l_tmpa_tl { \l_tmpa_tl { 
                \c_hash_str \c_hash_str \int_use:N \l_tmpa_int a ,
                \c_hash_str \c_hash_str \int_use:N \l_tmpa_int b
              } }
            }{
              \tl_set:Nx \l_tmpa_tl { \l_tmpa_tl { 
                \c_hash_str \c_hash_str \int_use:N \l_tmpa_int
              } }
            }
          }
        }
        \stex_annotate_invisible:nnn { notationcomp }{}{
          \str_set:Nx \l_stex_current_symbol_str {var://\l_@@_name_str }
          $ \exp_args:Nno \use:nn { \use:c {
            stex_var_notation_\l_@@_name_str _cs
          } } { \l_tmpa_tl } $
        }
      }
    }
  }

  \stex_notation_do:nnnn { \l_@@_args_str } { \prop_item:Nn \l_tmpa_prop { arity } } {}
}

\cs_new:Nn \_@@_reset:N {
  \tl_if_exist:NTF #1 {
    \def \exp_not:N #1 { \exp_args:No \exp_not:n #1 }
  }{
    \let \exp_not:N #1 \exp_not:N \undefined
  }
}

\NewDocumentCommand \_@@_do_complex:nn { m m }{
  \clist_set:Nx \l_@@_names { \tl_to_str:n {#1} }
  \exp_args:Nnx \use:nn {
    % TODO
    \stex_annotate_invisible:nnn {vardecls}{\clist_use:Nn\l_@@_names,}{
      #2
    }
  }{
    \_@@_reset:N \varnot
    \_@@_reset:N \vartype
    \_@@_reset:N \vardefi
  }
}

\NewDocumentCommand \vardef { s } {
  \IfBooleanTF#1 {
    \_@@_do_complex:nn
  }{
    \_@@_do_simple:nnn
  }
}

\NewDocumentCommand \svar { O{} m }{
  \tl_if_empty:nTF {#1}{
    \str_set:Nn \l_tmpa_str { #2 }
  }{
    \str_set:Nn \l_tmpa_str { #1 }
  }
  \_stex_term_omv:nn {
        var://\l_tmpa_str
    }{ \comp{ #2 } }
}

%    \end{macrocode}
%
%    \begin{macrocode}
%</package>
%    \end{macrocode}
%
% \end{implementation}
%
% \PrintIndex

% \endinput
% Local Variables:
% mode: doctex
% TeX-master: t
% End:
