%%%============================================================================== %% Copyright 2023-present by Alceu Frigeri %% %% This work may be distributed and/or modified under the conditions of %% %% * The [LaTeX Project Public License](http://www.latex-project.org/lppl.txt), %% version 1.3c (or later), and/or %% * The [GNU Affero General Public License](https://www.gnu.org/licenses/agpl-3.0.html), %% version 3 (or later) %% %% This work has the LPPL maintenance status *maintained*. %% %% The Current Maintainer of this work is Alceu Frigeri %% %% This is version {2.0} {2026/02/03} %% %% The list of files that compose this work can be found in the README.md file at %% https://ctan.org/pkg/starray %% %%%============================================================================== \NeedsTeXFormat{LaTeX2e}[2025/06/01] %%%%%%% %%% %%% Just an attempt at having my package's info in a regular way %%% \pkginfograb_set:nn {} { props} sets package info %%% %%% \pkginfograbProvidesExplPackage {} { props} sets package info %%% and calls \ProvidesExplPackage %%% %%%%%%% \RequirePackage{pkginfograb} \pkginfograbProvidesExplPackage {starray} { name = {starray} , prefix = {starray} , date = {2026/02/03}, version = {2.0} , description = {A NEW structured array/hash of properties} } %%%%%%% %%% End of cut-n-paste %%%%%%% %%%%%%%%%%%%%%%%%%% %%%% %%%% New package %%%% %%%%%%%%%%%%%%%%%%% \bool_new:N \l__starray_NNnames_bool \bool_new:N \l__starray_NNnames_warn_bool \keys_define:nn { starray } { % prefix .tl_set:N = g__starray_prfix_ , % prefix .value_required:n = true , % prefix .initial:n = l__starray_ , % prefix .usage:n = load , NN~names . usage:n = load , NN~names .choice: , NN~names / none .code:n = { \bool_set_false:N \l__starray_NNnames_bool }, NN~names / no~warnings .code:n = { \bool_set_true:N \l__starray_NNnames_bool \bool_set_false:N \l__starray_NNnames_warn_bool } , NN~names / strict .code:n = { \bool_set_true:N \l__starray_NNnames_bool \bool_set_true:N \l__starray_NNnames_warn_bool } , íter~cascade .usage:n = load , iter~cascade .bool_set:N = \l__starray_cascade_bool , iter~cascade .value_forbidden:n = true , msg-err .usage:n = load , msg-err .choice: , msg-err / none .code:n = { }, msg-err / default .code:n = {} , msg-err / strict .code:n = { \msg_redirect_module:nnn { starray / strict } { warning } { error } } , msg-err / syntax .code:n = { \msg_redirect_module:nnn { starray / strict } { warning } { error } \msg_redirect_module:nnn { starray / syntax } { warning } { error } } , msg-err / reference .code:n = { \msg_redirect_module:nnn { starray / strict } { warning } { error } \msg_redirect_module:nnn { starray / syntax } { warning } { error } \msg_redirect_module:nnn { starray / reference } { warning } { error } } , msg-err / all .code:n = { \msg_redirect_module:nnn { starray } { warning } { error } } , msg-supress .usage:n = load , msg-supress .choice: , msg-supress / none .code:n = {} , msg-supress / reference .code:n = { \msg_redirect_module:nnn { starray / reference } { warning } { none } } , msg-supress / syntax .code:n = { \msg_redirect_module:nnn { starray / strict } { warning } { none } \msg_redirect_module:nnn { starray / syntax } { warning } { none } } , msg-supress / strict .code:n = { \msg_redirect_module:nnn { starray / strict } { warning } { none } \msg_redirect_module:nnn { starray / syntax } { warning } { none } \msg_redirect_module:nnn { starray / reference } { warning } { none } } , msg-supress / all .code:n = { \msg_redirect_module:nnn { starray } { warning } { none } } , parsed~ check .usage:n = load , parsed~ check .bool_set:N = \l__starray_parsed_check_bool , parsed~ check .value_forbidden:n = true , } \ProcessKeyOptions [ starray ] %%%%%%%%%%%%%%% %%%%%%%%%%%%%%% %%%% %%%% New variants of core expl3 primitives %%%% expansion handling %%%% %%%%%%%%%%%%%%% %%%%%%%%%%%%%%% \cs_generate_variant:Nn \int_to_Alph:n {e} \cs_generate_variant:Nn \keyval_parse:nnn {ee} \cs_generate_variant:Nn \prg_new_conditional:Nnn { c } \cs_generate_variant:Nn \prg_new_conditional:Npnn {c} %% This is just for debugging. Otherwise, not needed \cs_generate_variant:Nn \tl_show:n {e} %%%%%%%%%%%%%%% %%%%%%%%%%%%%%% %%%% %%%% Package error/warning messages %%%% #1 'ID' (code identifier) %%%% #2 / #3 / #4 further fields (as needed) %%%% %%%%%%%%%%%%%%% %%%%%%%%%%%%%%% \msg_new:nnnn {starray} {strict / Expl} { Expl~ version~ too~ old.~ Update~ needed! } { Expl~ version~ too~ old.~ Update~ needed! } \msg_new:nnnn {starray} {strict / (re)define} { (ID:#1)~'#2'~already~defined! } { You~tried~to~(re)define~'#2'. ~Error~Code~ ID:<#1>. } \msg_new:nnnn {starray} {syntax / ref-syntax-err} { (ID:#1)~term~reference~'#2'~--~'#3'. } { Your~term~'#2'~contains~a~syntax~error:~'#3'. ~Error~ Code~ ID:<#1>. } \msg_new:nnnn {starray} {syntax / keyval-term} { (ID:#1)~term~reference~'#2'~error~'#3'. } { Your~term~'#2'~contains~a~syntax~error:~'#3'. ~Error~ Code~ ID:<#1>. } \msg_new:nnnn {starray} {syntax / term} { (ID:#1)~'#2'~isn't~a~valid~term~ref. } { Invalid~term~reference:~'#2'. ~Error~ Code~ ID:<#1>. } \msg_new:nnnn {starray} {syntax / parsed} { (ID:#1)~Can't~ call~ #2~ after~a~ failed~ \starray_term_parser: } { You~ called~ #2~ after~ a~ failed~ call~ to~ \starray_term_parser: ~Error~ Code~ ID:<#1>. } \msg_new:nnnn {starray} {syntax / structure-ref} { (ID:#1)~'#3'~isn't~a~sub-structure~of~'#2'. } { '#2' ~doesn't~have~a~sub-structure~named:~'#3'. ~Error~ Code~ ID:<#1>. } \msg_new:nnnn {starray} {syntax / iter} { (ID:#1)~cannot~set~iter. ~invalid~'#2'. } { cannot~set~iter.~ invalid '#2'. ~Error~ Code~ ID:<#1>. } \msg_new:nnnn {starray} {syntax / prop} { (ID:#1)~cannot~get/set~property~from~'#2'. } { You~have~referenced~an~invalid~structure~'#2'. ~Error~ Code~ ID:<#1>. } \msg_new:nnnn {starray} {reference / keyval} { (ID:#1)~key~'#2'~ignored. } { You~referenced~a~key~without~setting~it's~value. ~Key~ignored. } \msg_new:nnnn {starray} {reference / invalid-starray} %%%$$ { (ID:#1)~'#2'~invalid~starray. \tl_if_blank:nTF {#3} {~#3} {} } { '#2'~isn't~a~starray. \tl_if_blank:nTF {#3} {~#3} {} ~Error~ Code~ ID:<#1>. } \msg_new:nnnn {starray} {reference / iter} { (ID:#1)~invalid~iter~(#3)~from~'#2' \str_if_empty:nTF {#4} {} {#4} . } { Invalid~iter~(#3)~from~ '#2'.~You~might~have~tried~to~use/set/reset~an~iter~of ~an~ill~instantiated~structured. ~Error~ Code~ ID:<#1>. } \msg_new:nnnn {starray} {reference / prop} %%%$$ { (ID:#1)~cannot~get/set~property~'#3'~from~'#2'. } { '#3'~isn't~a~property~of~'#2'. ~Error~ Code~ ID:<#1>. } \msg_new:nnnn {starray} {info / show} { \iow_newline:(ID:#1)\iow_newline:~ #2 \iow_newline: #3 \iow_newline: definition's~end. } { \iow_newline:(ID:#1)\iow_newline:~ #2 \iow_newline: #3 \iow_newline: definition's~end. } %%%%% %%%%% %% Making this as short as possible (less than 60 chars) %% so \msg_expandable_error: might be used. %%%%% \msg_new:nnnn {starray} {strict / deprecate} { (#1)~'#2'~has ~ been ~ deprecated. } { The ~ command~'#2'~has ~ been ~ deprecated. ~ Use~'#3'~ instead. ~Error~ Code~ ID:<#1>. } \IfExplAtLeastTF{2024-03-14}{}{\msg_warning:nn {starray} {strict / Expl} } \cs_new_protected:Npn \__starray_msg:nnnnn #1#2#3#4#5 { \__starray_set_rtn_false: \seq_gput_right:Nn \g__starray_msg_seq { \msg_warning:nnnnnn {starray}{ #1 } { #2 }{ #3 }{ #4 }{ #5 } } } \cs_generate_variant:Nn \__starray_msg:nnnnn { nneee , neeee } \cs_new_protected:Npn \__starray_msg:nnnn #1#2#3#4 { \__starray_set_rtn_false: \seq_gput_right:Nn \g__starray_msg_seq { \msg_warning:nnnnn {starray}{ #1 } { #2 }{ #3 }{ #4 } } } \cs_generate_variant:Nn \__starray_msg:nnnn { nnee , neee } \cs_new_protected:Npn \__starray_msg_dispatch: { \seq_map_inline:Nn \g__starray_msg_seq { ##1 } \seq_gclear:N \g__starray_msg_seq } \cs_new_protected:Npn \__starray_msg_clear: { \seq_gclear:N \g__starray_msg_seq } %%%%%%%%%%%%%%% %%%%%%%%%%%%%%% %%%% %%%% Package Variables declaration %%%% %%%% %%%%%%%%%%%%%%% %%%%%%%%%%%%%%% %%%% %%%% 'general' (internal) returning bool %%%% \cs_new:Npn \__starray_set_rtn_true: { \cs_set_eq:NN \__starray_rtn: \prg_return_true: } \cs_new:Npn \__starray_set_rtn_false: { \cs_set_eq:NN \__starray_rtn: \prg_return_false: } %%%% %%%% sequence of 'error mensages' (stacked). %%%% \seq_new:N \g__starray_msg_seq \tl_new:N \l__starray_tmpa_tl % to replace \l_tmpa_tl % new_term \tl_new:N \l__starray_tmpb_tl % to replace \l_tmpb_tl % fix terms+set iter from hash+if valid idx+set from keyval \tl_new:N \l__starray_parser_tmp_A_tl \tl_new:N \l__starray_parser_tmp_B_tl \tl_new:N \l__starray_show_tmp_tl \tl_new:N \l__starray_tmp_term_st %%%% %%%% (sub)structure returning tl. %%%% \tl_new:N \l__starray_keyval_tmpb_tl \tl_new:N \l__starray_keyval_tmpa_tl %%%% %%%% parser related ones %%%% \bool_const:Nn \c__starray_no_idx_ending_bool \c_true_bool \bool_const:Nn \c__starray_idx_ending_bool \c_false_bool \tl_new:N \l__starray_from_keyval_orgref_tl %%%% %%%% parser returning variables %%%% \tl_new:N \l__starray_parsed_tl \tl_new:N \l__starray_parsed_ref_tl \tl_new:N \l__starray_parsed_base_st \tl_new:N \l__starray_parsed_term_st \tl_new:N \g__starray_parsed_saved_base_st \tl_new:N \g__starray_parsed_saved_term_st \bool_new:N \g__starray_parsed_bool \tl_new:N \l__starray_parsing_term_tl %%%% %%%% parser 'internal' variables %%%% \bool_new:N \l__starray_parser_no_idx_ending_bool \tl_new:N \l__starray_parsed_term_tl \tl_new:N \l__starray_parsed_idx_tl \bool_new:N \l__starray_parser_OK_bool %%%% %%%% for cs/prg generating commands %%%% \tl_new:N \l__starray_csuse_tmp_tl %%%% %%%% scan mark for _base_st, _term_st and _ref_st %%%% \scan_new:N \s__end \tl_new:N \l__starray_duocmd_tmpa_tl \tl_new:N \l__starray_duocmd_tmpb_tl %% big one, (g)put !! %%%% %%%% (g)put :: IF the effect shall be local or global %%%% \cs_set_eq:NN \__starray_put:cnn \use_none:nnn %%%%%%%%% %%% %%% This will create 3 variants %%% This one is *NEVER* expandable %%% {starray_ #cmd# : n #signature# } => standard one, expecting a starray-term-ref %%% This *might* be expandable (if base-code is) %%% {starray_ parsed_ #cmd# : NN #signature# } => expecting two user given variables (from previous parsing) %%% This *might* be expandable (if base-code (and if-parsed-bool-false, if checked) is) %%% {starray_ parsed_ #cmd# : #signature# } => using *last* parsed term, with/without checking %%% %%%%%%%%% %%% %%% Regarding the base-code: it will 'get' two extra param BEFORE the ones in #signature# %%% NN#signature# (for example, signature:nN... real signature: NNnN #1#2#3#4 %%% whereas the first two parameters, NN, will (should) always be '...ref_tl' and '...ref_no_idx_ending_tl' %%% %%% 'if-parser-failed' code shall expect a single parameter: starray-ref %%% %%% 'if-parsed-failed' code shall expect no parameter! %%% %%%%%%%%% %%% #1 -> #cmd# => base-name %%% #2 -> #signature# %%% #3 -> \c__starray_idx_ending_bool / \c__starray_no_idx_ending_bool %%% #4 -> base-code % if expandable, the resulting commands *might* also be %%% #5 -> if-parser-failed % NB.: this will be in the F branch of \__starry_parser: *not* expandable %%% #6 -> if-parsed-bool-false % NB.: this will be in the F branch of a \bool_if: *might* be expandable %%%%%%%%% \cs_new_protected:Npn \__starray_cs_generate:nnNnnn #1#2#3#4 { \int_case:nn { \tl_count:n {#2} } { {0} { \tl_set:Nn \l__starray_csuse_tmp_tl {} } {1} { \tl_set:Nn \l__starray_csuse_tmp_tl {\use_none:n} } {2} { \tl_set:Nn \l__starray_csuse_tmp_tl {\use_none:nn} } {3} { \tl_set:Nn \l__starray_csuse_tmp_tl {\use_none:nnn} } } \cs_new:cn {__starray_parsed_ #1 : nn#2} { #4 } \__starray_cs_generate:cVnnNnn {__starray_parsed_ #1 : nn#2} \l__starray_csuse_tmp_tl {#1}{#2} #3 } %%%%%%%%% %%% #1 -> base %%% #2 -> none %%% #3 -> cmd radix %%% #4 -> base signature %%% #5 -> \c__starray_idx_ending_bool / \c__starray_no_idx_ending_bool %%% #6 -> in case parser err %%% #7 -> in case *parsed* err %%%%%%%%% \cs_new_protected:Npn \__starray_cs_generate:NnnnNnn #1#2#3#4#5#6#7 { \cs_new:cpn {starray_uparsed_ #3 : N#4} ##1 { \exp_last_unbraced:NV #1 ##1 } \bool_if:NTF \l__starray_NNnames_bool { \bool_if:NTF \l__starray_NNnames_warn_bool { \cs_new:cpn {starray_parsed_ #3 : NN#4} ##1##2 { %%% Just in case 'this' is used in an expandable context \msg_expandable_error:nnnnn {starray} {strict / deprecate} {cs:01} { starray_parsed_ #3 : NN#4 } { starray_uparsed_ #3 : N#4 } \exp_last_unbraced:NV #1 ##1 } } { \cs_new:cpn {starray_parsed_ #3 : NN#4} ##1##2 { \exp_last_unbraced:NV #1 ##1 } } } {} \bool_if:NTF \l__starray_parsed_check_bool { \cs_new:cpn {starray_parsed_ #3 : #4} { \bool_if:NTF \g__starray_parsed_bool { \exp_args:Noo #1 \g__starray_parsed_saved_term_st \g__starray_parsed_saved_base_st} { #7 #2 } } } { \cs_new:cpn {starray_parsed_ #3 : #4} { \exp_args:Noo #1 \g__starray_parsed_saved_term_st \g__starray_parsed_saved_base_st} } \cs_new:cpn {starray_iparsed_ #3 : #4} { \exp_args:Noo #1 \g__starray_iterate_term_st \g__starray_iterate_base_st} \cs_new:cpn {starray_ #3 : n#4} ##1 { \__starray_parser:NeTF #5 {##1} { \exp_args:Noo #1 \l__starray_parsed_term_st \l__starray_parsed_base_st} { #6 #2 } } } \cs_generate_variant:Nn \__starray_cs_generate:NnnnNnn {cV} %%%%%%%%% WARNING: p variants.... might not be expandable !!! %%% %%% This will create 4 variants (x4 => p,T,F,TF) %%% This will *NEVER* expandable %%% {starray_ #cmd# : n #signature# {p,TF,T,F}} => standard one, expecting a starray-term-ref %%% This *might* be expandable (if base-code and T/F code (that follows) also are) %%% {starray_ parsed_ #cmd# : NN #signature# {p, TF,T,F}} => expecting two user given variables (from previous parsing) %%% This *might* be expandable (if base-code and T/F code (that follows) also are... and (if-parsed-boold-false, if checked) %%% {starray_ parsed_ #cmd# : #signature# {p,TF,T,F}} => using *last* parsed term, with/without checking %%% %%% regarding the _p variants.. they will be ok iff #3 is expandable! %%% %%%%%%%%% %%% %%% Regarding the base-code: it will 'get' two extra param BEFORE the ones in the signature %%% NN#signature# (for example, signature:nN... real signature: NNnN #1#2#3#4 %%% whereas the first two parameters, NN, will (should) always be '...ref_tl' and '...ref_no_idx_ending_tl' %%% %%% 'if-parser-failed' code shall expect a single parameter: starray-ref %%% %%% 'if-parsed-failed' code shall expect no parameter! %%% %%% For all of them to be expandable, #3, #4 and #5 have also to be expandable. %%% %%%%%%%%% %%% #1 -> #cmd# => base-name %%% #2 -> #signature# %%% #3 -> \c__starray_idx_ending_bool / \c__starray_no_idx_ending_bool %%% #3=>4 -> base-code %%% #4=>5 -> if-parser-failed %%% #5=>6 -> if-parsed-bool-false %%%%%%%%% \tl_new:N \l__starray_useAa_tl \tl_new:N \l__starray_useAb_tl \tl_new:N \l__starray_useBa_tl \tl_new:N \l__starray_useBb_tl \cs_new_protected:Npn \__starray_prg_generate:nnNnnn #1#2#3#4#5#6 { \int_case:nn { \tl_count:n {#2} } %%%% THOSE are for the "false" cases...(parameters not aboserbed by #signature#TF/_p/T/F cases) { {0} { \tl_set:Nn \l__starray_useBa_tl {\use_ii:nn} %% for the TF case \tl_set:Nn \l__starray_useBb_tl {} %% for the _p case \tl_set:Nn \l__starray_useAa_tl {\use_none:n} %% for the T case \tl_set:Nn \l__starray_useAb_tl {\use_i:n} %% for the F case } {1} { \tl_set:Nn \l__starray_useBa_tl {\use_iii:nnn} \tl_set:Nn \l__starray_useBb_tl {\use_none:n} \tl_set:Nn \l__starray_useAa_tl {\use_none:nn} \tl_set:Nn \l__starray_useAb_tl {\use_ii:nn} } {2} { \tl_set:Nn \l__starray_useBa_tl {\use_iv:nnnn} \tl_set:Nn \l__starray_useBb_tl {\use_none:nn} \tl_set:Nn \l__starray_useAa_tl {\use_none:nnn} \tl_set:Nn \l__starray_useAb_tl {\use_iii:nnn} } {3} { \tl_set:Nn \l__starray_useBa_tl {\use_v:nnnnn} \tl_set:Nn \l__starray_useBb_tl {\use_none:nnn} \tl_set:Nn \l__starray_useAa_tl {\use_none:nnnn} \tl_set:Nn \l__starray_useAb_tl {\use_iv:nnnn} } } % % the _p might be ok (expandable) ... depending on #4 % \prg_new_conditional:cnn {__starray_parsed_ #1 : nn#2} {p , T , F , TF} { #4 } \__starray_prg_generate_a:ccVVnnNnn {__starray_parsed_ #1 : nn#2 TF} {__starray_parsed_ #1 _p : nn#2} \l__starray_useBa_tl \l__starray_useBb_tl {#1}{#2}{#3}{#5}{#6} \__starray_prg_generate_b:ccVVnnNnn {__starray_parsed_ #1 : nn#2 T} {__starray_parsed_ #1 : nn#2 F} \l__starray_useAa_tl \l__starray_useAb_tl {#1}{#2}{#3}{#5}{#6} } %%%%%%%%% %%% %%% if not expandable, better undefine them %%% %%%%%%%%% \cs_new_protected:Npn \__starray_prg_undef_p:nn #1#2 { \bool_if:NTF \l__starray_NNnames_bool { \cs_undefine:c { starray_parsed_ #1 _p: NN#2 } } {} \cs_undefine:c { __starray_parsed_ #1 _p: nn#2 } \cs_undefine:c { starray_uparsed_ #1 _p: N#2 } \cs_undefine:c { starray_parsed_ #1 _p: #2 } } %%%%%%%%% %%% #1 -> baseTF %%% #2 -> base_p %%% #3 -> noneA %%% #4 -> none (for _p case) %%% #5 -> cmd radix %%% #6 -> base signature %%% #7 -> \c__starray_idx_ending_bool / \c__starray_no_idx_ending_bool %%% #7=>8 -> in case parser err %%% #8=>9 -> in case *parsed* err %%%%%%%%% \cs_new_protected:Npn \__starray_prg_generate_a:NNnnnnNnn #1#2#3#4#5#6#7#8#9 { \cs_new:cpn {starray_uparsed_ #5 : N#6 TF} ##1 { \exp_last_unbraced:NV #1 ##1} \cs_new:cpn {starray_uparsed_ #5 _p : N#6} ##1 { \exp_last_unbraced:NV #2 ##1} \bool_if:NTF \l__starray_NNnames_bool { \bool_if:NTF \l__starray_NNnames_warn_bool { \cs_new:cpn {starray_parsed_ #5 : NN#6 TF} ##1##2 { \msg_warning:nnnnn {starray} {strict / deprecate} {prg:01} { starray_parsed_ #5 : NN#6 TF } { starray_uparsed_ #5 : N#6 TF } \exp_last_unbraced:NV #1 ##1 } \cs_new:cpn {starray_parsed_ #5 _p : NN#6} ##1##2 { %%% Just in case 'this' is used in an expandable context \msg_expandable_error:nnnnn {starray} {strict / deprecate} {prg:02} % This will certainly generate low level erros... :/ % \msg_warning:nnnnn {starray} {strict / deprecate} {prg:02} { \ starray_parsed_ #5 _p : NN#6 } { \ starray_parsed_ #5 _p : N#6 } \exp_last_unbraced:NV #2 ##1 } } { \cs_new:cpn {starray_parsed_ #5 : NN#6 TF} ##1##2 { \exp_last_unbraced:NV #1 ##1 } \cs_new:cpn {starray_parsed_ #5 _p : NN#6} ##1##2 { \exp_last_unbraced:NV #2 ##1 } } } {} \bool_if:NTF \l__starray_parsed_check_bool { \cs_new:cpn {starray_parsed_ #5 : #6 TF} { \bool_if:NTF \g__starray_parsed_bool { \exp_args:Noo #1 \g__starray_parsed_saved_term_st \g__starray_parsed_saved_base_st} { #9 #3 } %%TODO... this should absorb N+2 and execute the last one... } \cs_new:cpn {starray_parsed_ #5 _p : #6 } { \bool_if:NTF \g__starray_parsed_bool { \exp_args:Noo #2 \g__starray_parsed_saved_term_st \g__starray_parsed_saved_base_st} { #9 #4 } %%TODO... hopefully this is correct... absorbs N tokens...execute none } } { \cs_new:cpn {starray_parsed_ #5 : #6 TF} { \exp_args:Noo #1 \g__starray_parsed_saved_term_st \g__starray_parsed_saved_base_st} \cs_new:cpn {starray_parsed_ #5 _p : #6 } { \exp_args:Noo #2 \g__starray_parsed_saved_term_st \g__starray_parsed_saved_base_st} } \cs_new:cpn {starray_iparsed_ #5 : #6 TF} { \exp_args:Noo #1 \g__starray_iterate_term_st \g__starray_iterate_base_st} \cs_new:cpn {starray_iparsed_ #5 _p : #6 } { \exp_args:Noo #2 \g__starray_iterate_term_st \g__starray_iterate_base_st} \cs_new:cpn {starray_ #5 : n#6 TF} ##1 { \__starray_parser:NeTF #7 {##1} { \exp_args:Noo #1 \l__starray_parsed_term_st \l__starray_parsed_base_st} { #8 #3 } %%TODO... this should absorb N+2 and execute the last one... } % for the record % \__starray_parser isn't expandable % *would it be...* % % \cs_new:cpn {starray_ #5 _p : n#6 } ##1 % { % \__starray_parser:NeTF \c__starray_idx_ending_bool {##1} % { #2 \l__starray_parsed_term_st \l__starray_parsed_base_st} % { #7 #4 } % } } \cs_generate_variant:Nn \__starray_prg_generate_a:NNnnnnNnn {ccVV} %%%%%%%%% %%% #1 -> baseT %%% #2 -> baseF %%% #3 -> noneA %%% #4 -> noneB %%% #5 -> cmd radix %%% #6 -> base signature %%% #7 -> \c__starray_idx_ending_bool / \c__starray_no_idx_ending_bool %%% #7=>8 -> in case parser err %%% #8=>9 -> in case *parsed* err %%%%%%%%% \cs_new_protected:Npn \__starray_prg_generate_b:NNnnnnNnn #1#2#3#4#5#6#7#8#9 { \cs_new:cpn {starray_uparsed_ #5 : N#6 T} ##1 { \exp_last_unbraced:NV #1 ##1 } \cs_new:cpn {starray_uparsed_ #5 : N#6 F} ##1 { \exp_last_unbraced:NV #2 ##1 } \bool_if:NTF \l__starray_NNnames_bool { \bool_if:NTF \l__starray_NNnames_warn_bool { \cs_new:cpn {starray_parsed_ #5 : NN#6 T} ##1##2 { \msg_warning:nnnnn {starray} {strict / deprecate} {prg:03} { starray_parsed_ #5 : NN#6 T } { starray_uparsed_ #5 : N#6 T } \exp_last_unbraced:NV #1 ##1 } \cs_new:cpn {starray_parsed_ #5 : NN#6 F} ##1##2 { \msg_warning:nnnnn {starray} {strict / deprecate} {prg:04} { starray_parsed_ #5 : NN#6 F } { starray_uparsed_ #5 : N#6 F } \exp_last_unbraced:NV #2 ##1 } } { \cs_new:cpn {starray_parsed_ #5 : NN#6 T} ##1##2 { \exp_last_unbraced:NV #1 ##1 } \cs_new:cpn {starray_parsed_ #5 : NN#6 F} ##1##2 { \exp_last_unbraced:NV #2 ##1 } } } {} \bool_if:NTF \l__starray_parsed_check_bool { \cs_new:cpn {starray_parsed_ #5 : #6 T} { \bool_if:NTF \g__starray_parsed_bool { \exp_args:Noo #1 \g__starray_parsed_saved_term_st \g__starray_parsed_saved_base_st} { #9 #3 } %%TODO... this should absorb N+1 and execute none... } \cs_new:cpn {starray_parsed_ #5 : #6 F} { \bool_if:NTF \g__starray_parsed_bool { \exp_args:Noo #2 \g__starray_parsed_saved_term_st \g__starray_parsed_saved_base_st} { #9 #4 } %%TODO... this should absorb N+1 and execute the last one... } } { \cs_new:cpn {starray_parsed_ #5 : #6 F} { \exp_args:Noo #1 \g__starray_parsed_saved_term_st \g__starray_parsed_saved_base_st} \cs_new:cpn {starray_parsed_ #5 : #6 T} { \exp_args:Noo #2 \g__starray_parsed_saved_term_st \g__starray_parsed_saved_base_st} } \cs_new:cpn {starray_iparsed_ #5 : #6 F} { \exp_args:Noo #1 \g__starray_iterate_term_st \g__starray_iterate_base_st} \cs_new:cpn {starray_iparsed_ #5 : #6 T} { \exp_args:Noo #2 \g__starray_iterate_term_st \g__starray_iterate_base_st} \cs_new:cpn {starray_ #5 : n#6 T} ##1 { \__starray_parser:NeTF #7 {##1} { \exp_args:Noo #1 \l__starray_parsed_term_st \l__starray_parsed_base_st} { #8 #3 } %%TODO... this should absorb N+1 and execute none... } \cs_new:cpn {starray_ #5 : n#6 F} ##1 { \__starray_parser:NeTF #7 {##1} { \exp_args:Noo #2 \l__starray_parsed_term_st \l__starray_parsed_base_st} { #8 #4 } %%TODO... this should absorb N+1 and execute the last one... } } \cs_generate_variant:Nn \__starray_prg_generate_b:NNnnnnNnn {ccVV , ccee} %%%%%%%%% %%% %%% This will create a pair %%% *none* expandable %%% #cmd:signature# => cs, expecting the #1 as a starray-ref %%% #cmd:signature#TF => prg, expecting the #1 as a starray-ref %%% %%%%%%%%% %%% %%% Regarding the base-code: #1 will always be treated as the starray-ref. %%% \__starray_return_true: / \__starray_return_false: will be set as %%% as *nothing* for the cs command %%% \prg_return_true: / \prg_return_false: for the prg command %%% %%% 'if-parser-failed' code can use all parameters %%% %%%%%%%%% %%% #1 -> #cmd:signature# => base-name %%% #2 -> \c__starray_idx_ending_bool / \c__starray_no_idx_ending_bool %%% #3 -> base-code %%% #4 -> if-parser-failed %%%%%%%%% \regex_const:Nn \c__starray_csa_regex {\c{prg_return_true:}|\c{prg_return_false:}} \regex_const:Nn \c__starray_csb_regex {\c{__starray_rtn:}} \regex_const:Nn \c__starray_prg_regex {\c{__starray_msg_dispatch:}} \cs_new_protected:Npn \__starray_cs_prg_duo_generate:NNnn #1#2#3 { \tl_set:Nn \l__starray_duocmd_tmpb_tl {#3} \regex_replace_all:NnN \c__starray_prg_regex {\c{__starray_msg_clear:}} \l__starray_duocmd_tmpb_tl \tl_set:Nn \l__starray_duocmd_tmpa_tl {#3} \regex_replace_all:NnN \c__starray_csa_regex {} \l__starray_duocmd_tmpa_tl \regex_replace_all:NnNTF \c__starray_csb_regex {} \l__starray_duocmd_tmpa_tl {\tl_put_left:Nn \l__starray_duocmd_tmpb_tl \__starray_set_rtn_true:} {} \__starray_cs_prg_duo_generate_a:NNVVn #1#2\l__starray_duocmd_tmpa_tl \l__starray_duocmd_tmpb_tl } \cs_new_protected:Npn \__starray_cs_prg_duo_generate_a:NNnnn #1#2#3#4#5 { \prg_new_conditional:Nnn #1 {T , F , TF} { \__starray_parser:NeTF #2 {##1} { #4 } { \__starray_msg_clear: \prg_return_false: } % returns nothing by default } \cs_new:Nn #1 { \__starray_parser:NeTF #2 {##1} { #3 } { \__starray_msg_dispatch: #5 } } } \cs_generate_variant:Nn \__starray_cs_prg_duo_generate_a:NNnnn {NNVV} %%%%%%%%%%%%%%% %%%%%%%%%%%%%%% %%%% %%%% Package conditionals %%%% %%%% %%%%%%%%%%%%%%% %%%%%%%%%%%%%%% \prg_new_eq_conditional:NNn \__starray_if_exist:c \cs_if_exist:c {p, T, F, TF} \prg_new_conditional:Npnn \starray_if_exist:n #1 {p, T, F, TF} { \__starray_if_exist:cTF { c__starray_prfix_. #1 _base_ref_st} \prg_return_true: \prg_return_false: } % % Note to self: One way would be to test the scan mark \s__end ... but cumbersome. % % DEPRECATED, unless some other (simple) test becomes available %\prg_new_conditional:Npnn \__starray_if_valid:n #1 {p, T, F, TF} % { % \bool_lazy_and:nnTF {\prop_if_exist_p:c {#1}} {\prop_item:cn {#1} {is_starray}} % { \prg_return_true: } % { \prg_return_false: } % } \prg_new_eq_conditional:NNn \__starray_if_valid:n \cs_if_exist:c {p, T, F, TF} \prg_generate_conditional_variant:Nnn \__starray_if_valid:n {e} {p, T, F, TF} \prg_new_conditional:Npnn \starray_if_valid:n #1 {p, T, F, TF} { \__starray_if_valid:nTF { c__starray_prfix_. #1 _ref_st} \prg_return_true: \prg_return_false: } \tl_const:Nn \c__starray_empty_hash_term_st { \relax \relax \s__end } %%% %%% This will generate two main commands %%% \#cmd# : N #sig# => idea beign the 1st parameter will be a _st variable %%% \#cmd# : c #sig# %%% \#cmd# : w #sig# => the _st variable is already o-expanded %%% Carefull when calling this, the 3rd parameter has to convay a parameter list (add a space after each # ) %%%%%%%%% %%% #1 -> #cmd# => base-name %%% #2 -> #signature# %%% #3 -> parameter description (the 'p') %%% #4 -> code % if expandable, the resulting commands will also be %%%%%%%%% \cs_new_protected:Npn \__starray_cs_wgen:nnnn #1#2#3#4 { \cs_new:cpe {#1:N#2} ##1 { \exp_not:N \exp_last_unbraced:No \exp_not:c {#1:w#2} ##1 } \cs_generate_variant:cn {#1:N#2} {c} \exp_last_unbraced:Nno \cs_new:cpn {#1:w#2} #3 { #4 } } %%% %%% This will generate two main conditional commands %%% \#cmd# : N #sig#TF => (and c variant) idea beign the 1st parameter will be a _st variable %%% \#cmd# : w #sig#TF => the _st variable is already o-expanded %%% Carefull when calling this, the 3rd parameter has to convay a parameter list (add a space after each # ) %%%%%%%%% %%% #1 -> #cmd# => base-name %%% #2 -> #signature# %%% #3 -> parameter description (the 'p') %%% #4 -> code % if expandable, the resulting commands will also be %%%%%%%%% \cs_new_protected:Npn \__starray_prg_wgen:nnnn #1#2#3#4 { \cs_new:cpe {#1:N#2TF} ##1 { \exp_not:N \exp_last_unbraced:No \exp_not:c {#1:w#2TF} ##1 } \cs_generate_variant:cn {#1:N#2TF} {c} \exp_last_unbraced:Nno \prg_new_conditional:cpnn {#1:w#2} #3 {TF} { #4 } } %%%%%%%%%%%%%%% %%%%%%%%%%%%%%% %%%% %%%% starray \...._new declarations %%%% %%%% Note: the \s__end allows to fast skip to the last itens, if not needed. %%%% %%%%%%%%%%%%%%% \cs_new_protected:Npn \__starray_base_new:nn #1#2 { \int_new:c { g__starray_prfix_. #2 _base_cnt_int } \int_new:c { g__starray_prfix_. #2 _base_iter_int } \prop_gclear_new_linked:c { g__starray_prfix_. #2 _base_ihash_prop} %% will have {key/hash} => {\term_prop}{infix-letter}{i}{infix}{stkeys_seq} \tl_const:ce { c__starray_prfix_. #2 _base_st } { \exp_not:c { g__starray_prfix_. #2 _base_ihash_prop} \exp_not:c { g__starray_prfix_. #2 _base_iter_int } \exp_not:c { g__starray_prfix_. #2 _base_cnt_int } \exp_not:c { g__starray_prfix_. #1 _defkeys_prop} \exp_not:c { g__starray_prfix_. #1 _defstkeys_seq} {#1}{#2} \exp_not:N \s__end } } \cs_generate_variant:Nn \__starray_base_new:nn { e } \cs_new_protected:Npn \__starray_sub_base_new:nnn #1#2#3 { \__starray_base_new:nn {#1.#3}{#2.#3} } \cs_new_protected:Npn \__starray_new:n #1 { \prop_new_linked:c { g__starray_prfix_. #1 _defkeys_prop } \seq_new:c { g__starray_prfix_. #1 _defstkeys_seq } \tl_const:ce { c__starray_prfix_. #1 _ref_st } { \exp_not:c { g__starray_prfix_. #1 _defkeys_prop } \exp_not:c { g__starray_prfix_. #1 _defstkeys_seq } {#1} \exp_not:N \s__end } } %%%%%%%%%%%%%%% %%%% %%%% \starray_new %%%% %%%%%%%%%%%%%%% \cs_new_protected:Npn \starray_new:n #1 { \__starray_if_exist:cTF { c__starray_prfix_. #1 _ref_st} { \msg_warning:nnnn {starray} {strict / (re)define} {new:1} {#1} } { \__starray_new:n { #1 } \__starray_base_new:nn {#1}{#1} % TODO: might be incomplete !!! } } \prg_new_protected_conditional:Npnn \starray_new:n #1 {T, F, TF} { \__starray_if_exist:cTF { c__starray_prfix_. #1 _ref_st} { \prg_return_false: } { \__starray_new:n { #1 } \__starray_base_new:nn {#1}{#1} % TODO: might be incomplete !!! \prg_return_true: } } %%%%%%%%%%%%%%% %%%%%%%%%%%%%%% %%%% %%%% starray ref parser %%%% %%%% %%%%%%%%%%%%%%% %%%%%%%%%%%%%%% %%%%%%%%%%%%%%% %%%%%%%%%%%%%%% %%%% %%%% get root reference (first term) assuming called as %%%% . \q_stop %%%% so that even if {ref} (has no dot, no idx) it will return 'the root ref' %%%% e.g.: \tl_set:Ne \l__tmpb_tl {\__starray_get_root:nw \l__starray_tmpa_tl . \q_stop} %%%% %%%% It will return the 'root ref' assuming that the ref is of form root.name.name (no [idx]) %%%% %%%%%%%%%%%%%%% %%%%%%%%%%%%%%% %%% %%% This one can't be protected... it is used in {e} expantion %%% if protected, it results in a quark loop %%% \cs_new:Npn \__starray_get_root:nw #1 . #2 \q_stop { #1 } \cs_generate_variant:Nn \__starray_get_root:nw {V} %%%%%%%%%%%%%%% %%%%%%%%%%%%%%% %%%% %%%% set root reference (first term) assuming called as %%%% . \q_stop %%%% so that even if {ref} (has no dot, no idx) it will return 'the root ref' %%%% e.g.: \__starray_set_root:Nnw \l__tmpb_tl \l__starray_tmpa_tl . \q_stop %%%% %%%% It will return the 'root ref' assuming that the ref is of form root.name.name (no [idx]) %%%% %%%%%%%%%%%%%%% %%%%%%%%%%%%%%% \cs_new_protected:Npn \__starray_set_root:Nnw #1 #2 . #3 \q_stop { \tl_set:Nn #1 {#2} } \cs_generate_variant:Nn \__starray_set_root:Nnw {Ne} %%%%%%%%%%%%%%% %%%%%%%%%%%%%%% %%%% %%%% adding property #3 (#4 being it's initial/default value) %%%% #1 prefix %%%% #2 starray %%%% %%%%%%%%%%%%%%% %%%%%%%%%%%%%%% %%% \c__starray...._ref_st %%% \c{ -ref- _defkeys_prop } %% #1 %%% \c{ -ref- _defstkeys_seq } %% #2 %%% {-ref-} %% #3 %%% \s__end %%%%%% %%% \__starray_refst_def_prop:Nnn %%% \__starray_refst_def_prop:cnn %%% \__starray_refst_def_prop:wnn %%%%%% \__starray_cs_wgen:nnnn {__starray_refst_def_prop}{nn}{ # 1 # 2 \s__end } { \prop_gput:Nnn #1 } %%%%%%%%%%%%%%% %%%% %%%% \starray_def_prop %%%% %%%%%%%%%%%%%%% \cs_new_protected:Npn \starray_def_prop:nnn #1#2#3 { \__starray_if_exist:cTF { c__starray_prfix_. #1 _ref_st} { \__starray_refst_def_prop:cnn { c__starray_prfix_. #1 _ref_st} {#2} {#3} } { \msg_warning:nnxxx {starray}{reference / invalid-starray} {addprop:1} {#1} {cannot~add~property:#2} } } \prg_new_protected_conditional:Npnn \starray_def_prop:nnn #1#2#3 {T, F, TF} { \__starray_if_exist:cTF { c__starray_prfix_. #1 _ref_st} { \__starray_refst_def_prop:cnn { c__starray_prfix_. #1 _ref_st} {#2} {#3} \prg_return_true: } \prg_return_false: } %%%%%%%%%%%%%%% %%%%%%%%%%%%%%% %%%% %%%% adding struct array #2 to a starray %%%% %%%% %%%%%%%%%%%%%%% %%%%%%%%%%%%%%% %%% \c__starray...._ref_st %%% \c{ -ref- _defkeys_prop } %% #1 %%% \c{ -ref- _defstkeys_seq } %% #2 %%% {-ref-} %% #3 %%% \s__end %%%%%% %%% \__starray_refst_def_struct:Nn %%% \__starray_refst_def_struct:cn %%% \__starray_refst_def_struct:wn %%%%%% \__starray_cs_wgen:nnnn {__starray_refst_def_struct}{n}{ # 1 # 2 # 3 \s__end # 4 } { \seq_if_in:NnF #2 {#4} { \seq_gput_right:Nn #2 {#4} \__starray_new:n { #3 . #4 } } } %%%%%% %%% \__starray_refst_keyval_def_struct:NnN %%% \__starray_refst_keyval_def_struct:cnN %%% \__starray_refst_keyval_def_struct:wnN %%%%%% \__starray_cs_wgen:nnnn {__starray_refst_keyval_def_struct}{nN}{ # 1 # 2 # 3 \s__end # 4 # 5} { \tl_set:Nn #5 {#3} \seq_if_in:NnF #2 {#4} { \seq_gput_right:Nn #2 {#4} \__starray_new:n { #3 . #4 } } } \cs_generate_variant:Nn \__starray_refst_keyval_def_struct:NnN {Ne} %%%%%%%%%%%%%%% %%%%%%%%%%%%%%% %%%% %%%% fixing struct _base for already instantiated terms %%%% %%%% %%%%%%%%%%%%%%% %%%%%%%%%%%%%%% %%% \c__starray_..._term_st %%% \c{ -infix- _term_prop } %% #1 %%% { -infix- } %% #2 %%% { -val- } %% iter's val for this entry %% #3 %%% { -idx- } %% #4 %%% \c{ -ref- _defstkeys_prop} %% #5 %%% \s__end %%%%%% %%% \__starray_termst_fix_terms:Nnn %%% \__starray_termst_fix_terms:cnn %%% \__starray_termst_fix_terms:wnn %%%%%% \__starray_cs_wgen:nnnn {__starray_termst_fix_terms}{nn}{ # 1 # 2 # 3 \s__end # 4 # 5} { \__starray_if_exist:cTF { c__starray_prfix_. #2 . #5 _base_st} { \__starray_basest_fix_terms:c { c__starray_prfix_. #2 . #5 _base_st} } { \__starray_base_new:nn { #4 . #5 } { #2 . #5 } } } %%% \c__starray_..._base_st %%% \c{ -infix- _ihash_prop} %% #1 %%% \c{ -infix- _base_iter_int } %% #2 %%% \c{ -infix- _base_cnt_int } %% #3 %%% \c{ -ref- _defkeys_prop} %% #4 %%% \c{ -ref- _defstkeys_prop} %% #5 %%% {-ref-}{-infix-} %% #6#7 %%% \s__end %%%%%% %%% \__starray_basest_fix_terms:N %%% \__starray_basest_fix_terms:c %%% \__starray_basest_fix_terms:w %%%%%% \__starray_cs_wgen:nnnn {__starray_basest_fix_terms}{}{ # 1 # 2 # 3 # 4 # 5 # 6 # 7 \s__end } { \prop_if_empty:NF #1 { \prop_map_inline:Nn #1 { %%% ##1 will be idx/hash ##2 will be _term_st \seq_map_inline:Nn #5 { \__starray_termst_fix_terms:wnn ##2 {#6}{####1} } } } } \cs_new_protected:Npn \starray_fix_terms:n #1 { \tl_set:Nn \l__starray_tmpb_tl {#1} \__starray_set_root:New \l__starray_tmpb_tl \l__starray_tmpb_tl . \q_stop \__starray_if_exist:cTF { c__starray_prfix_. \l__starray_tmpb_tl _ref_st} { \__starray_basest_fix_terms:c { c__starray_prfix_. \l__starray_tmpb_tl _base_st} } { \msg_warning:nnxxx {starray}{reference / invalid-starray} {fixterms:1} {#1} {} } } %%%%%%%%%%%%%%% %%%% %%%% \starray_def_struct %%%% %%%%%%%%%%%%%%% \cs_new_protected:Npn \starray_def_struct:nn #1#2 { \__starray_if_exist:cTF { c__starray_prfix_. #1 _ref_st} { \__starray_refst_def_struct:cn { c__starray_prfix_. #1 _ref_st} {#2} } { \msg_warning:nnxxx {starray}{reference / invalid-starray} {addstruct:1} {#1} {cannot~add~structure:#2} } } \prg_new_protected_conditional:Npnn \starray_def_struct:nn #1#2 {T, F, TF} { \__starray_if_exist:cTF { c__starray_prfix_. #1 _ref_st} { \__starray_refst_def_struct:cn { c__starray_prfix_. #1 _ref_st} {#2} \prg_return_true: } { \prg_return_false: } } %%%%%%%%%%%%%%% %%%%%%%%%%%%%%% %%%% %%%% adding prop/struct from keyval %%%% %%%% %%%%%%%%%%%%%%% %%%%%%%%%%%%%%% %\prg_new_conditional:Npnn \__starray_def_from_keyval_testdot_aux:w #1 . \q_nil { TF} % { % \str_compare:nNnTF {#1} = {struct} % { \prg_return_true: } % { \prg_return_false: } % } %%% This expects 3 parameters the last two are being used by \str_compare: \cs_new:Npn \__starray_def_from_keyval_testdot_aux:wTF #1 . \q_nil { \str_compare:nNnTF {#1} = {struct} } % % This can't be protected (\tl_set:Ne isn't expandable) but only the TF form matters. % \prg_new_conditional:Npnn \__starray_def_from_keyval_testdot:w #1 . #2 \q_stop { TF} { \quark_if_nil:nTF {#2} { \prg_return_false: } % no dot, OK { \__starray_def_from_keyval_testdot_aux:wTF #2 { \tl_set:Nn \l__starray_keyval_tmpb_tl { #1 } \prg_return_true: } % dot struct, OK { \prg_return_false: } %% possible syntax ERR (dot, but not struct!) } } \cs_new_protected:Npn \__starray_def_from_keyval_parse:Nnn #1#2#3 { \__starray_def_from_keyval_testdot:wTF #2 . \q_nil \q_stop { \__starray_refst_keyval_def_struct:NeN #1 \l__starray_keyval_tmpb_tl \l__starray_keyval_tmpa_tl \keyval_parse:een { \exp_not:N \__starray_def_from_keyval_parse:Nn \exp_not:c { c__starray_prfix_. \l__starray_keyval_tmpa_tl . \l__starray_keyval_tmpb_tl _ref_st } } { \exp_not:N \__starray_def_from_keyval_parse:Nnn \exp_not:c { c__starray_prfix_. \l__starray_keyval_tmpa_tl . \l__starray_keyval_tmpb_tl _ref_st } } {#3} } { % #1 should be ..._ref_st \__starray_refst_def_prop:Nnn #1 {#2}{#3} } } \cs_new_protected:Npn \__starray_def_from_keyval_parse:Nn #1#2 { % #1 should be _ref_st \__starray_refst_def_prop:Nnn #1 {#2}{} } %%%%%%%%%%%%%%% %%%% %%%% \starray_def_from_keyval %%%% %%%%%%%%%%%%%%% \cs_new_protected:Npn \starray_def_from_keyval:nn #1#2 { \__starray_if_exist:cTF { c__starray_prfix_. #1 _ref_st} { \keyval_parse:een { \exp_not:N \__starray_def_from_keyval_parse:Nn \exp_not:c { c__starray_prfix_. #1 _ref_st } } { \exp_not:N \__starray_def_from_keyval_parse:Nnn \exp_not:c { c__starray_prfix_. #1 _ref_st } } { #2 } } { \msg_warning:nnxxx {starray}{reference / invalid-starray} {addkeyval:1} {#1} {cannot~add:#2} } } \prg_new_protected_conditional:Npnn \starray_def_from_keyval:nn #1#2 {T, F, TF} { \__starray_if_exist:cTF { c__starray_prfix_. #1 _ref_st } { \keyval_parse:een { \exp_not:N \__starray_def_from_keyval_parse:Nn \exp_not:c { c__starray_prfix_. #1 _ref_st } } { \exp_not:N \__starray_def_from_keyval_parse:Nnn \exp_not:c { c__starray_prfix_. #1 _ref_st } } { #2 } \prg_return_true: } { \prg_return_false: } } %%%%%%%%%%%%%%% %%%%%%%%%%%%%%% %%%% %%%% adding terms %%%% %%%% %%%%%%%%%%%%%%% %%%%%%%%%%%%%%% %%% \c__starray_..._base_st %%% \c{ -infix- _ihash_prop} %% #1 %%% \c{ -infix- _base_iter_int } %% #2 %%% \c{ -infix- _base_cnt_int } %% #3 %%% \c{ -ref- _defkeys_prop} %% #4 %%% \c{ -ref- _defstkeys_prop} %% #5 %%% {-ref-}{-infix-} %% #6#7 %%% \s__end %%%%%% %%% \__starray_basest_new_term:Nn %%% \__starray_basest_new_term:cn %%% \__starray_basest_new_term:wn %%%%%% \__starray_cs_wgen:nnnn {__starray_basest_new_term}{n}{ # 1 # 2 # 3 # 4 # 5 # 6 # 7\s__end # 8 } { \int_gincr:N #3 \int_gset_eq:NN #2 #3 \tl_set:Ne \l__starray_tmpa_tl { \int_to_Alph:n #3 } \prop_gput:Nee #1 { \int_use:N #3 } { \exp_not:c { g__starray_prfix_. #7 _ \l__starray_tmpa_tl _term_prop } { #7 _ \l__starray_tmpa_tl } { \int_use:N #3 } { \l__starray_tmpa_tl } \exp_not:N #5 \exp_not:N \s__end } \tl_if_blank:nF {#8} { \prop_gput:Nee #1 { #8 } { \exp_not:c { g__starray_prfix_. #7 _ \l__starray_tmpa_tl _term_prop } { #7 _ \l__starray_tmpa_tl } { \int_use:N #3 } { \l__starray_tmpa_tl } \exp_not:N #5 \exp_not:N \s__end } } \prop_new_linked:c { g__starray_prfix_. #7 _ \l__starray_tmpa_tl _term_prop } \prop_gset_eq:cN { g__starray_prfix_. #7 _ \l__starray_tmpa_tl _term_prop } #4 % map over 'all sub-starrays parts of def_ref -> st_seq (those starting with a dot, @st_seq) \cs_set:Npe \__starray_sub_aux:n { \exp_not:N \__starray_sub_base_new:nnn { #6 }{ #7 _ \l__starray_tmpa_tl } } \seq_map_inline:Nn #5 { \__starray_sub_aux:n {##1} } } %%%%%%%%%%%%%%% %%%% %%%% \starray_new_term %%%% %%%%%%%%%%%%%%% \cs_new_protected:Npn \starray_new_term:nn #1#2 { \__starray_parser:NeTF \c__starray_no_idx_ending_bool {#1} { \__starray_basest_new_term:Nn \l__starray_parsed_base_st {#2} } { \__starray_msg_dispatch: \msg_warning:nnnn {starray}{syntax / term}{addterm:2}{#1} } } \prg_new_protected_conditional:Npnn \starray_new_term:nn #1#2 {T, F, TF} { \__starray_parser:NeTF \c__starray_no_idx_ending_bool {#1} { \__starray_basest_new_term:Nn \l__starray_parsed_base_st {#2} \prg_return_true: } { \prg_return_false: } } %%% \c__starray_..._term_st %%% \c{ -infix- _term_prop } %% #1 %%% { -infix- } %% #2 %%% { -val- } %% iter's val for this entry %% #3 %%% { -idx- } %% #4 %%% \c{ -ref- _defstkeys_prop} %% #5 %%% \s__end %%%%%% %%% \__starray_termst_get_infix:NN %%% \__starray_termst_get_infix:cN %%% \__starray_termst_get_infix:wN %%%%%% \__starray_cs_wgen:nnnn {__starray_termst_get_infix}{N}{ # 1 # 2 # 3 \s__end # 4 } { \tl_set:Nn #4 {#2} } %%%%%%%% %%%%% \__starray_termst_get_iterx:NNN %%%%% \__starray_termst_get_iterx:cNN %%%%% \__starray_termst_get_iterx:wNN %%%%%%%% %%\__starray_cs_wgen:nnnn %% {__starray_termst_get_iterx}{NN}{ # 1 # 2 # 3 # 4 \s__end # 5 # 6 } %% { %% \tl_set:Nn #5 {#3} %% \tl_set:Nn #6 {#2} %% } %%%%%% %%% \__starray_termst_get_iterval:NN %%% \__starray_termst_get_iterval:cN %%% \__starray_termst_get_iterval:wN %%%%%% \__starray_cs_wgen:nnnn {__starray_termst_get_iterval}{N}{ # 1 # 2 # 3 # 4 \s__end # 5 } { \tl_set:Nn #5 {#3} } \cs_new:Npn \__starray_cascade_aux:nN #1#2 { \seq_map_inline:Nn #2 { \__starray_basest_set_iter:cnTF { c__starray_prfix_. #1 . ##1 _base_st } {1} {} {} } } \cs_generate_variant:Nn \__starray_cascade_aux:nN {o} \bool_if:NTF \l__starray_cascade_bool { \cs_new:Npn \__starray_iter_cascade:NNN #1#2#3 { \prop_get:NeN #1 {\int_use:N #2} \l__starray_tmp_term_st \__starray_termst_get_infix:NN \l__starray_tmp_term_st \l__starray_tmp_infix_tl \__starray_cascade_aux:oN \l__starray_tmp_infix_tl #3 } } { \cs_new:Npn \__starray_iter_cascade:NNN #1#2#3 { } } %%% \c__starray_..._base_st %%% \c{ -infix- _ihash_prop} %% #1 %%% \c{ -infix- _base_iter_int } %% #2 %%% \c{ -infix- _base_cnt_int } %% #3 %%% \c{ -ref- _defkeys_prop} %% #4 %%% \c{ -ref- _defstkeys_prop} %% #5 %%% {-ref-}{-infix-} %% #6#7 %%% \s__end %%%%%% %%% \__starray_basest_set_iter:NnTF %%% \__starray_basest_set_iter:cnTF %%% \__starray_basest_set_iter:wnTF %%%%%% \__starray_prg_wgen:nnnn {__starray_basest_set_iter}{n}{ # 1 # 2 # 3 # 4 # 5 # 6 \s__end # 7 } { \int_compare:nNnTF {#7} > {#3} { \int_gset_eq:NN #2 #3 \int_compare:nNnTF #2 = \c_zero_int { } { \__starray_iter_cascade:NNN #1 #2 #5 } \prg_return_false: } { \int_gset:Nn #2 {#7} \__starray_iter_cascade:NNN #1 #2 #5 \prg_return_true: } } %%%%%% %%% \__starray_basest_incr_iter:NTF %%% \__starray_basest_incr_iter:cTF %%% \__starray_basest_incr_iter:wTF %%%%%% \__starray_prg_wgen:nnnn {__starray_basest_incr_iter}{}{ # 1 # 2 # 3 # 4 # 5 # 6 \s__end } { \int_compare:nNnTF {#2} = {#3} { \prg_return_false: } { \int_gincr:N #2 \__starray_iter_cascade:NNN #1 #2 #5 \prg_return_true: } } %%%%%% %%% \__starray_basest_set_iter_from_hash:NnTF %%% \__starray_basest_set_iter_from_hash:cnTF %%% \__starray_basest_set_iter_from_hash:wnTF %%%%%% \__starray_prg_wgen:nnnn {__starray_basest_set_iter_from_hash}{n}{ # 1 # 2 # 3 # 4 # 5 # 6 # 7 \s__end # 8 } { \prop_get:NeNTF #1 {#8} \l__starray_tmp_term_st { \__starray_termst_get_iterval:NN \l__starray_tmp_term_st \l__starray_tmpb_tl \int_gset:Nn #2 \l__starray_tmpb_tl \__starray_iter_cascade:NNN #1 #2 #5 \prg_return_true: } { \prg_return_false: } } \prg_generate_conditional_variant:Nnn \__starray_basest_set_iter_from_hash:Nn {Ne} {TF} %%%%%%%%%%%%%%% %%%% %%%% \starray_set_iter %%%% %%%%%%%%%%%%%%% %%%%%%%%%%%%%%% %%% \starray_set_iter_from_hash:nn %%% \starray_set_iter_from_hash:nnTF %%%%%%%%%%%%%%% \__starray_cs_prg_duo_generate:NNnn \starray_set_iter_from_hash:nn \c__starray_no_idx_ending_bool { \__starray_basest_set_iter_from_hash:NeTF \l__starray_parsed_base_st {#2} {} { \__starray_msg:nnnnn {reference / iter} {iterhash:1} {#1}{#2}{-here-} \__starray_msg_dispatch: \__starray_set_rtn_false: } \__starray_rtn: } { \msg_warning:nnnn {starray} {syntax / iter} {iter:1} {#1} } %%%%%%%%%%%%%%% %%% \starray_set_iter:nn %%% \starray_set_iter:nnTF %%%%%%%%%%%%%%% \__starray_cs_prg_duo_generate:NNnn \starray_set_iter:nn \c__starray_no_idx_ending_bool { \int_compare:nNnTF {#2} < {1} { \__starray_basest_set_iter:NnTF \l__starray_parsed_base_st {1} {}{} \prg_return_false: } { \__starray_basest_set_iter:NnTF \l__starray_parsed_base_st {#2} {} { \__starray_set_rtn_false: } \__starray_rtn: } } { \__starray_msg_dispatch: \msg_warning:nnnn {starray} {syntax / iter} {iter:1} {#1} } %%%%%%%%%%%%%%% %%% \starray_reset_iter:n %%% \starray_reset_iter:nTF %%%%%%%%%%%%%%% \__starray_cs_prg_duo_generate:NNnn \starray_reset_iter:n \c__starray_no_idx_ending_bool { \__starray_basest_set_iter:NnTF \l__starray_parsed_base_st {1} {} { \__starray_set_rtn_false: } \__starray_rtn: } { \msg_warning:nnnn {starray} {syntax / iter} {iter:4} {#1} } %%%%%%%%%%%%%%% %%% \starray_next_iter:n %%% \starray_next_iter:nTF %%%%%%%%%%%%%%% \__starray_cs_prg_duo_generate:NNnn \starray_next_iter:n \c__starray_no_idx_ending_bool { \__starray_basest_incr_iter:NTF \l__starray_parsed_base_st {} { \__starray_set_rtn_false: } \__starray_rtn: } { \msg_warning:nnnn {starray} {syntax / iter} {iter:5} {#1} } %%% \c__starray_..._base_st %%% \c{ -infix- _ihash_prop} %% #1 %%% \c{ -infix- _base_iter_int } %% #2 %%% \c{ -infix- _base_cnt_int } %% #3 %%% \c{ -ref- _defkeys_prop} %% #4 %%% \c{ -ref- _defstkeys_prop} %% #5 %%% {-ref-}{-infix-} %% #6#7 %%% \s__end %%%%%% %%% \__starray_basest_get_term:NN %%% \__starray_basest_get_term:cN %%% \__starray_basest_get_term:wN %%%%%% \__starray_cs_wgen:nnnn {__starray_basest_get_term}{N}{ # 1 # 2 # 3 \s__end # 4 } { \prop_get:NeN #1 {\int_use:N #2} \l__starray_tmp_term_st \tl_gset_eq:NN #4 \l__starray_tmp_term_st } \int_new:N \g__starray_istack_int \bool_new:N \g__starray_iterate_bool \tl_new:N \g__starray_iterate_base_st \tl_new:N \g__starray_iterate_term_st \cs_new_protected:Npn \__starray_istack_push: { \int_gincr:N \g__starray_istack_int \tl_gset_eq:cN { g__starray_istack_ \int_to_Alph:n \g__starray_istack_int _base_st} \g__starray_iterate_base_st \tl_gset_eq:cN { g__starray_istack_ \int_to_Alph:n \g__starray_istack_int _term_st} \g__starray_iterate_term_st \bool_gset_eq:cN { g__starray_istack_ \int_to_Alph:n \g__starray_istack_int _bool} \g__starray_iterate_bool } \cs_new_protected:Npn \__starray_istack_pop: { \tl_gset_eq:Nc \g__starray_iterate_base_st { g__starray_istack_ \int_to_Alph:n \g__starray_istack_int _base_st} \tl_gset_eq:Nc \g__starray_iterate_term_st { g__starray_istack_ \int_to_Alph:n \g__starray_istack_int _term_st} \bool_gset_eq:Nc \g__starray_iterate_bool { g__starray_istack_ \int_to_Alph:n \g__starray_istack_int _bool} \int_gdecr:N \g__starray_istack_int } %%%%%%%%%%%%%%% %%% %%% \starray_iterate_over:nn %%% \starray_iterate_over:nnTF %%% %%%%%%%%%%%%%%% \__starray_cs_prg_duo_generate:NNnn \starray_iterate_over:nn \c__starray_no_idx_ending_bool { \__starray_istack_push: \tl_gset_eq:NN \g__starray_iterate_base_st \l__starray_parsed_base_st \bool_gset_true:N \g__starray_iterate_bool \__starray_basest_set_iter:NnTF \g__starray_iterate_base_st {1} { \__starray_basest_get_term:NN \g__starray_iterate_base_st \g__starray_iterate_term_st \bool_do_while:Nn \g__starray_iterate_bool { #2 \__starray_basest_incr_iter:NTF \g__starray_iterate_base_st { \__starray_basest_get_term:NN \g__starray_iterate_base_st \g__starray_iterate_term_st } { \bool_gset_false:N \g__starray_iterate_bool } } \__starray_msg_clear: %% to clear the "iter_incr" warning/error \__starray_set_rtn_true: } { \__starray_msg:nnnn {syntax / iter} {iter:6a} {#1} {} \__starray_msg_dispatch: \__starray_set_rtn_false: } \__starray_istack_pop: \__starray_rtn: } { \msg_warning:nnnn {starray} {syntax / iter} {iter:6} {#1} } %%%%%%%%%%%%%%% %%%%%%%%%%%%%%% %%%% %%%% set/get properties %%%% %%%% %%%%%%%%%%%%%%% %%%%%%%%%%%%%%% %%% \c__starray_..._term_st %%% \c{ -infix- _term_prop } %% #1 %%% { -infix- } %% #2 %%% { -val- } %% iter's val for this entry %% #3 %%% { -idx- } %% #4 %%% \c{ -ref- _defstkeys_prop} %% #5 %%% \s__end %%%%%% %%% \__starray_termst_get_prop:Nn %%% \__starray_termst_get_prop:cn %%% \__starray_termst_get_prop:wn %%%%%% \__starray_cs_wgen:nnnn {__starray_termst_get_prop}{n}{ # 1 # 2 \s__end # 3 } { \prop_item:Nn #1 {#3} } %%%%%%%%%%%%%%% %%% \starray_get_prop:nn %%% \starray_parsed_get_prop:Nn %%% \starray_parsed_get_prop:n => checked/nocheck %%%%%%%%%%%%%%% \__starray_cs_generate:nnNnnn {get_prop}{n} \c__starray_idx_ending_bool { \__starray_termst_get_prop:wn #1 {#3} } { \__starray_msg_dispatch: \msg_warning:nnnn {starray} {syntax / prop} {get:1} {#1} } % returns nothing by default { \msg_warning:nnnn {starray} {syntax / parsed} {parsed:1} {\starray_parsed_get_prop:n} } %%% \c__starray_..._term_st %%% \c{ -infix- _term_prop } %% #1 %%% { -infix- } %% #2 %%% { -val- } %% iter's val for this entry %% #3 %%% { -idx- } %% #4 %%% \c{ -ref- _defstkeys_prop} %% #5 %%% \s__end %%%%%% %%% \__starray_termst_get_prop:NnN %%% \__starray_termst_get_prop:cnN %%% \__starray_termst_get_prop:wnN %%%%%% \__starray_cs_wgen:nnnn {__starray_termst_get_prop}{nN}{ # 1 # 2 \s__end # 3 # 4 } { \prop_get:NnNF #1 {#3} #4 { \tl_clear:N #4 } } %%%%%% %%% \__starray_termst_get_propTF:NnN %%% \__starray_termst_get_propTF:cnN %%% \__starray_termst_get_propTF:wnN %%%%%% \__starray_cs_wgen:nnnn {__starray_termst_get_propTF}{nN}{ # 1 # 2 \s__end # 3 # 4 } { \prop_get:NnNTF #1 {#3} #4 { \prg_return_true: } { \tl_clear:N #4 \prg_return_false: } } %%%%%%%%%%%%%%% %%% \starray_get_prop:nnN %%% \starray_parsed_get_prop:NNnN %%% \starray_parsed_get_prop:nN => checked/nocheck %%%%%%%%%%%%%%% \__starray_cs_generate:nnNnnn {get_prop}{nN} \c__starray_idx_ending_bool { \__starray_termst_get_prop:wnN #1 {#3} #4 } { \__starray_msg_dispatch: \msg_warning:nnnn {starray} {syntax / prop} {get:2} {#1} } % returns nothing by default { \msg_warning:nnnn {starray} {syntax / parsed} {parsed:2} {\starray_parsed_get_prop:nN} } %%%%%%%%%%%%%%% %%% %%% \starray_get_prop:nnN %%% \starray_parsed_get_prop:NNnN %%% \starray_parsed_get_prop:nN => checked/nocheck %%% %%%%%%%%%%%%%%% \__starray_prg_generate:nnNnnn {get_prop}{nN} \c__starray_idx_ending_bool { \__starray_termst_get_propTF:wnN #1 {#3} #4 } { \__starray_msg_clear: } %% This will be F case of \__starray_parser:NeTF, not expandable anyway { } %% This will be F case of \bool_if:NTF \__starray_prg_undef_p:nn {get_prop}{nN} %%% \c__starray_..._term_st %%% \c{ -infix- _term_prop } %% #1 %%% { -infix- } %% #2 %%% { -val- } %% iter's val for this entry %% #3 %%% { -idx- } %% #4 %%% \c{ -ref- _defstkeys_prop} %% #5 %%% \s__end %%%%%% %%% \__starray_termst_if_inTF:Nn %%% \__starray_termst_if_inTF:cn %%% \__starray_termst_if_inTF:wn %%%%%% \__starray_cs_wgen:nnnn {__starray_termst_if_inTF}{n}{ # 1 # 2 \s__end # 3 } { \prop_if_in:NnTF #1 {#3} \prg_return_true: \prg_return_false: } %%%%%%%%%%%%%%% %%% \starray_if_in:nnTF %%% \starray_parsed_if_in:NNnTF %%% \starray_parsed_if_in:nNTF => checked/nocheck %%%%%%%%%%%%%%% \__starray_prg_generate:nnNnnn {if_in}{n} \c__starray_idx_ending_bool { \__starray_termst_if_inTF:wn #1 {#3} } { \__starray_msg_clear: } %% This will be F case of \__starray_parser:NeTF, not expandable anyway { } %% This will be F case of \bool_if:NTF %%% \c__starray_..._base_st %%% \c{ -infix- _ihash_prop} %% #1 %%% \c{ -infix- _base_iter_int } %% #2 %%% \c{ -infix- _base_cnt_int } %% #3 %%% \c{ -ref- _defkeys_prop} %% #4 %%% \c{ -ref- _defstkeys_prop} %% #5 %%% {-ref-}{-infix-} %% #6#7 %%% \s__end %%%%%% %%% \__starray_basest_get_cnt:N %%% \__starray_basest_get_cnt:c %%% \__starray_basest_get_cnt:w %%%%%% \__starray_cs_wgen:nnnn {__starray_basest_get_cnt}{}{ # 1 # 2 # 3 # 4 \s__end } { \int_use:N #3 } %%%%%% %%% \__starray_basest_get_cnt:NN %%% \__starray_basest_get_cnt:cN %%% \__starray_basest_get_cnt:wN %%%%%% \__starray_cs_wgen:nnnn {__starray_basest_get_cnt}{N}{ # 1 # 2 # 3 # 4 \s__end # 5 } { \int_set_eq:NN #5 #3 } %%%%%% %%% \__starray_basest_get_iter:N %%% \__starray_basest_get_iter:c %%% \__starray_basest_get_iter:w %%%%%% \__starray_cs_wgen:nnnn {__starray_basest_get_iter}{}{ # 1 # 2 # 3 \s__end } { \int_use:N #2 } %%%%%% %%% \__starray_basest_get_iter:NN %%% \__starray_basest_get_iter:cN %%% \__starray_basest_get_iter:wN %%%%%% \__starray_cs_wgen:nnnn {__starray_basest_get_iter}{N}{ # 1 # 2 # 3 \s__end # 4 } { \int_set_eq:NN #4 #2 } %%%%%%%%%%%%%%% %%% \starray_get_cnt:n %%% \starray_parsed_get_cnt:NN %%% \starray_parsed_get_cnt: => checked/nocheck %%%%%%%%%%%%%%% \__starray_cs_generate:nnNnnn {get_cnt}{} \c__starray_no_idx_ending_bool { \__starray_basest_get_cnt:w #2 } { \__starray_msg_dispatch: \msg_warning:nnnn {starray} {syntax / prop} {get:3} {#1} } % returns nothing by default { \msg_warning:nnnn {starray} {syntax / parsed} {parsed:3} {\starray_parsed_get_cnt:} } %%%%%%%%%%%%%%% %%% \starray_get_cnt:nN %%% \starray_parsed_get_cnt:NNN %%% \starray_parsed_get_cnt:N => checked/nocheck %%%%%%%%%%%%%%% \__starray_cs_generate:nnNnnn {get_cnt}{N} \c__starray_no_idx_ending_bool { \__starray_basest_get_cnt:wN #2 #3 } { \__starray_msg_dispatch: \msg_warning:nnnn {starray} {syntax / prop} {get:4} {#1} } % returns nothing by default { \msg_warning:nnnn {starray} {syntax / parsed} {parsed:4} {\starray_parsed_get_cnt:N} } %%%%%%%%%%%%%%% %%% \starray_get_cnt:nNTF %%% \starray_parsed_get_cnt:NNNTF %%% \starray_parsed_get_cnt:NTF => checked/nocheck %%%%%%%%%%%%%%% \__starray_prg_generate:nnNnnn {get_cnt}{N} \c__starray_no_idx_ending_bool { \__starray_basest_get_cnt:wN #2 #3 \prg_return_true: } { \__starray_msg_clear: } %% This will be F case of \__starray_parser:NeTF, not expandable anyway { } %% This will be F case of \bool_if:NTF \__starray_prg_undef_p:nn {get_cnt}{N} %%%%%%%%%%%%%%% %%% %%% \starray_get_iter:n %%% \starray_parsed_get_iter:NN %%% \starray_parsed_get_iter: => checked/nocheck %%% %%%%%%%%%%%%%%% \__starray_cs_generate:nnNnnn {get_iter}{} \c__starray_no_idx_ending_bool { \__starray_basest_get_iter:w #2 } { \__starray_msg_dispatch: \msg_warning:nnnn {starray} {syntax / prop} {get:5} {#1} } % returns nothing by default { \msg_warning:nnnn {starray} {syntax / parsed} {parsed:5} {\starray_parsed_get_iter:} } %%%%%%%%%%%%%%% %%% \starray_get_iter:nN %%% \starray_parsed_get_iter:NNN %%% \starray_parsed_get_iter:N => checked/nocheck %%%%%%%%%%%%%%% \__starray_cs_generate:nnNnnn {get_iter}{N} \c__starray_no_idx_ending_bool { \__starray_basest_get_iter:wN #2 #3 } { \__starray_msg_dispatch: \msg_warning:nnnn {starray} {syntax / prop} {get:6} {#1} } % returns nothing by default { \msg_warning:nnnn {starray} {syntax / parsed} {parsed:6} {\starray_parsed_get_iter:N} } %%%%%%%%%%%%%%% %%% \starray_get_iter:nnTF %%% \starray_parsed_get_iter:NNnTF %%% \starray_parsed_get_iter:nNTF => checked/nocheck %%%%%%%%%%%%%%% \__starray_prg_generate:nnNnnn {get_iter}{N} \c__starray_no_idx_ending_bool { \__starray_basest_get_iter:wN #2 #3 \prg_return_true: } { \__starray_msg_clear: } %% This will be F case of \__starray_parser:NeTF, not expandable anyway { } %% This will be F case of \bool_if:NTF \__starray_prg_undef_p:nn {get_iter}{N} %%% \c__starray_..._term_st %%% \c{ -infix- _term_prop } %% #1 %%% { -infix- } %% #2 %%% { -val- } %% iter's val for this entry %% #3 %%% { -idx- } %% #4 %%% \c{ -ref- _defstkeys_prop} %% #5 %%% \s__end %%%%%% %%% \__starray_termst_get_unique_id:NN %%% \__starray_termst_get_unique_id:cN %%% \__starray_termst_get_unique_id:wN %%%%%% \__starray_cs_wgen:nnnn {__starray_termst_get_unique_id}{N}{ # 1 # 2 # 3 \s__end # 4 } { \tl_set:Nn #4 {#2} } %%%%%%%%%%%%%%% %%% %%% \starray_get_unique_id:nN %%% \starray_parsed_get_unique_id:NNN %%% \starray_parsed_get_unique_id:N => checked/nocheck %%% %%%%%%%%%%%%%%% \__starray_cs_generate:nnNnnn {get_unique_id}{N} \c__starray_idx_ending_bool { \__starray_termst_get_unique_id:wN #1 #3 } { \__starray_msg_dispatch: \msg_warning:nnnn {starray} {syntax / prop} {get:7} {#1} } % returns nothing by default { \msg_warning:nnnn {starray} {syntax / parsed} {parsed:7} {\starray_parsed_get_unique_id:N} } %%%%%%%%%%%%%%% %%% %%% \starray_get_unique_id:nNTF %%% \starray_parsed_get_unique_id:NNNTF %%% \starray_parsed_get_unique_id:NTF => checked/nocheck %%% %%%%%%%%%%%%%%% \__starray_prg_generate:nnNnnn {get_unique_id}{N} \c__starray_idx_ending_bool { \__starray_termst_get_unique_id:wN #1 #3 \prg_return_true: } { \__starray_msg_clear: } %% This will be F case of \__starray_parser:NeTF, not expandable anyway { } %% This will be F case of \bool_if:NTF \__starray_prg_undef_p:nn {get_unique_id}{N} %%% \c__starray_..._term_st %%% \c{ -infix- _term_prop } %% #1 %%% { -infix- } %% #2 %%% { -val- } %% iter's val for this entry %% #3 %%% { -idx- } %% #4 %%% \c{ -ref- _defstkeys_prop} %% #5 %%% \s__end %%%%%% %%% \__starray_termst_set_prop:NNnn %%% \__starray_termst_set_prop:cNnn %%% \__starray_termst_set_prop:wNnn %%%%%% \__starray_cs_wgen:nnnn {__starray_termst_set_prop}{Nnn}{ # 1 # 2 \s__end # 3 # 4 # 5 } { #3 %% this will be either \prop_put: or \prop_gput: #1 {#4} {#5} } %%%%%%%%%%%%%%% %%%% %%%% \starray_set_prop %%%% %%%%%%%%%%%%%%% %%%%%%%%%%%%%%% %%% \starray_set_prop:nnn %%% \starray_set_prop:nnnTF %%%%%%%%%%%%%%% \__starray_cs_prg_duo_generate:NNnn \starray_set_prop:nnn \c__starray_idx_ending_bool { \__starray_termst_set_prop:NNnn \l__starray_parsed_term_st \prop_put:Nnn {#2}{#3} \prg_return_true: } { \msg_warning:nnnn {starray} {syntax / prop} {set:1} {#1} } \cs_generate_variant:Nn \starray_set_prop:nnn {nnV} \prg_generate_conditional_variant:Nnn \starray_set_prop:nnn { nnV } {T, F , TF } %%% %%%%%%%%%%%%%%% %%% \starray_gset_prop:nnn %%% \starray_gset_prop:nnnTF %%%%%%%%%%%%%%% \__starray_cs_prg_duo_generate:NNnn \starray_gset_prop:nnn \c__starray_idx_ending_bool { \__starray_termst_set_prop:NNnn \l__starray_parsed_term_st \prop_gput:Nnn {#2}{#3} \prg_return_true: } { \msg_warning:nnnn {starray} {syntax / prop} {set:1} {#1} } \cs_generate_variant:Nn \starray_gset_prop:nnn {nnV} \prg_generate_conditional_variant:Nnn \starray_gset_prop:nnn { nnV } {T, F , TF } %%% %%%%%%%%%%%%%%% %%%%%%%%%%%%%%% %%%% %%%% set/get properties (keyval) %%%% %%%% %%%%%%%%%%%%%%% %%%%%%%%%%%%%%% \cs_new:Npn \__starray_set_parse_end_chk:w #1 ] \q_nil \q_stop { \tl_if_empty:nTF {#1} \prg_return_true: \prg_return_false: %% syntax ERR (something after ) } % % Not expandable. DO NOT generate a predicate version! % but, already a :w conditional anyway (internal) % \prg_new_conditional:Npnn \__starray_set_parse_end:w #1 ] #2 \q_stop { TF} { \quark_if_nil:nTF {#2} { \prg_return_false: } %% syntax ERR { \tl_set:Nn \l__starray_parser_tmp_A_tl {#1} \__starray_set_parse_end_chk:w #2 \q_stop } } % % Not expandable. DO NOT generate a predicate version! % but, already a :w conditional anyway (internal) % %\prg_new_conditional:Npnn \__starray_set_parse_aux:w #1#2 [ \q_nil \q_stop { TF} \cs_new:Npn \__starray_set_parse_aux:wTF #1 [ \q_nil \q_stop { \__starray_set_parse_end:wTF #1 ] \q_nil\q_stop % {\prg_return_true:} % {\prg_return_false:} } % % Not expandable. DO NOT generate a predicate version! % but, already a :w conditional anyway (internal) % \prg_new_conditional:Npnn \__starray_set_parse_begin:w #1 [ #2 \q_stop { TF} { \tl_set:Nn \l__starray_parser_tmp_B_tl {#1} \quark_if_nil:nTF {#2} { % no 'term' ref, just array_name (current/iter term) \tl_clear:N \l__starray_parser_tmp_A_tl \prg_return_true: } { \__starray_set_parse_aux:wTF #2 \q_stop \prg_return_true: \prg_return_false: } } \cs_new:Npn \__starray_set_from_keyval_parse:n #1 { } % hanging key, no value set, silently ignored. %%% \c__starray_..._base_st %%% \c{ -infix- _ihash_prop} %% #1 %%% \c{ -infix- _base_iter_int } %% #2 %%% \c{ -infix- _base_cnt_int } %% #3 %%% \c{ -ref- _defkeys_prop} %% #4 %%% \c{ -ref- _defstkeys_prop} %% #5 %%% {-ref-}{-infix-} %% #6#7 %%% \s__end %%%%%% %%% \__starray_basest_set_from_keyval_parse:N %%% \__starray_basest_set_from_keyval_parse:c %%% \__starray_basest_set_from_keyval_parse:w %%%%%% \__starray_cs_wgen:nnnn {__starray_basest_set_from_keyval_parse}{nn}{ # 1 # 2 # 3 \s__end # 4 # 5 } { \tl_if_blank:nTF {#4} { \prop_get:NeNTF #1 {\int_use:N #2} \l__starray_tmp_term_st { \keyval_parse:een { \exp_not:N \__starray_set_from_keyval_parse:n } { \exp_not:N \__starray_termst_set_from_keyval_parse:wnn \exp_not:o \l__starray_tmp_term_st } { #5 } } {%%err, non-instatiated \__starray_msg:nnee {reference / iter} {setkeyval:3} {--} {#4} } } { \prop_get:NnNTF #1 {#4} \l__starray_tmp_term_st { \keyval_parse:een { \exp_not:N \__starray_set_from_keyval_parse:n } { \exp_not:N \__starray_termst_set_from_keyval_parse:wnn \exp_not:o \l__starray_tmp_term_st } { #5 } } {%%err, invalid hash \__starray_msg:nnee {reference / iter} {setkeyval:3} {--} {#4} } } } \cs_generate_variant:Nn \__starray_basest_set_from_keyval_parse:Nnn {co} %%%%%%%%%%%%%%% %%%%%%%%%%%%%%% %%%% %%%% set from keyval %%%% %%%% NOTE: tmp variables are recursive aware. %%%% %%%%%%%%%%%%%%% %%%%%%%%%%%%%%% %%% \c__starray_..._term_st %%% \c{ -infix- _term_prop } %% #1 %%% { -infix- } %% #2 %%% { -val- } %% iter's val for this entry %% #3 %%% { -idx- } %% #4 %%% \c{ -ref- _defstkeys_prop} %% #5 %%% \s__end %%% #6 => prop/struct(key from keyval) %%% #7 => val/keyval (val from keyval) %%%%%% %%% \__starray_termst_set_from_keyval_parse:N %%% \__starray_termst_set_from_keyval_parse:c %%% \__starray_termst_set_from_keyval_parse:w %%%%%% \__starray_cs_wgen:nnnn {__starray_termst_set_from_keyval_parse}{nn}{ # 1 # 2 # 3 # 4 # 5 \s__end # 6 # 7 } { \__starray_set_parse_begin:wTF #6 [ \q_nil \q_stop { \seq_if_in:NeTF #5 \l__starray_parser_tmp_B_tl { \__starray_basest_set_from_keyval_parse:con {c__starray_prfix_. #2 . \l__starray_parser_tmp_B_tl _base_st } \l__starray_parser_tmp_A_tl {#7} } { \tl_if_empty:NTF \l__starray_parser_tmp_A_tl { \__starray_put:Nen #1 \l__starray_parser_tmp_B_tl {#7} } {%%err invalid ref / not a substructure \__starray_msg:nnee {syntax / structure-ref} {setkeyval:4} {#6} {\l__starray_parser_tmp_B_tl} } } } {%%err invalid ref/syntax \__starray_msg:nnnn {syntax / term} {setkeyval:5}{#6}{} } } %%%%%%%%%%%%%%% %%% \__starray_set_from_keyval:nn %%% \__starray_set_from_keyval:nnTF %%%%%%%%%%%%%%% \__starray_cs_prg_duo_generate:NNnn \__starray_set_from_keyval:nn \c__starray_idx_ending_bool { %%% just in case, for msg_err messages \tl_set:Nn \l__starray_from_keyval_orgref_tl {#1} \keyval_parse:een { \exp_not:N \__starray_set_from_keyval_parse:n } { \exp_not:N \__starray_termst_set_from_keyval_parse:wnn \exp_not:o \l__starray_parsed_term_st } { #2 } \__starray_msg_dispatch: \__starray_rtn: } { \msg_warning:nnnn {starray} {syntax / prop} {setkeyval:1} {#1} } %\cs_new_protected:Npn \starray_set_from_keyval:nn #1#2 % { % \cs_set_eq:NN \__starray_put:cnn \prop_put:cnn % \__starray_set_from_keyval:nn {#1}{#2} % } \cs_new_protected:Npn \starray_set_from_keyval:nn { \cs_set_eq:NN \__starray_put:Nen \prop_put:Nen \__starray_set_from_keyval:nn } %\cs_new_protected:Npn \starray_gset_from_keyval:nn #1#2 % { % \cs_set_eq:NN \__starray_put:cnn \prop_gput:cnn % \__starray_set_from_keyval:nn {#1}{#2} % } \cs_new_protected:Npn \starray_gset_from_keyval:nn { \cs_set_eq:NN \__starray_put:Nen \prop_gput:Nen \__starray_set_from_keyval:nn } %% %% TODO: Might be worth a bit (more) of optimization... %% \cs_new_protected: \starray_set_from_keyval:nnTF (etc...) with the two parameters being implicit... %% %\prg_new_protected_conditional:Npnn \starray_set_from_keyval:nn #1#2 {T, F, TF} % { % \cs_set_eq:NN \__starray_put:cnn \prop_put:cnn % \__starray_set_from_keyvalTF:nn {#1}{#2} % } \cs_new_protected:Npn \starray_set_from_keyval:nnT { \cs_set_eq:NN \__starray_put:Nen \prop_put:Nen \__starray_set_from_keyval:nnT } \cs_new_protected:Npn \starray_set_from_keyval:nnF { \cs_set_eq:NN \__starray_put:Nen \prop_put:Nen \__starray_set_from_keyval:nnF } \cs_new_protected:Npn \starray_set_from_keyval:nnTF { \cs_set_eq:NN \__starray_put:Nen \prop_put:Nen \__starray_set_from_keyval:nnTF } %\prg_new_protected_conditional:Npnn \starray_gset_from_keyval:nn #1#2 {T, F, TF} % { % \cs_set_eq:NN \__starray_put:cnn \prop_gput:cnn % \__starray_set_from_keyvalTF:nn {#1}{#2} % } \cs_new_protected:Npn \starray_gset_from_keyval:nnT { \cs_set_eq:NN \__starray_put:Nen \prop_gput:Nen \__starray_set_from_keyval:nnT } \cs_new_protected:Npn \starray_gset_from_keyval:nnF { \cs_set_eq:NN \__starray_put:Nen \prop_gput:Nen \__starray_set_from_keyval:nnF } \cs_new_protected:Npn \starray_gset_from_keyval:nnTF { \cs_set_eq:NN \__starray_put:Nen \prop_gput:Nen \__starray_set_from_keyval:nnTF } %%%%%%%%%%%%%%% %%%%%%%%%%%%%%% %%%% %%%% starray ref/address parser using quarks %%%% could be done with seq_split and regex but %%%% would have been even more cumbersome (and slow) %%%% %%%% := [ . ] %%%% := [ ] %%%% := \[ \] %%%% %%%%%%%%%%%%%%% %%%%%%%%%%%%%%% \cs_new:Npn \__starray_term_parser_end_chk:w #1 ] \q_nil \q_stop { \tl_if_empty:nTF {#1} \prg_return_true: \prg_return_false: %% syntax ERR (something after ) } %%% %%% \tl_set: isn't expandable... but (internal) and only the TF variant is needed. %%% :w macro anyway... %%% \prg_new_conditional:Npnn \__starray_term_parse_end:w #1 ] #2 \q_stop { TF} { \quark_if_nil:nTF {#2} { \prg_return_false: } %% syntax ERR { \tl_set:Nn \l__starray_parsed_idx_tl {#1} \__starray_term_parser_end_chk:w #2 \q_stop } } %%% %%% \tl_set: isn't expandable (see above)... but (internal) and only the TF variant is needed. %%% :w macro anyway... %%% %\prg_new_conditional:Npnn \__starray_term_parse_aux:w #1 [ \q_nil \q_stop { TF} % { % \__starray_term_parse_end:wTF #1 ] \q_nil\q_stop % {\prg_return_true:} % {\prg_return_false:} % } \cs_new:Npn \__starray_term_parse_aux:wTF #1 [ \q_nil \q_stop { \__starray_term_parse_end:wTF #1 ] \q_nil\q_stop } %%% %%% \tl_set: isn't expandable (see above)... but (internal) and only the TF variant is needed. %%% :w macro anyway... %%% \prg_new_conditional:Npnn \__starray_term_parse_begin:w #1 [ #2 \q_stop { TF} { \tl_set:Nn \l__starray_parsed_term_tl {#1} \quark_if_nil:nTF {#2} { % no 'term' ref, just array_name (current/iter term) \tl_clear:N \l__starray_parsed_idx_tl \prg_return_true: } { \__starray_term_parse_aux:wTF #2 \q_stop \prg_return_true: \prg_return_false: } } %%% \c__starray_..._base_st %%% \c{ -infix- _ihash_prop} %% #1 %%% \c{ -infix- _base_iter_int } %% #2 %%% \c{ -infix- _base_cnt_int } %% #3 %%% \c{ -ref- _defkeys_prop} %% #4 %%% \c{ -ref- _defstkeys_prop} %% #5 %%% {-ref-}{-infix-} %% #6#7 %%% \s__end %%%%%% %%% \__starray_basest_if_valid_idx:Nn %%% \__starray_basest_if_valid_idx:cn %%% \__starray_basest_if_valid_idx:wn %%%%%% \__starray_prg_wgen:nnnn {__starray_basest_if_valid_idx}{n}{ # 1 # 2 # 3 \s__end # 4 } { \tl_if_empty:NTF #4 { \prop_get:NeNTF #1 {\int_use:N #2} \l__starray_parsed_term_st { \__starray_termst_get_infix:NN \l__starray_parsed_term_st \l__starray_tmpb_tl \tl_set:Ne \l__starray_parsed_ref_tl { . \l__starray_tmpb_tl } \prg_return_true: } { \tl_set_eq:NN \l__starray_parsed_term_st \c__starray_empty_hash_term_st \prg_return_false: } } { \prop_get:NeNTF #1 {#4} \l__starray_parsed_term_st { \__starray_termst_get_infix:NN \l__starray_parsed_term_st \l__starray_tmpb_tl \tl_set:Ne \l__starray_parsed_ref_tl { . \l__starray_tmpb_tl } \prg_return_true: } { \tl_set_eq:NN \l__starray_parsed_term_st \c__starray_empty_hash_term_st \prg_return_false: } } } %%% %%% small surprise, it was possible to _protected this... TODO: further test it. %%% \cs_new_protected:Npn \__starray_ref_parse:nw #1 . #2 \q_stop { %% just if case, for _msg_ \tl_put_right:Nn \l__starray_parsed_tl {#1} \__starray_term_parse_begin:wTF #1 [ \q_nil \q_stop { % syntax ok so far. % TODO: verify instance validity hash/index % vars: \l__starray_parsed_term_tl % \l__starray_parsed_idx_tl \tl_put_right:Ne \l__starray_parsed_ref_tl { . \l__starray_parsed_term_tl } \__starray_if_exist:cTF { c__starray_prfix_ \l__starray_parsed_ref_tl _base_st } { \quark_if_nil:nTF {#2} { % this is the 'last one' \tl_set_eq:Nc \l__starray_parsed_base_st { c__starray_prfix_ \l__starray_parsed_ref_tl _base_st } \bool_if:NTF \l__starray_parser_no_idx_ending_bool { % assuming it is to add a term... \tl_if_empty:NTF \l__starray_parsed_idx_tl { } % done. correct { \bool_set_false:N \l__starray_parser_OK_bool \__starray_msg:nnee {syntax / ref-syntax-err} {parser:1} {\l__starray_parsing_term_tl} {invalid~index~\l__starray_parsed_idx_tl~(at~the~end)} } % err ! } { % assuming it is to set/get a property... _base_st maps to \__starray_if_valid_idx:NNNNNnnTF % This will set \l__starray_parsed_term_st (if it exists) \__starray_basest_if_valid_idx:cnTF { c__starray_prfix_ \l__starray_parsed_ref_tl _base_st } \l__starray_parsed_idx_tl { } % done, finish, ok { \bool_set_false:N \l__starray_parser_OK_bool \__starray_msg:nnee {syntax / ref-syntax-err} {parser:2} {\l__starray_parsing_term_tl} {invalid~index~\l__starray_parsed_idx_tl} } } } { % assuming it is to set/get a property... _base_st maps to \__starray_if_valid_idx:NNNNNnnTF % This will set \l__starray_parsed_term_st (if it exists) \__starray_basest_if_valid_idx:cnTF { c__starray_prfix_ \l__starray_parsed_ref_tl _base_st } \l__starray_parsed_idx_tl { \__starray_ref_parse:nw #2 \q_stop } % recurse next term { \bool_set_false:N \l__starray_parser_OK_bool \__starray_msg:nnee {syntax / ref-syntax-err} {parser:3} {\l__starray_parsing_term_tl} {invalid~index~\l__starray_parsed_idx_tl} } } } { \bool_set_false:N \l__starray_parser_OK_bool \__starray_msg:nnee {syntax / ref-syntax-err} {parser:4} {\l__starray_parsing_term_tl} {invalid~struct~\l__starray_parsed_ref_tl} } % invalid/ref err. } { \bool_set_false:N \l__starray_parser_OK_bool \__starray_msg:nnee {syntax / ref-syntax-err} {parser:5} {\l__starray_parsing_term_tl} {invalid~struct~#1~at~\l__starray_parsed_tl} } % syntax/ref err. } %%%%%%%%%%%%%%% %%%%%%%%%%%%%%% %%%% %%%% parser 'true' returns: %%%% \l__starray_parsed_ref_tl %%%% %%%% \l__starray_parsed_term_st !!! IF there is one! %%%% \l__starray_parsed_base_st !!! always, if OK %%%% %%%% parser 'false' returns: %%%% %%%% %%%%%%%%%%%%%%% %%%%%%%%%%%%%%% \cs_new_protected:Npn \__starray_parser:NnTF #1#2 { \bool_set_eq:NN \l__starray_parser_no_idx_ending_bool #1 \bool_set_true:N \l__starray_parser_OK_bool \tl_clear:N \l__starray_parsed_ref_tl %%% This is just for error/warning messages \tl_set:Nn \l__starray_parsing_term_tl {#2} \__starray_ref_parse:nw #2 .\q_nil\q_stop \bool_if:NTF \l__starray_parser_OK_bool } \cs_generate_variant:Nn \__starray_parser:NnTF {Ne} \cs_new_protected:Npn \starray_term_parser:n #1 { \__starray_parser:NeTF \c__starray_idx_ending_bool {#1} { \tl_gset_eq:NN \g__starray_parsed_saved_term_st \l__starray_parsed_term_st \tl_gset_eq:NN \g__starray_parsed_saved_base_st \l__starray_parsed_base_st \bool_gset_true:N \g__starray_parsed_bool } { \bool_gset_false:N \g__starray_parsed_bool \__starray_msg_dispatch: \msg_warning:nnnn {starray} {syntax / term} {term parser:1} {#1} } } \cs_new_protected:Npn \starray_term_syntax:n { \msg_warning:nnnnn {starray} {strict / deprecate} {dep:01} { \starray_term_syntax:n } { \starray_term_parser:n } \starray_term_parser:n } \prg_new_protected_conditional:Npnn \starray_term_parser:n #1 {T, F, TF} { \__starray_parser:NeTF \c__starray_idx_ending_bool {#1} { \tl_gset_eq:NN \g__starray_parsed_saved_term_st \l__starray_parsed_term_st \tl_gset_eq:NN \g__starray_parsed_saved_base_st \l__starray_parsed_base_st \bool_gset_true:N \g__starray_parsed_bool \prg_return_true: } { \bool_gset_false:N \g__starray_parsed_bool \__starray_msg_clear: \prg_return_false: } } \cs_new_protected:Npn \starray_term_syntax:nTF { \msg_warning:nnnnn {starray} {strict / deprecate} {dep:03} { \starray_term_syntax:nTF } { \starray_term_parser:nTF } \starray_term_parser:nTF } \cs_new_protected:Npn \starray_term_syntax:nT { \msg_warning:nnnnn {starray} {strict / deprecate} {dep:04} { \starray_term_syntax:nT } { \starray_term_parser:nT } \starray_term_parser:nT } \cs_new_protected:Npn \starray_term_syntax:nF { \msg_warning:nnnnn {starray} {strict / deprecate} {dep:05} { \starray_term_syntax:nF } { \starray_term_parser:nF } \starray_term_parser:nF } \cs_new_protected:Npn \starray_term_parser:nN #1#2 { \__starray_parser:NeTF \c__starray_idx_ending_bool {#1} { \tl_gset:Ne #2 { {\exp_not:o \l__starray_parsed_term_st} {\exp_not:o \l__starray_parsed_base_st} } } { \__starray_msg_dispatch: \msg_warning:nnnn {starray} {syntax / term} {term parser:2} {#1} } } \cs_new_protected:Npn \starray_term_parser:nNN #1#2#3 { \msg_warning:nnnnn {starray} {strict / deprecate} {dep:02a} { \starray_term_syntax:nNN } { \starray_term_parser:nN } \starray_term_parser:nN {#1}{#2} } \cs_new_protected:Npn \starray_term_syntax:nNN { \msg_warning:nnnnn {starray} {strict / deprecate} {dep:02} { \starray_term_syntax:nNN } { \starray_term_parser:nNN } \starray_term_parser:nNN } \prg_new_protected_conditional:Npnn \starray_term_parser:nN #1#2 {T, F, TF} { \__starray_parser:NeTF \c__starray_idx_ending_bool {#1} { \tl_gset:Ne #2 { {\exp_not:o \l__starray_parsed_term_st} {\exp_not:o \l__starray_parsed_base_st} } \prg_return_true: } { \__starray_msg_clear: \prg_return_false: } } \cs_new_protected:Npn \starray_term_parser:nNNTF #1#2#3 { \msg_warning:nnnnn {starray} {strict / deprecate} {dep:06a} { \starray_term_parser:nNNTF } { \starray_term_parser:nNTF } \starray_term_parser:nNTF {#1}{#2} } \cs_new_protected:Npn \starray_term_parser:nNNT #1#2#3 { \msg_warning:nnnnn {starray} {strict / deprecate} {dep:07a} { \starray_term_parser:nNNT } { \starray_term_parser:nNT } \starray_term_parser:nNT {#1}{#2} } \cs_new_protected:Npn \starray_term_parser:nNNF #1#2#3 { \msg_warning:nnnnn {starray} {strict / deprecate} {dep:08a} { \starray_term_parser:nNNF } { \starray_term_parser:nNF } \starray_term_parser:nNF {#1}{#2} } \cs_new_protected:Npn \starray_term_syntax:nNNTF { \msg_warning:nnnnn {starray} {strict / deprecate} {dep:06} { \starray_term_syntax:nNNTF } { \starray_term_parser:nNNTF } \starray_term_parser:nNNTF } \cs_new_protected:Npn \starray_term_syntax:nNNT { \msg_warning:nnnnn {starray} {strict / deprecate} {dep:07} { \starray_term_syntax:nNNT } { \starray_term_parser:nNNT } \starray_term_parser:nNNT } \cs_new_protected:Npn \starray_term_syntax:nNNF { \msg_warning:nnnnn {starray} {strict / deprecate} {dep:08} { \starray_term_syntax:nNNF } { \starray_term_parser:nNNF } \starray_term_parser:nNNF } %%%%%%%%%%%%%%% %%%%%%%%%%%%%%% %%%% %%%% \..show_def commands %%%% %%%%%%%%%%%%%%% %%%%%%%%%%%%%%% %%% \c__starray...._ref_st %%% \c{ -ref- _defkeys_prop } %% #1 %%% \c{ -ref- _defstkeys_seq } %% #2 %%% {-ref-} %% #3 %%% \s__end %%%%%% %%% \__starray_refst_show_def:Nnn %%% \__starray_refst_show_def:cnn %%% \__starray_refst_show_def:wnn %%%%%% \__starray_cs_wgen:nnnn {__starray_refst_show_def}{nn}{ # 1 # 2 # 3 \s__end # 4 # 5 } { \tl_put_right:Nn \l__starray_show_tmp_tl { \__starray_show: > #4 \tl_to_str:n {{#5}} \use:nn {~}{~} struct \use:nn {~}{~} => } \prop_map_inline:Nn #1 { \tl_put_right:Nn \l__starray_show_tmp_tl { \__starray_show: > #4 \use:nnn {~}{~}{~} \tl_to_str:n { {##1} } \use:nn {~}{~} => \use:nn {~}{~} \tl_to_str:n { {##2} } } } \seq_map_inline:Nn #2 { \__starray_refst_show_def:cnn { c__starray_prfix_. #3 . ##1 _ref_st } {#4 \use:nnn {~}{~}{~}} {##1} } } %%%%%%%%%%%%%%% %%%% %%%% \starray_show_def %%%% %%%%%%%%%%%%%%% \cs_new_protected:Npn \starray_show_def:n #1 { \tl_clear:N \l__starray_show_tmp_tl \cs_set_eq:NN \__starray_show: \iow_newline: \__starray_refst_show_def:cnn { c__starray_prfix_. #1 _ref_st } { } {#1} \msg_show:nnxxx {starray}{info / show} { show~def } { The~ starray~ <#1> ~is~defined~as~follow: } { \l__starray_show_tmp_tl } } \cs_new_protected:Npn \starray_show_def_in_text:n #1 { \tl_clear:N \l__starray_show_tmp_tl \cs_set_eq:NN \__starray_show: \par \__starray_refst_show_def:cnn { c__starray_prfix_. #1 _ref_st } { } {#1} \l__starray_show_tmp_tl } %%%%%%%%%%%%%%% %%%%%%%%%%%%%%% %%%% %%%% \..show_terms commands %%%% %%%%%%%%%%%%%%% %%%%%%%%%%%%%%% %%% \c__starray_..._term_st %%% \c{ -infix- _term_prop } %% #1 %%% { -infix- } %% #2 %%% { -val- } %% iter's val for this entry %% #3 %%% { -idx- } %% #4 %%% \c{ -ref- _defstkeys_prop} %% #5 %%% \s__end %%%%%% %%% \__starray_termst_show_item:NnnN %%% \__starray_termst_show_item:cnnN %%% \__starray_termst_show_item:wnnN %%%%%% \__starray_cs_wgen:nnnn {__starray_termst_show_item}{nnN}{ # 1 # 2 # 3 # 4 # 5 \s__end # 6 # 7 # 8} { \tl_put_right:Nn \l__starray_show_tmp_tl { \__starray_show: > #6 \tl_to_str:n { {#7} ~ (idx: ~ #4)} \use:nn {~}{~} => } \prop_map_inline:Nn #1 { \tl_put_right:Nn \l__starray_show_tmp_tl { \__starray_show: > #6 \use:nnn {~}{~}{~} \tl_to_str:n { {##1} } \use:nn {~}{~} => ~ \tl_to_str:n { {##2} } } } \seq_map_inline:Nn #8 { \__starray_basest_show_terms:cnn {c__starray_prfix_. #2 . ##1 _base_st} {#6 \use:nnn {~}{~}{~}} {##1} } } %%% \c__starray_..._base_st %%% \c{ -infix- _ihash_prop} %% #1 %%% \c{ -infix- _base_iter_int } %% #2 %%% \c{ -infix- _base_cnt_int } %% #3 %%% \c{ -ref- _defkeys_prop} %% #4 %%% \c{ -ref- _defstkeys_prop} %% #5 %%% {-ref-}{-infix-} %% #6#7 %%% \s__end %%%%%% %%% \__starray_basest_show_terms:Nnn %%% \__starray_basest_show_terms:cnn %%% \__starray_basest_show_terms:wnn %%%%%% \__starray_cs_wgen:nnnn {__starray_basest_show_terms}{nn}{ # 1 # 2 # 3 # 4 # 5 # 6 # 7 \s__end # 8 # 9 } { \prop_map_inline:Nn #1 { \__starray_termst_show_item:wnnN ##2 {#8} {#9[##1]} #5 } } %%%%%%%%%%%%%%% %%%% %%%% \starray_show_terms %%%% %%%%%%%%%%%%%%% \cs_new_protected:Npn \starray_show_terms:n #1 { \tl_clear:N \l__starray_show_tmp_tl \cs_set_eq:NN \__starray_show: \iow_newline: \__starray_basest_show_terms:cnn { c__starray_prfix_. #1 _base_st } { } {#1} \msg_show:nnxxx {starray}{info / show} { show~terms } { The~ starray~ <#1> ~has~the~following~terms: } { \l__starray_show_tmp_tl } } \cs_new_protected:Npn \starray_show_terms_in_text:n #1 { \tl_clear:N \l__starray_show_tmp_tl \cs_set_eq:NN \__starray_show: \par \__starray_basest_show_terms:cnn { c__starray_prfix_. #1 _base_st } { } {#1} \l__starray_show_tmp_tl }