summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/starray/latex/starray.sty
diff options
context:
space:
mode:
Diffstat (limited to 'macros/latex/contrib/starray/latex/starray.sty')
-rw-r--r--macros/latex/contrib/starray/latex/starray.sty2073
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
+ }
+
+