プログラミング
RustでAIが構築したPHPエンジンがPHP-srcテストの17%をパスし、WordPressをレンダリング
My AI-built PHP engine in Rust passes 17% of PHP-src tests, renders WordPress (ekinertac.com)
要約
著者はRustの知識がないにも関わらず、AIを用いてPHPのインタプリタ「Phargo」をゼロから開発しました。このエンジンはPHP公式テストスイートの17%をパスし、WordPressのページをレンダリングすることに成功しています。本プロジェクトは、AI生成コードの評価に外部テストスイートを厳密かつ公平なシステムとして活用する有効性を示しています。
全文翻訳
数晩前、私はターミナルが26KBのWordPressフロントページを出力するのを見ました — <title>Phargo Test Site</title>、ブロックライブラリのCSS、「Hello world!」がSQLiteデータベースから取得され、最後にクリーンな</html>が表示されました。完全に注目に値しない出力でしたが、一つの詳細を除いては:それをサーブしたPHPエンジンは、PHPの実際のソースコードを一行も含まないのです。それはRustで書かれたゼロからのインタプリタです。
ここで座って考えてほしい部分があります:私はRustを知りません。レクサーを書いたこともありません。別のタブでWikipediaの記事を読むことなく、「ツリーウォーキング評価子」とは何かを説明することはできません。もしパーティーで私を追い詰めてPHPのガベージコレクタがどのように機能するか尋ねたら、私は電話をふりして逃げるでしょう。
エンジンはPhargoと呼ばれ、それに対する私の貢献は、大まかに言って、指示を出すことです。AIがコードを書きます。私はターゲットをそれに向け、返ってきたものを中世の王が海軍の図表をレビューするように読みます — 厳粛なうなずき、理解はゼロ — そして現代のソフトウェア開発における最も強力なフレーズをタイプします:「良さそうだ、続けろ」。
実験:ビルドシステムとしてのラディカルな正直さ
今や誰もがAI構築プロジェクトを持っており、どのプロジェクトも同じ反証不可能な主張をしています:「それは動く!」誰にとって動くのでしょうか?書いたAIにとって?4回目のテイクで録画されたデモにとって?
そのため、実験全体は一つのアイデアに基づいています。Bunチームが実際のテストスイートに対してJavaScriptランタイムを駆動するのを見て借用したものです:AIに自分の宿題を採点させないこと。
PHPは独自のテストスイートを ship しています — 30年以上にわたってPHPの内部チームによって書かれた約22,000の.phptファイルです。私が書かなかったテスト。AIが書かなかったテスト。DateTimeの夏時間計算から、var_dump()がfloatに対して正確に何を出力するかまで、言語のあらゆる呪われた角をエンコードしたテストです。そのスイートが神託です。スコアボードはそれらすべてを実行し、実行後すぐにリポジトリにパス率が自動生成されます。
その数字は、お世辞でごまかすことも、交渉することも、より良い気分にさせるように促すこともできません。bug40261.phptがパスするかしないかのどちらかです。
現在のスコア:22,037件中3,844件 — 全体の上流PHPテストスイートの17.4%。そして17%を鼻で笑う前に:現実的な天井は約40〜45%です。なぜなら、残りのスイートはC拡張機能(GD、curl、SOAP、intl、MySQLドライバなど)をテストしており、それらは明確に範囲外だからです。実際の競技フィールド内では、この上昇は非常に現実的です — ゼロから始まりました。
人間としての私のループは、ほとんど恥ずかしいほど薄いです:
AIは、修正できる最大の失敗テストクラスターを見つけるために、コーパス全体で失敗ヒストグラムを実行します
そのものを実装します
約22,000テストのスコアボードを実行します(約7分間のファンノイズ)
数字が上がったら:コミット、プッシュ、繰り返し
数字が下がったら:私はもう一つのセリフを言うことができます、「うーん、それは後退した、もう一度見て」
それだけです。それが仕事です。私はピークの委任を達成しました、そして私は全く謝罪していません。
神託は買収できない。しかし、ハーネスは私の顔に嘘をついた。
初期の頃、パス率は不正確に感じられる方法で停滞しました。明らかに簡単なテストのカテゴリ全体が、期待される出力と全く同じに見える差分で失敗し続けていました。私は、違いを見つけるパズルで全く同じ写真を見つめる男のように、それらの差分を見つめましたが、何も見つかりませんでした。
違いは文字通り見えなかったため、見えませんでした:キャリッジリターンです。テストコーパスはWindowsでCRLFの行末でチェックアウトされており、私たちのスコアボードは出力をバイト単位で比較していました。PHP自身のテストランナーは比較前に正規化します。私たちのものはしませんでした。これは、ハーネスが本質的にマルチラインテストをすべて行末だけでサイレントに失敗させており、数週間もそうだったことを意味します。
正規化コードの一行。数百のテストが即座にグリーンに変わりました。
この教訓はプロジェクトに刻み込まれました:測定を測定せよ。あなたの神託は、それにつながる配管と同じくらい正直です。私たちは今、run-tests.phpと同じように正規化しており、それ以来のすべての疑わしい停滞は、まず同じ質問を引き起こしました — エンジンが間違っているのか、それともスコアボードが嘘をついているのか?
PHPのテストスイートはREADME付きの地雷原です。
誰かが教えてくれないことの一つは、誰かの22,000ファイルのテストコーパスを実行することです:それらのファイルの一部は爆弾です。悪意のあるものではなく、偶発的なものです。奇妙な構造を割り当てる古いメモリバグの回帰テスト、無限に展開するジェネレータテスト、PHP自身の慎重に隔離されたCI内でしか実行されないことを意図したテストです。
私はすべての偉大な発見と同じ方法でこれを発見しました:私の開発マシンがハードリセットされました。「プログラムがクラッシュした」ではありません。「ターミナルがフリーズした」ではありません。ジェネレータテストが私たちのエンジンに、ロケット推進のショッピングカートのように、ブレーキなしで家中のRAMをすべて食べさせるように仕向けたため、コンピュータ全体がブラックアウトして再起動しました。
その結果、エンジンは疑心暗鬼になり、正直なところ、それは疑心暗鬼をうまく着こなしています:
キャップされたグローバルアロケータ — エンジンは、テストがどれほどクリエイティブであっても、物理的に6GiB以上を割り当てることができません
ステップリミット、無限ループがスペースヒーターなしでエラーで終了するように
文字列サイズ、配列ノード、出力長、ジェネレータ展開のキャップ
スコアボードが現在のテスト名を更新するパンくずリストファイル、そのため何かがハングした場合、どのファイルを睨むべきか正確にわかります
これらはどれも華やかな言語実装の仕事ではありません。すべては「研究プロジェクト」と「コーヒーを淹れている間に、安全に22,000の敵対的なファイルを unattended で処理できるもの」との違いです。
サイレントに嘘をついていた機能
私の好きなバグのジャンル — そしてコーパスはそれらを執拗に見つけます — は、存在するが、解析され、エラーなく実行され、そして全く何も行わない機能です。ポチョムキン組み込み。数ヶ月にわたり、スイートは、とりわけ以下を明らかにしました:
clone — fine に解析され、NULL に評価されました。エンジン全体で。すべてのDateTimeImmutableは、すべてのテストでサイレントに永遠に壊れていました。なぜなら、不変の日付計算はcloneでできているからです。
unset($arr[$key]) — 完全なno-opでした。キーは単に…残りました。
trim($str, $charlist) — 最初からcharlist引数を無視し、とにかく空白をトリムしていました。
$$variableVariables — 存在しませんでした。
static function variables — 存在しませんでした。
spl_autoload_register() — あなたのオートローダーを温かい笑顔で受け入れ、決して呼びませんでした。
catch (\*Throwable) — 何もマッチしませんでした。これは、catch-allにとって非常に面白い特性です。
これらのそれぞれはデモを生き延びたでしょう。それぞれは、Rustを読まない誰か(私)によるコードレビューを生き延びたでしょう。それらのどれもコーパスを生き延びませんでした。それが実験の全体の論文です、一つの箇条書きリストで:私はコードを監査できません、だから22,000のテストが私に代わってそれを監査します、人間レビュアーが決して昼食を過ぎて維持できない徹底さで。
そしてWordPressページをサーブしました
北極星は常にWordPressでした — それはPHP互換性の最終ボスです、2003年以来のPHPのあらゆるイディオムの堆積層を含んでいるほど古いコードベースです。
wp-load.phpをブートストラップさせることさえ、言語弁護士の悪夢のような連鎖を燃焼させました:goto(はい、WordPressのHTMLパーサーはgotoを使用します)、str_replaceのby-reference $countパラメータ、正規表現文字クラス内の\xNNエスケープ、function_exists()が私たちの組み込みの半分に盲目であること。インストーラーは、wpdb::prepare内でpreg_splitがPREG_SPLIT_DELIM_CAPTUREフラグを無視していたため、独自のデータベースを破損しました — 私が診断できたものより4層下のバグ、AIによって発見され修正されました。私は曇ったガラスを通して開胸手術を見ている男のような自信で監督していました。
そしてある夜:wp_install()が完了しました。管理者ユーザーが作成され、オプションテーブルが入力され、SQLiteに3つの投稿がありました。フロントページがレンダリングされました — 実際のテーマ、実際の投稿、実際のパーマリンク。
完全な開示、なぜならラディカルな正直さがすべてだからです:
✅ 新規インストールが実行され、フロントページがデータベースからレンダリングされます
✅ /wp-admin/ もレンダリングされます — 実際のダッシュボード、問題なく、率直に言ってフロントページよりも私を驚かせました
⚠️ REST API は未踏の領域です
⚠️ 現在、実際のPHPの約55倍遅いです