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


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

\def\testme#1{[[[#1]]]}

\clist_new:N  \recurrence_csv_list
\tl_new:N     \recurrence_tl_bin
\tl_new:N     \recurrence_tl_temp
\tl_new:N     \recurrence_tl_name
\tl_new:N     \recurrence_tl_index
\tl_new:N     \recurrence_tl_rhs
\tl_new:N     \recurrence_tl_guard
\regex_const:Nn \recurrence_tl_integer_regex { ^[-+]*[0-9]+$ }
\regex_const:Nn \recurrence_tl_true          { true }
\int_new:N    \recurrence_case_count

\cs_new_nopar:Npn \recurrence_prefix: {
    recurrence
}

\cs_new_nopar:Npn \recurrence_is_integer:xTF #1{
    \regex_match:NnTF \recurrence_tl_integer_regex {#1}
}

\cs_new_nopar:Npn \recurrence_is_integer:NTF #1{
    % I don't understand why I need the exp_args:Nx
    \exp_args:Nx
    \recurrence_is_integer:xTF {\tl_use:N #1}
}

\cs_new_nopar:Npn \recurrence_case_name:xx #1#2{
    \recurrence_prefix: _ #1 _ #2:x
}

% #1 is integer token list
\cs_new_nopar:Npn \recurrence_case_name:N #1{
    \recurrence_case_name:xx \recurrence_tl_name {\int_use:N #1}
}

% #1 is integer
\cs_new_nopar:Npn \recurrence_case_name:n #1{
    \recurrence_case_name:xx \recurrence_tl_name {#1}
}


% #1 is index
% #2 is rhs
\cs_new_nopar:Npn \recurrence_define_constant:xx #1#2{%
    \edef\recurrence_current_case_count{\int_use:N \recurrence_case_count}
    \int_incr:N \recurrence_case_count
    \cs_new_nopar:cpx {\recurrence_case_name:n \recurrence_current_case_count} ##1{
        \exp_not:N
        \int_compare:nTF {##1=#1} {#2}
                         {\cs:w \recurrence_case_name:N \recurrence_case_count
                          \cs_end:{##1}}
    }
}

% #1 is guard tl
% #2 is rhs   tl
\cs_new_nopar:Npn \recurrence_case_definition:xx #1#2{
    \edef\recurrence_current_case_count{\int_use:N \recurrence_case_count}
    \int_incr:N \recurrence_case_count
    \cs_new_nopar:cpx {\recurrence_case_name:n \recurrence_current_case_count} ##1{
        \exp_not:N
        \bool_if:nTF {#1} {#2}
                     {\cs:w \recurrence_case_name:N \recurrence_case_count
                      \cs_end:{##1}}
    }
}

% #1 is name  tl
% #2 is index tl
% #3 is rhs   tl
% #4 is guard tl
\cs_new_nopar:Npn \recurrence_case_definition:NNNN #1#2#3#4{
    \exp_args:Nx
    \recurrence_sanitise:nNN {{\tl_use:N #1} {\tl_use:N #2}} #3 #4
    \regex_replace_all:NnN \recurrence_tl_true {\\int_compare_p:n \{ 1 = 1 \}} #4
    \recurrence_case_definition:xx #4 #3
}

\cs_new_nopar:Npn \recurrence_sanitise:nNN #1#2#3{
    \recurrence_sanitise:nnNN #1 #2 #3
}

% #1 is name
% #2 is index
% #3 is rhs   tl
% #4 is guard tl
\cs_new_nopar:Npn \recurrence_sanitise:nnNN #1#2#3#4{
    \recurrence_sanitise:nnN {#1} {#2} #3
    \recurrence_sanitise:nnN {#1} {#2} #4
}

% #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\b\[([^\]]+)\]} {\\#1:n\{\1\}} #3
}

\cs_new_nopar:Npn \recurrence_error_definition:{
    \edef\recurrence_current_case_count{\int_use:N \recurrence_case_count}
    \cs_new:cpx {\recurrence_case_name:n \recurrence_current_case_count}##1{
        \exp_not:N
        \error{\tl_use:N \recurrence_tl_name[~##1~]~undefined.}
    }
}


\cs_new_nopar:Npn \recurrence_wrapper_definitions:{
    \edef\recurrence_temp{\tl_use:N \recurrence_tl_name}
    \cs_new_nopar:cpx {\recurrence_temp} ##1{%
        \exp_after:wN \exp_not:N
        \cs:w \recurrence_temp :n \cs_end: {##1}
    }
    \cs_new_nopar:cpx {\recurrence_temp :n} ##1{%
        \noexpand \exp_args:Nx
        \exp_after:wN \exp_not:N
        \cs:w \recurrence_case_name:n 0 \cs_end:
              {\exp_not:N \int_eval:n{##1}}
    }
}

\cs_new_nopar:Npn \NewRecDef:n #1{
    \begingroup
    \clist_set:Nn  \recurrence_csv_list {#1}
    \clist_map_inline:Nn \recurrence_csv_list {
        \regex_extract_once:nnNTF
        { ^(\w+)\[(\w+)\]\=(.+?)\|(.+)\|(.+) } {##1|true||} \recurrence_tl_temp
        {
            % at this stage, \recurrence_tl_temp has 6 items,
            % 0th: a[i]= expression | guard | guard option
            \seq_pop:NN \recurrence_tl_temp \recurrence_tl_bin
            \seq_pop:NN \recurrence_tl_temp \recurrence_tl_name
            \seq_pop:NN \recurrence_tl_temp \recurrence_tl_index
            \seq_pop:NN \recurrence_tl_temp \recurrence_tl_rhs
            \seq_pop:NN \recurrence_tl_temp \recurrence_tl_guard
            \recurrence_is_integer:NTF
                \recurrence_tl_index
                {\recurrence_define_constant:xx \recurrence_tl_index \recurrence_tl_rhs}
                {\recurrence_case_definition:NNNN
                            \recurrence_tl_name \recurrence_tl_index
                            \recurrence_tl_rhs \recurrence_tl_guard}
        } { \recurrence_error }
    }
    \recurrence_error_definition:
    \recurrence_wrapper_definitions:
    \endgroup
}

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

\ExplSyntaxOff

