Files
hakorune/CURRENT_TASK.md
Moe Charm 11506cee3b Phase 11-12: LLVM backend initial, semantics layer, plugin unification
Major changes:
- LLVM backend initial implementation (compiler.rs, llvm mode)
- Semantics layer integration in interpreter (operators.rs)
- Phase 12 plugin architecture revision (3-layer system)
- Builtin box removal preparation
- MIR instruction set documentation (26→Core-15 migration)
- Cross-backend testing infrastructure
- Await/nowait syntax support

New features:
- LLVM AOT compilation support (--backend llvm)
- Semantics layer for interpreter→VM flow
- Tri-backend smoke tests
- Plugin-only registry mode

Bug fixes:
- Interpreter plugin box arithmetic operations
- Branch test returns incorrect values

Documentation:
- Phase 12 README.md updated with new plugin architecture
- Removed obsolete NYIR proposals
- Added LLVM test programs documentation

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-01 23:44:34 +09:00

754 lines
48 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.

# CURRENT TASK (Phase 11.7 kick-off: JIT Complete / Semantics Layer)
Phase 11.7 へ仕切り直し(会議合意)
- 単一意味論層: MIR→Semantics→{VM/Cranelift/LLVM/WASM} の設計に切替。VMは参照実装、実行/生成はCodegen側で一本化。
- フォールバック廃止: VM→JITの実行時フォールバックは行わない。JITは“コンパイル専用/AOT補助”に限定。
- 共通ABI: handle/i64/ptr 変換、to_bool/compare、タグ分類、invoke固定/可変、NyRTシム呼び出しを共通化。
- Cranelift: 軽量JIT/AOTパスを追加し、最小実装からMIR-15を段階的に緑化。LLVM AOT は併存。
Docs: docs/development/roadmap/phases/phase-11.7_jit_complete/{README.md, PLAN.md, CURRENT_TASK.md, MEETING_NOTES.md}
以降は下記の旧計画LLVM準備をアーカイブ参照。スモークやツールは必要箇所を段階で引継ぎ。
Update (2025-09-01 AM / JIT handoff follow-up)
- Cranelift 最小JITの下地は進捗良好LowerCore→CraneliftBuilder 経路)
- Compare/Branch/Jump、最小Phiblock params、StackSlotベースの Load/Store は実装済みbuilder.rs/core.rs
- ExternCall(env.console.log/println) の最小橋渡しConsoleBox.birth_h→by-id invokeを追加済み。
- 追加スモークjit-direct 用I/Oなし
- apps/tests/mir-store-load: x=1; y=2; x=x+y; return x → 3
- apps/tests/mir-phi-min: if(1<2){x=10}else{x=20}; return x 10
- apps/tests/mir-branch-multi: 入れ子条件分岐 1
- 実行例: `NYASH_JIT_THRESHOLD=1 ./target/release/nyash --jit-direct apps/tests/mir-store-load/main.nyash`
- jit-direct 分岐/PHI 根治進行中
- 現象: select/compare の実行時観測では cond=1/then=1/else=0 と正しいが最終結果が 0 に落ちるケースあり
- 統合JIT`--backend cranelift`は期待どおりLowerCore の意味論は正しくjit-direct のCFG/合流が疑わしい
- 主因仮説確度高: 関数共有の value_stack をブロック間で使い回し分岐/合流で返値取り違え
変更点犯人切り分けと根治のための構造改革ログ
- CraneliftBuilderjit-direct 経路
- 単一出口明示合流SSAへ切替途中段階完了段階へ移行中
- ret 合流ブロックを導入しBlockParam(i64) で戻り値を受け渡し
- すべての `emit_return` i64 正規化 `jump(ret, [val])`に統一return 命令は合流側だけ)。
- end_function 側で ret 合流ブロックに切替しBlockParam f64 変換必要時のうえ return
- Compare/Branch/Select まわり
- Compare 結果をローカルスロットへ保存Branch/Select 時に確実にロードスタック取りこぼし排除)。
- `br_if` 直前に cond b1 正規化i64b1)。
- デバッグ用 extern を登録必要時のみ
- `nyash.jit.dbg_i64(tag: i64, val: i64) -> i64`値観測用
- `nyash.jit.block_enter(idx: i64) -> void`ブロック入場ログ
- LowerCorereturn 値の堅牢化
- Return 値が known/param/slot 経路に乗らない場合同一ブロックの Const 定義をスキャンして materialize
- Fast-path読みやすさ単純化: then/else が定数 return の場合`select(cond, K_then, K_else)``emit_return` に縮約`NYASH_JIT_FASTPATH_SELECT=1` で強制)。
診断ログ必要時のみ ON
- `NYASH_JIT_TRACE_BLOCKS=1` ブロック入場ログ`[JIT-BLOCK] enter=<idx>`
- `NYASH_JIT_TRACE_BR=1` …… br_if cond 有無`[JIT-CLIF] br_if cond_present=...`
- `NYASH_JIT_TRACE_SEL=1` select cond/then/else tag=100/101/102
- `NYASH_JIT_TRACE_RET=1` return の値: emit_return 直前tag=201、ret 合流tag=200
再現実行コマンドjit-direct
- 分岐の最小: `apps/tests/mir-branch-ret/main.nyash`
- `NYASH_JIT_THRESHOLD=1 NYASH_JIT_DUMP=1 ./target/release/nyash --jit-direct apps/tests/mir-branch-ret/main.nyash`
- 診断ON: `NYASH_JIT_THRESHOLD=1 NYASH_JIT_DUMP=1 NYASH_JIT_TRACE_RET=1 NYASH_JIT_TRACE_BLOCKS=1 ./target/release/nyash --jit-direct apps/tests/mir-branch-ret/main.nyash`
- PHI最小: `apps/tests/mir-phi-min/main.nyash`
- 複合分岐: `apps/tests/mir-branch-multi/main.nyash`
期待と現状2025-09-01 PM 時点
- 統合JIT`--backend cranelift`: OK`mir-branch-ret`1)。
- jit-direct: 単一出口BlockParam 合流の配線で安定化を確認cond/then/else も正常)。tag=201/200 は一致
検証結果jit-direct / 2025-09-01 実行
- `apps/tests/mir-branch-ret`: Result=1, [JIT-DBG] 201=1 / 200=1
- `apps/tests/mir-phi-min`: Result=10, [JIT-DBG] 201=10 / 200=10
- `apps/tests/mir-branch-multi`: Result=1, [JIT-DBG] 201=1 / 200=1
- `apps/tests/mir-nested-branch`: Result=1, [JIT-DBG] 201=1 / 200=1
- `apps/tests/mir-phi-two`: Result=50
次のタスク仕上げ
1) LowerCore fastpath/select のガード整理`NYASH_JIT_FASTPATH_SELECT` の簡素化)。
2) b1 返り値 ABI を有効化する場合の経路確認feature `jit-b1-abi`)。
3) ドキュメント整備CraneliftBuilder 単一出口方針と TRACE 変数の最終化)。
Update (2025-09-01 PM2 / Interpreter parity blockers)
- 目的: Semantics 層での VM/JIT/Interpreter パリティ検証に向けInterpreter 側の既知不具合を記録引き継ぎ
- 再現ファイルユーザー提供
- examples/semantics_test_branch.nyash
- 期待: 100
- 実際(Interpreter): IntegerBox(4)変数IDが返る挙動
- 実際(VM): 100
- examples/simple_test.nyash
- 事象: PluginBoxV2 同士の加算でエラーIntegerBoxダウンキャストのみを試行して失敗
- /tmp/test_string_concat.nyash
- 事象: 文字列連結でエラーPluginBox String の連結が不可
- 現状の暫定対応実装済み
- Await(JIT): I::Await nyash.future.await_h に降下同期get
- Safepoint(JIT): I::Safepoint nyash.rt.checkpoint に降下global_hooks 経由で GC/scheduler 連携
- Barrier(JIT): Array.set/Map.set nyash.gc.barrier_write emit
- Interpreter: FutureBox を登録new FutureBox(42)
- Interpreter: 加算まわりのフォールバック強化
- 文字列likeの優先連結toUtf8/Result.Ok含む
- 数値文字列整数にパースできる場合は加算
- 未解決最優先
1) 返り値が変数IDになるexamples/semantics_test_branch.nyash
- 調査方針: execute_statement(Return)→execute_function_call の伝播経路Variable 解決/共有の箇所を追跡しBox 値ではなく内部ID/インデックスを返している箇所を特定修正
- 対応: Return 直前と関数エピローグでの実値/型ログ限定ログを差し込み最小修正
2) PluginBox 同士の演算の包括対応
- 暫定は toString数値/文字列へ正規化で回避恒久対応は Semantics/VM と同じ規約handle-first + 文字列like/数値likeに寄せる
3) 文字列連結の広範囲対応
- toString()/toUtf8/Result.Ok の内包を最優先で文字列正規化現状の強化で多くは通る追加ケースが出れば順次取り込み)。
- 次アクションInterpreter fix plan
- [ ] semantics_test_branch 再現Return 値の実体化ルート修正
- [ ] simple_test の演算パスを toString 正規化で網羅必要なら算術 toNumber
- [ ] test_string_concat の失敗パターン収集 try_box_to_string の対象拡張
- [ ] SemanticsVM/ClifAdapter パリティ小スモーク追加分岐/配列/extern/await
開発メモ / 注意点
- 分岐の取り違えはブロックまたぎの共有スタックが原因になりがち根治策として BlockParam 経由の合流単一出口 return を徹底
- デバッグログは 必要時のみ ON の方針で仕込む収束後に不要箇所は落とす本番は静かに)。
チェックリスト収束条件
- [ ] jit-direct: `mir-branch-ret` 1tag=201/200 とも 1
- [ ] jit-direct: `mir-phi-min` 10合流経路で BlockParam 値が正しい
- [ ] jit-direct: `mir-branch-multi` 1ネスト分岐でも合流が正しい
- [ ] 統合JIT--backend craneliftと一致
- [ ] ログ一時コードの整理必要なものだけ残す
- 既知の注意jit-direct 経路のみ
- 条件分岐系Branch/Jumpで戻り値が 0 になる事象を確認`--backend cranelift`統合経路では期待値どおり例: mir-branch-ret 1)。
- 影響範囲: jit-direct 実験フラグのみLowerCore/CraneliftBuilder IR 自体は生成されており統合経路では正しく実行される
- 次回対応: brif 直後のブロック制御/シール順の見直しentry/sealing)、条件値スタック消費タイミングの再点検
Update (2025-09-01 night / JIT-direct branch/PHI fix)
- Summary
- Fixed jit-direct returning 0 for branches by unifying returns to a single-exit ret block and improving MIR return type inference (including PHI-based inference).
- Stabilized PHI joins by materializing PHI results into locals and preferring local loads for Return.
- Corrected stack order for `br_if_with_args` (pop else args then args cond), matching LowerCore push order; added minimal fallback when predecessor mapping is unavailable.
- Added debug symbols and logs (gated by env) for ret path and CFG wiring.
- Code touched
- MIR: `src/mir/builder.rs` (return type inference incl. PHI inputs)
- Lowering core: `src/jit/lower/core.rs` (PHI materialize to local; arg wiring fallback; small traces)
- Builder (Cranelift): `src/jit/lower/builder.rs` (single-exit return; br_if/jump args order; debug symbol registrations)
- New smokes
- `apps/tests/mir-phi-two` merge two locals (x,y) then add
- `apps/tests/mir-nested-branch` nested branches returning constants
- Status (jit-direct)
- mir-branch-ret 1
- mir-phi-min 10
- mir-phi-two OK合流加算
- mir-nested-branch 1
- LLVM AOT snips (prebuilt binaries) still OK for VInvoke samples.
- How to run
- `NYASH_JIT_THRESHOLD=1 ./target/release/nyash --jit-direct apps/tests/mir-branch-ret/main.nyash`
- `NYASH_JIT_THRESHOLD=1 ./target/release/nyash --jit-direct apps/tests/mir-phi-min/main.nyash`
- `NYASH_JIT_THRESHOLD=1 ./target/release/nyash --jit-direct apps/tests/mir-phi-two/main.nyash`
- `NYASH_JIT_THRESHOLD=1 ./target/release/nyash --jit-direct apps/tests/mir-nested-branch/main.nyash`
- Optional logs: `NYASH_JIT_DUMP=1` and/or `NYASH_JIT_TRACE_RET=1`
- Next (small boxes; avoid saturation)
1) Fast-path(select) 1-hop extension only:
- If then/else each jump to a block that immediately returns a Const Integer, lower to `select(cond, K_then, K_else) → return`.
- Keep scope narrow to avoid regressions.
2) Multi-PHI (limited):
- Add one smoke with two PHI slots; confirm arg counts/ordering under `phi_min`.
3) Logging remains env-gated; no default noise. No broad refactors until the above are green.
# (以下、旧タスク: Phase 10.8 記録)
Contributor note: 開発手順レイアウトPR要件はリポジトリルートの `AGENTS.md`Repository Guidelines参照ビルド/テストやCIスモークの環境変数も簡潔にまとまっています
## Handoff (Phase 11 next): 実行確認プランtests/ は対象外)
目的: apps 配下の簡単なアプリから順にVM AOT(LLVM) の順で確実に動作させるtests/ フォルダは除外
前提/共通
- LLVM: `LLVM_SYS_180_PREFIX=$(llvm-config-18 --prefix)` を付与してビルド
- AOTリンク: `tools/build_llvm.sh <app.nyash> -o app` を使用`target/aot_objects/*.o` 固定
- Verbose: トラブル時は `NYASH_CLI_VERBOSE=1`
- プラグインテスター: `tools/plugin-tester` を利用可`cargo run --release -- check --config ../../nyash.toml --library <lib>`
推奨テスト順簡単段階的
1) apps/ny-array-llvm-ret/main.nyashArray push/get 戻り値
- 期待: `Result: 3`
- VM: `./target/release/nyash --backend vm apps/ny-array-llvm-ret/main.nyash`
- AOT: `tools/build_llvm.sh apps/ny-array-llvm-ret/main.nyash -o app && ./app`
2) apps/ny-vinvoke-llvm-ret-size/main.nyashby-id size
- 期待: `Result: 1`
- VM/AOT 同上
3) apps/ny-vinvoke-llvm-ret/main.nyashby-id get 可変長経路
- 期待: `Result: 42`
- VM/AOT 同上
4) apps/ny-echo-lite/main.nyashreadLine print 最小エコー
- 期待: 出力に `Result:` 行が含まれるllvm_smoke の基準
- 実行例: `echo hello | ./target/release/nyash --backend vm apps/ny-echo-lite/main.nyash`
- AOT: `tools/build_llvm.sh apps/ny-echo-lite/main.nyash -o app_echo && echo hello | ./app_echo`
5) apps/ny-llvm-smoke/main.nyashArray get/set/print
- 期待: `Result: 3`
- 備考: 文字列連結は NyRT concat シムへフォールバック済みemit 検知が不安定な場合は再試行問題が残る場合はこの項を後回し可
6) apps/ny-echo/main.nyashオプション付きエコー
- 期待: VM/JIT/AOT の出力一致upper/lower/そのまま
7) apps/ny-map-llvm-smoke/main.nyashMap by-id 経路
- 期待: 行に `Map: v=42` `size=1`
- 備考: 連結シム適用済み必要なら `NYASH_LLVM_ALLOW_BY_NAME=1` で一時回避
トラブルシュート要点
- AOT emit: `NYASH_LLVM_OBJ_OUT=$PWD/target/aot_objects/<name>.o ./target/release/nyash --backend llvm ...`
- リンク: `NYASH_LLVM_SKIP_EMIT=1 NYASH_LLVM_OBJ_OUT=... tools/build_llvm.sh ...`
- プラグイン: `nyash.toml` のパス解決拡張子はOSで異なる)。tester は拡張子補完に対応
Update (2025-08-31 AM / Phase 11.1 quick pass)
Update (2025-08-31 PM / Phase 11.2 partial)
- 方式ALLVM専用 NyRT 静的ライブラリで前進by-id を本線by-name はデバッグ用ラッパ方針
- Lowering 更新
- NewBox引数あり 12個)→ `nyash.box.birth_i64(type_id, argc, a1, a2)`int/handle ptr の最小対応)。0引数は `birth_h`
- BoxCallby-id, method_idあり)→ `nyash_plugin_invoke3_i64(type_id, method_id, argc, a0, a1, a2)` 接続a0=receiver handle
- 戻り: dstが整数/真偽ならi64のままBox/String/Array等は i64(handle)→i8*(ptr)
- ArrayBox.get/set は既存の `nyash_array_get_h/set_h` 安全パスを存続
- 生成関数名: `ny_main` に変更NyRTの起動ルーチンから呼び出し
- NyRT(libnyrt.a) 追加シンボル
- `nyash_string_new(i8*, i32)->i8*`Const String用
- `nyash_array_get_h(i64,i64)->i64`, `nyash_array_set_h(i64,i64,i64)->i64`
- 既存の `nyash.box.birth_h/i64`, `nyash.rt.checkpoint`, `nyash.gc.barrier_write` などは維持
- ツール
- `tools/build_llvm.sh` 追加.o libnyrt.a リンク EXE
- `tools/llvm_smoke.sh`.o生成のスモーク
- スモーク
- `examples/llvm11_core_smoke.nyash` EXE 実行し `Result: 3` を確認
Update (2025-08-31 PM2 / Phase 11.2 lightweight LLVM)
- 方針拡張性優先 / コア最小化: Tier0
- ExternCall: 環境/I/Oのみenv.console/debug/runtime など)。print ExternCall(env.console.log) 本線
- BoxCall: データ構造/Box 操作Array/Map/String/Instance )。AOT/LLVM は最小の安全シムのみ直結
- コアに残す安全シムNyRT: Array(get/set/push/length), Instance(getField/setField)。Map はコアに足さない後述)。
- Map/JSON/Math 等は当面コア外必要時はプラグイン byid + 汎用シムでAOTを通す)。
- 実装反映
- MIR パス: `passes/method_id_inject` 追加NewBox/Copy 由来の型から BoxCall method_id 注入PluginInvoke は可能なら BoxCall(byid)へ書換)。
- LLVM Lowering:
- ExternCall: `env.console.log` `nyash.console.log`NyRT, `env.debug.trace` `nyash.debug.trace`
- ExternCall: `env.console.readLine` 追加 `nyash.console.readline`stdin 1行, CR/LF 除去, C文字列返却)。
- ArrayBox: `get/set/push/length` NyRT 安全シム`nyash_array_get_h/set_h/push_h/length_h`に直結
- Instance: `getField/setField` NyRT 安全シム`nyash.instance.get_field_h/set_field_h`に直結既存)。
- プラグイン byid: f64 戻りの選択`nyash_plugin_invoke3_f64`/ i64 戻り`..._i64`)。先頭2引数はタグ付けint/float/handle対応`..._tagged_i64`)。
- byname 薄フォールバックデバッグ用: `NYASH_LLVM_ALLOW_BY_NAME=1` 下で `nyash.plugin.invoke_by_name_i64` を使用
- NyRT(libnyrt.a): 上記 API を追加console.log/debug.trace/readline, array push/length, instance get/set_field, byname, tagged_i64)。
- オブジェクト出力: `NYASH_LLVM_OBJ_OUT=<path>` .o を明示出力`runner/modes/llvm.rs` 経由)。
- ツール更新: `tools/build_llvm.sh` / `tools/llvm_smoke.sh` `NYASH_LLVM_OBJ_OUT` を使用して .o を取得後NyRT とリンク
- サンプル: `apps/ny-llvm-smoke/main.nyash`Array get/set/print)、`apps/ny-echo-lite/main.nyash`readLineprint)。
- しないこと / 後回し
- Map のコア安全シム追加`nyash_map_*_h`は見送り必要ならプラグイン byid + 汎用シムでAOT実行
- ConsoleBox の高度機能は ExternCall 側で段階導入出力は既存 log入力は readline のみ)。
- 汎用可変長引数>2は後段タグ付けの拡張で対応予定
- 次にやること(短期)
- ny-echo を縮小AOT対応console.readLine + print のみで OK 版)。
- Mapプラグイン最小版で string-key の get/set/size を byid 汎用シム経由でAOT実行コアは増やさない
- CI/スモーク: `.o→EXE→実行``apps/ny-llvm-smoke` / `apps/ny-echo-lite` で追加。
- ガードレール: コア安全シムを Tier0 以外に増やさない簡易チェックgrep ベース)導入検討。
- How to Build / RunAOT/LLVM
- ビルド: `LLVM_SYS_180_PREFIX=$(llvm-config-18 --prefix) cargo build --release --features llvm`
- .o→EXE: `tools/build_llvm.sh <file.nyash> -o app_llvm``./app_llvm`
- .o のみ: `NYASH_LLVM_OBJ_OUT=$PWD/nyash_llvm_temp.o ./target/release/nyash --backend llvm <file.nyash>`
- 推奨 @envmain.nyash 冒頭コメント):
- `// @env NYASH_CLI_VERBOSE=1`(詳細ログ)
- デバッグ時のみ `// @env NYASH_LLVM_ALLOW_BY_NAME=1`
Update (2025-08-31 PM3 / LLVM VInvoke triage)
- 直近のテスト結果(要約)
- VM backend正常
- MapBox.size(): Result: 1 ✅
- MapBox.get(1): Result: 42 ✅
- 可変長VInvoke: get(1,9,8,7,6): 期待どおりにTLV I64(tag=3)でエンコードされ、出力確認済 ✅
- LLVM backend要修正
- MapBox birth は成功instance_id=1
- set()/get() 呼び出し経路で戻り値が Result: 0期待は 42
- LLVM 実行時に VM 相当の PluginLoaderV2 Invoke 詳細ログが出ず、by-id/可変長の値流しに不整合がある可能性
- 実装・修正状況
- ランタイムNyRT
- by-id 固定長/可変長の argc を「レシーバ除外の実引数個数」に統一済み
- invoke 時の type_id を「レシーバ実体PluginBoxV2から取得した実 type_id」に変更呼び出し先揺れを排除
- LLVM Lowering
- <=4 引数: nyash_plugin_invoke3_tagged_i64f64→i64ビット化タグ付与
- >=5 引数: nyash.plugin.invoke_tagged_v_i64vals/tags の vector 経路)
- スモーク
- apps/ny-vinvoke-llvm-ret: 戻り値で 42 を検証する LLVM 用スモークを追加print/concatに依存しない
- tools/llvm_smoke.sh に VInvoke戻り値スモークをオプション追加NYASH_LLVM_VINVOKE_RET_SMOKE=1
- いま見えている課題LLVM
- by-id vector 経路vals/tags/argcのどこかで齟齬 → get が 0 を返す(キーが TLV 化されていない/タグずれなど)
- 固定長(<=4経路は未切り分け → まず size()/get(1) を LLVM 戻り値で確定size→1, get(1)→42
- .o 出力の一部環境不安定は Runner/Lowering にフォールバックを追加済write_to_memory_buffer
- 次アクション
1) LLVM 戻り値テストを段階確認
- MapBox.size() → Result: 1
- MapBox.get(1) → Result: 42
- これで固定長 by-id の健全性を確定後、可変長(>=5vector 経路へ絞り込み
2) NyRT デバッグNYASH_CLI_VERBOSE=1 時のみ)を最小追加
- nyash.plugin.invoke_tagged_v_i64: argc/method_id、vals[0..2], tags[0..2] を stderr に出力
- 実際のTLV化の前に観測し、ズレ箇所を確定
3) LLVM Loweringvector 経路)の配列構築を点検
- alloca([N x i64]) → inbounds GEP → store → i64* へ pointer_cast → 呼び出し
- GEP index[0,i]/型一致/メモリ幅を再確認
4) 必要なら一時的に「<=4 でも vector 経路を選択」する実験分岐を作り、経路差異を切り分け
5) tools/llvm_smoke.sh: target/aot_objects 固定・事前 emit → link のフローをデフォルト強化CI安定化
- ゴール(本フェーズ収束条件)
- LLVM backend で MapBox: size()/get(1)/get(1,9,8,7,6) が戻り値ベースで一致
- VInvoke可変長経路が by-id で安定
- print/concat のLoweringは後続必要最小に回す
- タスク実行MVP
- `nyash.toml``[env]` / `[tasks]` を記述し、CLIから `--run-task <name>` で実行可能。
- 例:
- `[tasks] build_llvm = "LLVM_SYS_180_PREFIX=$(llvm-config-18 --prefix) cargo build --release --features llvm"`
- 実行: `./target/release/nyash --run-task build_llvm`
- 備考: `{root}` 変数展開対応。OS別/依存/並列は未対応(将来拡張)。
残作業(合意順)
1) method_id 埋め込みと by-id 本線化
- ロード時に 名前→id を確定・キャッシュPluginLoaderV2し、MIR へ `method_id` 注入(実行時は常に by-id
2) BoxCall 汎用拡張
- 引数3個以上/戻り型の拡張i64/handle/f64 等。Field 系getField/setFieldを BoxCall として安全パス接続
3) by-name ラッパ(デバッグ/テスト用)
- Lowering フォールバックとして薄く導入env/flag 下でのみ使用)、本番は by-id 固定
4) ExternCall 網羅
- `env.console/debug/runtime/future` 等を puts 暫定から RT関数に置換、署名整備
5) スモーク/CI 拡張
- by-id の代表例CounterBox等、console/array/field/extern を .o→EXE→起動まで
- LLVM Lowering: Phi/Load/Store の最小実装を追加inkwell 0.5 / LLVM 18
- Phi: 事前に各BB先頭でPhiード生成→Branch/Jump時にincomingを配線
- Load/Store: entryでのalloca管理型は注釈/値から推定。i1/i64の簡易変換、ポインタはpointer_cast対応
- 型なしポインタopaque対応のため、`alloca`の要素型を別マップで追跡
- ビルド検証: `LLVM_SYS_180_PREFIX=$(llvm-config-18 --prefix) cargo build --features llvm` 成功
- 既存のConst/Unary/BinOp/Compare/Branch/Jump/Return と併せ、Phase 11.1の目標範囲は到達
---
一時メモMIRインタプリタ 80/20 方針)
- ConsoleBox.readLine ローカルフォールバック標準入力1行読みを一時実装`--backend mir` の echo-lite 用)。
- 後で必ず削除し、プラグイン側メソッド/Extern 経由に置換すること。
- 追跡タスク: 「ConsoleBox メソッド群の正式実装PluginInvoke/ExternCallとローカルフォールバックの撤去」。
- 影響箇所: `src/backend/mir_interpreter.rs`BoxCall: ConsoleBox.readLine 分岐)、`apps/tests/ny-echo-lite` スモーク。
次アクション(この項に紐づく)
- ClifSem 最小LoweringConst/Return/Addを実装し、JITスケルトンの0終了スモークを追加。
- ConsoleBox フォールバックは温存のままecho-liteのみのため。Console 正式化のタイミングで除去。
---
# Handoff (Phase 11.7) — MIR Interpreter + Cranelift Minimal JIT
目的: LLVMが重くなったため仕切り直し。新しいMIR解釈層と軽量Cranelift JITの最小機能を整備し、段階拡張しやすい骨格を確立。
実装済み(要点)
- 共通ABI/ユーティリティ:
- `src/backend/abi_util.rs`to_bool/eq/tag/handle
- MIRインタプリタ--backend mir:
- 対応: Const/Unary/BinOp(String結合)/Compare/Load/Store/Copy/Branch/Jump/Return/Print/Debug/Barrier/Safepoint(no-op)
- NewBox/PluginInvoke/BoxCall/ExternCallの最小対応PluginBoxV2はプラグインホスト経由
- ConsoleBox.readLine: 一時フォールバックで標準入力1行読みCURRENT_TASKに削除タスク記載済
- Cranelift最小JIT--backend cranelift:
- 実JITjit.rs: Const(i64/f64/bool->0/void->0)/Add/Sub/Mul/Div/Mod、Compare(Eq/Ne/Lt/Le/Gt/Ge)、Load/StoreStackSlot、Copy、Return/Jump/Branch
- 箱化: `src/backend/cranelift/context.rs` に ClifContext/BlockMap/ValueEnv を用意JIT構築をカプセル化
- LowerCore→ClifBuilderIRBuilder実体: 録画→実IR生成Const/Add/Returnを暫定実装
- 起動切替: `NYASH_JIT_LOWERCORE=1` で LowerCore→ClifBuilder 実IR経路を実行
- スモーク:
- `apps/tests/mir-const-add/main.nyash`0終了
- `apps/tests/mir-branch-ret/main.nyash`条件分岐で1
- どちらも --backend cranelift / --backend mir で確認済
使い方(コマンド)
- Cranelift有効ビルド: `cargo build --features cranelift-jit`
- MIRインタプリタ: `./target/debug/nyash --backend mir apps/tests/mir-const-add/main.nyash`
- Cranelift最小JIT: `./target/debug/nyash --backend cranelift apps/tests/mir-branch-ret/main.nyash`
- LowerCore→ClifBuilder 実IR: `NYASH_JIT_LOWERCORE=1 ./target/debug/nyash --backend cranelift apps/tests/mir-const-add/main.nyash`
次のタスク(推奨順)
1) ClifBuilder 実IR生成の拡張LowerCore連携
- Compare/Branch/Jump の実IR
- 最小PhiBlock Params
- StackSlotベースのLoad/StoreValueEnvから完全移行
2) ExternCallenv.console.log最小対応JIT経路でもprintln相当へ
3) スモーク追加: Load/Store、Phi最小ケース、Compare/Branch複合ケース
4) Console/Extern 正式化完了後に ConsoleBox.readLine フォールバック削除(本ファイルにタスク済)
5) 警告/CFG整理: 使っていないfeature cfgやunusedを段階的に整理
既知の注意/制限80/20の割り切り
- BoolはI64の0/1として扱っており、B1専用ABIは未導入将来拡張
- String/Null/Void のConstは暫定的に0へ丸め必要箇所から段階的に正規化
- `jit-b1-abi` 等のunexpected cfg警告は今後整理対象。
関連ファイル
- 追加: `src/backend/abi_util.rs`, `src/backend/mir_interpreter.rs`, `src/runner/modes/mir_interpreter.rs`
- 追加: `apps/tests/mir-const-add/main.nyash`, `apps/tests/mir-branch-ret/main.nyash`
- Cranelift: `src/backend/cranelift/jit.rs`, `src/backend/cranelift/context.rs`, `src/backend/cranelift/builder.rs`
- Semantics: `src/jit/semantics/{mod.rs,clif.rs}`(スケルトン)
メモ/トグル
- LowerCore→ClifBuilder 実IR: `NYASH_JIT_LOWERCORE=1`
- カバレッジログ: `NYASH_JIT_DUMP=1`
Handoff Snapshot (2025-08-31 / Phase 11 kick-off)
- Core-15 凍結(第三案 / Box-SSA
- セット: { Const, UnaryOp, BinOp, Compare, TypeOp, Load, Store, Jump, Branch, Return, Phi, Call, NewBox, BoxCall, ExternCall }
- Optimizer: ArrayGet/ArraySet/RefGet/RefSet/PluginInvoke → BoxCall に正規化get/set/getField/setField
- Verifier: 上記レガシー命令を UnsupportedLegacyInstruction としてエラー化(環境で一時解除可: NYASH_VERIFY_ALLOW_LEGACY=1
- VM: BoxCall("getField"/"setField") を InstanceBox に配線fieldsへ委譲。Arrayの get/set は既存BoxCall経路で動作
- 命令数固定テスト: Core15第三案へ切替済tests/mir_instruction_set_sync.rs
- LLVM 導入Phase 11 開始)
- 依存: LLVM 18 + inkwell 0.5.0features=["llvm18-0"]。feature `llvm` で有効化
- ビルド要件: LLVM_SYS_180_PREFIX例: /usr/lib/llvm-18, 追加依存: polly, zstdlibzstd-dev 等)
- 現状のLowering11.1の最小スケルトン → 11.2 反映):
- 対応: Const(Integer/Float/Bool/String/Null), Unary(Neg/Not/BitNot), BinOp整数/浮動の主要演算), Compare, Branch/Jump, Return
- 追加: Phi/Load/Store最小実装
- 追加: NewBox引数なし→nyash.box.birth_hへ; nyash.tomlの[box_types]からtype_id解決
- 追加: BoxCallArrayBox.get/set→nyash_array_get_h/set_h 経由の安全パス)
- 追加: ExternCallenv.console.log/env.debug.trace→libc putsで暫定出力
- 未対応(次タスク): NewBox引数あり, 一般BoxCallby-name/slot 汎用化), その他ExternCall
- エントリ: Main.main のみ対象に .o 出力backend::llvm::compile_to_object
- ドキュメント更新phase11
- README.md: 進行中に更新 / 4週スプリント計画11.1→11.4
- MIR_TO_LLVM_CONVERSION_PLAN.md: PluginInvoke→BoxCall統一、配列はBoxCallとして安全パス→型特化の二段階Lowering
- MIR_ANNOTATION_SYSTEM.md: setField/getFieldBoxCall前提に更新
- INSTRUCTION_SET.md: PluginInvokeはDeprecatedBoxCallに統一
How to Build/Run (recap)
- 通常/JIT: `cargo build --release --features cranelift-jit`
- LLVMAOTスケルトン:
- 事前: LLVM 18 / inkwell 0.5.0, polly, zstd を導入
- 例: `LLVM_SYS_180_PREFIX=$(llvm-config-18 --prefix) cargo build --release --features llvm`
- スモーク: `tools/mir15_smoke.sh release`
Next Steps (Phase 11)
1) 11.1 仕上げ(本タスク)
- Phi のLoweringBB事前作成→incoming追加
- Load/Storealloca/ローカル表現の最小規約、整数/浮動/ポインタ)
2) 11.2 安全パスBox/Extern
- [実装] NewBox(引数なし)→ `nyash.box.birth_h(type_id:i64)->i64` を呼び、i8*にinttoptrtype_idはnyash.tomlから解決
- [実装] Arrayの BoxCall("get"/"set") → `nyash_array_get_h/set_h`ハンドルi64渡し
- [実装] ExternCall: `env.console.log`/`env.debug.trace` は暫定で `puts` に接続AOTデバッグ用
- [残] BoxCall 汎用by-name/slot, Field系getField/setField, ExternCallの網羅
3) 11.3 最適化導線
- 注釈inline/purity/gc/alias→ LLVM属性/メタデータ
- 型特化: Array/Field の inline GEP + write barrier
4) 11.4 高度化
- 脱箱化、TBAA、PGO/ThinLTO
メモ
- Verifier の緩和スイッチ: `NYASH_VERIFY_ALLOW_LEGACY=1`移行用。通常はOFFで運用。
- Optimizer のRewrite はLLVM前提のBoxCall統一規約と整合済み。
最優先: MIR命令セットをCore-15に統一し、VM/JIT/AOTを整えてからLLVM(inkwell)へ移行する。
目的: MIR→VM→JIT→AOT の汎用化・単純化を一気に進める。命令の重複・メタ・実装露出を撤去/統合し、Builderが実際に発行するコア命令を最小化する。
現状観測2025-08-31
- 実装定義: 37命令src/mir/instruction.rs
- Docs: Canonical 26移行注記・Core-15ターゲット追記済
- Builder使用: 24命令自動集計
- 上位頻度: Const(19), TypeOp(13), Jump(6), ExternCall(5), Return(3), Call(3)
- 中頻度: NewBox(2), WeakRef(2), Barrier(2), BoxCall(1), Branch(1), Phi(1), PluginInvoke(1), Await(1)
- JITサポート: 約20命令ホストコール分は外部委譲で簡素
統合方針Core-15
- 重複統合
- TypeCheck, Cast → TypeOp に完全統合Builder 既に主に TypeOp を発行)
- WeakNew, WeakLoad → WeakRef に統合
- BarrierRead, BarrierWrite → Barrier に統合
- Box哲学へ移譲
- Print → env.console.log (ExternCall)Builder更新済
- Debug → DebugBox.trace()/env.debug.traceExternCall/BoxCall
- Throw, Catch → ExceptionBoxthrow/catch相当のBox APIへ移譲; 移行期はRewrite
- Safepoint → RuntimeBox.checkpointExternCall
- 未使用/メタ
- FutureSet → 一旦廃止Builder未使用
- Copy, Nop → メタ命令Optim/降格専用; Coreからは除外
最終ターゲット: Core-15 命令
- 基本演算(5): Const, UnaryOp, BinOp, Compare, TypeOp
- メモリ(2): Load, Store
- 制御(4): Branch, Jump, Return, Phi
- Box(3): NewBox, BoxCall, PluginInvoke
- 配列(2): ArrayGet, ArraySet
- 外部(1): ExternCall暫定; 将来はBox化でも可
進め方Core-15確定 → LLVM
1) Builder発行の一元化非破壊
- 既に Print→ExternCall 置換済み
- Builderが TypeCheck/Cast/WeakNew/WeakLoad/BarrierRead/BarrierWrite を発行しないよう整理(既存箇所の差し替え)
- 既存テストbuilder/optimizerを ExternCall/TypeOp/WeakRef/Barrier に合わせて更新
2) 互換Rewriteパスの追加MIR最適化フェーズ
- 古いMIR手書き/スナップショット/ツール)が生成した命令をコア命令に機械的変換
- TypeCheck/Cast → TypeOp
- WeakNew/WeakLoad → WeakRef
- BarrierRead/Write → Barrier
- Print → ExternCall(env.console.log)
- Debug → ExternCall(env.debug.trace)
- Throw/Catch → ExternCall(env.exception.*) もしくは BoxCall(ExceptionBox)
- Safepoint → ExternCall(env.runtime.checkpoint)
3) VM/JITの段階撤去と整理
- VM/JIT: コア命令に集中(ホストコール/Box経由のI/Oや例外
4) Docs/CI
- INSTRUCTION_SET をCore-15へ更新26→15マッピング表
- 命令数固定テストを「15」に切替
タスク分解(本フェーズ)
- [x] Builderからのレガシー発行のデフォルト停止WeakNew/WeakLoad/BarrierRead/Writeを統一命令に切替、トグルで復活可
- [x] MIR Rewriteパス追加一部完了: Print/Type/Weak/Barrier、Debug/Safepointはトグル
- [ ] Optimizer/Verifier/Printerの非互換の見直しVerifierでレガシー命令をエラー化
- [ ] VM: レガシー命令のコードパスに警告ログ(将来削除フラグ)
- [ ] JIT: コア命令に合わせたテーブル整理(未使用ホストコールの棚卸し)
- [ ] Docs更新命令セット、移行ガイド、Box哲学との整合
- [ ] 回帰テスト更新builder_modularizedを含む一式
追加の即応ステップ10.8a
- [x] Rewrite: Print → ExternCall(env.console.log)
- [x] Rewrite: TypeCheck/Cast → TypeOp、WeakNew/WeakLoad → WeakRef、BarrierRead/Write → Barrier
- [x] Rewrite(トグル): Debug → ExternCall(env.debug.trace)NYASH_REWRITE_DEBUG=1
- [x] Rewrite(トグル): Safepoint → ExternCall(env.runtime.checkpoint)NYASH_REWRITE_SAFEPOINT=1
- [x] Builder: Try/Catch/Throw/Safepoint の直接発行を抑止(トグル導入・モジュール化系にも適用)
- [x] Runtime: extern_call スタブ追加env.runtime.checkpoint, env.debug.trace
- [x] Rewrite(トグル・スキャフォールド): FutureNew/FutureSet/Await → ExternCall(env.future.*) 変換NYASH_REWRITE_FUTURE=1
引き継ぎ2025-08-31 深夜)
サマリ
- JIT予約シンボル: `nyash.rt.checkpoint`, `nyash.gc.barrier_write` を確保AOT/JITの双方で登録
- Future/Await Rewrite: `NYASH_REWRITE_FUTURE=1` で ExternCall(env.future.*) に段階導入runtime最小実装あり
- Builderレガシー停止: Weak/Barrier 系の直接発行を既定で無効化(統一命令に集約、必要時トグル)
- JIT-direct安定化: entry seal/戻り値制御/シム登録/コード寿命を調整し落ち着かせ済み
- 次の着手順: MIR15のVM/JITカバレッジ拡張 → LLVM(inkwell) 移行
- 完了/修正
- JIT/AOT 予約シンボルの登録完了(`nyash.rt.checkpoint`, `nyash.gc.barrier_write`
- JITスタブ実装no-opトレースとAOT(nyrt)エクスポートを追加
- Future/Await Rewriteのスキャフォールド`NYASH_REWRITE_FUTURE=1` runtime側`env.future.*`最小実装
- Builderレガシー停止を既定化WeakNew/WeakLoad/BarrierRead/Write→統一命令。必要時はトグルで復活
- `NYASH_BUILDER_LEGACY_WEAK=1`, `NYASH_BUILDER_LEGACY_BARRIER=1`
- JIT directの安定化segfault修正
- エントリblockのseal遅延PHI/引数受け用)
- MIRシグネチャに基づく戻り値有無Void関数はret無し/void呼び出し
- `nyash.console.birth_h` のJIT内シム追加JITBuilder登録
- finalize済みコードの寿命延長JITModuleをリークして新モジュールに差し替え
- カバレッジ確認MIR15→VM/JIT
- 追加ドキュメント: docs/reference/mir/MIR15_COVERAGE_CHECKLIST.md
- スモークスクリプト: tools/mir15_smoke.sh実行例: `cargo build --release --features cranelift-jit``tools/mir15_smoke.sh release`
- 現状OKJIT-direct: BinOp, Compare(真偽戻り), Load/Store(ローカル), Branch/Jump/PHI最小, ExternCall(console.log)
- まだoptionalフォールバックで許容: 配列/Mapのhostcall系len/isEmpty/get/push 等)
実行メモ
- ビルド: `cargo build --release --features cranelift-jit`
- スモーク: `tools/mir15_smoke.sh release`
- AOT(.o)簡易出力: `NYASH_AOT_OBJECT_OUT=target/aot_objects ./target/release/nyash --jit-direct examples/aot_min_return_42.nyash`
- 生成: `target/aot_objects/main.o`
- 備考: `tools/build_aot.sh` は jit-direct で .o を生成するよう更新済(要検証)
LLVM足場VM側 先行)
- Escape AnalysisVMのみ: `NYASH_VM_ESCAPE_ANALYSIS=1`
- 非エスケープなBoxの `Barrier(Read/Write)` を保守的に `Nop`
- 実装: `src/mir/passes/escape.rs`NewBox起点のローカル追跡Return/Call/Store使用でescape検出
- 適用: VM実行前にMIRへ適用`src/runner/modes/vm.rs`
- 目的: LLVM(inkwell)への最適化ヒント連携を見据えた足固めまずVMで効果検証
- 次の着手(この順で)
1) MIR15のVM/JITカバレッジをもう一段拡張配列/Map hostcallのJIT対応 or optionalのまま明確化
2) スモークに代表サンプルを追加し、CI/ローカルでワンコマンド確認
3) LLVMフェーズinkwellへ移行Const/Return→BinOp/Compare→CF/PHIの順
次フェーズ提案
- まずMIR15のVM/JITを固めるhostcallはoptional許容 or 段階実装)
- その後、LLVMinkwellへ移行開始
MIRセット移行メモ
- 現行の参照ドキュメントは「26命令Canonical」を維持`docs/reference/mir/INSTRUCTION_SET.md`)。
- 実装はCore-15へ段階移行中TypeOp/WeakRef/Barrier 統合、Print Deprecatedで、MIR15のカバレッジは `MIR15_COVERAGE_CHECKLIST.md` で運用。
- Core-15が安定した時点で参照ドキュメント側を「15命令」に更新し、命令数固定テストも切替える。
- [x] JIT/AOT: 将来のGCバリア/セーフポイント用のシンボル予約nyash.gc.barrier_write, nyash.rt.checkpoint
環境変数(段階移行トグル)
- NYASH_BUILDER_SAFEPOINT_ENTRY=1: 関数エントリにSafepointを発行
- NYASH_BUILDER_SAFEPOINT_LOOP=1: ループ各回でSafepointを発行
- NYASH_BUILDER_LEGACY_WEAK=1: 旧WeakNew/WeakLoad発行を有効化既定: 無効、WeakRefに統一
- NYASH_BUILDER_LEGACY_BARRIER=1: 旧BarrierRead/Write発行を有効化既定: 無効、Barrierに統一
- NYASH_BUILDER_DISABLE_TRYCATCH=1: try/catch/finallyを無効化try本体のみ
- NYASH_BUILDER_DISABLE_THROW=1: throwをenv.debug.traceへフォールバック
- NYASH_REWRITE_DEBUG=1: Debug命令をExternCall(env.debug.trace)に書き換え
- NYASH_REWRITE_SAFEPOINT=1: Safepoint命令をExternCall(env.runtime.checkpoint)に書き換え
- NYASH_REWRITE_FUTURE=1: FutureNew/Set/Await を ExternCall(env.future.*) に書き換え(スキャフォールド)
- NYASH_DEBUG_TRACE=1: env.debug.traceのログをstderrに出力
- NYASH_RUNTIME_CHECKPOINT_TRACE=1: env.runtime.checkpointのログをstderrに出力
直近実装(完了)
- AOT/JIT: string-like hostcalls 実装concat_hh/eq_hh/lt_hhとLowerer経路、シンボル登録
- Print命令の非推奨化: BuilderでExternCall(console.log)へ統一、Rewriteでも変換
- Builderlegacy抑止のトグル: Safepoint/Try-Catch/Throwをトグル化、loop safepointも任意化
- Runtime extern_call: env.debug.trace / env.runtime.checkpoint を追加
次の着手(順序)
1. JIT/AOT: GCバリア/セーフポイントのシンボル予約と下準備nyash.gc.barrier_write, nyash.rt.checkpoint
2. Docs: 上記トグル/Extern API/命令マッピングの追記INSTRUCTION_SET, runtime extern, migration
3. Future/AwaitのRewriteスキャフォールドNYASH_REWRITE_FUTURE=1と最小実装方針の明文化完了
4. Builderのlegacy APIemit_weak_new/load, barrier_read/writeの非推奨化と使用箇所の削減
5. JIT directのBlock-Sealパニック修正block seal順序・entry sealの見直し
期待効果
- 命令 37→15目安で読みやすさ/実装コスト/検証コストを大幅削減
- JIT/AOT の対応面積が小さくなり、今回の string-like hostcall のような追加の導入が容易に
- 「Everything is Box」に合致I/O, 例外, ランタイム機能をBox/Externに集約
優先度/スケジュール
- 優先度: 最優先10.5c/10.7に割り込み)
- 目安: 1〜2日でBuilder/Rewrite/Docs、続いてVM/JITの掃除を段階投入
直近スナップショット2025-08-30 更新)
Current State
- Plugin-First/Handle-First/TLVはAOT/VMで安定10.5e完了状態を継続)
- 10.6計画Thread-Safety/Schedulerと10.7計画トランスパイルAll-or-Nothingを確定
- Nyash-onlyパイプラインtools/pycを開始Parser/CompilerはNyashで実装方針
- include式の最小実装を追加式でBoxを返す1ファイル=1static box
- インタプリタ: include式は実行時評価
- VM/AOT: MIRビルダーが取り込み先を同一MIRに連結MIR命令は増やさない
- nyash.tomlの[include.roots]でルート解決拡張子省略、index.nyash対応
- tools/pycをモジュール分割
- tools/pyc/pyc.nyashエントリ: includeでPyIR/PythonParserNy/PyCompilerを取り込み
- tools/pyc/PyIR.nyash, PythonParserNy.nyash, PyCompiler.nyashNyash-only実装
How To RunNyash-only
- VM: `NYASH_PY_CODE=$'def main():\n return 42' ./target/release/nyash --backend vm tools/pyc/pyc.nyash`
- 出力: Parser JSON → IRreturn 42→ 生成Nyashソース現状は骨組み
- include動作サンプル: `./target/release/nyash --backend vm examples/include_main.nyash`Math.add(1,2)=3
進捗2025-08-30 夜)
- include: 循環検出を追加(インタプリタ/VM収集器ともにロード中スタックで経路出力。examples/cycle_a/b で検証
- tools/pyc: 最小IRreturn定数→Nyash生成を通し、出力をprintまで接続
- 文字列基盤: VMにString統一ブリッジを着手内部StringBoxとプラグインStringBoxの比較互換、内部Stringメソッドのフォールバック
- 追加プラグイン(小粒・基底)
- RegexBoxcompile/isMatch/find/replaceAll/split: examples/regex_min.nyash
- EncodingBoxutf8/base64/hex: examples/encoding_min.nyash
- TOMLBoxparse/get/toJson: examples/toml_min.nyash
- PathBoxjoin/dirname/basename/extname/isAbs/normalize: examples/path_min.nyash
Next Steps優先順・更新
1. String統一ブリッジ実装済・一次完了
- VM: 比較/加算/代表メソッドのフォールバックlength/isEmpty/charCodeAt/concat/+をstring-like正規化で実装
- Interpreter: 比較/加算はstring-like正規化を適用メソッドは後続で最小追補があれば対応
- 例: encoding_min/regex_min/toml_min/path_min で回帰確認
2. AOT/JITへのブリッジ降ろしMIR→VM→JIT→exeの汎用性維持・ハードコーディング禁止
- 文字列演算のhostcall化read-only: nyash.string.concat_hh / eq_hh / lt_hh
- Lowerer: BinOp(Add) / Compare(Eq/Lt) を「string-like」判定時にhostcallへフォールバック
- 代表メソッド: length/isEmpty/charCodeAtは既存hostcall経由で維持、concat(メソッド)も追加検討
- Registry: 署名/権限ReadOnly登録、シンボル解決とJITビルダー登録
- 目標: examples/string_bridge_min.nyash をAOTでも成功
3. tools/pyc: IR→Nyashの反映強化return/If/Assignを安定化、Strictスイッチ連動
4. Strictスイッチ: tools/pycunsupported_nodes非空でErr、envでON/OFF
5. CLI隠しフラグ `--pyc`/`--pyc-native`Parser→Compiler→AOTの一本化導線
6. 最小回帰VM/AOTの差分記録とdocs追補include/exportとpyc、Regex/Encoding/TOML/PathのAPI概要
Env Keyspyc
- NYASH_PY_CODE: Pythonソース文字列Nyash-onlyパイプライン/Parser用
- NYASH_PY_IR: IR(JSON)直接注入Rust雛形Compilerの確認用・オプション
目的: Handle-First + by-name を軸に、Python統合PyRuntimeBox/PyObjectBoxを汎用・安全に実装する。最適化は後段。さらに10.7のNyash-onlyトランスパイルC2pycを最小構成で立ち上げる。
ステータス2025-08-30 更新)
- フェーズ: 10.5c 汎用Handle/TLV実装の拡張Python統合開始
- 方針: 「綺麗に作って動かす」= ハードコーディング排除・Handle/TLV統一・最適化は後回し
10.5b 完了項目(橋渡し済み)
- by-name シムgetattr/callを実装JIT/AOTし、Lowerer から a0 を `nyash.handle.of` で確実にハンドル化して呼び出し
- 引数 a1/a2 はハンドル優先/なければレガシー参照から TLV 構築String/Integer はプリミティブ化)
- 汎用 birth シムを追加
- `nyash.box.birth_h(type_id:i64)->i64`JIT/AOT
- `nyash.box.birth_i64(type_id:i64, argc:i64, a1:i64, a2:i64)->i64`JIT/AOT
- Lowerer: NewBox引数無しは birth_h に統一。引数ありは安全なケースInteger const引数が既にハンドルだけ birth_i64 に段階導入
- AOT: examples/aot_py_math_sqrt_min.nyash で Strict でも .o 生成を確認target/aot_objects/main.o
- ログ
- AOT: NYASH_CLI_VERBOSE=1 で birth_h の可視化
- JIT: events で by-name/birth の観測(必要十分の最小限)
10.5c 着手項目(進行中)
- Lowerer: PluginInvoketype_id/method_id & by-nameの Handle-First 配線を統一a0を常にnyash.handle.of
- JIT/AOT: birth_h/_i64と by-name シムでTLV生成を汎用化String/Integerはプリミティブ化、他はHandle
- Strict時のJIT実行停止コンパイル専用でVM=仕様の原則を徹底
非対応(後回し・最適化)
- StringBox 専用の known_string/再利用最適化
- 汎用的な定数プールbirth の可変長 TLV 一括最適化
次の作業10.5c 続き)
1) FFI仕様の短文化a0/a1/a2=Handle優先→TLV、レガシー抑止フラグ、戻りTLVのdecodeポリシー
2) birth引数の一般化メモ可変長TLV、例外時ハンドリング
3) Python統合の最小チェーンimport→getattr→callのAOT/VM双方での実装確認サンプル追加
4) ドキュメント更新10.5c README/INDEX、FFIガイド
合意済みルール
- まず汎用・安全に動かす(最適化は内部に隠し、後段)
- StringBox 等の個別特化は入れない。Handle/TLV で統一し、Box 追加を阻害しない
- Strict/FailFast を維持fallback で隠さない)