summaryrefslogtreecommitdiff
path: root/tex/context/base/mult-aux.mkiv
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/mult-aux.mkiv')
-rw-r--r--tex/context/base/mult-aux.mkiv439
1 files changed, 415 insertions, 24 deletions
diff --git a/tex/context/base/mult-aux.mkiv b/tex/context/base/mult-aux.mkiv
index 6c44a0ec9..b69d7f370 100644
--- a/tex/context/base/mult-aux.mkiv
+++ b/tex/context/base/mult-aux.mkiv
@@ -106,10 +106,14 @@
\doubleexpandafter\gobbleoneargument
\else
\mult_interfaces_get_parameters_assign#1==\empty\_e_o_p_
- \doubleexpandafter\mult_interfaces_get_parameters_item
+ % \doubleexpandafter\mult_interfaces_get_parameters_item % saves skipping when at end
\fi\fi#2}
-\def\mult_interfaces_get_parameters_error#1#2#3%
+\def\mult_interfaces_get_parameters_error#1#2% #3%
+ {\mult_interfaces_get_parameters_error_indeed{#1}{#2}%
+ \gobbleoneargument}
+
+\def\mult_interfaces_get_parameters_error_indeed#1#2%
{\showassignerror{#2}{\the\inputlineno\space(#1)}}
\def\mult_interfaces_get_parameters_assign#1=#2=#3#4\_e_o_p_
@@ -118,9 +122,54 @@
\else\ifx#3\empty
\doubleexpandafter\mult_interfaces_get_parameters_error
\else
- \doubleexpandafter\dosetvalue
+ \doubleexpandafter\mult_interfaces_def
\fi\fi
- \m_mult_interfaces_namespace{#1}{#2}}
+ \m_mult_interfaces_namespace{#1}{#2}%
+ \doubleexpandafter\mult_interfaces_get_parameters_item}
+
+\startinterface english
+
+ % some 10% faster
+
+ \let\mult_interfaces_get_parameters_error\undefined
+
+ \def\mult_interfaces_get_parameters_error_one#1\csname#2#3\endcsname#4%
+ {\mult_interfaces_get_parameters_error_indeed{#2}{#3}\iftrue}
+
+ \def\mult_interfaces_get_parameters_error_two#1\csname#2#3\endcsname#4%
+ {\mult_interfaces_get_parameters_error_indeed{#2}{#3}}
+
+ \def\mult_interfaces_get_parameters_assign#1=#2=#3#4\_e_o_p_
+ {\ifx\empty#1\empty
+ \mult_interfaces_get_parameters_error_one
+ \else\ifx#3\empty
+ \mult_interfaces_get_parameters_error_two
+ \else
+ \expandafter\def\csname\m_mult_interfaces_namespace#1\endcsname{#2}%
+ \fi\fi
+ \doubleexpandafter\mult_interfaces_get_parameters_item}
+
+ % interesting but not faster
+ %
+ % \def\mult_interfaces_get_parameters_error_one#1\m_mult_interfaces_namespace#2\fi\fi%
+ % {\mult_interfaces_get_parameters_error_indeed\m_mult_interfaces_namespace{#2}\m_mult_interfaces_namespace\s!dummy\fi}
+ %
+ % \def\mult_interfaces_get_parameters_error_two#1\m_mult_interfaces_namespace#2\fi\fi%
+ % {\mult_interfaces_get_parameters_error_indeed\m_mult_interfaces_namespace{#2}\m_mult_interfaces_namespace\s!dummy\fi\fi}
+ %
+ % \def\mult_interfaces_get_parameters_assign#1=#2=#3#4\_e_o_p_
+ % {\expandafter\def\csname
+ % \ifx\empty#1\empty
+ % \mult_interfaces_get_parameters_error_one
+ % \else\ifx#3\empty
+ % \mult_interfaces_get_parameters_error_two
+ % \else
+ % \m_mult_interfaces_namespace#1%
+ % \fi\fi
+ % \endcsname{#2}
+ % \doubleexpandafter\mult_interfaces_get_parameters_item}
+
+\stopinterface
\newif\ifassignment
@@ -132,6 +181,24 @@
% End of experimental code.
+\unexpanded\def\mult_interfaces_let #1#2{\expandafter\let \csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname}
+\unexpanded\def\mult_interfaces_lete#1#2{\expandafter\let \csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname\empty}
+\unexpanded\def\mult_interfaces_def #1#2{\expandafter\def \csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname}
+\unexpanded\def\mult_interfaces_edef#1#2{\expandafter\edef\csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname}
+\unexpanded\def\mult_interfaces_gdef#1#2{\expandafter\gdef\csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname}
+\unexpanded\def\mult_interfaces_xdef#1#2{\expandafter\xdef\csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname}
+
+\startinterface english
+
+ \unexpanded\def\mult_interfaces_let #1#2{\expandafter \let\csname#1#2\endcsname}
+ \unexpanded\def\mult_interfaces_lete#1#2{\expandafter \let\csname#1#2\endcsname\empty}
+ \unexpanded\def\mult_interfaces_def #1#2{\expandafter \def\csname#1#2\endcsname}
+ \unexpanded\def\mult_interfaces_edef#1#2{\expandafter\edef\csname#1#2\endcsname}
+ \unexpanded\def\mult_interfaces_gdef#1#2{\expandafter\gdef\csname#1#2\endcsname}
+ \unexpanded\def\mult_interfaces_xdef#1#2{\expandafter\xdef\csname#1#2\endcsname}
+
+\stopinterface
+
% the commented detokenized variant that backtracks ... needs testing usage first
%
% \let\whatever\relax
@@ -156,14 +223,30 @@
\def#8##1{\csname\ifcsname#1#2:##1\endcsname#1#2:##1\else\s!empty\fi\endcsname}%
\def#9##1{\csname#1#2:##1\endcsname}}
+% pre-expansion can be a bit faster but handly any effect on a normal run so let's go for
+% saving some memory
+%
+% \unexpanded\def\mult_interfaces_install_parameter_handler#1#2#3#4#5#6#7#8#9% inlining \csname*\endcsname is more efficient (#3 and #6 only)
+% {\ifx#2\relax\let#2\empty\fi % it is hardly faster but produces less expansion tracing
+% %\def#3##1{\csname#4{#1#2}{##1}\endcsname}%
+% \edef#3##1{\noexpand\csname\noexpand\ifcsname#1\noexpand#2:##1\endcsname#1\noexpand#2:##1\noexpand\else\noexpand\expandafter\noexpand#5\noexpand\csname#1\noexpand#2:\s!parent\endcsname{##1}\noexpand\fi\endcsname}%
+% \edef#4##1##2{\noexpand\ifcsname##1:##2\endcsname##1:##2\noexpand\else\noexpand\expandafter\noexpand#5\noexpand\csname##1:\s!parent\endcsname{##2}\noexpand\fi}%
+% \def #5##1##2{\ifx##1\relax\s!empty\else#4{##1}{##2}\fi}% is {} needed around ##1 ?
+% \edef#6##1##2{\noexpand\csname\noexpand\ifcsname#1##1:##2\endcsname#1##1:##2\noexpand\else\noexpand\expandafter\noexpand#5\noexpand\csname#1##1:\s!parent\endcsname{##2}\noexpand\fi\endcsname}%
+% \def#7##1{\detokenize\expandafter\expandafter\expandafter{\csname#1#2:##1\endcsname}}% always root, no backtrack
+% % \def#7##1{\mult_interfaces_detokenize{\csname#4{#1#2}{##1}\endcsname}}% compact version
+% % \def#7##1{\mult_interfaces_detokenize{\csname\ifcsname#1#2:##1\endcsname#1#2:##1\else\expandafter#5\csname#1#2:\s!parent\endcsname{##1}\fi\endcsname}}%
+% \edef#8##1{\noexpand\csname\noexpand\ifcsname#1\noexpand#2:##1\endcsname#1\noexpand#2:##1\noexpand\else\s!empty\noexpand\fi\endcsname}%
+% \edef#9##1{\noexpand\csname#1#2:##1\endcsname}}
+
\unexpanded\def\installparameterhandler#1#2%
{\normalexpanded
{\mult_interfaces_install_parameter_handler
{\noexpand#1}% \??aa
\expandafter\noexpand\csname current#2\endcsname
\expandafter\noexpand\csname #2parameter\endcsname
- \expandafter\noexpand\csname do#2parameter\endcsname % or : #2_parameter_hash
- \expandafter\noexpand\csname do#2parentparameter\endcsname % or : #2_parent_parameter_hash
+ \expandafter\noexpand\csname do#2parameter\endcsname % or : #2_parameter
+ \expandafter\noexpand\csname do#2parentparameter\endcsname % or : #2_parent_parameter
\expandafter\noexpand\csname named#2parameter\endcsname
\expandafter\noexpand\csname detokenized#2parameter\endcsname
\expandafter\noexpand\csname strict#2parameter\endcsname % checked
@@ -207,14 +290,14 @@
% In \MKIV\ we can probably use the english variant for all other
% languages too.
-% todo: inline the \do*value
+% todo: inline the def/let
\unexpanded\def\mult_interfaces_install_parameter_set_handler#1#2#3#4#5#6%
{\ifx#2\relax\let#2\empty\fi
- \unexpanded\def#3{\dosetvalue {#1#2:}}% ##1 {##2} (braces are mandate)
- \unexpanded\def#4{\dosetevalue{#1#2:}}% ##1 {##2} (braces are mandate)
- \unexpanded\def#5{\doletvalue {#1#2:}}% ##1 ##2
- \unexpanded\def#6{\doletvalue {#1#2:}\empty}}% ##1
+ \unexpanded\def#3{\mult_interfaces_def {#1#2:}}% ##1 {##2} (braces are mandate)
+ \unexpanded\def#4{\mult_interfaces_edef{#1#2:}}% ##1 {##2} (braces are mandate)
+ \unexpanded\def#5{\mult_interfaces_let {#1#2:}}% ##1 ##2
+ \unexpanded\def#6{\mult_interfaces_lete{#1#2:}}}% ##1
\startinterface english
@@ -272,6 +355,11 @@
\expandafter\edef\csname#1#4:\s!parent\endcsname{#2}%
\fi \fi}
+\def\mult_interfaces_chain#1#2{\ifcsname#1#2:\s!chain\endcsname\csname#1#2:\s!chain\endcsname\space\fi}
+\def\getparentchain #1#2{\ifcsname#1#2:\s!chain\endcsname\csname#1#2:\s!chain\endcsname\fi}
+\def\getcurrentparentchain#1#2{\csname#1#2:\s!chain\endcsname} % for the moment test:
+\def\getcurrentparentchain#1#2{\ifcsname#1#2:\s!chain\endcsname\csname#1#2:\s!chain\endcsname\fi}
+
\unexpanded\def\mult_interfaces_install_define_handler#1#2#3#4#5#6#7#8#9% why is \expanded still needed in clones
{\ifx#4\relax\let#4\empty\fi % see \defineregister
\unexpanded\def#2{\dotripleempty#5}%
@@ -284,6 +372,7 @@
\the#6% predefine
\edef#8{##2}%
\mult_check_for_parent{#1}{#3}#4#8%
+ \expandafter\edef\csname#1#4:\s!chain\endcsname{\mult_interfaces_chain#1{##2}##1}%
\expandafter\edef\csname#1#4:\s!parent\endcsname{#1##2}%
\mult_interfaces_get_parameters{#1#4:}[##3]%
\else\ifsecondargument
@@ -291,16 +380,19 @@
\expandafter\mult_check_for_assignment_indeed\detokenize{##2}=@@\_end_
\ifassignment
\let#8\empty
+ \expandafter\edef\csname#1#4:\s!chain\endcsname{##1}%
\expandafter\edef\csname#1#4:\s!parent\endcsname{#3}%
\mult_interfaces_get_parameters{#1#4:}[##2]%
\else
\edef#8{##2}%
\mult_check_for_parent{#1}{#3}#4#8%
+ \expandafter\edef\csname#1#4:\s!chain\endcsname{\mult_interfaces_chain#1{##2}##1}%
\expandafter\edef\csname#1#4:\s!parent\endcsname{#1##2}%
\fi
\else
\the#6% predefine
\let#8\empty
+ \expandafter\edef\csname#1#4:\s!chain\endcsname{##1}%
\expandafter\edef\csname#1#4:\s!parent\endcsname{#3}%
\fi\fi
\the#7%
@@ -548,10 +640,10 @@
\expandafter\noexpand\csname everysetup#2\endcsname}}
\unexpanded\def\mult_interfaces_install_direct_parameter_set_handler#1#2#3#4#5%
- {\unexpanded\def#2{\dosetvalue #1}%
- \unexpanded\def#3{\dosetevalue#1}%
- \unexpanded\def#4{\doletvalue #1}%
- \unexpanded\def#5{\doletvalue #1\empty}}%
+ {\unexpanded\def#2{\mult_interfaces_def #1}%
+ \unexpanded\def#3{\mult_interfaces_edef#1}%
+ \unexpanded\def#4{\mult_interfaces_let #1}%
+ \unexpanded\def#5{\mult_interfaces_let #1\empty}}%
\startinterface english
@@ -629,7 +721,7 @@
\edef#2{##1}%
#3[##2]%
\else\iffirstargument
- \doifassignmentelse{##1}
+ \doifelseassignment{##1}
{\let#2\empty
#3[##1]}%
{\edef#2{##1}}%
@@ -691,12 +783,11 @@
\else
\global\advance\c_mult_interfaces_n_of_namespaces\plusone
\expandafter\edef\csname ??#1\endcsname{\v_interfaces_prefix_template}%
- \ctxcommand{registernamespace(\number\c_mult_interfaces_n_of_namespaces,"#1")}%
+ \clf_registernamespace\c_mult_interfaces_n_of_namespaces{#1}%
\fi}
-\def\mult_interfaces_get_parameters_error#1#2#3% redefined
- {\ctxcommand{showassignerror("#1","#2","#3",\the\inputlineno)}%
- \waitonfatalerror}
+\def\mult_interfaces_get_parameters_error_indeed#1#2%
+ {\clf_showassignerror{#1}{#2}\inputlineno} % no longer \waitonfatalerror
% We install two core namespaces here, as we want nice error messages. Maybe
% we will reserve the first 9.
@@ -778,10 +869,10 @@
{\dodoubleargument\mult_interfaces_define_name_space}
\def\mult_interfaces_define_name_space[#1][#2]% namespace settings
- {\ctxlua{interfaces.namespaces.define(\!!bs#1\!!es,\!!bs#2\!!es)}}
+ {\clf_definenamespace{#1}{#2}}
\def\listnamespaces
- {\ctxlua{interfaces.namespaces.list()}}
+ {\clf_listnamespaces}
%D Helper:
%D
@@ -807,6 +898,8 @@
\expandafter\secondoftwoarguments
\fi}
+\let\doifcommandhandlerelse\doifelsecommandhandler
+
\unexpanded\def\doifcommandhandler#1#2% namespace name
{\ifcsname#1#2:\s!parent\endcsname
\expandafter\firstofoneargument
@@ -825,10 +918,10 @@
% another set of (fast) helpers (grep for usage):
-\def\expandnamespaceparameter#1#2#3% \??xx \getp \c!xx \c!yy
+\def\expandnamespaceparameter#1#2#3% \??xx \getp \c!xx \v!yy
{\csname#1\ifcsname#1\expandafter\expandafter\expandafter\mult_aux_expand_namespace_parameter#2#3}
-\def\mult_aux_expand_namespace_parameter#1#2% \cs \c!yy
+\def\mult_aux_expand_namespace_parameter#1#2% \cs \v!yy
{#1\endcsname#1\else#2\fi\endcsname}
\def\expandnamespacemacro#1#2#3% \??xx \some_edefed_cs \c!yy
@@ -856,4 +949,302 @@
%D \edef\m_class_whatever{whatever}
%D \stoptyping
+% experiment: in principle this is faster but not that noticeable as we don't do that
+% many assignments and mechanism that do are also slow; the advantage is mostly nicer
+% in tracing
+
+\def\s!simple{simple}
+\def\s!single{single}
+\def\s!double{double}
+\def\s!triple{triple}
+
+\unexpanded\def\syst_helpers_double_empty#1#2#3%
+ {\syst_helpers_argument_reset
+ \doifelsenextoptional
+ {\syst_helpers_double_empty_one_yes_mult#2#3}%
+ {\syst_helpers_double_empty_one_nop_mult#1}}
+
+\def\syst_helpers_double_empty_one_yes_mult#1#2[#3]%
+ {\firstargumenttrue
+ \doifelsenextoptional
+ {\secondargumenttrue#2[{#3}]}%
+ {\syst_helpers_double_empty_two_nop_mult#1{#3}}}
+
+\def\syst_helpers_double_empty_one_nop_mult% #1%
+ {\firstargumentfalse
+ \secondargumentfalse
+ }% #1}
+
+\def\syst_helpers_double_empty_two_nop_mult
+ {\secondargumentfalse
+ \if_next_blank_space_token
+ \expandafter\syst_helpers_double_empty_one_spaced_mult
+ \else
+ \expandafter\syst_helpers_double_empty_one_normal_mult
+ \fi}
+
+\def\syst_helpers_double_empty_one_spaced_mult#1#2{#1[{#2}] }
+\def\syst_helpers_double_empty_one_normal_mult#1#2{#1[{#2}]}
+
+\unexpanded\def\mult_interfaces_install_setup_handler#1#2#3#4#5#6#7#8%
+ {\ifx#3\relax\let#3\empty\fi
+ \unexpanded\def#5{\mult_interfaces_get_parameters{#1#3:}}% no every ! don't change it
+ \newtoks#4%
+ \newtoks#7%
+ \edef\m_mult_interface_setup{\strippedcsname#2_}%
+ \unexpanded\edef#2{\syst_helpers_double_empty
+ \csname\m_mult_interface_setup\s!simple\endcsname
+ \csname\m_mult_interface_setup\s!single\endcsname
+ \csname\m_mult_interface_setup\s!double\endcsname}%
+ \unexpanded\expandafter\def\csname\m_mult_interface_setup\s!double\endcsname[##1][##2]%
+ {\let#6#3%
+ \def#8####1% we will have a simple one as well
+ {\edef#3{####1}%
+ \mult_interfaces_get_parameters{#1#3:}[##2]%
+ \the#4}%
+ \processcommalist[##1]#8%
+ \let#3#6%
+ \the#7}%
+ \unexpanded\expandafter\def\csname\m_mult_interface_setup\s!single\endcsname[##1]%
+ {\let#6#3%
+ \let#3\empty
+ \mult_interfaces_get_parameters{#1:}[##1]%
+ \the#4%
+ \let#3#6%
+ \the#7}%
+ \unexpanded\expandafter\def\csname\m_mult_interface_setup\s!simple\endcsname%
+ {\let#6#3%
+ \let#3\empty
+ \the#4%
+ \let#3#6%
+ \the#7}}
+
+\unexpanded\def\installsetuphandler#1#2%
+ {\normalexpanded
+ {\mult_interfaces_install_setup_handler
+ {\noexpand#1}% \??aa
+ \expandafter\noexpand\csname setup#2\endcsname
+ \expandafter\noexpand\csname current#2\endcsname
+ \expandafter\noexpand\csname everysetup#2\endcsname
+ \expandafter\noexpand\csname setupcurrent#2\endcsname
+ \expandafter\noexpand\csname saved_setup_current#2\endcsname
+ \expandafter\noexpand\csname everysetup#2root\endcsname
+ \expandafter\noexpand\csname nested_setup_current#2\endcsname}}
+
+\unexpanded\def\syst_helpers_triple_empty#1#2#3#4%
+ {\syst_helpers_argument_reset
+ \doifelsenextoptional
+ {\syst_helpers_triple_empty_one_yes_mult#2#3#4}%
+ {\syst_helpers_triple_empty_one_nop_mult#1}}
+
+\def\syst_helpers_triple_empty_one_yes_mult#1#2#3[#4]%
+ {\firstargumenttrue
+ \doifelsenextoptional
+ {\syst_helpers_triple_empty_two_yes_mult#2#3{#4}}%
+ {\syst_helpers_triple_empty_two_nop_mult#1{#4}}}
+
+\def\syst_helpers_triple_empty_two_yes_mult#1#2#3[#4]%
+ {\secondargumenttrue
+ \doifelsenextoptional
+ {\thirdargumenttrue#2[{#3}][{#4}]}%
+ {\syst_helpers_triple_empty_three_nop_mult#1{#3}{#4}}}
+
+\def\syst_helpers_triple_empty_one_nop_mult % #1%
+ {\firstargumentfalse
+ \secondargumentfalse
+ \thirdargumentfalse
+ } % #1
+
+\def\syst_helpers_triple_empty_two_nop_mult
+ {\secondargumentfalse
+ \thirdargumentfalse
+ \if_next_blank_space_token
+ \expandafter\syst_helpers_triple_empty_two_spaced_mult
+ \else
+ \expandafter\syst_helpers_triple_empty_two_normal_mult
+ \fi}
+
+\def\syst_helpers_triple_empty_three_nop_mult
+ {\thirdargumentfalse
+ \if_next_blank_space_token
+ \expandafter\syst_helpers_triple_empty_three_spaced_mult
+ \else
+ \expandafter\syst_helpers_triple_empty_three_normal_mult
+ \fi}
+
+\def\syst_helpers_triple_empty_two_spaced_mult #1#2{#1[{#2}] }
+\def\syst_helpers_triple_empty_two_normal_mult #1#2{#1[{#2}]}
+\def\syst_helpers_triple_empty_three_spaced_mult#1#2#3{#1[{#2}][{#3}] }
+\def\syst_helpers_triple_empty_three_normal_mult#1#2#3{#1[{#2}][{#3}]}
+
+\unexpanded\def\mult_interfaces_install_auto_setup_handler#1#2#3#4#5#6#7#8%
+ {\ifx#3\relax\let#3\empty\fi
+ \unexpanded\def#5{\mult_interfaces_get_parameters{#1#3:}}%
+ \newtoks#4%
+ \edef\m_mult_interface_setup{\strippedcsname#2_}%
+ \unexpanded\edef#2{\syst_helpers_triple_empty
+ \csname\m_mult_interface_setup\s!simple\endcsname
+ \csname\m_mult_interface_setup\s!single\endcsname
+ \csname\m_mult_interface_setup\s!double\endcsname
+ \csname\m_mult_interface_setup\s!triple\endcsname}%
+ \unexpanded\expandafter\def\csname\m_mult_interface_setup\s!triple\endcsname[##1][##2][##3]%
+ {\let#7#3%
+ \def#8####1%
+ {\edef#3{####1}%
+ \expandafter\def\csname#1#3:\s!parent\endcsname{#1##2}%
+ \mult_interfaces_get_parameters{#1#3:}[##3]% always sets parent
+ \the#4}%
+ \processcommalist[##1]#8%
+ \let#3#7}%
+ \unexpanded\expandafter\def\csname\m_mult_interface_setup\s!double\endcsname[##1][##2]%
+ {\let#7#3%
+ \def#8####1%
+ {\edef#3{####1}%
+ #6% checks parent and sets if needed
+ \mult_interfaces_get_parameters{#1#3:}[##2]%
+ \the#4}%
+ \processcommalist[##1]#8%
+ \let#3#7}%
+ \unexpanded\expandafter\def\csname\m_mult_interface_setup\s!single\endcsname[##1]%
+ {\let#7#3%
+ \let#3\empty
+ \mult_interfaces_get_parameters{#1:}[##1]%
+ \the#4%
+ \let#3#7}%
+ \unexpanded\expandafter\def\csname\m_mult_interface_setup\s!simple\endcsname%
+ {\let#7#3%
+ \let#3\empty
+ \the#4%
+ \let#3#7}}
+
+\unexpanded\def\installautosetuphandler#1#2%
+ {\normalexpanded
+ {\mult_interfaces_install_auto_setup_handler
+ {\noexpand#1}% \??aa
+ \expandafter\noexpand\csname setup#2\endcsname
+ \expandafter\noexpand\csname current#2\endcsname
+ \expandafter\noexpand\csname everysetup#2\endcsname
+ \expandafter\noexpand\csname setupcurrent#2\endcsname
+ \expandafter\noexpand\csname check#2parent\endcsname
+ \expandafter\noexpand\csname saved_setup_current#2\endcsname
+ \expandafter\noexpand\csname nested_setup_current#2\endcsname}}
+
+% okay, we can also get rid of the #9, but this code looks pretty bad, while the previous is
+% still okay given that we can also use #6 as setup (so in fact we can save some cs again and
+% only use one extra)
+%
+% \global\advance\commalevel \plusone
+% \expandafter\def\csname\??nextcommalevel\the\commalevel\endcsname####1,%
+% {\edef#3{####1}%
+% \mult_interfaces_get_parameters{#1#3:}[##2]%
+% \the#5%
+% \syst_helpers_do_process_comma_item}%
+% \expandafter\syst_helpers_do_do_process_comma_item\gobbleoneargument\relax##1,]\relax
+% % \syst_helpers_do_do_process_comma_item##1,]\relax
+% \global\advance\commalevel \minusone
+
+% The next one is experimental (and used in publications):
+
+\let\c_mult_set\relax
+
+\unexpanded\def\mult_interfaces_install_definition_set#1#2#3#4#5#6#7%
+ {\newcount#3%
+ \let#6\empty
+ \unexpanded\def#2%
+ {\expandafter\let\expandafter\c_mult_set\csname #1_t_#6\endcsname
+ \ifx\c_mult_set\relax
+ \expandafter\newtoks\c_mult_set
+ \expandafter\let\csname #1_t_#6\endcsname\c_mult_set
+ \fi}
+ \unexpanded\def#4##1%
+ {\pushmacro#6%
+ \advance#3\plusone
+ \edef#6{##1}%
+ \unprotect}%
+ \unexpanded\def#5%
+ {\protect
+ \advance#3\minusone
+ \popmacro#6}%
+ \unexpanded\def#7##1%
+ {\edef#6{##1}%
+ #2%
+ \the\c_mult_set\relax}}
+
+\unexpanded\def\installdefinitionset#1#2%
+ {\normalexpanded
+ {\mult_interfaces_install_definition_set
+ {\noexpand#1}% \??aa
+ \expandafter\noexpand\csname set_#2_toks\endcsname
+ \expandafter\noexpand\csname #2_nesting_depth\endcsname
+ \expandafter\noexpand\csname push#2\endcsname
+ \expandafter\noexpand\csname pop#2\endcsname
+ \expandafter\noexpand\csname current#2\endcsname
+ \expandafter\noexpand\csname use#2\endcsname}}
+
+\unexpanded\def\mult_interfaces_install_definition_set_member#1#2#3#4#5#6#7#8#9% no everysetups etc
+ {\let#5#2%
+ \unexpanded\def#2%
+ {\ifcase#4\relax\expandafter#5\else\expandafter#6\fi}%
+ \unexpanded\def#6%
+ {\dodoubleempty#7}%
+ \unexpanded\def#7[##1][##2]%
+ {\ifsecondargument
+ #3\c_mult_set\expandafter{\the\c_mult_set#9[##1][##2]}%
+ \else\iffirstargument
+ #3\c_mult_set\expandafter{\the\c_mult_set#8[##1]}%
+ \fi\fi}}
+
+\unexpanded\def\installdefinitionsetmember#1#2#3#4%
+ {\normalexpanded
+ {\mult_interfaces_install_definition_set_member
+ {\noexpand#3}% \??aa
+ \expandafter\noexpand\csname setup#4\endcsname
+ \expandafter\noexpand\csname set_#2_toks\endcsname
+ \expandafter\noexpand\csname #2_nesting_depth\endcsname
+ \expandafter\noexpand\csname normal_setup_#4\endcsname
+ \expandafter\noexpand\csname delayed_setup_#4\endcsname
+ \expandafter\noexpand\csname do_delayed_setup_#4\endcsname
+ \expandafter\noexpand\csname setup#4_\s!single\endcsname
+ \expandafter\noexpand\csname setup#4_\s!double\endcsname}}
+
+%D Another experiment:
+
+\unexpanded\def\mult_interfaces_install_parent_injector#1#2#3#4%
+ {\unexpanded\def#4##1%
+ {\ifx#3\empty
+ \expandafter\def\csname#1#2:\s!parent\endcsname{#1##1}%
+ \fi}}
+
+\unexpanded\def\installparentinjector#1#2%
+ {\normalexpanded{\mult_interfaces_install_parent_injector
+ {\noexpand#1}%
+ \expandafter\noexpand\csname current#2\endcsname
+ \expandafter\noexpand\csname current#2parent\endcsname
+ \expandafter\noexpand\csname inject#2parent\endcsname}}
+
\protect
+
+%\unprotect
+% \installcorenamespace {test} \installcommandhandler \??test {test} \??test
+% \unexpanded\def\TestMeA[#1]%
+% {\edef\currenttest{#1}
+% \edef\p_before{\testparameter\c!before}%
+% \ifx\p_before\empty \relax \else \relax \fi}
+% \unexpanded\def\TestMeB[#1]%
+% {\edef\currenttest{#1}
+% \doifelsenothing{\testparameter\c!before}\relax\relax}
+% \unexpanded\def\TestMeC[#1]%
+% {\edef\currenttest{#1}
+% \expandafter\expandafter\expandafter\ifx\testparameter\c!before\empty \relax \else \relax \fi}
+% \unexpanded\def\TestMeD[#1]%
+% {\edef\currenttest{#1}
+% \doubleexpandafter\ifx\testparameter\c!before\empty \relax \else \relax \fi}
+% \protect
+%
+% \starttext
+% \definetest[foo] \definetest[bar][foo] \setuptest[bar][before=indeed]
+% \resettimer \dorecurse{100000}{\TestMeA[bar]} A:\elapsedtime \par % 0.502
+% \resettimer \dorecurse{100000}{\TestMeB[bar]} B:\elapsedtime \par % 0.530
+% \resettimer \dorecurse{100000}{\TestMeC[bar]} C:\elapsedtime \par % 0.487
+% \resettimer \dorecurse{100000}{\TestMeD[bar]} D:\elapsedtime \par % 0.493
+% \stoptext