


多くの言語向けのラッパーを作るコード生成器を、直してテストする
ネイティブライブラリの宣言から多言語のラッパーを作る、コンパイラ型のツールを直す時に使う。不具合が始まる処理段階をたどり、変更に合った大きさのテストを回し、回帰テストを足し、変更履歴を書く。
このAIルールを使うには
## 先に作業別のガイドを読み、生成ファイルではなく入力側を直す
### タスク別ガイドから始める
コード変更や専門的なコマンドの実行前に、リポジトリ内の短いタスク別ガイドを探す。広範な概要から手順を組み立て直さず、作業に合うガイドを読む。一般にガイドが扱う内容は次のとおり。
- 全テスト、特定の対象言語一式、単一テストケースの実行。
- コンパイラのデバッグ、構文解析木の調査、メモリ障害の追跡。
- ユーザーマニュアルの編集と構造の検証。
- ソース整形、コメント、コントリビューション規則、コミットメッセージ。
- 継続的インテグレーションでだけ発生する失敗の再現。
これらのガイドに正確なコマンド、フラグ、規則がある場合は正本として扱う。検出用エイリアスやシンボリックリンクによって同じガイドが複数のツール別場所に見える場合は、正本を1つに保ち、コントリビューターの環境でリンクが正しく実体化することを確認する。
### 編集前にシステムを理解する
このリポジトリはコンパイラ型の生成器を実装している。ネイティブ宣言とインターフェース記述を読み取り、ネイティブライブラリを多くの対象言語から利用できるラッパーを生成する。このモデルには三つの実務上の帰結がある。
- 生成ファイルは成果物であり、挙動を直す主要な場所ではない。
- 言語横断の挙動は共有インターフェース入力に置き、対象言語固有のランタイム検査は対応する対象言語用テストディレクトリに置く。
- 構文解析、型解決、所有権、ラッパー生成の変更は、報告された症状が一つのバックエンドだけに見えても、多数のバックエンドへ影響し得る。
リポジトリ自身のガイド、ビルドファイル、テストを根拠として使う。見慣れたディレクトリ名や別プロジェクトの規則だけから、ワークフローを推測しない。
## CIと同じビルドシステムで作り、意味のある一番小さいテストを選ぶ
### 正しいソース形態からビルドする
継続的インテグレーションが使う主要ビルドシステムを使用する。バージョン管理から取得した作業ツリーでは設定ファイルを生成するブートストラップ工程が必要な場合がある一方、リリースアーカイブにはすでに含まれている場合がある。通常の順序は、必要ならブートストラップ、次に設定、最後にビルドとなる。インストール先の接頭辞や任意依存関係の制御など、対応済みの設定スイッチを維持する。
補助ビルドシステムが存在しても、主要パイプラインの失敗を調査する際に黙って置き換えない。テストや例が、ビルド直後のライブラリディレクトリへランタイムを向ける未インストール作業ツリー用ランチャーを使う場合がある。そのランチャーを使用し、インストール済みコピーではなく現在の作業ツリーをテストする。補助的なコンパイラキャッシュ要素が標準のビルド・テストグラフに含まれる場合、正本ガイドが明示的に範囲を狭めていない限り、それも含める。
### 意味のある最小テストを選ぶ
変更範囲にコマンドを合わせる。
- 局所的な挙動を反復確認する間は、生成ラッパーの単一テストを実行する。
- バックエンドの挙動を変更した場合は、影響する対象言語の全テストを実行する。
- パーサー、型システム、所有権、共通生成ロジックを変更した場合は、共有テスト一式を実行する。
- リポジトリが対応する場合に限り、並列実行を使う。
- 広範な実行で最初の失敗時に止めるより全失敗を収集する方が有用なら、継続実行モードを使う。
テストターゲット名は、ネイティブ言語モード、オブジェクト指向モード、複数モジュールモードなど、ソース形態を表すことが多い。ケースに合う接尾辞を使い、古い生成物を新しい失敗と判断する前に、対応するクリーンアップターゲットを実行する。
### 自動化と同じ経路を検証する
失敗が継続的インテグレーションでだけ起きる場合は、リポジトリで保守されているコンテナイメージと実際のインストールスクリプトを使って実行環境を再現する。その場で作った環境より、ホスト側実行環境を再現するヘルパーを優先する。原因をソースコードへ帰属させる前に、依存関係のバージョン、環境変数、ビルドモード、テストターゲットが一致することを確認する。
不具合修正や機能追加には、通常は回帰テストを含める。コンパイラのビルド成功だけで変更を検証済みと判断しない。ラッパー生成、生成コードのコンパイル、対象言語でのランタイム挙動は、それぞれ別の検査点となる。
## 不具合が始まる処理段階を探し、パーサーを入れ子で呼ばない
### 処理段階を順に追う
パイプラインに沿って順番に挙動を追跡する。
1. プリプロセッサーがインターフェース入力と条件付きディレクティブを展開する。
2. 字句解析器が入力テキストを字句要素へ変換する。
3. パーサーが文法を適用し、属性を持つノードの木を作る。
4. 型システムが名前、同値関係、テンプレート、変換を解決する。
5. 木レベルのパスが、後続段階に必要な情報を追加または正規化する。
6. 対象言語バックエンドが木を走査し、ラッパーコードを生成する。
実際の状態が期待状態から最初にずれる段階を特定する。不正なラッパーがあっても、バックエンドが原因とは限らない。バックエンドは、より前の段階で作られた誤った構文解析ノード、型、所有権フラグ、変換規則を忠実に反映しているだけの場合がある。
### 中核となる抽象概念を使う
構文解析ノードはキーと値のオブジェクトのように振る舞い、共有パスと各言語バックエンドから走査される。属性が作られる地点と使われる地点の両方で、その内容を調べる。型変換マップは、ネイティブ値が境界を越えて対象言語の値になる方法を制御する。変換挙動が誤っている場合、生成テキストを修正する前に、選択の優先順位と型の同値関係を確認する。
テンプレートの実体化は同じ型同値判定の仕組みに依存するため、特殊化の照合とラッパーの整形を切り分ける。バックエンド固有のライフタイム回避策を加える前に、共有の所有権・割り当て解析を調べる。
### 非再入パーサーの境界を守る
実装が別の事実を示さない限り、パーサーは非再入であると考える。パーサーを包むエントリーポイントは、現在の入力位置、意味値、先読みを含むグローバルなパーサー状態を上書きする場合がある。文法アクションの内側から、それらのエントリーポイントを再帰的に呼び出さない。
文法規則で新しいパラメーター一覧や関連部分構文を組み立てる必要がある場合は、入れ子の構文解析を始めず、進行中の構文解析内で既存の文法生成規則を再利用する。その文法機能を導入した最古の言語規格に対する回帰ケースで変更を検証する。
### 対応済みのデバッグ機能を使う
リポジトリに記載されたデバッグフラグ、テキストまたは構造化された木のダンプ、デバッガーヘルパー、実行ラッパー、機能選択用変数、メモリプール診断を使う。自動化でだけ発生する失敗では、計測を拡張する前に自動化環境を再現する。診断用の変更は一時的に保ち、必要性を示す失敗テストなしにローカル回避策を製品の挙動へ変えない。
## 回帰テストを、共有の入力と言語別のスクリプトに分けて置く
### 挙動を適切な層へ配置する
テストは通常、生成処理を駆動する共有インターフェース入力と、生成ラッパーを実行する任意の対象言語用ランタイムスクリプトから成る。言語非依存の文法・ラッパー要件は共有入力へ置く。対象言語の構文、ランタイムassert、言語固有の境界ケースは、対応するランタイムスクリプトへ置く。
新しいケースは、真の適用範囲に合うテスト区分へ登録する。言語規格に紐づくテスト名の接頭辞は、便利な例が使う新しい規格ではなく、その文法機能を導入した最古の規格を表さなければならない。機能を単独で特定してから、対応する規格区分へテストを配置する。
### 失敗を観測可能にする
最適化されたランタイムモードでも有効なassertヘルパーを使う。対象言語が最適化中に組み込みassert文を無効にできる場合、回帰テストをその文に依存させてはならない。失敗時に役立つ値を示す、明示的な同値、条件、期待例外用のヘルパーを使う。
テストコメントは短くし、コードだけでは分からない点に限定する。コンパイラの回避策や意味上の落とし穴を簡潔な1行で説明し、コードがすでに示している内容を繰り返さない。回帰テストは修正前に失敗し、修正後に成功し、偶発的な内部ヘルパーではなく外部から利用される挙動を検査しなければならない。
### 共有部分への影響を検証する
パーサーや共通型システムの変更では、影響経路が共有されているなら、最初に失敗したバックエンド以外もテストする。バックエンドだけの挙動では、根拠なしに実行範囲を広げない。実質的に異なるテスト設定の間では生成ファイルをクリーンアップし、報告では生成失敗、ネイティブコンパイル失敗、ランタイム失敗を区別する。
## コミットに無関係な変更を混ぜず、ユーザーに見える変更を変更履歴に書く
### ソースとコメントの規則に従う
無関係なコードを手作業で正規化せず、リポジトリの整形検査とフォーマッターを使う。定着しているネイティブ言語のコメント形式、字句要素の引用方法、行幅、関数ヘッダーの規則に合わせる。文法ファイルでは新しいコードにさらに厳しい規則が課される場合があるため、それに従い、製品パーサーの変更中に無関係なリファクタリングを行わない。
コミット前に、生成ファイル、意図しない広範な置換、対象サブシステム外の変更が差分へ入っていないか確認する。コミット文は平易で簡潔かつ正確にする。自動化ツールを共同著者として記載しない。重要な自動化支援の開示が必要な場合は、メールアドレスを含む識別情報ではなく、プロジェクト所定の支援用トレーラーを使う。
### ユーザーから見える変更を記録する
ユーザーから見える不具合修正、機能、挙動変更、警告変更、非推奨化には、必ず現在の変更履歴へ項目を追加する。内部ヘルパー名やリファクタリングの詳細ではなく、ユーザーが観測する変化を書く。リポジトリ所定の日付とissue形式に従い、新しい項目を想定された順序へ配置し、互換性リスクを明示する。観測可能な影響がない純粋な内部変更には、ユーザー向け項目は不要となる。
### 開発者向け文書とユーザー向け文書を保守する
マニュアル編集時は、自動生成された数値アンカーではなく、安定していて内容を表す見出しアンカーを維持する。コード、対象言語の例、シェルセッション、図には、文書化されたコンテンツクラスを使う。文書間リンクは安定したリンク先へ固定し、目次生成器と文書検査を実行する。
開発者向け文書では、内部オブジェクトモデル、木の属性、型システム、拡張経路を説明する。ユーザー向け文書では、対応する構文と観測可能な挙動に焦点を当てる。レンダリング後の構造とリンク先の両方を検証する。ソース編集の成功だけでは、マニュアルの移動経路が保たれている証拠にならない。
