マクロツイーター

はてダから移行した記事の表示が崩れてますが、そのうちに直せればいいのに(えっ)

TeX での「代数的データ型」の扱い (4)

前回の続き)

前回までで「TeX で『代数的データ型』(のようなもの)を扱う、少し変態的な方法」について説明した。これを読んで「確かに使えるかも知れないが、現実の実用的なプログラミングの場面で使うことがあるのか」と疑問に思ったかも知れない。実はこの手法は、bxgrassator パッケージという、極めて実用的な*1プログラムにおいて多用されている。

多くの Grass 言語のインタプリタと同様、bxgrassator でも与えられた Grass 言語のソースを「抽象構文形式」(App と Abs の列;Grass 本家サイトの「操作的意味論」の小節を参照)に変換して変数(トークン列マクロ)に格納している。実際に SML 版のインタプリタのソースを見ると、この App や Abs は代数的データ型として扱われていることが解る。

  datatype insn = App of int * int | Abs of int * code
           withtype code = insn list

それでは、実際に bxgrassator で「抽象構文形式」のプログラムがどのように表現されているかを、少し細工をして調べてみよう。

[test.tex]
% pLaTeX 用; 文字コードは pTeX の指定に従う
\documentclass[a4paper]{article}
\usepackage{bxgrassator}
\begin{document}

\begin{prochomuhomu}{\outputTeX}
ほむほむほむ ほむほむほむ ほむほむ ほむほむほむ ほむほむ ほむほむ ほむ
ほむほむ ほむほむ ほむ ほむほむほむ ほむ ほむほむほむほむ ほむ
 ほむほむ ほむ ほむほむほむ ほむ ほむほむほむほむ ほむ ほむほむほむほむ ほむ
 ほむ ほむほむほむほむほむほむほむほむ ほむ ほむほむほむほむほむほむほむほむほむほむ
 ほむほむほむほむほむ ほむほむほむほむほむほむほむほむほむほむ ほむ ほむほむ
 ほむほむほむほむほむほむほむほむ ほむほむほむほむほむほむほむほむほむほむほむほむ
 ほむ ほむほむ ほむほむ ほむ ほむほむほむほむほむ ほむ ほむほむほむほむ ほむ
ほむ ほむほむほむほむほむほむほむほむほむほむほむほむほむほむほむほむほむ ほむ
 ほむ ほむほむほむほむ ほむほむ ほむほむほむほむほむほむほむほむ
 ほむほむほむ ほむほむほむほむ ほむほむほむほむ ほむほむほむほむほむほむほむほむ
ほむ
\end{prochomuhomu}

%% \end{document} せずに終わる

ソースが Grass 言語でないように見えるが気にしないことにしよう。

\end{document} がないため、文書を処理した後に対話モードに入る。ここで、\outputTeX の定義内容を調べてみよう。

# platex -kanji=utf8 test
This is e-pTeX, Version 3.1415926-p3.2-110825-2.3 (utf8.sjis) (TeX Live 2011/W3
TeX)
 restricted \write18 enabled.
entering extended mode
(./test.tex
………(途中省略)………
(c:/Users/yato/texmf/tex/latex/grassator/bxgrassator-px.def))
No file test.aux.
)
*\show\outputTeX                        % \outputTeX の中身を調べる
> \outputTeX=macro:
+>\bxgs@invoke@proc {1}.                % 内部ID「1」が振られている
<*> \show\outputTeX

?
                                        % コードを「コンパイル」した結果が \bxgs@PrArray/1
*\expandafter\show\csname bxgs@PrArray/1\endcsname % に入っているので中身を見る
> \bxgs@PrArray/1=macro:                % 構築子表現を用いていることが解る
+>\bxgs@Abs {3}{\bxgs@App {3}{2}\bxgs@App {3}{2}\bxgs@App {2}{1}}\bxgs@Abs {2}{
\bxgs@App {2}{1}\bxgs@App {3}{1}\bxgs@App {4}{1}}\bxgs@App {2}{1}\bxgs@App {3}{
1}\bxgs@App {4}{1}\bxgs@App {4}{1}\bxgs@App {1}{8}\bxgs@App {1}{10}\bxgs@App {5
}{10}\bxgs@App {1}{2}\bxgs@App {8}{12}\bxgs@App {1}{2}\bxgs@App {2}{1}\bxgs@App
 {5}{1}\bxgs@App {4}{1}\bxgs@Abs {1}{\bxgs@App {17}{1}}\bxgs@App {1}{4}\bxgs@Ap
p {2}{8}\bxgs@App {3}{4}\bxgs@App {4}{8}\bxgs@Abs {1}{}.
<recently read> \bxgs@PrArray/1

<*> ...dafter\show\csname bxgs@PrArray/1\endcsname

? x

これまでに説明したような、構築子を制御綴で表した形式を用いていることが解る。先述の SML 版のインタプリタを見ると、他にも代数的データ型(ソース中の value 等)が使われているが、bxgrassator ではこれらに相当するものも全て同様の扱いを行っている。

*1:異論は当面保留しておこう。