docs(20.39): add Next Steps and mark hv1 unify + string scanner fix DONE; loop count_param: accept swapped < / <= (cmp Gt/Ge); add canaries for swapped_lt/lte
This commit is contained in:
@ -21,6 +21,12 @@ Remaining (20.39 — typed IR & finalize)
|
|||||||
- Remove include fallback from scripts(直行のみ)。
|
- Remove include fallback from scripts(直行のみ)。
|
||||||
- Sweep concatenations and update helpers.
|
- Sweep concatenations and update helpers.
|
||||||
|
|
||||||
|
Next Steps (ordered)
|
||||||
|
1) ループ比較の正規化拡張(>/>=/==/!= → Lt/Gt/Ge 正規化;左右スワップ++1調整、canary補強)
|
||||||
|
2) SSOT 拡張(compare/branch/jump/phi を cf_common に段階移行)
|
||||||
|
3) Unicode `\\uXXXX` 復号のトグル実装(既定OFF;canary追加)
|
||||||
|
4) hv1 一本化(main入口)と文字列スキャナ根治('対応+エスケープ拡張)を DONE に反映
|
||||||
|
|
||||||
Hotfix Plan — Using/Prelude Unification (Self‑Host)
|
Hotfix Plan — Using/Prelude Unification (Self‑Host)
|
||||||
- Problem: .hako を NyashParser に通す経路でパース落ち(Invalid expression)。
|
- Problem: .hako を NyashParser に通す経路でパース落ち(Invalid expression)。
|
||||||
- Decision: プレリュードは“テキスト統合(merge_prelude_text)”に一本化。AST マージは撤退。
|
- Decision: プレリュードは“テキスト統合(merge_prelude_text)”に一本化。AST マージは撤退。
|
||||||
@ -50,29 +56,14 @@ Acceptance
|
|||||||
- v1 φ/branch/jump の代表カナリーが IR 反復で strict PASS。tolerate ケースは期待と一致。
|
- v1 φ/branch/jump の代表カナリーが IR 反復で strict PASS。tolerate ケースは期待と一致。
|
||||||
- Verify 既定が v1→Hakorune(Core fallback)で quick 緑維持。
|
- Verify 既定が v1→Hakorune(Core fallback)で quick 緑維持。
|
||||||
- Hako 構文を Nyash VM で実行しようとした場合、入口で Fail‑Fast(診断メッセージ)。
|
- Hako 構文を Nyash VM で実行しようとした場合、入口で Fail‑Fast(診断メッセージ)。
|
||||||
|
- hv1 直行は main 入口で早期退出し、プラグイン初期化ログが出ない(canaryで保証)。
|
||||||
|
|
||||||
Changes (this step)
|
Changes (this step)
|
||||||
- Docs: phase‑20.39 に計画と進捗(verify直行 DONE/concat-safety VM/Core DONE/build2 適用済み lowers)を反映。
|
- hv1 direct を main 入口で早期退出に一本化(プラグイン初期化前で rc のみ出力)。
|
||||||
- Add typed IR box file(hakorune-vm.ir.types)と module export(構造のみ・参照用)。
|
- Tokenizer 根治: Stage‑3 でシングルクォート受理、エスケープ(\\/ \\b \\f \\' \\r)拡張。
|
||||||
- Concat-safety: StrCast 追加、VM/Core の “"" + <Box>” を置換(canaries 緑維持)。
|
- SSOT: Builder BinOp を `emit_binop_to_dst` で発行(挙動不変)。
|
||||||
- V1PhiAdapterBox: robust incoming scan (multi‑pair, spaces/newlines) using array‑end scanner.
|
- Loop 正規化: CountParam に `L<i` / `L<=i`(降順)を追加受理(cmp=Gt/Ge)。canary 2本追加(swapped_lt/lte)。
|
||||||
- V1SchemaBox: new block_segment_wo_phi(json, bid) to build IR segment without φ.
|
- Docs: phase‑20.39 Next Steps を追記、hv1一本化/文字列スキャナ根治を DONE として明記。
|
||||||
- V1SchemaBox: phi_table_for_block(json,bid) 追加(dst と incoming[[pred,val],…] を返す)
|
|
||||||
- NyVmDispatcherV1Box(FLOW): IR‑based loop(block_segment_wo_phi)+ entry φ は V1PhiTableBox.apply_table_at_entry で一括適用(scan は後退互換のfallbackに)
|
|
||||||
- Entry φ application: still centralized in V1PhiTableBox; added optional trace hooks (HAKO_V1_FLOW_TRACE=1).
|
|
||||||
- Canary updated to enable experiment flag: v1_hakovm_phi_simple_flow_canary_vm.sh sets HAKO_V1_ALLOW_PHI_EXPERIMENT=1.
|
|
||||||
- φ canaries 追加: multi‑incoming / multi‑phi / whitespace混在 → いずれも PASS
|
|
||||||
- v1 extern canaries(20.38): env.get / warn / error / emit / codegen を PASS 化(タグ+rc=0)。
|
|
||||||
- hv1 inline prelude: prelude_v1.hako を path‑using に切替(inline -c での alias 揺れ回避)。
|
|
||||||
- phase2038 hv1 inline canary ドライバは ALLOW_USING_FILE を付与し、preinclude で安定化を準備(現状は alias 未解決で SKIP)。
|
|
||||||
- extern stub canaries(emit/codegen): include 依存を撤去し、rc=0 のみ確認に簡素化(タグ観測は hv1 inline カナリーへ委譲)。
|
|
||||||
- test_runner の provider タグ用シムを撤去(hv1 inline が安定したため)。
|
|
||||||
- vm.rs に hv1 ルーティング口を追加(opt-in、Fail‑Fast 緩和下で NYASH_VERIFY_JSON の inline を hv1 wrapper にルート)。
|
|
||||||
- verify は env(NYASH_VERIFY_JSON)受け渡し+末尾数値抽出で rc を安定化。
|
|
||||||
- Dispatcher(FLOW) は構造IRの反復へ完全切替(scan断片を撤去)。
|
|
||||||
- V1Schema.get_function_ir: blocks/phi_table 構築を実装(op/text+一部フィールド抽出で dispatcher の負荷低減)。
|
|
||||||
- Program(JSON v0) → MIR(JSON v0) bridge: Continue 降下の根治(増分注入→cond へ)。
|
|
||||||
- test_runner: verify_program_via_builder_to_core(env 渡し+Rust CLI fallback)を導入。
|
|
||||||
|
|
||||||
// Loop compares normalization (Step‑1)
|
// Loop compares normalization (Step‑1)
|
||||||
- Loop lowers(simple/count_param/sum_bc): Compare 受理を拡張し Lt 形へ正規化。
|
- Loop lowers(simple/count_param/sum_bc): Compare 受理を拡張し Lt 形へ正規化。
|
||||||
|
|||||||
@ -79,8 +79,10 @@ static box LowerLoopCountParamBox {
|
|||||||
cmp = (op == ">") ? "Gt" : "Ge"
|
cmp = (op == ">") ? "Gt" : "Ge"
|
||||||
} else { return null }
|
} else { return null }
|
||||||
} else {
|
} else {
|
||||||
// swapped (Int on lhs, Var i on rhs): L > i / L >= i (ascending)
|
// swapped (Int on lhs, Var i on rhs):
|
||||||
if op != ">" && op != ">=" { return null }
|
// L > i / L >= i → ascending(i < L / i < L+1)→ cmp="Lt"(limit +1 for >=)
|
||||||
|
// L < i / L <= i → descending(i > L / i >= L)→ cmp="Gt" / "Ge"
|
||||||
|
if op != ">" && op != ">=" && op != "<" && op != "<=" { return null }
|
||||||
local k_lhs = s.indexOf("\"lhs\":{", k_cmp); if k_lhs < 0 { return null }
|
local k_lhs = s.indexOf("\"lhs\":{", k_cmp); if k_lhs < 0 { return null }
|
||||||
local k_lim_t2 = s.indexOf("\"type\":\"Int\"", k_lhs)
|
local k_lim_t2 = s.indexOf("\"type\":\"Int\"", k_lhs)
|
||||||
if k_lim_t2 >= 0 {
|
if k_lim_t2 >= 0 {
|
||||||
@ -91,8 +93,17 @@ static box LowerLoopCountParamBox {
|
|||||||
limit = PatternUtilBox.find_local_int_before(s, lname3, k_cmp)
|
limit = PatternUtilBox.find_local_int_before(s, lname3, k_cmp)
|
||||||
}
|
}
|
||||||
if limit == null { return null }
|
if limit == null { return null }
|
||||||
if op == ">=" { limit = StringHelpers.int_to_str(JsonFragBox._str_to_int(limit) + 1) }
|
if op == ">" {
|
||||||
cmp = "Lt"
|
cmp = "Lt"
|
||||||
|
} else if op == ">=" {
|
||||||
|
limit = StringHelpers.int_to_str(JsonFragBox._str_to_int(limit) + 1)
|
||||||
|
cmp = "Lt"
|
||||||
|
} else if op == "<" {
|
||||||
|
cmp = "Gt"
|
||||||
|
} else {
|
||||||
|
// op == "<="
|
||||||
|
cmp = "Ge"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Body increment: Local i = Binary('+', Var i, Int step)
|
// Body increment: Local i = Binary('+', Var i, Int step)
|
||||||
local k_body_i = s.indexOf("\"name\":\"" + varname + "\"", k_loop)
|
local k_body_i = s.indexOf("\"name\":\"" + varname + "\"", k_loop)
|
||||||
|
|||||||
@ -58,12 +58,19 @@ static box LowerLoopSimpleBox {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// swapped: we expect op to be '>' or '>='
|
// swapped: L ? i
|
||||||
if op == ">" {
|
if op == ">" {
|
||||||
// L > i ≡ i < L
|
// L > i ≡ i < L
|
||||||
} else if op == ">=" {
|
} else if op == ">=" {
|
||||||
// L >= i ≡ i <= L ≡ i < (L+1)
|
// L >= i ≡ i <= L ≡ i < (L+1)
|
||||||
limit = StringHelpers.int_to_str(JsonFragBox._str_to_int(limit) + 1)
|
limit = StringHelpers.int_to_str(JsonFragBox._str_to_int(limit) + 1)
|
||||||
|
} else if op == "<" {
|
||||||
|
// L < i ≡ i > L → for simple ascending loop (init=0, step=1) this pattern is not canonical;
|
||||||
|
// we treat as descending form not supported by simple box
|
||||||
|
return null
|
||||||
|
} else if op == "<=" {
|
||||||
|
// L <= i ≡ i >= L — same reason as above
|
||||||
|
return null
|
||||||
} else {
|
} else {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,39 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Loop internal — swapped compare (Int < Var) → normalize to i > limit (descending); expect rc == 0 (no iterations)
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
|
||||||
|
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||||
|
|
||||||
|
tmp_json="/tmp/program_loop_swapped_lt_$$.json"
|
||||||
|
cat > "$tmp_json" <<'JSON'
|
||||||
|
{
|
||||||
|
"version": 0,
|
||||||
|
"kind": "Program",
|
||||||
|
"body": [
|
||||||
|
{ "type":"Local", "name":"i", "expr": {"type":"Int","value":0} },
|
||||||
|
{ "type":"Local", "name":"s", "expr": {"type":"Int","value":0} },
|
||||||
|
{ "type":"Loop",
|
||||||
|
"cond": {"type":"Compare","op":"<","lhs":{"type":"Int","value":3},"rhs":{"type":"Var","name":"i"}},
|
||||||
|
"body": [
|
||||||
|
{ "type":"Local", "name":"s", "expr": {"type":"Binary","op":"+","lhs":{"type":"Var","name":"s"},"rhs":{"type":"Int","value":1}} },
|
||||||
|
{ "type":"Local", "name":"i", "expr": {"type":"Binary","op":"-","lhs":{"type":"Var","name":"i"},"rhs":{"type":"Int","value":1}} }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{ "type":"Return", "expr": {"type":"Var","name":"s"} }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
JSON
|
||||||
|
|
||||||
|
set +e
|
||||||
|
HAKO_VERIFY_PRIMARY=core verify_mir_rc "$tmp_json" >/dev/null 2>&1
|
||||||
|
rc=$?
|
||||||
|
set -e
|
||||||
|
rm -f "$tmp_json" || true
|
||||||
|
|
||||||
|
if [ "$rc" -eq 0 ]; then
|
||||||
|
echo "[PASS] mirbuilder_loop_swapped_lt_core_exec_canary_vm"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
echo "[FAIL] mirbuilder_loop_swapped_lt_core_exec_canary_vm (rc=$rc, expect 0)" >&2; exit 1
|
||||||
|
|
||||||
@ -0,0 +1,39 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Loop internal — swapped compare (Int <= Var) → normalize to i >= limit (descending); with i starts at 0, no iterations → rc==0
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
|
||||||
|
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||||
|
|
||||||
|
tmp_json="/tmp/program_loop_swapped_lte_$$.json"
|
||||||
|
cat > "$tmp_json" <<'JSON'
|
||||||
|
{
|
||||||
|
"version": 0,
|
||||||
|
"kind": "Program",
|
||||||
|
"body": [
|
||||||
|
{ "type":"Local", "name":"i", "expr": {"type":"Int","value":0} },
|
||||||
|
{ "type":"Local", "name":"s", "expr": {"type":"Int","value":0} },
|
||||||
|
{ "type":"Loop",
|
||||||
|
"cond": {"type":"Compare","op":"<=","lhs":{"type":"Int","value":3},"rhs":{"type":"Var","name":"i"}},
|
||||||
|
"body": [
|
||||||
|
{ "type":"Local", "name":"s", "expr": {"type":"Binary","op":"+","lhs":{"type":"Var","name":"s"},"rhs":{"type":"Int","value":1}} },
|
||||||
|
{ "type":"Local", "name":"i", "expr": {"type":"Binary","op":"-","lhs":{"type":"Var","name":"i"},"rhs":{"type":"Int","value":1}} }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{ "type":"Return", "expr": {"type":"Var","name":"s"} }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
JSON
|
||||||
|
|
||||||
|
set +e
|
||||||
|
HAKO_VERIFY_PRIMARY=core verify_mir_rc "$tmp_json" >/dev/null 2>&1
|
||||||
|
rc=$?
|
||||||
|
set -e
|
||||||
|
rm -f "$tmp_json" || true
|
||||||
|
|
||||||
|
if [ "$rc" -eq 0 ]; then
|
||||||
|
echo "[PASS] mirbuilder_loop_swapped_lte_core_exec_canary_vm"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
echo "[FAIL] mirbuilder_loop_swapped_lte_core_exec_canary_vm (rc=$rc, expect 0)" >&2; exit 1
|
||||||
|
|
||||||
Reference in New Issue
Block a user