diff options
Diffstat (limited to 'macros/latex/contrib/starray/latex/starray.sty')
-rw-r--r-- | macros/latex/contrib/starray/latex/starray.sty | 2073 |
1 files changed, 2073 insertions, 0 deletions
diff --git a/macros/latex/contrib/starray/latex/starray.sty b/macros/latex/contrib/starray/latex/starray.sty new file mode 100644 index 0000000000..332118809f --- /dev/null +++ b/macros/latex/contrib/starray/latex/starray.sty @@ -0,0 +1,2073 @@ +%%%============================================================================== +%% Copyright 2023 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 1.0 (2023/05/11) +%% +%% The list of files that compose this work can be found in the README.md file at +%% https://ctan.org/pkg/starray +%% +%%%============================================================================== +\NeedsTeXFormat{LaTeX2e}[2022/06/01] +\RequirePackage{ expl3 } +\ProvidesExplPackage + {starray} + {2023/05/11} + {1.0} + {A structured array/hash of properties} + +\prop_if_exist:NTF \g__codedesc_pkg_prop + {} + { \prop_new:N \g__codedesc_pkg_prop } + +\prop_put_from_keyval:Nn \g__codedesc_pkg_prop + { + starray . name = starrayr , + starray . prefix = starray , + starray . date = 2023/05/01 , + starray . version = 1.0 , + starray . description = A structured array/hash of properties + } + +\cs_gset:Npn \__codedesc_pkg_info:nn #1#2 + { + \prop_item:Nn \g__codedesc_pkg_prop {#1.#2} + } + +\cs_if_exist:NTF \PkgInfo + {} + { + \NewDocumentCommand \PkgInfo {mm} { \prop_item:Nn \g__codedesc_pkg_prop {#1.#2} } + } + + +%%%%%%%%%%%%%%%%%%% +%%%% +%%%% New package +%%%% +%%%%%%%%%%%%%%%%%%% + +\tl_new:N \l__starray_prefix_tl +%\tl_gset:Nn \l__starray_prefix_tl {l__starray_} + + +\keys_define:nn { starray } +{ + prefix .tl_set:N = \l__starray_prefix_tl , + prefix .value_required:n = true , + prefix .initial:n = l__starray_ , + prefix .usage:n = load , + + msg-err .choice: , + msg-err / none .code:n = { + % \msg_redirect_module:nnn { starray } { warning } { none } + }, + 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-err . 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 } , + msg-supress . usage:n = load , + + +} + +\ProcessKeyOptions [ starray ] + +%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%% +%%%% +%%%% New variants of core expl3 primitives +%%%% expansion handling +%%%% +%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%% + +\cs_generate_variant:Nn \prop_item:Nn { ce , Ne } +\cs_generate_variant:Nn \tl_put_right:Nn {Ne} +\cs_generate_variant:Nn \tl_gput_right:Nn {Ne} +\cs_generate_variant:Nn \tl_set:Nn {Ne , ce} +\cs_generate_variant:Nn \tl_gset:Nn {Ne , ce} + +\cs_generate_variant:Nn \seq_put_right:Nn {ce} +\cs_generate_variant:Nn \seq_gput_right:Nn {ce} + +\cs_generate_variant:Nn \int_to_Alph:n {e} + +\cs_generate_variant:Nn \prop_put:Nnn {Nee , cee} +\cs_generate_variant:Nn \prop_gput:Nnn {Nee , cee} + +\cs_generate_variant:Nn \prop_get:NnN {Nnc , cnc , Nec , cec} + +\prg_generate_conditional_variant:Nnn \prop_get:NnN {Nnc , cnc , Nec , cec} { F , T , TF} + +\prg_generate_conditional_variant:Nnn \seq_if_in:Nn {ce} {TF} +\prg_generate_conditional_variant:Nnn \prop_if_in:Nn {ce} {TF} + + +%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%% +%%%% +%%%% Package error/warning messages +%%%% #1 'ID' (code identifier) +%%%% #2 / #3 / #4 further fields (as 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 / 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~structur~'#2'. + ~Error~ Code~ ID:<#1>. + } + + +\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. + } + + + + + +\cs_new:Npn \__starray_msg:nnnnn #1#2#3#4#5 + { + \bool_gset_false:N \l__starray_rtn_bool + + \seq_gput_right:Nn \l__starray_msg_seq + { + \msg_warning:nnnnnn + {starray}{ #1 } { #2 }{ #3 }{ #4 }{ #5 } + } + } + +\cs_generate_variant:Nn \__starray_msg:nnnnn { nneee , neeee } + +\cs_new:Npn \__starray_msg_dispatch: + { + \seq_map_tokens:Nn \l__starray_msg_seq { } + \seq_clear:N \l__starray_msg_seq + } + +%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%% +%%%% +%%%% Package Variables declaration +%%%% +%%%% +%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%% +% TODO variables declaration + +\prop_new:N \l__starray_tmpA_prop + +%%%% +%%%% 'general' (internal) returning bool +%%%% +\bool_new:N \l__starray_rtn_bool + +%%%% +%%%% sequence of 'error mensages' (stacked). +%%%% +\seq_new:N \l__starray_msg_seq + +%%%% +%%%% recursive/reentrant aware tmp variables. +%%%% + +\int_set:Nn \l_tmpa_int {7} +\tl_clear:N \l_tmpa_tl +\int_do_while:nNnn {\l_tmpa_int} > {0} + { + \tl_put_left:Nn \l_tmpa_tl {A} + \prop_new:c { l__starray_tmp \l_tmpa_tl _hash_prop } + \prop_new:c { l__starray_tmp \l_tmpa_tl _def_prop } + \prop_new:c { l__starray_tmp \l_tmpa_tl _idx_prop } + \int_new:c { l__starray_tmp \l_tmpa_tl _int } + \seq_new:c { l__starray_tmp \l_tmpa_tl _seq } + \tl_new:c { l__starray_tmp \l_tmpa_tl _tl } + \tl_new:c { l__starray_tmp \l_tmpa_tl :A_tl } + \tl_new:c { l__starray_tmp \l_tmpa_tl :B_tl } + \tl_new:c { l__starray_tmp \l_tmpa_tl _idx_tl } + + \int_decr:N \l_tmpa_int + } + +\tl_new:N \l__starray_tmpa_tl +\tl_new:N \l__starray_tmpb_tl + +\tl_new:N \l__starray_showcmd_tl + +%%%% +%%%% (sub)structure returning tl. +%%%% +\tl_new:N \l__starray_tmpST_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 + + +%%%% +%%%% 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_ref_tl +\tl_new:N \l__starray_parsed_root_ref_tl + +\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 + +\tl_new:N \l__starray_parser_aux_tl %% when constructing parser ref, 1st <nothing> then dot . + +\bool_new:N \l__starray_parser_OK_bool + + +%% big one, (g)put !! +%%%% +%%%% (g)put :: IF the effect shall be local or global +%%%% +\tl_new:N \l__starray_put_tl + + + +%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%% +%%%% +%%%% Package conditionals +%%%% +%%%% +%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%% + +\prg_new_conditional:Npnn \__starray_if_free:n #1 {p, T, F, TF} + { + \prop_if_exist:cTF {#1} + { \prg_return_false: } + { \prg_return_true: } + } + +\prg_generate_conditional_variant:Nnn \__starray_if_free:n {e} {p, T, F, TF} + +\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_generate_conditional_variant:Nnn \__starray_if_valid:n {e} {p, T, F, TF} + +%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%% +%%%% +%%%% starray \...._new declarations +%%%% +%%%% +%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%% + + +\cs_new:Npn \__starray_base_new:nn #1#2 + { + \int_new:c + { \l__starray_prefix_tl #2 _cnt_int } + \int_gzero:c + { \l__starray_prefix_tl #2 _cnt_int } + + \int_new:c + { \l__starray_prefix_tl #2 _iter_int } + \int_gzero:c + { \l__starray_prefix_tl #2 _iter_int } + + \prop_new:c { \l__starray_prefix_tl #2 _base_prop } + + \prop_gset_from_keyval:cn + { \l__starray_prefix_tl #2 _base_prop } + { + def_ref = #1 , + is_starray = \c_true_bool , + } + + \prop_gput:cno + { \l__starray_prefix_tl #2 _base_prop } + { cnt } + { \use:c { \l__starray_prefix_tl #2 _cnt_int } } + + \prop_gput:cno + { \l__starray_prefix_tl #2 _base_prop } + { iter } + { \use:c {\l__starray_prefix_tl #2 _iter_int} } + + \prop_gput:cnV + { \l__starray_prefix_tl #2 _base_prop } + { idx_hash } + \c_empty_prop + } + +\cs_generate_variant:Nn \__starray_base_new:nn { ee } + + +\cs_new:Npn \__starray_sub_base_new:nnn #1#2#3 + { \__starray_base_new:ee {#1.#3}{#2.#3} } + + +\cs_new:Npn \__starray_new:n #1 + { + \prop_new:c + { \l__starray_prefix_tl #1 _def_prop } + + \prop_gset_from_keyval:cn + { \l__starray_prefix_tl #1 _def_prop } + { + is_starray = \c_true_bool , + def_ref = #1 + } + + \prop_clear:N \l_tmpa_prop + + \prop_gput:cnV { \l__starray_prefix_tl #1 _def_prop } {@st_seq} \c_empty_seq + + \prop_gput:cnV + { \l__starray_prefix_tl #1 _def_prop} {def} \l_tmpa_prop + + } + +\cs_generate_variant:Nn \__starray_new:n { e } + + +%%%%%%%%%%%%%%% +%%%% +%%%% \starray_new +%%%% +%%%%%%%%%%%%%%% + +\cs_new:Npn \starray_new:n #1 + { + \__starray_if_free:nTF {\l__starray_prefix_tl #1 _def_prop} + { + \__starray_new:e {#1 } + \__starray_base_new:ee {#1}{#1} % TODO: might be incomplete !!! + } + { + \msg_warning:nnnn {starray} {strict / (re)define} {new:1} {#1} + } + } + + +\prg_new_conditional:Npnn \starray_new:n #1 {p, T, F, TF} + { + \__starray_if_free:nTF {\l__starray_prefix_tl #1 _def_prop} + { + \__starray_new:e {#1 } + \__starray_base_new:ee {#1}{#1} % TODO: might be incomplete !!! + \prg_return_true: + } + { \prg_return_false: } + } + +%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%% +%%%% +%%%% starray ref parser +%%%% +%%%% +%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%% +%%%% +%%%% get root reference (first term) assuming called as +%%%% <st-ref> . \q_nil \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:w \l__starray_tmpa_tl . \q_nil \q_stop} +%%%% +%%%% It will return the 'root ref' assuming that the ref is of form root.name.name (no [idx]) +%%%% +%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%% + +\cs_new:Npn \__starray_get_root:w #1 . #2 \q_stop { #1 } + + +%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%% +%%%% +%%%% adding property #3 (#4 being it's initial/default value) +%%%% #1 prefix +%%%% #2 starray +%%%% +%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%% + + +\cs_new:Npn \__starray_def_prop:nnn #1#2#3 + { + \prop_get:cnN {\l__starray_prefix_tl #1 _def_prop} {def} \l_tmpa_prop + \prop_put:Nnn \l_tmpa_prop {#2} {#3} + \prop_gput:cnV {\l__starray_prefix_tl #1 _def_prop} {def} \l_tmpa_prop + } + + + +%%%%%%%%%%%%%%% +%%%% +%%%% \starray_def_prop +%%%% +%%%%%%%%%%%%%%% + +\cs_new:Npn \starray_def_prop:nnn #1#2#3 + { + \__starray_if_valid:nTF {\l__starray_prefix_tl #1 _def_prop} + { \__starray_def_prop:nnn {#1} {#2} {#3} } + { + \msg_warning:nnxxx {starray}{reference / invalid-starray} + {addprop:1} {#1} {cannot~add~property:#2} + } + } + + +\prg_new_conditional:Npnn \starray_def_prop:nnn #1#2#3 {p, T, F, TF} + { + \__starray_if_valid:nTF {\l__starray_prefix_tl #1 _def_prop} + { + \__starray_def_prop:nnn {#1} {#2} {#3} + \prg_return_true: + } + { \prg_return_false: } + } + + +%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%% +%%%% +%%%% adding struct array #2 to a starray +%%%% +%%%% +%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%% + +\cs_new:Npn \__starray_def_struct:nn #1#2 + { + \prop_get:cnN {\l__starray_prefix_tl #1 _def_prop} {@st_seq} \l_tmpa_seq + \seq_if_in:NnF \l_tmpa_seq {#2} + { + \seq_put_right:Nn \l_tmpa_seq {#2} + + \prop_gput:cnV {\l__starray_prefix_tl #1 _def_prop} {@st_seq} \l_tmpa_seq + + \__starray_new:e { #1 . #2} + } + } + +\cs_generate_variant:Nn \__starray_def_struct:nn {ne} + + +%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%% +%%%% +%%%% fixing struct _base for already instantiated terms +%%%% +%%%% +%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%% +%TODO: recurse over 'terms' to fix a 'late addtion' (after being instantiated?) + +\cs_new:Npn \__starray_fix_terms_seq_aux:nnnn #1#2#3#4 + { + \__starray_if_valid:eTF {\l__starray_prefix_tl #2 _ #3 . #4 _base_prop} + { + \__starray_fix_terms:nn {#1.#4}{#2_#3.#4} + } + { + \__starray_base_new:ee {#1.#4}{#2_#3.#4} + } + } + +\cs_new:Npn \__starray_fix_terms_seq:nnnn #1#2#3#4 + { + \prop_get:cnN + {\l__starray_prefix_tl #2 _base_prop} + {def_ref} + \l_tmpa_tl + \prop_get:cec + {\l__starray_prefix_tl \l_tmpa_tl _def_prop} + {@st_seq} + {l__starray_tmp A_seq} + \seq_map_tokens:cn + {l__starray_tmp A_seq} + {\__starray_fix_terms_seq_aux:nnnn {#1}{#2}{#4}} + + } + +\cs_new:Npn \__starray_fix_terms:nn #1#2 + { + \group_begin: + \prop_get:cnc + {\l__starray_prefix_tl #2 _base_prop} + {idx_hash} + {l__starray_tmp A_prop} + \prop_if_empty:cF {l__starray_tmp A_prop} + { + \prop_map_tokens:cn + {l__starray_tmp A_prop} + {\__starray_fix_terms_seq:nnnn {#1}{#2}} + } + \group_end: + } + +\cs_generate_variant:Nn \__starray_fix_terms:nn {ee} + + + +\cs_new:Npn \starray_fix_terms:n #1 + { + \tl_set:Ne \l_tmpb_tl {\__starray_get_root:w #1 . \q_nil \q_stop} + + \__starray_if_valid:nTF { \l__starray_prefix_tl \l_tmpb_tl _def_prop} + { + \__starray_fix_terms:ee {\l_tmpb_tl}{\l_tmpb_tl} + } + { + \msg_warning:nnxxx {starray}{reference / invalid-starray} + {fixterms:1} {#1} {} + } + } + + + +%%%%%%%%%%%%%%% +%%%% +%%%% \starray_def_struct +%%%% +%%%%%%%%%%%%%%% + +\cs_new:Npn \starray_def_struct:nn #1#2 + { + \__starray_if_valid:nTF { \l__starray_prefix_tl #1 _def_prop} + { + \__starray_def_struct:nn {#1} {#2} + } + { + \msg_warning:nnxxx {starray}{reference / invalid-starray} + {addstruct:1} {#1} {cannot~add~structure:#2} + } + } + +\prg_new_conditional:Npnn \starray_def_struct:nn #1#2 {p, T, F, TF} + { + \__starray_if_valid:nTF { \l__starray_prefix_tl #1 _def_prop} + { + \__starray_def_struct:nn {#1} {#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 { p, TF} + { + \str_compare:nNnTF {#1} = {struct} + { \prg_return_true: } + { \prg_return_false: } + } + + +\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:Ne \l__starray_tmpST_tl { #1 } + \prg_return_true: + } % dot struct, OK + { +% \bool_gset_false:N \l__starray_rtn_bool + \prg_return_false: + } %% possible syntax ERR (dot, but no struct!) + } + } + + +\cs_new:Npn \__starray_def_from_keyval_parse:nnn #1#2#3 + { + \group_begin: + \__starray_def_from_keyval_testdot:wTF #2 . \q_nil \q_stop + { + \tl_set:ce {l__starray_tmp A _tl} {#1 . \l__starray_tmpST_tl} + \__starray_def_struct:ne {#1} {\l__starray_tmpST_tl} + \keyval_parse:nnn + {\__starray_def_from_keyval_parse:en {\tl_use:c {l__starray_tmp A _tl}}} + {\__starray_def_from_keyval_parse:enn {\tl_use:c {l__starray_tmp A _tl}}} + {#3} + } + { + \__starray_def_prop:nnn {#1} {#2} {#3} + } + \group_end: + } + +\cs_generate_variant:Nn \__starray_def_from_keyval_parse:nnn {enn} + + +\cs_new:Npn \__starray_def_from_keyval_parse:nn #1#2 + { + \__starray_def_prop:nnn {#1} {#2} {} + } + +\cs_generate_variant:Nn \__starray_def_from_keyval_parse:nn {en} + + + +%%%%%%%%%%%%%%% +%%%% +%%%% \starray_def_from_keyval +%%%% +%%%%%%%%%%%%%%% + +\cs_new:Npn \starray_def_from_keyval:nn #1#2 + { +% \bool_set_true:N \l__starray_rtn_bool + \__starray_if_valid:nTF { \l__starray_prefix_tl #1 _def_prop} + { + \keyval_parse:nnn + {\__starray_def_from_keyval_parse:en {#1}} + {\__starray_def_from_keyval_parse:enn {#1}} + { #2 } + } + { + \msg_warning:nnxxx {starray}{reference / invalid-starray} + {addkeyval:1} {#1} {cannot~add:#2} + } + } + +\cs_generate_variant:Nn \starray_def_from_keyval:nn {ne , ee} + + +\prg_new_conditional:Npnn \starray_def_from_keyval:nn #1#2 {p, T, F, TF} + { + \__starray_if_valid:nTF { \l__starray_prefix_tl #1 _def_prop} + { + \keyval_parse:nnn + {\__starray_def_from_keyval_parse:en {#1}} + {\__starray_def_from_keyval_parse:enn {#1}} + { #2 } + \prg_return_true: + } + { \prg_return_false: } + } + + +%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%% +%%%% +%%%% adding terms +%%%% +%%%% +%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%% + +\cs_new:Npn \__starray_new_term:nn #1#2 + { + \int_gincr:N + {\prop_item:cn {\l__starray_prefix_tl #1 _base_prop} {cnt} } + + \int_gset_eq:NN + {\prop_item:cn {\l__starray_prefix_tl #1 _base_prop} {iter} } + {\prop_item:cn {\l__starray_prefix_tl #1 _base_prop} {cnt} } + + + % idx_hash Update. + \prop_get:cnN {\l__starray_prefix_tl #1 _base_prop} {idx_hash} \l_tmpa_prop + + \prop_put:Nee \l_tmpa_prop + { \int_use:N \prop_item:cn {\l__starray_prefix_tl #1 _base_prop} {cnt} } + { \int_to_Alph:e { \prop_item:cn {\l__starray_prefix_tl #1 _base_prop} {cnt} } } + + \tl_if_blank:nF {#2} + { + \prop_put:Nee \l_tmpa_prop + { #2 } + { \int_to_Alph:e { \prop_item:cn {\l__starray_prefix_tl #1 _base_prop} {cnt} } } + } + + \prop_gput:cnV {\l__starray_prefix_tl #1 _base_prop} {idx_hash} \l_tmpa_prop + + % creating the 'new property list' (aka. term) + \tl_set:Ne \l_tmpa_tl + { \int_to_Alph:e { \prop_item:cn {\l__starray_prefix_tl #1 _base_prop} {cnt} } } + + \prop_new:c + { \l__starray_prefix_tl #1 _ \l_tmpa_tl _term_prop } + + \prop_get:cnN {\l__starray_prefix_tl #1 _base_prop} {def_ref} \l_tmpb_tl + + \prop_get:cnN {\l__starray_prefix_tl \l_tmpb_tl _def_prop} {def} \l_tmpa_prop + + \prop_gset_eq:cN { \l__starray_prefix_tl #1 _ \l_tmpa_tl _term_prop } \l_tmpa_prop + + \prop_get:cnN {\l__starray_prefix_tl \l_tmpb_tl _def_prop} {@st_seq} \l_tmpa_seq + +% map over 'all sub-starrays parts of def_ref -> st_seq (those starting with a dot, @st_seq) + \seq_map_tokens:Nn + \l_tmpa_seq + { + \__starray_sub_base_new:nnn + { \l_tmpb_tl }{ #1 _ \l_tmpa_tl } + } + } + + +%%%%%%%%%%%%%%% +%%%% +%%%% \starray_new_term +%%%% +%%%%%%%%%%%%%%% + +\cs_new:Npn \starray_new_term:nn #1#2 + { + \__starray_parser:nnTF {\c__starray_no_idx_ending_bool}{#1} + { + \__starray_new_term:nn + {\l__starray_parsed_ref_tl } + {#2} + } + { + \__starray_msg_dispatch: + \msg_warning:nnnn {starray}{syntax / term}{addterm:2}{#1} + } + } + +\prg_new_conditional:Npnn \starray_new_term:nn #1#2 {p, T, F, TF} + { + \__starray_parser:nnTF {\c__starray_no_idx_ending_bool}{#1} + { + \__starray_new_term:nn + {\l__starray_parsed_ref_tl } + {#2} + \prg_return_true: + } + { \prg_return_false: } + } + + +%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%% +%%%% +%%%% changing iterator value (recursing sub-structures) +%%%% +%%%% NOTE: since iterator change 'can' be just local, 'temp vars' are recursive aware. +%%%% +%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%% + +\cs_new:Npn \__starray_incr_iter:n #1 + { + \int_compare:nNnTF + {\prop_item:cn {\l__starray_prefix_tl #1 _base_prop} {iter}} < + {\prop_item:cn {\l__starray_prefix_tl #1 _base_prop} {cnt}} + { + \int_gincr:N { \prop_item:cn {\l__starray_prefix_tl #1 _base_prop} {iter} } + } + { + % TODO: should it be a potential 'warning' ??? + \bool_set_false:N \l__starray_rtn_bool + } + } + +\prg_new_conditional:Npnn \__starray_set_iter:nn #1#2 {p , T , F , TF} + { + \int_compare:nNnTF {#1} > {\prop_item:cn {\l__starray_prefix_tl #2 _base_prop} {cnt}} + { + \int_gset_eq:NN + { \prop_item:cn {\l__starray_prefix_tl #2 _base_prop} {iter} } + { \prop_item:cn {\l__starray_prefix_tl #2 _base_prop} {cnt} } + \prg_return_false: + } + { + \int_gset:Nn + { \prop_item:cn {\l__starray_prefix_tl #2 _base_prop} {iter} } + { #1 } + \prg_return_true: + } + } + +\prg_generate_conditional_variant:Nnn \__starray_set_iter:nn {ne} {p , T , F , TF} + +\cs_new:Npn \__starray_set_sub_iter:nnn #1#2#3 + { + \prop_get:cnN {\l__starray_prefix_tl #2#3 _base_prop} {idx_hash} \l_tmpa_prop + + \prop_get:NecT \l_tmpa_prop + { \int_use:N \prop_item:cn {\l__starray_prefix_tl #2#3 _base_prop} {iter} } + { l__starray_tmp #1 A_tl } + { + \prop_get:cnN + {\l__starray_prefix_tl #2#3 _base_prop} + {def_ref} + \l_tmpa_tl + + \prop_get:cnc + { \l__starray_prefix_tl \l_tmpa_tl _def_prop } + { @st_seq } + {l__starray_tmp #1 A_seq } + + \seq_if_empty:cF {l__starray_tmp #1 A_seq } + { + \seq_map_variable:cNn + { l__starray_tmp #1 A_seq } + \l_tmpb_tl + { + \__starray_set_iter:neTF + { 1 } + { #2#3 _ \tl_use:c {l__starray_tmp #1 A_tl} . \l_tmpb_tl } + {} + {} + + \__starray_set_sub_iter:nne + { #1 A } + { #2#3 _ \tl_use:c {l__starray_tmp #1 A_tl} . } + { \l_tmpb_tl } + } + } + } + } + +\cs_generate_variant:Nn \__starray_set_sub_iter:nnn {nne} + + +%%%%%%%%%%%%%%% +%%%% +%%%% \starray_set_iter +%%%% +%%%%%%%%%%%%%%% + +\cs_new:Npn \starray_set_iter:nn #1#2 + { + \__starray_parser:nnTF {\c__starray_no_idx_ending_bool}{#1} + { + \int_compare:nNnTF {#2} < {1} + { + \__starray_set_iter:nnTF {1}{\l__starray_parsed_ref_tl} + {} {} + } + { + \__starray_set_iter:nnTF {#2}{\l__starray_parsed_ref_tl} + {} {} + } + \__starray_set_sub_iter:nnn {}{\l__starray_parsed_ref_tl}{} + } + { + \__starray_msg_dispatch: + \msg_warning:nnnn {starray} {syntax / iter} {iter:1} {#1} + } % returns nothing by default + } + + + +\prg_new_conditional:Npnn \starray_set_iter:nn #1#2 {p, T, F, TF} + { + \bool_set_true:N \l__starray_rtn_bool + + \__starray_parser:nnTF {\c__starray_no_idx_ending_bool}{#1} + { + \int_compare:nNnTF {#2} < {1} + { + \bool_set_false:N \l__starray_rtn_bool + \__starray_set_iter:nnTF {1}{\l__starray_parsed_ref_tl} + {} + {} + } + { + \__starray_set_iter:nnTF {#2}{\l__starray_parsed_ref_tl} + {} + {\bool_set_false:N \l__starray_rtn_bool} + } + \__starray_set_sub_iter:nnn {}{\l__starray_parsed_ref_tl}{} + \bool_if:NTF \l__starray_rtn_bool + {\prg_return_true:} + {\prg_return_false:} + } + { + \seq_clear:N \l__starray_msg_seq + \prg_return_false: + } + } + + +%%%%%%%%%%%%%%% +%%%% +%%%% \starray_reset_iter +%%%% +%%%%%%%%%%%%%%% + +\cs_new:Npn \starray_reset_iter:n #1 + { + \__starray_parser:nnTF {\c__starray_no_idx_ending_bool}{#1} + { + \__starray_set_iter:nnTF {1}{\l__starray_parsed_ref_tl} {}{} + \__starray_set_sub_iter:nnn {}{\l__starray_parsed_ref_tl}{} + } + { + \__starray_msg_dispatch: + \msg_warning:nnnn {starray} {syntax / iter} {iter:4} {#1} + } % returns nothing by default + } + + +\prg_new_conditional:Npnn \starray_reset_iter:n #1 {p, T, F, TF} + { + \bool_set_true:N \l__starray_rtn_bool + + \__starray_parser:nnTF {\c__starray_no_idx_ending_bool}{#1} + { + \__starray_set_iter:nnTF {1}{\l__starray_parsed_ref_tl} {}{\bool_set_false:N \l__starray_rtn_bool} %% TODO: verify logic !@!! + \__starray_set_sub_iter:nnn {}{\l__starray_parsed_ref_tl}{} + \bool_if:NTF \l__starray_rtn_bool + {\prg_return_true:} + {\prg_return_false:} + } + { + \seq_clear:N \l__starray_msg_seq + \prg_return_false: + } + } + + +%%%%%%%%%%%%%%% +%%%% +%%%% \starray_next_iter +%%%% +%%%%%%%%%%%%%%% + +\cs_new:Npn \starray_next_iter:n #1 + { +% \bool_set_true:N \l__starray_rtn_bool + \seq_clear:N \l__starray_msg_seq + + \__starray_parser:nnTF {\c__starray_no_idx_ending_bool}{#1} + { + \__starray_incr_iter:n {\l__starray_parsed_ref_tl} + \__starray_set_sub_iter:nnn {}{\l__starray_parsed_ref_tl}{} + } + { + \__starray_msg_dispatch: +% \bool_set_false:N \l__starray_rtn_bool + \msg_warning:nnnn {starray} {syntax / iter} {iter:5} {#1} + } % returns nothing by default + } + + + +\prg_new_conditional:Npnn \starray_next_iter:n #1 {p, T, F, TF} + { + \bool_set_true:N \l__starray_rtn_bool + \seq_clear:N \l__starray_msg_seq + + \__starray_parser:nnTF {\c__starray_no_idx_ending_bool}{#1} + { + \__starray_incr_iter:n {\l__starray_parsed_ref_tl} + \__starray_set_sub_iter:nnn {}{\l__starray_parsed_ref_tl}{} + \bool_if:NTF \l__starray_rtn_bool + {\prg_return_true:} + {\prg_return_false:} + } + { \prg_return_false: } + } + +%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%% +%%%% +%%%% set/get properties +%%%% +%%%% +%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%% + + +\cs_new:Npn \__starray_get_prop:nn #1#2 + { + \prop_item:cn {\l__starray_prefix_tl #1 _term_prop}{#2} + } + +\cs_generate_variant:Nn \__starray_get_prop:nn {ee} + + +%%%%%%%%%%%%%%% +%%%% +%%%% \starray_get_prop +%%%% +%%%%%%%%%%%%%%% + +\cs_new:Npn \starray_get_prop:nn #1#2 + { + \__starray_parser:nnTF {\c__starray_idx_ending_bool}{#1} + { + \__starray_get_prop:ee {\l__starray_parsed_ref_tl}{#2} + } + { + \__starray_msg_dispatch: + \msg_warning:nnnn {starray} {syntax / prop} {get:1} {#1} + } % returns nothing by default + } + +\cs_new:Npn \starray_get_prop:nnN #1#2#3 + { + \__starray_parser:nnTF {\c__starray_idx_ending_bool}{#1} + { + \prop_get:cnNF + {\l__starray_prefix_tl \l__starray_parsed_ref_tl _term_prop} {#2} #3 + { \tl_set:Nn #3 {} } + } + { + \tl_set:Nn #3 {} + \__starray_msg_dispatch: + \msg_warning:nnnn {starray} {syntax / prop} + {get:1} {#1} + } % returns nothing by default + } + + +\prg_new_conditional:Npnn \starray_get_prop:nnN #1#2#3 {p, T, F, TF} + { + \__starray_parser:nnTF {\c__starray_idx_ending_bool}{#1} + { + \prop_get:cnNTF + {\l__starray_prefix_tl \l__starray_parsed_ref_tl _term_prop} {#2} #3 + { + \prg_return_true: + } + { + \tl_set:Nn #3 {} + \prg_return_false: + } + } + { + \tl_set:Nn #3 {} + \seq_clear:N \l__starray_msg_seq + \prg_return_false: + } % returns nothing by default + } + + +\prg_new_conditional:Npnn \starray_if_in:nn #1#2 {p, T, F, TF} + { + \__starray_parser:nnTF {\c__starray_idx_ending_bool}{#1} + { + \prop_if_in:cnTF + {\l__starray_prefix_tl \l__starray_parsed_ref_tl _term_prop} {#2} + { + \prg_return_true: + } + { + \prg_return_false: + } + } + { + \seq_clear:N \l__starray_msg_seq + \prg_return_false: + } % returns nothing by default + } + + +\cs_new:Npn \starray_get_cnt:n #1 + { + \__starray_parser:nnTF {\c__starray_no_idx_ending_bool}{#1} + { + \int_use:N + \prop_item:cn { \l__starray_prefix_tl \l__starray_parsed_ref_tl _base_prop } {cnt} + } + { + \__starray_msg_dispatch: + \msg_warning:nnnn {starray} {syntax / prop} {get:XX} {#1} + } % returns nothing by default + } + +\cs_new:Npn \starray_get_cnt:nN #1#2 + { + \__starray_parser:nnTF {\c__starray_no_idx_ending_bool}{#1} + { + \int_set_eq:NN + #2 + \prop_item:cn { \l__starray_prefix_tl \l__starray_parsed_ref_tl _base_prop } {cnt} + } + { + \__starray_msg_dispatch: + \msg_warning:nnnn {starray} {syntax / prop} + {get:XX} {#1} + } % returns nothing by default + } + +\prg_new_conditional:Npnn \starray_get_cnt:nN #1#2 {p, T, F, TF} + { + \__starray_parser:nnTF {\c__starray_no_idx_ending_bool}{#1} + { + \int_set_eq:NN + #2 + \prop_item:cn { \l__starray_prefix_tl \l__starray_parsed_ref_tl _base_prop } {cnt} + \prg_return_true: + } + { + \seq_clear:N \l__starray_msg_seq + \prg_return_false: + } % returns nothing by default + } + +\cs_new:Npn \starray_get_iter:n #1 + { + \__starray_parser:nnTF {\c__starray_no_idx_ending_bool}{#1} + { + \int_use:N + \prop_item:cn { \l__starray_prefix_tl \l__starray_parsed_ref_tl _base_prop } {iter} + } + { + \__starray_msg_dispatch: + \msg_warning:nnnn {starray} {syntax / prop} + {get:XX} {#1} + } % returns nothing by default + } + + +\cs_new:Npn \starray_get_iter:nN #1#2 + { + \__starray_parser:nnTF {\c__starray_no_idx_ending_bool}{#1} + { + \int_set_eq:NN + #2 + \prop_item:cn { \l__starray_prefix_tl \l__starray_parsed_ref_tl _base_prop } {iter} + } + { + \__starray_msg_dispatch: + \msg_warning:nnnn {starray} {syntax / prop} + {get:XX} {#1} + } % returns nothing by default + } + +\prg_new_conditional:Npnn \starray_get_iter:nN #1#2 {p, T, F, TF} + { + \__starray_parser:nnTF {\c__starray_no_idx_ending_bool}{#1} + { + \int_set_eq:NN + #2 + \prop_item:cn { \l__starray_prefix_tl \l__starray_parsed_ref_tl _base_prop } {iter} + \prg_return_true: + } + { + \seq_clear:N \l__starray_msg_seq + \prg_return_false: + } % returns nothing by default + } + + + + + +\cs_new:Npn \__starray_set_prop:nnn #1#2#3 + { + \l__starray_put_tl {\l__starray_prefix_tl #1 _term_prop}{#2}{#3} + } + + +%%%%%%%%%%%%%%% +%%%% +%%%% \starray_set_prop +%%%% +%%%%%%%%%%%%%%% + +\cs_new:Npn \starray_set_prop:nnn #1#2#3 + { + \tl_set:Nn \l__starray_put_tl \prop_put:cnn + \__starray_parser:nnTF {\c__starray_idx_ending_bool}{#1} + { + \__starray_set_prop:nnn {\l__starray_parsed_ref_tl}{#2}{#3} + } + { + \__starray_msg_dispatch: + \msg_warning:nnnn {starray} {syntax / prop} + {set:1} {#1} + } % returns nothing by default + } + +\cs_generate_variant:Nn \starray_set_prop:nnn {nnV} + +\cs_new:Npn \starray_gset_prop:nnn #1#2#3 + { + \tl_set:Nn \l__starray_put_tl \prop_gput:cnn + \__starray_parser:nnTF {\c__starray_idx_ending_bool}{#1} + { + \__starray_set_prop:nnn {\l__starray_parsed_ref_tl}{#2}{#3} + } + { + \__starray_msg_dispatch: + \msg_warning:nnnn {starray} {syntax / prop} + {set:1} {#1} + } % returns nothing by default + } + +\cs_generate_variant:Nn \starray_gset_prop:nnn {nnV} + + +\prg_new_conditional:Npnn \starray_set_prop:nnn #1#2#3 {p, T, F, TF} + { + \tl_set:Nn \l__starray_put_tl \prop_put:cnn + \__starray_parser:nnTF {\c__starray_idx_ending_bool}{#1} + { + \__starray_set_prop:nnn {\l__starray_parsed_ref_tl}{#2}{#3} + \prg_return_true: + } + { + \seq_clear:N \l__starray_msg_seq + \prg_return_false: + } + } + +\prg_generate_conditional_variant:Nnn \starray_set_prop:nnn { nnV } { p , T, F , TF } + +\prg_new_conditional:Npnn \starray_gset_prop:nnn #1#2#3 {p, T, F, TF} + { + \tl_set:Nn \l__starray_put_tl \prop_gput:cnn + \__starray_parser:nnTF {\c__starray_idx_ending_bool}{#1} + { + \__starray_set_prop:nnn {\l__starray_parsed_ref_tl}{#2}{#3} + \prg_return_true: + } + { + \seq_clear:N \l__starray_msg_seq + \prg_return_false: + } + } + + +\prg_generate_conditional_variant:Nnn \starray_gset_prop:nnn { nnV } { p , T, F , TF } + + +%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%% +%%%% +%%%% set/get properties (keyval) +%%%% +%%%% +%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%% + + +\prg_new_conditional:Npnn \__starray_set_parse_end:w #1#2 ] #3 \q_stop { TF} + { + \quark_if_nil:nTF {#3} + { \prg_return_false: } %% syntax ERR + { + \tl_set:cn {l__starray_tmp #1 :A_tl} {#2} + \prg_return_true: + } + } + + +\prg_new_conditional:Npnn \__starray_set_parse_aux:w #1#2 [ \q_nil \q_stop { TF} + { + \__starray_set_parse_end:wTF {#1}#2 ] \q_nil\q_stop + {\prg_return_true:} + {\prg_return_false:} + } + + +\prg_new_conditional:Npnn \__starray_set_parse_begin:w #1#2 [ #3 \q_stop { TF} + { + \quark_if_nil:nTF {#3} + { % no 'term' ref, just array_name (current/iter term) + \tl_clear:c {l__starray_tmp #1 :A_tl} + \prg_return_true: + } + { + \tl_set:cn {l__starray_tmp #1 :B_tl}{#2} + \__starray_set_parse_aux:wTF {#1}#3 \q_stop + {\prg_return_true:} + {\prg_return_false:} + } + } + + + +\cs_new:Npn \__starray_set_from_keyval_parse:nnnn #1#2#3#4 + { + \__starray_set_prop:nnn {#3}{#4}{} + } + +\cs_generate_variant:Nn \__starray_set_from_keyval_parse:nnnn {nnen} + +%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%% +%%%% +%%%% set from keyval +%%%% +%%%% NOTE: tmp variables are recursive aware. +%%%% +%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%% + + +\cs_new:Npn \__starray_set_from_keyval_parse:nnnnn #1#2#3#4#5 + { + \tl_clear:c {l__starray_tmp #1 _tl} + \__starray_set_parse_begin:wTF {#1}#4 [ \q_nil \q_stop + { + \tl_if_blank:eTF {\tl_use:c{l__starray_tmp #1 :A_tl}} + { + \prop_get:cnc + {\l__starray_prefix_tl #2 _def_prop} + {@st_seq} + {l__starray_tmp #1 _seq} + + \seq_if_in:cnTF {l__starray_tmp #1 _seq}{#4} + { + \prop_get:cnc + { \l__starray_prefix_tl #3 .#4 _base_prop } + { idx_hash } + { l__starray_tmp #1 _hash_prop } + \prop_get:cnc + { \l__starray_prefix_tl #3 .#4 _base_prop } + { iter } + { l__starray_tmp #1 _int } + \int_compare:nNnTF {\int_use:c {l__starray_tmp #1 _int}} < {1} + { + \__starray_msg:nnnnn {reference / iter} + {setkeyval:2}{#2.#4}{-0-}{~(not~instantiated)} + % invalid iter / not instantiated + } + { + \tl_set:ce + { l__starray_tmp #1 _tl } + { #3.#4 _ \int_to_Alph:e {\int_use:c {l__starray_tmp #1 _int}} } + \keyval_parse:nnn + { + \__starray_set_from_keyval_parse:nnen + { #1 A } + { #2.#4 } + { \tl_use:c { l__starray_tmp #1 _tl } } + } + { + \__starray_set_from_keyval_parse:nnenn + { #1 A } + { #2.#4 } + { \tl_use:c { l__starray_tmp #1 _tl } } + } + { #5 } + + } + } + { + \__starray_set_prop:nnn {#3}{#4}{#5} + } + } + { + \prop_get:cnc + { \l__starray_prefix_tl #2 _def_prop } + { @st_seq } + { l__starray_tmp #1 _seq } + + \seq_if_in:ceTF + { l__starray_tmp #1 _seq } { \tl_use:c{l__starray_tmp #1 :B_tl} } + { + \prop_get:cnc + { \l__starray_prefix_tl #3. \tl_use:c{l__starray_tmp #1 :B_tl} _base_prop } + { idx_hash } + { l__starray_tmp #1 _hash_prop } + \tl_set:ce + { l__starray_tmp #1 _idx_tl } + { + #3 . \tl_use:c{l__starray_tmp #1 :B_tl} _ + \prop_item:ce + { l__starray_tmp #1 _hash_prop } + { \tl_use:c{ l__starray_tmp #1 :A_tl } } + } + \tl_put_left:cn { l__starray_tmp #1 :B_tl } { #2 . } + \prop_if_in:ceTF + { l__starray_tmp #1 _hash_prop } + { \tl_use:c{l__starray_tmp #1 :A_tl}} + { + \keyval_parse:nnn + { + \__starray_set_from_keyval_parse:nnen + { #1 A } + { \tl_use:c{l__starray_tmp #1 :B_tl} } + { \tl_use:c { l__starray_tmp #1 _idx_tl } } + } + { + \__starray_set_from_keyval_parse:nnenn + { #1 A } + { \tl_use:c{l__starray_tmp #1 :B_tl} } + { \tl_use:c { l__starray_tmp #1 _idx_tl } } + } + { #5 } + + } + { + \__starray_msg:nneee {reference / iter} + {setkeyval:3} {#2.#4} {\tl_use:c{l__starray_tmp #1 :A_tl}} {} + % invalid hash + } + } + { + \__starray_msg:nneee {syntax / structure-ref} + {setkeyval:4} {#2.#4} {\tl_use:c{l__starray_tmp #1 :B_tl}} {} + % invalid ref / not a substructure + } + } + } + { + \__starray_msg:nnnnn {syntax / term} + {setkeyval:5}{#4}{}{} + % invalid ref/syntax + } + } + +\cs_generate_variant:Nn \__starray_set_from_keyval_parse:nnnnn {nnenn} + + +%%%%%%%%%%%%%%% +%%%% +%%%% \starray_set_from_keyval +%%%% +%%%%%%%%%%%%%%% + + +\cs_new:Npn \__starray_set_from_keyval:nn #1#2 + { + \bool_set_true:N \l__starray_rtn_bool + \__starray_parser:nnTF {\c__starray_idx_ending_bool}{#1} + { + \keyval_parse:nnn + {\__starray_set_from_keyval_parse:nnen {A}{#1}{\l__starray_parsed_ref_tl}} + {\__starray_set_from_keyval_parse:nnenn {A}{#1}{\l__starray_parsed_ref_tl}} + { #2 } + \bool_if:NF \l__starray_rtn_bool + { \__starray_msg_dispatch: } + } + { + \__starray_msg_dispatch: + \msg_warning:nnnn {starray} {syntax / prop} + {setkeyval:1} {#1} + } % returns nothing by default + } + + +\cs_new:Npn \starray_set_from_keyval:nn #1#2 + { + \tl_set:Nn \l__starray_put_tl \prop_put:cnn + \__starray_set_from_keyval:nn {#1}{#2} + } + +\cs_new:Npn \starray_gset_from_keyval:nn #1#2 + { + \tl_set:Nn \l__starray_put_tl \prop_gput:cnn + \__starray_set_from_keyval:nn {#1}{#2} + } + + +\cs_new:Npn \__starray_set_from_keyvalTF:nn #1#2 + { + \bool_set_true:N \l__starray_rtn_bool + \__starray_parser:nnTF {\c__starray_idx_ending_bool}{#1} + { + \keyval_parse:nnn + {\__starray_set_from_keyval_parse:nnen {A}{#1}{\l__starray_parsed_ref_tl}} + {\__starray_set_from_keyval_parse:nnenn {A}{#1}{\l__starray_parsed_ref_tl}} + { #2 } + \bool_if:NTF \l__starray_rtn_bool + {\prg_return_true:} + {\prg_return_false:} + } + { \prg_return_false: } + } + +\prg_new_conditional:Npnn \starray_set_from_keyval:nn #1#2 {p, T, F, TF} + { + \tl_set:Nn \l__starray_put_tl \prop_put:cnn + \__starray_set_from_keyvalTF:nn {#1}{#2} + } + +\prg_new_conditional:Npnn \starray_gset_from_keyval:nn #1#2 {p, T, F, TF} + { + \tl_set:Nn \l__starray_put_tl \prop_gput:cnn + \__starray_set_from_keyvalTF:nn {#1}{#2} + } + + +%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%% +%%%% +%%%% starray ref/address parser using quarks +%%%% could be done with seq_split and regex but +%%%% would have been even more cumbersome +%%%% +%%%% <starray_ref> := <array_ref> [ . <starray_ref> ] +%%%% <array_ref> := <array_name> [ <term_ref> ] +%%%% <term_ref> := \[ <number/hash> \] +%%%% +%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%% + +\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} + \prg_return_true: + } + } + + +\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:} + } + + +\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:} + } + } + + +% verify #2 before going for #1 . . . +% if #2 isn't empty test for it return true/false +% if #2 is empty, test if #1 is valid, return true/false +\prg_new_conditional:Npnn \__starray_if_valid_idx:nn #1#2 {p, T, F, TF} + { + \prop_get:cnN {\l__starray_prefix_tl \l__starray_parsed_ref_tl _base_prop} {idx_hash} \l_tmpa_prop + + \tl_if_blank:nTF {#2} + { + \tl_put_right:Ne \l__starray_parsed_ref_tl + { _ \prop_item:Ne \l_tmpa_prop {#1} } + } + { + \tl_put_right:Ne \l__starray_parsed_ref_tl + { _ \prop_item:Ne \l_tmpa_prop {#2} } + } + + \prop_if_exist:cTF { \l__starray_prefix_tl \l__starray_parsed_ref_tl _term_prop } + {\prg_return_true:} + {\prg_return_false:} + } + +\prg_generate_conditional_variant:Nnn \__starray_if_valid_idx:nn {ee} {p, T, F, TF} + +\cs_new:Npn \__starray_ref_parse:w #1 . #2 \q_stop + { + \tl_put_right:Ne \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_parser_aux_tl \l__starray_parsed_term_tl } + \tl_put_right:Ne \l__starray_parsed_base_ref_tl + { \l__starray_parser_aux_tl \l__starray_parsed_term_tl } + \tl_set:Nn \l__starray_parser_aux_tl { . } + + \__starray_if_valid:eTF + {\l__starray_prefix_tl \l__starray_parsed_ref_tl _base_prop} + { + \quark_if_nil:nTF {#2} + { % this is the last one + \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:nneee {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 + \__starray_if_valid_idx:eeTF + { + \int_use:N + \prop_item:cn + {\l__starray_prefix_tl \l__starray_parsed_ref_tl _base_prop} + {iter} + } + { + \l__starray_parsed_idx_tl + } + { } % done, finish, ok + { + \bool_set_false:N \l__starray_parser_OK_bool + \__starray_msg:nneee {syntax / ref-syntax-err} {parser:2} + {\l__starray_parsing_term_tl} + {invalid~index~\l__starray_parsed_idx_tl} + {} + } + } + } + { + \__starray_if_valid_idx:eeTF + { + \int_use:N + \prop_item:cn + {\l__starray_prefix_tl \l__starray_parsed_ref_tl _base_prop} + {iter} + } + { + \l__starray_parsed_idx_tl + } + { + \__starray_ref_parse:w #2 \q_stop + } % recurse next term + { + \bool_set_false:N \l__starray_parser_OK_bool + \__starray_msg:nneee {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:nneee {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:nneee {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_base_ref_tl +%%%% \l__starray_parsed_root_ref_tl +%%%% parser 'false' returns: +%%%% +%%%% +%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%% + +\prg_new_conditional:Npnn \__starray_parser:nn #1#2 {p, T, F, TF} + { + \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_tl + \tl_clear:N \l__starray_parsed_ref_tl + \tl_clear:N \l__starray_parsed_base_ref_tl + \tl_clear:N \l__starray_parsed_root_ref_tl + + \tl_set:Nn \l__starray_parser_aux_tl {} + + \tl_set:Nn \l__starray_parsing_term_tl {#2} + + \__starray_ref_parse:w #2 .\q_nil\q_stop + + \bool_if:NTF \l__starray_parser_OK_bool + { + \tl_set:Ne \l__starray_parsed_root_ref_tl + { \__starray_get_root:w \l__starray_parsed_base_ref_tl .\q_nil\q_stop } + \prg_return_true: + } + { + \prg_return_false: + } + } + + +\prg_new_conditional:Npnn \starray_term_syntax:n #1 {p, T, F, TF} + { + \__starray_parser:nnTF {\c__starray_idx_ending_bool}{#1} + {\prg_return_true:} + { + \seq_clear:N \l__starray_msg_seq + \prg_return_false: + } + } + +%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%% +%%%% +%%%% \..show_def commands +%%%% +%%%% +%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%% +%%%% +%%%% Note to self: +%%%% \l__starray_showcmd_tl could be an extra param as well +%%%% (more tokens jungling around...) +%%%% +%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%% + + +\cs_new:Npn \__starray_show_def_item:nnn #1#2#3 + { + \tl_gput_right:Nn \l__starray_tmpa_tl + { + \l__starray_showcmd_tl > #1 \use:nnn { ~ } { ~ } { ~ } + \tl_to_str:n { {#2} } + \use:nn { ~ } { ~ } => \use:nn { ~ } { ~ } + \tl_to_str:n { {#3} } + } + } + +\cs_new:Npn \__starray_show_def:nnn #1#2#3 + { + \group_begin: + \tl_gput_right:Nn \l__starray_tmpa_tl + { + \l__starray_showcmd_tl > #1 + \tl_to_str:n {{#3} ~ struct} + \use:nn { ~ } { ~ } => + } + + \prop_get:cnc + {\l__starray_prefix_tl #2#3 _def_prop} + {def} + {l__starray_tmp A _def_prop} + + \prop_get:cnc + { \l__starray_prefix_tl #2#3 _def_prop } + { @st_seq } + {l__starray_tmp A _seq } + + \prop_map_tokens:cn + {l__starray_tmp A _def_prop} + {\__starray_show_def_item:nnn {#1}} + + \seq_if_empty:cF { l__starray_tmp A _seq } + { + \seq_map_tokens:cn + { l__starray_tmp A _seq } + { \__starray_show_def:nnn { #1 \use:nnn { ~ } { ~ } { ~ }} { #2#3. } } + } + \group_end: + } + +%%%%%%%%%%%%%%% +%%%% +%%%% \starray_show_def +%%%% +%%%%%%%%%%%%%%% + +\cs_new:Npn \starray_show_def:n #1 + { + \tl_clear:N \l__starray_tmpa_tl + \tl_set:Nn \l__starray_showcmd_tl \iow_newline: + \__starray_show_def:nnn {}{}{#1} + + \msg_show:nnxxx {starray}{info / show} + { show~def } + { The~ starray~ <#1> ~is~defined~as~follow: } + { \tl_use:N \l__starray_tmpa_tl } + } + +\cs_new:Npn \starray_show_def_in_text:n #1 + { + \tl_clear:N \l__starray_tmpa_tl + \tl_set:Nn \l__starray_showcmd_tl \par + \__starray_show_def:nnn {}{}{#1} + + \tl_use:N \l__starray_tmpa_tl + } + + + +%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%% +%%%% +%%%% \..show_terms commands +%%%% +%%%% +%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%% +%%%% +%%%% Note to self: +%%%% \l__starray_showcmd_tl could be an extra param as well +%%%% (more tokens jungling around...) +%%%% +%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%% + + +\cs_new:Npn \__starray_show_term_item:nnnnn #1#2#3#4#5 + { + \group_begin: + \tl_gput_right:Nn \l__starray_tmpa_tl + { + \l__starray_showcmd_tl > #1 + \tl_to_str:n { {#3[#4]} ~ (idx: ~ #5)} + \use:nn { ~ } { ~ } => + } + + \prop_map_tokens:cn + {\l__starray_prefix_tl #2 #3 _ #5 _term_prop} + {\__starray_show_def_item:nnn {#1 }} + + \prop_get:cnN + { \l__starray_prefix_tl #2 #3 _base_prop } + { def_ref } + \l_tmpa_tl + + \prop_get:cnc + { \l__starray_prefix_tl \l_tmpa_tl _def_prop } + { @st_seq } + {l__starray_tmp A _seq } + + \seq_if_empty:cTF { l__starray_tmp A _seq } + {} + { + \seq_map_tokens:cn + { l__starray_tmp A _seq } + { \__starray_show_terms:nen { #1 \use:nnn { ~ } { ~ } { ~ }} { #2 #3_#5. } } + } + \group_end: + } + + + +\cs_new:Npn \__starray_show_terms:nnn #1#2#3 + { + \group_begin: + \prop_get:cnc + {\l__starray_prefix_tl #2 #3 _base_prop} + {idx_hash} + {l__starray_tmp A _idx_prop} + + \prop_map_tokens:cn + {l__starray_tmp A _idx_prop} + {\__starray_show_term_item:nnnnn {#1}{#2}{#3}} + \group_end: + } + +\cs_generate_variant:Nn \__starray_show_terms:nnn {nen} + +%%%%%%%%%%%%%%% +%%%% +%%%% \starray_show_terms +%%%% +%%%%%%%%%%%%%%% + +\cs_new:Npn \starray_show_terms:n #1 + { + \tl_clear:N \l__starray_tmpa_tl + \tl_set:Nn \l__starray_showcmd_tl \iow_newline: + \__starray_show_terms:nnn {}{}{#1} + + \msg_show:nnxxx {starray}{info / show} + { show~terms } + { The~ starray~ <#1> ~has~the~following~terms: } + { \tl_use:N \l__starray_tmpa_tl } + } + +\cs_new:Npn \starray_show_terms_in_text:n #1 + { + \tl_clear:N \l__starray_tmpa_tl + \tl_set:Nn \l__starray_showcmd_tl \par + \__starray_show_terms:nnn {}{}{#1} + + \tl_use:N \l__starray_tmpa_tl + } + + |