ADR-0003: マニフェストを dowel.toml と dowel.build に分離する
状態: Accepted
文脈
マニフェストを単一ファイル(DSL のみ)とするか、 機械可読部(依存・パッケージ情報)と人間記述部(ターゲット定義)に分離するかの選択。
Cargo は Cargo.toml 単独で成立しているが、これは依存とターゲットの両方が単純なため。
C/C++ のターゲット記述はそこに収まらない。
決定
分離する。dowel.toml(厳密な TOML)と dowel.build(TOML 風方言)。
根拠
当初は「機械による書き換えが単純になる」ことを根拠としたが、 言語サーバのために可逆 CST が必須である以上、この論拠は弱い。実際に効くのは以下2点。
1. 第三者ツールが読めること
依存宣言を厳密な TOML に置くと、SBOM 生成器、脆弱性スキャナ、更新ボットが 本システムの言語を実装せずに依存一覧を読める。 cooldown や監査を重視する方針を採る以上、外部のサプライチェーンツールとの接続性は実利に直結する。
2. 依存宣言に表現力は不要である
単一ファイル案では、原理的に以下が書けてしまう。
deps {
for name in ["a", "b", "c"] { (name) = registry("1.0") }
}
このとき dowel add は挿入すべき場所を持たない。
回避するには deps ブロック内をリテラルのみに制限する必要があるが、
制限した結果は区切り記号が違うだけの TOML になる。
単一ファイル案の利点だった「概念が1つ」はその時点で失われる。
帰結
dowel.tomlは厳密な TOML として維持し、値の位置に式を許さない- 条件付き依存は
when = { os = "windows" }のように閉じた語彙の構造体で表す。 Cargo の[target.'cfg(windows)'.dependencies]のようなキーへの文字列埋め込みは採らない (CMake のジェネレータ式と同じ失敗様式のため) - パーサが2系統になる。TOML ローダが DSL と同じ
Value(型・データ・来歴)を 生成することで、下流の型検査とwhyを共通化する whenの述語語彙はdowel.buildのwhenと同一の意味論を持たなければならない(Q1)
却下した案
単一ファイル(dowel.build のみ) — 読み物としての一貫性では優るが、
上記の理由により依存宣言部を制限せざるを得ず、利点が消える。