%%%==============================================================================
%% Copyright 2023-present by Alceu Frigeri
%%
%% This work may be distributed and/or modified under the conditions of
%%
%% * The [LaTeX Project Public License](http://www.latex-project.org/lppl.txt),
%%   version 1.3c (or later), and/or
%% * The [GNU Affero General Public License](https://www.gnu.org/licenses/agpl-3.0.html),
%%   version 3 (or later)
%%
%% This work has the LPPL maintenance status *maintained*.
%%
%% The Current Maintainer of this work is Alceu Frigeri
%%
%% This is version {1.9b} {2025/02/14} 
%%
%% The list of files that compose this work can be found in the README.md file at
%% https://ctan.org/pkg/starray
%%
%%%==============================================================================
\NeedsTeXFormat{LaTeX2e}[2023/11/01]


\ProvidesExplPackage
    {starray}
    {2025/02/14}
    {1.9b}
    {A structured array/hash of properties}


%%%%%%%
%%%
%%% Just an attempt of having my packages info in a regular way
%%% Idea being: { <pck-name> / pkg info } for each and all.
%%%
%%%%%%%
\keys_define:nn { starray / pkg info}
  {
     name        .code:n = {starray} ,
     prefix      .code:n = {starray} ,
     date        .code:n = {2025/02/14},
     version     .code:n = {1.9b} ,
     description .code:n = {A~structured~array/hash~of~properties}
  }
\cs_if_exist:NF \PkgInfo 
  {
    \NewDocumentCommand \PkgInfo {mm} { \keys_set:nn {#1 / pkg info}{#2} } 
    \NewDocumentCommand \PkgDescription {m} 
      { \noindent Package~ \textbf{\PkgInfo{#1}{name}}~Version:~\PkgInfo{#1}{version}~ -~ \PkgInfo{#1}{date}\par \emph{\PkgInfo{#1}{description}}~\par } 
  }  
%%%%%%%
%%% End of cut-n-paste
%%%%%%%





%%%%%%%%%%%%%%%%%%%
%%%%
%%%%  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-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 \int_gset:Nn {Ne}

\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 { cnc , cec }

\prg_generate_conditional_variant:Nnn \prop_get:NnN { Nec , cec , ceN , cnN } { 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 / Expl}
  {
    Expl~ version~ too~ old.~ Update~ needed!
  }
  {
    Expl~ version~ too~ old.~ Update~ needed!
  }

\msg_new:nnnn {starray} {strict / (re)define}
  {
    (ID:#1)~'#2'~already~defined!
  }
  {
    You~tried~to~(re)define~'#2'.
    ~Error~Code~ ID:<#1>.
  }


\msg_new:nnnn {starray} {syntax / ref-syntax-err}
  {
    (ID:#1)~term~reference~'#2'~--~'#3'.
  }
  {
    Your~term~'#2'~contains~a~syntax~error:~'#3'.
    ~Error~ Code~ ID:<#1>.
  }

\msg_new:nnnn {starray} {syntax / keyval-term}
  {
    (ID:#1)~term~reference~'#2'~error~'#3'.
  }
  {
    Your~term~'#2'~contains~a~syntax~error:~'#3'.
    ~Error~ Code~ ID:<#1>.
  }

\msg_new:nnnn {starray} {syntax /  term}
  {
    (ID:#1)~'#2'~isn't~a~valid~term~ref.
  }
  {
    Invalid~term~reference:~'#2'.
    ~Error~ Code~ ID:<#1>.
  }

\msg_new:nnnn {starray} {syntax /  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.
  }



\IfExplAtLeastTF{2024-03-14}{}{\msg_warning:nn {starray} {strict / Expl} }


\cs_new_protected: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_protected:Npn \__starray_msg_dispatch:
  {
    \seq_map_inline:Nn \l__starray_msg_seq { ##1 }
    \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.
%%%% this is clumsy and utterly ugly... 
%%%% a set of variables for each recursing level...
%%%%

\int_set:Nn \l_tmpa_int {9}
\tl_clear:N \l_tmpa_tl
\int_do_while:nNnn {\l_tmpa_int} > {0}
  {
    \tl_put_left:Nn \l_tmpa_tl {A}
    \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_tmp_A_tl
\tl_new:N \l__starray_tmp_B_tl
\tl_new:N \l__starray_tmp_C_tl
\tl_new:N \l__starray_tmp_D_tl

\tl_new:N \l__starray_showcmd_tl

%%%%
%%%% (sub)structure returning tl.
%%%%
\tl_new:N \l__starray_tmp_ST_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_ref_no_idx_ending_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_eq_conditional:NNn \__starray_if_exist:n \cs_if_exist:c {p, T, F, TF}

\prg_generate_conditional_variant:Nnn \__starray_if_exist:n {e} {p, T, F, TF}


\prg_new_conditional:Npnn \starray_if_exist:n #1 {p, T, F, TF}
  {
    \__starray_if_exist:nTF {\l__starray_prefix_tl #1 _base_defref_tl}
      { \prg_return_true: }
      { \prg_return_false: }
  }

% DEPRECATED, unless some other (simple) test become available
%\prg_new_conditional:Npnn \__starray_if_valid:n #1 {p, T, F, TF}
%  {
%    \bool_lazy_and:nnTF {\prop_if_exist_p:c {#1}} {\prop_item:cn {#1} {is_starray}}
%      { \prg_return_true: }
%      { \prg_return_false: }
%  }

\prg_new_eq_conditional:NNn \__starray_if_valid:n \cs_if_exist:c {p, T, F, TF}

\prg_generate_conditional_variant:Nnn \__starray_if_valid:n {e} {p, T, F, TF}


\prg_new_conditional:Npnn \starray_if_valid:n #1 {p, T, F, TF}
  {
    \__starray_if_valid:nTF {\l__starray_prefix_tl #1 _defref_tl}
      { \prg_return_true: }
      { \prg_return_false: }
  }


%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%
%%%%
%%%% starray \...._new declarations
%%%%
%%%%
%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%
%%%
%%% TODO: to add another property list mapping hash/idx -> iter
%%%       intend: \__starray_set_iter_hash !
%%%
% needs protection.
\cs_new_protected:Npn \__starray_base_new:nn #1#2
  {
    \int_new:c
      { \l__starray_prefix_tl #2 _base_cnt_int }

    \int_new:c
      { \l__starray_prefix_tl #2 _base_iter_int }
      
    \tl_new:c { \l__starray_prefix_tl #2 _base_defref_tl }
    \tl_set:cn { \l__starray_prefix_tl #2 _base_defref_tl } {#1}

    \prop_new_linked:c {\l__starray_prefix_tl #2 _base_idxhash_prop}
      
    \prop_new_linked:c {\l__starray_prefix_tl #2 _base_iterhash_prop}
  }

\cs_generate_variant:Nn \__starray_base_new:nn { ee }


% needs protection.
\cs_new_protected:Npn \__starray_sub_base_new:nnn #1#2#3
  { \__starray_base_new:ee {#1.#3}{#2.#3} }


% needs protection.
\cs_new_protected:Npn \__starray_new:n #1
  {
    \tl_new:c { \l__starray_prefix_tl #1 _defref_tl }
    \tl_set:cn { \l__starray_prefix_tl #1 _defref_tl } {#1}

    \seq_new:c { \l__starray_prefix_tl #1 _defstkeys_seq }
      
    \prop_new_linked:c {\l__starray_prefix_tl #1 _defkeys_prop}
  }

\cs_generate_variant:Nn \__starray_new:n { e }


%%%%%%%%%%%%%%%
%%%%
%%%% \starray_new
%%%%
%%%%%%%%%%%%%%%

% needs protection.
\cs_new_protected:Npn \starray_new:n #1
  {
    \__starray_if_exist:nTF {\l__starray_prefix_tl #1 _defref_tl}
      {
        \msg_warning:nnnn {starray} {strict / (re)define} {new:1} {#1}
      }
      {
        \__starray_new:e {#1 }
        \__starray_base_new:ee {#1}{#1} % TODO: might be incomplete !!!
      }
  }


% needs protection.
\prg_new_protected_conditional:Npnn \starray_new:n #1 {T, F, TF}
  {
    \__starray_if_exist:nTF {\l__starray_prefix_tl #1 _defref_tl}
      { \prg_return_false: }
      {
        \__starray_new:e {#1 }
        \__starray_base_new:ee {#1}{#1} % TODO: might be incomplete !!!
        \prg_return_true:
      }
  }

%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%
%%%%
%%%% 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_tmp_A_tl . \q_nil \q_stop}
%%%%
%%%% It will return the 'root ref' assuming that the ref is of form root.name.name (no [idx])
%%%%
%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%

%%%
%%% This one can't be protected... it is used in {e} expantion
%%% if protected, it results in a quark loop
%%%
% 
\cs_new:Npn \__starray_get_root:w #1 . #2 \q_stop { #1 }


%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%
%%%%
%%%% adding property #3 (#4 being it's initial/default value)
%%%%    #1 prefix
%%%%    #2 starray
%%%%
%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%


% needs protection.
\cs_new_protected:Npn \__starray_def_prop:nnn #1#2#3
  {
    \prop_gput:cnn {\l__starray_prefix_tl #1 _defkeys_prop} {#2} {#3}
  }



%%%%%%%%%%%%%%%
%%%%
%%%% \starray_def_prop
%%%%
%%%%%%%%%%%%%%%

% needs protection, because of _p
\cs_new_protected:Npn \starray_def_prop:nnn #1#2#3
  {
    \__starray_if_exist:nTF {\l__starray_prefix_tl #1 _defref_tl}
      { \__starray_def_prop:nnn  {#1} {#2} {#3} }
      {
        \msg_warning:nnxxx {starray}{reference / invalid-starray} 
          {addprop:1} {#1} {cannot~add~property:#2}
      }
  }


% needs protection, because of _p
\prg_new_protected_conditional:Npnn \starray_def_prop:nnn #1#2#3 {T, F, TF}
  {
    \__starray_if_exist:nTF {\l__starray_prefix_tl #1 _defref_tl}
      {
        \__starray_def_prop:nnn  {#1} {#2} {#3}
        \prg_return_true:
      }
      { \prg_return_false: }
  }


%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%
%%%%
%%%% adding struct array #2 to a starray
%%%%
%%%%
%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%

% needs protection because of \seq_if...
\cs_new_protected:Npn \__starray_def_struct:nn #1#2
  {
    \seq_if_in:cnF {\l__starray_prefix_tl #1 _defstkeys_seq} {#2}
      {
        \seq_gput_right:cn 
          {\l__starray_prefix_tl #1 _defstkeys_seq} 
          {#2}
        \__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 addition' (after being instantiated?)

\cs_new_protected:Npn \__starray_fix_terms_seq_aux:nnnn #1#2#3#4
  {
    \__starray_if_exist:eTF {\l__starray_prefix_tl #2 _ #3 . #4 _base_defref_tl}
      {
       \__starray_fix_terms:nn {#1.#4}{#2_#3.#4}
      }
      {
       \__starray_base_new:ee {#1.#4}{#2_#3.#4}
      }
  }


\cs_new_protected:Npn \__starray_fix_terms_seq:nnnn #1#2#3#4
  {
    \tl_set_eq:Nc \l_tmpa_tl {\l__starray_prefix_tl #2 _base_defref_tl}
      
    \seq_map_inline:cn
      {\tl_use:N \l__starray_prefix_tl \tl_use:N \l_tmpa_tl _defstkeys_seq}
      {\__starray_fix_terms_seq_aux:nnnn {#1}{#2}{#4}{##1} }
  
  }


\cs_new_protected:Npn \__starray_fix_terms:nn #1#2
  {
    \group_begin:
      \prop_if_empty:cF {\tl_use:N \l__starray_prefix_tl #2 _base_idxhash_prop}
        {
          \prop_map_inline:cn
            {\tl_use:N \l__starray_prefix_tl #2 _base_idxhash_prop}
            {\__starray_fix_terms_seq:nnnn {#1}{#2}{##1}{##2} }
        }  
    \group_end:
  }

\cs_generate_variant:Nn \__starray_fix_terms:nn {ee}


\cs_new_protected:Npn \starray_fix_terms:n #1
  {
    \tl_set:Ne \l_tmpb_tl {\__starray_get_root:w #1 . \q_nil \q_stop}
  
    \__starray_if_exist:nTF { \l__starray_prefix_tl \l_tmpb_tl _defref_tl}
      {
        \__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_protected:Npn \starray_def_struct:nn #1#2
  {
    \__starray_if_exist:nTF { \l__starray_prefix_tl #1 _defref_tl}
      {
        \__starray_def_struct:nn  {#1} {#2}
      }
      {
        \msg_warning:nnxxx {starray}{reference / invalid-starray} 
          {addstruct:1} {#1} {cannot~add~structure:#2}
      }
  }


\prg_new_protected_conditional:Npnn \starray_def_struct:nn #1#2 {T, F, TF}
  {
    \__starray_if_exist:nTF { \l__starray_prefix_tl #1 _defref_tl}
      {
        \__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 { TF}
  {
    \str_compare:nNnTF {#1} = {struct}
      { \prg_return_true: }
      { \prg_return_false: }
  }

%
% This should be protected (\tl_set:Ne isn't expandable) but only the TF form matters.
%
\prg_new_conditional:Npnn \__starray_def_from_keyval_testdot:w  #1 . #2 \q_stop { TF}
  {
    \quark_if_nil:nTF {#2}
      {
        \prg_return_false:
      } % no dot, OK
      {
        \__starray_def_from_keyval_testdot_aux:wTF #2
          {
            \tl_set:Ne \l__starray_tmp_ST_tl { #1 }
            \prg_return_true:
          } % dot struct, OK
          {
            \prg_return_false:
          } %% possible syntax ERR (dot, but no struct!)
      }
  }


\cs_new_protected: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:Ne \l__starray_tmpA_tl {#1 . \l__starray_tmp_ST_tl}
          \__starray_def_struct:ne {#1} {\l__starray_tmp_ST_tl}
          \keyval_parse:nnn
            {\__starray_def_from_keyval_parse:en  {\tl_use:N \l__starray_tmpA_tl}}
            {\__starray_def_from_keyval_parse:enn {\tl_use:N \l__starray_tmpA_tl}}
            {#3}
        }
        {
          \__starray_def_prop:nnn {#1} {#2} {#3}
        }
    \group_end:
  }

\cs_generate_variant:Nn \__starray_def_from_keyval_parse:nnn {enn}


\cs_new_protected: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_protected:Npn \starray_def_from_keyval:nn #1#2
  {
    \__starray_if_exist:nTF { \l__starray_prefix_tl #1 _defref_tl}
      {
        \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_protected_conditional:Npnn \starray_def_from_keyval:nn #1#2 {T, F, TF}
  {
    \__starray_if_exist:nTF { \l__starray_prefix_tl #1 _defref_tl}
      {
        \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
%%%%
%%%%
%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%
%%%
%%% TODO: to add {_iter_from_hash} property {hash} -> iter (integer!)
%%%
%%%

\cs_new_protected:Npn \__starray_new_term:nn #1#2
  {
    \int_gincr:c {\l__starray_prefix_tl #1 _base_cnt_int}

    \int_gset_eq:cc
      {\l__starray_prefix_tl #1 _base_iter_int}
      {\l__starray_prefix_tl #1 _base_cnt_int}

    \tl_set:Ne \l__starray_tmp_A_tl
      { \int_to_Alph:e {\int_use:c {\l__starray_prefix_tl #1 _base_cnt_int} }  }

    \prop_put:cee {\l__starray_prefix_tl #1 _base_idxhash_prop}
      { \int_use:c {\l__starray_prefix_tl #1 _base_cnt_int} }
      { \l__starray_tmp_A_tl }

    \prop_put:cee {\l__starray_prefix_tl #1 _base_iterhash_prop}
      { \int_use:c {\l__starray_prefix_tl #1 _base_cnt_int} }
      { \int_use:c {\l__starray_prefix_tl #1 _base_cnt_int} }
  
    \tl_if_blank:nF {#2}
      {
        \prop_put:cee {\l__starray_prefix_tl #1 _base_idxhash_prop}
          { #2  }
          { \l__starray_tmp_A_tl  }

        \prop_put:cee {\l__starray_prefix_tl #1 _base_iterhash_prop}    
          { #2  }
          { \int_use:c {\l__starray_prefix_tl #1 _base_cnt_int} }  
      }

    \prop_new_linked:c
      { \l__starray_prefix_tl #1 _ \l__starray_tmp_A_tl _term_prop }

    \tl_set_eq:Nc \l_tmpb_tl {\l__starray_prefix_tl #1 _base_defref_tl}

    \prop_gset_eq:cc { \l__starray_prefix_tl #1 _ \l__starray_tmp_A_tl _term_prop } {\l__starray_prefix_tl \l_tmpb_tl _defkeys_prop}
    
    %\prop_make_linked:c { \l__starray_prefix_tl #1 _ \l__starray_tmp_A_tl _term_prop }

% map over 'all sub-starrays parts of def_ref -> st_seq (those starting with a dot, @st_seq)
    \seq_map_inline:cn
      {\l__starray_prefix_tl \l_tmpb_tl _defstkeys_seq}
      {
        \__starray_sub_base_new:nnn
          { \l_tmpb_tl }{ #1 _ \l__starray_tmp_A_tl } {##1}
      }

  }


%%%%%%%%%%%%%%%
%%%%
%%%% \starray_new_term
%%%%
%%%%%%%%%%%%%%%

\cs_new_protected: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_protected_conditional:Npnn \starray_new_term:nn #1#2 {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 over sub-structures)
%%%%
%%%% NOTE: since iterator change 'can' be just local, 'temp vars' are recursive aware.
%%%%
%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%

\cs_new_protected:Npn \__starray_incr_iter:n #1
  {
    \int_compare:nNnTF
      {\use:c {\l__starray_prefix_tl #1 _base_iter_int}} <
      {\use:c {\l__starray_prefix_tl #1 _base_cnt_int}}
      {
        \int_gincr:c {\l__starray_prefix_tl #1 _base_iter_int}
      }
      {
        % TODO: validade _rtn_bool for end user???
        \bool_set_false:N \l__starray_rtn_bool
      }
  }


\prg_new_protected_conditional:Npnn \__starray_set_iter:nn #1#2 {T , F , TF}
  {
    \int_compare:nNnTF {#1} > { \use:c {\l__starray_prefix_tl #2 _base_cnt_int} }
      {
        \int_gset_eq:cc
          {\l__starray_prefix_tl #2 _base_iter_int}
          {\l__starray_prefix_tl #2 _base_cnt_int}
        \prg_return_false:
      }
      {
        \int_gset:cn
          {\l__starray_prefix_tl #2 _base_iter_int}
          { #1 }
        \prg_return_true:
      }
  }


\prg_generate_conditional_variant:Nnn \__starray_set_iter:nn {ne} {T , F , TF}


\cs_new_protected:Npn \__starray_set_sub_iter:nnn #1#2#3
  {
    \prop_get:cecT {\l__starray_prefix_tl #2#3 _base_idxhash_prop}
      { \int_use:c {\l__starray_prefix_tl #2#3 _base_iter_int } }
      { l__starray_tmp #1 A_tl }
      {
    \tl_set_eq:Nc \l__starray_tmp_C_tl {\l__starray_prefix_tl #2#3 _base_defref_tl}
          
        \seq_if_empty:cF {\l__starray_prefix_tl \l__starray_tmp_C_tl  _defstkeys_seq}
          {
            \seq_map_inline:cn
              {\l__starray_prefix_tl \l__starray_tmp_C_tl  _defstkeys_seq}
              {
                \__starray_set_iter:neTF 
                  { 1 }
                  { #2#3 _ \tl_use:c {l__starray_tmp #1 A_tl} . ##1 }
                  {}
                  {}
  
                \__starray_set_sub_iter:nne
                  { #1 A }
                  { #2#3 _ \tl_use:c {l__starray_tmp #1 A_tl} . }
                  { ##1 }
              }
          }
      }
  }

\cs_generate_variant:Nn \__starray_set_sub_iter:nnn {nne}


%%%%%%%%%%%%%%%
%%%%
%%%% \starray_set_iter
%%%%
%%%%%%%%%%%%%%%
\prg_new_protected_conditional:Npnn \__starray_set_iter_from_hash:nn #1#2 {T , F, TF}
  {
    \prop_get:cnNTF {\l__starray_prefix_tl #1 _base_iterhash_prop} {#2} \l_tmpa_tl
      {
        \int_gset:cn
          { \l__starray_prefix_tl #1 _base_iter_int }
          { \l_tmpa_tl }
        \prg_return_true:
      }
      {
        \prg_return_false:
      }    
  }


\cs_new_protected:Npn \starray_set_iter_from_hash:nn #1#2
  {
    \__starray_parser:nnTF {\c__starray_no_idx_ending_bool}{#1}
      {
        \__starray_set_iter_from_hash:nnTF {\l__starray_parsed_ref_tl}{#2}
          {
            \__starray_set_sub_iter:nnn {}{\l__starray_parsed_ref_tl}{}        
          }
          {
            \msg_warning:nnnn {starray} {reference /  iter} {iterhash:1} {#1}{#2}            
          }
      }
      {
        \__starray_msg_dispatch:
        \msg_warning:nnnn {starray} {syntax /  iter} {iter:1} {#1}
      } % returns nothing by default
  }


\prg_new_protected_conditional:Npnn \starray_set_iter_from_hash:nn #1#2 {T, F, TF}
  {
    \bool_set_true:N \l__starray_rtn_bool

    \__starray_parser:nnTF {\c__starray_no_idx_ending_bool}{#1}
      {
        \__starray_set_iter_from_hash:nnTF {\l__starray_parsed_ref_tl}{#2}
          {
            \__starray_set_sub_iter:nnn {}{\l__starray_parsed_ref_tl}{}        
            \prg_return_true:
          }
          {
            \bool_set_false:N \l__starray_rtn_bool
            \prg_return_false:
          }
      }
      {
        \bool_set_false:N \l__starray_rtn_bool
        \seq_clear:N \l__starray_msg_seq
        \prg_return_false:
      } % returns nothing by default
  }


\cs_new_protected: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_protected_conditional:Npnn \starray_set_iter:nn #1#2 {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:}
      }
      { 
        \bool_set_false:N \l__starray_rtn_bool
        \seq_clear:N \l__starray_msg_seq
        \prg_return_false: 
      }
  }


%%%%%%%%%%%%%%%
%%%%
%%%% \starray_reset_iter
%%%%
%%%%%%%%%%%%%%%

\cs_new_protected: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_protected_conditional:Npnn \starray_reset_iter:n #1 {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_protected: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_protected_conditional:Npnn \starray_next_iter:n #1 {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:}
      }
      { 
        \bool_set_false:N \l__starray_rtn_bool
        \prg_return_false: 
      }
  }


%%%%%%%%%%%%%%%
%%%%
%%%% \starray_iterate_over
%%%%
%%%%%%%%%%%%%%%
\bool_new:N \l__starray_iterate_bool

\cs_new_protected:Npn \starray_iterate_over:nn #1#2
  {    
    \bool_if_exist:cF {l__starray_iterate_ #1 _bool}
      { \bool_new:c   {l__starray_iterate_ #1 _bool} }
    \starray_reset_iter:nTF {#1}
      {
        \bool_gset_true:c {l__starray_iterate_ #1 _bool}
        \bool_do_while:cn {l__starray_iterate_ #1 _bool}
        {        
          #2 
          \starray_next_iter:nTF {#1}
            { \bool_gset_true:c  {l__starray_iterate_ #1 _bool} }
            { \bool_gset_false:c {l__starray_iterate_ #1 _bool} }
        }
      }
      {
        \bool_set_false:N \l__starray_rtn_bool
        \msg_warning:nnnn {starray} {syntax /  iter} {iter:6} {#1}
      }     
  }


\prg_new_protected_conditional:Npnn \starray_iterate_over:nn #1#2 {T, F, TF}
  {
    \bool_if_exist:cF {l__starray_iterate_#1_bool}
      {\bool_new:c {l__starray_iterate_#1_bool}}
    \starray_reset_iter:nTF {#1}
      {
        \bool_gset_true:c {l__starray_iterate_#1_bool}
        \bool_do_while:cn {l__starray_iterate_#1_bool}
        {
          #2
          \starray_next_iter:nF {#1}
            %{\bool_gset_true:c {l__starray_iterate_#1_bool}}
            {\bool_gset_false:c {l__starray_iterate_#1_bool}}
        }
        \prg_return_true:
      }
      {
        \seq_clear:N \l__starray_msg_seq
        \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_protected: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
  }
  
  
%%%%%%%%%%%%%%%%
%%%
%%% WARNING: This uses the 'last parsed term'.
%%%
%%%%%%%%%%%%%%%%  
\cs_new:Npn \starray_parsed_get_prop:n #1
  {
    \__starray_get_prop:ee {\l__starray_parsed_ref_tl}{#1}
  }  


%%%%%%%%%%%%%%%%
%%%
%%% WARNING: #1 should be \l__starray_parsed_ref_tl
%%%          #2 should be \l__starray_parsed_ref_no_idx_ending_tl
%%%         
%%%%%%%%%%%%%%%%
\cs_new:Npn \starray_parsed_get_prop:NNn #1#2#3
  {
    \__starray_get_prop:ee {#1}{#3}
  }  


\cs_new_protected: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:2} {#1}
      } % returns nothing by default
  }


\prg_new_protected_conditional:Npnn \starray_get_prop:nnN #1#2#3 {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_protected_conditional:Npnn \starray_if_in:nn #1#2 {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
  }

%%%%%%%%%%%%%%%%
%%%
%%% WARNING: This uses the 'last parsed term'.
%%%
%%%%%%%%%%%%%%%%
\prg_new_conditional:Npnn \starray_parsed_if_in:n #1 {p, T, F, TF}
  {
    \prop_if_in:cnTF 
      { \l__starray_prefix_tl \l__starray_parsed_ref_tl _term_prop } 
      {#1}
      { \prg_return_true: }
      { \prg_return_false: }
  }

%%%%%%%%%%%%%%%%
%%%
%%% WARNING: #1 should be \l__starray_parsed_ref_tl
%%%          #2 should be \l__starray_parsed_ref_no_idx_ending_tl
%%%         
%%%%%%%%%%%%%%%%
\prg_new_conditional:Npnn \starray_parsed_if_in:NNn #1#2#3 {p, T, F, TF}
  {
    \prop_if_in:cnTF 
      { \l__starray_prefix_tl #1 _term_prop } 
      {#3}
      { \prg_return_true: }
      { \prg_return_false: }
  }


\cs_new_protected:Npn \starray_get_cnt:n #1
  {
    \__starray_parser:nnTF {\c__starray_no_idx_ending_bool}{#1}
      {
        \int_use:c { \l__starray_prefix_tl \l__starray_parsed_ref_tl _base_cnt_int }
      }
      {
        \__starray_msg_dispatch:
        \msg_warning:nnnn {starray} {syntax /  prop} {get:3} {#1}
      } % returns nothing by default
  }


%%%%%%%%%%%%%%%%
%%%
%%% WARNING: This uses the 'last parsed term'.
%%%         It will leave cnt directly in the input stream
%%%%%%%%%%%%%%%%

\cs_new:Npn \starray_parsed_get_cnt:
  {
    \int_use:c { \l__starray_prefix_tl \l__starray_parsed_ref_no_idx_ending_tl _base_cnt_int }
  }
   
%%%%%%%%%%%%%%%%
%%%
%%% WARNING: #1 should be \l__starray_parsed_ref_tl
%%%          #2 should be \l__starray_parsed_ref_no_idx_ending_tl
%%%         
%%%%%%%%%%%%%%%%

\cs_new:Npn \starray_parsed_get_cnt:NN #1#2
  {
    \int_use:c { \l__starray_prefix_tl #2 _base_cnt_int }
  }


\cs_new_protected:Npn \starray_get_cnt:nN #1#2
  {
    \__starray_parser:nnTF {\c__starray_no_idx_ending_bool}{#1}
      {
        \int_set_eq:Nc
          #2 
          { \l__starray_prefix_tl \l__starray_parsed_ref_tl _base_cnt_int }
      }
      {
        \__starray_msg_dispatch:
        \msg_warning:nnnn {starray} {syntax /  prop} 
          {get:4} {#1}
      } % returns nothing by default
  }


\prg_new_protected_conditional:Npnn \starray_get_cnt:nN #1#2  {T, F, TF}
  {
    \__starray_parser:nnTF {\c__starray_no_idx_ending_bool}{#1}
      {
        \int_set_eq:Nc
          #2 
          { \l__starray_prefix_tl \l__starray_parsed_ref_tl _base_cnt_int } 
        \prg_return_true:
      }
    {
      \seq_clear:N \l__starray_msg_seq
      \prg_return_false:
    } % returns nothing by default
  }


\cs_new_protected:Npn \starray_get_iter:n #1
  {
    \__starray_parser:nnTF {\c__starray_no_idx_ending_bool}{#1}
      {
        \int_use:c { \l__starray_prefix_tl \l__starray_parsed_ref_tl _base_iter_int }
      }
      {
        \__starray_msg_dispatch:
        \msg_warning:nnnn {starray} {syntax /  prop} 
          {get:5} {#1}
      } % returns nothing by default
  }


%%%%%%%%%%%%%%%%
%%%
%%% WARNING: This uses the 'last parsed term'.
%%%         It will leave current iter directly in the input stream
%%%%%%%%%%%%%%%%

\cs_new:Npn \starray_parsed_get_iter:
  {
    \int_use:c
      { \l__starray_prefix_tl \l__starray_parsed_ref_no_idx_ending_tl _base_iter_int }
  }


%%%%%%%%%%%%%%%%
%%%
%%% WARNING: #1 should be \l__starray_parsed_ref_tl
%%%          #2 should be \l__starray_parsed_ref_no_idx_ending_tl
%%%         
%%%%%%%%%%%%%%%%

\cs_new:Npn \starray_parsed_get_iter:NN #1#2
  {
    \int_use:c
      { \l__starray_prefix_tl #2 _base_iter_int }
  }


\cs_new_protected:Npn \starray_get_iter:nN #1#2
  {
    \__starray_parser:nnTF {\c__starray_no_idx_ending_bool}{#1}
    {
      \int_set_eq:Nc
        #2 
        { \l__starray_prefix_tl \l__starray_parsed_ref_tl _base_iter_int }
    }
    {
      \__starray_msg_dispatch:
      \msg_warning:nnnn {starray} {syntax /  prop} 
        {get:6} {#1}
    } % returns nothing by default
  }


\prg_new_protected_conditional:Npnn \starray_get_iter:nN #1#2 {T, F, TF}
  {
    \__starray_parser:nnTF {\c__starray_no_idx_ending_bool}{#1}
    {
      \int_set_eq:Nc
        #2 
        { \l__starray_prefix_tl \l__starray_parsed_ref_tl _base_iter_int }
      \prg_return_true:
    }
    {
      \seq_clear:N \l__starray_msg_seq
      \prg_return_false:
    } % returns nothing by default
  }


\cs_new_protected:Npn \starray_get_unique_id:nN #1#2
  {
    \__starray_parser:nnTF {\c__starray_no_idx_ending_bool}{#1}
    {
      \int_set_eq:Ne
        #2 
        { \l__starray_parsed_ref_tl }
    }
    {
      \__starray_msg_dispatch:
      \msg_warning:nnnn {starray} {syntax /  prop} 
        {get:7} {#1}
    } % returns nothing by default
  }


\prg_new_protected_conditional:Npnn \starray_get_unique_id:nN #1#2 {T, F, TF}
  {
    \__starray_parser:nnTF {\c__starray_idx_ending_bool}{#1}
    {
      \tl_set:Ne 
        #2 
        { \l__starray_parsed_ref_tl }
      \prg_return_true:
    }
    {
      \seq_clear:N \l__starray_msg_seq
      \prg_return_false:
    } % returns nothing by default
  }


\cs_new_protected: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_protected: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_protected: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_protected_conditional:Npnn \starray_set_prop:nnn #1#2#3 {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 } {T, F , TF } %%%


\prg_new_protected_conditional:Npnn \starray_gset_prop:nnn #1#2#3 {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 } {T, F , TF }


%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%
%%%%
%%%% set/get properties (keyval)
%%%%
%%%%
%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%

%
% Not expandable. DO NOT generate a predicate version! 
% but, already a :w conditional anyway (internal)
%
\prg_new_conditional:Npnn \__starray_set_parse_end:w  #1#2 ] #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:
      }
  }


%
% Not expandable. DO NOT generate a predicate version! 
% but, already a :w conditional anyway (internal)
%
\prg_new_conditional:Npnn \__starray_set_parse_aux:w  #1#2 [ \q_nil \q_stop { TF}
  {
    \__starray_set_parse_end:wTF  {#1}#2 ] \q_nil\q_stop
      {\prg_return_true:}
      {\prg_return_false:}
  }


%
% Not expandable. DO NOT generate a predicate version! 
% but, already a :w conditional anyway (internal)
%
\prg_new_conditional:Npnn \__starray_set_parse_begin:w #1#2 [ #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 {neen}

%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%
%%%%
%%%% set from keyval
%%%%
%%%% NOTE: tmp variables are recursive aware.
%%%%
%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%

%%% what a mess. :(
%%% #1 => tmp series A, AA, AAA
%%% #2 => no_idx_ending ref 
%%% #3 => idx_ending ref !!!
%%% #4 => prop/struct(key from keyval)
%%% #5 => val/keyval (val from keyval)
%%%
\cs_new:Npn \__starray_set_from_keyval_parse:nnnnn #1#2#3#4#5
  {
    \tl_clear_new: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}}
          {
          %
          % what should be here: 
          %  get #2_base_prop -> _def_prop -> @st_seq
          % _base_prop comes from (parser) _no_idx_ending_tl
          %
          % from there #3.<#4> => {}{...} 'next #2'
          %    #3.<#4>_[<#4>] (idx construct from #4) 'next #3'
          %

            \seq_if_in:cnTF 
              {\tl_use:N \l__starray_prefix_tl \tl_use:c {\l__starray_prefix_tl #2 _base_defref_tl} _defstkeys_seq} 
              {#4}
              { 
                \int_compare:nNnTF {\int_use:c { \tl_use:N \l__starray_prefix_tl #3 .#4 _base_iter_int }} < {1}
                  {
                    \__starray_msg:nnnnn {reference / iter}
                      {setkeyval:2}{#2.#4}{-0-}{~(not~instantiated)}
                    % invalid iter / not instantiated
                  }
                  {
    %%%% WARNING: is't sure it does exist? will result in a quark loop if not!
                    \prop_get:cec
                      { \tl_use:N \l__starray_prefix_tl #3 .#4 _base_idxhash_prop }
                      {\int_use:c { \tl_use:N \l__starray_prefix_tl #3 .#4 _base_iter_int }}
                      { l__starray_tmp #1 _tl }

                    \keyval_parse:nnn
                      {
                        \__starray_set_from_keyval_parse:neen
                          { #1 A }
                          { #3.#4 }
                          {  #3.#4 _ \tl_use:c { l__starray_tmp #1 _tl } }
                      }
                      {
                        \__starray_set_from_keyval_parse:neenn
                          { #1 A }
                          { #3.#4 }
                          {  #3.#4 _ \tl_use:c { l__starray_tmp #1 _tl } }
                      }
                      { #5 }

                  }
              }
              {
                \__starray_set_prop:nnn {#3}{#4}{#5}
              }
          }
          {          
            \seq_if_in:ceTF 
              {\tl_use:N \l__starray_prefix_tl \tl_use:c {\l__starray_prefix_tl #2 _base_defref_tl} _defstkeys_seq}
              { \tl_use:c{l__starray_tmp #1 :B_tl} }
              {
                \prop_get:ceNTF
                  { \l__starray_prefix_tl #3. \tl_use:c{l__starray_tmp #1 :B_tl} _base_idxhash_prop }
                  { \tl_use:c{l__starray_tmp #1 :A_tl}}
                  \l__starray_tmp_D_tl
                  {
                    %% here should be all the remaining code. 'everything fine so far'.
                    \tl_set:ce
                      { l__starray_tmp #1 _idx_tl }
                      {
                        #3 . \tl_use:c{l__starray_tmp #1 :B_tl} _
                          \tl_use:N \l__starray_tmp_D_tl
                      }
                    \tl_put_left:cn { l__starray_tmp #1 :B_tl } { #3 . }

                    \keyval_parse:nnn
                      {
                        \__starray_set_from_keyval_parse:neen
                        { #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:neenn
                        { #1 A }
                        { \tl_use:c{l__starray_tmp #1 :B_tl} }
                        { \tl_use:c { l__starray_tmp #1 _idx_tl } }
                      }
                      { #5 }
                                    
                  }
                  {
                    %% if we got here, it doesn't exist. wrong idx, 
                    \__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 {neenn}


%%%%%%%%%%%%%%%
%%%%
%%%% \starray_set_from_keyval
%%%%
%%%%%%%%%%%%%%%

\tl_new:N \l__starray_from_keyval_orgref_tl

\cs_new_protected:Npn \__starray_set_from_keyval:nn #1#2
  {
    \bool_set_true:N \l__starray_rtn_bool
    
    %%% just in case, for msg_err messages
    \tl_set:Nn \l__starray_from_keyval_orgref_tl {#1}
    
    \__starray_parser:nnTF {\c__starray_idx_ending_bool}{#1}
    {
      \keyval_parse:nnn
        {\__starray_set_from_keyval_parse:neen  {A}{\l__starray_parsed_ref_no_idx_ending_tl}{\l__starray_parsed_ref_tl}}
        {\__starray_set_from_keyval_parse:neenn {A}{\l__starray_parsed_ref_no_idx_ending_tl}{\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_protected: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_protected: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}
  }


%%%
%%% small surprise, it was possible to _protected it... TODO: further test it.
%%%
\cs_new_protected:Npn \__starray_set_from_keyvalTF:nn #1#2
  {
    \bool_set_true:N \l__starray_rtn_bool
    
    %%% just in case, for msg_err messages
    \tl_set:Nn \l__starray_from_keyval_orgref_tl {#1}
    
    \__starray_parser:nnTF {\c__starray_idx_ending_bool}{#1}
      {
        \keyval_parse:nnn
          {\__starray_set_from_keyval_parse:neen  {A}{\l__starray_parsed_ref_no_idx_ending_tl}{\l__starray_parsed_ref_tl}}
          {\__starray_set_from_keyval_parse:neenn {A}{\l__starray_parsed_ref_no_idx_ending_tl}{\l__starray_parsed_ref_tl}}
          { #2 }
        \bool_if:NTF \l__starray_rtn_bool
          {\prg_return_true:}
          {\prg_return_false:}
      }
      { \prg_return_false: }
  }
  
  
\prg_new_protected_conditional:Npnn \starray_set_from_keyval:nn #1#2 {T, F, TF}
  {
    \tl_set:Nn \l__starray_put_tl \prop_put:cnn
    \__starray_set_from_keyvalTF:nn {#1}{#2}
  }
  
  
\prg_new_protected_conditional:Npnn \starray_gset_from_keyval:nn #1#2 {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> \]
%%%%
%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%

%%%
%%% \tl_set: isn't expandable... but (internal) and only the TF variant is needed.
%%% :w macro anyway...
%%%
\prg_new_conditional:Npnn \__starray_term_parse_end:w  #1 ] #2 \q_stop { TF}
  {
    \quark_if_nil:nTF {#2}
      { \prg_return_false: } %% syntax ERR
      {
        \tl_set:Nn \l__starray_parsed_idx_tl {#1}
        \prg_return_true:
      }
  }


%%%
%%% \tl_set: isn't expandable (see above)... but (internal) and only the TF variant is needed.
%%% :w macro anyway...
%%%
\prg_new_conditional:Npnn \__starray_term_parse_aux:w  #1 [ \q_nil \q_stop { TF}
  {
    \__starray_term_parse_end:wTF  #1 ] \q_nil\q_stop
      {\prg_return_true:}
      {\prg_return_false:}
  }


%%%
%%% \tl_set: isn't expandable (see above)... but (internal) and only the TF variant is needed.
%%% :w macro anyway...
%%%
\prg_new_conditional:Npnn \__starray_term_parse_begin:w #1 [ #2 \q_stop { TF}
  {
    \tl_set:Nn \l__starray_parsed_term_tl {#1}

    \quark_if_nil:nTF {#2}
      {               % no 'term' ref, just array_name (current/iter term)
        \tl_clear:N \l__starray_parsed_idx_tl
        \prg_return_true:
      }
      {
        \__starray_term_parse_aux:wTF #2 \q_stop
          {\prg_return_true:}
          {\prg_return_false:}
      }
  }


%  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_protected_conditional:Npnn \__starray_if_valid_idx:nn #1#2 {T, F, TF}
  {
    \tl_if_blank:nTF {#2}
      {
        \prop_get:ceNF {\l__starray_prefix_tl \l__starray_parsed_ref_tl _base_idxhash_prop} {#1} \l_tmpa_tl
          { \tl_set:Nn \l_tmpa_tl {} }
      }
      {
        \prop_get:ceNF {\l__starray_prefix_tl \l__starray_parsed_ref_tl _base_idxhash_prop} {#2} \l_tmpa_tl
          { \tl_set:Nn \l_tmpa_tl {} }
      }
    \tl_put_right:Ne \l__starray_parsed_ref_tl { _ \l_tmpa_tl }


    \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} {T, F, TF}


%%%
%%% small surprise, it was possible to _protected this... TODO: further test it.
%%%
\cs_new_protected: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_exist:eTF 
          {\l__starray_prefix_tl \l__starray_parsed_ref_tl _base_defref_tl}
          {
            \quark_if_nil:nTF {#2}
            {       % this is the last one
              \tl_set:Ne 
                \l__starray_parsed_ref_no_idx_ending_tl 
                {\l__starray_parsed_ref_tl}
              \bool_if:NTF \l__starray_parser_no_idx_ending_bool
              {                                  % assuming it is to add a term...
                \tl_if_empty:NTF \l__starray_parsed_idx_tl
                { }       % done. correct
                {
                  \bool_set_false:N \l__starray_parser_OK_bool
                  \__starray_msg: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:c
                        { \l__starray_prefix_tl \l__starray_parsed_ref_tl _base_iter_int }
                  }
                  {
                    \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:c
                      { \l__starray_prefix_tl \l__starray_parsed_ref_tl _base_iter_int }
                }
                {
                  \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_ref_no_idx_ending_tl
%%%%                       \l__starray_parsed_base_ref_tl
%%%%                       \l__starray_parsed_root_ref_tl
%%%% parser 'false' returns:
%%%%                       
%%%%
%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%

\prg_new_protected_conditional:Npnn \__starray_parser:nn #1#2 {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_ref_no_idx_ending_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_protected_conditional:Npnn \starray_term_syntax:n #1 {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:
      }
  }
  
  
\prg_new_protected_conditional:Npnn \starray_term_syntax:nNN #1#2#3 {T, F, TF}
  {
    \__starray_parser:nnTF {\c__starray_idx_ending_bool}{#1}
      {
        \tl_gset:Ne #2 {\l__starray_parsed_ref_tl}
        \tl_gset:Ne #3 {\l__starray_parsed_ref_no_idx_ending_tl}
        \prg_return_true:
      }
      {
        \seq_clear:N \l__starray_msg_seq
        \prg_return_false:
      }  
  }  


\cs_new_protected:Npn \starray_term_syntax:n #1
  {
    \__starray_parser:nnTF {\c__starray_idx_ending_bool}{#1}
      {}
      {
        \__starray_msg_dispatch:
        \msg_warning:nnnn {starray} {syntax /  prop} 
          {setkeyval:1} {#1}
      }  
  }  


\cs_new_protected:Npn \starray_term_syntax:nNN #1#2#3
  {
    \__starray_parser:nnTF {\c__starray_idx_ending_bool}{#1}
      {
        \tl_gset:Ne #2 {\l__starray_parsed_ref_tl}
        \tl_gset:Ne #3 {\l__starray_parsed_ref_no_idx_ending_tl}
      }
      {
        \__starray_msg_dispatch:
        \msg_warning:nnnn {starray} {syntax /  prop} 
          {setkeyval:1} {#1}
      }  
  }  



%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%
%%%%
%%%% \..show_def commands
%%%%
%%%%
%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%
%%%%
%%%% Note to self: 
%%%% \l__starray_showcmd_tl could be an extra param as well
%%%% (more tokens jungling around...)
%%%%
%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%


\cs_new_protected:Npn \__starray_show_def_item:nnn #1#2#3
  {
    \tl_gput_right:Nn \l__starray_tmp_B_tl
    {
      \l__starray_showcmd_tl > #1 \use:nnn { ~ } { ~ } { ~ }
      \tl_to_str:n { {#2} }
      \use:nn { ~ } { ~ } => \use:nn { ~ } { ~ }
      \tl_to_str:n { {#3} }
    }
  }


\cs_new_protected:Npn \__starray_show_def:nnn #1#2#3
  {
    \group_begin:
      \tl_gput_right:Nn \l__starray_tmp_B_tl
      {
        \l__starray_showcmd_tl > #1
        \tl_to_str:n {{#3} ~ struct}
        \use:nn { ~ } { ~ } =>
      }
    
      \prop_map_inline:cn 
        {\l__starray_prefix_tl #2#3 _defkeys_prop} 
        {\__starray_show_def_item:nnn {#1} {##1} {##2} }

      \seq_if_empty:cF { \l__starray_prefix_tl #2#3 _defstkeys_seq}
        {
          \seq_map_inline:cn
          { \l__starray_prefix_tl #2#3 _defstkeys_seq}
          { \__starray_show_def:nnn  { #1 \use:nnn { ~ } { ~ } { ~ }} { #2#3. } {##1} }
        }
    \group_end:
  }

%%%%%%%%%%%%%%%
%%%%
%%%% \starray_show_def
%%%%
%%%%%%%%%%%%%%%

\cs_new_protected:Npn \starray_show_def:n #1
  {
    \tl_clear:N \l__starray_tmp_B_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_tmp_B_tl }
  }


\cs_new_protected:Npn \starray_show_def_in_text:n #1
  {
    \tl_clear:N \l__starray_tmp_B_tl
    \tl_set:Nn \l__starray_showcmd_tl \par
    \__starray_show_def:nnn {}{}{#1}
  
    \tl_use:N \l__starray_tmp_B_tl
  }



%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%
%%%%
%%%% \..show_terms commands
%%%%
%%%%
%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%
%%%%
%%%% Note to self: 
%%%% \l__starray_showcmd_tl could be an extra param as well
%%%% (more tokens jungling around...)
%%%%
%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%

\cs_new_protected:Npn \__starray_show_term_item:nnnnn #1#2#3#4#5
  {
    \group_begin:
      \tl_gput_right:Nn \l__starray_tmp_B_tl
        {
          \l__starray_showcmd_tl > #1
          \tl_to_str:n { {#3[#4]} ~ (idx: ~ #5)}
          \use:nn { ~ } { ~ } =>
        }
  
      \prop_map_inline:cn 
        {\l__starray_prefix_tl #2 #3 _ #5 _term_prop} 
        {\__starray_show_def_item:nnn {#1 } {##1}{##2}}
  
    \tl_set_eq:Nc \l_tmpa_tl {\l__starray_prefix_tl #2#3 _base_defref_tl}
         
      \seq_if_empty:cTF { \l__starray_prefix_tl \l_tmpa_tl _defstkeys_seq }
        {}
        {
          \seq_map_inline:cn
            { \l__starray_prefix_tl \l_tmpa_tl _defstkeys_seq }
            { \__starray_show_terms:nen { #1 \use:nnn { ~ } { ~ } { ~ }} { #2  #3_#5. } {##1} }
        }       
    \group_end:
  }


\cs_new_protected:Npn \__starray_show_terms:nnn #1#2#3
  {
    \group_begin:
      \prop_map_inline:cn
        {\l__starray_prefix_tl #2 #3 _base_idxhash_prop}
        {\__starray_show_term_item:nnnnn {#1}{#2}{#3}{##1}{##2}}
    \group_end:
  }

\cs_generate_variant:Nn \__starray_show_terms:nnn {nen}


%%%%%%%%%%%%%%%
%%%%
%%%% \starray_show_terms
%%%%
%%%%%%%%%%%%%%%

\cs_new_protected:Npn \starray_show_terms:n #1
  {
    \tl_clear:N \l__starray_tmp_B_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_tmp_B_tl }
  }


\cs_new_protected:Npn \starray_show_terms_in_text:n #1
  {
    \tl_clear:N \l__starray_tmp_B_tl
    \tl_set:Nn \l__starray_showcmd_tl \par
    \__starray_show_terms:nnn {}{}{#1}
  
     \tl_use:N \l__starray_tmp_B_tl
  }