texjporg / ptex-manual

Japanese pTeX Manual
BSD 3-Clause "New" or "Revised" License
23 stars 1 forks source link

pTeX の和文文字トークンのカテゴリーコード #4

Closed aminophen closed 10 months ago

aminophen commented 5 years ago

https://github.com/texjporg/tex-jp-build/issues/68 とはまた別件で…

https://twitter.com/zr_tex8r/status/1119952801952485377

​\kcatcode`あ=18
\def\xA{あ}\let\yA=あ
\ifcat あ\xA O\else X\fi
\ifcat あ\yA O\else X\fi

\kcatcode`あ=17
\ifcat あ\xA O\else X\fi % (1)
\ifcat あ\yA O\else X\fi % (2)
\bye

(1) と (2) は

pTeX では和文文字トークンには kcatcode が含まれず,その都度算出されるが,upTeX では元々和文文字トークンに kcatcode も含まれる … (★)

という現象を試すためのものです。確かに upTeX では両方 X となるのですが,pTeX では (1) が O で (2) が X になります。(★)に基づくと (2) が X になるのが不思議ですが,なにか理由があるのでしょうか?

h-kitagawa commented 5 years ago

tex.web の \let の処理のところを見ると,次のように cur_cmd, cur_chr を保存するようになっています.和文文字トークンの場合は kcatcode が cur_cmd なので,和文文字トークンを \let すると kcatcode が保存されることになります.

@ @<Assignments@>=
let:  begin n:=cur_chr;
  get_r_token; p:=cur_cs;
  ...
  if cur_cmd>=call then add_token_ref(cur_chr);
  define(p,cur_cmd,cur_chr);
  end;

あくまでも (★) を貫くとしたら,\if\ifcat の判定処理で「cur_cmd が 16, 17, 18 のどれかならば,文字コード (cur_chr) から改めて再計算」を加えることになる?

aminophen commented 5 years ago

ご説明ありがとうございます。なるほど,理由は理解できました。どうするのがいいかは悩み中。

(ドキュメント化しようとすると,疑問発生は尽きないですね…。)

aminophen commented 5 years ago

texjporg/tex-jp-build@bdfba95 のコメント欄の続きです。


あくまでも (★) を貫くとしたら,\if や \ifcat の判定処理で「cur_cmd が 16, 17, 18 のどれかならば,文字コード (cur_chr) から改めて再計算」を加えることになる?

「pTeX 単独の挙動の一貫性」という観点からは,この方針に賛成です。ところが,

という2点が引っかかっています。

[2] は先のコメントに書いた通りです。

[1] は,アスキーの公式文書には「随時算出」の記載が見つからないという理由です。一方で,pTeX に詳しい方からすれば,よく知られている挙動なのでしょうか?

ptex-manual.tex:

  \item 欧文文字は\TeX82と同様に1つの文字トークンはカテゴリーコード$c$と文字コード$s$の組
    み合わせ($256c+s$)で表現されていた.\pTeX では和文文字トークンは文字コードのみで表現さ
    れ,そのカテゴリーコードは随時算出されるようになっている
    \footnote{\upTeX では和文文字トークンについてもそのカテゴリーコードの情報が
    含まれるようになった.}.

uptex-base/01uptex_doc_utf8.txt:

<10> 従来のpTeXでは、kcatcodeの参照を文字コードからkcatcodeの表を引き
   間接的に行う方法を行っている。この方法を
   ファイルなどからの読み込み時と内部処理時の両方で行っている。
   upTeXでは、ファイルなどからの読み込み時は同様であるが、
   内部処理時には、<9>でCJKトークン毎に振ったkcatcodeを読み込むように
   変更した。たとえ同じ文字コードでもkcatcodeの途中変更を行えば、
   CJKトークン毎に異なるkcatcodeを割り当てることが出来るようになる。
t-tk commented 5 years ago

「随時算出」という仕様として書かれているわけではありませんが関連する記述としては

ASCII社のweb archiveの kcatcode関連のところ (ドワンゴgithubの同ページ)に

なお、pTeXでは、2バイト文字のカテゴリコードを変更することはできません。なぜなら、pTeXは2バイト文字のカテゴリコードを、その文字の1バイト目で 判断していますが、つぎのように、シフトJISコードの1バイト目が必ずしも、 区点コードの`区'に対応していないためです。 そのため、仮に区単位でカテゴリコードを変更できるようにしても、 SJIS版とEUC版で同じ動作が保証できなくなります。 内部コードを統一すれば不可能ではありませんが、現在は見送っております。

とあります。 「kcatcode を変更して使用することは想定外」と解釈できます。「随時算出」という実装形態を取っているかどうかの点が「仕様」なのではなく「kcatcodeは変更しない」点が仕様のようなものに当たるという風に私は認識しています。ただし、文書全体でkcatcodeがデフォルトと異なるものに固定してしまってもいい場合はASCII pTeXでもkcatcodeの変更は出来たはずです。 しかし、ASCII pTeXを離れてコミュニティ版pTeXとして考えた場合には拡張してもよい部分と思っています。ASCII社さんの「内部コードを統一すれば不可能ではありませんが、現在は見送っております。」という文も将来の拡張の可能性を匂わせる記述ですし。

t-tk commented 5 years ago

それから、現行のpTeXは内部コードがSJISの場合でも「シフトJISコードの1バイト目」ではなく「区点コードの`区'相当」で判定するようになっているはずです。ptexencかその前身のlibkanjiのどこかで実装されました。つまり「内部コードを統一すれば」は既に実現しています。

h-kitagawa commented 5 years ago

[2] この変更は pTeX と upTeX の差分が増やす方向である

想定されていない使い方でしょうけれども,例えば

\kcatcode`あ=16
\def\X#1あ{\message{X: #1}}
\kcatcode`あ=17
\def\Y#1あ{\message{Y: #1}}
\kcatcode`あ=17
\X aあ\Y bあ\bye

を走らせると,次のように現行でも pTeX と upTeX で挙動の違いが見られます:

「pTeX と upTeX の差分を減らす」のならば,pTeX でも \kcatcode を和文文字トークンに含めるように改修するのがもっとも自然でしょう.ただ,個人的には「そこまでして upTeX じゃなくて pTeX にこだわる必要はあるの?」と思っていますが…….

t-tk commented 5 years ago

「素の pTeX/upTeX バイナリ」https://github.com/texjporg/tex-jp-build/issues/32 で途中になっている議論にも関連し、「pTeX と upTeXのメンテを今後どうやっていく?」ということにも深く関わっていると思います。 曖昧な記憶では upTeX の開発初期の頃 pTeX の挙動を離れ kcatcode をトークンごとに振るようにするのは相当骨が折れる作業でしたが

ということと

ということを天秤に掛けつつ、思い切ってやることにしました。 「将来 pTeX が upTeX の kcatcode の実装を取り込んでくれる形になればpTeX と upTeX の差分を減らすことが出来る」ということは、当時は夢のようなレベルで考えていました。

「そこまでして upTeX じゃなくて pTeX にこだわる必要はあるの?」

「こだわり」というより、今後のメンテナンス性という面で「pTeXとupTeXの差分を減らしたい」という希望はあります。しかし、もしやるとなると目前の実装や検証の手間もエンバグの恐怖も発生する訳で、「どこまで頑張るか?」あるいは「どこで頑張るか?」ですね。

aminophen commented 5 years ago

皆様ありがとうございます。悩みましたが,以下のように考えるのはどうでしょうか。

pTeX族のプログラムと互換性があるはず/あるつもりですが、どこまで検証するかが課題になりそう

では,この差異を無視する。

pTeX に upTeX の実装を持ち込む作業の手間とエンバグの恐怖を避けつつ,今後のメンテナンス性をなるべく損わない落とし所はこんなところかな,という一案です。

t-tk commented 5 years ago

本件に関して気になった点。

ptex-manual.tex:

  \csitem[\.{kcatcode} <character code>=<16--18>]
  |\kcatcode|はDVI中の上位バイト(すなわち,JISコードでいう区ごと)に値が設定可能である.
  初期状態では1,~2, 7--15, 85--94区の文字が18,3--6区の文字が17,16--84区の文字が16である.

欧文TeXの catcode, upTeXの kcatcode では文字ごとに {,k}catcodeが保存されていたり、グループごとに初期値を別々に設定できたり細かい制御が出来る訳ですが、それと同じノリで捉えた場合に上記の表現が誤解を生むと思いました。 先日から話の出ている、pTeX の kcatcode の「固定という前提」や「(現在の)実装」をもとにすると「初期値の変更は想定されていないし、あえて変更するならgoto型の設定変更になる」ような情報も入れたほうがよいかもしれません。 具体的な文案はまだ考えていません。

t-tk commented 5 years ago

細かいことですが、オリジナルのASCII pTeXでは内部コードがSJISのときkcatcodeはSJISの上位バイト(2区ごと)に設定可能でした。 しかし、このマニュアルのあちこちで ptexenc版の pTeX の動作を記述している箇所がいろいろあるようです。なので、むしろ、マニュアルが対象としているpTeXとはどの版なのかをどこかに明示すべきということになります。

aminophen commented 5 years ago

upTeX のリビルドに付随して,pTeX のソースにも texjporg/tex-jp-build@ea452bc の

\if や \ifcat の判定処理で「cur_cmd が 16, 17, 18 のどれかならば,文字コード (cur_chr) から改めて再計算」を加える

が反映されたことになります。上のコメントに書いたマニュアルのアップデートも後ほどやっておきます。(そのためここはまだ open にしておきます)

aminophen commented 3 years ago

本件ですが,改めて動かしてみると \let\CS=あ とした制御綴 \CS を比較すると,pTeX の \ifcat では「\kcatcode 再評価」が行われるのに対し,\ifx では行われないことに気づきました。

%#!ptex
\kcatcode`あ=16\relax
\let\X=あ
\let\Z=あ
\kcatcode`あ=17\relax
\let\Y=あ

\if\X\Y    T\else F\fi
\if\X\Z    T\else F\fi
\ifcat\X\Y T\else F\fi
\ifcat\X\Z T\else F\fi
\ifx\X\Y   T\else F\fi % => why FALSE?
\ifx\X\Z   T\else F\fi

\end

つまり,\ifcat と \ifx で挙動が違う状態になっています。

一応,このパッチのようにすれば \ifx でも「\kcatcode 再評価」ができますが,pTeX と upTeX の差分を増やす方向になってしまいます。むしろ前回の変更 (https://github.com/texjporg/tex-jp-build/commit/ea452bc) を元に戻して「\let\CS=和文文字 では kcatcode が保存される」としてもいいような気がしてきました。

aminophen commented 3 years ago

https://github.com/texjporg/ptex-manual/issues/8 に絡んで発生した TeX.SX の質問に回答したところ,速攻で「\let\CS=あ」した制御綴の \ifx 挙動が一貫していないことがばれてしまいました(回答に付随するコメント欄参照)。というわけで,すぐ上のコメントの結論を出さないといけないようです。

aminophen commented 3 years ago

https://github.com/texjporg/tex-jp-build/pull/120 をマージしたので

に合わせてドキュメント更新しようと思います(r59701 で p3.9.1 にしています)。 → 5404284028b894c7601bb9e40b9f494999220bef

aminophen commented 3 years ago

https://github.com/texjporg/tex-jp-build/pull/120 のコメントのうち関連する物:

By aminophen:

2019-05-06 付けの「pTeX (非upTeX) では和文文字トークンが kcatcode を持たないので,制御綴に \let されたものを再計算する」を意図したコードを revert するものです。意図は,この再計算が \ifcat には効いているものの \ifx には効いておらず,結果的に不整合を起こしていたため,元の挙動に戻したいということです。

「和文文字トークンは kcatcode を持たない」という仕様/挙動の一貫性については,\let された制御綴からは再計算しない(見た目も「和文文字トークン」に見えないし…)としても大して損なわれないと考え直しました。むしろ \let で kcatcode が保持される方が使い勝手は良い気がしますし,upTeX とのコード差分も減らす方向です。

By t-tk:

将来の方向性として、「pTeX (非upTeX) では和文文字トークンが kcatcode を持たない」という仕様をやめて「pTeXも(upTeXと同じように)和文文字トークンが kcatcode を持つ」ように改造する方向はいかがでしょうか。 現行pTeXエンジンとの差分は大きいというデメリットがある一方、upTeXエンジンとの差分を減らす方向ですし、既存のpTeX向けに書いたソースコードの動作には影響ないはずです。

By aminophen:

個人的には好ましい方向だと思います。一方で

  • pTeX (非upTeX) では和文文字トークンが kcatcode を持たない
  • upTeX では CJK 文字トークンが kcatcode を持つ

この差を取り除けば,もはや pTeX が独立して存在する意義はなくなると思います。ですので,いろいろな方面から意見を聞きたいです。

pTeX の仕様変更に合意された場合は,もはや実際には upTeX-1.25 の

  • Set default internal encoding EUC/SJIS if a command name is with prefix of "p" or "ep", intending to be compatible with pTeX family (ptex, eptex, pbibtex, pdvitype, ppltotf, (experimental).

という機能を活用して「内部コードが euc/sjis の upTeX」を pTeX の代わりに起動すれば十分であると思います。 texjporg/tex-jp-build#32 とも近い話で,バイナリを減らす方向ならメンテナンス性は上がりそうです。