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

%%%%%%%
%%%
%%% Just an attempt at having my package's info in a regular way
%%%   \pkginfograb_set:nn {<pkg-name>} { props} sets package info
%%%
%%%   \pkginfograbProvidesExplPackage {<pkg-name>} { props} sets package info
%%%     and calls \ProvidesExplPackage
%%%
%%%%%%%
\RequirePackage{pkginfograb}
\pkginfograbProvidesExplPackage {starray}
  {
     name        = {starray} ,
     prefix      = {starray} ,
     date        = {2026/02/24},
     version     = {2.1} ,
     description = {A NEW structured array/hash of properties}
  }
%%%%%%%
%%% End of cut-n-paste
%%%%%%%



%%%%%%%%%%%%%%%%%%%
%%%%
%%%%  New package
%%%%
%%%%%%%%%%%%%%%%%%%

\bool_new:N \l__starray_NNnames_bool
\bool_new:N \l__starray_NNnames_warn_bool

\keys_define:nn { starray }
  {
%    prefix .tl_set:N          =  g__starray_prfix_  ,
%    prefix .value_required:n  = true ,
%    prefix .initial:n         = l__starray_ ,
%    prefix .usage:n           = load ,
  
    NN~names . usage:n = load ,
    NN~names .choice: ,
    NN~names / none .code:n = 
      { 
        \bool_set_false:N \l__starray_NNnames_bool
      },
    NN~names / no~warnings .code:n = 
      {
        \bool_set_true:N \l__starray_NNnames_bool
        \bool_set_false:N \l__starray_NNnames_warn_bool      
      } ,
    NN~names / strict .code:n = 
      {
        \bool_set_true:N \l__starray_NNnames_bool
        \bool_set_true:N \l__starray_NNnames_warn_bool      
      } ,

    íter~cascade .usage:n = load ,
    iter~cascade .bool_set:N = \l__starray_cascade_bool ,
    iter~cascade .value_forbidden:n = true ,

    msg-err .usage:n = load ,
    msg-err .choice: ,
    msg-err / none .code:n = { },
    msg-err / default .code:n = {} ,
    msg-err / strict .code:n = 
      {
        \msg_redirect_module:nnn { starray / strict } { warning } { error }
      } ,
    msg-err / syntax .code:n = 
      {
        \msg_redirect_module:nnn { starray / strict } { warning } { error }
        \msg_redirect_module:nnn { starray / syntax } { warning } { error }
      } ,
    msg-err / reference .code:n = 
      {
        \msg_redirect_module:nnn { starray / strict } { warning } { error }
        \msg_redirect_module:nnn { starray / syntax } { warning } { error }
        \msg_redirect_module:nnn { starray / reference } { warning } { error }
      } ,
    msg-err / all .code:n = 
      {
        \msg_redirect_module:nnn { starray } { warning } { error } 
      } ,
  
    msg-supress .usage:n = load ,
    msg-supress .choice: ,
    msg-supress / none .code:n = {} ,
    msg-supress / reference .code:n = 
      {
        \msg_redirect_module:nnn { starray / reference } { warning } { none }
      } ,
    msg-supress / syntax .code:n = 
      {
        \msg_redirect_module:nnn { starray / strict } { warning } { none }
        \msg_redirect_module:nnn { starray / syntax } { warning } { none }
      } ,
    msg-supress / strict .code:n = 
      {
        \msg_redirect_module:nnn { starray / strict } { warning } { none }
        \msg_redirect_module:nnn { starray / syntax } { warning } { none }
        \msg_redirect_module:nnn { starray / reference } { warning } { none }
      } ,
    msg-supress / all .code:n = 
      {
        \msg_redirect_module:nnn { starray } { warning } { none } 
      } ,
    
    parsed~ check .usage:n = load ,
    parsed~ check .bool_set:N = \l__starray_parsed_check_bool ,
    parsed~ check .value_forbidden:n = true ,
  
  }

\ProcessKeyOptions [ starray ]

%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%
%%%%
%%%% New variants of core expl3 primitives
%%%% expansion handling
%%%%
%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%
\cs_generate_variant:Nn \keyval_parse:nnn {ee}
\cs_generate_variant:Nn \prg_new_conditional:Nnn { c }
\cs_generate_variant:Nn \prg_new_conditional:Npnn {c}
    %% This is just for debugging. Otherwise, not needed
\cs_generate_variant:Nn \tl_show:n {e}


%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%
%%%%
%%%% Package error/warning messages
%%%% #1 'ID' (code identifier)
%%%% #2 / #3 / #4  further fields (as needed)
%%%%
%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%

\msg_new:nnnn {starray} {strict / Expl}
  {
    Expl~ version~ too~ old.~ Update~ needed!
  }
  {
    Expl~ version~ too~ old.~ Update~ needed!
  }

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

\msg_new:nnnn {starray} {strict / not defined}
  {
    (#1)~'#2'~isn't~defined!
  }
  {
    You~tried~to~use~a~non~defined~'#2'.
    ~Error~Code: (#1).
  }

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

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

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

\msg_new:nnnn {starray} {syntax /  parsed}
  {
    (#1)~Can't~ call~ #2~ after~a~ failed~ \starray_term_parser:
  }
  {
    You~ called~ #2~ after~ a~ failed~ call~ to~ \starray_term_parser:
    ~Error~ Code: (#1).
  }
  

\msg_new:nnnn {starray} {syntax /  structure-ref}
  {
    (#1)~'#3'~isn't~a~sub-structure~of~'#2'.
  }
  {
    '#2' ~doesn't~have~a~sub-structure~named:~'#3'.
    ~Error~ Code: (#1).
  }

\msg_new:nnnn {starray} {syntax /  iter}
  {
    (#1)~cannot~set~iter. ~invalid~'#2'. 
  }
  {
    cannot~set~iter.~ invalid '#2'.
    ~Error~ Code: (#1).
  }


\msg_new:nnnn {starray} {syntax /  prop}
  {
    (#1)~cannot~get/set~property~from~'#2'.
  }
  {
    You~have~referenced~an~invalid~structure~'#2'.
    ~Error~ Code: (#1).
  }


\msg_new:nnnn {starray} {reference /  keyval}
  {
    (#1)~key~'#2'~ignored.
  }
  {
    You~referenced~a~key~without~setting~it's~value. ~Key~ignored.
  }

\msg_new:nnnn {starray} {reference / invalid-starray}  %%%$$
  {
    (#1)~'#2'~invalid~starray.
    \tl_if_blank:nTF {#3}
      {~#3}
      {}
  }
  {
    '#2'~isn't~a~starray.
    \tl_if_blank:nTF {#3}
      {~#3}
      {}
    ~Error~ Code: (#1).
  }

\msg_new:nnnn {starray} {reference / iter}
  {
    (#1)~invalid~iter~(#3)~from~'#2'
    \str_if_empty:nTF {#4}
      {}
      {#4}
    .
  }
  {
    Invalid~iter~(#3)~from~ '#2'.~You~might~have~tried~to~use/set/reset~an~iter~of
    ~an~ill~instantiated~structured.
    ~Error~ Code: (#1).
  }

\msg_new:nnnn {starray} {reference / prop} %%%$$
  {
    (#1)~cannot~get/set~property~'#3'~from~'#2'.
  }
  {
    '#3'~isn't~a~property~of~'#2'.
    ~Error~ Code: (#1).
  }

\msg_new:nnnn {starray} {info / show}
  {
    \iow_newline:(#1)\iow_newline:~ #2 \iow_newline:

    #3

    \iow_newline:
    definition's~end.
  }
  {
    \iow_newline:(#1)\iow_newline:~ #2 \iow_newline:

    #3

    \iow_newline:
    definition's~end.
  }

%%%%% 
%%%%%
%% Making this as short as possible (less than 60 chars)
%% so \msg_expandable_error: might be used.
%%%%%
\msg_new:nnnn {starray} {strict / deprecate} 
  {
    (#1)~'#2'~has ~ been ~ deprecated.
  }
  {
    The ~ command~'#2'~has ~ been ~ deprecated. ~
    Use~'#3'~ instead.
    ~Error~ Code: (#1).
  }


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


\cs_new_protected:Npn \__starray_msg:nnnnn #1#2#3#4#5
  {
    \__starray_set_rtn_false:

    \seq_gput_right:Nn \g__starray_msg_seq
      {
        \msg_warning:nnnnnn
          {starray}{ #1 } { #2 }{ #3 }{ #4 }{ #5 }
      }
  }
\cs_generate_variant:Nn \__starray_msg:nnnnn { nneee , neeee }


\cs_new_protected:Npn \__starray_msg:nnnn #1#2#3#4
  {
    \__starray_set_rtn_false:

    \seq_gput_right:Nn \g__starray_msg_seq
      {
        \msg_warning:nnnnn
          {starray}{ #1 } { #2 }{ #3 }{ #4 }
      }
  }
\cs_generate_variant:Nn \__starray_msg:nnnn { nnee , neee }


\cs_new_protected:Npn \__starray_msg_dispatch:
  {
    \seq_map_inline:Nn \g__starray_msg_seq { ##1 }
    \seq_gclear:N \g__starray_msg_seq
  }

\cs_new_protected:Npn \__starray_msg_clear:
  {
    \seq_gclear:N \g__starray_msg_seq
  }

%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%
%%%%
%%%% Package Variables declaration
%%%%
%%%%
%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%

%%%%
%%%% 'general' (internal) returning bool
%%%%
\cs_new:Npn \__starray_set_rtn_true:
  { \cs_set_eq:NN \__starray_rtn: \prg_return_true: }
\cs_new:Npn \__starray_set_rtn_false:
  { \cs_set_eq:NN \__starray_rtn: \prg_return_false: }

%%%%
%%%% sequence of 'error mensages' (stacked).
%%%%
\seq_new:N \g__starray_msg_seq

\tl_new:N  \l__starray_tmpa_tl  % to replace \l_tmpa_tl  % new_term
\tl_new:N  \l__starray_tmpb_tl % to replace \l_tmpb_tl   % fix terms+set iter from hash+if valid idx+set from keyval

\tl_new:N \l__starray_parser_tmp_A_tl
\tl_new:N \l__starray_parser_tmp_B_tl

\tl_new:N \l__starray_show_tmp_tl

\tl_new:N \l__starray_tmp_term_st


%%%%
%%%% (sub)structure returning tl.
%%%%
\tl_new:N \l__starray_keyval_tmpb_tl
\tl_new:N \l__starray_keyval_tmpa_tl

%%%%
%%%% parser related ones
%%%%
\bool_const:Nn \c__starray_no_idx_ending_bool \c_true_bool
\bool_const:Nn \c__starray_idx_ending_bool    \c_false_bool

      
\tl_new:N \l__starray_from_keyval_orgref_tl

%%%%
%%%% parser returning variables
%%%%
\tl_new:N \l__starray_parsed_tl
\tl_new:N \l__starray_parsed_ref_tl

\tl_new:N \l__starray_parsed_base_st
\tl_new:N \l__starray_parsed_term_st

\tl_new:N   \g__starray_parsed_saved_base_st 
\tl_new:N   \g__starray_parsed_saved_term_st 
\bool_new:N \g__starray_parsed_bool
  
\tl_new:N \l__starray_parsing_term_tl 

%%%%
%%%% parser 'internal' variables
%%%%
\bool_new:N \l__starray_parser_no_idx_ending_bool

\tl_new:N \l__starray_parsed_term_tl
\tl_new:N \l__starray_parsed_idx_tl

\bool_new:N \l__starray_parser_OK_bool


%%%%
%%%% for cs/prg generating commands
%%%%
\tl_new:N \l__starray_csuse_tmp_tl

%%%%
%%%% scan mark for _base_st, _term_st and _ref_st
%%%%
\scan_new:N \s__end

\tl_new:N \l__starray_duocmd_tmpa_tl
\tl_new:N \l__starray_duocmd_tmpb_tl


%% big one, (g)put !!
%%%%
%%%% (g)put :: IF the effect shall be local or global
%%%%
\cs_set_eq:NN \__starray_put:cnn \use_none:nnn


%%%%%%%%%
%%%
%%% This will create 3 variants
%%%                  This one is *NEVER* expandable
%%% {starray_ #cmd# : n #signature# } => standard one, expecting a starray-term-ref 
%%%                  This *might* be expandable (if base-code is)
%%% {starray_ parsed_ #cmd# : NN #signature# } => expecting two user given variables (from previous parsing)
%%%                  This *might* be expandable (if base-code (and if-parsed-bool-false, if checked) is)
%%% {starray_ parsed_ #cmd# : #signature# } => using *last* parsed term, with/without checking
%%%
%%%%%%%%%
%%%
%%% Regarding the base-code: it will 'get' two extra param BEFORE the ones in the signature
%%% nn#signature# (for example, signature:nN... real signature: nnnN #1#2#3#4
%%% whereas the first two parameters, nn, will (should) always be (o-expanded) '...term_st' and '...base_st'
%%%
%%% 'if-parser-failed' code shall expect a single parameter: starray-ref
%%%
%%% 'if-parsed-failed' code shall expect no parameter!
%%%
%%%%%%%%%
%%% #1 -> #cmd#      => base-name
%%% #2 -> #signature#
%%% #3 -> \c__starray_idx_ending_bool / \c__starray_no_idx_ending_bool
%%% #4 -> base-code                 % if expandable, the resulting commands *might* also be
%%% #5 -> if-parser-failed          % NB.: this will be in the F branch of \__starry_parser: *not* expandable
%%% #6 -> if-parsed-bool-false      % NB.: this will be in the F branch of a \bool_if: *might* be expandable
%%%%%%%%%
\cs_new_protected:Npn \__starray_cs_generate:nnNnnn #1#2#3#4
  {
    \int_case:nn { \tl_count:n {#2} }
      {
        {0} { \tl_set:Nn \l__starray_csuse_tmp_tl {} }
        {1} { \tl_set:Nn \l__starray_csuse_tmp_tl {\use_none:n} }
        {2} { \tl_set:Nn \l__starray_csuse_tmp_tl {\use_none:nn} }
        {3} { \tl_set:Nn \l__starray_csuse_tmp_tl {\use_none:nnn} }
      }
      
    \cs_new:cn {__starray_parsed_ #1 : nn#2}
      { #4 }
    
    \__starray_cs_generate:cVnnNnn 
      {__starray_parsed_ #1 : nn#2} 
      \l__starray_csuse_tmp_tl
      {#1}{#2} #3
  }

%%%%%%%%%
%%% #1 -> base
%%% #2 -> none
%%% #3 -> cmd radix
%%% #4 -> base signature
%%% #5 -> \c__starray_idx_ending_bool /  \c__starray_no_idx_ending_bool
%%% #6 -> in case  parser  err
%%% #7 -> in case *parsed* err
%%%%%%%%%
\cs_new_protected:Npn \__starray_cs_generate:NnnnNnn #1#2#3#4#5#6#7
  {
    \cs_new:cpn {starray_uparsed_ #3 : N#4} ##1
      { \exp_last_unbraced:NV #1 ##1 }

    \bool_if:NTF \l__starray_NNnames_bool
      {
        \bool_if:NTF \l__starray_NNnames_warn_bool
          {
            \cs_new:cpn {starray_parsed_ #3 : NN#4} ##1##2
              { 
                %%% Just in case 'this' is used in an expandable context
                \msg_expandable_error:nnnnn {starray} {strict / deprecate} {cs:01}
                  {  starray_parsed_ #3 : NN#4 }
                  {  starray_uparsed_ #3 : N#4  }
                \exp_last_unbraced:NV #1 ##1
              }
          }
          {
            \cs_new:cpn {starray_parsed_ #3 : NN#4} ##1##2
              { \exp_last_unbraced:NV #1 ##1 }
          }
      }
      {}
      

    \bool_if:NTF \l__starray_parsed_check_bool
      {
        \cs_new:cpn {starray_parsed_ #3 : #4}
          { 
            \bool_if:NTF \g__starray_parsed_bool
              { \exp_args:Noo #1 \g__starray_parsed_saved_term_st \g__starray_parsed_saved_base_st}
              { #7 #2  }
          }      
      }
      {
        \cs_new:cpn {starray_parsed_ #3 : #4}
          { \exp_args:Noo #1 \g__starray_parsed_saved_term_st \g__starray_parsed_saved_base_st}
      }
  
    \cs_new:cpn {starray_iparsed_ #3 : #4}
      { \exp_args:Noo #1 \g__starray_iterate_term_st \g__starray_iterate_base_st}
      
    \cs_new:cpn {starray_ #3 : n#4} ##1
      { 
        \__starray_parser:NeTF #5 {##1}
          { \exp_args:Noo #1 \l__starray_parsed_term_st \l__starray_parsed_base_st}
          { #6 #2 }
      }
  }
\cs_generate_variant:Nn \__starray_cs_generate:NnnnNnn {cV}


%%%%%%%%% WARNING: p variants.... might not be expandable !!!
%%%
%%% This will create 4 variants (x4 => p,T,F,TF)
%%%                  This will *NEVER* expandable
%%% {starray_ #cmd# : n #signature# {p,TF,T,F}} => standard one, expecting a starray-term-ref
%%%                  This *might* be expandable (if base-code and T/F code (that follows) also are)
%%% {starray_ parsed_ #cmd# : NN #signature# {p, TF,T,F}} => expecting two user given variables (from previous parsing)
%%%                  This *might* be expandable (if base-code and T/F code (that follows) also are... and (if-parsed-boold-false, if checked)
%%% {starray_ parsed_ #cmd# : #signature# {p,TF,T,F}} => using *last* parsed term, with/without checking
%%%
%%% regarding the _p variants.. they will be ok iff #3 is expandable!
%%%
%%%%%%%%%
%%%
%%% Regarding the base-code: it will 'get' two extra param BEFORE the ones in the signature
%%% nn#signature# (for example, signature:nN... real signature: nnnN #1#2#3#4
%%% whereas the first two parameters, nn, will (should) always be (o-expanded) '...term_st' and '...base_st'
%%%
%%% 'if-parser-failed' code shall expect a single parameter: starray-ref
%%%
%%% 'if-parsed-failed' code shall expect no parameter!
%%%
%%% For all of them to be expandable, #3, #4 and #5 have also to be expandable.
%%%
%%%%%%%%%
%%% #1 -> #cmd#      => base-name
%%% #2 -> #signature#
%%% #3 -> \c__starray_idx_ending_bool /  \c__starray_no_idx_ending_bool
%%% #3=>4 -> base-code
%%% #4=>5 -> if-parser-failed
%%% #5=>6 -> if-parsed-bool-false
%%%%%%%%%
\tl_new:N \l__starray_useAa_tl
\tl_new:N \l__starray_useAb_tl
\tl_new:N \l__starray_useBa_tl
\tl_new:N \l__starray_useBb_tl

\cs_new_protected:Npn \__starray_prg_generate:nnNnnn #1#2#3#4#5#6
  {
    \int_case:nn { \tl_count:n {#2} }  %%%% THOSE are for the "false" cases...(parameters not aboserbed by #signature#TF/_p/T/F cases)
      {
        {0} { 
              \tl_set:Nn \l__starray_useBa_tl {\use_ii:nn}    %% for the TF case
              \tl_set:Nn \l__starray_useBb_tl {}              %% for the _p case
              \tl_set:Nn \l__starray_useAa_tl {\use_none:n}   %% for the T case
              \tl_set:Nn \l__starray_useAb_tl {\use_i:n}      %% for the F case
            }
        {1} { 
              \tl_set:Nn \l__starray_useBa_tl {\use_iii:nnn} 
              \tl_set:Nn \l__starray_useBb_tl {\use_none:n} 
              \tl_set:Nn \l__starray_useAa_tl {\use_none:nn} 
              \tl_set:Nn \l__starray_useAb_tl {\use_ii:nn} 
            }
        {2} { 
              \tl_set:Nn \l__starray_useBa_tl {\use_iv:nnnn} 
              \tl_set:Nn \l__starray_useBb_tl {\use_none:nn} 
              \tl_set:Nn \l__starray_useAa_tl {\use_none:nnn} 
              \tl_set:Nn \l__starray_useAb_tl {\use_iii:nnn} 
            }
        {3} { 
              \tl_set:Nn \l__starray_useBa_tl {\use_v:nnnnn} 
              \tl_set:Nn \l__starray_useBb_tl {\use_none:nnn} 
              \tl_set:Nn \l__starray_useAa_tl {\use_none:nnnn} 
              \tl_set:Nn \l__starray_useAb_tl {\use_iv:nnnn} 
            }
      }
      
    %
    % the _p might be ok (expandable) ... depending on #4
    %
    \prg_new_conditional:cnn {__starray_parsed_ #1 : nn#2} {p , T , F , TF}
      { #4 }

    \__starray_prg_generate_a:ccVVnnNnn
      {__starray_parsed_ #1 : nn#2 TF} {__starray_parsed_ #1 _p : nn#2} 
      \l__starray_useBa_tl \l__starray_useBb_tl   
      {#1}{#2}{#3}{#5}{#6}
    \__starray_prg_generate_b:ccVVnnNnn
      {__starray_parsed_ #1 : nn#2 T} {__starray_parsed_ #1 : nn#2 F}
      \l__starray_useAa_tl \l__starray_useAb_tl  
      {#1}{#2}{#3}{#5}{#6}

  }

%%%%%%%%%
%%%
%%% if not expandable, better undefine them
%%%
%%%%%%%%%
\cs_new_protected:Npn \__starray_prg_undef_p:nn #1#2
  {
    \bool_if:NTF \l__starray_NNnames_bool
      { \cs_undefine:c { starray_parsed_ #1 _p: NN#2 } }
      {}
    
    \cs_undefine:c { __starray_parsed_ #1 _p: nn#2 }
    \cs_undefine:c { starray_uparsed_ #1 _p: N#2 }
    \cs_undefine:c { starray_parsed_ #1 _p: #2 }
  }

%%%%%%%%%
%%% #1 -> baseTF
%%% #2 -> base_p
%%% #3 -> noneA
%%% #4 -> none (for _p case)
%%% #5 -> cmd radix
%%% #6 -> base signature
%%% #7 -> \c__starray_idx_ending_bool /  \c__starray_no_idx_ending_bool
%%% #7=>8 -> in case  parser  err
%%% #8=>9 -> in case *parsed* err
%%%%%%%%%
\cs_new_protected:Npn \__starray_prg_generate_a:NNnnnnNnn #1#2#3#4#5#6#7#8#9
  {  
    \cs_new:cpn {starray_uparsed_ #5 : N#6 TF} ##1
      { \exp_last_unbraced:NV #1 ##1}

    \cs_new:cpn {starray_uparsed_ #5 _p : N#6} ##1
      { \exp_last_unbraced:NV #2 ##1}


    \bool_if:NTF \l__starray_NNnames_bool
      {
        \bool_if:NTF \l__starray_NNnames_warn_bool
          {
            \cs_new:cpn {starray_parsed_ #5 : NN#6 TF} ##1##2
              { 
                \msg_warning:nnnnn {starray} {strict / deprecate} {prg:01}
                  {  starray_parsed_ #5 : NN#6 TF }
                  {  starray_uparsed_ #5 : N#6 TF }
                \exp_last_unbraced:NV #1 ##1
              }
            \cs_new:cpn {starray_parsed_ #5 _p : NN#6} ##1##2
              { 
                %%% Just in case 'this' is used in an expandable context
                \msg_expandable_error:nnnnn {starray} {strict / deprecate} {prg:02}
                % This will certainly generate low level erros... :/
%                \msg_warning:nnnnn {starray} {strict / deprecate} {prg:02}  
                  { \ starray_parsed_ #5 _p : NN#6 }
                  { \ starray_parsed_ #5 _p : N#6 }
                \exp_last_unbraced:NV #2 ##1
              }
          }
          {
            \cs_new:cpn {starray_parsed_ #5 : NN#6 TF} ##1##2
              { \exp_last_unbraced:NV #1 ##1 }
            \cs_new:cpn {starray_parsed_ #5 _p : NN#6} ##1##2
              { \exp_last_unbraced:NV #2 ##1 }
          }
      }
      {}

    \bool_if:NTF \l__starray_parsed_check_bool
      {
        \cs_new:cpn {starray_parsed_ #5 : #6 TF}
          { 
            \bool_if:NTF \g__starray_parsed_bool
              { \exp_args:Noo #1 \g__starray_parsed_saved_term_st \g__starray_parsed_saved_base_st}
              { #9 #3 }  %%TODO... this should absorb N+2 and execute the last one...
          }
        \cs_new:cpn {starray_parsed_ #5 _p : #6 }
          { 
            \bool_if:NTF \g__starray_parsed_bool
              { \exp_args:Noo #2 \g__starray_parsed_saved_term_st \g__starray_parsed_saved_base_st}
              { #9 #4 }   %%TODO... hopefully this is correct... absorbs N tokens...execute none
          }
      }
      {
        \cs_new:cpn {starray_parsed_ #5 : #6 TF}
          { \exp_args:Noo #1 \g__starray_parsed_saved_term_st \g__starray_parsed_saved_base_st}
        \cs_new:cpn {starray_parsed_ #5 _p : #6 }
          { \exp_args:Noo #2 \g__starray_parsed_saved_term_st \g__starray_parsed_saved_base_st}
      }

    \cs_new:cpn {starray_iparsed_ #5 : #6 TF}
      { \exp_args:Noo #1 \g__starray_iterate_term_st \g__starray_iterate_base_st}
    \cs_new:cpn {starray_iparsed_ #5 _p : #6 }
      { \exp_args:Noo #2 \g__starray_iterate_term_st \g__starray_iterate_base_st}
  
    \cs_new:cpn {starray_ #5 : n#6 TF} ##1
      { 
        \__starray_parser:NeTF #7 {##1}
          { \exp_args:Noo #1 \l__starray_parsed_term_st \l__starray_parsed_base_st}
          { #8 #3 }  %%TODO... this should absorb N+2 and execute the last one...
      }

% for the record
% \__starray_parser isn't expandable
% *would it be...*
%
%    \cs_new:cpn {starray_ #5 _p : n#6 } ##1
%      { 
%        \__starray_parser:NeTF \c__starray_idx_ending_bool {##1}
%          { #2 \l__starray_parsed_term_st \l__starray_parsed_base_st}
%          { #7 #4 }
%      }
  
  }
\cs_generate_variant:Nn \__starray_prg_generate_a:NNnnnnNnn {ccVV}



%%%%%%%%%
%%% #1 -> baseT
%%% #2 -> baseF
%%% #3 -> noneA
%%% #4 -> noneB
%%% #5 -> cmd radix
%%% #6 -> base signature
%%% #7 -> \c__starray_idx_ending_bool /  \c__starray_no_idx_ending_bool
%%% #7=>8 -> in case  parser  err
%%% #8=>9 -> in case *parsed* err
%%%%%%%%%
\cs_new_protected:Npn \__starray_prg_generate_b:NNnnnnNnn #1#2#3#4#5#6#7#8#9
  {  
    \cs_new:cpn {starray_uparsed_ #5 : N#6 T} ##1
      { \exp_last_unbraced:NV #1 ##1 }
  
    \cs_new:cpn {starray_uparsed_ #5 : N#6 F} ##1
      { \exp_last_unbraced:NV #2 ##1 }

    \bool_if:NTF \l__starray_NNnames_bool
      {
        \bool_if:NTF \l__starray_NNnames_warn_bool
          {
            \cs_new:cpn {starray_parsed_ #5 : NN#6 T} ##1##2
              { 
                \msg_warning:nnnnn {starray} {strict / deprecate} {prg:03}
                  {  starray_parsed_ #5 : NN#6 T }
                  {  starray_uparsed_ #5 : N#6 T }
                \exp_last_unbraced:NV #1 ##1
              }   
            \cs_new:cpn {starray_parsed_ #5 : NN#6 F} ##1##2
              { 
                \msg_warning:nnnnn {starray} {strict / deprecate} {prg:04}
                  {  starray_parsed_ #5 : NN#6 F }
                  {  starray_uparsed_ #5 : N#6 F }
                \exp_last_unbraced:NV #2 ##1
              }
          }
          {
            \cs_new:cpn {starray_parsed_ #5 : NN#6 T} ##1##2
              { \exp_last_unbraced:NV #1 ##1  }
          
            \cs_new:cpn {starray_parsed_ #5 : NN#6 F} ##1##2
              { \exp_last_unbraced:NV #2 ##1  }
          }
      }
      {}


    \bool_if:NTF \l__starray_parsed_check_bool
      {
        \cs_new:cpn {starray_parsed_ #5 : #6 T}
          { 
            \bool_if:NTF \g__starray_parsed_bool
              { \exp_args:Noo #1 \g__starray_parsed_saved_term_st \g__starray_parsed_saved_base_st}
              { #9 #3 } %%TODO... this should absorb N+1 and execute none...
          }
        \cs_new:cpn {starray_parsed_ #5 : #6 F}
          { 
            \bool_if:NTF \g__starray_parsed_bool
              { \exp_args:Noo #2 \g__starray_parsed_saved_term_st \g__starray_parsed_saved_base_st}
              { #9 #4 } %%TODO... this should absorb N+1 and execute the last one...
          }
      }
      {
        \cs_new:cpn {starray_parsed_ #5 : #6 F}
          { \exp_args:Noo #1 \g__starray_parsed_saved_term_st \g__starray_parsed_saved_base_st}   
        \cs_new:cpn {starray_parsed_ #5 : #6 T}
          { \exp_args:Noo #2 \g__starray_parsed_saved_term_st \g__starray_parsed_saved_base_st}
      }
  
    \cs_new:cpn {starray_iparsed_ #5 : #6 F}
      { \exp_args:Noo #1 \g__starray_iterate_term_st \g__starray_iterate_base_st}   
    \cs_new:cpn {starray_iparsed_ #5 : #6 T}
      { \exp_args:Noo #2 \g__starray_iterate_term_st \g__starray_iterate_base_st}

    \cs_new:cpn {starray_ #5 : n#6 T} ##1
      { 
        \__starray_parser:NeTF #7 {##1}
          { \exp_args:Noo #1 \l__starray_parsed_term_st \l__starray_parsed_base_st}
          { #8 #3 }  %%TODO... this should absorb N+1 and execute none...
      }

    \cs_new:cpn {starray_ #5 : n#6 F} ##1
      { 
        \__starray_parser:NeTF #7 {##1}
          { \exp_args:Noo #2 \l__starray_parsed_term_st \l__starray_parsed_base_st}
          { #8 #4 }  %%TODO... this should absorb N+1 and execute the last one...
      }

  }
\cs_generate_variant:Nn \__starray_prg_generate_b:NNnnnnNnn {ccVV , ccee}



%%%%%%%%%
%%%
%%% This will create a pair
%%%                  *none* expandable
%%% #cmd:signature#    => cs,  expecting the #1 as a starray-ref
%%% #cmd:signature#TF  => prg, expecting the #1 as a starray-ref
%%%
%%%%%%%%%
%%%
%%% Regarding the base-code: #1 will always be treated as the starray-ref.
%%% \__starray_return_true: / \__starray_return_false: will be set as
%%%   as *nothing* for the cs command
%%%  \prg_return_true: / \prg_return_false: for the prg command
%%%
%%% 'if-parser-failed' code can use all parameters 
%%%
%%%%%%%%%
%%% #1 -> #cmd:signature#           => base-name
%%% #2 -> \c__starray_idx_ending_bool / \c__starray_no_idx_ending_bool
%%% #3 -> base-code                 
%%% #4 -> if-parser-failed
%%%%%%%%%
\regex_const:Nn \c__starray_csa_regex {\c{prg_return_true:}|\c{prg_return_false:}}
\regex_const:Nn \c__starray_csb_regex {\c{__starray_rtn:}}
\regex_const:Nn \c__starray_prg_regex {\c{__starray_msg_dispatch:}}

\cs_new_protected:Npn \__starray_cs_prg_duo_generate:NNnn #1#2#3
  {
    
    \tl_set:Nn \l__starray_duocmd_tmpb_tl {#3}
    \regex_replace_all:NnN \c__starray_prg_regex {\c{__starray_msg_clear:}} \l__starray_duocmd_tmpb_tl

    \tl_set:Nn \l__starray_duocmd_tmpa_tl {#3}
    \regex_replace_all:NnN \c__starray_csa_regex {} \l__starray_duocmd_tmpa_tl
    \regex_replace_all:NnNTF \c__starray_csb_regex {} \l__starray_duocmd_tmpa_tl
      {\tl_put_left:Nn  \l__starray_duocmd_tmpb_tl \__starray_set_rtn_true:}
      {}
    \__starray_cs_prg_duo_generate_a:NNVVn #1#2\l__starray_duocmd_tmpa_tl \l__starray_duocmd_tmpb_tl
  }

\cs_new_protected:Npn  \__starray_cs_prg_duo_generate_a:NNnnn #1#2#3#4#5
  {
    \prg_new_conditional:Nnn #1 {T , F , TF}
      {
        \__starray_parser:NeTF #2 {##1}
          { #4 }
          {
            \__starray_msg_clear:
            \prg_return_false:
          } % returns nothing by default
      }

    \cs_new:Nn #1
      {
        \__starray_parser:NeTF #2 {##1}
          { #3 }
          { 
            \__starray_msg_dispatch:
            #5 
          }
      }
  }
\cs_generate_variant:Nn \__starray_cs_prg_duo_generate_a:NNnnn {NNVV}


%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%
%%%%
%%%% Package conditionals
%%%%
%%%%
%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%


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

\prg_new_conditional:Npnn \starray_if_exist:n #1 {p, T, F, TF}
  {
    \__starray_if_exist:cTF { c__starray_prfix_.  #1 _base_ref_st}
      \prg_return_true:
      \prg_return_false:
  }

%
% Note to self: One way would be to test the scan mark \s__end ... but cumbersome.
%
% DEPRECATED, unless some other (simple) test becomes available
%\prg_new_conditional:Npnn \__starray_if_valid:n #1 {p, T, F, TF}
%  {
%    \bool_lazy_and:nnTF {\prop_if_exist_p:c {#1}} {\prop_item:cn {#1} {is_starray}}
%      { \prg_return_true: }
%      { \prg_return_false: }
%  }

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

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


\prg_new_conditional:Npnn \starray_if_valid:n #1 {p, T, F, TF}
  {
    \__starray_if_valid:nTF { c__starray_prfix_.  #1 _ref_st}
      \prg_return_true:
      \prg_return_false:
  }


\tl_const:Nn \c__starray_empty_hash_term_st
  {
    \relax \relax \s__end
  }
  

%%%
%%% This will generate two main commands
%%%      \#cmd# : N #sig#  => idea beign the 1st parameter will be a _st variable
%%%      \#cmd# : c #sig#  
%%%      \#cmd# : w #sig#  => the _st variable is already o-expanded
%%% Carefull when calling this, the 3rd parameter has to convay a parameter list (add a space after each # )
%%%%%%%%%
%%% #1 -> #cmd#      => base-name
%%% #2 -> #signature#
%%% #3 -> parameter description (the 'p')
%%% #4 -> code                 % if expandable, the resulting commands will also be
%%%%%%%%%
\cs_new_protected:Npn \__starray_cs_wgen:nnnn #1#2#3#4
  {
    \cs_new:cpe {#1:N#2} ##1
      {
        \exp_not:N \exp_last_unbraced:No \exp_not:c {#1:w#2} ##1
      }
    \cs_generate_variant:cn {#1:N#2} {c}
    
    \exp_last_unbraced:Nno \cs_new:cpn {#1:w#2} #3
      { #4 }
  }


%%%
%%% This will generate two main conditional commands
%%%      \#cmd# : N #sig#TF  => (and c variant) idea beign the 1st parameter will be a _st variable
%%%      \#cmd# : w #sig#TF  => the _st variable is already o-expanded
%%% Carefull when calling this, the 3rd parameter has to convay a parameter list (add a space after each # )
%%%%%%%%%
%%% #1 -> #cmd#      => base-name
%%% #2 -> #signature#
%%% #3 -> parameter description (the 'p')
%%% #4 -> code                 % if expandable, the resulting commands will also be
%%%%%%%%%
\cs_new_protected:Npn \__starray_prg_wgen:nnnn #1#2#3#4
  {
    \cs_new:cpe {#1:N#2TF} ##1 
      {
        \exp_not:N \exp_last_unbraced:No \exp_not:c {#1:w#2TF} ##1
      }
    \cs_generate_variant:cn {#1:N#2TF} {c}

    \exp_last_unbraced:Nno \prg_new_conditional:cpnn {#1:w#2} #3 {TF}
      { #4 }
  }

  
%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%
%%%%
%%%% starray \...._new declarations
%%%%
%%%% Note: the \s__end allows to fast skip to the last itens, if not needed.
%%%%
%%%%%%%%%%%%%%%
\cs_new_protected:Npn \__starray_base_new:nn #1#2
  {
    \int_new:c
      { g__starray_prfix_.  #2 _base_cnt_int }
    \int_new:c
      { g__starray_prfix_.  #2 _base_iter_int }
    \prop_gclear_new_linked:c
      { g__starray_prfix_.  #2 _base_ihash_prop} %% will have {key/hash} => {\term_prop}{infix-letter}{i}{infix}{stkeys_seq}
      
    \tl_const:ce {  c__starray_prfix_.  #2 _base_st } 
      {
        \exp_not:c { g__starray_prfix_.  #2 _base_ihash_prop}
        \exp_not:c { g__starray_prfix_.  #2 _base_iter_int }
        \exp_not:c { g__starray_prfix_.  #2 _base_cnt_int }
        \exp_not:c { g__starray_prfix_.  #1 _defkeys_prop}
        \exp_not:c { g__starray_prfix_.  #1 _defstkeys_seq}
        {#1}{#2}
        \exp_not:N \s__end
      }
      
  }
\cs_generate_variant:Nn \__starray_base_new:nn { e }

\cs_new_protected:Npn \__starray_sub_base_new:nnn #1#2#3
  { 
    \__starray_base_new:nn {#1.#3}{#2.#3}
  }

\cs_new_protected:Npn \__starray_new:n #1
  {
    \prop_new_linked:c { g__starray_prfix_.  #1 _defkeys_prop }
    \seq_new:c { g__starray_prfix_.  #1 _defstkeys_seq }
    \tl_const:ce {  c__starray_prfix_.  #1 _ref_st } 
      {
        \exp_not:c { g__starray_prfix_.  #1 _defkeys_prop }
        \exp_not:c { g__starray_prfix_.  #1 _defstkeys_seq }
        {#1}
        \exp_not:N \s__end
      }
  }


%%%%%%%%%%%%%%%
%%%%
%%%% \starray_new
%%%%
%%%%%%%%%%%%%%%
\cs_new_protected:Npn \starray_new:n #1
  {
    \__starray_if_exist:cTF { c__starray_prfix_. #1 _ref_st}
      {
        \msg_warning:nnnn {starray} {strict / (re)define} {new:1} {#1}
      }
      {
        \__starray_new:n { #1 }
        \__starray_base_new:nn {#1}{#1} % TODO: might be incomplete !!!
      }
  }

\prg_new_protected_conditional:Npnn \starray_new:n #1 {T, F, TF}
  {
    \__starray_if_exist:cTF { c__starray_prfix_. #1 _ref_st}
      { \prg_return_false: }
      {
        \__starray_new:n { #1 }
        \__starray_base_new:nn {#1}{#1} % TODO: might be incomplete !!!
        \prg_return_true:
      }
  }

%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%
%%%%
%%%% starray ref parser
%%%%
%%%%
%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%
%%%%
%%%% get root reference (first term) assuming called as
%%%%   <tl-var> <st-ref> .  \q_stop
%%%% so that even if {ref} (has no dot, no idx) it will return 'the root ref'
%%%% e.g.: \tl_set:Ne \l__tmpb_tl {\__starray_get_root:nw \l__starray_tmpa_tl .  \q_stop}
%%%%
%%%% It will return the 'root ref' assuming that the ref is of form root.name.name (no [idx])
%%%%
%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%
%%%
%%% This one can't be protected... it is used in {e} expantion
%%% if protected, it results in a quark loop
%%% 
\cs_new:Npn \__starray_get_root:nw #1 . #2 \q_stop { #1 }
\cs_generate_variant:Nn \__starray_get_root:nw {V}

%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%
%%%%
%%%% set root reference (first term) assuming called as
%%%%   <tl-var> <st-ref> . \q_stop
%%%% so that even if {ref} (has no dot, no idx) it will return 'the root ref'
%%%% e.g.:  \__starray_set_root:Nnw \l__tmpb_tl \l__starray_tmpa_tl . \q_stop
%%%%
%%%% It will return the 'root ref' assuming that the ref is of form root.name.name (no [idx])
%%%%
%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%
\cs_new_protected:Npn \__starray_set_root:Nnw #1 #2 . #3 \q_stop { \tl_set:Nn #1 {#2} }
\cs_generate_variant:Nn \__starray_set_root:Nnw {Ne}


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


%%% \c__starray...._ref_st
%%%        \c{ -ref- _defkeys_prop }                  %% #1
%%%        \c{ -ref- _defstkeys_seq }                 %% #2
%%%        {-ref-}                                    %% #3
%%%    \s__end
%%%%%%
%%% \__starray_refst_def_prop:Nnn
%%% \__starray_refst_def_prop:cnn
%%% \__starray_refst_def_prop:wnn
%%%%%%
\__starray_cs_wgen:nnnn
  {__starray_refst_def_prop}{nn}{ # 1 # 2 \s__end }
  { 
    \prop_gput:Nnn #1 
  }

%%%%%%%%%%%%%%%
%%%%
%%%% \starray_def_prop
%%%%
%%%%%%%%%%%%%%%
\cs_new_protected:Npn \starray_def_prop:nnn #1#2#3
  {
    \__starray_if_exist:cTF { c__starray_prfix_.  #1 _ref_st}
      { 
        \__starray_refst_def_prop:cnn 
          { c__starray_prfix_.  #1 _ref_st} {#2} {#3}
      }
      {
        \msg_warning:nnxxx {starray}{reference / invalid-starray} 
          {addprop:1} {#1} {cannot~add~property:#2}
      }
  }

\prg_new_protected_conditional:Npnn \starray_def_prop:nnn #1#2#3 {T, F, TF}
  {
    \__starray_if_exist:cTF { c__starray_prfix_.  #1 _ref_st}
      {
        \__starray_refst_def_prop:cnn 
          { c__starray_prfix_.  #1 _ref_st} {#2} {#3}
        
        \prg_return_true:
      }
      \prg_return_false:
  }


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

%%% \c__starray...._ref_st
%%%        \c{ -ref- _defkeys_prop }                  %% #1
%%%        \c{ -ref- _defstkeys_seq }                 %% #2
%%%        {-ref-}                                    %% #3
%%%    \s__end
%%%%%%
%%% \__starray_refst_def_struct:Nn
%%% \__starray_refst_def_struct:cn
%%% \__starray_refst_def_struct:wn
%%%%%%
\__starray_cs_wgen:nnnn
  {__starray_refst_def_struct}{n}{  # 1 # 2 # 3 \s__end # 4 }
  { 
    \seq_if_in:NnF #2 {#4}
      {
        \seq_gput_right:Nn #2 {#4} 
        \__starray_new:n { #3 . #4 }
      }
  }

%%%%%%
%%% \__starray_refst_keyval_def_struct:NnN
%%% \__starray_refst_keyval_def_struct:cnN
%%% \__starray_refst_keyval_def_struct:wnN
%%%%%%
\__starray_cs_wgen:nnnn
  {__starray_refst_keyval_def_struct}{nN}{  # 1 # 2 # 3 \s__end # 4 # 5}
  {
    \tl_set:Nn #5 {#3}
    \seq_if_in:NnF #2 {#4}
      {
        \seq_gput_right:Nn #2 {#4} 
        \__starray_new:n { #3 . #4 }
      }
  }
\cs_generate_variant:Nn \__starray_refst_keyval_def_struct:NnN {Ne}  
  
%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%
%%%%
%%%% fixing struct _base for already instantiated terms
%%%%
%%%%
%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%

%%% \c__starray_..._term_st
%%%        \c{ -infix- _term_prop }                  %% #1
%%%        { -infix- }                               %% #2
%%%        { -val- }  %% iter's val for this entry   %% #3
%%%        { -idx- }                                 %% #4
%%%        \c{ -ref- _defstkeys_prop}                %% #5
%%%    \s__end
%%%%%%
%%% \__starray_termst_fix_terms:Nnn
%%% \__starray_termst_fix_terms:cnn
%%% \__starray_termst_fix_terms:wnn
%%%%%%
\__starray_cs_wgen:nnnn
  {__starray_termst_fix_terms}{nn}{  # 1 # 2 # 3 \s__end # 4 # 5}
  {
    \__starray_if_exist:cTF { c__starray_prfix_.  #2 . #5 _base_st}
      {
        \__starray_basest_fix_terms:c 
          { c__starray_prfix_.  #2 . #5 _base_st}
      }
      {
        \__starray_base_new:nn { #4 . #5 } { #2 . #5 }
      }
  }

%%% \c__starray_..._base_st
%%%        \c{ -infix- _ihash_prop}                   %% #1
%%%        \c{ -infix- _base_iter_int }               %% #2
%%%        \c{ -infix- _base_cnt_int }                %% #3
%%%        \c{ -ref- _defkeys_prop}                   %% #4
%%%        \c{ -ref- _defstkeys_prop}                 %% #5
%%%        {-ref-}{-infix-}                           %% #6#7
%%%    \s__end
%%%%%%
%%% \__starray_basest_fix_terms:N
%%% \__starray_basest_fix_terms:c
%%% \__starray_basest_fix_terms:w
%%%%%%
\__starray_cs_wgen:nnnn
  {__starray_basest_fix_terms}{}{ # 1 # 2 # 3 # 4 # 5 # 6 # 7 \s__end }
  {
    \prop_if_empty:NF #1
      {
        \prop_map_inline:Nn #1
          { %%% ##1 will be idx/hash ##2 will be _term_st
            \seq_map_inline:Nn #5  
              {  
                \__starray_termst_fix_terms:wnn
                  ##2 {#6}{####1}  
              }
          }
      }  
  }

\cs_new_protected:Npn \starray_fix_terms:n #1
  {
    \tl_set:Nn \l__starray_tmpb_tl {#1}
    \__starray_set_root:New 
      \l__starray_tmpb_tl 
      \l__starray_tmpb_tl  .  \q_stop
  
    \__starray_if_exist:cTF {  c__starray_prfix_.  \l__starray_tmpb_tl _ref_st}
      {
        \__starray_basest_fix_terms:c 
          {  c__starray_prfix_.  \l__starray_tmpb_tl _base_st}
      }
      {
        \msg_warning:nnxxx {starray}{reference / invalid-starray} 
          {fixterms:1} {#1} {}
      }
  }

%%%%%%%%%%%%%%%
%%%%
%%%% \starray_def_struct
%%%%
%%%%%%%%%%%%%%%
\cs_new_protected:Npn \starray_def_struct:nn #1#2
  {
    \__starray_if_exist:cTF {  c__starray_prfix_.  #1 _ref_st}
      {
        \__starray_refst_def_struct:cn 
          { c__starray_prfix_.  #1 _ref_st} {#2}
      }
      {
        \msg_warning:nnxxx {starray}{reference / invalid-starray} 
          {addstruct:1} {#1} {cannot~add~structure:#2}
      }
  }


\prg_new_protected_conditional:Npnn \starray_def_struct:nn #1#2 {T, F, TF}
  {
    \__starray_if_exist:cTF {  c__starray_prfix_.  #1 _ref_st}
      {
        \__starray_refst_def_struct:cn 
          { c__starray_prfix_.  #1 _ref_st} {#2}
        \prg_return_true:
      }
      { \prg_return_false: }
  }


%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%
%%%%
%%%% adding prop/struct from keyval
%%%%
%%%%
%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%


%\prg_new_conditional:Npnn \__starray_def_from_keyval_testdot_aux:w  #1 . \q_nil { TF}
%  {
%    \str_compare:nNnTF {#1} = {struct}
%      { \prg_return_true: }
%      { \prg_return_false: }
%  }

%%% This expects 3 parameters the last two are being used by \str_compare:
\cs_new:Npn \__starray_def_from_keyval_testdot_aux:wTF  #1 . \q_nil
  {
    \str_compare:nNnTF {#1} = {struct}
  }


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

\cs_new_protected:Npn \__starray_def_from_keyval_parse:Nnn #1#2#3
  {
      \__starray_def_from_keyval_testdot:wTF #2 . \q_nil \q_stop
        { 
          \__starray_refst_keyval_def_struct:NeN #1 
            \l__starray_keyval_tmpb_tl 
            \l__starray_keyval_tmpa_tl
          
          \keyval_parse:een 
            { 
              \exp_not:N \__starray_def_from_keyval_parse:Nn  
                \exp_not:c { c__starray_prfix_. \l__starray_keyval_tmpa_tl . \l__starray_keyval_tmpb_tl _ref_st } 
            }
            { 
              \exp_not:N \__starray_def_from_keyval_parse:Nnn 
                \exp_not:c { c__starray_prfix_. \l__starray_keyval_tmpa_tl . \l__starray_keyval_tmpb_tl _ref_st } 
            }
            {#3}
        }
        { % #1 should be ..._ref_st
          \__starray_refst_def_prop:Nnn #1 {#2}{#3}
        }
  }

\cs_new_protected:Npn \__starray_def_from_keyval_parse:Nn #1#2
  { % #1 should be _ref_st 
    \__starray_refst_def_prop:Nnn #1 {#2}{}
  }



%%%%%%%%%%%%%%%
%%%%
%%%% \starray_def_from_keyval
%%%%
%%%%%%%%%%%%%%%
\cs_new_protected:Npn \starray_def_from_keyval:nn #1#2
  {
    \__starray_if_exist:cTF {  c__starray_prfix_.  #1 _ref_st}
      { 
        \keyval_parse:een
          { \exp_not:N \__starray_def_from_keyval_parse:Nn  \exp_not:c { c__starray_prfix_.  #1 _ref_st } }
          { \exp_not:N \__starray_def_from_keyval_parse:Nnn \exp_not:c { c__starray_prfix_.  #1 _ref_st } }
          { #2 }
      }
      {
        \msg_warning:nnxxx {starray}{reference / invalid-starray} 
          {addkeyval:1} {#1} {cannot~add:#2}
      }
  }

\prg_new_protected_conditional:Npnn \starray_def_from_keyval:nn #1#2 {T, F, TF}
  {
    \__starray_if_exist:cTF { c__starray_prfix_.  #1 _ref_st }
      { 
        \keyval_parse:een
          { \exp_not:N \__starray_def_from_keyval_parse:Nn  \exp_not:c { c__starray_prfix_.  #1 _ref_st } }
          { \exp_not:N \__starray_def_from_keyval_parse:Nnn \exp_not:c { c__starray_prfix_.  #1 _ref_st } }
          { #2 }
        \prg_return_true:
      }
      { \prg_return_false: }
  }


%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%
%%%%
%%%% adding terms
%%%%
%%%%
%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%

%%% \c__starray_..._base_st
%%%        \c{ -infix- _ihash_prop}                   %% #1
%%%        \c{ -infix- _base_iter_int }               %% #2
%%%        \c{ -infix- _base_cnt_int }                %% #3
%%%        \c{ -ref- _defkeys_prop}                   %% #4
%%%        \c{ -ref- _defstkeys_prop}                 %% #5
%%%        {-ref-}{-infix-}                           %% #6#7
%%%    \s__end
%%%%%%
%%% \__starray_basest_new_term:Nn
%%% \__starray_basest_new_term:cn
%%% \__starray_basest_new_term:wn
%%%%%%
\__starray_cs_wgen:nnnn
  {__starray_basest_new_term}{n}{ # 1 # 2 # 3 # 4 # 5 # 6 # 7\s__end # 8 }
  {
    \int_gincr:N #3

    \int_gset_eq:NN #2 #3

    \tl_set:Ne \l__starray_tmpa_tl
      { \int_to_Alph:n #3 }

    \prop_gput:Nee #1
      { \int_use:N #3 }
      {
        \exp_not:c {  g__starray_prfix_.  #7 _ \l__starray_tmpa_tl _term_prop }
        { #7 _ \l__starray_tmpa_tl }
        { \int_use:N #3 }
        { \l__starray_tmpa_tl }
        \exp_not:N #5
        \exp_not:N \s__end
      }
      
    \tl_if_blank:nF {#8}
      {
        \prop_gput:Nee #1
          { #8 }
          {
            \exp_not:c {  g__starray_prfix_.  #7 _ \l__starray_tmpa_tl _term_prop }
            { #7 _ \l__starray_tmpa_tl }
            { \int_use:N #3 }
            { \l__starray_tmpa_tl }
            \exp_not:N #5
            \exp_not:N \s__end
          }
      }

   \prop_new_linked:c
      {  g__starray_prfix_.  #7 _ \l__starray_tmpa_tl _term_prop }
   \prop_gset_eq:cN
      {  g__starray_prfix_.  #7 _ \l__starray_tmpa_tl _term_prop }
      #4

% map over 'all sub-starrays parts of def_ref -> st_seq (those starting with a dot, @st_seq)
    \cs_set:Npe \__starray_sub_aux:n 
      {
        \exp_not:N \__starray_sub_base_new:nnn
          { #6 }{ #7 _ \l__starray_tmpa_tl }
      }
    \seq_map_inline:Nn #5
      { \__starray_sub_aux:n {##1} }
  }

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

\cs_new_protected:Npn \starray_new_term:nn #1#2
  {
    \__starray_parser:NeTF \c__starray_no_idx_ending_bool {#1}
      {
        \__starray_basest_new_term:Nn
          \l__starray_parsed_base_st {#2}
      }
      {
        \__starray_msg_dispatch:
        \msg_warning:nnnn {starray}{syntax /  term}{addterm:2}{#1}
      }
  }


\prg_new_protected_conditional:Npnn \starray_new_term:nn #1#2 {T, F, TF}
  {
    \__starray_parser:NeTF \c__starray_no_idx_ending_bool {#1}
      {
        \__starray_basest_new_term:Nn
          \l__starray_parsed_base_st {#2}
        \prg_return_true:
      }
      { \prg_return_false: }
  }


%%% \c__starray_..._term_st
%%%        \c{ -infix- _term_prop }                  %% #1
%%%        { -infix- }                               %% #2
%%%        { -val- }  %% iter's val for this entry   %% #3
%%%        { -idx- }                                 %% #4
%%%        \c{ -ref- _defstkeys_prop}                %% #5
%%%    \s__end
%%%%%%
%%% \__starray_termst_get_infix:NN
%%% \__starray_termst_get_infix:cN
%%% \__starray_termst_get_infix:wN
%%%%%%
\__starray_cs_wgen:nnnn
  {__starray_termst_get_infix}{N}{ # 1 # 2 # 3 \s__end # 4 }
  { 
    \tl_set:Nn #4 {#2} 
  }

%%%%%%%%
%%%%% \__starray_termst_get_iterx:NNN
%%%%% \__starray_termst_get_iterx:cNN
%%%%% \__starray_termst_get_iterx:wNN
%%%%%%%%
%%\__starray_cs_wgen:nnnn
%%  {__starray_termst_get_iterx}{NN}{  # 1 # 2 # 3 # 4 \s__end # 5 # 6 }
%%  { 
%%    \tl_set:Nn #5 {#3} 
%%    \tl_set:Nn #6 {#2} 
%%  }

%%%%%%
%%% \__starray_termst_get_iterval:NN
%%% \__starray_termst_get_iterval:cN
%%% \__starray_termst_get_iterval:wN
%%%%%%
\__starray_cs_wgen:nnnn
  {__starray_termst_get_iterval}{N}{  # 1 # 2 # 3 # 4 \s__end # 5 }
  { 
    \tl_set:Nn #5 {#3} 
  }

\cs_new:Npn \__starray_cascade_aux:nN #1#2
  {
    \seq_map_inline:Nn #2
      {
        \__starray_basest_set_iter:cnTF 
          { c__starray_prfix_. #1 . ##1 _base_st } {1}
          {} {}
      }
  }
\cs_generate_variant:Nn  \__starray_cascade_aux:nN {o}


\bool_if:NTF \l__starray_cascade_bool
  {
    \cs_new:Npn \__starray_iter_cascade:NNN #1#2#3
      {
        \prop_get:NeN #1 
          {\int_use:N #2} \l__starray_tmp_term_st
        
        \__starray_termst_get_infix:NN
          \l__starray_tmp_term_st \l__starray_tmp_infix_tl 
          
        \__starray_cascade_aux:oN 
          \l__starray_tmp_infix_tl #3
      }
  }
  {
    \cs_new:Npn \__starray_iter_cascade:NNN #1#2#3
      { }
  }

%%% \c__starray_..._base_st
%%%        \c{ -infix- _ihash_prop}                   %% #1
%%%        \c{ -infix- _base_iter_int }               %% #2
%%%        \c{ -infix- _base_cnt_int }                %% #3
%%%        \c{ -ref- _defkeys_prop}                   %% #4
%%%        \c{ -ref- _defstkeys_prop}                 %% #5
%%%        {-ref-}{-infix-}                           %% #6#7
%%%    \s__end
%%%%%%
%%% \__starray_basest_set_iter:NnTF
%%% \__starray_basest_set_iter:cnTF
%%% \__starray_basest_set_iter:wnTF
%%%%%%
\__starray_prg_wgen:nnnn
  {__starray_basest_set_iter}{n}{ # 1 # 2 # 3 # 4 # 5 # 6 \s__end # 7 }
  {
    \int_compare:nNnTF {#7} > {#3}
      {
        \int_gset_eq:NN #2 #3  

        \int_compare:nNnTF #2 = \c_zero_int
          { }
          {
            \__starray_iter_cascade:NNN #1 #2 #5
          }

        \prg_return_false:
      }
      {
        \int_gset:Nn #2 {#7}

        \__starray_iter_cascade:NNN #1 #2 #5

        \prg_return_true:
      }    
  }

%%%%%%
%%% \__starray_basest_incr_iter:NTF
%%% \__starray_basest_incr_iter:cTF
%%% \__starray_basest_incr_iter:wTF
%%%%%%
\__starray_prg_wgen:nnnn
  {__starray_basest_incr_iter}{}{ # 1 # 2 # 3 # 4 # 5 # 6 \s__end }
  {
    \int_compare:nNnTF {#2} = {#3}
      {
        \prg_return_false:
      }
      {
        \int_gincr:N #2

        \__starray_iter_cascade:NNN #1 #2 #5

        \prg_return_true:
      }    
  }

%%%%%%
%%% \__starray_basest_set_iter_from_hash:NnTF
%%% \__starray_basest_set_iter_from_hash:cnTF
%%% \__starray_basest_set_iter_from_hash:wnTF
%%%%%%
\__starray_prg_wgen:nnnn
  {__starray_basest_set_iter_from_hash}{n}{ # 1 # 2 # 3 # 4 # 5 # 6 # 7 \s__end # 8 }
  {
    \prop_get:NeNTF #1 {#8} \l__starray_tmp_term_st
      {
        \__starray_termst_get_iterval:NN
          \l__starray_tmp_term_st 
          \l__starray_tmpb_tl
        \int_gset:Nn #2 \l__starray_tmpb_tl

        \__starray_iter_cascade:NNN #1 #2 #5
        
        \prg_return_true:
      }
      {
        \prg_return_false:
      }
  }
\prg_generate_conditional_variant:Nnn \__starray_basest_set_iter_from_hash:Nn {Ne} {TF}


%%%%%%%%%%%%%%%
%%%%
%%%% \starray_set_iter
%%%%
%%%%%%%%%%%%%%%


%%%%%%%%%%%%%%%
%%% \starray_set_iter_from_hash:nn
%%% \starray_set_iter_from_hash:nnTF
%%%%%%%%%%%%%%%
\__starray_cs_prg_duo_generate:NNnn
  \starray_set_iter_from_hash:nn
  \c__starray_no_idx_ending_bool
  {
    \__starray_basest_set_iter_from_hash:NeTF
      \l__starray_parsed_base_st {#2}
      {}  
      { 
        \__starray_msg:nnnnn {reference /  iter} {iterhash:1} {#1}{#2}{-here-}
        \__starray_msg_dispatch:
        \__starray_set_rtn_false: 
      }
    \__starray_rtn:
  }
  {
        \msg_warning:nnnn {starray} {syntax /  iter} {iter:1} {#1}
  }
  




%%%%%%%%%%%%%%%
%%% \starray_set_iter:nn
%%% \starray_set_iter:nnTF
%%%%%%%%%%%%%%%
\__starray_cs_prg_duo_generate:NNnn
  \starray_set_iter:nn
  \c__starray_no_idx_ending_bool
  {
    \int_compare:nNnTF {#2} < {1}
      { 
        \__starray_basest_set_iter:NnTF
          \l__starray_parsed_base_st {1}
          {}{}

        \prg_return_false:
      }
      {
        \__starray_basest_set_iter:NnTF
          \l__starray_parsed_base_st {#2}
          {}  { \__starray_set_rtn_false: }

        \__starray_rtn:
      }
  }
  {
        \__starray_msg_dispatch:
        \msg_warning:nnnn {starray} {syntax /  iter} {iter:1} {#1}
  }




%%%%%%%%%%%%%%%
%%% \starray_reset_iter:n
%%% \starray_reset_iter:nTF
%%%%%%%%%%%%%%%
\__starray_cs_prg_duo_generate:NNnn
  \starray_reset_iter:n
  \c__starray_no_idx_ending_bool
  {
    \__starray_basest_set_iter:NnTF
      \l__starray_parsed_base_st {1}
      {}  { \__starray_set_rtn_false: }

    \__starray_rtn:
  }
  {
        \msg_warning:nnnn {starray} {syntax /  iter} {iter:4} {#1}
  }

       

%%%%%%%%%%%%%%%
%%% \starray_next_iter:n
%%% \starray_next_iter:nTF
%%%%%%%%%%%%%%%
\__starray_cs_prg_duo_generate:NNnn
  \starray_next_iter:n
  \c__starray_no_idx_ending_bool
  {
    \__starray_basest_incr_iter:NTF
      \l__starray_parsed_base_st
      {}  { \__starray_set_rtn_false: }

    \__starray_rtn:
  }
  {
        \msg_warning:nnnn {starray} {syntax /  iter} {iter:5} {#1}
  }


%%% \c__starray_..._base_st
%%%        \c{ -infix- _ihash_prop}                   %% #1
%%%        \c{ -infix- _base_iter_int }               %% #2
%%%        \c{ -infix- _base_cnt_int }                %% #3
%%%        \c{ -ref- _defkeys_prop}                   %% #4
%%%        \c{ -ref- _defstkeys_prop}                 %% #5
%%%        {-ref-}{-infix-}                           %% #6#7
%%%    \s__end
%%%%%%
%%% \__starray_basest_get_term:NN
%%% \__starray_basest_get_term:cN
%%% \__starray_basest_get_term:wN
%%%%%%
\__starray_cs_wgen:nnnn
  {__starray_basest_get_term}{N}{ # 1 # 2 # 3 \s__end # 4 }
  {
    \prop_get:NeN #1 {\int_use:N #2} \l__starray_tmp_term_st
    \tl_gset_eq:NN #4 \l__starray_tmp_term_st
  }



\RequirePackage{tokglobalstack}

\globalstack_csnew:n    {__starray_istack}
\cs_generate_variant:Nn \__starray_istack_gpush:n {e}

\cs_new_protected:Npn \__starray_istack_push:
  {
    \bool_if:NTF \g__starray_iterate_bool
      {
        \__starray_istack_gpush:e
          {
            \exp_not:N \tl_gset:Nn   \exp_not:N \g__starray_iterate_base_st { \exp_not:o \g__starray_iterate_base_st }
            \exp_not:N \tl_gset:Nn   \exp_not:N \g__starray_iterate_term_st { \exp_not:o \g__starray_iterate_term_st }
            \exp_not:N \bool_gset_true:N \exp_not:N \g__starray_iterate_bool
          }        
      }
      {
        \__starray_istack_gpush:e
          {
            \exp_not:N \tl_gset:Nn   \exp_not:N \g__starray_iterate_base_st { \exp_not:o \g__starray_iterate_base_st }
            \exp_not:N \tl_gset:Nn   \exp_not:N \g__starray_iterate_term_st { \exp_not:o \g__starray_iterate_term_st }
            \exp_not:N \bool_gset_false:N \exp_not:N \g__starray_iterate_bool
          }        
      }      
  }
\cs_set_eq:NN \__starray_istack_pop: \__starray_istack_gpop:

\bool_new:N \g__starray_iterate_bool
\tl_new:N   \g__starray_iterate_base_st
\tl_new:N   \g__starray_iterate_term_st


%%%%%%%%%%%%%%%
%%%
%%% \starray_iterate_over:nn
%%% \starray_iterate_over:nnTF
%%%
%%%%%%%%%%%%%%%
\__starray_cs_prg_duo_generate:NNnn
  \starray_iterate_over:nn
  \c__starray_no_idx_ending_bool
  {
    \__starray_istack_push:

    \tl_gset_eq:NN \g__starray_iterate_base_st \l__starray_parsed_base_st
    \bool_gset_true:N \g__starray_iterate_bool

    \__starray_basest_set_iter:NnTF
      \g__starray_iterate_base_st {1}
      {
        \__starray_basest_get_term:NN
          \g__starray_iterate_base_st
          \g__starray_iterate_term_st
        \bool_do_while:Nn \g__starray_iterate_bool
          {
            #2

            \__starray_basest_incr_iter:NTF
              \g__starray_iterate_base_st
              {
                \__starray_basest_get_term:NN
                  \g__starray_iterate_base_st
                  \g__starray_iterate_term_st
              }
              { 
                \bool_gset_false:N \g__starray_iterate_bool
              }
          }
          \__starray_msg_clear:  %% to clear the  "iter_incr" warning/error

          \__starray_set_rtn_true: 
      }  
      { 
        \__starray_msg:nnnn {syntax /  iter} {iter:6a} {#1} {} 
        \__starray_msg_dispatch:

        \__starray_set_rtn_false: 
      }
    \__starray_istack_pop:
    \__starray_rtn:
  }
  {
        \msg_warning:nnnn {starray} {syntax /  iter} {iter:6} {#1}
  }



%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%
%%%%
%%%% set/get properties
%%%%
%%%%
%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%


%%% \c__starray_..._term_st
%%%        \c{ -infix- _term_prop }                  %% #1
%%%        { -infix- }                               %% #2
%%%        { -val- }  %% iter's val for this entry   %% #3
%%%        { -idx- }                                 %% #4
%%%        \c{ -ref- _defstkeys_prop}                %% #5
%%%    \s__end
%%%%%%
%%% \__starray_termst_get_prop:Nn
%%% \__starray_termst_get_prop:cn
%%% \__starray_termst_get_prop:wn
%%%%%%
\__starray_cs_wgen:nnnn
  {__starray_termst_get_prop}{n}{ # 1 # 2 \s__end # 3 }
  {
    \prop_item:Nn #1 {#3}
  }

%%%%%%%%%%%%%%%
%%% \starray_get_prop:nn
%%% \starray_parsed_get_prop:Nn
%%% \starray_parsed_get_prop:n => checked/nocheck
%%%%%%%%%%%%%%%
\__starray_cs_generate:nnNnnn 
  {get_prop}{n} \c__starray_idx_ending_bool
  {
    \__starray_termst_get_prop:wn #1 {#3}
  }
  {
    \__starray_msg_dispatch:
    \msg_warning:nnnn {starray} {syntax /  prop} 
      {get:1} {#1}
  } % returns nothing by default
  {
    \msg_warning:nnnn {starray} {syntax /  parsed} 
      {parsed:1} {\starray_parsed_get_prop:n}
  }
  

%%% \c__starray_..._term_st
%%%        \c{ -infix- _term_prop }                  %% #1
%%%        { -infix- }                               %% #2
%%%        { -val- }  %% iter's val for this entry   %% #3
%%%        { -idx- }                                 %% #4
%%%        \c{ -ref- _defstkeys_prop}                %% #5
%%%    \s__end
%%%%%%
%%% \__starray_termst_get_prop:NnN
%%% \__starray_termst_get_prop:cnN
%%% \__starray_termst_get_prop:wnN
%%%%%%
\__starray_cs_wgen:nnnn
  {__starray_termst_get_prop}{nN}{ # 1 # 2 \s__end # 3 # 4 }
  {
    \prop_get:NnNF #1 {#3} #4
      { \tl_clear:N #4 }
  }

%%%%%%
%%% \__starray_termst_get_propTF:NnN
%%% \__starray_termst_get_propTF:cnN
%%% \__starray_termst_get_propTF:wnN
%%%%%%
\__starray_cs_wgen:nnnn
  {__starray_termst_get_propTF}{nN}{ # 1 # 2 \s__end # 3 # 4 }
  {
    \prop_get:NnNTF #1 {#3} #4
      { \prg_return_true: }
      { 
        \tl_clear:N #4
        \prg_return_false:
      }
  }


%%%%%%%%%%%%%%%
%%% \starray_get_prop:nnN
%%% \starray_parsed_get_prop:NNnN
%%% \starray_parsed_get_prop:nN => checked/nocheck
%%%%%%%%%%%%%%%
\__starray_cs_generate:nnNnnn 
  {get_prop}{nN}  \c__starray_idx_ending_bool
  {
    \__starray_termst_get_prop:wnN #1
      {#3} #4    
  }
  {
    \__starray_msg_dispatch:
    \msg_warning:nnnn {starray} {syntax /  prop} 
      {get:2} {#1}
  } % returns nothing by default
  {
    \msg_warning:nnnn {starray} {syntax /  parsed} 
      {parsed:2} {\starray_parsed_get_prop:nN}
  }
  

%%%%%%%%%%%%%%%
%%%
%%% \starray_get_prop:nnN
%%% \starray_parsed_get_prop:NNnN
%%% \starray_parsed_get_prop:nN => checked/nocheck
%%%
%%%%%%%%%%%%%%%
\__starray_prg_generate:nnNnnn 
  {get_prop}{nN} \c__starray_idx_ending_bool
  {
    \__starray_termst_get_propTF:wnN #1
      {#3} #4    
  }
  { \__starray_msg_clear: }  %% This will be F case of \__starray_parser:NeTF, not expandable anyway
  { }                                   %% This will be F case of \bool_if:NTF

\__starray_prg_undef_p:nn {get_prop}{nN}


%%% \c__starray_..._term_st
%%%        \c{ -infix- _term_prop }                  %% #1
%%%        { -infix- }                               %% #2
%%%        { -val- }  %% iter's val for this entry   %% #3
%%%        { -idx- }                                 %% #4
%%%        \c{ -ref- _defstkeys_prop}                %% #5
%%%    \s__end
%%%%%%
%%% \__starray_termst_if_inTF:Nn
%%% \__starray_termst_if_inTF:cn
%%% \__starray_termst_if_inTF:wn
%%%%%%
\__starray_cs_wgen:nnnn
  {__starray_termst_if_inTF}{n}{ # 1 # 2 \s__end # 3 }
  {
    \prop_if_in:NnTF #1 {#3}
      \prg_return_true:
      \prg_return_false:
  }


%%%%%%%%%%%%%%%
%%% \starray_if_in:nnTF 
%%% \starray_parsed_if_in:NNnTF
%%% \starray_parsed_if_in:nNTF => checked/nocheck
%%%%%%%%%%%%%%%
\__starray_prg_generate:nnNnnn 
  {if_in}{n} \c__starray_idx_ending_bool
  {
    \__starray_termst_if_inTF:wn #1 {#3}
  }
  { \__starray_msg_clear:  } %% This will be F case of \__starray_parser:NeTF, not expandable anyway
  { }                                   %% This will be F case of \bool_if:NTF
  


%%% \c__starray_..._base_st
%%%        \c{ -infix- _ihash_prop}                   %% #1
%%%        \c{ -infix- _base_iter_int }               %% #2
%%%        \c{ -infix- _base_cnt_int }                %% #3
%%%        \c{ -ref- _defkeys_prop}                   %% #4
%%%        \c{ -ref- _defstkeys_prop}                 %% #5
%%%        {-ref-}{-infix-}                           %% #6#7
%%%    \s__end
%%%%%%
%%% \__starray_basest_get_cnt:N
%%% \__starray_basest_get_cnt:c
%%% \__starray_basest_get_cnt:w
%%%%%%
\__starray_cs_wgen:nnnn
  {__starray_basest_get_cnt}{}{ # 1 # 2 # 3 # 4 \s__end }
  { \int_use:N #3 }

%%%%%%
%%% \__starray_basest_get_cnt:NN
%%% \__starray_basest_get_cnt:cN
%%% \__starray_basest_get_cnt:wN
%%%%%%
\__starray_cs_wgen:nnnn
  {__starray_basest_get_cnt}{N}{ # 1 # 2 # 3 # 4 \s__end # 5 }
  { \int_set_eq:NN #5 #3 }

%%%%%%
%%% \__starray_basest_get_iter:N
%%% \__starray_basest_get_iter:c
%%% \__starray_basest_get_iter:w
%%%%%%
\__starray_cs_wgen:nnnn
  {__starray_basest_get_iter}{}{ # 1 # 2 # 3 \s__end }
  { \int_use:N #2 }

%%%%%%
%%% \__starray_basest_get_iter:NN
%%% \__starray_basest_get_iter:cN
%%% \__starray_basest_get_iter:wN
%%%%%%
\__starray_cs_wgen:nnnn
  {__starray_basest_get_iter}{N}{ # 1 # 2 # 3 \s__end # 4 }
  { \int_set_eq:NN #4 #2 }


%%%%%%%%%%%%%%%
%%% \starray_get_cnt:n
%%% \starray_parsed_get_cnt:NN
%%% \starray_parsed_get_cnt: => checked/nocheck
%%%%%%%%%%%%%%%
\__starray_cs_generate:nnNnnn 
  {get_cnt}{}  \c__starray_no_idx_ending_bool
  {
    \__starray_basest_get_cnt:w #2 
  } 
  {
    \__starray_msg_dispatch:
    \msg_warning:nnnn {starray} {syntax /  prop} 
      {get:3} {#1}
  } % returns nothing by default
  {
    \msg_warning:nnnn {starray} {syntax /  parsed} 
      {parsed:3} {\starray_parsed_get_cnt:}
  }
  

%%%%%%%%%%%%%%%
%%% \starray_get_cnt:nN
%%% \starray_parsed_get_cnt:NNN
%%% \starray_parsed_get_cnt:N => checked/nocheck
%%%%%%%%%%%%%%%
\__starray_cs_generate:nnNnnn 
  {get_cnt}{N}  \c__starray_no_idx_ending_bool
  {
    \__starray_basest_get_cnt:wN #2 #3
  }
  {
    \__starray_msg_dispatch:
    \msg_warning:nnnn {starray} {syntax /  prop} 
      {get:4} {#1}
  } % returns nothing by default
  {
    \msg_warning:nnnn {starray} {syntax /  parsed} 
      {parsed:4} {\starray_parsed_get_cnt:N}
  }
  


%%%%%%%%%%%%%%%
%%% \starray_get_cnt:nNTF
%%% \starray_parsed_get_cnt:NNNTF
%%% \starray_parsed_get_cnt:NTF => checked/nocheck
%%%%%%%%%%%%%%%
\__starray_prg_generate:nnNnnn 
  {get_cnt}{N} \c__starray_no_idx_ending_bool
  {
    \__starray_basest_get_cnt:wN #2 #3
    \prg_return_true:
  }
  { \__starray_msg_clear:  }  %% This will be F case of \__starray_parser:NeTF, not expandable anyway
  { }                                    %% This will be F case of \bool_if:NTF

\__starray_prg_undef_p:nn {get_cnt}{N}



%%%%%%%%%%%%%%%
%%%
%%% \starray_get_iter:n
%%% \starray_parsed_get_iter:NN
%%% \starray_parsed_get_iter: => checked/nocheck
%%%
%%%%%%%%%%%%%%%
\__starray_cs_generate:nnNnnn 
  {get_iter}{}  \c__starray_no_idx_ending_bool
  {
    \__starray_basest_get_iter:w #2
  }
  {
    \__starray_msg_dispatch:
    \msg_warning:nnnn {starray} {syntax /  prop} 
      {get:5} {#1}
  } % returns nothing by default
  {
    \msg_warning:nnnn {starray} {syntax /  parsed} 
      {parsed:5} {\starray_parsed_get_iter:}
  }



%%%%%%%%%%%%%%%
%%% \starray_get_iter:nN
%%% \starray_parsed_get_iter:NNN
%%% \starray_parsed_get_iter:N => checked/nocheck
%%%%%%%%%%%%%%%
\__starray_cs_generate:nnNnnn 
  {get_iter}{N}  \c__starray_no_idx_ending_bool
  {
    \__starray_basest_get_iter:wN #2 #3
  }
  {
    \__starray_msg_dispatch:
    \msg_warning:nnnn {starray} {syntax /  prop} 
      {get:6} {#1}
  } % returns nothing by default
  {
    \msg_warning:nnnn {starray} {syntax /  parsed} 
      {parsed:6} {\starray_parsed_get_iter:N}
  }


%%%%%%%%%%%%%%% 
%%% \starray_get_iter:nnTF 
%%% \starray_parsed_get_iter:NNnTF
%%% \starray_parsed_get_iter:nNTF => checked/nocheck
%%%%%%%%%%%%%%%
\__starray_prg_generate:nnNnnn 
  {get_iter}{N} \c__starray_no_idx_ending_bool
  {
    \__starray_basest_get_iter:wN #2 #3
    \prg_return_true:
  }
  { \__starray_msg_clear:  } %% This will be F case of \__starray_parser:NeTF, not expandable anyway
  { }                                   %% This will be F case of \bool_if:NTF

\__starray_prg_undef_p:nn
  {get_iter}{N}



%%% \c__starray_..._term_st
%%%        \c{ -infix- _term_prop }                  %% #1
%%%        { -infix- }                               %% #2
%%%        { -val- }  %% iter's val for this entry   %% #3
%%%        { -idx- }                                 %% #4
%%%        \c{ -ref- _defstkeys_prop}                %% #5
%%%    \s__end
%%%%%%
%%% \__starray_termst_get_unique_id:NN
%%% \__starray_termst_get_unique_id:cN
%%% \__starray_termst_get_unique_id:wN
%%%%%%
\__starray_cs_wgen:nnnn
  {__starray_termst_get_unique_id}{N}{ # 1 # 2 # 3 \s__end # 4 }
  {
    \tl_set:Nn #4 {#2}
  }

%%%%%%%%%%%%%%%
%%%
%%% \starray_get_unique_id:nN
%%% \starray_parsed_get_unique_id:NNN
%%% \starray_parsed_get_unique_id:N => checked/nocheck
%%%
%%%%%%%%%%%%%%%
\__starray_cs_generate:nnNnnn 
  {get_unique_id}{N}  \c__starray_idx_ending_bool
  {
    \__starray_termst_get_unique_id:wN #1 #3
  }
  {
    \__starray_msg_dispatch:
    \msg_warning:nnnn {starray} {syntax /  prop} 
      {get:7} {#1}
  } % returns nothing by default
  {
    \msg_warning:nnnn {starray} {syntax /  parsed} 
      {parsed:7} {\starray_parsed_get_unique_id:N}
  }


%%%%%%%%%%%%%%% 
%%%
%%% \starray_get_unique_id:nNTF 
%%% \starray_parsed_get_unique_id:NNNTF
%%% \starray_parsed_get_unique_id:NTF => checked/nocheck
%%%
%%%%%%%%%%%%%%%
\__starray_prg_generate:nnNnnn 
  {get_unique_id}{N} \c__starray_idx_ending_bool
  {
    \__starray_termst_get_unique_id:wN #1 #3
    \prg_return_true:
  }
  { \__starray_msg_clear:  } %% This will be F case of \__starray_parser:NeTF, not expandable anyway
  { }                                   %% This will be F case of \bool_if:NTF

\__starray_prg_undef_p:nn
  {get_unique_id}{N}


%%% \c__starray_..._term_st
%%%        \c{ -infix- _term_prop }                  %% #1
%%%        { -infix- }                               %% #2
%%%        { -val- }  %% iter's val for this entry   %% #3
%%%        { -idx- }                                 %% #4
%%%        \c{ -ref- _defstkeys_prop}                %% #5
%%%    \s__end
%%%%%%
%%% \__starray_termst_set_prop:NNnn
%%% \__starray_termst_set_prop:cNnn
%%% \__starray_termst_set_prop:wNnn
%%%%%%
\__starray_cs_wgen:nnnn
  {__starray_termst_set_prop}{Nnn}{ # 1 # 2 \s__end # 3 # 4 # 5 }
  { #3  %% this will be either \prop_put: or \prop_gput:
     #1 {#4} {#5} }


%%%%%%%%%%%%%%%
%%%%
%%%% \starray_set_prop
%%%%
%%%%%%%%%%%%%%%


%%%%%%%%%%%%%%%
%%% \starray_set_prop:nnn
%%% \starray_set_prop:nnnTF
%%%%%%%%%%%%%%%
\__starray_cs_prg_duo_generate:NNnn
  \starray_set_prop:nnn
  \c__starray_idx_ending_bool
  {
    \__starray_termst_set_prop:NNnn  
      \l__starray_parsed_term_st 
      \prop_put:Nnn 
      {#2}{#3}
    \prg_return_true:
  }
  {
        \msg_warning:nnnn {starray} {syntax /  prop} 
          {set:1} {#1}
  }
\cs_generate_variant:Nn \starray_set_prop:nnn {nnV}
\prg_generate_conditional_variant:Nnn \starray_set_prop:nnn { nnV } {T, F , TF } %%%

%%%%%%%%%%%%%%%
%%% \starray_gset_prop:nnn
%%% \starray_gset_prop:nnnTF
%%%%%%%%%%%%%%%
\__starray_cs_prg_duo_generate:NNnn
  \starray_gset_prop:nnn
  \c__starray_idx_ending_bool
  {
    \__starray_termst_set_prop:NNnn  
      \l__starray_parsed_term_st 
      \prop_gput:Nnn 
      {#2}{#3}
    \prg_return_true:
  }
  {
        \msg_warning:nnnn {starray} {syntax /  prop} 
          {set:1} {#1}
  }
\cs_generate_variant:Nn \starray_gset_prop:nnn {nnV}
\prg_generate_conditional_variant:Nnn \starray_gset_prop:nnn { nnV } {T, F , TF } %%%



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

\cs_new:Npn \__starray_set_parse_end_chk:w #1 ] \q_nil \q_stop
  {
    \tl_if_empty:nTF {#1}
      \prg_return_true:
      \prg_return_false:  %% syntax ERR (something after  )
  }

%
% Not expandable. DO NOT generate a predicate version! 
% but, already a :w conditional anyway (internal)
%
\prg_new_conditional:Npnn \__starray_set_parse_end:w  #1 ] #2 \q_stop { TF}
  {
    \quark_if_nil:nTF {#2}
      { \prg_return_false: } %% syntax ERR
      {
        \tl_set:Nn \l__starray_parser_tmp_A_tl {#1}
        \__starray_set_parse_end_chk:w #2 \q_stop
      }
  }


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


%
% Not expandable. DO NOT generate a predicate version! 
% but, already a :w conditional anyway (internal)
%
\prg_new_conditional:Npnn \__starray_set_parse_begin:w #1 [ #2 \q_stop { TF}
  {
    \tl_set:Nn \l__starray_parser_tmp_B_tl {#1}
    \quark_if_nil:nTF {#2}
      {               % no 'term' ref, just array_name (current/iter term)
        \tl_clear:N \l__starray_parser_tmp_A_tl
        \prg_return_true:
      }
      {
        \__starray_set_parse_aux:wTF #2 \q_stop
          \prg_return_true:
          \prg_return_false:
      }
  }


\cs_new:Npn \__starray_set_from_keyval_parse:n #1
  { }   % hanging key, no value set, silently ignored.


%%% \c__starray_..._base_st
%%%        \c{ -infix- _ihash_prop}                   %% #1
%%%        \c{ -infix- _base_iter_int }               %% #2
%%%        \c{ -infix- _base_cnt_int }                %% #3
%%%        \c{ -ref- _defkeys_prop}                   %% #4
%%%        \c{ -ref- _defstkeys_prop}                 %% #5
%%%        {-ref-}{-infix-}                           %% #6#7
%%%    \s__end
%%%%%%
%%% \__starray_basest_set_from_keyval_parse:N
%%% \__starray_basest_set_from_keyval_parse:c
%%% \__starray_basest_set_from_keyval_parse:w
%%%%%%
\__starray_cs_wgen:nnnn
  {__starray_basest_set_from_keyval_parse}{nn}{ # 1 # 2 # 3 \s__end # 4 # 5 }
  {
    \tl_if_blank:nTF {#4}
      {
        \prop_get:NeNTF #1 {\int_use:N #2} \l__starray_tmp_term_st
          {
            \keyval_parse:een
              { \exp_not:N \__starray_set_from_keyval_parse:n   }
              { 
                \exp_not:N \__starray_termst_set_from_keyval_parse:wnn
                \exp_not:o \l__starray_tmp_term_st 
              }  
              { #5 }
          }
          {%%err, non-instatiated
            \__starray_msg:nnee {reference / iter}
              {setkeyval:3} {--} {#4}
          }
      }
      {
        \prop_get:NnNTF #1 {#4} \l__starray_tmp_term_st
          {
            \keyval_parse:een
              { \exp_not:N \__starray_set_from_keyval_parse:n   }
              { 
                \exp_not:N \__starray_termst_set_from_keyval_parse:wnn
                \exp_not:o \l__starray_tmp_term_st 
              }  
              { #5 }
          }
          {%%err, invalid hash
            \__starray_msg:nnee {reference / iter}
              {setkeyval:3} {--} {#4}
          }
      }
  }
\cs_generate_variant:Nn \__starray_basest_set_from_keyval_parse:Nnn {co}

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

%%% \c__starray_..._term_st
%%%        \c{ -infix- _term_prop }                  %% #1
%%%        { -infix- }                               %% #2
%%%        { -val- }  %% iter's val for this entry   %% #3
%%%        { -idx- }                                 %% #4
%%%        \c{ -ref- _defstkeys_prop}                %% #5
%%%    \s__end
%%% #6 => prop/struct(key from keyval)
%%% #7 => val/keyval (val from keyval)
%%%%%%
%%% \__starray_termst_set_from_keyval_parse:N
%%% \__starray_termst_set_from_keyval_parse:c
%%% \__starray_termst_set_from_keyval_parse:w
%%%%%%
\__starray_cs_wgen:nnnn
  {__starray_termst_set_from_keyval_parse}{nn}{ # 1 # 2 # 3 # 4 # 5 \s__end # 6 # 7 }
  {
    \__starray_set_parse_begin:wTF #6 [ \q_nil \q_stop
      {
        \seq_if_in:NeTF #5 \l__starray_parser_tmp_B_tl
          {
            \__starray_basest_set_from_keyval_parse:con
              {c__starray_prfix_. #2 . \l__starray_parser_tmp_B_tl _base_st } 
              \l__starray_parser_tmp_A_tl {#7}
          }
          {
            \tl_if_empty:NTF \l__starray_parser_tmp_A_tl
              {
                \__starray_put:Nen #1 \l__starray_parser_tmp_B_tl {#7}
              }
              {%%err  invalid ref / not a substructure
                \__starray_msg:nnee {syntax / structure-ref}
                  {setkeyval:4} {#6} {\l__starray_parser_tmp_B_tl}
              }
          }
      }
      {%%err invalid ref/syntax
        \__starray_msg:nnnn {syntax / term}
          {setkeyval:5}{#6}{}
      }
  }
      
%%%%%%%%%%%%%%%
%%% \__starray_set_from_keyval:nn
%%% \__starray_set_from_keyval:nnTF
%%%%%%%%%%%%%%%
\__starray_cs_prg_duo_generate:NNnn
  \__starray_set_from_keyval:nn
  \c__starray_idx_ending_bool
  {
        %%% just in case, for msg_err messages
        \tl_set:Nn \l__starray_from_keyval_orgref_tl {#1}
        
        \keyval_parse:een
          { \exp_not:N \__starray_set_from_keyval_parse:n   }
          { 
            \exp_not:N \__starray_termst_set_from_keyval_parse:wnn
            \exp_not:o \l__starray_parsed_term_st 
          }
          { #2 }

        \__starray_msg_dispatch:
        \__starray_rtn:
  }
  {
      \msg_warning:nnnn {starray} {syntax /  prop} 
        {setkeyval:1} {#1}
  }


%\cs_new_protected:Npn \starray_set_from_keyval:nn #1#2
%  {
%    \cs_set_eq:NN \__starray_put:cnn \prop_put:cnn
%    \__starray_set_from_keyval:nn {#1}{#2}
%  }
\cs_new_protected:Npn \starray_set_from_keyval:nn
  { 
    \cs_set_eq:NN \__starray_put:Nen \prop_put:Nen
    \__starray_set_from_keyval:nn
  }


%\cs_new_protected:Npn \starray_gset_from_keyval:nn #1#2
%  {
%    \cs_set_eq:NN \__starray_put:cnn \prop_gput:cnn
%    \__starray_set_from_keyval:nn {#1}{#2}
%  }
\cs_new_protected:Npn \starray_gset_from_keyval:nn
  { 
    \cs_set_eq:NN \__starray_put:Nen \prop_gput:Nen
    \__starray_set_from_keyval:nn
  }

  
%%
%% TODO: Might be worth a bit (more) of optimization...
%% \cs_new_protected: \starray_set_from_keyval:nnTF (etc...) with the two parameters being implicit...
%%  
%\prg_new_protected_conditional:Npnn \starray_set_from_keyval:nn #1#2 {T, F, TF}
%  {
%    \cs_set_eq:NN \__starray_put:cnn \prop_put:cnn
%    \__starray_set_from_keyvalTF:nn {#1}{#2}
%  }
\cs_new_protected:Npn \starray_set_from_keyval:nnT 
  { 
    \cs_set_eq:NN \__starray_put:Nen \prop_put:Nen
    \__starray_set_from_keyval:nnT
  }
\cs_new_protected:Npn \starray_set_from_keyval:nnF
  { 
    \cs_set_eq:NN \__starray_put:Nen \prop_put:Nen
    \__starray_set_from_keyval:nnF
  }
\cs_new_protected:Npn \starray_set_from_keyval:nnTF
  { 
    \cs_set_eq:NN \__starray_put:Nen \prop_put:Nen
    \__starray_set_from_keyval:nnTF
  }
  
%\prg_new_protected_conditional:Npnn \starray_gset_from_keyval:nn #1#2 {T, F, TF}
%  {
%    \cs_set_eq:NN \__starray_put:cnn \prop_gput:cnn
%    \__starray_set_from_keyvalTF:nn {#1}{#2}
%  }
\cs_new_protected:Npn \starray_gset_from_keyval:nnT
  { 
    \cs_set_eq:NN \__starray_put:Nen \prop_gput:Nen
    \__starray_set_from_keyval:nnT
  }
\cs_new_protected:Npn \starray_gset_from_keyval:nnF
  { 
    \cs_set_eq:NN \__starray_put:Nen \prop_gput:Nen
    \__starray_set_from_keyval:nnF
  }
\cs_new_protected:Npn \starray_gset_from_keyval:nnTF 
  { 
    \cs_set_eq:NN \__starray_put:Nen \prop_gput:Nen
    \__starray_set_from_keyval:nnTF
  }


%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%
%%%%
%%%% starray ref/address parser using quarks
%%%% could be done with seq_split and regex but
%%%% would have been even more cumbersome (and slow)
%%%%
%%%% <starray_ref> := <array_ref> [ . <starray_ref> ]
%%%% <array_ref>   := <array_name> [ <term_ref> ]
%%%% <term_ref>    := \[ <number/hash> \]
%%%%
%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%
\cs_new:Npn \__starray_term_parser_end_chk:w #1 ] \q_nil \q_stop
  {
    \tl_if_empty:nTF {#1}
      \prg_return_true:
      \prg_return_false:  %% syntax ERR (something after  )
  }


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


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


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

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


%%% \c__starray_..._base_st
%%%        \c{ -infix- _ihash_prop}                   %% #1
%%%        \c{ -infix- _base_iter_int }               %% #2
%%%        \c{ -infix- _base_cnt_int }                %% #3
%%%        \c{ -ref- _defkeys_prop}                   %% #4
%%%        \c{ -ref- _defstkeys_prop}                 %% #5
%%%        {-ref-}{-infix-}                           %% #6#7
%%%    \s__end
%%%%%%
%%% \__starray_basest_if_valid_idx:Nn
%%% \__starray_basest_if_valid_idx:cn
%%% \__starray_basest_if_valid_idx:wn
%%%%%%
\__starray_prg_wgen:nnnn
  {__starray_basest_if_valid_idx}{n}{ # 1 # 2 # 3 \s__end # 4 }
  {
    \tl_if_empty:NTF #4
      {
        \prop_get:NeNTF #1 {\int_use:N #2} \l__starray_parsed_term_st
          {
            \__starray_termst_get_infix:NN
              \l__starray_parsed_term_st 
              \l__starray_tmpb_tl  
              
            \tl_set:Ne \l__starray_parsed_ref_tl { . \l__starray_tmpb_tl }
            \prg_return_true:
          }
          {
            \tl_set_eq:NN \l__starray_parsed_term_st \c__starray_empty_hash_term_st
            \prg_return_false:
          }
      }
      {
        \prop_get:NeNTF #1 {#4} \l__starray_parsed_term_st
          { 
            \__starray_termst_get_infix:NN
              \l__starray_parsed_term_st 
              \l__starray_tmpb_tl  

            \tl_set:Ne \l__starray_parsed_ref_tl { . \l__starray_tmpb_tl }
            \prg_return_true:
          }
          {
            \tl_set_eq:NN \l__starray_parsed_term_st \c__starray_empty_hash_term_st
            \prg_return_false:
          }
      }
  }
  
  
%%%
%%% small surprise, it was possible to _protected this... TODO: further test it.
%%%
\cs_new_protected:Npn \__starray_ref_parse:nw #1 . #2 \q_stop
  {
    %% just if case, for _msg_
    \tl_put_right:Nn \l__starray_parsed_tl {#1}

    \__starray_term_parse_begin:wTF #1 [ \q_nil \q_stop
      {                              % syntax ok so far.
                                     % TODO: verify instance validity hash/index
                                     % vars: \l__starray_parsed_term_tl
                                     %       \l__starray_parsed_idx_tl
        \tl_put_right:Ne \l__starray_parsed_ref_tl 
          { . \l__starray_parsed_term_tl }

        \__starray_if_exist:cTF 
          { c__starray_prfix_  \l__starray_parsed_ref_tl _base_st }
          {
            \quark_if_nil:nTF {#2}
            {       % this is the 'last one'
                
              \tl_set_eq:Nc
                \l__starray_parsed_base_st { c__starray_prfix_  \l__starray_parsed_ref_tl _base_st }
                                
              \bool_if:NTF \l__starray_parser_no_idx_ending_bool
              {                                  % assuming it is to add a term...
                \tl_if_empty:NTF \l__starray_parsed_idx_tl
                { }       % done. correct
                {
                  \bool_set_false:N \l__starray_parser_OK_bool
                  \__starray_msg:nnee {syntax / ref-syntax-err} {parser:1} 
                    {\l__starray_parsing_term_tl} 
                    {invalid~index~\l__starray_parsed_idx_tl~(at~the~end)}              
                } % err !
              }
              { % assuming it is to set/get a property... _base_st maps to \__starray_if_valid_idx:NNNNNnnTF 
                % This will set \l__starray_parsed_term_st (if it exists)
                
                \__starray_basest_if_valid_idx:cnTF
                  { c__starray_prfix_  \l__starray_parsed_ref_tl _base_st } \l__starray_parsed_idx_tl
                  { }      % done, finish, ok
                  {
                    \bool_set_false:N \l__starray_parser_OK_bool
                    \__starray_msg:nnee {syntax / ref-syntax-err} {parser:2} 
                      {\l__starray_parsing_term_tl} 
                      {invalid~index~\l__starray_parsed_idx_tl}    
                  }
              }
            }
            {                       
              % assuming it is to set/get a property... _base_st maps to \__starray_if_valid_idx:NNNNNnnTF 
              % This will set \l__starray_parsed_term_st (if it exists)
              \__starray_basest_if_valid_idx:cnTF
                { c__starray_prfix_  \l__starray_parsed_ref_tl _base_st } \l__starray_parsed_idx_tl
                {
                  \__starray_ref_parse:nw #2 \q_stop
                }      % recurse next term
                {
                  \bool_set_false:N \l__starray_parser_OK_bool
                  \__starray_msg:nnee {syntax / ref-syntax-err} {parser:3} 
                    {\l__starray_parsing_term_tl} 
                    {invalid~index~\l__starray_parsed_idx_tl} 
                }
            }
          }
          {
            \bool_set_false:N \l__starray_parser_OK_bool
            \__starray_msg:nnee {syntax / ref-syntax-err} {parser:4} 
              {\l__starray_parsing_term_tl} 
              {invalid~struct~\l__starray_parsed_ref_tl} 
          } % invalid/ref err.
      }
      {
        \bool_set_false:N \l__starray_parser_OK_bool
        \__starray_msg:nnee {syntax / ref-syntax-err} {parser:5} 
          {\l__starray_parsing_term_tl} 
          {invalid~struct~#1~at~\l__starray_parsed_tl}         
      } % syntax/ref err.
  }

%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%
%%%%
%%%% parser 'true' returns:
%%%%                       \l__starray_parsed_ref_tl
%%%%
%%%%                       \l__starray_parsed_term_st !!! IF there is one!
%%%%                       \l__starray_parsed_base_st !!! always, if OK
%%%%
%%%% parser 'false' returns:
%%%%                       
%%%%
%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%
\cs_new_protected:Npn \__starray_parser:NnTF #1#2 
  {
    \bool_set_eq:NN \l__starray_parser_no_idx_ending_bool #1
    \bool_set_true:N \l__starray_parser_OK_bool

    \tl_clear:N \l__starray_parsed_ref_tl

%%% This is just for error/warning messages    
    \tl_set:Nn \l__starray_parsing_term_tl {#2}

    \__starray_ref_parse:nw #2 .\q_nil\q_stop

    \bool_if:NTF \l__starray_parser_OK_bool
  }
\cs_generate_variant:Nn \__starray_parser:NnTF {Ne}

\cs_new_protected:Npn \starray_term_parser:n #1
  {
    \__starray_parser:NeTF \c__starray_idx_ending_bool {#1}
      {
        \tl_gset_eq:NN \g__starray_parsed_saved_term_st \l__starray_parsed_term_st
        \tl_gset_eq:NN \g__starray_parsed_saved_base_st \l__starray_parsed_base_st
        
        \bool_gset_true:N \g__starray_parsed_bool
      }
      {
        \bool_gset_false:N \g__starray_parsed_bool
        \__starray_msg_dispatch:
        \msg_warning:nnnn {starray} {syntax /  term} 
          {term parser:1} {#1}
      }  
  }
  
\cs_new_protected:Npn \starray_term_syntax:n
  {
    \msg_warning:nnnnn {starray} {strict / deprecate} {dep:01}
      { \starray_term_syntax:n }
      { \starray_term_parser:n }
    \starray_term_parser:n
  }

\prg_new_protected_conditional:Npnn \starray_term_parser:n #1 {T, F, TF}
  {
    \__starray_parser:NeTF \c__starray_idx_ending_bool {#1}
      {
        \tl_gset_eq:NN \g__starray_parsed_saved_term_st \l__starray_parsed_term_st
        \tl_gset_eq:NN \g__starray_parsed_saved_base_st \l__starray_parsed_base_st

        \bool_gset_true:N \g__starray_parsed_bool
        \prg_return_true:
      }
      {
        \bool_gset_false:N \g__starray_parsed_bool
        \__starray_msg_clear:
        \prg_return_false:
      }
  }
\cs_new_protected:Npn \starray_term_syntax:nTF
  {
    \msg_warning:nnnnn {starray} {strict / deprecate} {dep:03}
      { \starray_term_syntax:nTF }
      { \starray_term_parser:nTF }
    \starray_term_parser:nTF
  }
\cs_new_protected:Npn \starray_term_syntax:nT
  {
    \msg_warning:nnnnn {starray} {strict / deprecate} {dep:04}
      { \starray_term_syntax:nT }
      { \starray_term_parser:nT }
    \starray_term_parser:nT
  }
\cs_new_protected:Npn \starray_term_syntax:nF
  {
    \msg_warning:nnnnn {starray} {strict / deprecate} {dep:05}
      { \starray_term_syntax:nF }
      { \starray_term_parser:nF }
    \starray_term_parser:nF
  }
  
\cs_new_protected:Npn \starray_term_parser:nN #1#2
  {
    \__starray_parser:NeTF \c__starray_idx_ending_bool {#1}
      {
        \tl_gset:Ne #2 
          {
            {\exp_not:o \l__starray_parsed_term_st}
            {\exp_not:o \l__starray_parsed_base_st}
          }          
      }
      {
        \__starray_msg_dispatch:
        \msg_warning:nnnn {starray} {syntax /  term} 
          {term parser:2} {#1}
      }  
  }  
  
\cs_new_protected:Npn \starray_term_parser:nNN #1#2#3
  {
    \msg_warning:nnnnn {starray} {strict / deprecate} {dep:02a}
      { \starray_term_syntax:nNN }
      { \starray_term_parser:nN }
    \starray_term_parser:nN {#1}{#2}
  }  
  
\cs_new_protected:Npn \starray_term_syntax:nNN
  {
    \msg_warning:nnnnn {starray} {strict / deprecate} {dep:02}
      { \starray_term_syntax:nNN }
      { \starray_term_parser:nNN }
    \starray_term_parser:nNN
  }
  
\prg_new_protected_conditional:Npnn \starray_term_parser:nN #1#2 {T, F, TF}
  {
    \__starray_parser:NeTF \c__starray_idx_ending_bool {#1}
      {
        \tl_gset:Ne #2 
          {
            {\exp_not:o \l__starray_parsed_term_st}
            {\exp_not:o \l__starray_parsed_base_st}
          }
        \prg_return_true:
      }
      {
        \__starray_msg_clear:
        \prg_return_false:
      }  
  }  
  
\cs_new_protected:Npn \starray_term_parser:nNNTF #1#2#3
  {
    \msg_warning:nnnnn {starray} {strict / deprecate} {dep:06a}
      { \starray_term_parser:nNNTF }
      { \starray_term_parser:nNTF }
    \starray_term_parser:nNTF {#1}{#2}
  }
\cs_new_protected:Npn \starray_term_parser:nNNT #1#2#3
  {
    \msg_warning:nnnnn {starray} {strict / deprecate} {dep:07a}
      { \starray_term_parser:nNNT }
      { \starray_term_parser:nNT }
    \starray_term_parser:nNT {#1}{#2}
  }
\cs_new_protected:Npn \starray_term_parser:nNNF #1#2#3
  {
    \msg_warning:nnnnn {starray} {strict / deprecate} {dep:08a}
      { \starray_term_parser:nNNF }
      { \starray_term_parser:nNF }
    \starray_term_parser:nNF {#1}{#2}
  }

  
\cs_new_protected:Npn \starray_term_syntax:nNNTF
  {
    \msg_warning:nnnnn {starray} {strict / deprecate} {dep:06}
      { \starray_term_syntax:nNNTF }
      { \starray_term_parser:nNNTF }
    \starray_term_parser:nNNTF
  }
\cs_new_protected:Npn \starray_term_syntax:nNNT
  {
    \msg_warning:nnnnn {starray} {strict / deprecate} {dep:07}
      { \starray_term_syntax:nNNT }
      { \starray_term_parser:nNNT }
    \starray_term_parser:nNNT
  }
\cs_new_protected:Npn \starray_term_syntax:nNNF
  {
    \msg_warning:nnnnn {starray} {strict / deprecate} {dep:08}
      { \starray_term_syntax:nNNF }
      { \starray_term_parser:nNNF }
    \starray_term_parser:nNNF
  }



%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%
%%%%
%%%% \..show_def commands
%%%%
%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%

%%% \c__starray...._ref_st
%%%        \c{ -ref- _defkeys_prop }                  %% #1
%%%        \c{ -ref- _defstkeys_seq }                 %% #2
%%%        {-ref-}                                    %% #3
%%%    \s__end
%%%%%%
%%% \__starray_refst_show_def:Nnn
%%% \__starray_refst_show_def:cnn
%%% \__starray_refst_show_def:wnn
%%%%%%
\__starray_cs_wgen:nnnn
  {__starray_refst_show_def}{nn}{  # 1 # 2 # 3 \s__end # 4 # 5 }
  {
      \tl_put_right:Nn \l__starray_show_tmp_tl
        {
          \__starray_show: > #4
          \tl_to_str:n {{#5}}
          \use:nn {~}{~} struct
          \use:nn {~}{~} =>
        }    
      \prop_map_inline:Nn  #1
        {
          \tl_put_right:Nn \l__starray_show_tmp_tl
            {
              \__starray_show: > #4 \use:nnn {~}{~}{~}
              \tl_to_str:n { {##1} }
              \use:nn {~}{~} => \use:nn {~}{~}
              \tl_to_str:n { {##2} }
            }          
        }
      \seq_map_inline:Nn #2
        {   
          \__starray_refst_show_def:cnn 
            { c__starray_prfix_. #3 . ##1 _ref_st } 
            {#4 \use:nnn {~}{~}{~}} {##1}
        }
  }


%%%%%%%%%%%%%%%
%%%%
%%%% \starray_show_def
%%%%
%%%%%%%%%%%%%%%
\cs_new_protected:Npn \starray_show_def:n #1
  {
    \__starray_if_exist:cTF { c__starray_prfix_.  #1 _ref_st}
      {
        \tl_clear:N \l__starray_show_tmp_tl
        \cs_set_eq:NN \__starray_show: \iow_newline:
        
        \__starray_refst_show_def:cnn 
          { c__starray_prfix_. #1 _ref_st } 
          { } {#1}
    
        \msg_show:nnxxx {starray}{info / show}
          { show~def }
          { The~ starray~ <#1> ~is~defined~as~follow: }
          { \l__starray_show_tmp_tl }
      }
      {
        \msg_warning:nnnn {starray}{strict / not defined}
          { show~def } { #1 }
      }
     
  }

\cs_new_protected:Npn \starray_show_def_in_text:n #1
  {
    \__starray_if_exist:cTF { c__starray_prfix_.  #1 _ref_st}
      {
        \tl_clear:N \l__starray_show_tmp_tl
        \cs_set_eq:NN \__starray_show: \par
        
        \__starray_refst_show_def:cnn 
          { c__starray_prfix_. #1 _ref_st } 
          { } {#1}
    
        \l__starray_show_tmp_tl
      }
      {
        \msg_warning:nnnn {starray}{strict / not defined}
          { show~def } { #1 }
      }
  }


%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%
%%%%
%%%% \..show_terms commands
%%%%
%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%

%%% \c__starray_..._term_st
%%%        \c{ -infix- _term_prop }                  %% #1
%%%        { -infix- }                               %% #2
%%%        { -val- }  %% iter's val for this entry   %% #3
%%%        { -idx- }                                 %% #4
%%%        \c{ -ref- _defstkeys_prop}                %% #5
%%%    \s__end
%%%%%%
%%% \__starray_termst_show_item:NnnN
%%% \__starray_termst_show_item:cnnN
%%% \__starray_termst_show_item:wnnN
%%%%%%
\__starray_cs_wgen:nnnn
  {__starray_termst_show_item}{nnN}{ # 1 # 2 # 3 # 4 # 5 \s__end # 6 # 7 # 8}
  {
    \tl_put_right:Nn \l__starray_show_tmp_tl
      {
        \__starray_show: > #6
        \tl_to_str:n { {#7} ~ (idx: ~ #4)}
        \use:nn {~}{~} =>
      }  

    \prop_map_inline:Nn #1
      {
        \tl_put_right:Nn \l__starray_show_tmp_tl
          {
            \__starray_show: > #6 \use:nnn {~}{~}{~}
            \tl_to_str:n { {##1} }
            \use:nn {~}{~} => ~ \tl_to_str:n { {##2} }
          }          
      }

    \seq_map_inline:Nn #8
      {
        \__starray_basest_show_terms:cnn
          {c__starray_prfix_. #2 . ##1 _base_st} 
          {#6 \use:nnn {~}{~}{~}} {##1}
      }


  }

%%% \c__starray_..._base_st
%%%        \c{ -infix- _ihash_prop}                   %% #1
%%%        \c{ -infix- _base_iter_int }               %% #2
%%%        \c{ -infix- _base_cnt_int }                %% #3
%%%        \c{ -ref- _defkeys_prop}                   %% #4
%%%        \c{ -ref- _defstkeys_prop}                 %% #5
%%%        {-ref-}{-infix-}                           %% #6#7
%%%    \s__end
%%%%%%
%%% \__starray_basest_show_terms:Nnn
%%% \__starray_basest_show_terms:cnn
%%% \__starray_basest_show_terms:wnn
%%%%%%
\__starray_cs_wgen:nnnn
  {__starray_basest_show_terms}{nn}{ # 1 # 2 # 3 # 4 # 5 # 6 # 7 \s__end # 8 # 9 }
  {
    \prop_map_inline:Nn #1
      {
        \__starray_termst_show_item:wnnN
          ##2 {#8} {#9[##1]} #5
      }
  }
  
%%%%%%%%%%%%%%%
%%%%
%%%% \starray_show_terms
%%%%
%%%%%%%%%%%%%%%
\cs_new_protected:Npn \starray_show_terms:n #1
  {
    \__starray_if_exist:cTF { c__starray_prfix_.  #1 _base_st}
      {
        \tl_clear:N \l__starray_show_tmp_tl
        \cs_set_eq:NN \__starray_show: \iow_newline:
           
        \__starray_basest_show_terms:cnn
          { c__starray_prfix_. #1 _base_st } 
          { } {#1}
    
        \msg_show:nnxxx {starray}{info / show}
          { show~terms }
          { The~ starray~ <#1> ~has~the~following~terms: }
          { \l__starray_show_tmp_tl }
      }
      {
        \msg_warning:nnnn {starray}{strict / not defined}
          { show~terms } { #1 }
      }
  }


\cs_new_protected:Npn \starray_show_terms_in_text:n #1
  {
    \__starray_if_exist:cTF { c__starray_prfix_.  #1 _base_st}
      {
        \tl_clear:N \l__starray_show_tmp_tl
        \cs_set_eq:NN \__starray_show: \par
        
        \__starray_basest_show_terms:cnn
          { c__starray_prfix_. #1 _base_st } 
          { } {#1}
      
         \l__starray_show_tmp_tl
      }
      {
        \msg_warning:nnnn {starray}{strict / not defined}
          { show~terms } { #1 }
      }
  }


