%%% -*- coding: utf-8 -*-
%% ----------------------------------------------------------------------------
%% Functional: LaTeX2 functional interfaces to LaTeX3 programming layer
%% Copyright : 2022 (c) Jianrui Lyu <tolvjr@163.com>
%% Repository: https://github.com/lvjr/functional
%% License   : The LaTeX Project Public License 1.3c
%% ----------------------------------------------------------------------------

%%% --------------------------------------------------------
%%> \section{Interfaces for Function Definitions (l3basics)}
%%% --------------------------------------------------------

\NeedsTeXFormat{LaTeX2e}[2018-04-01]

\RequirePackage{expl3}
\ProvidesExplPackage{functional}{2022-03-10}{2022A}
  {^^JLaTeX2 functional interfaces to LaTeX3 programming layer}

\cs_generate_variant:Nn \iow_log:n { V }
\cs_generate_variant:Nn \tl_set:Nn { Ne }

\tl_new:N \gResultTl
\int_new:N \l__fun_arg_count_int
\tl_new:N \l__fun_parameters_defined_tl
\tl_const:Nn \c__fun_parameter_defined_i__tl     {  } % no argument
\tl_const:Nn \c__fun_parameter_defined_i_i_tl    { #1 }
\tl_const:Nn \c__fun_parameter_defined_i_ii_tl   { #1 #2 }
\tl_const:Nn \c__fun_parameter_defined_i_iii_tl  { #1 #2 #3 }
\tl_const:Nn \c__fun_parameter_defined_i_iv_tl   { #1 #2 #3 #4 }
\tl_const:Nn \c__fun_parameter_defined_i_v_tl    { #1 #2 #3 #4 #5 }
\tl_const:Nn \c__fun_parameter_defined_i_vi_tl   { #1 #2 #3 #4 #5 #6 }
\tl_const:Nn \c__fun_parameter_defined_i_vii_tl  { #1 #2 #3 #4 #5 #6 #7 }
\tl_const:Nn \c__fun_parameter_defined_i_viii_tl { #1 #2 #3 #4 #5 #6 #7 #8 }
\tl_const:Nn \c__fun_parameter_defined_i_ix_tl   { #1 #2 #3 #4 #5 #6 #7 #8 #9 }
\tl_new:N \l__fun_parameters_called_tl
\tl_const:Nn \c__fun_parameter_called_i_i_tl   { {#1} }
\tl_const:Nn \c__fun_parameter_called_i_ii_tl  { {#1}{#2} }
\tl_const:Nn \c__fun_parameter_called_i_iii_tl { {#1}{#2}{#3} }
\tl_const:Nn \c__fun_parameter_called_i_iv_tl  { {#1}{#2}{#3}{#4} }
\tl_const:Nn \c__fun_parameter_called_i_v_tl   { {#1}{#2}{#3}{#4}{#5} }
\tl_const:Nn \c__fun_parameter_called_i_vi_tl  { {#1}{#2}{#3}{#4}{#5}{#6} }
\tl_const:Nn \c__fun_parameter_called_i_vii_tl { {#1}{#2}{#3}{#4}{#5}{#6}{#7} }
\tl_new:N \l__fun_parameters_true_tl
\tl_new:N \l__fun_parameters_false_tl
\tl_const:Nn \c__fun_parameter_called_i_tl    { {#1} }
\tl_const:Nn \c__fun_parameter_called_ii_tl   { {#2} }
\tl_const:Nn \c__fun_parameter_called_iii_tl  { {#3} }
\tl_const:Nn \c__fun_parameter_called_iv_tl   { {#4} }
\tl_const:Nn \c__fun_parameter_called_v_tl    { {#5} }
\tl_const:Nn \c__fun_parameter_called_vi_tl   { {#6} }
\tl_const:Nn \c__fun_parameter_called_vii_tl  { {#7} }
\tl_const:Nn \c__fun_parameter_called_viii_tl { {#8} }
\tl_const:Nn \c__fun_parameter_called_ix_tl   { {#9} }
\tl_new:N \l__fun_argument_tl
\tl_new:N \l__fun_argument_i_tl
\tl_new:N \l__fun_argument_ii_tl
\tl_new:N \l__fun_argument_iii_tl
\tl_new:N \l__fun_argument_iv_tl
\tl_new:N \l__fun_argument_v_tl
\tl_new:N \l__fun_argument_vi_tl
\tl_new:N \l__fun_argument_vii_tl
\tl_new:N \l__fun_argument_viii_tl
\tl_new:N \l__fun_argument_ix_tl

%% #1: function name; #2: argument specification; #3 function body
\cs_new_protected:Npn \__fun_new_function:Nnn #1 #2 #3
  {
    \int_set:Nn \l__fun_arg_count_int { \tl_count:n {#2} } % spaces are ignored
    \tl_set_eq:Nc \l__fun_parameters_defined_tl
      { c__fun_parameter_defined_i_ \int_to_roman:n { \l__fun_arg_count_int } _tl }
    \exp_last_unbraced:NcV \cs_new_protected:Npn
      { __fun_defined_ \cs_to_str:N #1 : w }
      \l__fun_parameters_defined_tl
      {
        \__fun_group_begin:
        \tl_gclear:N \gResultTl
        #3
        \__fun_tracing_log:e { [O] ~ \gResultTl }
        \__fun_group_end:
      }
    \use:c { __fun_new_with_arg_ \int_to_roman:n { \l__fun_arg_count_int } :NnV }
      #1 {#2} \l__fun_parameters_defined_tl
  }
\cs_generate_variant:Nn \__fun_new_function:Nnn { cne }

\cs_set_eq:NN \PrgNewFunction \__fun_new_function:Nnn

\tl_new:N \g__fun_last_result_tl

%% #1: function name; #2: argument specification; #3 function body
\cs_new_protected:Npn \__fun_new_conditional:Nnn #1 #2 #3
  {
    \__fun_new_function:Nnn #1 { #2 } { #3 }
    \tl_set_eq:Nc \l__fun_parameters_called_tl
      { c__fun_parameter_called_i_ \int_to_roman:n { \l__fun_arg_count_int } _tl }
    \tl_set_eq:Nc \l__fun_parameters_true_tl
      { c__fun_parameter_called_ \int_to_roman:n { \l__fun_arg_count_int + 1 } _tl }
    \tl_set_eq:Nc \l__fun_parameters_false_tl
      { c__fun_parameter_called_ \int_to_roman:n { \l__fun_arg_count_int + 2 } _tl }
    \__fun_new_function:cne { \cs_to_str:N #1 TF } { #2 n n }
      {
        #1 \exp_not:V \l__fun_parameters_called_tl
        \exp_not:n
          {
            \tl_set_eq:NN \g__fun_last_result_tl \gResultTl
            \tl_gclear:N \gResultTl
            \exp_last_unbraced:NV \bool_if:NTF \g__fun_last_result_tl
          }
        \exp_not:V \l__fun_parameters_true_tl
        \exp_not:V \l__fun_parameters_false_tl
      }
  }

\cs_set_eq:NN \PrgNewConditional \__fun_new_conditional:Nnn

%% #1: function name; #2: argument specifications; #3 parameters tl defined
%% Some times we need to create a function without arguments
\cs_new_protected:Npn \__fun_new_with_arg_:Nnn #1 #2 #3
  {
    \cs_new_protected:Npn #1 #3
      {
        \__fun_evaluate:Nn #1 {#2}
      }
  }
\cs_generate_variant:Nn \__fun_new_with_arg_:Nnn { NnV }

%% #1: function name; #2: argument specifications; #3 parameters tl defined
\cs_new_protected:Npn \__fun_new_with_arg_i:Nnn #1 #2 #3
  {
    \cs_new_protected:Npn #1 #3
      {
        \tl_set:Nn \l__fun_argument_i_tl { ##1 }
        \__fun_evaluate:Nn #1 {#2}
      }
  }
\cs_generate_variant:Nn \__fun_new_with_arg_i:Nnn { NnV }

%% #1: function name; #2: argument specifications; #3 parameters tl defined
\cs_new_protected:Npn \__fun_new_with_arg_ii:Nnn #1 #2 #3
  {
    \cs_new_protected:Npn #1 #3
      {
        \tl_set:Nn \l__fun_argument_i_tl  { ##1 }
        \tl_set:Nn \l__fun_argument_ii_tl { ##2 }
        \__fun_evaluate:Nn #1 {#2}
      }
  }
\cs_generate_variant:Nn \__fun_new_with_arg_ii:Nnn { NnV }

%% #1: function name; #2: argument specifications; #3 parameters tl defined
\cs_new_protected:Npn \__fun_new_with_arg_iii:Nnn #1 #2 #3
  {
    \cs_new_protected:Npn #1 #3
      {
        \tl_set:Nn \l__fun_argument_i_tl   { ##1 }
        \tl_set:Nn \l__fun_argument_ii_tl  { ##2 }
        \tl_set:Nn \l__fun_argument_iii_tl { ##3 }
        \__fun_evaluate:Nn #1 {#2}
      }
  }
\cs_generate_variant:Nn \__fun_new_with_arg_iii:Nnn { NnV }

%% #1: function name; #2: argument specifications; #3 parameters tl defined
\cs_new_protected:Npn \__fun_new_with_arg_iv:Nnn #1 #2 #3
  {
    \cs_new_protected:Npn #1 #3
      {
        \tl_set:Nn \l__fun_argument_i_tl   { ##1 }
        \tl_set:Nn \l__fun_argument_ii_tl  { ##2 }
        \tl_set:Nn \l__fun_argument_iii_tl { ##3 }
        \tl_set:Nn \l__fun_argument_iv_tl  { ##4 }
        \__fun_evaluate:Nn #1 {#2}
      }
  }
\cs_generate_variant:Nn \__fun_new_with_arg_iv:Nnn { NnV }

%% #1: function name; #2: argument specifications; #3 parameters tl defined
\cs_new_protected:Npn \__fun_new_with_arg_v:Nnn #1 #2 #3
  {
    \cs_new_protected:Npn #1 #3
      {
        \tl_set:Nn \l__fun_argument_i_tl   { ##1 }
        \tl_set:Nn \l__fun_argument_ii_tl  { ##2 }
        \tl_set:Nn \l__fun_argument_iii_tl { ##3 }
        \tl_set:Nn \l__fun_argument_iv_tl  { ##4 }
        \tl_set:Nn \l__fun_argument_v_tl   { ##5 }
        \__fun_evaluate:Nn #1 {#2}
      }
  }
\cs_generate_variant:Nn \__fun_new_with_arg_v:Nnn { NnV }

%% #1: function name; #2: argument specifications; #3 parameters tl defined
\cs_new_protected:Npn \__fun_new_with_arg_vi:Nnn #1 #2 #3
  {
    \cs_new_protected:Npn #1 #3
      {
        \tl_set:Nn \l__fun_argument_i_tl   { ##1 }
        \tl_set:Nn \l__fun_argument_ii_tl  { ##2 }
        \tl_set:Nn \l__fun_argument_iii_tl { ##3 }
        \tl_set:Nn \l__fun_argument_iv_tl  { ##4 }
        \tl_set:Nn \l__fun_argument_v_tl   { ##5 }
        \tl_set:Nn \l__fun_argument_vi_tl  { ##6 }
        \__fun_evaluate:Nn #1 {#2}
      }
  }
\cs_generate_variant:Nn \__fun_new_with_arg_vi:Nnn { NnV }

%% #1: function name; #2: argument specifications; #3 parameters tl defined
\cs_new_protected:Npn \__fun_new_with_arg_vii:Nnn #1 #2 #3
  {
    \cs_new_protected:Npn #1 #3
      {
        \tl_set:Nn \l__fun_argument_i_tl   { ##1 }
        \tl_set:Nn \l__fun_argument_ii_tl  { ##2 }
        \tl_set:Nn \l__fun_argument_iii_tl { ##3 }
        \tl_set:Nn \l__fun_argument_iv_tl  { ##4 }
        \tl_set:Nn \l__fun_argument_v_tl   { ##5 }
        \tl_set:Nn \l__fun_argument_vi_tl  { ##6 }
        \tl_set:Nn \l__fun_argument_vii_tl { ##7 }
        \__fun_evaluate:Nn #1 {#2}
      }
  }
\cs_generate_variant:Nn \__fun_new_with_arg_vii:Nnn { NnV }

%% #1: function name; #2: argument specifications; #3 parameters tl defined
\cs_new_protected:Npn \__fun_new_with_arg_viii:Nnn #1 #2 #3
  {
    \cs_new_protected:Npn #1 #3
      {
        \tl_set:Nn \l__fun_argument_i_tl    { ##1 }
        \tl_set:Nn \l__fun_argument_ii_tl   { ##2 }
        \tl_set:Nn \l__fun_argument_iii_tl  { ##3 }
        \tl_set:Nn \l__fun_argument_iv_tl   { ##4 }
        \tl_set:Nn \l__fun_argument_v_tl    { ##5 }
        \tl_set:Nn \l__fun_argument_vi_tl   { ##6 }
        \tl_set:Nn \l__fun_argument_vii_tl  { ##7 }
        \tl_set:Nn \l__fun_argument_viii_tl { ##8 }
        \__fun_evaluate:Nn #1 {#2}
      }
  }
\cs_generate_variant:Nn \__fun_new_with_arg_viii:Nnn { NnV }

%% #1: function name; #2: argument specifications; #3 parameters tl defined
\cs_new_protected:Npn \__fun_new_with_arg_ix:Nnn #1 #2 #3
  {
    \cs_new_protected:Npn #1 #3
      {
        \tl_set:Nn \l__fun_argument_i_tl    { ##1 }
        \tl_set:Nn \l__fun_argument_ii_tl   { ##2 }
        \tl_set:Nn \l__fun_argument_iii_tl  { ##3 }
        \tl_set:Nn \l__fun_argument_iv_tl   { ##4 }
        \tl_set:Nn \l__fun_argument_v_tl    { ##5 }
        \tl_set:Nn \l__fun_argument_vi_tl   { ##6 }
        \tl_set:Nn \l__fun_argument_vii_tl  { ##7 }
        \tl_set:Nn \l__fun_argument_viii_tl { ##8 }
        \tl_set:Nn \l__fun_argument_ix_tl   { ##9 }
        \__fun_evaluate:Nn #1 {#2}
      }
  }
\cs_generate_variant:Nn \__fun_new_with_arg_ix:Nnn { NnV }

\int_new:N \g__fun_nesting_level_int
\int_new:N \l__fun_argtype_number_int
\tl_new:N \l__fun_argtype_tl
\tl_const:Nn \c__fun_argtype_m_tl { m }
\tl_const:Nn \c__fun_argtype_M_tl { M }
\tl_const:Nn \c__fun_argtype_n_tl { n }
\tl_const:Nn \c__fun_argtype_N_tl { N }

%% #1: function name; #2: argument specifications
\cs_new_protected:Npn \__fun_evaluate:Nn #1 #2
  {
    \int_zero:N \l__fun_argtype_number_int
    \int_gincr:N \g__fun_nesting_level_int
    \__fun_arguments_gclear:
    \tl_map_variable:nNn { #2 } \l__fun_argtype_tl % spaces are ignored
      {
        \int_incr:N \l__fun_argtype_number_int
        \tl_set_eq:Nc \l__fun_argument_tl
          { l__fun_argument_ \int_to_roman:n { \l__fun_argtype_number_int } _tl }
        \tl_case:Nn \l__fun_argtype_tl
          {
            \c__fun_argtype_m_tl
              {
                \__fun_evaluate_and_put_argument:N \l__fun_argument_tl
              }
            \c__fun_argtype_M_tl
              {
                \__fun_evaluate_and_put_argument:N \l__fun_argument_tl
              }
            \c__fun_argtype_n_tl
              {
                \__fun_arguments_gput:e { { \exp_not:V \l__fun_argument_tl } }
              }
            \c__fun_argtype_N_tl
              {
                \__fun_arguments_gput:e { \exp_not:V \l__fun_argument_tl }
              }
          }
      }
    \__fun_arguments_log:N #1
    \__fun_arguments_called:c { __fun_defined_ \cs_to_str:N #1 : w }
    \int_gdecr:N \g__fun_nesting_level_int
    \__fun_return_result:
  }

\cs_set_eq:NN \__fun_cs_temp:w \scan_stop:

\cs_new_protected:Npn \__fun_evaluate_and_put_argument:N #1
  {
    \cs_set_eq:Nc \__fun_cs_temp:w
      {
        __fun_defined_ \exp_last_unbraced:Ne \cs_to_str:N { \tl_head:N #1 } : w
      }
    \cs_if_exist:NTF \__fun_cs_temp:w
      {
        #1
        \__fun_arguments_gput:e { { \exp_not:V \gResultTl } }
      }
      {
        \__fun_arguments_gput:e { { \exp_not:V #1 } }
      }
  }

\cs_new_protected:Npn \__fun_arguments_called:N #1
  {
    \exp_last_unbraced:Nv
      #1 { g__fun_arguments_ \int_use:N \g__fun_nesting_level_int _tl }
  }
\cs_generate_variant:Nn \__fun_arguments_called:N { c }

\cs_new_protected:Npn \__fun_arguments_gclear:
  {
    \tl_gclear:c { g__fun_arguments_ \int_use:N \g__fun_nesting_level_int _tl }
  }

\cs_new_protected:Npn \__fun_arguments_log:N #1
  {
    \__fun_tracing_log:e
    {
      [I] ~ \token_to_str:N #1
     \exp_not:v { g__fun_arguments_ \int_use:N \g__fun_nesting_level_int _tl }
    }
  }

\cs_new_protected:Npn \__fun_arguments_gput:n #1
  {
    \tl_gput_right:cn
      { g__fun_arguments_ \int_use:N \g__fun_nesting_level_int _tl } { #1 }
  }
\cs_generate_variant:Nn \__fun_arguments_gput:n { e }

\cs_new_protected:Npn \__fun_put_result:n #1
  {
    \tl_gput_right:Nn \gResultTl { #1 }
  }
\cs_generate_variant:Nn \__fun_put_result:n { e, V }

\PrgNewFunction \Result { m }
  {
    \__fun_put_result:n { #1 }
  }

\PrgNewFunction \Name { m }
  {
    \exp_args:Nc \__fun_put_result:n { #1 }
  }
\cs_set_eq:NN \UseName \Name

\PrgNewFunction \Expand { m }
  {
    \__fun_put_result:e { #1 }
  }
\cs_set_eq:NN \UseExpand \Expand

\PrgNewFunction \Value { M }
  {
    \__fun_put_result:V #1
  }
\cs_set_eq:NN \UseValue \Value

\cs_set_eq:NN \ExpNot \exp_not:n
\cs_set_eq:NN \ExpValue \exp_not:V

\cs_new_protected:Npn \__fun_return_result:
  {
    \int_compare:nNnT { \g__fun_nesting_level_int } = { 0 }
      { \tl_use:N \gResultTl }
  }

\tl_new:N \l__fun_variable_type_tl

\prg_new_protected_conditional:Npnn \__fun_if_global_variable:N #1 { TF }
  {
    \tl_set:Ne \l__fun_variable_type_tl
      { \exp_args:Ne \tl_head:n { \cs_to_str:N #1 } }
    \str_if_eq:VnTF \l__fun_variable_type_tl { g }
      { \prg_return_true: }
      {
        \str_if_eq:VnTF \l__fun_variable_type_tl { c }
          { \prg_return_true: }
          { \prg_return_false: }
      }
  }

%% We must not put an assignment inside a group
\cs_new_protected:Npn \__fun_do_assignment:Nnn #1 #2 #3
  {
    \__fun_group_end:
    \__fun_if_global_variable:NTF #1 { #2 } { #3 }
    \__fun_group_begin:
  }

\bool_new:N \l__fun_scoping_bool

\cs_new_protected:Npn \__fun_scoping_true:
  {
    \cs_set_eq:NN \__fun_group_begin: \group_begin:
    \cs_set_eq:NN \__fun_group_end: \group_end:
  }

\cs_new_protected:Npn \__fun_scoping_false:
  {
    \cs_set_eq:NN \__fun_group_begin: \scan_stop:
    \cs_set_eq:NN \__fun_group_end: \scan_stop:
  }

\cs_new_protected:Npn \__fun_scoping_set:
  {
    \bool_if:NTF \l__fun_scoping_bool
      { \__fun_scoping_true: } { \__fun_scoping_false: }
  }

\bool_new:N \l__fun_tracing_bool
\tl_new:N \l__tracing_text_tl

\cs_new_protected:Npn \__fun_tracing_log_on:n #1
  {
    \tl_set:Ne \l__tracing_text_tl
      {
        \prg_replicate:nn
          { \int_eval:n { (\g__fun_nesting_level_int - 1) * 4 } } { ~ }
      }
    \tl_put_right:Nn \l__tracing_text_tl { #1 }
    \iow_log:V \l__tracing_text_tl
  }
\cs_generate_variant:Nn \__fun_tracing_log_on:n { e, V }

\cs_new_protected:Npn \__fun_tracing_log_off:n #1 { }
\cs_generate_variant:Nn \__fun_tracing_log_off:n { e, V }

\cs_new_protected:Npn \__fun_tracing_true:
  {
    \cs_set_eq:NN \__fun_tracing_log:n \__fun_tracing_log_on:n
    \cs_set_eq:NN \__fun_tracing_log:e \__fun_tracing_log_on:e
    \cs_set_eq:NN \__fun_tracing_log:V \__fun_tracing_log_on:V
  }

\cs_new_protected:Npn \__fun_tracing_false:
  {
    \cs_set_eq:NN \__fun_tracing_log:n \__fun_tracing_log_off:n
    \cs_set_eq:NN \__fun_tracing_log:e \__fun_tracing_log_off:e
    \cs_set_eq:NN \__fun_tracing_log:V \__fun_tracing_log_off:V
  }

\cs_new_protected:Npn \__fun_tracing_set:
  {
    \bool_if:NTF \l__fun_tracing_bool
      { \__fun_tracing_true: } { \__fun_tracing_false: }
  }

\keys_define:nn { functional }
  {
    scoping .bool_set:N = \l__fun_scoping_bool,
    tracing .bool_set:N = \l__fun_tracing_bool,
  }

\NewDocumentCommand \Functional { m }
  {
    \keys_set:nn { functional } { #1 }
    \__fun_scoping_set:
    \__fun_tracing_set:
  }

\Functional { scoping = false, tracing = false }

\PrgNewFunction \UseOne { n }
  {
    \Result { #1 }
  }

\PrgNewFunction \GobbleOne { n }
  {
    \Result { }
  }

\PrgNewFunction \UseGobble { n n }
  {
    \UseOne { #1 }
  }

\PrgNewFunction \GobbleUse { n n }
  {
    \UseOne { #2 }
  }

%%% --------------------------------------------------------
%%> \section{Interfaces for Control Structures (l3prg)}
%%% --------------------------------------------------------

\bool_const:Nn \cTrueBool { \c_true_bool }
\bool_const:Nn \cFalseBool { \c_false_bool }

\bool_new:N \lTmpaBool   \bool_new:N \lTmpbBool   \bool_new:N \lTmpcBool
\bool_new:N \lTmpiBool   \bool_new:N \lTmpjBool   \bool_new:N \lTmpkBool
\bool_new:N \l@Funx@Bool \bool_new:N \l@Funy@Bool \bool_new:N \l@Funz@Bool

\bool_new:N \gTmpaBool   \bool_new:N \gTmpbBool   \bool_new:N \gTmpcBool
\bool_new:N \gTmpiBool   \bool_new:N \gTmpjBool   \bool_new:N \gTmpkBool
\bool_new:N \g@Funx@Bool \bool_new:N \g@Funy@Bool \bool_new:N \g@Funz@Bool

\cs_set_eq:NN \BoolNew \bool_new:N
\cs_set_eq:NN \BoolLog \bool_log:N

\PrgNewFunction \BoolSetTrue { M }
  {
    \__fun_do_assignment:Nnn #1 { \bool_gset_true:N #1 } { \bool_set_true:N #1 }
  }

\PrgNewFunction \BoolSetFalse { M }
  {
    \__fun_do_assignment:Nnn #1 { \bool_gset_false:N #1 } { \bool_set_false:N #1 }
  }

\PrgNewConditional \BoolIf { N }
  {
    \Result { #1 }
  }

%%% --------------------------------------------------------
%%> \section{Interfaces for Token Lists (l3tl)}
%%% --------------------------------------------------------

\tl_new:N \lTmpaTl   \tl_new:N \lTmpbTl   \tl_new:N \lTmpcTl
\tl_new:N \lTmpiTl   \tl_new:N \lTmpjTl   \tl_new:N \lTmpkTl
\tl_new:N \l@Funx@Tl \tl_new:N \l@Funy@Tl \tl_new:N \l@Funz@Tl

\tl_new:N \gTmpaTl   \tl_new:N \gTmpbTl   \tl_new:N \gTmpcTl
\tl_new:N \gTmpiTl   \tl_new:N \gTmpjTl   \tl_new:N \gTmpkTl
\tl_new:N \g@Funx@Tl \tl_new:N \g@Funy@Tl \tl_new:N \g@Funz@Tl

\cs_set_eq:NN \TlNew \tl_new:N
\cs_set_eq:NN \TlLog \tl_log:N

\PrgNewFunction \TlClear { M }
  {
    \__fun_do_assignment:Nnn #1 { \tl_gclear:N #1 } { \tl_clear:N #1 }
  }

\PrgNewFunction \TlSet { M m }
  {
    \__fun_do_assignment:Nnn #1 { \tl_gset:Nn #1 {#2} } { \tl_set:Nn #1 {#2} }
  }

\PrgNewFunction \TlPutLeft { M m }
  {
    \__fun_do_assignment:Nnn #1
      { \tl_gput_left:Nn #1 {#2} } { \tl_put_left:Nn #1 {#2} }
  }

\PrgNewFunction \TlPutRight { M m }
  {
    \__fun_do_assignment:Nnn #1
      { \tl_gput_right:Nn #1 {#2} } { \tl_put_right:Nn #1 {#2} }
  }

\PrgNewFunction \TlUse { M }
  {
    \Result { \Value #1 }
  }

\PrgNewConditional \TlIfEmpty { N }
  {
    \tl_if_empty:NTF #1
      { \Result { \cTrueBool } }
      { \Result { \cFalseBool } }
  }

\PrgNewConditional \TlIfEq { N N }
  {
    \tl_if_eq:NNTF #1 #2
      { \Result { \cTrueBool } }
      { \Result { \cFalseBool } }
  }

%%% --------------------------------------------------------
%%> \section{Interfaces for Integers (l3int)}
%%% --------------------------------------------------------

\int_new:N \lTmpaInt   \int_new:N \lTmpbInt   \int_new:N \lTmpcInt
\int_new:N \lTmpiInt   \int_new:N \lTmpjInt   \int_new:N \lTmpkInt
\int_new:N \l@Funx@Int \int_new:N \l@Funy@Int \int_new:N \l@Funz@Int

\int_new:N \gTmpaInt   \int_new:N \gTmpbInt   \int_new:N \gTmpcInt
\int_new:N \gTmpiInt   \int_new:N \gTmpjInt   \int_new:N \gTmpkInt
\int_new:N \g@Funx@Int \int_new:N \g@Funy@Int \int_new:N \g@Funz@Int

\cs_set_eq:NN \IntNew \int_new:N
\cs_set_eq:NN \IntLog \int_log:N

\PrgNewFunction \IntZero { M }
  {
    \__fun_do_assignment:Nnn #1 { \int_gzero:N #1 } { \int_zero:N #1 }
  }

\PrgNewFunction \IntIncr { M }
  {
    \__fun_do_assignment:Nnn #1 { \int_gincr:N #1 } { \int_incr:N #1 }
  }

\PrgNewFunction \IntDecr { M }
  {
    \__fun_do_assignment:Nnn #1 { \int_gdecr:N #1 } { \int_decr:N #1 }
  }

\PrgNewFunction \IntSet { M m }
  {
    \__fun_do_assignment:Nnn #1 { \int_gset:Nn #1 {#2} } { \int_set:Nn #1 {#2} }
  }

\PrgNewFunction \IntAdd { M m }
  {
    \__fun_do_assignment:Nnn #1 { \int_gadd:Nn #1 {#2} } { \int_add:Nn #1 {#2} }
  }

\PrgNewFunction \IntSub { M m }
  {
    \__fun_do_assignment:Nnn #1 { \int_gsub:Nn #1 {#2} } { \int_sub:Nn #1 {#2} }
  }

\PrgNewFunction \IntUse { M }
  {
    \Result { \Value #1 }
  }

\PrgNewFunction \IntEval { m }
  {
    \Result { \Expand { \int_eval:n { #1 } } }
  }

\PrgNewFunction \IntMathAdd { m m }
  {
    \int_set:Nn \l@Funx@Int { \int_eval:n { #1 + #2 } }
    \Result { \Value \l@Funx@Int }
  }

\PrgNewFunction \IntMathSub { m m }
  {
    \int_set:Nn \l@Funx@Int { \int_eval:n { #1 - #2 } }
    \Result { \Value \l@Funx@Int }
  }

\PrgNewFunction \IntMathMult { m m }
  {
    \int_set:Nn \l@Funx@Int { \int_eval:n { #1 * #2 } }
    \Result { \Value \l@Funx@Int }
  }

\PrgNewFunction \IntMathDiv { m m }
  {
    \int_set:Nn \l@Funx@Int { \int_eval:n { #1 / #2 } }
    \Result { \Value \l@Funx@Int }
  }

\PrgNewFunction \IntStepVariable { m m m M n }
  {
    \int_step_variable:nnnNn { #1 } { #2 } { #3 } #4 { #5 }
  }

\PrgNewConditional \IntCompare { m N m }
  {
    \int_compare:nNnTF {#1} #2 {#3}
      { \Result { \cTrueBool } }
      { \Result { \cFalseBool } }
  }

