diff --git a/CURRENT_TASK.md b/CURRENT_TASK.md index a88ed90e..1438c4a0 100644 --- a/CURRENT_TASK.md +++ b/CURRENT_TASK.md @@ -1,6 +1,6 @@ # Current Task — Phase Freeze (Macro Complete) -Updated: 2025‑09‑19 +Updated: 2025‑09‑19 (night) ## Status マクロ基盤は完成・既定ONで安定(AST JSON v0、PyVMサンドボックス、strict/timeout、dump/golden、JSONL trace、プロファイル)。ここで機能を一旦凍結し、自己ホスト/実アプリ開発に注力して磨き込むフェーズに入る。 @@ -23,6 +23,14 @@ Updated: 2025‑09‑19 - CI: min‑gate に macro‑golden ジョブと selfhost‑preexpand‑smoke を追加。 - Docs: user‑macros.md / ast‑json‑v0.md / capabilities.md (io/net/env). +## Delivered (LoopForm – MVP‑1 Safe) +- LoopNormalize macro (Nyash runner) scaffolded and active. +- Canonicalize Loop node key order (condition → body). +- Safe body reorder: move Assignment nodes to tail only when original order already has non‑assign → assign; otherwise keep order (no semantic change). +- JsonBuilder utility added for AST JSON v0 fragments (string‑based minimal helpers). +- Golden comparison made key‑order insensitive (JSON normalized via python) for macro tests. +- LLVM pre‑expand run verified on loop_simple (PyVM → MIR → LLVM). + ## Focus — Freeze & Polish 1) 実アプリの作成と運用(マクロ前展開/PyVM/LLVMラインの動作確認) 2) バグ修正・ドキュメント整備・スモーク/ゴールデン/CI強化(仕様不変) @@ -39,21 +47,20 @@ Updated: 2025‑09‑19 - DONE: MacroCtx 契約 PoC — ランナーが `expand(json, ctx)` を優先、失敗時に `expand(json)` へフォールバック。 Next (short) -- Self‑host 前展開: array/map ケースの追加スモーク(auto 動作の追認)。 -- `macro-profile` の最終化(ドキュメント化 + CIプロファイルの導入検討)。 -- MacroCtx: ctx JSON スキーマの明記(limits/nonce/gensym 提示)と `ctx.gensym` の採用例を追加。 +- LoopForm MVP‑2: while → carrier normalization (no break/continue, up to 2 vars) + - Extract updated vars (e.g., i, sum) and normalize body so updates are tail; emit carrier‑like structure with existing AST forms (Local/If/Loop/Assignment) while preserving semantics. + - Add goldens (two‑vars) + selfhost‑preexpand smokes; verify PyVM/LLVM parity. +- LoopForm MVP‑3: break/continue minimal handling (single‑level) +- for/foreach pre‑desugaring → LoopForm normalization (limited) +- LLVM IR hygiene for LoopForm cases — PHI at block head, no empty PHIs (smoke) +- Docs: enrich `docs/guides/loopform.md` with carrier examples and JSON builder snippets. Action Items (next 48h) -- [x] Add selfhost pre-expand smokes for array/map - - Scripts: `tools/test/smoke/macro/selfhost_preexpand_array_auto.sh`, `selfhost_preexpand_map_auto.sh` - - Accept: logs contain "selfhost macro pre-expand: engaging" and program exits 0 -- [x] Finalize macro profiles - - Docs: `docs/guides/macro-profiles.md`(dev/lite/ci → envの対応) - - CLI: `--profile {lite|dev|ci|strict}` 実装済 -- [x] MacroCtx example - - Example macro: `apps/macros/examples/gensym_example_macro.nyash` -- [x] ENV縮約の警告 - - 旧ENV使用時の非推奨ログを追加(TOPLEVEL_ALLOW/BOX_CHILD_RUNNER/BOX_NY_*) +- [x] Enable sugar by default (array/map literals) +- [x] Golden normalizer (key‑order insensitive) for macro tests +- [x] Loop simple/two‑vars goldens with normalization +- [ ] LoopForm MVP‑2: two‑vars carrier safe normalization + tests/smokes +- [ ] LLVM PHI hygiene smoke on LoopForm cases ## Phase‑16 Outlook - MacroCtx (gensym/report/getEnv) and capabilities mapped to `nyash.toml`. diff --git a/docs/guides/loopform.md b/docs/guides/loopform.md index 72ab005f..128e4058 100644 --- a/docs/guides/loopform.md +++ b/docs/guides/loopform.md @@ -27,6 +27,71 @@ local assign = JB.assignment(v_i, JB.binary("+", v_i, JB.literal_int(1))) - ループで更新される変数群をタプルに束ね、ヘッダに“1個のφ”を置く。 - break/continue は“次キャリア”または“現キャリア”で遷移し、一貫した合流点を保つ。 +キャリア正規化(MVP-2)の具体例 +- 前提: break/continue なし、更新変数は最大2個(例: i と sum)。 + +例1: 基本的な while(i を 0..n-1 で加算) + +Nyash(入力・素朴形) +``` +local i = 0 +local sum = 0 +while (i < n) { + sum = sum + i + i = i + 1 +} +``` + +正規化の狙い(概念) +- ループ本体の末尾に更新(Assignment)をそろえる(既に末尾ならそのまま)。 +- ループヘッダの合流で i と sum を同一グループの PHI でまとめやすくする。 + +AST JSON v0 のスケッチ(JsonBuilder を用いた生成例) +``` +local JB = include "apps/lib/json_builder.nyash" +local v_i = JB.variable("i") +local v_s = JB.variable("sum") +local v_n = JB.variable("n") + +// 先頭(ローカル導入) +local i0 = JB.local_decl("i", JB.literal_int(0)) +local s0 = JB.local_decl("sum", JB.literal_int(0)) + +// 条件と本体(更新は末尾に揃える) +local cond = JB.binary("<", v_i, v_n) +local body_nonassign = JB.block([ + JB.assignment(v_s, JB.binary("+", v_s, v_i)) +]) +local body_updates = JB.block([ + JB.assignment(v_i, JB.binary("+", v_i, JB.literal_int(1))) +]) + +// ループノード(MVP: while→Loop; キャリアは概念上) +local loop_node = JB.loop(cond, JB.concat_blocks(body_nonassign, body_updates)) + +JB.program([ i0, s0, loop_node ]) +``` + +備考 +- MVP-2 では“新しいキャリア用ノード”は導入せず、既存の Local/If/Loop/Assignment で表現する。 +- 「非代入→代入」の順を崩すと意味が変わる可能性があるため、再配置は安全にできる場合のみ行う(既に末尾に更新がある等)。 + +例2: 2変数更新の順序混在(安全な並べ替え) +``` +while (i < n) { + print(i) + sum = sum + i + i = i + 1 +} +``` +- 正規化: 非代入(print)→ 代入(sum) → 代入(i) の末尾整列。 +- 非代入が末尾に来るケースは再配置しない(意味が変わりうるため、スキップ)。 + +今後の拡張(MVP-3 概要) +- continue: 「次キャリア」へ(更新後にヘッダへ戻す)。 +- break: 「現キャリア」を exit へ(ヘッダ合流と衝突しないよう保持)。 +- いずれも 1 段ネストまでの最小対応から開始。 + 対応状況(MVP→順次拡張) - Week1: while(break/continue無し) - Week2: break/continue/ネスト最小対応、キャリア自動抽出 @@ -39,5 +104,12 @@ local assign = JB.assignment(v_i, JB.binary("+", v_i, JB.literal_int(1))) - macro‑golden(展開後ASTのゴールデン) - LLVM PHI健全性スモーク(空PHI無し、先頭グループ化) +手元での確認 +- ゴールデン(キー順無視の比較) + - `tools/test/golden/macro/loop_simple_user_macro_golden.sh` + - `tools/test/golden/macro/loop_two_vars_user_macro_golden.sh` +- 自己ホスト前展開(PyVM 経由) + - `NYASH_VM_USE_PY=1 NYASH_USE_NY_COMPILER=1 NYASH_MACRO_ENABLE=1 NYASH_MACRO_PATHS=apps/macros/examples/loop_normalize_macro.nyash ./target/release/nyash --macro-preexpand --backend vm apps/tests/macro_golden_loop_simple.nyash` + 参考 - docs/development/roadmap/phases/phase-17-loopform-selfhost/