cli の設計
設計目標
適合性の実行は、多数の native プロセスを並列に起動する Python ツールによって駆動されます。--backend スイッチを持つ単一の実行ファイルにすることで、ビルドは単純(MoonBit パッケージ 1 つ、リンク 1 回)に保たれ、各バックエンドは独自のオプション構文を維持できます。ディスパッチャの役割は、ランナーを選び、その戻り値をプロセスの終了ステータスに変換することだけです。
数学的背景
ランナーのもの以外にはありません。唯一の契約は機能的なものです。終了ステータスはランナーの戻り値であり、ランナーの出力はその引数と読み込むファイルにのみ依存します(internal/runner_cli の設計を参照)。
設計上の判断
3 つの層
コーパスの解析と実行は純粋な frontend/* パッケージに、引数処理、ファイルアクセス、出力は cli/*_expr_cli ランナー(それぞれ run(arguments) -> Int を持つライブラリ)にあります。プロセス境界(@env.args()、@sys.exit)は cli にのみ存在します。ランナーがライブラリであるため、その使用経路はプロセスを起動せずに単体テストでき、フロントエンドはすべてのターゲットで利用可能なままです。
プログラム名を転送する
ディスパッチャは --backend とその値を取り除き、[program, rest…] を転送します。どのランナーも要素 0 をスキップするため、ランナーはディスパッチャから呼ばれても、テストから呼ばれても、(原理的には)単独の実行ファイルとして呼ばれても同じように動作します。
1 つのバイナリをバックエンドごとにコピー
tools/conformance_cli.py は src/cli をバックエンド固有のターゲットディレクトリにビルドし、<backend>-conformance.exe にコピーします。したがって異なるバックエンドの並列ビルドが _build ディレクトリやロックを共有することはなく、ツールは常に、何を実行するかが名前からわかる実行ファイルを呼び出します。
ディスパッチャのヘルプが優先
--help はバックエンドが決まる前、引数の走査中に処理されるため、常にディスパッチャの使い方を表示して 0 で終了します。これにより --help はどんな組み合わせでも安全に呼び出せます。ランナーのオプションはそれぞれのページで説明されています。
正しさ/不変条件
- 1 回の呼び出しで呼ばれるランナーはちょうど 1 つです。ただし引数が無効な場合(終了コード
2)や--helpが指定された場合(終了コード0)は 1 つも呼ばれません。 - 終了ステータスはランナーの戻り値
0、1、2のいずれかに等しくなります。 --backend、その値、--help/-h以外の引数は、変更されず順序どおりにランナーに渡されます。
却下した代替案
- 4 つの実行ファイル。 同一の
main関数を持つ 4 つのパッケージと 4 回のリンクが必要になり、動作上の利点はありません。 - サブコマンド(
floating-conformance gda …)。 位置引数によるバックエンド指定はランナーのパスと衝突します。明示的なオプションなら曖昧さがありません。 - ランナーからの終了コード。 ランナー内で
exitを呼ぶと、ライブラリとしてテストできなくなります。
境界
- native ターゲットのみ(ファイルアクセスは
moonbitlang/x/fs、終了はmoonbitlang/x/sys経由)。 - コーパスのダウンロード、計画、並列化、集計は行いません。それらは
tools/conformance.pyとtools/run_*_interpreter.pyスクリプトにあります。 - 公開 MoonBit API はありません。