luatex:latelua 的执行顺序、对封闭节点列表的影响及其内部工作原理

luatex:latelua 的执行顺序、对封闭节点列表的影响及其内部工作原理

在我对 luatex 的思考中,也许就像爱丽丝梦游仙境一样,有一件事不太清楚,那就是 latelua 的内部工作原理。据我所知,页面上要输出的所有材料都是构建和存储为(可能是单独的,也可能是深层的)tex“节点”嵌套链接列表。此外,据我所知,latelua 将其内容放入其封闭的链接列表中,作为稍后在执行时处理的节点(因此前缀为“late”)。latelua 代码是在包含它的节点列表将出现在页面上时执行的,这意味着它可以在很多页之后,并且可能执行包含节点列表在文档中出现的次数。此外,更棒的是,可以拆分或合并节点列表以形成新的节点列表,然后再将它们放在其他页面上。因此,这里有一些相关问题:luatex 引擎如何维护有关 latelua 节点的信息?是否有处理它们的特殊数据结构(可能是为了提高性能?)。就像一些带有表格的配色方案:比如说,当遇到 latelua 节点时,会在其父节点中设置一个标志,并在 luatex 执行移回父节点时将其传送到上游。这种方案必须尊重节点列表拆分和连接。或者没有单独的数据结构……并且在将内容发送到页面之前,luatex 会遍历该页面上要包含的内容的整个嵌套节点列表,并检查是否存在必须执行的 latelua 节点(这次)?如果是这样,即没有单独的 latelua 节点特殊数据结构,并且要发送的整个节点列表都被遍历,是不是因为 luatex 无论如何都需要完全遍历页面上要出现的节点列表?如果是,那么为什么它在发货前要遍历整个节点列表?有没有办法让发货过程抓取一些预先烘焙的 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

相关内容