LATEX-L Archives

Mailing list for the LaTeX3 project

LATEX-L@LISTSERV.UNI-HEIDELBERG.DE

Options: Use Forum View

Use Monospaced Font
Show Text Part by Default
Condense Mail Headers

Message: [<< First] [< Prev] [Next >] [Last >>]
Topic: [<< First] [< Prev] [Next >] [Last >>]
Author: [<< First] [< Prev] [Next >] [Last >>]

Print Reply
Sender:
Mailing list for the LaTeX3 project <[log in to unmask]>
Date:
Mon, 24 Dec 2018 09:22:33 +0000
Reply-To:
Mailing list for the LaTeX3 project <[log in to unmask]>
Message-ID:
Subject:
MIME-Version:
1.0
Content-Transfer-Encoding:
8bit
In-Reply-To:
Content-Type:
text/plain; charset=utf-8; format=flowed
From:
Joseph Wright <[log in to unmask]>
Parts/Attachments:
text/plain (101 lines)
On 24/12/2018 08:13, Tisha Shusho wrote:
> Hello List,
> 
> I am trying to understand the expl3 conventions by looking at its source
> files.

Bear in mind that the code here is often optimised or is set up for 
bootstrapping, particularly if you look at the early stuff.

> As I understand, after the first level of expansion it becomes:
> 
> \prg_new_conditional:Npnn \token_if_macro:N #1 % Line 1
>    { p , T ,  F , TF }                          % Line 2
>    {                                            % Line 3
>      \exp_after:wN \__token_if_macro_p:w        % Line 4
>      \token_to_meaning:N #1 ma:                 % Line 5
>        \q_stop                                  % Line 6
>    }                                            % Line 7
> \cs_new:Npn \__token_if_macro_p:w              % Line 8
>    #1 ma #2 : #3 \q_stop                        % Line 9
>    {                                            % Line 10
>      \str_if_eq:nnTF { #2 } { cro }             % Line 11
>        { \prg_return_true: }                    % Line 12
>        { \prg_return_false: }                   % Line 13
>    }

Yes: the x-type expansion is just dealing with the catcode-12 business.

> The category codes of all characters in ma: (in line 5),
> ma (in line 9), and : (in line 9) are 12.
> Now let's suppose that the arguments are
> \aaa whose meaning is "zzz", bbb, and x respectively.
> So, after the second level of expansion, I think the
> following piece of code is placed into the input stream:
> 
> \prg_new_conditional:Npnn \token_if_macro:N \aaa % Line 1
>    { p , T ,  F , TF }                            % Line 2
>    {                                              % Line 3
>      \__token_if_macro_p:w                        % Line 4
>      zzzma:                                       % Line 5
>                                                   % Line 6
>    }                                              % Line 7
> \cs_new:Npn \__token_if_macro_p:w                % Line 8
>    zzzmabbb:x                                     % Line 9
>    {                                              % Line 10
>      \str_if_eq:nnTF { bbb } { cro }              % Line 11
>        { \prg_return_true: }                      % Line 12
>        { \prg_return_false: }                     % Line 13
>    }
> 
> Shouldn't the token "\aaa" in Line 1 and zzz in
> line 5 and 9 be replaced with "#1", because the function
> \prg_new_conditional:Npnn expects a parameter to be there?
> 
> Also, I am not quite sure about the expansion in Line 9.
> Any help would be gratefully appreciated.

You are trying to do two things at once :) In particular, you are 
thinking that #1, #2, #3, etc. have a fixed meaning 'within one macro'. 
They don't: at *each* step, we have to work out what they mean.

TeX is a macro expansion language, so we need to step through the way it 
does. When you have input

     \token_if_macro:NTF \aaa

it's replaced by the meaning of \token_if_macro:NTF with #1 replaced by 
\aaa. So we have

     \exp_after:wN \__token_if_macro_p:w
       \token_to_meaning:N \aaa ma:
       \q_stop

Then we expand along

     \__token_if_macro_p:w zzzma: \q_stop

and again do replacement, this time matching #1 and #2 for 
\__token_if_macro_p:w. That is a delimited argument so we have

     #1 = zzz
     #2 = [empty]
     #3 = [empty]

which means we have

     \str_if_eq:nnTF { } { cro }
       { \prg_return_true: }
       { \prg_return_false: }

Our test is false, and after that all gets expanded we hit 
\prg_return_false:. There's then some code to deal with the result, and 
it is only at that stage that the two 'payload' arguments become 
important. The code that absorbs them is 'hidden away' inside 
\prg_return_(true|false):. (Try \cs_show:N \prg_return_false:, for example.)

This is a common TeX trick: we don't have to absorb all arguments 'up 
front'. They'll sit there in the input stream until we deal with them ...

Joseph

ATOM RSS1 RSS2