%%%============================================================================== %% 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.1a} {2026/07/04} %% %% The list of files that compose this work can be found in the README.md file at %% https://ctan.org/pkg/starray %% %%%============================================================================== \NeedsTeXFormat{LaTeX2e}[2026/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/07/04}, version = {2.1a} , description = {A 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 \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 } { (#1)~'#2'~already~defined! } { You~tried~to~(re)define~'#2'. ~Error~Code: (#1). } \msg_new:nnnn { starray } { strict / not defined } { (#1)~'#2'~isn't~defined! } { You~tried~to~use~a~non~defined~'#2'. ~Error~Code: (#1). } \msg_new:nnnn { starray } { syntax / ref-syntax-err } { (#1)~term~reference~'#2'~--~'#3'. } { Your~term~'#2'~contains~a~syntax~error:~'#3'. ~Error~ Code: (#1). } \msg_new:nnnn { starray } { syntax / keyval-term } { (#1)~term~reference~'#2'~error~'#3'. } { Your~term~'#2'~contains~a~syntax~error:~'#3'. ~Error~ Code: (#1). } \msg_new:nnnn { starray } { syntax / term } { (#1)~'#2'~isn't~a~valid~term~ref. } { Invalid~term~reference:~'#2'. ~Error~ Code: (#1). } \msg_new:nnnn { starray } { syntax / parsed } { (#1)~Can't~ call~ #2~ after~a~ failed~ \starray_term_parser: } { You~ called~ #2~ after~ a~ failed~ call~ to~ \starray_term_parser: ~Error~ Code: (#1). } \msg_new:nnnn { starray } { syntax / structure-ref } { (#1)~'#3'~isn't~a~sub-structure~of~'#2'. } { '#2' ~doesn't~have~a~sub-structure~named:~'#3'. ~Error~ Code: (#1). } \msg_new:nnnn { starray } { syntax / iter } { (#1)~cannot~set~iter. ~invalid~'#2'. } { cannot~set~iter.~ invalid '#2'. ~Error~ Code: (#1). } \msg_new:nnnn { starray } { syntax / prop } { (#1)~cannot~get/set~property~from~'#2'. } { You~have~referenced~an~invalid~structure~'#2'. ~Error~ Code: (#1). } \msg_new:nnnn { starray } { reference / keyval } { (#1)~key~'#2'~ignored. } { You~referenced~a~key~without~setting~it's~value. ~Key~ignored. } \msg_new:nnnn { starray } { reference / invalid-starray } %%%$$ { (#1)~'#2'~invalid~starray. \tl_if_blank:nTF { #3 } {~#3 } {} } { '#2'~isn't~a~starray. \tl_if_blank:nTF { #3 } {~#3 } {} ~Error~ Code: (#1). } \msg_new:nnnn { starray } { reference / iter } { (#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: (#1). } \msg_new:nnnn { starray } { reference / prop } %%%$$ { (#1)~cannot~get/set~property~'#3'~from~'#2'. } { '#3'~isn't~a~property~of~'#2'. ~Error~ Code: (#1). } \msg_new:nnnn { starray } { info / show } { \iow_newline:(#1)\iow_newline:~ #2 \iow_newline: #3 \iow_newline: definition's~end. } { \iow_newline:(#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: (#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 } \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_tl %%%% %%%% (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 \tl_new:N \l__starray_parsed_term_st_tl \tl_new:N \g__starray_parsed_saved_base_st_tl \tl_new:N \g__starray_parsed_saved_term_st_tl \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_tl, _term_st_tl and _ref_st_tl %%%% \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 4 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_ uparsed_ #cmd# : N #signature# } => expecting an user given variable (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 %%% This *might* be expandable (if base-code (and if-parsed-bool-false, if checked) is) %%% { starray_ iparsed_ #cmd# : #signature# } => using iterate over parsed term %%% %%%%%%%%% %%% %%% 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 (o-expanded) '...term_st' and '...base_st' %%% %%% '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_tl \g__starray_parsed_saved_base_st_tl } { #7 #2 } } } { \cs_new:cpn { starray_parsed_ #3 : #4 } { \exp_args:Noo #1 \g__starray_parsed_saved_term_st_tl \g__starray_parsed_saved_base_st_tl } } \cs_new:cpn { starray_iparsed_ #3 : #4 } { \exp_args:Noo #1 \g__starray_iterate_term_st_tl \g__starray_iterate_base_st_tl } \cs_new:cpn { starray_ #3 : n#4 } ##1 { \__starray_parser:NeTF #5 { ##1 } { \exp_args:Noo #1 \l__starray_parsed_term_st_tl \l__starray_parsed_base_st_tl } { #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_ uparsed_ #cmd# : N #signature# { p, TF,T,F }} => expecting an 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 %%% This *might* be expandable (if base-code and T/F code (that follows) also are... and (if-parsed-boold-false, if checked) %%% { starray_ iparsed_ #cmd# : #signature# { p,TF,T,F }} => using iterate over parsed term %%% %%% 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 (o-expanded) '...term_st' and '...base_st' %%% %%% '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_tl \g__starray_parsed_saved_base_st_tl } { #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_tl \g__starray_parsed_saved_base_st_tl } { #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_tl \g__starray_parsed_saved_base_st_tl } \cs_new:cpn { starray_parsed_ #5 _p : #6 } { \exp_args:Noo #2 \g__starray_parsed_saved_term_st_tl \g__starray_parsed_saved_base_st_tl } } \cs_new:cpn { starray_iparsed_ #5 : #6 TF } { \exp_args:Noo #1 \g__starray_iterate_term_st_tl \g__starray_iterate_base_st_tl } \cs_new:cpn { starray_iparsed_ #5 _p : #6 } { \exp_args:Noo #2 \g__starray_iterate_term_st_tl \g__starray_iterate_base_st_tl } \cs_new:cpn { starray_ #5 : n#6 TF } ##1 { \__starray_parser:NeTF #7 { ##1 } { \exp_args:Noo #1 \l__starray_parsed_term_st_tl \l__starray_parsed_base_st_tl } { #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_tl \l__starray_parsed_base_st_tl } % { #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_tl \g__starray_parsed_saved_base_st_tl } { #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_tl \g__starray_parsed_saved_base_st_tl } { #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_tl \g__starray_parsed_saved_base_st_tl } \cs_new:cpn { starray_parsed_ #5 : #6 T } { \exp_args:Noo #2 \g__starray_parsed_saved_term_st_tl \g__starray_parsed_saved_base_st_tl } } \cs_new:cpn { starray_iparsed_ #5 : #6 F } { \exp_args:Noo #1 \g__starray_iterate_term_st_tl \g__starray_iterate_base_st_tl } \cs_new:cpn { starray_iparsed_ #5 : #6 T } { \exp_args:Noo #2 \g__starray_iterate_term_st_tl \g__starray_iterate_base_st_tl } \cs_new:cpn { starray_ #5 : n#6 T } ##1 { \__starray_parser:NeTF #7 { ##1 } { \exp_args:Noo #1 \l__starray_parsed_term_st_tl \l__starray_parsed_base_st_tl } { #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_tl \l__starray_parsed_base_st_tl } { #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 %%% *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_tl } \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_tl } \prg_return_true: \prg_return_false: } \tl_const:Nn \c__starray_empty_hash_term_st_tl { \relax \relax \s__end } %%% %%% This will generate three main commands %%% \#cmd# : N #sig# => idea being the 1st parameter will be a _st variable %%% \#cmd# : c #sig# %%% \#cmd# : w #sig# => the _st variable is already o-expanded %%% Careful when calling this, the 3rd parameter has to convey 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 three main conditional commands %%% \#cmd# : N #sig#TF => (and c variant) idea being the 1st parameter will be a _st variable %%% \#cmd# : w #sig#TF => the _st variable is already o-expanded %%% Careful when calling this, the 3rd parameter has to convey 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 iten, 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_tl } { \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_tl } { \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_tl } { \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_tl } { \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_tl %%% \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_tl } { \__starray_refst_def_prop:cnn { c__starray_prfix_. #1 _ref_st_tl } { #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_tl } { \__starray_refst_def_prop:cnn { c__starray_prfix_. #1 _ref_st_tl } { #2 } { #3 } \prg_return_true: } \prg_return_false: } %%%%%%%%%%%%%%% %%%%%%%%%%%%%%% %%%% %%%% adding struct array #2 to a starray %%%% %%%% %%%%%%%%%%%%%%% %%%%%%%%%%%%%%% %%% \c__starray...._ref_st_tl %%% \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_tl %%% \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_tl } { \__starray_basest_fix_terms:c { c__starray_prfix_. #2 . #5 _base_st_tl } } { \__starray_base_new:nn { #4 . #5 } { #2 . #5 } } } %%% \c__starray_..._base_st_tl %%% \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_tl \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_tl } { \__starray_basest_fix_terms:c { c__starray_prfix_. \l__starray_tmpb_tl _base_st_tl } } { \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_tl } { \__starray_refst_def_struct:cn { c__starray_prfix_. #1 _ref_st_tl } { #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_tl } { \__starray_refst_def_struct:cn { c__starray_prfix_. #1 _ref_st_tl } { #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_tl } } { \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_tl } } { #3 } } { % #1 should be ..._ref_st_tl \__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_tl \__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_tl } { \keyval_parse:een { \exp_not:N \__starray_def_from_keyval_parse:Nn \exp_not:c { c__starray_prfix_. #1 _ref_st_tl } } { \exp_not:N \__starray_def_from_keyval_parse:Nnn \exp_not:c { c__starray_prfix_. #1 _ref_st_tl } } { #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_tl } { \keyval_parse:een { \exp_not:N \__starray_def_from_keyval_parse:Nn \exp_not:c { c__starray_prfix_. #1 _ref_st_tl } } { \exp_not:N \__starray_def_from_keyval_parse:Nnn \exp_not:c { c__starray_prfix_. #1 _ref_st_tl } } { #2 } \prg_return_true: } { \prg_return_false: } } %%%%%%%%%%%%%%% %%%%%%%%%%%%%%% %%%% %%%% adding terms %%%% %%%% %%%%%%%%%%%%%%% %%%%%%%%%%%%%%% %%% \c__starray_..._base_st_tl %%% \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_tl { #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_tl { #2 } \prg_return_true: } { \prg_return_false: } } %%% \c__starray_..._term_st_tl %%% \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_tl } { 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_tl \__starray_termst_get_infix:NN \l__starray_tmp_term_st_tl \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_tl %%% \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_tl { \__starray_termst_get_iterval:NN \l__starray_tmp_term_st_tl \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_tl { #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_tl { 1 } {}{} \prg_return_false: } { \__starray_basest_set_iter:NnTF \l__starray_parsed_base_st_tl { #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_tl { 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_tl {} { \__starray_set_rtn_false: } \__starray_rtn: } { \msg_warning:nnnn { starray } { syntax / iter } { iter:5 } { #1 } } %%% \c__starray_..._base_st_tl %%% \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 \tl_gset_eq:NN #4 \l__starray_tmp_term_st_tl } \RequirePackage{ tokglobalstack } \globalstack_csnew:n { __starray_istack } \cs_generate_variant:Nn \__starray_istack_gpush:n { e } \cs_new_protected:Npn \__starray_istack_push: { \bool_if:NTF \g__starray_iterate_bool { \__starray_istack_gpush:e { \exp_not:N \tl_gset:Nn \exp_not:N \g__starray_iterate_base_st_tl { \exp_not:o \g__starray_iterate_base_st_tl } \exp_not:N \tl_gset:Nn \exp_not:N \g__starray_iterate_term_st_tl { \exp_not:o \g__starray_iterate_term_st_tl } \exp_not:N \bool_gset_true:N \exp_not:N \g__starray_iterate_bool } } { \__starray_istack_gpush:e { \exp_not:N \tl_gset:Nn \exp_not:N \g__starray_iterate_base_st_tl { \exp_not:o \g__starray_iterate_base_st_tl } \exp_not:N \tl_gset:Nn \exp_not:N \g__starray_iterate_term_st_tl { \exp_not:o \g__starray_iterate_term_st_tl } \exp_not:N \bool_gset_false:N \exp_not:N \g__starray_iterate_bool } } } \cs_set_eq:NN \__starray_istack_pop: \__starray_istack_gpop: \bool_new:N \g__starray_iterate_bool \tl_new:N \g__starray_iterate_base_st_tl \tl_new:N \g__starray_iterate_term_st_tl %%%%%%%%%%%%%%% %%% %%% \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_tl \l__starray_parsed_base_st_tl \bool_gset_true:N \g__starray_iterate_bool \__starray_basest_set_iter:NnTF \g__starray_iterate_base_st_tl { 1 } { \__starray_basest_get_term:NN \g__starray_iterate_base_st_tl \g__starray_iterate_term_st_tl \bool_do_while:Nn \g__starray_iterate_bool { #2 \__starray_basest_incr_iter:NTF \g__starray_iterate_base_st_tl { \__starray_basest_get_term:NN \g__starray_iterate_base_st_tl \g__starray_iterate_term_st_tl } { \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_tl %%% \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_tl %%% \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_tl %%% \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_tl %%% \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_tl %%% \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_tl %%% \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_tl \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_tl \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_tl %%% \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_tl { \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_tl } { #5 } } {%%err, non-instatiated \__starray_msg:nnee { reference / iter } { setkeyval:3 } {--} { #4 } } } { \prop_get:NnNTF #1 { #4 } \l__starray_tmp_term_st_tl { \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_tl } { #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_tl %%% \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_tl } \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_tl } { #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_tl %%% \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_tl { \__starray_termst_get_infix:NN \l__starray_parsed_term_st_tl \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_tl \c__starray_empty_hash_term_st_tl \prg_return_false: } } { \prop_get:NeNTF #1 { #4 } \l__starray_parsed_term_st_tl { \__starray_termst_get_infix:NN \l__starray_parsed_term_st_tl \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_tl \c__starray_empty_hash_term_st_tl \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_tl } { \quark_if_nil:nTF { #2 } { % this is the 'last one' \tl_set_eq:Nc \l__starray_parsed_base_st_tl { c__starray_prfix_ \l__starray_parsed_ref_tl _base_st_tl } \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_tl maps to \__starray_if_valid_idx:NNNNNnnTF % This will set \l__starray_parsed_term_st_tl (if it exists) \__starray_basest_if_valid_idx:cnTF { c__starray_prfix_ \l__starray_parsed_ref_tl _base_st_tl } \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_tl maps to \__starray_if_valid_idx:NNNNNnnTF % This will set \l__starray_parsed_term_st_tl (if it exists) \__starray_basest_if_valid_idx:cnTF { c__starray_prfix_ \l__starray_parsed_ref_tl _base_st_tl } \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_tl !!! IF there is one! %%%% \l__starray_parsed_base_st_tl !!! 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_tl \l__starray_parsed_term_st_tl \tl_gset_eq:NN \g__starray_parsed_saved_base_st_tl \l__starray_parsed_base_st_tl \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_tl \l__starray_parsed_term_st_tl \tl_gset_eq:NN \g__starray_parsed_saved_base_st_tl \l__starray_parsed_base_st_tl \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_tl } { \exp_not:o \l__starray_parsed_base_st_tl } } } { \__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_tl } { \exp_not:o \l__starray_parsed_base_st_tl } } \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_tl %%% \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_tl } { #4 \use:nnn {~}{~}{~}} { ##1 } } } %%%%%%%%%%%%%%% %%%% %%%% \starray_show_def %%%% %%%%%%%%%%%%%%% \cs_new_protected:Npn \starray_show_def:n #1 { \__starray_if_exist:cTF { c__starray_prfix_. #1 _ref_st_tl } { \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_tl } { } { #1 } \msg_show:nnxxx { starray }{ info / show } { show~def } { The~ starray~ <#1> ~is~defined~as~follow: } { \l__starray_show_tmp_tl } } { \msg_warning:nnnn { starray }{ strict / not defined } { show~def } { #1 } } } \cs_new_protected:Npn \starray_show_def_in_text:n #1 { \__starray_if_exist:cTF { c__starray_prfix_. #1 _ref_st_tl } { \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_tl } { } { #1 } \l__starray_show_tmp_tl } { \msg_warning:nnnn { starray }{ strict / not defined } { show~def } { #1 } } } %%%%%%%%%%%%%%% %%%%%%%%%%%%%%% %%%% %%%% \..show_terms commands %%%% %%%%%%%%%%%%%%% %%%%%%%%%%%%%%% %%% \c__starray_..._term_st_tl %%% \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_tl } { #6 \use:nnn {~}{~}{~}} { ##1 } } } %%% \c__starray_..._base_st_tl %%% \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 { \__starray_if_exist:cTF { c__starray_prfix_. #1 _base_st_tl } { \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_tl } { } { #1 } \msg_show:nnxxx { starray }{ info / show } { show~terms } { The~ starray~ <#1> ~has~the~following~terms: } { \l__starray_show_tmp_tl } } { \msg_warning:nnnn { starray }{ strict / not defined } { show~terms } { #1 } } } \cs_new_protected:Npn \starray_show_terms_in_text:n #1 { \__starray_if_exist:cTF { c__starray_prfix_. #1 _base_st_tl } { \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_tl } { } { #1 } \l__starray_show_tmp_tl } { \msg_warning:nnnn { starray }{ strict / not defined } { show~terms } { #1 } } }