% \iffalse
%% File: l3prop.dtx Copyright (C) 1990-2008 LaTeX3 project
%%
%% It may be distributed and/or modified under the conditions of the
%% LaTeX Project Public License (LPPL), either version 1.3c of this
%% license or (at your option) any later version.  The latest version
%% of this license is in the file
%%
%%    http://www.latex-project.org/lppl.txt
%%
%% This file is part of the ``expl3 bundle'' (The Work in LPPL)
%% and all files in that bundle must be distributed together.
%%
%% The released version of this bundle is available from CTAN.
%%
%% -----------------------------------------------------------------------
%%
%% The development version of the bundle can be found at
%%
%%    http://www.latex-project.org/cgi-bin/cvsweb.cgi/
%%
%% for those people who are interested.
%%
%%%%%%%%%%%
%% NOTE: %%
%%%%%%%%%%%
%%
%%   Snapshots taken from the repository represent work in progress and may
%%   not work or may contain conflicting material!  We therefore ask
%%   people _not_ to put them into distributions, archives, etc. without
%%   prior consultation with the LaTeX Project Team.
%%
%% -----------------------------------------------------------------------
%
%<*driver|package>
\RequirePackage{l3names}
%</driver|package>
%\fi
\GetIdInfo$Id: l3prop.dtx 745 2008-08-03 18:50:46Z morten $
          {L3 Experimental Property Lists}
%\iffalse
%<*driver>
%\fi
\ProvidesFile{\filename.\filenameext}
  [\filedate\space v\fileversion\space\filedescription]
%\iffalse
\documentclass{l3doc}
\begin{document}
\DocInput{\filename.\filenameext}
\end{document}
%</driver>
% \fi
%
%
% \title{The \textsf{l3prop} package\thanks{This file
%         has version number \fileversion, last
%         revised \filedate.}\\
% Property Lists}
% \author{\Team}
% \date{\filedate}
% \maketitle
%
%
%
% \section{Property lists}
%
%  \LaTeX3 implements a data structure which allows to store information
% associated with individual tokens.
%
% \subsection{Functions}
%
% \begin{function}{%
%                  \prop_new:N |
%                  \prop_new:c |
% }
% \begin{syntax}
%    "\prop_new:N" <plist>
% \end{syntax}
% Defines <plist> to be a variable of type p-list.
% \end{function}
%
% \begin{function}{%
%                  \prop_clear:N |
%                  \prop_gclear:N |
% }
% \begin{syntax}
%   "\prop_clear:N"  <plist>
% \end{syntax}
% These functions locally or globally clear <plist>.
% \end{function}
%
% \begin{function}{%
%                  \prop_put:Nnn |
%                  \prop_put:ccn |
%                  \prop_gput:Nnn |
%                  \prop_gput:Nno |
%                  \prop_gput:Noo |
%                  \prop_gput:Ncn |
%                  \prop_gput:Ooo |
%                  \prop_gput:Nox |
%                  \prop_gput:cnn |
%                  \prop_gput:ccn |
%                  \prop_gput:cco |
%                  \prop_gput:ccx |
% }
% \begin{syntax}
%   "\prop_put:Nnn" <plist> "{"<key>"}" "{"<token list>"}"
% \end{syntax}
% Locally or globally associates <token list> with <key> in the p-list
% <plist>. If <key> has already a meaning within <plist> this value is
% overwritten.
% \end{function}
%
% \begin{function}{%
%                  \prop_gput_if_new:Nnn |
% }
% \begin{syntax}
%   "\prop_gput_if_new:Nnn" <plist> "{"<key>"}" "{"<token list>"}"
% \end{syntax}
%  Globally associates <token list> with <key> in the p-list
% <plist> but only if <key> has so far no meaning within <plist>.
% overwritten.
% \end{function}
%
% \begin{function}{%
%                  \prop_get:NnN |
%                  \prop_get:cnN |
%                  \prop_gget:NnN |
%                  \prop_gget:NcN |
%                  \prop_gget:cnN |
% }
% \begin{syntax}
%    "\prop_get:NnN" <plist> "{"<key>"}" <tlp>
% \end{syntax}
% If <info> is the information associated with <key> in the p-list
% <plist> then the token list pointer <tlp> gets <info> assigned.
% Otherwise its value is the special quark "\q_no_value".
%^^A See section \ref{sec:quarks} to test this.
% The assignment is done either locally or globally.
% \end{function}
%
% \begin{function}{%
%                  \prop_set_eq:NN |
%                  \prop_set_eq:cc |
%                  \prop_gset_eq:NN |
%                  \prop_gset_eq:cc
% }
% \begin{syntax}
%    "\prop_set_eq:NN" <plist 1> <plist 2>
% \end{syntax}
% A fast assignment of <plist>s.
% \end{function}
%
% \begin{function}{%
%                  \prop_get_gdel:NnN |
% }
% \begin{syntax}
%    "\prop_get_gdel:NnN" <plist> "{"<key>"}" <tlp>
% \end{syntax}
% Like "\prop_get:NnN" but additionally removes <key> (and its <info>)
% from <plist>.
% \end{function}
%
% \begin{function}{%
%                  \prop_del:Nn |
%                  \prop_gdel:Nn |
% }
% \begin{syntax}
%    "\prop_del:Nn" <plist> "{"<key>"}"
% \end{syntax}
% Locally or globally deletes <key> and its <info> from <plist> if
% found. Otherwise does nothing.
% \end{function}
%
%
% \begin{function}{\prop_map_function:NN |
%                  \prop_map_function:cN |
%                  \prop_map_function:Nc |
%                  \prop_map_function:cc |
% }
% \begin{syntax}
%   "\prop_map_function:NN" <plist> <function>
% \end{syntax}
% Maps <function> which should be a function with two arguments (<key>
% and <info>) over every <key> <info> pair of <plist>. Expandable.
% \end{function}
%
% \begin{function}{\prop_map_inline:Nn |
%                  \prop_map_inline:cn
% }
% \begin{syntax}
%   "\prop_map_inline:Nn" <plist> "{" <inline function> "}"
% \end{syntax}
% Just like "\prop_map_function:NN" but with the function of two arguments
% supplied as inline code. Within <inline function> refer to the
% arguments via "#1" (<key>) and "#2" (<info>). Nestable.
% \end{function}
%
%
%  \begin{function}{%
%                   \prop_map_break:w |
%  }
%  \begin{syntax}
%     "\prop_map_break:w"
%  \end{syntax}
%  For breaking out of a loop. To be used inside "TF" type functions.
%  \end{function}
%
%
%
% \subsection{Predicates and conditionals}
%
% \begin{function}{\prop_if_empty:NTF}
% \begin{syntax}
%   "\prop_if_empty:NTF" <plist> "{"<true code>"}{"<false code>"}"
% \end{syntax}
% Set of conditionals that test whether or not a particular <plist>
% is empty.
% \end{function}
%
% \begin{function}{\prop_if_eq:NNF |
%                  \prop_if_eq:ccF
%                  }
% \begin{syntax}
%   "\prop_if_eq:NNF" <plist1> <plist2> "{"<false code>"}"
% \end{syntax}
% Execute <false code> if <plist1> doesn't hold the same token list as
% <plist2>.
% \end{function}
%
%
% \begin{function}{%
%                  \prop_if_in:NnTF |
%                  \prop_if_in:NoTF |
%                  \prop_if_in:ccTF |
% }
% \begin{syntax}
%   "\prop_if_in:NnTF" <plist>"{"<key>"}{"<true code>"}{"<false code>"}"
% \end{syntax}
% Tests if <key> is used in <plist> and then either executes <true code>
% or <false code>.
% \end{function}
%
% \subsection{Internal functions}
%
% \begin{function}{%
%                  \prop_put_aux:w |
%                  \prop_put_if_new_aux:w |
% }
% Internal functions implementing the put operations.
% \end{function}
%
% \begin{function}{%
%                  \prop_get_aux:w |
%                  \prop_get_del_aux:w |
%                  \prop_del_aux:w |
% }
% Internal functions implementing the get and delete operations.
% \end{function}
%
% \begin{function}{%
%                  \prop_if_in_aux:w |
% }
% Internal function implementing the key test operation.
% \end{function}
%
% \begin{function}{%
%                  \prop_map_function_aux:NNn |
%                  \prop_map_inline_aux:Nn |
% }
% Internal functions implementing the map operations.
% \end{function}
%
% \begin{function}{%
%                  \g_prop_inline_level_num |
% }
% Fake integer used in internal name for function used inside
% "\prop_map_inline:NN".
% \end{function}
%
% \begin{function}{\prop_split_aux:Nnn}
% \begin{syntax}
%   "\prop_split_aux:Nnn" <plist> <key> <cmd>
% \end{syntax}
% Internal function that invokes <cmd> with 3 arguments: 1st is the
% beginning of <plist> before <key>, 2nd is the value associated with
% <key>, 3rd is the rest of <plist> after <key>.  If there is no key
% <key> in <plist>, then the 2 arg is "\q_no_value " and the 3rd arg is
% empty; otherwise the 3rd argument has the two extra tokens <prop>
% "\q_no_value" at the end.
%
% This function is used to implement various get operations.
% \end{function}
%
% \StopEventually{}
%
% \subsection {The Implementation}
%
%    We start by ensuring that the required packages are loaded.
%    \begin{macrocode}
%<package>\ProvidesExplPackage
%<package>  {\filename}{\filedate}{\fileversion}{\filedescription}
%<package>\RequirePackage{l3toks}\par
%<package>\RequirePackage{l3quark}\par
%<*initex|package>
%    \end{macrocode}
%
% A property list is a token register whose contents is
% of the form `\zz{q_prop}key$\sb1$\zz{q_prop}\zv{val$\sb1$} \ldots{}
% \zz{q_prop}key$\sb n$\zz{q_prop}\zv{val$\sb{}n$}'. 
% The properties have to be single
% token, the values might be arbitrary token lists they get surrounded
% by braces.
%
% \begin{macro}{\q_prop}
%    \begin{macrocode}
\quark_new:N\q_prop
%    \end{macrocode}
% \end{macro}

% To get values from property-lists, token lists should be passed to
% the appropriate functions.
%
% \begin{macro}{\prop_new:N}
% \begin{macro}{\prop_new:c}
%    Property lists are implemented as token lists.
%    \begin{macrocode}
\def_new:Npn \prop_new:N #1{\toks_new:N #1}
\def_new:Npn \prop_new:c {\exp_args:Nc \prop_new:N}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\prop_clear:N}
% \begin{macro}{\prop_clear:c}
% \begin{macro}{\prop_gclear:N}
% \begin{macro}{\prop_gclear:c}
%    The same goes for clearing a property list, either
%    locally or globally.
%    \begin{macrocode}
\let_new:NN \prop_clear:N \toks_clear:N
\def_new:Npn \prop_clear:c {\exp_args:Nc\prop_clear:N}
\let_new:NN \prop_gclear:N \toks_gclear:N
\def_new:Npn \prop_gclear:c {\exp_args:Nc\prop_gclear:N}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
%
%
% \begin{macro}{\prop_split_aux:Nnn}
%   |\prop_split_aux:NNn|\zz{plist}\zz{prop}\zz{cmd} invokes \zz{cmd}
%   with 3 arguments: 1st is the beginning of \zz{plist} before
%   \zz{prop}, 2nd is the value associated with \zz{prop}, 3rd is the
%   rest of \zz{plist} after \zz{prop}.  If there is no property
%   \zz{prop} in \zz{plist}, then the 2nd argument will be |\q_no_value|
%   and the 3rd argument is empty; otherwise the 3rd argument has the 
%   extra tokens  |\q_prop| \zz{prop} |\q_prop| |\q_no_value| at the end.
%    \begin{macrocode}
\def_long_new:Npn \prop_split_aux:Nnn #1#2#3{
  \def:Npn \tmp:w ##1\q_prop#2\q_prop##2##3\q_stop {#3{##1}{##2}{##3}}
  \exp_after:NN\tmp:w \toks_use:N#1\q_prop#2\q_prop\q_no_value \q_stop
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\prop_get:NnN}
% \begin{macro}{\prop_get:cnN}
% \begin{macro}{\prop_get_aux:w}
%    |\prop_get:NNN |\zz{plist}\zz{prop}\zz{tlp} defines
%    \zz{tlp} to be the value associated with \zz{prop} in \zz{plist},
%    |\q_no_value| if not found.
%    \begin{macrocode}
\def_long_new:NNn \prop_get:NnN 2{
  \prop_split_aux:Nnn #1{#2}\prop_get_aux:w}
\def_long_new:NNn \prop_get_aux:w 4{\tlp_set:Nx#4{\exp_not:n{#2}}}
\def_new:Npn \prop_get:cnN { \exp_args:Nc \prop_get:NnN }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\prop_gget:NnN}
% \begin{macro}{\prop_gget:NcN}
% \begin{macro}{\prop_gget:cnN}
% \begin{macro}{\prop_gget_aux:w}
%    The global version of the previous function.
%    \begin{macrocode}
\def_long_new:NNn \prop_gget:NnN 2{
  \prop_split_aux:Nnn #1{#2}\prop_gget_aux:w}
\def_new:Npn \prop_gget:NcN {\exp_args:NNc \prop_gget:NnN}
\def_new:Npn \prop_gget:cnN {\exp_args:Nc \prop_gget:NnN}
\def_long_new:NNn \prop_gget_aux:w 4{\tlp_gset:Nx#4{\exp_not:n{#2}}}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\prop_get_gdel:NNN}
% \begin{macro}{\prop_get_del_aux:w}
%    |\prop_get_gdel:NNN| is the same as |\prop_get:NNN| but the
%    \m{property_key} and its value are afterwards globally removed
%    from \m{property_list}. One probably also needs the local
%    variants or only the local one, or\ldots\ We decide this later.
%    \begin{macrocode}
\def_long_new:NNn \prop_get_gdel:NnN 3{
  \prop_split_aux:Nnn #1{#2}{\prop_get_del_aux:w #3{\toks_gset:Nn #1}{#2}}}
\def_long_new:NNn \prop_get_del_aux:w 6{
  \tlp_set:Nx #1{\exp_not:n{#5}}
  \quark_if_no_value:NF #1 {
    \def:Npn \tmp:w ##1\q_prop#3\q_prop\q_no_value {#2{#4##1}}
    \tmp:w #6}
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\prop_put:Nnn}
% \begin{macro}{\prop_put:ccn}
% \begin{macro}{\prop_gput:Nnn}
% \begin{macro}{\prop_gput:Nno}
% \begin{macro}{\prop_gput:Nnx}
% \begin{macro}{\prop_gput:Nox}
% \begin{macro}{\prop_gput:Noo}
% \begin{macro}{\prop_gput:Ncn}
% \begin{macro}{\prop_gput:Ooo}
% \begin{macro}{\prop_gput:cNn}
% \begin{macro}{\prop_gput:ccn}
% \begin{macro}{\prop_gput:cco}
% \begin{macro}{\prop_gput:ccx}
% \begin{macro}{\prop_put_aux:w}
%    |\prop_put:Nnn |\zz{plist}\zz{prop}\zv{val} adds/changes the
%    value associated with \zz{prop} in \zz{plist} to \zv{val}.
%    \begin{macrocode}
\def_long_new:NNn \prop_put:Nnn 2{
  \prop_split_aux:Nnn #1{#2}{
    \prop_clear:N #1
    \prop_put_aux:w {\toks_put_right:Nn #1}{#2}}
}
\def_new:Npn \prop_put:ccn {\exp_args:Ncc \prop_put:Nnn }

\def_long_new:NNn \prop_gput:Nnn 2{
  \prop_split_aux:Nnn #1{#2}{
    \prop_gclear:N #1
    \prop_put_aux:w {\toks_gput_right:Nn #1}{#2}}
}

\def_long_new:NNn \prop_put_aux:w 6{
  #1{\q_prop#2\q_prop{#6}#3}
  \tlist_if_empty:nF{#5}
  {
    \def:Npn \tmp:w ##1\q_prop#2\q_prop\q_no_value {#1{##1}}
    \tmp:w #5
  }
}
\def_new:Npn \prop_gput:Nno {\exp_args:NNno \prop_gput:Nnn}
\def_new:Npn \prop_gput:Nnx {\exp_args:NNnx \prop_gput:Nnn}
\def_new:Npn \prop_gput:Nox {\exp_args:NNox \prop_gput:Nnn}
\def_new:Npn \prop_gput:Noo {\exp_args:NNoo \prop_gput:Nnn}
\def_new:Npn \prop_gput:Ncn {\exp_args:NNc  \prop_gput:Nnn}
\def_new:Npn \prop_gput:Ooo {\exp_args:NOoo \prop_gput:Nnn}
\def_new:Npn \prop_gput:cnn {\exp_args:Nc   \prop_gput:Nnn}
\def_new:Npn \prop_gput:ccn {\exp_args:Ncc  \prop_gput:Nnn}
\def_new:Npn \prop_gput:cco {\exp_args:Ncco \prop_gput:Nnn}
\def_new:Npn \prop_gput:ccx {\exp_args:Nccx \prop_gput:Nnn}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\prop_del:Nn}
% \begin{macro}{\prop_gdel:Nn}
% \begin{macro}{\prop_del_aux:w}
%    |\prop_del:NN |\zz{plist}\zz{prop} deletes the entry for
%    \zz{prop} in \zz{plist}, if any.
%    \begin{macrocode}
\def_long_new:NNn \prop_del:Nn 2{
  \prop_split_aux:Nnn #1{#2}{\prop_del_aux:w {\toks_set:Nn #1}{#2}}}
\def_long_new:NNn \prop_gdel:Nn 2{
  \prop_split_aux:Nnn #1{#2}{\prop_del_aux:w {\toks_gset:Nn #1}{#2}}}
\def_long_new:NNn \prop_del_aux:w 5{
   \def:Npn \tmp:w {#4}
   \quark_if_no_value:NF \tmp:w
     {\def:Npn \tmp:w ##1\q_prop#2\q_prop\q_no_value {#1{#3##1}}
      \tmp:w #5}}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
%
%
% \begin{macro}{\prop_if_in:NnTF}
% \begin{macro}{\prop_if_in:NoTF}
% \begin{macro}{\prop_if_in:ccTF}
% \begin{macro}{\prop_if_in_aux:w}
%    |\prop_if_in:NNTF| \m{property_list} \m{property_key}
%    \m{true_case} \m{false_case} will check whether or not
%    \m{property_key} is on the \m{property_list} and then select
%    either the true or false case.
%    \begin{macrocode}
\def_new:NNn \prop_if_in:NnTF 2{
  \prop_split_aux:Nnn #1{#2}\prop_if_in_aux:w}
\def_new:NNn \prop_if_in_aux:w 3{\quark_if_no_value:nFT {#2}}

\def_new:Npn \prop_if_in:NoTF {\exp_args:NNo \prop_if_in:NnTF}
\def_new:Npn \prop_if_in:ccTF {\exp_args:Ncc \prop_if_in:NnTF}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\prop_gput_if_new:Nnn}
%    |\prop_gput_if_new:NNn| \m{property_list} \m{property_key}
%    \m{property_value} is equivalent to
%    \begin{tabbing}
%       xxxxx\=xxxxx\= \kill
%       |\prop_if_in:NNTF |\m{property}\m{property_key} \\
%       \> |{}%| \\
%       \> |{\prop_gput:Nnn| \\
%       \>\> \m{property_list} \\
%       \>\> \m{property_key} \\
%       \>\> \m{property_value}|}|
%     \end{tabbing}
%    Here we go (listening to Porgy \& Bess in a recording with Ella
%    F. and Louis A. which makes writing macros sometimes difficult; I
%    find myself humming instead of working):
%    \begin{macrocode}
\def_long_new:NNn \prop_gput_if_new:Nnn 2{
  \prop_split_aux:Nnn #1{#2}{\prop_put_if_new_aux:w #1{#2}}}
\def_long_new:NNn \prop_put_if_new_aux:w 6{
  \tlist_if_empty:nT {#5}{#1{\q_prop#2\q_prop{#6}#3}}}
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\prop_set_eq:NN}
% \begin{macro}{\prop_set_eq:Nc}
% \begin{macro}{\prop_set_eq:cN}
% \begin{macro}{\prop_set_eq:cc}
% \begin{macro}{\prop_gset_eq:NN}
% \begin{macro}{\prop_gset_eq:Nc}
% \begin{macro}{\prop_gset_eq:cN}
% \begin{macro}{\prop_gset_eq:cc}
%    This makes two \m{plist}s have the same contents.
%    \begin{macrocode}
\let_new:NN \prop_set_eq:NN  \toks_set_eq:NN
\let_new:NN \prop_set_eq:Nc  \toks_set_eq:Nc
\let_new:NN \prop_set_eq:cN  \toks_set_eq:cN
\let_new:NN \prop_set_eq:cc  \toks_set_eq:cc
\let_new:NN \prop_gset_eq:NN \toks_gset_eq:NN
\let_new:NN \prop_gset_eq:Nc \toks_gset_eq:Nc
\let_new:NN \prop_gset_eq:cN \toks_gset_eq:cN
\let_new:NN \prop_gset_eq:cc \toks_gset_eq:cc
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\prop_if_empty_p:N}
% \begin{macro}{\prop_if_empty_p:c}
% \begin{macro}{\prop_if_empty:NTF}
% \begin{macro}{\prop_if_empty:NT}
% \begin{macro}{\prop_if_empty:NF}
% \begin{macro}{\prop_if_empty:cTF}
% \begin{macro}{\prop_if_empty:cT}
% \begin{macro}{\prop_if_empty:cF}
%    This conditional takes a \m{plist} as its argument and evaluates
%    either the true or the false case, depending on whether or not
%    \m{plist} contains any properties.
%    \begin{macrocode}
\let_new:NN \prop_if_empty_p:N \toks_if_empty_p:N
\let_new:NN \prop_if_empty_p:c \toks_if_empty_p:c
\let_new:NN \prop_if_empty:NTF \toks_if_empty:NTF
\let_new:NN \prop_if_empty:NT  \toks_if_empty:NT
\let_new:NN \prop_if_empty:NF  \toks_if_empty:NF
\let_new:NN \prop_if_empty:cTF \toks_if_empty:cTF
\let_new:NN \prop_if_empty:cT  \toks_if_empty:cTF
\let_new:NN \prop_if_empty:cF  \toks_if_empty:cF
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
%
% \begin{macro}{\prop_if_eq:NNTF}
% \begin{macro}{\prop_if_eq:NNT}
% \begin{macro}{\prop_if_eq:NNF}
% \begin{macro}{\prop_if_eq:NcTF}
% \begin{macro}{\prop_if_eq:NcT}
% \begin{macro}{\prop_if_eq:NcF}
% \begin{macro}{\prop_if_eq:cNTF}
% \begin{macro}{\prop_if_eq:cNT}
% \begin{macro}{\prop_if_eq:cNF}
% \begin{macro}{\prop_if_eq:ccTF}
% \begin{macro}{\prop_if_eq:ccT}
% \begin{macro}{\prop_if_eq:ccF}
%    This function test whether the property lists that are in its first
%    two arguments are equal; if they are not |#3| is executed.
%    \begin{macrocode}
\def_new:NNn \prop_if_eq:NNTF 2 {
  \tlist_if_eq:xxTF{\toks_use:N #1}{\toks_use:N #2}
}
\def_new:NNn \prop_if_eq:NNT 2 {
  \tlist_if_eq:xxT{\toks_use:N #1}{\toks_use:N #2}
}
\def_new:NNn \prop_if_eq:NNF 2 {
  \tlist_if_eq:xxF{\toks_use:N #1}{\toks_use:N #2}
}
\def_new:Npn \prop_if_eq:NcTF {\exp_args:NNc \prop_if_eq:NNTF}
\def_new:Npn \prop_if_eq:NcT {\exp_args:NNc \prop_if_eq:NNT}
\def_new:Npn \prop_if_eq:NcF {\exp_args:NNc \prop_if_eq:NNF}
\def_new:Npn \prop_if_eq:cNTF {\exp_args:Nc \prop_if_eq:NNTF}
\def_new:Npn \prop_if_eq:cNT {\exp_args:Nc \prop_if_eq:NNT}
\def_new:Npn \prop_if_eq:cNF {\exp_args:Nc \prop_if_eq:NNF}
\def_new:Npn \prop_if_eq:ccTF {\exp_args:Ncc \prop_if_eq:NNTF}
\def_new:Npn \prop_if_eq:ccT {\exp_args:Ncc \prop_if_eq:NNT}
\def_new:Npn \prop_if_eq:ccF {\exp_args:Ncc \prop_if_eq:NNF}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\prop_map_function:NN}
% \begin{macro}{\prop_map_function:cN}
% \begin{macro}{\prop_map_function:Nc}
% \begin{macro}{\prop_map_function:cc}
% \begin{macro}{\prop_map_function_aux:w}
%    Maps a function on every entry in the property list.  The
%    function must take 2 arguments: a key and a value.
%    \begin{macrocode}
\def_new:Npn \prop_map_function:NN #1#2{
  \exp_after:NN \prop_map_function_aux:w
  \exp_after:NN #2 \toks_use:N #1 \q_prop{}\q_prop \q_no_value \q_stop
}
\def_new:Npn \prop_map_function_aux:w #1\q_prop#2\q_prop#3{
  \if:w \tlist_if_empty_p:n{#2}
    \exp_after:NN \prop_map_break:w
  \fi:
  #1{#2}{#3}
  \prop_map_function_aux:w #1
}
% problem with the above impl, is that an empty key stops the mapping but all
% other functions in the module allow the use of empty keys (as one value)

\def:Npn \prop_map_function:NN #1#2{
  \exp_after:NN \prop_map_function_aux:w
  \exp_after:NN #2 \toks_use:N #1 \q_prop \q_no_value \q_prop \q_no_value 
}
\def:Npn \prop_map_function_aux:w #1\q_prop#2\q_prop#3{
  \quark_if_no_value:nF{#2}
    {
     #1{#2}{#3}
     \prop_map_function_aux:w #1
    }
}
% problem with the above impl is that \quark_if_no_value:nF is fairly slow and
%  if \quark_if_no_value:NF is used instead we have to do an assignment thus
%  making the mapping not expandable (is that important?)

\def:Npn \prop_map_function:NN #1#2{
    \exp_after:NN \prop_map_function_aux:w
    \exp_after:NN #2 \toks_use:N #1 \q_prop \q_nil \q_prop \q_no_value \q_stop
}
\def:Npn \prop_map_function_aux:w #1\q_prop#2\q_prop#3{
  \if_meaning:NN \q_nil #2
    \exp_after:NN \prop_map_break:w
  \fi:
  #1{#2}{#3}
  \prop_map_function_aux:w #1
}

% (potential) problem with the above impl is that it will returns true is #2
% contains more than just \q_nil thus executing whatever follows. Claim: this
% can't happen :-) so we should be ok

\def_new:Npn \prop_map_function:cN {\exp_args:Nc \prop_map_function:NN }
\def_new:Npn \prop_map_function:Nc {\exp_args:NNc \prop_map_function:NN }
\def_new:Npn \prop_map_function:cc {\exp_args:Ncc \prop_map_function:NN}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
%  \begin{macro}{\prop_map_inline:Nn}
%  \begin{macro}{\prop_map_inline:cn}
%  \begin{macro}{\g_prop_inline_level_num}
%  The inline functions are straight forward. It takes longer
%  to test if the list is empty than to run it on an empty list so
%  we don't waste time doing that.
%    \begin{macrocode}
\num_new:N \g_prop_inline_level_num
\def_new:Npn \prop_map_inline:Nn #1#2 {
  \num_gincr:N \g_prop_inline_level_num
  \gdef_long:cpn {prop_map_inline_ \num_use:N \g_prop_inline_level_num :n} 
    ##1##2{#2}
  \prop_map_function:Nc #1
    {prop_map_inline_ \num_use:N \g_prop_inline_level_num :n}
  \num_gdecr:N \g_prop_inline_level_num
}
\def_new:Npn \prop_map_inline:cN { \exp_args:Nc \prop_map_inline:NN }
%    \end{macrocode}
%  \end{macro}
%  \end{macro}
%  \end{macro}
%
%  \begin{macro}{\prop_map_break:w}
%  The break statement.
%    \begin{macrocode}
\let_new:NN \prop_map_break:w \use_none_delimit_by_q_stop:w
%    \end{macrocode}
%  \end{macro}
%
% Finally a bunch of compatibility commands with the old syntax: they will
% vanish soon!
%    \begin{macrocode}
\def:Npn \prop_put:NNn {\typeout{Warning:~name~ 
                    changed~ to~ \string\prop_put:Nnn}\prop_put:Nnn}
\def:Npn \prop_gput:NNn  {\typeout{Warning:~name~ 
                    changed~ to~ \string\prop_gput:Nnn }\prop_gput:Nnn }
\def:Npn \prop_gput:NNo  {\typeout{Warning:~name~ 
                    changed~ to~ \string\prop_gput:Nno }\prop_gput:Nno }
\def:Npn \prop_gput:cNn  {\typeout{Warning:~name~ 
                    changed~ to~ \string\prop_gput:cnn }\prop_gput:cnn }
\def:Npn \prop_gput_if_new:NNn  {\typeout{Warning:~name~ 
                    changed~ to~ \string\prop_gput_if_new:Nnn }\prop_gput_if_new:Nnn }
\def:Npn \prop_get:NNN  {\typeout{Warning:~name~ 
                    changed~ to~ \string\prop_get:NnN }\prop_get:NnN }
\def:Npn \prop_get:cNN  {\typeout{Warning:~name~ 
                    changed~ to~ \string\prop_get:cnN }\prop_get:cnN }
\def:Npn \prop_gget:NNN  {\typeout{Warning:~name~ 
                    changed~ to~ \string\prop_gget:NnN }\prop_gget:NnN }
\def:Npn \prop_gget:cNN  {\typeout{Warning:~name~ 
                    changed~ to~ \string\prop_gget:cnN }\prop_gget:cnN }
\def:Npn \prop_get_gdel:NNN  {\typeout{Warning:~name~ 
                    changed~ to~ \string\prop_get_gdel:NnN }\prop_get_gdel:NnN }
\def:Npn \prop_del:NN  {\typeout{Warning:~name~ 
                    changed~ to~ \string\prop_del:Nn }\prop_del:Nn }
\def:Npn \prop_gdel:NN  {\typeout{Warning:~name~ 
                    changed~ to~ \string\prop_gdel:Nn }\prop_gdel:Nn }
\def:Npn \prop_if_in:NNTF  {\typeout{Warning:~name~ 
                    changed~ to~ \string\prop_if_in:NnTF }\prop_if_in:NnTF }
%    \end{macrocode}
%
%    Show token usage:
%    \begin{macrocode}
%</initex|package>
%<*showmemory>
%\showMemUsage
%</showmemory>
%    \end{macrocode}
%
%
%
%    \begin{macrocode}
%<*unused>
\file_input_stop:
%    \end{macrocode}
%
%    \begin{macrocode}
%</unused>
%    \end{macrocode}
%
% \endinput
%
