TL/1 の呼出規約

私は以前にプログラミング言語 TL/1 のトランスレータを作った。 その他、 TL/1 の面白いと思った部分を取り上げて何度か記事にしている。 私が TL/1 を紹介するにあたって根拠にしているのは月刊 ASCII の 1981 年 1 月号であり、その号には TL/1 のサンプルとして連珠のプログラムが載っていて、自作のトランスレータでその連珠を変換できることも確認している。

TL/1 トランスレータ - 主題のない日記

しかし、確認するにあたって、掲載されていた連珠のプログラムに明らかな間違いがあることも発見している。 仮引数が二個の関数を実引数なしで呼び出している個所が存在するのだ。

状況を単純化した例としてこのようなものを考えよう。

FUNC SQUARE

BEGIN
  WRITE(0: SQUARE)
END

SQUARE(X)
BEGIN
  RETURN X*X
END

関数 SQUARE は引数をひとつ取る関数であるにもかかわらず呼出側では実引数を与えていない。 TL/1 では最初に関数を宣言する段階では引数の情報を持たないので、パーサは SQUARE を呼び出している個所をエラーにすることは出来ない。 コンパイラがこの間違いを検出するとしたら 2 パスにする必要があるが、古い時代の限られたリソースでコンパイルするとしたら厳密な処理はしなかった (エラーとして検出しなかった) 可能性は充分にある。

私は TL/1 については資料を読んだだけで実際に動く環境を持っていなかったのだが、実際に連珠のプログラムを当時のコンパイラコンパイルしてみたという方から情報をもらった。 実引数の数が間違っている連珠のプログラムは当時のコンパイラコンパイルできたそうだ。 しかも、ゲームとして問題なく動作しているように見えるとのことだ。 このことから、 TL/1 の 1981 年当時のコンパイラでは引数の後始末を呼出側でやっているものと推測される。 スタックがずれてしまえば動作どころではなく暴走してしまうのだから、スタックの整合性は保たれていると考えられるからだ。 呼出規約が stdcall や PASCAL のような方式であれば、実引数の個数が間違っていても変数の中身が一時的におかしな値に見えるだけでスタックのずれは起こらない。

Document ID: 6640b10004b68b64362e7c7723299e0b