\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{recurrence}[2012/02/02 Recurrence Equation Support]


%\usepackage{tikz} 
\usepackage{xparse}
\usepackage{expl3}
\usepackage{l3regex}
\usepackage{l3int}

\ExplSyntaxOn

\tl_new:N     \l_recurrence_bin_tl
\tl_new:N     \l_recurrence_temp_seq
\tl_new:N     \l_recurrence_name_tl
\tl_new:N     \l_recurrence_index_tl
\tl_new:N     \l_recurrence_rhs_tl
\tl_new:N     \l_recurrence_guard_tl

\int_new:N      \l_recurrence_case_count_int
\int_new:N      \l_recurrence_current_case_count_int

% FOLLOWING NOT USED
\regex_const:Nn \c_recurrence_true_regex    { true }

\regex_const:Nn \c_recurrence_integer_regex { ^[-+]*[0-9]+$ }
\tl_const:Nn    \c_recurrence_prefix_tl { recurrence }

% #1 is expression
\cs_new_protected_nopar:Npn \recurrence_is_integer:nTF #1{
    \regex_match:NnTF \c_recurrence_integer_regex {#1}
}
\cs_generate_variant:Nn \recurrence_is_integer:nTF { V }

\cs_new_nopar:Npn \recurrence_case_name:nn #1#2{
    \tl_use:N \c_recurrence_prefix_tl _ #1 _ #2:n
}

% #1 is integer variable
\cs_new_nopar:Npn \recurrence_case_name:n #1{
    \recurrence_case_name:nn \l_recurrence_name_tl {\int_eval:n #1}
}

% #1 is index
% #2 is rhs
\cs_new_nopar:Npn \recurrence_define_constant:xx #1#2{%
    \int_set_eq:NN \l_recurrence_current_case_count_int \l_recurrence_case_count_int
    \int_incr:N \l_recurrence_case_count_int
    \cs_new_nopar:cpx {\recurrence_case_name:n \l_recurrence_current_case_count_int} ##1{
        \exp_not:N \int_compare:nTF {##1=#1} {#2}
                   {\cs:w \recurrence_case_name:n \l_recurrence_case_count_int
                    \cs_end:{##1}}
    }
}

% #1 is guard tl
% #2 is rhs   tl
\cs_new_nopar:Npn \recurrence_case_definition:xx #1#2{
    \int_set_eq:NN \l_recurrence_current_case_count_int \l_recurrence_case_count_int
    \int_incr:N \l_recurrence_case_count_int
    \cs_new_nopar:cpx {\recurrence_case_name:n \l_recurrence_current_case_count_int} ##1{
        \exp_not:N \bool_if:nTF {#1} {#2}
                   {\cs:w \recurrence_case_name:n \l_recurrence_case_count_int
                    \cs_end:{##1}}
    }
}

% #1 is name  tl
% #2 is index tl
\cs_new_nopar:Npn \recurrence_case_definition:NN #1#2{
    \recurrence_sanitise:VVN #1 #2 \l_recurrence_rhs_tl
    \recurrence_sanitise:VVN #1 #2 \l_recurrence_guard_tl
    \regex_replace_all:NnN \c_recurrence_true_regex
                           {\c{int_compare_p:n} \cB\{ 1 = 1 \cE\}}
                           \l_recurrence_guard_tl
    \recurrence_case_definition:xx \l_recurrence_guard_tl \l_recurrence_rhs_tl
}

% #1 is name
% #2 is index
% #3 is tl list
\cs_new_nopar:Npn \recurrence_sanitise:nnN #1#2#3{
    \regex_replace_all:nnN {#2} {\#1} #3
    \regex_replace_all:nnN {\b#1\[([^\]]+)\]} {\\#1:n \cB\{\1 \cE\}} #3
}
\cs_generate_variant:Nn \recurrence_sanitise:nnN {VV}

\cs_new_nopar:Npn \recurrence_error_definition:{
    \int_set_eq:NN \l_recurrence_current_case_count_int \l_recurrence_case_count_int
    \cs_new:cpx {\recurrence_case_name:n \l_recurrence_current_case_count_int}##1{
        0\exp_not:N \msg_expandable_error:n {\tl_use:N \l_recurrence_name_tl[~##1~]~undefined.}
    }
}


\cs_new_nopar:Npn \recurrence_wrapper_definitions:{
    \cs_new_nopar:cpx { \l_recurrence_name_tl } ##1{%
        \exp_not:N \int_eval:n {\exp_not:c { \l_recurrence_name_tl :n } {##1}}
    }
    \cs_new_nopar:cpx { \l_recurrence_name_tl :n } ##1{%
        \exp_not:N \exp_args:Nf
        \exp_not:c { \recurrence_case_name:n 0 }
                   { \exp_not:N \int_eval:n {##1} }
    }
}

\cs_new_nopar:Npn \recurrence_rec_def:n #1{
    \group_begin:
    \clist_set:Nn \recurrence_csv_list {#1}
    \clist_map_inline:Nn \recurrence_csv_list {
        \regex_extract_once:nnNTF
        { ^(\w+)\[(\w+)\]\=(.+?)\|(.+)\|(.+) } {##1|true||} \l_recurrence_temp_seq
        {
            % at this stage, \l_recurrence_temp_seq has 6 items,
            % 0th: a[i]= expression | guard | guard option
            \seq_pop:NN \l_recurrence_temp_seq \l_recurrence_bin_tl
            \seq_pop:NN \l_recurrence_temp_seq \l_recurrence_name_tl
            \seq_pop:NN \l_recurrence_temp_seq \l_recurrence_index_tl
            \seq_pop:NN \l_recurrence_temp_seq \l_recurrence_rhs_tl
            \seq_pop:NN \l_recurrence_temp_seq \l_recurrence_guard_tl
            \recurrence_is_integer:VTF
                \l_recurrence_index_tl
                {\recurrence_define_constant:xx \l_recurrence_index_tl \l_recurrence_rhs_tl}
                {\recurrence_case_definition:NN
                            \l_recurrence_name_tl \l_recurrence_index_tl}
        } { \recurrence_error }
    }
    \recurrence_error_definition:
    \recurrence_wrapper_definitions:
    \group_end:
}

\DeclareDocumentCommand\NewRecDef{ m }{
    \recurrence_rec_def:n {#1}
}

\ExplSyntaxOff

