core: for/foreach -> Loop normalization (always-on); LoopForm MVP-3 per-segment reorder; smokes stabilized (VM + LLVM PHI); docs updated (macro-system, loopform); quiet macro load logs
This commit is contained in:
@ -92,6 +92,21 @@ while (i < n) {
|
||||
- break: 「現キャリア」を exit へ(ヘッダ合流と衝突しないよう保持)。
|
||||
- いずれも 1 段ネストまでの最小対応から開始。
|
||||
|
||||
MVP-3(実装済み・最小対応)
|
||||
- 本体を break/continue でセグメント分割し、各セグメント内のみ安全に「非代入→代入」に整列。
|
||||
- ガード:
|
||||
- 代入先は変数のみ(フィールド等は対象外)
|
||||
- 全体の更新変数は最大2種(MVP-2 制約を継承)
|
||||
- セグメント内で「代入の後に非代入」があれば整列しない(順序保持)
|
||||
- スモーク:
|
||||
- `tools/test/smoke/macro/loopform_continue_break_output_smoke.sh`
|
||||
|
||||
for / foreach の糖衣と正規化(概要)
|
||||
- for: `for(fn(){ init }, cond, fn(){ step }, fn(){ body })` を `init; loop(cond){ body; step }` へ正規化。
|
||||
- init/step は `Assignment`/`Local` 単体でも可。
|
||||
- foreach: `foreach(arr, "x", fn(){ body })` を `__ny_i` で走査する Loop へ正規化し、`x` を `arr.get(__ny_i)` に置換。
|
||||
- スモーク: `tools/test/smoke/macro/for_foreach_output_smoke.sh`
|
||||
|
||||
対応状況(MVP→順次拡張)
|
||||
- Week1: while(break/continue無し)
|
||||
- Week2: break/continue/ネスト最小対応、キャリア自動抽出
|
||||
@ -103,13 +118,23 @@ while (i < n) {
|
||||
検証
|
||||
- macro‑golden(展開後ASTのゴールデン)
|
||||
- LLVM PHI健全性スモーク(空PHI無し、先頭グループ化)
|
||||
- 出力一致スモーク(two‑vars の実行出力が同一であること)
|
||||
|
||||
手元での確認
|
||||
- ゴールデン(キー順無視の比較)
|
||||
- `tools/test/golden/macro/loop_simple_user_macro_golden.sh`
|
||||
- `tools/test/golden/macro/loop_two_vars_user_macro_golden.sh`
|
||||
- 出力一致スモーク(VM)
|
||||
- `tools/test/smoke/macro/loop_two_vars_output_smoke.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/loopform/simple.nyash`
|
||||
|
||||
実装メモ(内蔵変換ルート / Rust)
|
||||
- 既定のマクロ実行は internal‑child(Rust内蔵)です。LoopNormalize は以下の保守的なガードで正規化します。
|
||||
- トップレベル本体に Break/Continue がないこと
|
||||
- 代入対象は最大2変数、かつ単純な変数(フィールド代入などは除外)
|
||||
- 代入の後ろに非代入が現れない(安全に末尾整列できる)
|
||||
- 条件を満たす場合のみ「非代入→代入」の順でボディを再構成します(意味は不変)。
|
||||
|
||||
参考
|
||||
- docs/development/roadmap/phases/phase-17-loopform-selfhost/
|
||||
|
||||
@ -60,6 +60,26 @@ NYASH_MACRO_ENABLE=1 NYASH_TEST_ARGS_DEFAULTS=1 \
|
||||
```
|
||||
Shows pre/post expansion AST (debug only).
|
||||
|
||||
## Core Normalization (always-on when macros enabled)
|
||||
|
||||
Certain language sugars are normalized before MIR across all runners when the macro gate is enabled. These are not user macros and do not require any registration:
|
||||
|
||||
- for sugar → Loop
|
||||
- `for(fn(){ init }, cond, fn(){ step }, fn(){ body })`
|
||||
- Emits: `init; loop(cond){ body; step }`
|
||||
- `init/step` also accept a single Assignment or Local instead of `fn(){..}`.
|
||||
|
||||
- foreach sugar → Loop
|
||||
- `foreach(array_expr, "x", fn(){ body_with_x })`
|
||||
- Expands into an index-based loop with `__ny_i`, and substitutes `x` with `array_expr.get(__ny_i)` inside body.
|
||||
|
||||
Normalization order (within the core pass):
|
||||
1) for/foreach → 2) match(PeekExpr) → 3) loop tail alignment (carrier-like ordering; break/continue segments supported).
|
||||
|
||||
Notes:
|
||||
- Backward-compat function names `ny_for` / `ny_foreach` are also accepted but `for` / `foreach` are preferred.
|
||||
- This pass is part of the language pipeline; it is orthogonal to user-defined macros.
|
||||
|
||||
## Developer API (preview)
|
||||
|
||||
- Pattern/Quote primitives are available to bootstrap macro authorship.
|
||||
|
||||
Reference in New Issue
Block a user