% \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-Structural Features
% 	\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-features} 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-features}
% \fi
%
% \begin{documentation}\label{pkg:features:doc}
%
% Code related to structural features
%
% \section{Macros and Environments}\label{pkg:features:doc:macros}
%
% \subsection{Structures}
%
% \begin{environment}{mathstructure}
%   TODO
% \end{environment}
%
% \end{documentation}
%
% \begin{implementation}\label{pkg:features:impl}
%
% \section{\sTeX-Structural Features Implementation}
%
%    \begin{macrocode}
%<*package>

%%%%%%%%%%%%%   features.dtx   %%%%%%%%%%%%%

%<@@=stex_features>
%    \end{macrocode}
%
% Warnings and error messages
%
%    \begin{macrocode}
\msg_new:nnn{stex}{error/copymodule/notallowed}{
  Symbol~#1~can~not~be~assigned~in~copymodule~#2
}
\msg_new:nnn{stex}{error/interpretmodule/nodefiniens}{
  Symbol~#1~not~assigned~in~interpretmodule~#2
}

%    \end{macrocode}
%
% \subsection{Imports with modification}
%
%    \begin{macrocode}
\cs_new_protected:Nn \stex_get_symbol_in_copymodule: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
    }
  }
}

\cs_new_protected:Nn \_@@_get_symbol_from_string:n {
  \str_set:Nn \l_tmpa_str { #1 }
  \bool_set_false:N \l_tmpa_bool
  \bool_if:NF \l_tmpa_bool {
    \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 }
    \seq_map_inline:Nn \l_@@_copymodule_fields_seq {
      \str_set:Nn \l_tmpb_str { ##1 }
      \str_if_eq:eeT { \l_tmpa_str } {
        \str_range:Nnn \l_tmpb_str { -\l_tmpa_int } { -1 }
      } {
        \seq_map_break:n {
          \tl_set:Nn \l_tmpa_tl {
            \str_set:Nn \l_stex_get_symbol_uri_str {
              ##1
            }
            \_@@_get_symbol_check:
          }
        }
      }
    }
    \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
      \_@@_get_symbol_check:
    }{
      % TODO
      % tail is not a single group
    }
  }{
    % TODO
    % tail is not a single group
  }
}

\cs_new_protected:Nn \_@@_get_symbol_check: {
  \exp_args:NNno \seq_set_split:Nnn \l_tmpa_seq {?} \l_stex_get_symbol_uri_str
  \int_compare:nNnTF {\seq_count:N \l_tmpa_seq} = 3 {
    \seq_pop_right:NN \l_tmpa_seq \l_tmpb_str
    \str_set:Nx \l_tmpa_str {\seq_use:Nn \l_tmpa_seq ?}
    \seq_if_in:NoF \l_@@_copymodule_modules_seq \l_tmpa_str {
      \msg_error:nnxx{stex}{error/copymodule/notallowed}{\l_stex_get_symbol_uri_str}{
        \l_stex_current_copymodule_name_str\\Allowed:~\seq_use:Nn \l_@@_copymodule_modules_seq {,~}
        }
    }
  }{
    \msg_error:nnxx{stex}{error/copymodule/notallowed}{\l_stex_get_symbol_uri_str}{
      \l_stex_current_copymodule_name_str~(inexplicably)
    }
  }
}

\cs_new_protected:Nn \stex_copymodule_start:nnnn {
  \stex_import_module_uri:nn { #1 } { #2 }
  \str_set:Nx \l_stex_current_copymodule_name_str {#3}
  \stex_import_require_module:nnnn 
    { \l_stex_import_ns_str } { \l_stex_import_archive_str } 
    { \l_stex_import_path_str } { \l_stex_import_name_str }
  \stex_collect_imports:n {\l_stex_import_ns_str ?\l_stex_import_name_str }
  \seq_set_eq:NN \l_@@_copymodule_modules_seq \l_stex_collect_imports_seq
  \seq_clear:N \l_@@_copymodule_fields_seq
  \seq_map_inline:Nn \l_@@_copymodule_modules_seq {
    \seq_map_inline:cn {c_stex_module_##1_constants}{
      \exp_args:NNx \seq_put_right:Nn \l_@@_copymodule_fields_seq {
        ##1 ? ####1
      }
    }
  }
  \seq_clear:N \l_tmpa_seq
  \exp_args:NNx \prop_set_from_keyval:Nn \l_stex_current_copymodule_prop {
    name      = \l_stex_current_copymodule_name_str ,
    module    = \l_stex_current_module_str ,
    from      = \l_stex_import_ns_str ?\l_stex_import_name_str ,
    includes  = \l_tmpa_seq ,
    fields    = \l_tmpa_seq
  }
  \stex_debug:nn{copymodule}{#4~for~module~{\l_stex_import_ns_str ?\l_stex_import_name_str}
    as~\l_stex_current_module_str?\l_stex_current_copymodule_name_str}
    \stex_debug:nn{copymodule}{modules:\seq_use:Nn \l_@@_copymodule_modules_seq {,~}}
  \stex_debug:nn{copymodule}{fields:\seq_use:Nn \l_@@_copymodule_fields_seq {,~}}
  \stex_if_smsmode:F {
    \begin{stex_annotate_env} {#4} {
      \l_stex_current_module_str?\l_stex_current_copymodule_name_str
    }
    \stex_annotate_invisible:nnn{from}{\l_stex_import_ns_str ?\l_stex_import_name_str}{}
  }
  \bool_set_eq:NN \l_@@_oldhtml_bool \_stex_html_do_output_bool
  \bool_set_false:N \_stex_html_do_output_bool
}
\cs_new_protected:Nn \stex_copymodule_end:n {
  \def \l_tmpa_cs ##1 ##2 {#1}
  \bool_set_eq:NN \_stex_html_do_output_bool \l_@@_oldhtml_bool
  \tl_clear:N \l_tmpa_tl
  \tl_clear:N \l_tmpb_tl
  \prop_get:NnN \l_stex_current_copymodule_prop {fields} \l_tmpa_seq
  \seq_map_inline:Nn \l_@@_copymodule_modules_seq {
    \seq_map_inline:cn {c_stex_module_##1_constants}{
      \tl_clear:N \l_tmpc_tl
      \l_tmpa_cs{##1}{####1}
      \str_if_exist:cTF {l_@@_copymodule_##1?####1_name_str} {
        \tl_put_right:Nx \l_tmpa_tl {
          \prop_set_from_keyval:cn {
            l_stex_symdecl_\l_stex_current_module_str ? \use:c{l_@@_copymodule_##1?####1_name_str}_prop
          }{
            \exp_after:wN \prop_to_keyval:N \csname
              l_stex_symdecl_\l_stex_current_module_str ? \use:c{l_@@_copymodule_##1?####1_name_str}_prop
            \endcsname
          }
          \seq_clear:c {
            l_stex_symdecl_ 
            \l_stex_current_module_str ? \use:c{l_@@_copymodule_##1?####1_name_str}
            _notations
          }
        }
        \tl_put_right:Nx \l_tmpc_tl { 
          \stex_copy_notations:nn {\l_stex_current_module_str ? \use:c{l_@@_copymodule_##1?####1_name_str}}{##1?####1}
          \stex_annotate_invisible:nnn{alias}{\use:c{l_@@_copymodule_##1?####1_name_str}}{}
        }
        \seq_put_right:Nx \l_tmpa_seq {\l_stex_current_module_str ? \use:c{l_@@_copymodule_##1?####1_name_str}}
        \str_if_exist:cT {l_@@_copymodule_##1?####1_macroname_str} {
          \tl_put_right:Nx \l_tmpc_tl { 
            \stex_annotate_invisible:nnn{macroname}{\use:c{l_@@_copymodule_##1?####1_macroname_str}}{}
          }
          \tl_put_right:Nx \l_tmpa_tl {
            \tl_set:cx {\use:c{l_@@_copymodule_##1?####1_macroname_str}}{
              \stex_invoke_symbol:n {
                \l_stex_current_module_str ? \use:c{l_@@_copymodule_##1?####1_name_str}
              }
            }
          }
        }
      }{
        \tl_put_right:Nx \l_tmpc_tl {
          \stex_copy_notations:nn {\l_stex_current_module_str ? \l_stex_current_copymodule_name_str / ####1 }{##1?####1}
        }
        \prop_set_eq:Nc \l_tmpa_prop {l_stex_symdecl_ ##1?####1 _prop}
        \prop_put:Nnx \l_tmpa_prop { name }{ \l_stex_current_copymodule_name_str / ####1 }
        \prop_put:Nnx \l_tmpa_prop { module }{ \l_stex_current_module_str }
        \tl_put_right:Nx \l_tmpa_tl {
          \prop_set_from_keyval:cn {
            l_stex_symdecl_\l_stex_current_module_str ? \l_stex_current_copymodule_name_str / ####1_prop
          }{
            \prop_to_keyval:N \l_tmpa_prop
          }
          \seq_clear:c {
            l_stex_symdecl_ 
            \l_stex_current_module_str ? \l_stex_current_copymodule_name_str / ####1
            _notations
          }
        }
        \seq_put_right:Nx \l_tmpa_seq {\l_stex_current_module_str ? \l_stex_current_copymodule_name_str / ####1 }
        \str_if_exist:cT {l_@@_copymodule_##1?####1_macroname_str} {
          \tl_put_right:Nx \l_tmpc_tl { 
            \stex_annotate_invisible:nnn{macroname}{\use:c{l_@@_copymodule_##1?####1_macroname_str}}{}
          }
          \tl_put_right:Nx \l_tmpa_tl {
            \tl_set:cx {\use:c{l_@@_copymodule_##1?####1_macroname_str}}{
              \stex_invoke_symbol:n {
                \l_stex_current_module_str ? \l_stex_current_copymodule_name_str / ####1
              }
            }
          }
        }
      }
      \tl_if_exist:cT {l_@@_copymodule_##1?####1_def_tl}{
        \tl_put_right:Nx \l_tmpc_tl { 
          \stex_annotate_invisible:nnn{definiens}{}{$\use:c{l_@@_copymodule_##1?####1_def_tl}$}
        }
      }
      \tl_put_right:Nx \l_tmpb_tl {
        \stex_annotate:nnn{assignment} {##1?####1} { \l_tmpc_tl }
      }
    }
  }
  \prop_put:Nno \l_stex_current_copymodule_prop {fields} \l_tmpa_seq
  \tl_put_left:Nx \l_tmpa_tl {
    \prop_set_from_keyval:cn {
      l_stex_copymodule_ \l_stex_current_module_str?\l_stex_current_copymodule_name_str _prop
    }{
      \prop_to_keyval:N \l_stex_current_copymodule_prop
    }
  }
  \exp_args:No \stex_add_to_current_module:n \l_tmpa_tl
  \stex_debug:nn{copymodule}{result:\meaning \l_tmpa_tl}
  \exp_args:Nx \stex_do_up_to_module:n { 
      \exp_args:No \exp_not:n \l_tmpa_tl
  }
  \l_tmpb_tl
  \stex_if_smsmode:F {
    \end{stex_annotate_env}
  }
}

\NewDocumentEnvironment {copymodule} { O{} m m}{
  \stex_copymodule_start:nnnn { #1 }{ #2 }{ #3 }{ structure }
  \stex_deactivate_macro:Nn \symdecl {module~environments}
  \stex_deactivate_macro:Nn \symdef {module~environments}
  \stex_deactivate_macro:Nn \notation {module~environments}
  \stex_reactivate_macro:N \assign
  \stex_reactivate_macro:N \renamedecl
  \stex_reactivate_macro:N \donotcopy
  \stex_smsmode_do:
}{
  \stex_copymodule_end:n {}
}

\NewDocumentEnvironment {interpretmodule} { O{} m m}{
  \stex_copymodule_start:nnnn { #1 }{ #2 }{ #3 }{ realization }
  \stex_deactivate_macro:Nn \symdecl {module~environments}
  \stex_deactivate_macro:Nn \symdef {module~environments}
  \stex_deactivate_macro:Nn \notation {module~environments}
  \stex_reactivate_macro:N \assign
  \stex_reactivate_macro:N \renamedecl
  \stex_reactivate_macro:N \donotcopy
  \stex_smsmode_do:
}{
  \stex_copymodule_end:n {
    \tl_if_exist:cF {
      l_@@_copymodule_##1?##2_def_tl
    }{
      \msg_error:nnxx{stex}{error/interpretmodule/nodefiniens}{
        ##1?##2
      }{\l_stex_current_copymodule_name_str}
    }
  }
}

\NewDocumentCommand \donotcopy { O{} m}{
  \stex_import_module_uri:nn { #1 } { #2 }
  \stex_collect_imports:n {\l_stex_import_ns_str ?\l_stex_import_name_str }
  \seq_map_inline:Nn \l_stex_collect_imports_seq {
    \seq_remove_all:Nn \l_@@_copymodule_modules_seq { ##1 }
    \seq_map_inline:cn {c_stex_module_##1_constants}{
      \seq_remove_all:Nn \l_@@_copymodule_fields_seq { ##1 ? ####1 }
      \bool_lazy_any_p:nT {
        { \cs_if_exist_p:c {l_@@_copymodule_##1?####1_name_str}}
        { \cs_if_exist_p:c {l_@@_copymodule_##1?####1_macroname_str}}
        { \cs_if_exist_p:c {l_@@_copymodule_##1?####1_def_tl}}
      }{
        % TODO throw error
      }
    }
  }

  \prop_get:NnN \l_stex_current_copymodule_prop { includes } \l_tmpa_seq
  \seq_put_right:Nx \l_tmpa_seq {\l_stex_import_ns_str ?\l_stex_import_name_str }
  \prop_put:Nnx \l_stex_current_copymodule_prop {includes} \l_tmpa_seq
}

\NewDocumentCommand \assign { m m }{
  \stex_get_symbol_in_copymodule:n {#1}
  \stex_debug:nn{assign}{defining~{\l_stex_get_symbol_uri_str}~as~\detokenize{#2}}
  \tl_set:cn {l_@@_copymodule_\l_stex_get_symbol_uri_str _def_tl}{#2}
}

\keys_define:nn { stex / renamedecl } {
  name        .str_set_x:N  = \l_stex_renamedecl_name_str
}
\cs_new_protected:Nn \_@@_renamedecl_args:n {
  \str_clear:N \l_stex_renamedecl_name_str
  
  \keys_set:nn { stex / renamedecl } { #1 }
}

\NewDocumentCommand \renamedecl { O{} m m}{
  \_@@_renamedecl_args:n { #1 }
  \stex_get_symbol_in_copymodule:n {#2}
  \stex_debug:nn{renamedecl}{renaming~{\l_stex_get_symbol_uri_str}~to~#3}
  \str_set:cx {l_@@_copymodule_\l_stex_get_symbol_uri_str _macroname_str}{#3}
  \str_if_empty:NTF \l_stex_renamedecl_name_str {
    \tl_set:cx { #3 }{ \stex_invoke_symbol:n {
      \l_stex_get_symbol_uri_str
    } }
  } {
    \str_set:cx {l_@@_copymodule_\l_stex_get_symbol_uri_str _name_str}{\l_stex_renamedecl_name_str}
    \stex_debug:nn{renamedecl}{@~\l_stex_current_module_str ? \l_stex_renamedecl_name_str}
    \prop_set_eq:cc {l_stex_symdecl_ 
      \l_stex_current_module_str ? \l_stex_renamedecl_name_str
      _prop
    }{l_stex_symdecl_ \l_stex_get_symbol_uri_str _prop}
    \seq_set_eq:cc {l_stex_symdecl_ 
      \l_stex_current_module_str ? \l_stex_renamedecl_name_str
      _notations
    }{l_stex_symdecl_ \l_stex_get_symbol_uri_str _notations}
    \prop_put:cnx {l_stex_symdecl_ 
      \l_stex_current_module_str ? \l_stex_renamedecl_name_str
      _prop
    }{ name }{ \l_stex_renamedecl_name_str }
    \prop_put:cnx {l_stex_symdecl_ 
      \l_stex_current_module_str ? \l_stex_renamedecl_name_str
      _prop
    }{ module }{ \l_stex_current_module_str }
    \exp_args:NNx \seq_put_left:Nn \l_@@_copymodule_fields_seq {
      \l_stex_current_module_str ? \l_stex_renamedecl_name_str
    }
    \tl_set:cx { #3 }{ \stex_invoke_symbol:n {
      \l_stex_current_module_str ? \l_stex_renamedecl_name_str
    } }
  }
}

\stex_deactivate_macro:Nn \assign {copymodules}
\stex_deactivate_macro:Nn \renamedecl {copymodules}
\stex_deactivate_macro:Nn \donotcopy {copymodules}


%    \end{macrocode}
%
%
%
%    \begin{macrocode}
\seq_new:N \l_stex_implicit_morphisms_seq
\NewDocumentCommand \implicitmorphism { O{} m m}{
  \stex_import_module_uri:nn { #1 } { #2 }
  \stex_debug:nn{implicits}{
    Implicit~morphism:~
    \l_stex_module_ns_str ? \l_@@_name_str
  }
  \exp_args:NNx \seq_if_in:NnT \l_stex_all_modules_seq {
    \l_stex_module_ns_str ? \l_@@_name_str
  }{
    \msg_error:nnn{stex}{error/conflictingmodules}{
      \l_stex_module_ns_str ? \l_@@_name_str
    }
  }

  % TODO
  


  \seq_put_right:Nx \l_stex_implicit_morphisms_seq {
    \l_stex_module_ns_str ? \l_@@_name_str
  }
}

%    \end{macrocode}
%
%
% \subsection{The feature environment}
%
% \begin{environment}{structural@feature}
%    \begin{macrocode}

\NewDocumentEnvironment{structural@feature}{ m m m }{
  \stex_if_in_module:F {
    \msg_set:nnn{stex}{error/nomodule}{
      Structural~Feature~has~to~occur~in~a~module:\\
      Feature~#2~of~type~#1\\
      In~File:~\stex_path_to_string:N \g_stex_currentfile_seq
    }
    \msg_error:nn{stex}{error/nomodule}
  }

  \str_set:Nx \l_stex_module_name_str {
    \prop_item:Nn \l_stex_current_module_prop
      { name } / #2 - feature
  }
  
  \str_set:Nx \l_stex_module_ns_str {
    \prop_item:Nn \l_stex_current_module_prop
      { ns }
  }

  
  \str_clear:N \l_tmpa_str
  \seq_clear:N \l_tmpa_seq
  \tl_clear:N \l_tmpa_tl
  \exp_args:NNx \prop_set_from_keyval:Nn \l_stex_current_module_prop {
    origname  = #2,
    name      = \l_stex_module_name_str ,
    ns        = \l_stex_module_ns_str ,
    imports   = \exp_not:o { \l_tmpa_seq } ,
    constants = \exp_not:o { \l_tmpa_seq } ,
    content   = \exp_not:o { \l_tmpa_tl }  ,
    file      = \exp_not:o { \g_stex_currentfile_seq } ,
    lang      = \l_stex_module_lang_str ,
    sig       = \l_tmpa_str ,
    meta      = \l_tmpa_str ,
    feature   = #1 ,
  }

  \stex_if_smsmode:F {
    \begin{stex_annotate_env}{ feature:#1 }{}
      \stex_annotate_invisible:nnn{header}{}{ #3 }
  }
}{  
  \str_set:Nx \l_tmpa_str {
    c_stex_feature_
    \prop_item:Nn \l_stex_current_module_prop { ns } ?
    \prop_item:Nn \l_stex_current_module_prop { name }
    _prop
  }
  \prop_gset_eq:cN { \l_tmpa_str } \l_stex_current_module_prop
  \prop_gset_eq:NN \g_stex_last_feature_prop \l_stex_current_module_prop
  \stex_if_smsmode:F {
    \end{stex_annotate_env}
  }
}

%    \end{macrocode}
% \end{environment}
%
%
% \subsection{Features}
%
% \begin{environment}{structure}
%    \begin{macrocode}

\prop_new:N \l_stex_all_structures_prop

\keys_define:nn { stex / features / structure } {
  name         .str_set_x:N  = \l_@@_structure_name_str ,
}

\cs_new_protected:Nn \_@@_structure_args:n {
  \str_clear:N \l_@@_structure_name_str
  \keys_set:nn { stex / features / structure } { #1 }
}

\NewDocumentEnvironment{mathstructure}{ O{} m }{
  \_@@_structure_args:n { #1 }
  \str_if_empty:NT \l_@@_structure_name_str {
    \str_set:Nx \l_@@_structure_name_str { #2 }
  }
  \exp_args:Nnnx
  \begin{structural@feature}{ structure }
    { \l_@@_structure_name_str }{}
    \seq_clear:N \l_tmpa_seq
    \prop_put:Nno \l_stex_current_module_prop { fields } \l_tmpa_seq
    \stex_smsmode_do:
}{
    \prop_get:NnN \l_stex_current_module_prop { constants } \l_tmpa_seq
    \prop_get:NnN \l_stex_current_module_prop { fields } \l_tmpb_seq
    \str_set:Nx \l_tmpa_str {
      \prop_item:Nn \l_stex_current_module_prop { ns } ?
      \prop_item:Nn \l_stex_current_module_prop { name }
    }
    \seq_map_inline:Nn \l_tmpa_seq {
      \exp_args:NNx \seq_put_right:Nn \l_tmpb_seq { \l_tmpa_str ? ##1 }
    }
    \prop_put:Nno \l_stex_current_module_prop { fields } { \l_tmpb_seq }
    \exp_args:Nnx
    \AddToHookNext { env / mathstructure / after }{
      \symdecl{ #2 }[type = \exp_not:N\collection,def={\STEXsymbol{module-type}{
        \_stex_term_math_oms:nnnn { \l_tmpa_str }{}{0}{}
      }}, name = \prop_item:Nn \l_stex_current_module_prop { origname }]
      \STEXexport {
        \prop_put:Nno \exp_not:N \l_stex_all_structures_prop 
          {\prop_item:Nn \l_stex_current_module_prop { origname }}
          {\l_tmpa_str}
          \prop_put:Nno \exp_not:N \l_stex_all_structures_prop 
            {#2}{\l_tmpa_str}
%        \seq_put_right:Nn \exp_not:N \l_stex_all_structures_seq {
%          \prop_item:Nn \l_stex_current_module_prop { origname },
%          \l_tmpa_str
%        }
%        \seq_put_right:Nn \exp_not:N \l_stex_all_structures_seq {
%          #2,\l_tmpa_str
%        }
%        \tl_set:cx { #2 } { 
%          \stex_invoke_structure:n { \l_tmpa_str }
      }
    }
    
  \end{structural@feature}
  % \g_stex_last_feature_prop
}
%    \end{macrocode}
% \end{environment}
%
%
% \begin{macro}{\instantiate}
%    \begin{macrocode}
\seq_new:N \l_@@_structure_field_seq
\str_new:N \l_@@_structure_field_str
\str_new:N \l_@@_structure_def_tl
\prop_new:N \l_@@_structure_prop
\NewDocumentCommand \instantiate { m O{} m }{
  \prop_get:NnN \l_stex_all_structures_prop {#1} \l_tmpa_str
  \prop_set_eq:Nc \l_@@_structure_prop {
    c_stex_feature_\l_tmpa_str _prop
  }
  \seq_set_from_clist:Nn \l_@@_structure_field_seq { #2 }
  \seq_map_inline:Nn \l_@@_structure_field_seq {
    \seq_set_split:Nnn \l_tmpa_seq{=}{ ##1 }
    \int_compare:nNnTF {\seq_count:N \l_tmpa_seq} > 1 {
      \seq_get_left:NN \l_tmpa_seq \l_tmpa_tl
      \exp_args:NNno \seq_set_split:Nnn \l_tmpb_seq
        {!} \l_tmpa_tl 
      \int_compare:nNnTF {\seq_count:N \l_tmpb_seq} > 1 {
        \str_set:Nx \l_@@_structure_field_str {\seq_item:Nn \l_tmpb_seq 1}
        \seq_get_right:NN \l_tmpb_seq \l_tmpb_tl
        \seq_get_right:NN \l_tmpa_seq \l_tmpa_tl
      }{
        \str_set:Nx \l_@@_structure_field_str \l_tmpa_tl
        \seq_get_right:NN \l_tmpa_seq \l_tmpa_tl
        \exp_args:NNno \seq_set_split:Nnn \l_tmpb_seq{!}
          \l_tmpa_tl 
        \int_compare:nNnTF {\seq_count:N \l_tmpb_seq} > 1 {
          \seq_get_left:NN \l_tmpb_seq \l_tmpa_tl
          \seq_get_right:NN \l_tmpb_seq \l_tmpb_tl
        }{
          \tl_clear:N \l_tmpb_tl
        }
      }
    }{
      \seq_set_split:Nnn \l_tmpa_seq{!}{ ##1 }
      \int_compare:nNnTF {\seq_count:N \l_tmpa_seq} > 1 {
        \str_set:Nx \l_@@_structure_field_str {\seq_item:Nn \l_tmpa_seq 1}
        \seq_get_right:NN \l_tmpa_seq \l_tmpb_tl
        \tl_clear:N \l_tmpa_tl
      }{
        % TODO throw error
      }
    }
    % \l_tmpa_str: name
    % \l_tmpa_tl: definiens
    % \l_tmpb_tl: notation
    \tl_if_empty:NT \l_@@_structure_field_str { 
      % TODO throw error
    }
    \str_clear:N \l_tmpb_str
    
    \prop_get:NnN \l_@@_structure_prop { fields } \l_tmpa_seq
    \seq_map_inline:Nn \l_tmpa_seq {
      \seq_set_split:Nnn \l_tmpb_seq ? { ####1 }
      \seq_get_right:NN \l_tmpb_seq \l_tmpb_str
      \str_if_eq:NNT \l_@@_structure_field_str \l_tmpb_str {
        \seq_map_break:n {
          \str_set:Nn \l_tmpb_str { ####1 }
        }
      }
    }
    \prop_get:cnN { l_stex_symdecl_ \l_tmpb_str _prop } {args}
      \l_tmpb_str

    \tl_if_empty:NTF \l_tmpb_tl {
      \tl_if_empty:NF \l_tmpa_tl {
        \exp_args:Nx \use:n {
          \symdecl{#3/\l_@@_structure_field_str}[args=\l_tmpb_str,def={\exp_args:No\exp_not:n{\l_tmpa_tl}}]
        }
      }
    }{
      \tl_if_empty:NTF \l_tmpa_tl {
        \exp_args:Nx \use:n {
          \symdef{#3/\l_@@_structure_field_str}[args=\l_tmpb_str]\exp_after:wN\exp_not:n\exp_after:wN{\l_tmpb_tl}
        }

      }{
        \exp_args:Nx \use:n {
          \symdef{#3/\l_@@_structure_field_str}[args=\l_tmpb_str,def={\exp_args:No\exp_not:n{\l_tmpa_tl}}]
          \exp_after:wN\exp_not:n\exp_after:wN{\l_tmpb_tl}
        }
      }
    }
%    \par \prop_item:Nn \l_stex_current_module_prop {ns} ?
%    \prop_item:Nn \l_stex_current_module_prop {name} ?
%    #3/\l_@@_structure_field_str
%    \par
%    \expandafter\present\csname
%      l_stex_symdecl_
%      \prop_item:Nn \l_stex_current_module_prop {ns} ?
%      \prop_item:Nn \l_stex_current_module_prop {name} ?
%      #3/\l_@@_structure_field_str
%      _prop
%    \endcsname
  }

  \tl_clear:N \l_@@_structure_def_tl

  \prop_get:NnN \l_@@_structure_prop { fields } \l_tmpa_seq
  \seq_map_inline:Nn \l_tmpa_seq {
    \seq_set_split:Nnn \l_tmpb_seq ? { ##1 }
    \seq_get_right:NN \l_tmpb_seq \l_tmpa_str
    \exp_args:Nx \use:n {
      \tl_put_right:Nn \exp_not:N \l_@@_structure_def_tl {

      }
    }

    \prop_if_exist:cF {
      l_stex_symdecl_
      \prop_item:Nn \l_stex_current_module_prop {ns} ?
      \prop_item:Nn \l_stex_current_module_prop {name} ?
      #3/\l_tmpa_str
      _prop
    }{
      \prop_get:cnN { l_stex_symdecl_ ##1 _prop } {args}
        \l_tmpb_str
      \exp_args:Nx \use:n {
        \symdecl{#3/\l_tmpa_str}[args=\l_tmpb_str]
      }
    }
  }

  \symdecl*{#3}[type={\STEXsymbol{module-type}{
    \_stex_term_math_oms:nnnn {
      \prop_item:Nn \l_@@_structure_prop {ns} ?
      \prop_item:Nn \l_@@_structure_prop {name}
      }{}{0}{}
  }}]
  
  % TODO: -> sms file

  \tl_set:cx{ #3 }{
    \stex_invoke_structure:nnn {
      \prop_item:Nn \l_stex_current_module_prop {ns} ?
      \prop_item:Nn \l_stex_current_module_prop {name} ? #3
    } {
      \prop_item:Nn \l_@@_structure_prop {ns} ?
      \prop_item:Nn \l_@@_structure_prop {name}
    }
  }
  \stex_smsmode_do:
}
%    \end{macrocode}
% \end{macro}
%
%
%
% \begin{macro}{\stex_invoke_structure:nnn}
%    \begin{macrocode}
% #1: URI of the instance
% #2: URI of the instantiated module
\cs_new_protected:Nn \stex_invoke_structure:nnn {
  \tl_if_empty:nTF{ #3 }{  
    \prop_set_eq:Nc \l_@@_structure_prop {
      c_stex_feature_ #2 _prop
    }
    \tl_clear:N \l_tmpa_tl
    \prop_get:NnN \l_@@_structure_prop { fields } \l_tmpa_seq
    \seq_map_inline:Nn \l_tmpa_seq {
      \seq_set_split:Nnn \l_tmpb_seq ? { ##1 }
      \seq_get_right:NN \l_tmpb_seq \l_tmpa_str
      \cs_if_exist:cT {
        stex_notation_ #1/\l_tmpa_str \c_hash_str\c_hash_str _cs
      }{
        \tl_if_empty:NF \l_tmpa_tl {
          \tl_put_right:Nn \l_tmpa_tl {,}
        }
        \tl_put_right:Nx \l_tmpa_tl {
          \stex_invoke_symbol:n {#1/\l_tmpa_str}!
        }
      }
    }
    \exp_args:No \mathstruct \l_tmpa_tl
  }{
    \stex_invoke_symbol:n{#1/#3}
  }
}
%    \end{macrocode}
% \end{macro}
%
%    \begin{macrocode}
%</package>
%    \end{macrocode}
%
% \end{implementation}
%
% \PrintIndex
