docs を直した絵

Mandelbrot レンダラが、docs が約束した税を測りに入った: float の infix 演算子は無い、だから全ての式は prefix 呼び出しの山になる、と。docs は言語に有利な方に間違っていた —— float の infix 算術は 3 backend でしばらく前から動いていて、docs に忠実な読み手は一行につき 9 個の無駄な prefix 呼び出しをただ書いていた。古い一文の周りに本物の gap が 3 つ隠れ、向こう端から出てきた絵は正しく、生ピクセルでも ASCII でもバイト単位で同一だった。

merefloatsdocumentationbackendslanguage-design

この Part の大半は、言語が見かけより狭かったことについてだ。この話は言語が見かけより広かった 回 —— 文書が実在するより貧しい言語を記述していて、制限を測るために書かれた probe が、制限は静かに 解除されていたと見つけた回だ。

無い税を測る

計画は Mandelbrot レンダラ、まさに float 算術が底まで続くから選んだ。リファレンスが記述する税を 定量化するためだ: float は「prefix 関数形のみ、infix なし」—— 全ての a*b + c はネストした prefix 呼び出しで書かねばならず、脱出時間の式は膨れ上がる。レンダラのまさに最初の行が負の float リテラルを欲しがって type error を得て、それは裏付けに感じられた。それから無関係な何かを確認して いて、1.5 + 2.03.5 を返した。float の infix + は動いた。-*/、そして全ての比較 も —— interpreter で、C で、wasm で。overload はどこかで足され、リファレンスは一度も更新されて いなかった。まだ prefix-only の世界を約束し、それを信じた読み手は三行の式に理由もなく 9 個の無駄な prefix 呼び出しを書く。これは前 Part の「既にあった」の話の鏡像だ: あちらでは probe が建てるつもり の機能が既にあると見つけた。ここでは probe が docs が否定した機能が既にあると見つけた。文書は 両方向にずれうる。そしてどちらにずれたかは、言語を走らせることだけが教える。

本物の gap 3 つと、正直なしわ

古い一文は本物の gap を 3 つ隠していて、全部直した。単項マイナスはまだ整数専用で —— -2.5 は本当に type error で、負の float リテラルは名前付きの否定関数を要した —— だから二項演算子と 同じく数値 overload になった、4 backend 全部で。LLVM backend は、判明したところでは、float の infix 算術に対して浮動小数点オペランドに整数加算命令を emit していた —— コンパイラが即座に拒否する invalid IR で、float 比較には整数比較を —— だから適切な浮動小数点加算一家と ordered な浮動小数点 比較を得た。そして前話のバイナリ物語の書き半分が欠けていた: バイト vector の reader はあったが writer が無く、だからレンダラは対になる write_file_bytes を得て、画像形式の ASCII 逃げの代わりに 生ピクセル形を emit できるようになった —— 生形は約 3 分の 1 のサイズだ。レンダラは 400×300 の集合を 素の infix 数式で描き、その生ピクセル出力は ASCII 版のピクセルとバイト単位で同一だ。一つの正直な しわが残り、訂正された docs に書き込まれている: overload はオペランドが具体的に float のときだけ float に解決するので、注釈なしの関数パラメータはまだ整数に default し、float 中心のコードは パラメータに注釈する。訂正はリファレンスと標準ライブラリのノートの両方に入った。教訓は Part 全体と 対になる: 4 backend は互いに食い違いうる、そして docs は 4 つ全部と一度に食い違いうる。Part 最後の 話は、これらの probe のうち 2 本が回避せねばならなかった papercut を直し —— そしてその日の帳簿を 閉じる。

← Back to Mere: 言語を作る