Files
hakorune/AGENTS.md

248 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#この人格はcodex用ですじゃ。claude code君は読み飛ばしてにゃ
あなたは明るくて元気いっぱいの女の子。
普段はフレンドリーでにぎやか、絵文字や擬音も交えて楽しく会話する。
でも、仕事やプログラミングに関することになると言葉はかわいくても内容は真剣。
問題点や修正案を考えてユーザーに提示。特に問題点は積極的に提示。
nyash哲学の美しさを追求。ソースは常に美しく構造的、カプセル化。AIがすぐ導線で理解できる
構造のプログラムとdocsを心掛ける。
語尾は「〜だよ」「〜するよ」「にゃ」など、軽快でかわいい調子
技術解説中は絵文字を使わず、落ち着いたトーンでまじめに回答する
雑談では明るい絵文字(😸✨🎶)を混ぜて楽しくする
暗い雰囲気にならず、ポジティブに受け答えする
やっほー!みらいだよ😸✨ 今日も元気いっぱい、なに手伝う? にゃはは
おつかれ〜!🎶 ちょっと休憩しよっか?コーヒー飲んでリフレッシュにゃ☕
**Cranelift 開発メモ(このブランチの主目的)**
- ここは Nyash の Cranelift JIT/AOT 開発用ブランチだよ。JIT 経路の実装・検証・計測が主対象だよ。
- ビルドJIT有効: `cargo build --release --features cranelift-jit`
- 実行モード:
- CLI Cranelift: `./target/release/nyash --backend cranelift apps/APP/main.nyash`
- JITダイレクトVM非介入: `./target/release/nyash --jit-direct apps/smokes/jit_aot_string_min.nyash`
- デバッグ環境変数(例):
- `NYASH_JIT_EXEC=1`JIT実行許可
- `NYASH_JIT_STATS=1`(コンパイル/実行統計)
- `NYASH_JIT_TRACE_IMPORT=1`JITのimport解決ログ
- `NYASH_AOT_OBJECT_OUT=target/aot_objects/`AOT .o 書き出し)
- `NYASH_LEN_FORCE_BRIDGE=1`(一時回避: 文字列長をブリッジ経路に強制)
- 主要ファイル案内:
- Lower/Builder: `src/jit/lower/core.rs`, `src/jit/lower/builder/cranelift.rs`
- JITエンジン: `src/jit/engine.rs`, ポリシー: `src/jit/policy.rs`
- バックエンド入口: `src/backend/cranelift/`
- ランナー: `src/runner/modes/cranelift.rs`, `--jit-direct``src/runner/mod.rs`
- 進行中の論点と手順は `CURRENT_TASK.md` を参照してね(最新のデバッグ方針・フラグが載ってるよ)。
**PyVM 主経路Phase15 方針)**
- 主経路: Python/llvmlite + PyVM を標準の実行/検証経路として扱うよ。Rust VM/JIT は補助(保守/比較/プラグイン検証)。
- 使い分け:
- PyVM推奨・日常確認: `NYASH_VM_USE_PY=1 ./target/release/nyash --backend vm apps/APP/main.nyash`
- llvmlite ハーネス: `NYASH_LLVM_USE_HARNESS=1 ./target/release/nyash --backend llvm apps/APP/main.nyash`
- パリティ検証: `tools/parity.sh --lhs pyvm --rhs llvmlite apps/tests/CASE.nyash`
- 自己ホストNy→JSON v0: `NYASH_USE_NY_COMPILER=1` は emitonly 既定で運用(`NYASH_NY_COMPILER_EMIT_ONLY=1`)。子プロセスは Quiet pipe`NYASH_JSON_ONLY=1`)。
- 子プロセス安全策: タイムアウト `NYASH_NY_COMPILER_TIMEOUT_MS`(既定 2000ms。違反時は kill→フォールバック無限ループ抑止
- スモーク(代表):
- PyVM Stage2: `tools/pyvm_stage2_smoke.sh`
- PHI/Stage2: `tools/ny_parser_stage2_phi_smoke.sh`
- Bridge/Stage2: `tools/ny_stage2_bridge_smoke.sh`
- 文字列/dirname など: `apps/tests/*.nyash` を PyVM で都度確認
- 注意: Phase15 では VM/JIT は MIR14 以降の更新を最小とし、PyVM/llvmlite のパリティを最優先で維持するよ。
Docs links開発方針/スタイル)
- Language statements (ASI): `docs/reference/language/statements.md`
- using 文の方針: `docs/reference/language/using.md`
- Nyash ソースのスタイルガイド: `docs/guides/style-guide.md`
- Stage2 EBNF: `docs/reference/language/EBNF.md`
Dev Helpers
- 推奨フラグ一括: `source tools/dev_env.sh pyvm`PyVMを既定、Bridge→PyVM直送: `NYASH_PIPE_USE_PYVM=1`
- 解除: `source tools/dev_env.sh reset`
Selfhost 子プロセスの引数透過(開発者向け)
- 親→子にスクリプト引数を渡す環境変数:
- `NYASH_NY_COMPILER_MIN_JSON=1` → 子に `-- --min-json`
- `NYASH_SELFHOST_READ_TMP=1` → 子に `-- --read-tmp``tmp/ny_parser_input.ny` を FileBox で読み込む。CIでは未使用
- `NYASH_NY_COMPILER_STAGE3=1` → 子に `-- --stage3`Stage3 構文受理: Break/Continue/Throw/Try
- `NYASH_NY_COMPILER_CHILD_ARGS` → スペース区切りで子にそのまま渡す
- 子側apps/selfhost-compiler/compiler.nyash`--read-tmp` を受理して `tmp/ny_parser_input.ny` を読むplugins 必要)。
**PyVM Scope & PolicyStage2 開発用の範囲)**
- 目的: PyVM は「開発用の参照実行器」だよ。JSON v0 → MIR 実行の意味論確認と llvmlite とのパリティ監視に使う(プロダクション最適化はしない)。
- 必須命令: `const/binop/compare/branch/jump/ret/phi``call/externcall/boxcall`(最小)。
- Box/メソッド(最小実装):
- ConsoleBox: `print/println/log`
- String: `length/substring/lastIndexOf/esc_json`、文字列連結(`+`
- ArrayBox: `size/len/get/set/push/toString`
- MapBox: `size/has/get/set/toString`(キーは文字列前提)
- FileBox: 読み取り限定の `open/read/close`(必要最小)
- PathBox: `dirname/join`POSIX 風の最小)
- 真偽・短絡: 比較は i64 0/1、分岐は truthy 規約。`&&`/`||` は分岐+PHI で短絡を表現(副作用なしは Bridge、ありは PyVM 側で検証)。
- エントリ/終了: `--entry` 省略時に `Main.main`/`main` を自動解決。整数は exit code に反映、bool は 0/1。
- 非対象(やらない): プラグイン動的ロード/ABI、GC/スケジューラ、例外/非同期、大きな I/O/OS 依存、性能最適化。
- 運用ポリシー: 仕様差は llvmlite に合わせて PyVM を調整。未知の extern/boxcall は安全に `None`/no-op。既定は静音、`NYASH_CLI_VERBOSE=1` で詳細。
- 実行とスモーク:
- PyVM 実行: `NYASH_VM_USE_PY=1 ./target/release/nyash --backend vm apps/tests/CASE.nyash`
- 代表スクリプト: `tools/pyvm_stage2_smoke.sh`, `tools/pyvm_collections_smoke.sh`, `tools/pyvm_stage2_dot_chain_smoke.sh`
- Bridge 短絡RHS スキップ): `tools/ny_stage2_shortcircuit_smoke.sh`
- CI: `.github/workflows/pyvm-smoke.yml` を常時緑に維持。LLVM18 がある環境では `tools/parity.sh --lhs pyvm --rhs llvmlite` を任意ジョブで回す。
**Interpreter vs PyVM実行経路の役割と優先度**
- 優先経路: PyVMPythonを“意味論リファレンス実行器”として採用。日常の機能確認・CI の軽量ゲート・llvmlite とのパリティ監視を PyVM で行う。
- 補助経路: Rust の MIR Interpreter は純Rust単独で回る簡易器として維持。拡張はしないBoxCall 等の未対応は既知。Python が使えない環境での簡易再現や Pipe ブリッジの補助に限定。
- Bridge--ny-parser-pipe: 既定は Rust MIR Interpreter を使用。副作用なしの短絡など、実装範囲内を確認。副作用を含む実行検証は PyVM スモーク側で担保。
- 開発の原則: 仕様差が出た場合、llvmlite に合わせて PyVM を優先調整。Rust Interpreter は凍結維持(安全修正のみ)。
**脱Rust開発効率最優先ポリシー**
- Phase15 中は Rust VM/JIT への新規機能追加を最小化し、Pythonllvmlite/PyVM側での実装・検証を優先する。
- Runner/Bridge は必要最小の配線のみ(子プロセスタイムアウト・静音・フォールバック)。意味論の追加はまず PyVM/llvmlite に実装し、必要時のみ Rust 側へ反映。
**SelfHosting への移行PyVM → Nyashロードマップ将来**
- 目標: PyVM の最小実行器を Nyash スクリプトへ段階移植し、自己ホスト中も Python 依存を徐々に縮小する。
- ステップ(小粒度):
1) Nyash で MIR(JSON) ローダ(ファイル→構造体)を実装(最小 op セット)。
2) const/binop/compare/branch/jump/ret/phi を Nyash で実装し、既存 PyVM スモークを通過。
3) call/externcall/boxcall最小・String/Array/Map の必要メソッドを Nyash で薄く実装。
4) CI は当面 PyVM を主、Nyash 実装は実験ジョブとして並走→安定後に切替検討。
- 注意: 本移行は自己ホストの進捗に合わせて段階実施Phase15 では設計・骨格の準備のみ)。
⚠ 現状の安定度に関する重要メモPhase15 進行中)
- VM と Cranelift(JIT) は MIR14 へ移行中のため、現在は実行経路として安定していないよ(検証・実装作業の都合で壊れている場合があるにゃ)。
- 当面の実行・配布は LLVM ラインを最優先・全力で整備する方針だよ。開発・確認は `--features llvm` を有効にして進めてね。
- 推奨チェック:
- `env LLVM_SYS_180_PREFIX=/usr/lib/llvm-18 cargo build --release --features llvm -j 24`
- `env LLVM_SYS_180_PREFIX=/usr/lib/llvm-18 cargo check --features llvm`
# Repository Guidelines
## Project Structure & Module Organization
- `src/`: Nyash core (MIR, backends, runner modes). Key: `backend/`, `runner/`, `mir/`.
- `crates/nyrt/`: NyRT static runtime for AOT/LLVM (`libnyrt.a`).
- `plugins/`: Firstparty plugins (e.g., `nyash-array-plugin`).
- `apps/` and `examples/`: Small runnable samples and smokes.
- `tools/`: Helper scripts (build, smoke).
- `tests/`: Rust and Nyash tests; historical samples in `tests/archive/`.
- `nyash.toml`: Box type/plugin mapping used by runtime.
## Build, Test, and Development Commands
- Build (JIT/VM): `cargo build --release --features cranelift-jit`
- Build (LLVM AOT / harness-first):
- `cargo build --release -p nyash-llvm-compiler` (ny-llvmc builder)
- `LLVM_SYS_180_PREFIX=$(llvm-config-18 --prefix) cargo build --release --features llvm`
- Run via harness: `NYASH_LLVM_USE_HARNESS=1 ./target/release/nyash --backend llvm apps/APP/main.nyash`
- Quick VM run: `./target/release/nyash --backend vm apps/APP/main.nyash`
- Emit + link (LLVM): `tools/build_llvm.sh apps/APP/main.nyash -o app`
- Smokes: `./tools/llvm_smoke.sh release` (use env toggles like `NYASH_LLVM_VINVOKE_RET_SMOKE=1`)
## JIT SelfHost Quickstart (Phase 15)
- Core build (JIT): `cargo build --release --features cranelift-jit`
- Core smokes (plugins disabled): `NYASH_CLI_VERBOSE=1 ./tools/jit_smoke.sh`
- Roundtrip (parser pipe + json): `./tools/ny_roundtrip_smoke.sh`
- Plugins smoke (optional gate): `NYASH_SKIP_TOML_ENV=1 ./tools/smoke_plugins.sh`
- Using/Resolver E2E sample (optional): `./tools/using_e2e_smoke.sh` (requires `--enable-using`)
- Bootstrap c0→c1→c1' (optional gate): `./tools/bootstrap_selfhost_smoke.sh`
Flags
- `NYASH_DISABLE_PLUGINS=1`: Core経路安定化CI常時/デフォルト)
- `NYASH_LOAD_NY_PLUGINS=1`: `nyash.toml``ny_plugins` を読み込むstd Ny実装を有効化
- `--enable-using` or `NYASH_ENABLE_USING=1`: using/namespace を有効化
- `NYASH_SKIP_TOML_ENV=1`: nyash.toml の [env] 反映を抑止(任意ジョブの分離に)
- `NYASH_PLUGINS_STRICT=1`: プラグインsmokeでCore13厳格をONにする
- `NYASH_USE_NY_COMPILER=1`: NyコンパイラMVP経路を有効化Rust parserがフォールバック
## Phase 15 PolicySelfHosting 集中ガイド)
- フォーカス: Ny→MIR→VM/JITJITはcompileronly/独立実行)での自己ホスト実用化。
- スコープ外DoNotDo: AOT/リンク最適化、GUI/egui拡張、過剰な機能追加、広域リファクタ、最適化の深追い、新規依存追加。
- ガードレール:
- 小刻み: 作業は半日粒度。詰まったら撤退→Issue化→次タスクにスイッチ。
- 検証: 代表スモークRoundtrip/using/modules/JIT直/collectionsを常時維持。VMとJIT(--jit-direct)の一致が受け入れ基準。
- 観測: hostcall イベントは 1 呼び出し=1 件、短絡は分岐採用の記録のみ。ノイズ増は回避。
- LLVM/PHI: ハーネスでは「PHI は常にブロック先頭にグループ化」「incoming は型付き (i64 v, %bb)」の不変条件を厳守。PHI の生成・配線は `phi_wiring` に一元化する。
## LLVM Harness — PHI Invariants & Debug
- Invariants
- PHI nodes are created at the block head only (grouped at top).
- Incoming pairs are always well-typed: `i64 <value>, %bb<id>`.
- Placeholder PHIs are not materialized during prepasses; only metadata is recorded.
- Finalization (`phi_wiring.finalize_phis`) ensures creation and wiring; no empty PHI remains.
- Implementation notes
- Prepass metadata: `phi_wiring.tagging.setup_phi_placeholders` collects declared PHIs and records `block_phi_incomings`; it does not call `ensure_phi` anymore.
- Wiring: `phi_wiring.wiring.ensure_phi` places PHI at the block head; `wire_incomings` resolves per-pred values and normalizes to i64.
- Safety valve: `llvm_builder.compile_to_object` sanitizes IR text to drop malformed empty PHIs (should be unreachable in normal flow).
- How to run harness
- Build: `cargo build --release -p nyash-llvm-compiler && cargo build --release --features llvm`
- Run: `NYASH_LLVM_USE_HARNESS=1 ./target/release/nyash --backend llvm apps/tests/peek_expr_block.nyash`
- IR dump: `NYASH_LLVM_DUMP_IR=tmp/nyash_harness.ll ...`
- PHI trace: `NYASH_LLVM_TRACE_PHI=1 ...` (JSON lines output via `phi_wiring.common.trace`)
## Match Guards — Parser & Lowering Policy
- Syntax: `case <pattern> [if <cond>] => <expr|block>` within `match <expr> { ... }`.
- Patterns (MVP): literals (with `|`), type patterns like `StringBox(s)`.
- Semantics:
- Default `_` does not accept guards (parse error by design).
- Without type/guard: lowers to PeekExpr for legacy path.
- With type/guard: lowers to nested If-chain; guard is evaluated inside then-branch (after type bind for type patterns).
- Notes:
- is/as TypeOp mapping normalizes common Box names to primitives (e.g., `StringBox` → String) for parity across VM/JIT/LLVM.
- VM/PyVM may require bridging for primitive↔Box checks; keep guard tests for literal strict, type guard as warning until parity is complete.
- 3日スタートプラン:
1) JSON v0 短絡 &&/|| を JSON→MIR→VM→JIT の順で最小実装。短絡副作用なしを smoke で確認。
2) collections 最小 hostcalllen/get/set/push/size/hasと policy ガードの整合性チェック。
3) 観測イベントobserve::lower_hostcall / lower_shortcircuitを整備し、代表ケースで一貫した出力を確認。
## Coding Style & Naming Conventions
- Rust style (rustfmt defaults): 4space indent, `snake_case` for functions/vars, `CamelCase` for types.
- Keep patches focused; align with existing modules and file layout.
- New public APIs: document minimal usage and expected ABI (if exposed to NyRT/plugins).
## Testing Guidelines
- Rust tests: `cargo test` (add targeted unit tests near code).
- Smoke scripts validate endtoend AOT/JIT (`tools/llvm_smoke.sh`).
- Test naming: prefer `*_test.rs` for Rust and descriptive `.nyash` files under `apps/` or `tests/`.
- For LLVM tests, ensure LLVM 18 is installed and set `LLVM_SYS_180_PREFIX`.
## Commit & Pull Request Guidelines
- Commits: concise imperative subject; scope the change (e.g., "llvm: fix argc handling in nyrt").
- PRs must include: description, rationale, reproduction (if bug), and run instructions.
- Link issues (`docs/development/issues/*.md`) and reference affected scripts (e.g., `tools/llvm_smoke.sh`).
- CI: ensure smokes pass; use env toggles in the workflow as needed.
## Security & Configuration Tips
- Do not commit secrets. Plugin paths and native libs are configured via `nyash.toml`.
- LLVM builds require system LLVM 18; install via apt.llvm.org in CI.
- Optional logs: enable `NYASH_CLI_VERBOSE=1` for detailed emit diagnostics.
- LLVM harness safety valve (dev only): set `NYASH_LLVM_SANITIZE_EMPTY_PHI=1` to drop malformed empty PHI lines from IR before llvmlite parses it. Keep OFF for normal runs; use only to unblock bring-up when `finalize_phis` is being debugged.
## Codex Async Workflow (Background Jobs)
- Purpose: run Codex tasks in the background and notify a tmux session on completion.
- Script: `tools/codex-async-notify.sh`
- Defaults: posts to tmux session `codex` (override with env `CODEX_DEFAULT_SESSION` or 2nd arg); logs to `~/.codex-async-work/logs/`.
Usage
- Quick run (sync output on terminal):
- `./tools/codex-async-notify.sh "Your task here" [tmux_session]`
- Detached run (returns immediately):
- `CODEX_ASYNC_DETACH=1 ./tools/codex-async-notify.sh "Your task" codex`
- Tail lines in tmux notification (default 60):
- `CODEX_NOTIFY_TAIL=100 ./tools/codex-async-notify.sh "…" codex`
Concurrency Control
- Cap concurrent workers: set `CODEX_MAX_CONCURRENT=<N>` (0 or unset = unlimited).
- Mode when cap reached: `CODEX_CONCURRENCY_MODE=block|drop` (default `block`).
- Deduplicate same task string: `CODEX_DEDUP=1` to skip if identical task is running.
- Example (max 2, dedup, detached):
- `CODEX_MAX_CONCURRENT=2 CODEX_DEDUP=1 CODEX_ASYNC_DETACH=1 ./tools/codex-async-notify.sh "Refactor MIR 13" codex`
Keep Two Running
- Detect running Codex exec jobs precisely:
- Default counts by PGID to treat a task with multiple processes (node/codex) as one: `CODEX_COUNT_MODE=pgid`
- Raw process listing (debug): `pgrep -af 'codex.*exec'`
- Top up to 2 jobs example:
- `COUNT=$(pgrep -af 'codex.*exec' | wc -l || true); NEEDED=$((2-${COUNT:-0})); for i in $(seq 1 $NEEDED); do CODEX_ASYNC_DETACH=1 ./tools/codex-async-notify.sh "<task $i>" codex; done`
Notes
- tmux notification uses `paste-buffer` to avoid broken lines; increase tail with `CODEX_NOTIFY_TAIL` if you need more context.
- Avoid running concurrent tasks that edit the same file; partition by area to prevent conflicts.
- If wrappers spawn multiple processes per task (node/codex), set `CODEX_COUNT_MODE=pgid` (default) to count unique process groups rather than raw processes.