% \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> \def\libfolder#1{../../lib/#1} \input{../../doc/stex-docheader} \begin{document} \DocInput{\jobname.dtx} \end{document} % % \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} % \changes{3.1.0}{2022/03/03}{Implemented mathstructures and instantiations} % % 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 %%%%%%%%%%%%% % \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 } \msg_new:nnn{stex}{error/unknownstructure}{ No~structure~#1~found! } \msg_new:nnn{stex}{error/unknownfield}{ No~field~#1~in~instance~#2~found!\\#3 } \msg_new:nnn{stex}{error/keyval}{ Invalid~key=value~pair:#1 } \msg_new:nnn{stex}{error/instantiate/missing}{ Assignments~missing~in~instantiate:~#1 } \msg_new:nnn{stex}{error/incompatible}{ Incompatible~signature:~#1~(#2)~and~#3~(#4) } % \end{macrocode} % % \subsection{Imports with modification} % % \begin{macrocode} %<@@=stex_copymodule> \cs_new_protected:Nn \stex_get_symbol_in_seq:nn { \tl_if_head_eq_catcode:nNTF { #1 } \relax { \tl_set:Nn \l_tmpa_tl { #1 } \_@@_get_symbol_from_cs: }{ % 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 { \_@@_get_symbol_from_cs:n{ #2 } }{ \_@@_get_symbol_from_string:nn { #1 }{ #2 } } } { \_@@_get_symbol_from_string:nn { #1 }{ #2 } } }{ % argument is not a command name \_@@_get_symbol_from_string:nn { #1 }{ #2 } % \l_stex_all_symbols_seq } } } \cs_new_protected:Nn \_@@_get_symbol_from_string:nn { \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_error:nnn{stex}{error/unknownsymbol}{#1} } \str_set:Nn \l_tmpa_str { #1 } \int_set:Nn \l_tmpa_int { \str_count:N \l_tmpa_str } \seq_map_inline:Nn #2 { \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 } } } } } \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:n { #1 } }{ % TODO % tail is not a single group } }{ % TODO % tail is not a single group } } \cs_new_protected:Nn \_@@_get_symbol_check:n { \exp_args:NNx \seq_if_in:NnF #1 \l_stex_get_symbol_uri_str { \msg_error:nnxx{stex}{error/copymodule/notallowed}{\l_stex_get_symbol_uri_str}{ :~\seq_use:Nn #1 {,~} } } } \cs_new_protected:Nn \stex_copymodule_start:nnnn { % import module \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 % fields \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 } } } % setup prop \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_do_html:T { \begin{stex_annotate_env} {#4} { \l_stex_current_module_str?\l_stex_current_copymodule_name_str } \stex_annotate_invisible:nnn{domain}{\l_stex_import_ns_str ?\l_stex_import_name_str}{} } } \cs_new_protected:Nn \stex_copymodule_end:n { % apply to every field \def \l_tmpa_cs ##1 ##2 {#1} \tl_clear:N \_@@_module_tl \tl_clear:N \_@@_exec_tl %\prop_get:NnN \l_stex_current_copymodule_prop {fields} \l_tmpa_seq \seq_clear:N \_@@_fields_seq \seq_map_inline:Nn \l_@@_copymodule_modules_seq { \seq_map_inline:cn {c_stex_module_##1_constants}{ \tl_clear:N \_@@_curr_symbol_tl % <- wrap in current symbol html \l_tmpa_cs{##1}{####1} \str_if_exist:cTF {l_@@_copymodule_##1?####1_name_str} { \str_set_eq:Nc \_@@_curr_name_str {l_@@_copymodule_##1?####1_name_str} \stex_if_do_html:T { \tl_put_right:Nx \_@@_curr_symbol_tl { \stex_annotate_invisible:nnn{alias}{\use:c{l_@@_copymodule_##1?####1_name_str}}{} } } }{ \str_set:Nx \_@@_curr_name_str { \l_stex_current_copymodule_name_str / ####1 } } \prop_set_eq:Nc \l_tmpa_prop {l_stex_symdecl_ ##1?####1 _prop} \prop_put:Nnx \l_tmpa_prop { name } \_@@_curr_name_str \prop_put:Nnx \l_tmpa_prop { module } \l_stex_current_module_str \tl_if_exist:cT {l_@@_copymodule_##1?####1_def_tl}{ \stex_if_do_html:T { \tl_put_right:Nx \_@@_curr_symbol_tl { $\stex_annotate_invisible:nnn{definiens}{}{\exp_after:wN \exp_not:N\csname l_@@_copymodule_##1?####1_def_tl\endcsname}$ } } \prop_put:Nnn \l_tmpa_prop { defined } { true } } \stex_add_constant_to_current_module:n \_@@_curr_name_str \tl_put_right:Nx \_@@_module_tl { \seq_clear:c {l_stex_symdecl_ \l_stex_current_module_str ? \_@@_curr_name_str _notations} \prop_set_from_keyval:cn { l_stex_symdecl_\l_stex_current_module_str ? \_@@_curr_name_str _prop }{ \prop_to_keyval:N \l_tmpa_prop } } \str_if_exist:cT {l_@@_copymodule_##1?####1_macroname_str} { \stex_if_do_html:T { \tl_put_right:Nx \_@@_curr_symbol_tl { \stex_annotate_invisible:nnn{macroname}{\use:c{l_@@_copymodule_##1?####1_macroname_str}}{} } } \tl_put_right:Nx \_@@_module_tl { \tl_set:cx {\use:c{l_@@_copymodule_##1?####1_macroname_str}}{ \stex_invoke_symbol:n { \l_stex_current_module_str ? \_@@_curr_name_str } } } } \seq_put_right:Nx \_@@_fields_seq {\l_stex_current_module_str ? \_@@_curr_name_str } \tl_put_right:Nx \_@@_exec_tl { \stex_copy_notations:nn {\l_stex_current_module_str ? \_@@_curr_name_str} { ##1 ? ####1 } } \tl_put_right:Nx \_@@_exec_tl { \stex_if_do_html:TF{ \stex_annotate_invisible:nnn{assignment} {##1?####1} { \exp_after:wN \exp_not:n \exp_after:wN {\_@@_curr_symbol_tl} } }{ \exp_after:wN \exp_not:n \exp_after:wN {\_@@_curr_symbol_tl} } } } } \prop_put:Nno \l_stex_current_copymodule_prop {fields} \_@@_fields_seq \tl_put_left:Nx \_@@_module_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 } } \seq_gput_right:cx{c_stex_module_\l_stex_current_module_str _copymodules}{ \l_stex_current_module_str?\l_stex_current_copymodule_name_str } \exp_args:No \stex_execute_in_module:n \_@@_module_tl \stex_debug:nn{copymodule}{result:\meaning \_@@_module_tl} \stex_debug:nn{copymodule}{output:\meaning \_@@_exec_tl} \_@@_exec_tl \stex_if_do_html:T { \end{stex_annotate_env} } } \NewDocumentEnvironment {copymodule} { O{} m m}{ \stex_copymodule_start:nnnn { #1 }{ #2 }{ #3 }{ copymodule } \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 }{ interpretmodule } \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 }{ \str_if_eq:eeF { \prop_item:cn{ l_stex_symdecl_ ##1 ? ##2 _prop }{ defined } }{ true }{ \msg_error:nnxx{stex}{error/interpretmodule/nodefiniens}{ ##1?##2 }{\l_stex_current_copymodule_name_str} } } } } \iffalse \begin{stex_annotate_env} \fi \NewDocumentEnvironment {realization} { O{} m}{ \stex_copymodule_start:nnnn { #1 }{ #2 }{ #2 }{ realize } \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 \donotcopy \stex_reactivate_macro:N \assign \stex_smsmode_do: }{ \stex_import_module_uri:nn { #1 } { #2 } \tl_clear:N \_@@_exec_tl \tl_set:Nx \_@@_module_tl { \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 } } \exp_args:Nx \stex_add_import_to_current_module:n{ \l_stex_import_ns_str ? \l_stex_import_name_str } \seq_map_inline:Nn \l_@@_copymodule_modules_seq { \seq_map_inline:cn {c_stex_module_##1_constants}{ \str_set:Nx \_@@_curr_name_str { \l_stex_current_copymodule_name_str / ####1 } \tl_if_exist:cT {l_@@_copymodule_##1?####1_def_tl}{ \stex_if_do_html:T { \tl_put_right:Nx \_@@_exec_tl { \stex_annotate_invisible:nnn{assignment} {##1?####1} { $\stex_annotate_invisible:nnn{definiens}{}{\exp_after:wN \exp_not:N\csname l_@@_copymodule_##1?####1_def_tl\endcsname}$ } } } \tl_put_right:Nx \_@@_module_tl { \prop_put:cnn {l_stex_symdecl_##1?####1_prop}{ defined }{ true } } } }} \exp_args:No \stex_execute_in_module:n \_@@_module_tl \_@@_exec_tl \stex_if_do_html:T {\end{stex_annotate_env}} } \NewDocumentCommand \donotcopy { m }{ \str_clear:N \l_stex_import_name_str \str_set:Nn \l_tmpa_str { #1 } \int_set:Nn \l_tmpa_int { \str_count:N \l_tmpa_str } \seq_map_inline:Nn \l_stex_all_modules_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 { \stex_if_do_html:T { \stex_if_smsmode:F { \stex_annotate_invisible:nnn{donotcopy}{##1}{ \stex_annotate:nnn{domain}{##1}{} } } } \str_set_eq:NN \l_stex_import_name_str \l_tmpb_str } } \seq_map_inline:cn {c_stex_module_##1_copymodules}{ \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 {\seq_map_break:n { \stex_if_do_html:T { \stex_if_smsmode:F { \stex_annotate_invisible:nnn{donotcopy}{####1}{ \stex_annotate:nnn{domain}{ \prop_item:cn {l_stex_copymodule_ ####1 _prop}{module} }{} } } } \str_set:Nx \l_stex_import_name_str { \prop_item:cn {l_stex_copymodule_ ####1 _prop}{module} } }} } } } \str_if_empty:NTF \l_stex_import_name_str { % TODO throw error }{ \stex_collect_imports:n {\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: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_name_str } \prop_put:Nno \l_stex_current_copymodule_prop {includes} \l_tmpa_seq } \stex_smsmode_do: } \NewDocumentCommand \assign { m m }{ \stex_get_symbol_in_seq:nn {#1} \l_@@_copymodule_fields_seq \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} \stex_smsmode_do: } \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_seq:nn {#2} \l_@@_copymodule_fields_seq \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_smsmode_do: } \stex_deactivate_macro:Nn \assign {copymodules} \stex_deactivate_macro:Nn \renamedecl {copymodules} \stex_deactivate_macro:Nn \donotcopy {copymodules} % \end{macrocode} % % % \subsection{The feature environment} % % \begin{environment}{structural@feature} % \begin{macrocode} %<@@=stex_features> \NewDocumentEnvironment{structural_feature_module}{ 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_eq:NN \l_stex_feature_parent_str \l_stex_current_module_str \stex_module_setup:nn{meta=NONE}{#2 - #1} \stex_if_do_html:T { \begin{stex_annotate_env}{ feature:#1 }{\l_stex_feature_parent_str ? #2 - #1} \stex_annotate_invisible:nnn{header}{}{ #3 } } }{ \str_gset_eq:NN \l_stex_last_feature_str \l_stex_current_module_str \prop_gput:cnn {c_stex_module_ \l_stex_current_module_str _prop}{feature}{#1} \stex_debug:nn{features}{ Feature: \l_stex_last_feature_str } \stex_if_do_html:T { \end{stex_annotate_env} } } % \end{macrocode} % \end{environment} % % \subsection{Structure} % % \begin{environment}{structure} % \begin{macrocode} %<@@=stex_structures> \cs_new_protected:Nn \stex_add_structure_to_current_module:nn { \prop_if_exist:cF {c_stex_module_\l_stex_current_module_str _structures}{ \prop_new:c {c_stex_module_\l_stex_current_module_str _structures} } \prop_gput:cxx{c_stex_module_\l_stex_current_module_str _structures} {#1}{#2} } \keys_define:nn { stex / features / structure } { name .str_set_x:N = \l_@@_name_str , } \cs_new_protected:Nn \_@@_structure_args:n { \str_clear:N \l_@@_name_str \keys_set:nn { stex / features / structure } { #1 } } \NewDocumentEnvironment{mathstructure}{m O{}}{ \begin{mathstructure_inner}{#1}[#2] \stex_smsmode_do: \ignorespacesandpars }{\end{mathstructure_inner}} \NewDocumentEnvironment{mathstructure_inner}{m O{}}{ \_@@_structure_args:n { #2 } \str_if_empty:NT \l_@@_name_str { \str_set:Nx \l_@@_name_str { #1 } } \stex_suppress_html:n { \bool_set_true:N \l_stex_symdecl_make_macro_bool \exp_args:Nx \stex_symdecl_do:nn { name = \l_@@_name_str , def = {\STEXsymbol{module-type}{ \STEXInternalTermMathOMSiiii { \prop_item:cn {c_stex_module_\l_stex_current_module_str _prop} { ns } ? \prop_item:cn {c_stex_module_\l_stex_current_module_str _prop} { name } / \l_@@_name_str - structure }{}{0}{} }} }{ #1 } } \exp_args:Nnnx \begin{structural_feature_module}{ structure } { \l_@@_name_str }{} }{ \end{structural_feature_module} \_stex_reset_up_to_module:n \l_stex_last_feature_str \exp_args:No \stex_collect_imports:n \l_stex_last_feature_str \seq_clear:N \l_tmpa_seq \seq_map_inline:Nn \l_stex_collect_imports_seq { \seq_map_inline:cn{c_stex_module_##1_constants}{ \seq_put_right:Nn \l_tmpa_seq { ##1 ? ####1 } } } \exp_args:Nnno \prop_gput:cnn {c_stex_module_ \l_stex_last_feature_str _prop}{fields}\l_tmpa_seq \stex_debug:nn{structure}{Fields:~\seq_use:Nn \l_tmpa_seq ,} \stex_add_structure_to_current_module:nn \l_@@_name_str \l_stex_last_feature_str \stex_execute_in_module:x { \tl_set:cn { #1 }{ \exp_not:N \stex_invoke_structure:nn {\l_stex_current_module_str }{ \l_@@_name_str} } } } \cs_new:Nn \stex_invoke_structure:nn { \stex_invoke_symbol:n { #1?#2 } } \cs_new_protected:Nn \stex_get_structure:n { \tl_if_head_eq_catcode:nNTF { #1 } \relax { \tl_set:Nn \l_tmpa_tl { #1 } \_@@_get_from_cs: }{ \cs_if_exist:cTF { #1 }{ \cs_set_eq:Nc \l_tmpa_cs { #1 } \str_set:Nx \l_tmpa_str {\cs_argument_spec:N \l_tmpa_cs } \str_if_empty:NTF \l_tmpa_str { \cs_if_eq:NNTF { \tl_head:N \l_tmpa_cs} \stex_invoke_structure:nn { \_@@_get_from_cs: }{ \_@@_get_from_string:n { #1 } } }{ \_@@_get_from_string:n { #1 } } }{ \_@@_get_from_string:n { #1 } } } } \cs_new_protected:Nn \_@@_get_from_cs: { \exp_args:NNx \tl_set:Nn \l_tmpa_tl { \tl_tail:N \l_tmpa_tl } \str_set:Nx \l_tmpa_str { \exp_after:wN \use_i:nn \l_tmpa_tl } \str_set:Nx \l_tmpb_str { \exp_after:wN \use_ii:nn \l_tmpa_tl } \str_set:Nx \l_stex_get_structure_str { \l_tmpa_str ? \l_tmpb_str } \str_set:Nx \l_stex_get_structure_module_str { \exp_args:Nno \prop_item:cn {c_stex_module_\l_tmpa_str _structures}{\l_tmpb_str} } } \cs_new_protected:Nn \_@@_get_from_string:n { \tl_set:Nn \l_tmpa_tl { \msg_error:nnn{stex}{error/unknownstructure}{#1} } \str_set:Nn \l_tmpa_str { #1 } \int_set:Nn \l_tmpa_int { \str_count:N \l_tmpa_str } \seq_map_inline:Nn \l_stex_all_modules_seq { \prop_if_exist:cT {c_stex_module_##1_structures} { \prop_map_inline:cn {c_stex_module_##1_structures} { \exp_args:No \str_if_eq:nnT \l_tmpa_str {####1}{ %\str_if_eq:eeT { \l_tmpa_str }{ \str_range:nnn {##1?####1}{-\l_tmpa_int}{-1}}{ \prop_map_break:n{\seq_map_break:n{ \tl_set:Nn \l_tmpa_tl { \str_set:Nn \l_stex_get_structure_str {##1?####1} \str_set:Nn \l_stex_get_structure_module_str {####2} } }} } } } } \l_tmpa_tl } % \end{macrocode} % \end{environment} % % % \begin{macro}{\instantiate} % \begin{macrocode} \NewDocumentEnvironment{usestructure}{m}{ \stex_get_structure:n {#1} \exp_args:Nnx \stex_debug:nn{features}{using~structure:~\l_stex_get_structure_module_str} \exp_args:No \stex_activate_module:n \l_stex_get_structure_module_str }{} \keys_define:nn { stex / instantiate } { name .str_set_x:N = \l_@@_name_str } \cs_new_protected:Nn \_@@_instantiate_args:n { \str_clear:N \l_@@_name_str \keys_set:nn { stex / instantiate } { #1 } } \NewDocumentEnvironment{extstructure}{m m O{}}{ \begin{mathstructure_inner}{#1}[#3] \seq_set_split:Nnn\_@@_extstructure_imports_seq,{#2} \seq_map_inline:Nn\_@@_extstructure_imports_seq { \stex_get_structure:n {##1} \exp_args:Nnx \stex_debug:nn{features}{importing~structure:~\l_stex_get_structure_module_str{}~into~\l_stex_current_module_str} \exp_args:No \stex_activate_module:n \l_stex_get_structure_module_str \stex_if_smsmode:F { \stex_annotate_invisible:nnn {import} {\l_stex_get_structure_module_str} {} } \exp_args:Nx \stex_add_import_to_current_module:n { \l_stex_get_structure_module_str } \exp_args:Nx \stex_add_to_current_module:n { \exp_args:No \stex_activate_module:n \l_stex_get_structure_module_str } } \stex_smsmode_do: \ignorespacesandpars }{ \end{mathstructure_inner} } \NewDocumentEnvironment{extstructure*}{m m O{}}{ % TODO \begin{extstructure}{#1}{#2}[#3] }{ \end{extstructure} } \NewDocumentCommand \instantiate {m O{} m m O{}}{ \begingroup \stex_get_structure:n {#3} \_@@_instantiate_args:n { #2 } \str_if_empty:NT \l_@@_name_str { \str_set:Nn \l_@@_name_str { #1 } } \exp_args:No \stex_activate_module:n \l_stex_get_structure_module_str \seq_clear:N \l_@@_fields_seq \exp_args:Nx \stex_collect_imports:n \l_stex_get_structure_module_str \seq_map_inline:Nn \l_stex_collect_imports_seq { \seq_map_inline:cn {c_stex_module_##1_constants}{ \seq_put_right:Nx \l_@@_fields_seq { ##1 ? ####1 } } } \tl_if_empty:nF{#5}{ \seq_set_split:Nnn \l_tmpa_seq , {#5} \prop_clear:N \l_tmpa_prop \seq_map_inline:Nn \l_tmpa_seq { \seq_set_split:Nnn \l_tmpb_seq = { ##1 } \int_compare:nNnF { \seq_count:N \l_tmpb_seq } = 2 { \msg_error:nnn{stex}{error/keyval}{##1} } \exp_args:Nx \stex_get_symbol_in_seq:nn {\seq_item:Nn \l_tmpb_seq 1} \l_@@_fields_seq \str_set_eq:NN \l_@@_dom_str \l_stex_get_symbol_uri_str \exp_args:NNx \seq_remove_all:Nn \l_@@_fields_seq \l_stex_get_symbol_uri_str \exp_args:Nx \stex_get_symbol:n {\seq_item:Nn \l_tmpb_seq 2} \exp_args:Nxx \str_if_eq:nnF {\prop_item:cn{l_stex_symdecl_\l_@@_dom_str _prop}{args}} {\prop_item:cn{l_stex_symdecl_\l_stex_get_symbol_uri_str _prop}{args}}{ \msg_error:nnxxxx{stex}{error/incompatible} {\l_@@_dom_str} {\prop_item:cn{l_stex_symdecl_\l_@@_dom_str _prop}{args}} {\l_stex_get_symbol_uri_str} {\prop_item:cn{l_stex_symdecl_\l_stex_get_symbol_uri_str _prop}{args}} } \prop_put:Nxx \l_tmpa_prop {\seq_item:Nn \l_tmpb_seq 1} \l_stex_get_symbol_uri_str } } \seq_map_inline:Nn \l_@@_fields_seq { \str_set:Nx \l_tmpa_str {field:\l_@@_name_str . \prop_item:cn {l_stex_symdecl_##1_prop}{name} } \stex_debug:nn{instantiate}{Field~\l_tmpa_str :~##1} \stex_add_constant_to_current_module:n {\l_tmpa_str} \stex_execute_in_module:x { \prop_set_from_keyval:cn { l_stex_symdecl_ \l_stex_current_module_str?\l_tmpa_str _prop}{ name = \l_tmpa_str , args = \prop_item:cn {l_stex_symdecl_##1_prop}{args} , arity = \prop_item:cn {l_stex_symdecl_##1_prop}{arity} , assocs = \prop_item:cn {l_stex_symdecl_##1_prop}{assocs} , argnames = {\prop_item:cn {l_stex_symdecl_##1_prop}{argnames}} } \seq_clear:c {l_stex_symdecl_\l_stex_current_module_str?\l_tmpa_str _notations} } \seq_if_empty:cF{l_stex_symdecl_##1_notations}{ \stex_find_notation:nn{##1}{} \stex_execute_in_module:x { \seq_put_right:cn {l_stex_symdecl_\l_stex_current_module_str?\l_tmpa_str _notations}{\l_stex_notation_variant_str} } \stex_copy_control_sequence_ii:ccN {stex_notation_\l_stex_current_module_str?\l_tmpa_str\c_hash_str \l_stex_notation_variant_str _cs} {stex_notation_##1\c_hash_str \l_stex_notation_variant_str _cs} \l_tmpa_tl \exp_args:No \stex_execute_in_module:n \l_tmpa_tl \cs_if_exist:cT{stex_op_notation_##1\c_hash_str \l_stex_notation_variant_str _cs}{ \tl_set_eq:Nc \l_tmpa_cs {stex_op_notation_##1\c_hash_str \l_stex_notation_variant_str _cs} \stex_execute_in_module:x { \tl_set:cn {stex_op_notation_\l_stex_current_module_str?\l_tmpa_str\c_hash_str \l_stex_notation_variant_str _cs} { \exp_args:No \exp_not:n \l_tmpa_cs} } } } \prop_put:Nxx \l_tmpa_prop {\prop_item:cn {l_stex_symdecl_##1_prop}{name}}{\l_stex_current_module_str?\l_tmpa_str} } \stex_execute_in_module:x { \prop_set_from_keyval:cn {l_stex_instance_\l_stex_current_module_str?\l_@@_name_str _prop}{ domain = \l_stex_get_structure_module_str , \prop_to_keyval:N \l_tmpa_prop } \tl_set:cn{ #1 }{\stex_invoke_instance:n{ \l_stex_current_module_str?\l_@@_name_str} } } \stex_debug:nn{instantiate}{ Instance~\l_stex_current_module_str?\l_@@_name_str \\ \prop_to_keyval:N \l_tmpa_prop } \exp_args:Nxx \stex_symdecl_do:nn { type={\STEXsymbol{module-type}{ \STEXInternalTermMathOMSiiii { \l_stex_get_structure_module_str }{}{0}{} }} }{\l_@@_name_str} % { \str_set:Nx \l_stex_get_symbol_uri_str {\l_stex_current_module_str?\l_@@_name_str} \tl_set:Nn \l_stex_notation_after_do_tl {\__stex_notation_final:} \stex_notation_do:nnnnn{}{0}{}{}{\comp{#4}} % } %\exp_args:Nx \notation{\l_@@_name_str}{\comp{#5}} \endgroup \stex_smsmode_do:\ignorespacesandpars } \cs_new_protected:Nn \stex_symbol_or_var:n { \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_variable:n { \bool_set_true:N \l_stex_symbol_or_var_bool \bool_set_false:N \l_stex_instance_or_symbol_bool \tl_set:Nx \l_tmpa_tl {\tl_tail:N \l_tmpa_tl} \tl_set:Nx \l_tmpa_tl {\exp_after:wN \use:n \l_tmpa_tl} \str_set:Nx \l_stex_get_symbol_uri_str { \exp_after:wN \use:n \l_tmpa_tl } }{ % TODO \stex_invoke_varinstance:n \exp_args:Nx \cs_if_eq:NNTF { \tl_head:N \l_tmpa_tl } \stex_invoke_varinstance:n { \bool_set_true:N \l_stex_symbol_or_var_bool \bool_set_true:N \l_stex_instance_or_symbol_bool \tl_set:Nx \l_tmpa_tl {\tl_tail:N \l_tmpa_tl} \tl_set:Nx \l_tmpa_tl {\exp_after:wN \use:n \l_tmpa_tl} \str_set:Nx \l_stex_get_symbol_uri_str { \exp_after:wN \use:n \l_tmpa_tl } }{ \bool_set_false:N \l_stex_symbol_or_var_bool \stex_get_symbol:n{#1} } } }{ \_@@_symbolorvar_from_string:n{ #1 } } }{ \_@@_symbolorvar_from_string:n{ #1 } } } \cs_new_protected:Nn \_@@_symbolorvar_from_string:n { \prop_if_exist:cTF {l_stex_symdecl_var://#1 _prop}{ \bool_set_true:N \l_stex_symbol_or_var_bool \str_set:Nn \l_stex_get_symbol_uri_str { #1 } }{ \bool_set_false:N \l_stex_symbol_or_var_bool \stex_get_symbol:n{#1} } } \keys_define:nn { stex / varinstantiate } { name .str_set_x:N = \l_@@_name_str, bind .choices:nn = {forall,exists} {\str_set:Nx \l_@@_bind_str {\l_keys_choice_tl}} } \cs_new_protected:Nn \_@@_varinstantiate_args:n { \str_clear:N \l_@@_name_str \str_clear:N \l_@@_bind_str \keys_set:nn { stex / varinstantiate } { #1 } } \NewDocumentCommand \varinstantiate {m O{} m m O{}}{ \begingroup \stex_get_structure:n {#3} \_@@_varinstantiate_args:n { #2 } \str_if_empty:NT \l_@@_name_str { \str_set:Nn \l_@@_name_str { #1 } } \stex_if_do_html:TF{ \stex_annotate:nnn{varinstance}{\l_@@_name_str} }{\use:n} { \stex_if_do_html:T{ \stex_annotate_invisible:nnn{domain}{\l_stex_get_structure_module_str}{} } \seq_clear:N \l_@@_fields_seq \exp_args:Nx \stex_collect_imports:n \l_stex_get_structure_module_str \seq_map_inline:Nn \l_stex_collect_imports_seq { \seq_map_inline:cn {c_stex_module_##1_constants}{ \seq_put_right:Nx \l_@@_fields_seq { ##1 ? ####1 } } } \exp_args:No \stex_activate_module:n \l_stex_get_structure_module_str \prop_clear:N \l_tmpa_prop \tl_if_empty:nF {#5} { \seq_set_split:Nnn \l_tmpa_seq , {#5} \seq_map_inline:Nn \l_tmpa_seq { \seq_set_split:Nnn \l_tmpb_seq = { ##1 } \int_compare:nNnF { \seq_count:N \l_tmpb_seq } = 2 { \msg_error:nnn{stex}{error/keyval}{##1} } \exp_args:Nx \stex_get_symbol_in_seq:nn {\seq_item:Nn \l_tmpb_seq 1} \l_@@_fields_seq \str_set_eq:NN \l_@@_dom_str \l_stex_get_symbol_uri_str \exp_args:NNx \seq_remove_all:Nn \l_@@_fields_seq \l_stex_get_symbol_uri_str \exp_args:Nx \stex_symbol_or_var:n {\seq_item:Nn \l_tmpb_seq 2} \stex_if_do_html:T{ \stex_annotate:nnn{assign}{\l_@@_dom_str, \bool_if:NTF\l_stex_symbol_or_var_bool{var://}{}\l_stex_get_symbol_uri_str}{} } \bool_if:NTF \l_stex_symbol_or_var_bool { \exp_args:Nxx \str_if_eq:nnF {\prop_item:cn{l_stex_symdecl_\l_@@_dom_str _prop}{args}} {\prop_item:cn{l_stex_symdecl_var://\l_stex_get_symbol_uri_str _prop}{args}}{ \msg_error:nnxxxx{stex}{error/incompatible} {\l_@@_dom_str} {\prop_item:cn{l_stex_symdecl_\l_@@_dom_str _prop}{args}} {\l_stex_get_symbol_uri_str} {\prop_item:cn{l_stex_symdecl_var://\l_stex_get_symbol_uri_str _prop}{args}} } \prop_put:Nxx \l_tmpa_prop {\seq_item:Nn \l_tmpb_seq 1} {\stex_invoke_variable:n {\l_stex_get_symbol_uri_str}} }{ \exp_args:Nxx \str_if_eq:nnF {\prop_item:cn{l_stex_symdecl_\l_@@_dom_str _prop}{args}} {\prop_item:cn{l_stex_symdecl_\l_stex_get_symbol_uri_str _prop}{args}}{ \msg_error:nnxxxx{stex}{error/incompatible} {\l_@@_dom_str} {\prop_item:cn{l_stex_symdecl_\l_@@_dom_str _prop}{args}} {\l_stex_get_symbol_uri_str} {\prop_item:cn{l_stex_symdecl_\l_stex_get_symbol_uri_str _prop}{args}} } \prop_put:Nxx \l_tmpa_prop {\seq_item:Nn \l_tmpb_seq 1} {\stex_invoke_symbol:n {\l_stex_get_symbol_uri_str}} } } } \tl_gclear:N \g_@@_aftergroup_tl \seq_map_inline:Nn \l_@@_fields_seq { \str_set:Nx \l_tmpa_str {\l_@@_name_str . \prop_item:cn {l_stex_symdecl_##1_prop}{name} } \stex_debug:nn{varinstantiate}{Field~\l_tmpa_str :~##1} \seq_if_empty:cF{l_stex_symdecl_##1_notations}{ \stex_find_notation:nn{##1}{} \cs_gset_eq:cc{g_@@_tmpa_\l_tmpa_str _cs} {stex_notation_##1\c_hash_str \l_stex_notation_variant_str _cs} \stex_debug:nn{varinstantiate}{Notation:~\cs_meaning:c{g_@@_tmpa_\l_tmpa_str _cs}} \cs_if_exist:cT{stex_op_notation_##1\c_hash_str \l_stex_notation_variant_str _cs}{ \cs_gset_eq:cc {g_@@_tmpa_op_\l_tmpa_str _cs} {stex_op_notation_##1\c_hash_str \l_stex_notation_variant_str _cs} \stex_debug:nn{varinstantiate}{Operator~Notation:~\cs_meaning:c{g_@@_tmpa_op_\l_tmpa_str _cs}} } } \exp_args:NNx \tl_gput_right:Nn \g_@@_aftergroup_tl { \prop_set_from_keyval:cn { l_stex_symdecl_ var://\l_tmpa_str _prop}{ name = \l_tmpa_str , args = \prop_item:cn {l_stex_symdecl_##1_prop}{args} , arity = \prop_item:cn {l_stex_symdecl_##1_prop}{arity} , assocs = \prop_item:cn {l_stex_symdecl_##1_prop}{assocs} , argnames = {\prop_item:cn {l_stex_symdecl_##1_prop}{argnames}} , } \cs_set_eq:cc {stex_var_notation_\l_tmpa_str _cs} {g_@@_tmpa_\l_tmpa_str _cs} \cs_set_eq:cc {stex_var_op_notation_\l_tmpa_str _cs} {g_@@_tmpa_op_\l_tmpa_str _cs} } \prop_put:Nxx \l_tmpa_prop {\prop_item:cn {l_stex_symdecl_##1_prop}{name}}{\stex_invoke_variable:n {\l_tmpa_str}} } \exp_args:NNx \tl_gput_right:Nn \g_@@_aftergroup_tl { \prop_set_from_keyval:cn {l_stex_varinstance_\l_@@_name_str _prop }{ domain = \l_stex_get_structure_module_str , \prop_to_keyval:N \l_tmpa_prop } \tl_set:cn { #1 }{\stex_invoke_varinstance:n {\l_@@_name_str}} \tl_set:cn {l_stex_varinstance_\l_@@_name_str _op_tl}{ \exp_args:Nnx \exp_not:N \use:nn { \str_set:Nn \exp_not:N \STEXInternalCurrentSymbolStr {var://\l_@@_name_str} \_stex_term_omv:nn {var://\l_@@_name_str}{ \exp_not:n{ \_varcomp{#4} } } }{ \exp_not:n{\_stex_reset:N \STEXInternalCurrentSymbolStr} } } } } \stex_debug:nn{varinstantiate}{\expandafter\detokenize\expandafter{\g_@@_aftergroup_tl}} \aftergroup\g_@@_aftergroup_tl \endgroup \stex_smsmode_do:\ignorespacesandpars } \cs_new_protected:Nn \stex_invoke_instance:n { \peek_charcode_remove:NTF ! { \stex_invoke_symbol:n{#1} }{ \_stex_invoke_instance:nn {#1} } } \cs_new_protected:Nn \stex_invoke_varinstance:n { \peek_charcode_remove:NTF ! { \exp_args:Nnx \use:nn { \def\comp{\_varcomp} \use:c{l_stex_varinstance_#1_op_tl} }{ \_stex_reset:N \comp } }{ \_stex_invoke_varinstance:nn {#1} } } \cs_new_protected:Nn \_stex_invoke_instance:nn { \prop_if_in:cnTF {l_stex_instance_ #1 _prop}{#2}{ \exp_args:Nx \stex_invoke_symbol:n {\prop_item:cn{l_stex_instance_ #1 _prop}{#2}} }{ \prop_set_eq:Nc \l_tmpa_prop{l_stex_instance_ #1 _prop} \msg_error:nnxxx{stex}{error/unknownfield}{#2}{#1}{ \prop_to_keyval:N \l_tmpa_prop } } } \cs_new_protected:Nn \_stex_invoke_varinstance:nn { \prop_if_in:cnTF {l_stex_varinstance_ #1 _prop}{#2}{ \prop_get:cnN{l_stex_varinstance_ #1 _prop}{#2}\l_tmpa_tl \l_tmpa_tl }{ \msg_error:nnnnn{stex}{error/unknownfield}{#2}{#1}{} } } % \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} % % \end{macrocode} % % \end{implementation} % \ifinfulldoc\else\printbibliography\fi % % \PrintIndex