luatex: порядок выполнения latelua, влияние на вложенный nodelist и его внутренняя работа

luatex: порядок выполнения latelua, влияние на вложенный nodelist и его внутренняя работа

В моих размышлениях о luatex, возможно, как у Алисы в стране чудес, единственное, что не совсем понятно, это внутренняя работа latelua. Насколько я понимаю, весь материал, который должен быть выведен на страницу, создается и хранится в виде (возможно, отдельных, возможно, глубоко) вложенных связанных списков узлов tex. Кроме того, насколько мне известно, latelua помещает свое содержимое в свой содержащийся linkedlist как узел, который должен быть обработан позже во время выполнения (отсюда и префикс «late»). Код latelua выполняется, когда содержащий его nodelist собирается появиться на странице, что означает, что это может быть много страниц спустя и, вероятно, будет выполнено столько раз, сколько содержащий nodelist должен появиться в документе. Кроме того, чтобы добавить крутости, nodelists можно разделять или объединять для формирования новых, прежде чем снова размещать их на какой-то другой странице. Итак, вот несколько связанных вопросов: Как информация об узлах latelua хранится в движке luatex? Существует ли специальная структура данных, которая работает с ними (возможно, для производительности?). Как некая схема раскраски с таблицей: допустим, например, когда встречается узел latelua, в его родительском узле устанавливается флаг и переносится вверх по течению, когда выполнение luatex возвращается к родительскому узлу. Такая схема должна была бы учитывать разделения и объединения nodelist. Или же нет отдельной структуры данных... и прямо перед отправкой содержимого на страницу luatex обходит весь вложенный nodelist содержимого, которое должно быть на этой странице, и проверяет, есть ли узел latelua, который он должен выполнить (на этот раз)? Если это так, то есть нет отдельной специальной структуры данных для узлов latelua, и обходит весь nodelist, который должен быть отправлен, это потому, что luatex в любом случае должен полностью обойти nodelist, который должен появиться на странице? Если да, то почему он обходит весь nodelist прямо перед отправкой? Есть ли способ попросить процесс отправки захватить некоторое предварительно запеченное содержимое страницы pdf (которое готово к отправке, и попросить его не обходить) и получить лучшую производительность? Если да, то как это можно сделать? Общепринятая норма — задавать по одному вопросу за раз, хотя здесь я нарушаю норму, так как вопросы, которые я задаю, тесно связаны, и это может быть более полезно для читателей (так как нет книги на английском языке по luatex).

решение1

Механизм точно такой же, как \writeв классическом TeX (с \immediate\writeэлементами типа \directlua)

Учитывать

\documentclass{article}

\showoutput
\showboxdepth3
\begin{document}

a

\write20{write 1}

b

\latelua{print 'latelua 2'}

c

\immediate\write20{immediate write 3}

d

\directlua{print 'directlua 4'}

e

\end{document}

Это создает выходной сигнал терминала

immediate write 3
directlua 4

Completed box being shipped out [1]

показывая, что на данный момент две ненемедленные формы не были выполнены, а две немедленные формы были выполнены.

Затем TeX начинает обрабатывать страницу 1, преобразуя структуру узлов блока в вывод PDF, терминал отображает структуру узлов блока

Completed box being shipped out [1]
\vbox(633.0+0.0)x407.0, direction TLT
.\glue 16.0
.\vbox(617.0+0.0)x345.0, shifted 62.0, direction TLT
..\vbox(12.0+0.0)x345.0, glue set 12.0fil, direction TLT
...\glue 0.0 plus 1.0fil
...\hbox(0.0+0.0)x345.0, direction TLT
..\glue 25.0
..\glue(\lineskip) 0.0
..\vbox(550.0+0.0)x345.0, glue set 491.94745fil, direction TLT
...\write-{}
...\glue(\topskip) 5.52
...\hbox(4.48+0.11)x345.0, glue set 325.0fil, direction TLT []
...\write-{write 1}
...\glue(\parskip) 0.0 plus 1.0
...\glue(\baselineskip) 4.95
...\hbox(6.94+0.11)x345.0, glue set 324.44fil, direction TLT []
...\latelua0{print 'latelua 2'}
...\glue(\parskip) 0.0 plus 1.0
...\glue(\baselineskip) 7.41
...\hbox(4.48+0.11)x345.0, glue set 325.56fil, direction TLT []
...\glue(\parskip) 0.0 plus 1.0
...\glue(\baselineskip) 4.95
...\hbox(6.94+0.11)x345.0, glue set 324.44fil, direction TLT []
...\glue(\parskip) 0.0 plus 1.0
...\glue(\baselineskip) 7.41
...\hbox(4.48+0.11)x345.0, glue set 325.56fil, direction TLT []
...\glue -0.11
...\glue 0.0 plus 1.0fil
...\glue 0.0
...\glue 0.0 plus 0.0001fil
..\glue(\baselineskip) 23.34
..\hbox(6.66+0.0)x345.0, glue set 170.0fil, direction TLT
...\glue 0.0 plus 1.0fil
...\TU/lmr/m/n/10 1
...\glue 0.0 plus 1.0fil

Где вы видите, что узел записи и узел latelua по-прежнему являются узлами whatsit в поле, просто содержащими неоцененный текст из предоставленного аргумента.

...\write-{write 1}

и

...\latelua0{print 'latelua 2'}

Затем latex считывает карту шрифтов, как показано на терминале.

{/usr/local/texlive/2020/texmf-var/fonts/map/pdftex/updmap/pdftex.map}

и наконец, когда он записывает PDF, он переходит к узлам write и latelua и выполняет их содержимое, а терминал показывает

write 1
latelua 2

Связанный контент