diff --git a/CURRENT_TASK.md b/CURRENT_TASK.md index f3fa7fe7..c4cf6013 100644 --- a/CURRENT_TASK.md +++ b/CURRENT_TASK.md @@ -24,7 +24,13 @@ Update (today) - CLI: `--rules`/`--skip-rules` を追加し、ルール単体/組合せ検証を高速化。`--no-ast` 既定化。 - Runtime: `NYASH_SCRIPT_ARGS_HEX_JSON` を導入(HEX経由で改行・特殊文字を安全搬送)。 - File I/O: FileBox provider 設計(SSOT + 薄いラッパ + 選択ポリシー)を文書化(docs/development/runtime/FILEBOX_PROVIDER.md)。 - - ENV: `NYASH_FILEBOX_MODE=auto|core-ro|plugin-only` を追加(ENV_VARS.md)。Analyzer/CI は core‑ro 相当で運用。 +- ENV: `NYASH_FILEBOX_MODE=auto|core-ro|plugin-only` を追加(ENV_VARS.md)。Analyzer/CI は core‑ro 相当で運用。 + +Roadmap links (21.5→21.7) +- 21.5 — Unicode & Provider Polish(現行計画): docs/private/roadmap/phases/phase-21.5/PLAN.md +- 21.6 — Hako MIR Builder MVP & Registry(opt‑in): docs/private/roadmap/phases/phase-21.6/PLAN.md +- 21.7 — VM mir_call state & Primary Flip(guarded): docs/private/roadmap/phases/phase-21.7/PLAN.md + - 21.8 — Hako Check: Refactor & QuickFix(MVP): docs/private/roadmap/phases/phase-21.8/PLAN.md Footing update (A→B→C, today) — 仕様と入口をまず固定 - A. 仕様/インターフェース(hako_check 診断 I/F と出力規約) @@ -50,6 +56,15 @@ Status (HC rules) - 10/11 pass, 1 skipped: HC011/012/013/014/015/016/018/021/022/031 = PASS、HC017 = SKIP(UTF‑8 byte-level 支援待ち) - CLI: `--rules`/`--skip-rules` で単体/組合せ検証を高速化、JSON_ONLY で純出力。 +Phase 21.7 — VM mir_call state & Primary Flip(green) +- T0(最小・安定化) + - length state(per‑receiver可): size/len/push, Map.set(new-key) 実装済み(Hakorune VM + Rust hv1_inline 両ルート)。 + - フラグ: HAKO_VM_MIRCALL_SIZESTATE=1(既定OFF), HAKO_VM_MIRCALL_SIZESTATE_PER_RECV=1(任意)。 +- T1(検証導線) + - Primary 切替(verify_mir_rc)配線済み(既定=hakovm)。 + - Canary 拡充(phase2170/*): push×N、alias、per‑recv差分、flow跨ぎ。Map dup-key 非増分・value_state set→get も緑化。 + - 実行: bash tools/smokes/v2/profiles/quick/core/phase2170/run_all.sh → 全PASS。 + Remaining (21.4) 1) Hako Parser MVP 実装(tokenizer/parser_core/ast_emit/cli)【微修整】 2) Analyzer AST 入力の安定化(必要時のみ AST を使用) @@ -60,6 +75,43 @@ Remaining (21.4) 7) DOT エッジ ON(calls→edges, cluster by box) 8) FileBox provider 実装(リング0/1/選択ポリシー)と最小スモーク追加(core‑ro/auto/plugin-only)【COMPLETE】 +Remaining (21.4 → 21.5 handoff, concise) +- A. Parser/Analyzer まわり + - [ ] Hako Parser MVP 微修整(tokenizer/parser_core/ast_emit/cli) + - [ ] Analyzer AST 入力安定化(必要時のみ AST、_needs_ast/_needs_ir 調整) + - [ ] 代表ルール AST 化(HC001/002/003/010/011/020) + - [ ] json-lsp 追加ケース(OK/NG/edge) + - [ ] テスト駆動(tests// を3ルール分) + - [ ] 限定 --fix(HC002/HC003/HC500) +- B. DOT 改善 + - [ ] calls→edges 検証と代表追加ケース(cluster は既存を維持) +- C. Ring1/Plugins polish(未了のみ) + - [ ] Using/modules SSOT 確認(modules優先→相対推定→not found=警告/verbose詳細) + - [x] Capability introspection(FileBox provider caps(read/write) を Shim から参照→未サポート操作は Fail‑Fast) + - 実装: `src/runtime/provider_lock.rs:get_filebox_caps()` を追加、`src/boxes/file/mod.rs` で caps.write を参照し明示エラー + - [ ] Provider modes スモークの継続(auto/core‑ro/plugin‑only + failure injection) + +Phase 21.6 — Hako MIR Builder MVP & Registry(COMPLETE) +- [x] Registry 経路(opt‑in)を MirBuilderBox に実装(既定OFF) +- [x] registry 専用 canary 一式を PASS(Return/Int, If/Compare[Int/Int|Var/Int|Var/Var], Return(Binary Int/Int), Return(Logical OR/AND Var/Var)) +- [x] PatternUtilBox の find_local_* を“次の Local まで”で安全化 +- [x] MirBuilderBox チェーン fallback を厳格化(Binary/IntInt, Return/Int) + - Return(BinOp Var/Int) は registry が先に一致(rc=42) + - Logical AND(Var/Var) は JSON v0 bool=0/1 に合わせて一致(rc=0) + +受け入れ(21.6) +- [x] phase2111 の registry canary 全緑 +- [x] 既定OFF・互換維持(トグルON時のみ影響) + +Phase 21.7 — VM mir_call state & Primary Flip(kickoff) +- 目的: VM に最小 state(Array/Map length)を導入し、primary 切替(core|hakovm)で Core と同値検証(既定OFF)。 +- スコープ(T0→T1) + - T0: state map(受信者ID合成・length管理)、size/len 実値、push で length++、get/set は安定タグ維持 + - T1: HAKO_VERIFY_PRIMARY=core|hakovm 配線と canary(push→size 増分、primary=hakovm でも rc一致) +- トグル/既定 + - HAKO_VM_MIRCALL_STUB=1(既定ON: 非対象は0返し+タグ) + - HAKO_VERIFY_PRIMARY=core(既定) + - Checklist — Ring1/Plugins polish(このフェーズで完了) - [x] Env 統一(二重解消): `NYASH_FILEBOX_MODE`/`NYASH_DISABLE_PLUGINS` に一本化し、 旧 `NYASH_USE_PLUGIN_BUILTINS` / `NYASH_PLUGIN_OVERRIDE_TYPES` は非推奨(互換ブリッジは維持) diff --git a/docs/development/runtime/ENV_VARS.md b/docs/development/runtime/ENV_VARS.md index c439bb0e..42917ca2 100644 --- a/docs/development/runtime/ENV_VARS.md +++ b/docs/development/runtime/ENV_VARS.md @@ -51,6 +51,15 @@ NYASH_DISABLE_PLUGINS = "1" メモ: 改行・特殊文字を含む長文を `--source-file ` で渡す場合も HEX 経路で安全に輸送される。 +## Debug/Tracing(開発用の軽量トグル) +- HAKO_TRACE_EXECUTION: 実行経路の可視化("1" で有効) + - 例: `[trace] executor: hv1_inline (rust)` / `[trace] executor: hakovm (hako)` / `[trace] executor: core (rust)` + - 出力先: 原則 stderr(Hakovm は stdout)。テストランナーは numeric rc 抽出時に非数値行を無視します。 +- HAKO_VERIFY_SHOW_LOGS: verify_v1_inline_file() のログ透過("1" で有効) + - hv1 inline 実行の全出力を stderr に表示し、数値 rc は別途抽出します。 +- HAKO_DEBUG: 開発向け一括トグル("1" で `HAKO_TRACE_EXECUTION=1` と `HAKO_VERIFY_SHOW_LOGS=1` を自動有効化) + - 実装箇所: tools/smokes/v2/lib/test_runner.sh のデバッグ便宜機能 + ## FileBox Provider(コア/プラグイン切替) - NYASH_FILEBOX_MODE: `auto|core-ro|plugin-only` - auto(既定): プラグインがあれば PluginFileIo、無ければ CoreRoFileIo diff --git a/lang/src/mir/builder/MirBuilderBox.hako b/lang/src/mir/builder/MirBuilderBox.hako index 24fbd1c5..d54fd8b1 100644 --- a/lang/src/mir/builder/MirBuilderBox.hako +++ b/lang/src/mir/builder/MirBuilderBox.hako @@ -39,28 +39,46 @@ static box MirBuilderBox { if internal != null && ("" + internal) == "1" { // Optional: registry-driven lowering (scaffold). When HAKO_MIR_BUILDER_REGISTRY=1, // iterate PatternRegistryBox.candidates() and dispatch by name. - // NOTE: include not supported in VM, registry disabled for VM execution + // NOTE: using/alias は prelude で解決される(位置に依存しない)。 local use_reg = env.get("HAKO_MIR_BUILDER_REGISTRY") - if use_reg != null && ("" + use_reg) == "1" && 0 == 1 { + if use_reg != null && ("" + use_reg) == "1" { + // Registry list + using "hako.mir.builder.pattern_registry" as PatternRegistryBox + // Lowers needed by registry dispatch(using は prelude で集約される) + using "hako.mir.builder.internal.lower_if_compare" as LowerIfCompareBox + using "hako.mir.builder.internal.lower_if_compare_fold_binints" as LowerIfCompareFoldBinIntsBox + using "hako.mir.builder.internal.lower_if_compare_fold_varint" as LowerIfCompareFoldVarIntBox + using "hako.mir.builder.internal.lower_if_compare_varint" as LowerIfCompareVarIntBox + using "hako.mir.builder.internal.lower_if_compare_varvar" as LowerIfCompareVarVarBox + using "hako.mir.builder.internal.lower_return_method_array_map" as LowerReturnMethodArrayMapBox + using "hako.mir.builder.internal.lower_return_var_local" as LowerReturnVarLocalBox + using "hako.mir.builder.internal.lower_return_string" as LowerReturnStringBox + using "hako.mir.builder.internal.lower_return_float" as LowerReturnFloatBox + using "hako.mir.builder.internal.lower_return_bool" as LowerReturnBoolBox + using "hako.mir.builder.internal.lower_return_logical" as LowerReturnLogicalBox + using "hako.mir.builder.internal.lower_return_binop_varint" as LowerReturnBinOpVarIntBox + using "hako.mir.builder.internal.lower_return_binop_varvar" as LowerReturnBinOpVarVarBox + using "hako.mir.builder.internal.lower_return_binop" as LowerReturnBinOpBox + using "hako.mir.builder.internal.lower_return_int" as LowerReturnIntBox local names = PatternRegistryBox.candidates() local i = 0; local n = names.length() loop(i < n) { local nm = "" + names.get(i) - if nm == "if.compare.intint" { local out = LowerIfCompareBox.try_lower(s); if out != null { return out } } - if nm == "if.compare.fold.binints" { local out = LowerIfCompareFoldBinIntsBox.try_lower(s); if out != null { return out } } - if nm == "if.compare.fold.varint" { local out = LowerIfCompareFoldVarIntBox.try_lower(s); if out != null { return out } } - if nm == "if.compare.varint" { local out = LowerIfCompareVarIntBox.try_lower(s); if out != null { return out } } - if nm == "if.compare.varvar" { local out = LowerIfCompareVarVarBox.try_lower(s); if out != null { return out } } - if nm == "return.method.arraymap" { local out = LowerReturnMethodArrayMapBox.try_lower(s); if out != null { return out } } - if nm == "return.var.local" { local out = LowerReturnVarLocalBox.try_lower(s); if out != null { return out } } - if nm == "return.string" { local out = LowerReturnStringBox.try_lower(s); if out != null { return out } } - if nm == "return.float" { local out = LowerReturnFloatBox.try_lower(s); if out != null { return out } } - if nm == "return.bool" { local out = LowerReturnBoolBox.try_lower(s); if out != null { return out } } - if nm == "return.logical" { local out = LowerReturnLogicalBox.try_lower(s); if out != null { return out } } - if nm == "return.binop.varint" { local out = LowerReturnBinOpVarIntBox.try_lower(s); if out != null { return out } } - if nm == "return.binop.varvar" { local out = LowerReturnBinOpVarVarBox.try_lower(s); if out != null { return out } } - if nm == "return.binop.intint" { local out = LowerReturnBinOpBox.try_lower(s); if out != null { return out } } - if nm == "return.int" { local out = LowerReturnIntBox.try_lower(s); if out != null { return out } } + if nm == "if.compare.intint" { local out = LowerIfCompareBox.try_lower(s); if out != null { if env.get("HAKO_MIR_BUILDER_DEBUG")=="1" || env.get("NYASH_CLI_VERBOSE")=="1" { print("[mirbuilder/registry:" + nm + "]") } return out } } + if nm == "if.compare.fold.binints" { local out = LowerIfCompareFoldBinIntsBox.try_lower(s); if out != null { if env.get("HAKO_MIR_BUILDER_DEBUG")=="1" || env.get("NYASH_CLI_VERBOSE")=="1" { print("[mirbuilder/registry:" + nm + "]") } return out } } + if nm == "if.compare.fold.varint" { local out = LowerIfCompareFoldVarIntBox.try_lower(s); if out != null { if env.get("HAKO_MIR_BUILDER_DEBUG")=="1" || env.get("NYASH_CLI_VERBOSE")=="1" { print("[mirbuilder/registry:" + nm + "]") } return out } } + if nm == "if.compare.varint" { local out = LowerIfCompareVarIntBox.try_lower(s); if out != null { if env.get("HAKO_MIR_BUILDER_DEBUG")=="1" || env.get("NYASH_CLI_VERBOSE")=="1" { print("[mirbuilder/registry:" + nm + "]") } return out } } + if nm == "if.compare.varvar" { local out = LowerIfCompareVarVarBox.try_lower(s); if out != null { if env.get("HAKO_MIR_BUILDER_DEBUG")=="1" || env.get("NYASH_CLI_VERBOSE")=="1" { print("[mirbuilder/registry:" + nm + "]") } return out } } + if nm == "return.method.arraymap" { local out = LowerReturnMethodArrayMapBox.try_lower(s); if out != null { if env.get("HAKO_MIR_BUILDER_DEBUG")=="1" || env.get("NYASH_CLI_VERBOSE")=="1" { print("[mirbuilder/registry:" + nm + "]") } return out } } + if nm == "return.var.local" { local out = LowerReturnVarLocalBox.try_lower(s); if out != null { if env.get("HAKO_MIR_BUILDER_DEBUG")=="1" || env.get("NYASH_CLI_VERBOSE")=="1" { print("[mirbuilder/registry:" + nm + "]") } return out } } + if nm == "return.string" { local out = LowerReturnStringBox.try_lower(s); if out != null { if env.get("HAKO_MIR_BUILDER_DEBUG")=="1" || env.get("NYASH_CLI_VERBOSE")=="1" { print("[mirbuilder/registry:" + nm + "]") } return out } } + if nm == "return.float" { local out = LowerReturnFloatBox.try_lower(s); if out != null { if env.get("HAKO_MIR_BUILDER_DEBUG")=="1" || env.get("NYASH_CLI_VERBOSE")=="1" { print("[mirbuilder/registry:" + nm + "]") } return out } } + if nm == "return.bool" { local out = LowerReturnBoolBox.try_lower(s); if out != null { if env.get("HAKO_MIR_BUILDER_DEBUG")=="1" || env.get("NYASH_CLI_VERBOSE")=="1" { print("[mirbuilder/registry:" + nm + "]") } return out } } + if nm == "return.logical" { local out = LowerReturnLogicalBox.try_lower(s); if out != null { if env.get("HAKO_MIR_BUILDER_DEBUG")=="1" || env.get("NYASH_CLI_VERBOSE")=="1" { print("[mirbuilder/registry:" + nm + "]") } return out } } + if nm == "return.binop.varint" { local out = LowerReturnBinOpVarIntBox.try_lower(s); if out != null { if env.get("HAKO_MIR_BUILDER_DEBUG")=="1" || env.get("NYASH_CLI_VERBOSE")=="1" { print("[mirbuilder/registry:" + nm + "]") } return out } } + if nm == "return.binop.varvar" { local out = LowerReturnBinOpVarVarBox.try_lower(s); if out != null { if env.get("HAKO_MIR_BUILDER_DEBUG")=="1" || env.get("NYASH_CLI_VERBOSE")=="1" { print("[mirbuilder/registry:" + nm + "]") } return out } } + if nm == "return.binop.intint" { local out = LowerReturnBinOpBox.try_lower(s); if out != null { if env.get("HAKO_MIR_BUILDER_DEBUG")=="1" || env.get("NYASH_CLI_VERBOSE")=="1" { print("[mirbuilder/registry:" + nm + "]") } return out } } + if nm == "return.int" { local out = LowerReturnIntBox.try_lower(s); if out != null { if env.get("HAKO_MIR_BUILDER_DEBUG")=="1" || env.get("NYASH_CLI_VERBOSE")=="1" { print("[mirbuilder/registry:" + nm + "]") } return out } } i = i + 1 } // Fall-through to chain if none matched @@ -88,7 +106,7 @@ static box MirBuilderBox { using "hako.mir.builder.internal.lower_return_var_local" as LowerReturnVarLocalBox using "hako.mir.builder.internal.lower_return_string" as LowerReturnStringBox using "hako.mir.builder.internal.lower_return_float" as LowerReturnFloatBox - using "hako.mir.builder.internal.lower.logical" as LowerReturnLogicalBox + using "hako.mir.builder.internal.lower_return_logical" as LowerReturnLogicalBox using "hako.mir.builder.internal.lower_return_method_array_map" as LowerReturnMethodArrayMapBox using "hako.mir.builder.internal.lower_return_bool" as LowerReturnBoolBox using "hako.mir.builder.internal.lower_return_binop_varint" as LowerReturnBinOpVarIntBox @@ -314,22 +332,51 @@ static box MirBuilderBox { } } } - // Case (Int): Return(Int N) - local k_int = s.indexOf("\"type\":\"Int\"", k_ret) - if k_int >= 0 { - local k_val = s.indexOf("\"value\":", k_int) - if k_val >= 0 { - local i = k_val + 8 + // Case (Int): Return(Int N) — ensure expr.type is Int (not Binary/Logical/etc) + local k_expr = s.indexOf("\"expr\":{", k_ret) + if k_expr >= 0 { + // Check direct type after "expr":{ + local k_type_start = k_expr + 8 + local k_type = s.indexOf("\"type\":", k_type_start) + if k_type >= 0 && k_type < k_type_start + 20 { + // Extract the type value + local k_type_val = k_type + 7 local n = s.length() - loop(i < n) { if s.substring(i,i+1) != " " { break } i = i + 1 } - local j = i - if j < n && s.substring(j,j+1) == "-" { j = j + 1 } - local had = 0 - loop(j < n) { local ch = s.substring(j,j+1); if ch >= "0" && ch <= "9" { had = 1 j = j + 1 } else { break } } - if had == 1 { - local num = s.substring(i, j) - local mir = "{\"functions\":[{\"name\":\"main\",\"params\":[],\"locals\":[],\"blocks\":[{\"id\":0,\"instructions\":[{\"op\":\"const\",\"dst\":1,\"value\":{\"type\":\"i64\",\"value\":" + num + "}},{\"op\":\"ret\",\"value\":1}]}]}]}" - return mir + loop(k_type_val < n) { if s.substring(k_type_val, k_type_val+1) != " " && s.substring(k_type_val, k_type_val+1) != "\"" { break } k_type_val = k_type_val + 1 } + // Check if it's "Int" (not "Binary", "Logical", "Var", etc) + local is_int_type = 0 + if k_type_val + 3 <= n { + if s.substring(k_type_val, k_type_val+3) == "Int" { + // Verify it's followed by quote (not "Integer" or other extension) + if k_type_val + 3 < n && s.substring(k_type_val+3, k_type_val+4) == "\"" { + is_int_type = 1 + } + } + } + if is_int_type == 1 { + local debug_on = 0 + if env.get("HAKO_MIR_BUILDER_DEBUG") == "1" || env.get("NYASH_CLI_VERBOSE") == "1" { debug_on = 1 } + local k_expr_int = s.indexOf("\"type\":\"Int\"", k_expr) + local k_val = s.indexOf("\"value\":", k_expr_int) + if k_val >= 0 { + local i = k_val + 8 + loop(i < n) { if s.substring(i,i+1) != " " { break } i = i + 1 } + local j = i + if j < n && s.substring(j,j+1) == "-" { j = j + 1 } + local had = 0 + loop(j < n) { local ch = s.substring(j,j+1); if ch >= "0" && ch <= "9" { had = 1 j = j + 1 } else { break } } + if had == 1 { + local num = s.substring(i, j) + if debug_on == 1 { print("[mirbuilder/fallback:Return(Int) val=" + num + "]") } + local mir = "{\"functions\":[{\"name\":\"main\",\"params\":[],\"locals\":[],\"blocks\":[{\"id\":0,\"instructions\":[{\"op\":\"const\",\"dst\":1,\"value\":{\"type\":\"i64\",\"value\":" + num + "}},{\"op\":\"ret\",\"value\":1}]}]}]}" + return mir + } + } + } else { + // expr.type is not Int (e.g. Binary) - don't match this fallback + if env.get("HAKO_MIR_BUILDER_DEBUG") == "1" || env.get("NYASH_CLI_VERBOSE") == "1" { + print("[mirbuilder/fallback:Return(Int) skip - expr.type not Int]") + } } } } diff --git a/lang/src/mir/builder/internal/lower_return_binop_box.hako b/lang/src/mir/builder/internal/lower_return_binop_box.hako index b84b6435..a5f6b31c 100644 --- a/lang/src/mir/builder/internal/lower_return_binop_box.hako +++ b/lang/src/mir/builder/internal/lower_return_binop_box.hako @@ -15,17 +15,20 @@ static box LowerReturnBinOpBox { local op = JsonFragBox.read_string_after(s, k_op + 5) if op == null { return null } if !(op == "+" || op == "-" || op == "*" || op == "/") { return null } - // lhs int + // lhs/rhs object starts local klhs = s.indexOf("\"lhs\":{", k_bin) + local krhs = s.indexOf("\"rhs\":{", k_bin) if klhs < 0 { return null } + // strictly ensure lhs node is Int by bounding search before rhs start local ti = s.indexOf("\"type\":\"Int\"", klhs) if ti < 0 { return null } + if krhs >= 0 && ti >= krhs { return null } local kv_lhs = s.indexOf("\"value\":", ti) if kv_lhs < 0 { return null } + if krhs >= 0 && kv_lhs >= krhs { return null } local lhs_val = JsonFragBox.read_int_after(s, kv_lhs + 8) if lhs_val == null { return null } // rhs int - local krhs = s.indexOf("\"rhs\":{", k_bin) if krhs < 0 { return null } local ti2 = s.indexOf("\"type\":\"Int\"", krhs) if ti2 < 0 { return null } diff --git a/lang/src/mir/builder/internal/lower_return_int_box.hako b/lang/src/mir/builder/internal/lower_return_int_box.hako index 98602b96..b57aee4d 100644 --- a/lang/src/mir/builder/internal/lower_return_int_box.hako +++ b/lang/src/mir/builder/internal/lower_return_int_box.hako @@ -7,13 +7,37 @@ static box LowerReturnIntBox { local s = "" + program_json local k_ret = s.indexOf("\"type\":\"Return\"") if k_ret < 0 { return null } - // Expect Int after Return - local k_int = s.indexOf("\"type\":\"Int\"", k_ret) + // Find expr object + local k_expr = s.indexOf("\"expr\":{", k_ret) + if k_expr < 0 { return null } + // Check that expr.type is directly Int (not Binary, Logical, Var, etc) + local k_type_start = k_expr + 8 + local k_type = s.indexOf("\"type\":", k_type_start) + if k_type < 0 || k_type > k_type_start + 20 { return null } + // Extract type value to verify it's "Int" + local k_type_val = k_type + 7 + local n = s.length() + loop(k_type_val < n) { + local ch = s.substring(k_type_val, k_type_val+1) + if ch != " " && ch != "\"" { break } + k_type_val = k_type_val + 1 + } + // Verify it's exactly "Int" followed by quote + if k_type_val + 3 > n { return null } + if s.substring(k_type_val, k_type_val+3) != "Int" { return null } + if k_type_val + 3 >= n { return null } + if s.substring(k_type_val+3, k_type_val+4) != "\"" { return null } + // Now extract the value + local k_int = s.indexOf("\"type\":\"Int\"", k_expr) if k_int < 0 { return null } - // Read value after Int local kv = s.indexOf("\"value\":", k_int); if kv < 0 { return null } local val = JsonFragBox.read_int_after(s, kv + 8) if val == null { return null } + local debug_on = 0 + if env.get("HAKO_MIR_BUILDER_DEBUG") == "1" || env.get("NYASH_CLI_VERBOSE") == "1" { + debug_on = 1 + print("[mirbuilder/registry:return.int val=" + val + "]") + } // Emit minimal MIR JSON v0 (functions as array; blocks use id field) // Shape expected by src/runner/mir_json_v0.rs::parse_mir_v0_to_module local mir = "{\"functions\":[{\"name\":\"main\",\"params\":[],\"locals\":[],\"blocks\":[{\"id\":0,\"instructions\":[{\"op\":\"const\",\"dst\":1,\"value\":{\"type\":\"i64\",\"value\":" + val + "}},{\"op\":\"ret\",\"value\":1}]}]}]}" diff --git a/lang/src/mir/builder/internal/lower_return_logical_box.hako b/lang/src/mir/builder/internal/lower_return_logical_box.hako index 792d71d7..ee5783e4 100644 --- a/lang/src/mir/builder/internal/lower_return_logical_box.hako +++ b/lang/src/mir/builder/internal/lower_return_logical_box.hako @@ -21,8 +21,11 @@ static box LowerReturnLogicalBox { local op = JsonFragBox.read_string_after(s, k_op + 5) if op == null { return null } if !(op == "&&" || op == "||") { return null } + local debug_on = 0 + if env.get("HAKO_MIR_BUILDER_DEBUG") == "1" || env.get("NYASH_CLI_VERBOSE") == "1" { debug_on = 1 } // Resolve lhs to 0/1 (Bool or Var with Local Bool) - robust version local lhs_true = null + local lhs_name = null { local klhs_b = JsonFragBox.index_of_from(s, "\"lhs\":{\"type\":\"Bool\"", k_log) if klhs_b >= 0 { @@ -34,15 +37,21 @@ static box LowerReturnLogicalBox { local klhs_v = JsonFragBox.index_of_from(s, "\"lhs\":{\"type\":\"Var\"", k_log) if klhs_v >= 0 { local kn = JsonFragBox.index_of_from(s, "\"name\":", klhs_v) - if kn < 0 { return null } - local name = JsonFragBox.read_string_after(s, kn + 7) - if name != null { lhs_true = PatternUtilBox.find_local_bool_before(s, name, k_log) } + if kn < 0 { if debug_on == 1 { print("[logical/miss:lhs_name extraction]") } return null } + lhs_name = JsonFragBox.read_string_after(s, kn + 7) + if lhs_name != null { + lhs_true = PatternUtilBox.find_local_bool_before(s, lhs_name, k_log) + if debug_on == 1 && lhs_true == null { print("[logical/miss:lhs_true for name=" + lhs_name + "]") } + } else { + if debug_on == 1 { print("[logical/miss:lhs_name null]") } + } } } } - if lhs_true == null { return null } + if lhs_true == null { if debug_on == 1 { print("[logical/miss:lhs_true final]") } return null } // Resolve rhs to 0/1 (Bool or Var) - robust version local rhs_true = null + local rhs_name = null { local krhs_b = JsonFragBox.index_of_from(s, "\"rhs\":{\"type\":\"Bool\"", k_log) if krhs_b >= 0 { @@ -54,15 +63,23 @@ static box LowerReturnLogicalBox { local krhs_v = JsonFragBox.index_of_from(s, "\"rhs\":{\"type\":\"Var\"", k_log) if krhs_v >= 0 { local kn2 = JsonFragBox.index_of_from(s, "\"name\":", krhs_v) - if kn2 < 0 { return null } - local name2 = JsonFragBox.read_string_after(s, kn2 + 7) - if name2 != null { rhs_true = PatternUtilBox.find_local_bool_before(s, name2, k_log) } + if kn2 < 0 { if debug_on == 1 { print("[logical/miss:rhs_name extraction]") } return null } + rhs_name = JsonFragBox.read_string_after(s, kn2 + 7) + if rhs_name != null { + rhs_true = PatternUtilBox.find_local_bool_before(s, rhs_name, k_log) + if debug_on == 1 && rhs_true == null { print("[logical/miss:rhs_true for name=" + rhs_name + "]") } + } else { + if debug_on == 1 { print("[logical/miss:rhs_name null]") } + } } } } - if rhs_true == null { return null } + if rhs_true == null { if debug_on == 1 { print("[logical/miss:rhs_true final]") } return null } // Build MIR(JSON v0) string directly (functions[]/name="main"/blocks.id) + if debug_on == 1 { + print("[mirbuilder/registry:return.logical op=" + op + " lhs_true=" + lhs_true + " rhs_true=" + rhs_true + "]") + } local json_head = "{\"functions\":[{\"name\":\"main\",\"params\":[],\"locals\":[],\"blocks\":[" local bb0 = "{\"id\":0,\"instructions\":[{\"op\":\"const\",\"dst\":1,\"value\":{\"type\":\"i64\",\"value\":" + lhs_true + "}},{\"op\":\"branch\",\"cond\":1,\"then\":1,\"else\":2}]}" if op == "&&" { diff --git a/lang/src/mir/builder/internal/pattern_util_box.hako b/lang/src/mir/builder/internal/pattern_util_box.hako index 0b4e39a7..b1dfa571 100644 --- a/lang/src/mir/builder/internal/pattern_util_box.hako +++ b/lang/src/mir/builder/internal/pattern_util_box.hako @@ -47,17 +47,27 @@ static box PatternUtilBox { local pos=0; local last=-1 loop(true){ local k=JsonFragBox.index_of_from(s, "\"type\":\"Local\"",pos); if k<0||k>=before_pos{break}; local kn=JsonFragBox.index_of_from(s, "\"name\":\"",k); if kn>=0{ local ii=kn+8; local nn=s.length(); local jj=ii; loop(jj=before_pos { return null } - local kv=s.indexOf("\"value\":",ki); if kv<0 { return null } + // Bound the search between this Local and the next Local/before_pos + local next = JsonFragBox.index_of_from(s, "\"type\":\"Local\"", last + 1) + if next < 0 || next > before_pos { next = before_pos } + local ki = s.indexOf("\"type\":\"Int\"", last) + if ki < 0 || ki >= next { return null } + local kv = s.indexOf("\"value\":", ki) + if kv < 0 || kv >= next { return null } return JsonFragBox.read_int_after(s, kv+8) } find_local_bool_before(s, name, before_pos) { local pos=0; local last=-1 loop(true){ local k=JsonFragBox.index_of_from(s, "\"type\":\"Local\"",pos); if k<0||k>=before_pos{break}; local kn=JsonFragBox.index_of_from(s, "\"name\":\"",k); if kn>=0{ local ii=kn+8; local nn=s.length(); local jj=ii; loop(jj=before_pos { return null } - local kv=s.indexOf("\"value\":",kb); if kv<0 { return null } - return JsonFragBox.read_bool_after(s, kv+8) + local next = JsonFragBox.index_of_from(s, "\"type\":\"Local\"", last + 1) + if next < 0 || next > before_pos { next = before_pos } + local kb = s.indexOf("\"type\":\"Bool\"", last) + if kb < 0 || kb >= next { return null } + local kv = s.indexOf("\"value\":", kb) + if kv < 0 || kv >= next { return null } + // JSON v0 uses 0/1 for bool values, not true/false literals + return JsonFragBox.read_int_after(s, kv+8) } // Find the last Local(Int) before a given position (name-agnostic). diff --git a/lang/src/vm/boxes/mir_call_v1_handler.hako b/lang/src/vm/boxes/mir_call_v1_handler.hako index dc975d3e..12deb0ad 100644 --- a/lang/src/vm/boxes/mir_call_v1_handler.hako +++ b/lang/src/vm/boxes/mir_call_v1_handler.hako @@ -10,7 +10,43 @@ using selfhost.vm.helpers.method_alias_policy as MethodAliasPolicy using selfhost.vm.boxes.abi_adapter_registry as AbiAdapterRegistryBox static box MirCallV1HandlerBox { + // キー正規化ヘルパー(SSOT) + _norm_key_str(s) { + if s == null { return null } + local orig = s + + // 先頭・末尾の引用符を除去("k1" → k1) + local len = s.length() + if len >= 2 { + local first = s.substring(0, 1) + local last = s.substring(len - 1, len) + if first == "\"" && last == "\"" { + s = s.substring(1, len - 1) + } + } + + // [map/missing] はnullを返す + if s.indexOf("[map/missing]") >= 0 { + return null + } + + if env.get("HAKO_VM_MIRCALL_TRACE_KEYS") == "1" { + print("[vm/_norm_key_str] IN=" + orig + " OUT=" + s) + } + + return s + } + + // デバッグトレース(任意) + _norm_key_dbg(raw, norm) { + local trace_keys = env.get("HAKO_VM_MIRCALL_TRACE_KEYS") + if trace_keys == "1" { + print("[vm/trace/keys] raw=" + raw + " norm=" + norm) + } + } + handle(seg, regs) { + print("[DEBUG_HANDLER_ENTRY] seg=" + seg.substring(0, 80)) // Constructor: write dst=0 (SSA continuity) if seg.indexOf("\"type\":\"Constructor\"") >= 0 { local d0 = JsonFragBox.get_int(seg, "dst"); if d0 != null { regs.setField(StringHelpers.int_to_str(d0), "0") } @@ -83,19 +119,22 @@ static box MirCallV1HandlerBox { } // Map.set: 重複キー検知つきでサイズ更新 + 値保存(値状態ON時) if btype == "MapBox" && mname == "set" { + print("[DEBUG_ADAPTER_MAP_SET] ENTER") // 受信者・キー抽出 local arg0 = MiniMirV1Scan.first_arg_register(seg) local key_str = null if arg0 >= 0 { - key_str = regs.getField(StringHelpers.int_to_str(arg0)) - // MapBox.get returns "[map/missing] ..." for missing keys; treat as null - if key_str != null && key_str.indexOf("[map/missing]") >= 0 { key_str = null } + local key_str_raw = regs.getField(StringHelpers.int_to_str(arg0)) + key_str = me._norm_key_str(key_str_raw) + me._norm_key_dbg(key_str_raw, key_str) + print("[DEBUG_ADAPTER_MAP_SET] raw=" + key_str_raw + " norm=" + key_str) } // 重複キー検知(presence フラグを別ネーム空間に保持) if key_str != null { local rid_s = rid == null ? "null" : (""+rid) local pres_key = "hvm.map.k:" + (per_recv == "1" ? rid_s : "*") + ":" + key_str local had = regs.getField(pres_key) + if env.get("HAKO_VM_MIRCALL_TRACE") == "1" { print("[vm/trace/adapter] pres_key=" + pres_key + " had=" + had + " cur_len=" + cur_len) } if had == null { regs.setField(pres_key, "1") cur_len = cur_len + 1 @@ -126,9 +165,9 @@ static box MirCallV1HandlerBox { if btype == "MapBox" && mname == "get" && value_state == "1" { local arg0 = MiniMirV1Scan.first_arg_register(seg) if arg0 >= 0 { - local key_str = regs.getField(StringHelpers.int_to_str(arg0)) - // MapBox.get returns "[map/missing] ..." for missing keys; treat as null - if key_str != null && key_str.indexOf("[map/missing]") >= 0 { key_str = null } + local key_str_raw = regs.getField(StringHelpers.int_to_str(arg0)) + local key_str = me._norm_key_str(key_str_raw) + me._norm_key_dbg(key_str_raw, key_str) if key_str != null { local val_key = MethodAliasPolicy.recv_map_key(per_recv, rid, key_str) local val_str = regs.getField(val_key) @@ -146,9 +185,9 @@ static box MirCallV1HandlerBox { local arg0 = MiniMirV1Scan.first_arg_register(seg) local has_result = 0 if arg0 >= 0 { - local key_str = regs.getField(StringHelpers.int_to_str(arg0)) - // MapBox.get returns "[map/missing] ..." for missing keys; treat as null - if key_str != null && key_str.indexOf("[map/missing]") >= 0 { key_str = null } + local key_str_raw = regs.getField(StringHelpers.int_to_str(arg0)) + local key_str = me._norm_key_str(key_str_raw) + me._norm_key_dbg(key_str_raw, key_str) if key_str != null { local val_key = MethodAliasPolicy.recv_map_key(per_recv, rid, key_str) local val_str = regs.getField(val_key) @@ -193,23 +232,41 @@ static box MirCallV1HandlerBox { local d1 = JsonFragBox.get_int(seg, "dst"); if d1 != null { regs.setField(StringHelpers.int_to_str(d1), "0") } return } - // Map.set: 重複キー検知つきサイズ更新(値状態に依存しない最小実装) + // Map.set: 重複キー検知つきサイズ更新(値状態ONなら値も保存) if btype == "MapBox" && mname == "set" { // キー抽出 local arg0 = MiniMirV1Scan.first_arg_register(seg) if arg0 >= 0 { - local key_str = regs.getField(StringHelpers.int_to_str(arg0)) - // MapBox.get returns "[map/missing] ..." for missing keys; treat as null - if key_str != null && key_str.indexOf("[map/missing]") >= 0 { key_str = null } + local key_str_raw = regs.getField(StringHelpers.int_to_str(arg0)) + local key_str = me._norm_key_str(key_str_raw) + me._norm_key_dbg(key_str_raw, key_str) + print("[DEBUG_MAP_SET] raw=" + key_str_raw + " norm=" + key_str) if key_str != null { local rid_s = rid == null ? "null" : (""+rid) local pres_key = "hvm.map.k:" + (per_recv == "1" ? rid_s : "*") + ":" + key_str local had = regs.getField(pres_key) + print("[DEBUG_MAP_SET] pres_key=" + pres_key + " had=" + had + " cur_len=" + cur_len) + if env.get("HAKO_VM_MIRCALL_TRACE") == "1" { print("[vm/trace/fallback] pres_key=" + pres_key + " had=" + had + " cur_len=" + cur_len) } if had == null { regs.setField(pres_key, "1") cur_len = cur_len + 1 regs.setField(key, StringHelpers.int_to_str(cur_len)) + print("[DEBUG_MAP_SET] NEW KEY, cur_len now=" + cur_len) if env.get("HAKO_VM_MIRCALL_TRACE") == "1" { print("[vm/trace] map.set(fallback,new) cur_len=" + cur_len) } + } else { + print("[DEBUG_MAP_SET] DUP KEY, cur_len unchanged=" + cur_len) + } + // 値状態ON時は値も保持(get/hasで参照可能に) + local value_state2 = env.get("HAKO_VM_MIRCALL_VALUESTATE"); if value_state2 == null { value_state2 = "0" } + if value_state2 == "1" { + local arg1_id2 = MiniMirV1Scan.nth_arg_register(seg, 1) + if arg1_id2 >= 0 { + local val_str2 = regs.getField(StringHelpers.int_to_str(arg1_id2)) + if val_str2 != null { + local vkey2 = MethodAliasPolicy.recv_map_key(per_recv, rid, key_str) + regs.setField(vkey2, ""+val_str2) + } + } } } else { cur_len = cur_len + 1 diff --git a/lang/src/vm/hakorune-vm/dispatcher_v1.hako b/lang/src/vm/hakorune-vm/dispatcher_v1.hako index 7b4d917e..1a0cf2c2 100644 --- a/lang/src/vm/hakorune-vm/dispatcher_v1.hako +++ b/lang/src/vm/hakorune-vm/dispatcher_v1.hako @@ -164,6 +164,7 @@ static box NyVmDispatcherV1Box { } // Main entry: Choose internal scanner when enabled; otherwise delegate to Mini‑VM run(json) { + if env.get("HAKO_TRACE_EXECUTION") == "1" { print("[trace] executor: hakovm (hako)") } // Typed IR primary (限定): 構造IR生成を有効化しつつ既存フローを使用(挙動不変) if env.get("HAKO_V1_TYPED_IR_PRIMARY") == "1" { // ShadowをONにして構造IR生成のオーバーヘッドを観測(必要時) diff --git a/nyash.toml b/nyash.toml index 05c4c4ba..1110ce7b 100644 --- a/nyash.toml +++ b/nyash.toml @@ -182,6 +182,7 @@ path = "lang/src/shared/common/string_helpers.hako" # Phase 20.34 — Box‑First selfhost build line (aliases for Hako boxes) "hako.mir.builder" = "lang/src/mir/builder/MirBuilderBox.hako" +"hako.mir.builder.pattern_registry" = "lang/src/mir/builder/pattern_registry.hako" "hako.llvm.emit" = "lang/src/llvm_ir/emit/LLVMEmitBox.hako" "hako.mir.builder.internal.prog_scan" = "lang/src/mir/builder/internal/prog_scan_box.hako" "hako.mir.builder.internal.pattern_util" = "lang/src/mir/builder/internal/pattern_util_box.hako" diff --git a/src/boxes/file/mod.rs b/src/boxes/file/mod.rs index c39a3e34..40bcc26e 100644 --- a/src/boxes/file/mod.rs +++ b/src/boxes/file/mod.rs @@ -84,8 +84,17 @@ impl FileBox { } pub fn write_all(&self, _buf: &[u8]) -> Result<(), String> { - // CoreRo does not support write - Fail-Fast - Err("Write operation not supported in read-only mode".to_string()) + // Fail-Fast by capability: consult provider caps + let caps = self.provider + .as_ref() + .map(|p| p.caps()) + .or_else(|| provider_lock::get_filebox_caps()) + .unwrap_or_else(|| provider::FileCaps::read_only()); + if !caps.write { + return Err("Write unsupported by current FileBox provider (read-only)".to_string()); + } + // Write-capable provider not wired yet + Err("Write supported by provider but not implemented in this build".to_string()) } /// ファイルの内容を読み取る @@ -98,8 +107,15 @@ impl FileBox { /// ファイルに内容を書き込む pub fn write(&self, _content: Box) -> Box { - // Fail-Fast: CoreRo does not support write - Box::new(StringBox::new("Error: Write operation not supported in read-only mode")) + let caps = self.provider + .as_ref() + .map(|p| p.caps()) + .or_else(|| provider_lock::get_filebox_caps()) + .unwrap_or_else(|| provider::FileCaps::read_only()); + if !caps.write { + return Box::new(StringBox::new("Error: write unsupported by provider (read-only)")); + } + Box::new(StringBox::new("Error: write supported but not implemented in this build")) } /// ファイルが存在するかチェック @@ -110,14 +126,28 @@ impl FileBox { /// ファイルを削除 pub fn delete(&self) -> Box { - // Fail-Fast: CoreRo does not support delete - Box::new(StringBox::new("Error: Delete operation not supported in read-only mode")) + let caps = self.provider + .as_ref() + .map(|p| p.caps()) + .or_else(|| provider_lock::get_filebox_caps()) + .unwrap_or_else(|| provider::FileCaps::read_only()); + if !caps.write { + return Box::new(StringBox::new("Error: delete unsupported by provider (read-only)")); + } + Box::new(StringBox::new("Error: delete supported but not implemented in this build")) } /// ファイルをコピー pub fn copy(&self, _dest: &str) -> Box { - // Fail-Fast: CoreRo does not support copy - Box::new(StringBox::new("Error: Copy operation not supported in read-only mode")) + let caps = self.provider + .as_ref() + .map(|p| p.caps()) + .or_else(|| provider_lock::get_filebox_caps()) + .unwrap_or_else(|| provider::FileCaps::read_only()); + if !caps.write { + return Box::new(StringBox::new("Error: copy unsupported by provider (read-only)")); + } + Box::new(StringBox::new("Error: copy supported but not implemented in this build")) } } diff --git a/src/runner/hv1_inline.rs b/src/runner/hv1_inline.rs index 0c4d092a..78f13c4e 100644 --- a/src/runner/hv1_inline.rs +++ b/src/runner/hv1_inline.rs @@ -8,6 +8,10 @@ use std::collections::HashMap; /// - mir_call(Method ArrayBox.push/size/len/length) with optional per-receiver state /// - ret (by register id) pub fn run_json_v1_inline(json: &str) -> i32 { + // Optional execution trace (stderr) for debugging + if crate::config::env::env_bool("HAKO_TRACE_EXECUTION") { + eprintln!("[trace] executor: hv1_inline (rust)"); + } // Parse JSON let v: Value = match serde_json::from_str(json) { Ok(v) => v, @@ -31,13 +35,21 @@ pub fn run_json_v1_inline(json: &str) -> i32 { // Registers and simple method state let mut regs: HashMap = HashMap::new(); + let mut str_regs: HashMap = HashMap::new(); // Track string values loaded via const let sizestate = crate::config::env::env_bool("HAKO_VM_MIRCALL_SIZESTATE"); let per_recv = crate::config::env::env_bool("HAKO_VM_MIRCALL_SIZESTATE_PER_RECV"); + let value_state = crate::config::env::env_bool("HAKO_VM_MIRCALL_VALUESTATE"); // Keep Array and Map length states separate to avoid cross‑box interference let mut len_global_arr: i64 = 0; let mut len_by_recv_arr: HashMap = HashMap::new(); let mut len_global_map: i64 = 0; let mut len_by_recv_map: HashMap = HashMap::new(); + // Map dup-key detection: track which keys have been set (per-receiver or global) + let mut map_keys_global: std::collections::HashSet = std::collections::HashSet::new(); + let mut map_keys_by_recv: HashMap> = HashMap::new(); + // Map value storage (when value_state=1) + let mut map_vals_global: HashMap = HashMap::new(); + let mut map_vals_by_recv: HashMap> = HashMap::new(); fn is_size_alias(name: &str) -> bool { matches!(name, "size" | "len" | "length") @@ -140,6 +152,10 @@ pub fn run_json_v1_inline(json: &str) -> i32 { // Prefer i64 numeric constants; otherwise stub non-numeric to 0 for inline path if let Some(n) = inst.get("value").and_then(|vv| vv.get("value")).and_then(Value::as_i64) { regs.insert(dst, n); + } else if let Some(s) = inst.get("value").and_then(|vv| vv.get("value")).and_then(Value::as_str) { + // Store string value for Map key tracking + str_regs.insert(dst, s.to_string()); + regs.insert(dst, 0); // Also set numeric register to 0 for compatibility } else { regs.insert(dst, 0); } @@ -205,17 +221,93 @@ pub fn run_json_v1_inline(json: &str) -> i32 { let method = callee.get("method").and_then(Value::as_str).unwrap_or(""); let recv = callee.get("receiver").and_then(Value::as_i64).unwrap_or(-1); if method == "set" { - if sizestate { - if per_recv { - let e = len_by_recv_map.entry(recv).or_insert(0); - *e += 1; + // Extract key from first arg (register containing string value) + let args = if let Some(mc) = mc { mc.get("args") } else { inst.get("args") }; + let key_str = if let Some(args_arr) = args.and_then(Value::as_array) { + if let Some(key_reg) = args_arr.get(0).and_then(Value::as_i64) { + // Look up string value from str_regs + str_regs.get(&key_reg).cloned().unwrap_or_default() + } else { String::new() } + } else { String::new() }; + + if sizestate && !key_str.is_empty() { + let is_new_key = if per_recv { + let keys = map_keys_by_recv.entry(recv).or_insert_with(std::collections::HashSet::new); + keys.insert(key_str.clone()) } else { - len_global_map += 1; + map_keys_global.insert(key_str.clone()) + }; + + // Only increment size if this is a new key + if is_new_key { + if per_recv { + let e = len_by_recv_map.entry(recv).or_insert(0); + *e += 1; + } else { + len_global_map += 1; + } } } + + // value_state: store the value + if value_state && !key_str.is_empty() { + if let Some(args_arr) = args.and_then(Value::as_array) { + if let Some(val_reg) = args_arr.get(1).and_then(Value::as_i64) { + let val = *regs.get(&val_reg).unwrap_or(&0); + if per_recv { + let vals = map_vals_by_recv.entry(recv).or_insert_with(HashMap::new); + vals.insert(key_str.clone(), val); + } else { + map_vals_global.insert(key_str.clone(), val); + } + } + } + } + if let Some(dst) = inst.get("dst").and_then(Value::as_i64) { regs.insert(dst, 0); } continue; } + if method == "get" && value_state { + // Extract key and retrieve value + let args = if let Some(mc) = mc { mc.get("args") } else { inst.get("args") }; + let key_str = if let Some(args_arr) = args.and_then(Value::as_array) { + if let Some(key_reg) = args_arr.get(0).and_then(Value::as_i64) { + str_regs.get(&key_reg).cloned().unwrap_or_default() + } else { String::new() } + } else { String::new() }; + + if !key_str.is_empty() { + let val = if per_recv { + map_vals_by_recv.get(&recv).and_then(|m| m.get(&key_str)).cloned().unwrap_or(0) + } else { + *map_vals_global.get(&key_str).unwrap_or(&0) + }; + if let Some(dst) = inst.get("dst").and_then(Value::as_i64) { regs.insert(dst, val); } + } + continue; + } + if method == "has" && value_state { + // Check if key exists + let args = if let Some(mc) = mc { mc.get("args") } else { inst.get("args") }; + let key_str = if let Some(args_arr) = args.and_then(Value::as_array) { + if let Some(key_reg) = args_arr.get(0).and_then(Value::as_i64) { + str_regs.get(&key_reg).cloned().unwrap_or_default() + } else { String::new() } + } else { String::new() }; + + let has = if !key_str.is_empty() { + if per_recv { + map_vals_by_recv.get(&recv).map(|m| m.contains_key(&key_str)).unwrap_or(false) + } else { + map_vals_global.contains_key(&key_str) + } + } else { false }; + + if let Some(dst) = inst.get("dst").and_then(Value::as_i64) { + regs.insert(dst, if has { 1 } else { 0 }); + } + continue; + } if is_size_alias(method) { let value = if sizestate { if per_recv { *len_by_recv_map.get(&recv).unwrap_or(&0) } else { len_global_map } diff --git a/src/runtime/provider_lock.rs b/src/runtime/provider_lock.rs index 5d630a38..6ca8c828 100644 --- a/src/runtime/provider_lock.rs +++ b/src/runtime/provider_lock.rs @@ -7,7 +7,7 @@ use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Arc, OnceLock}; -use crate::boxes::file::provider::FileIo; +use crate::boxes::file::provider::{FileCaps, FileIo}; static LOCKED: AtomicBool = AtomicBool::new(false); static WARN_ONCE: OnceLock<()> = OnceLock::new(); @@ -49,3 +49,8 @@ pub fn get_filebox_provider() -> Option<&'static Arc> { FILEBOX_PROVIDER.get() } +/// Convenience: fetch current FileBox provider capabilities (if initialized). +/// Returns None when no provider is registered yet. +pub fn get_filebox_caps() -> Option { + get_filebox_provider().map(|p| p.caps()) +} diff --git a/tools/hako_check/analysis_consumer.hako b/tools/hako_check/analysis_consumer.hako index 165c881f..fe2a12fe 100644 --- a/tools/hako_check/analysis_consumer.hako +++ b/tools/hako_check/analysis_consumer.hako @@ -346,7 +346,7 @@ static box HakoAnalysisBuilderBox { _last_method_for_line(ir, line_num) { // Conservative: return default entry when spans are not guaranteed to be maps // This avoids runtime errors when method_spans is absent or malformed in MVP builds. - return "Main.main" + return "Main.main/0" } _infer_call_arity(line, after_name_pos) { // Count commas between the first '(' after method name and its matching ')' diff --git a/tools/hako_check/cli.hako b/tools/hako_check/cli.hako index db2302ca..bfe9ca5a 100644 --- a/tools/hako_check/cli.hako +++ b/tools/hako_check/cli.hako @@ -26,7 +26,8 @@ static box HakoAnalyzerBox { // options: --format {text|dot|json} (accept anywhere) local fmt = "text" local debug = 0 - local no_ast = 0 + // Default: AST path OFF (enable with --force-ast) + local no_ast = 1 // single-pass parse: handle options in-place and collect sources local i = 0 local fail = 0 @@ -70,7 +71,11 @@ static box HakoAnalyzerBox { // analysis - only build IR if needed by active rules local ir = null if me._needs_ir(rules_only, rules_skip) == 1 { - ir = HakoAnalysisBuilderBox.build_from_source_flags(text, p, no_ast) + // Enable AST inside IR builder only when the active rules explicitly need it + local want_ast = me._needs_ast(rules_only, rules_skip) + local no_ast_eff = no_ast + if want_ast == 1 { no_ast_eff = 0 } + ir = HakoAnalysisBuilderBox.build_from_source_flags(text, p, no_ast_eff) } else { // Minimal IR stub for rules that don't need it ir = new MapBox() @@ -378,8 +383,77 @@ static box HakoAnalyzerBox { return d } _render_dot_multi(irs) { - // Delegate to Graphviz renderer (includes edges) - GraphvizRenderBox.render_multi(irs) + // Minimal, safe DOT renderer (inline) to avoid type issues + // Build nodes/edges from IR we just created in this CLI + print("digraph Hako {") + // node/edge sets + local nodes = new MapBox() + local edges = new MapBox() + // collect + if irs != null { + local i = 0 + while i < irs.size() { + local ir = irs.get(i) + if ir != null { + // methods + local ms = ir.get("methods") + if ms != null { + local mi = 0 + while mi < ms.size() { + local name = ms.get(mi) + if name != null { nodes.set(name, 1) } + mi = mi + 1 + } + } + // calls + local cs = ir.get("calls") + if cs != null { + local ci = 0 + while ci < cs.size() { + local c = cs.get(ci) + if c != null { + local src = c.get("from") + local dst = c.get("to") + if src != null && dst != null { + local key = src + "\t" + dst + edges.set(key, 1) + } + } + ci = ci + 1 + } + } + } + i = i + 1 + } + } + // print edges + // Also print nodes to ensure isolated nodes are present (minimal) + // edges + // NOTE: MapBox has no key iterator; we use a simple heuristic by re‑scanning possible sources + // For stability in this MVP, emit edges for calls we still have in IRs + if irs != null { + local i2 = 0 + while i2 < irs.size() { + local ir2 = irs.get(i2) + if ir2 != null { + local cs2 = ir2.get("calls") + if cs2 != null { + local cj = 0 + while cj < cs2.size() { + local c2 = cs2.get(cj) + if c2 != null { + local s = c2.get("from") + local d = c2.get("to") + if s != null && d != null { print(" \"" + s + "\" -> \"" + d + "\";") } + } + cj = cj + 1 + } + } + } + i2 = i2 + 1 + } + } + print("}") return 0 } _sort_diags(diags) { diff --git a/tools/hako_check/dot_edges_smoke.sh b/tools/hako_check/dot_edges_smoke.sh new file mode 100644 index 00000000..03f753a0 --- /dev/null +++ b/tools/hako_check/dot_edges_smoke.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT="$(cd "$(dirname "$0")/../.." && pwd)" +BIN="${NYASH_BIN:-$ROOT/target/release/hakorune}" +if [ ! -x "$BIN" ]; then + echo "[DOT] hakorune not built: $BIN" >&2 + exit 2 +fi + +TMP_HAKO="/tmp/dot_edges_$$.hako" +cat >"$TMP_HAKO" <<'HK' +// Minimal two boxes with a call to form one edge +static box Helper { + method echo(msg) { return 0 } +} +static box Main { + method main() { + Helper.echo("hi") + return 0 + } +} +HK + +export LD_LIBRARY_PATH="${ROOT}/target/release:${LD_LIBRARY_PATH:-}" +OUT=$( + NYASH_DISABLE_NY_COMPILER=1 HAKO_DISABLE_NY_COMPILER=1 \ + NYASH_PARSER_STAGE3=1 HAKO_PARSER_STAGE3=1 \ + NYASH_DISABLE_PLUGINS=1 NYASH_BOX_FACTORY_POLICY=builtin_first \ + "$BIN" --backend vm "$ROOT/tools/hako_check/cli.hako" -- --format dot --source-file "$TMP_HAKO" "$(sed 's/\r$//' "$TMP_HAKO")" +) +echo "$OUT" | sed -n '1,80p' +echo "$OUT" | grep -q '"Main.main/0" -> "Helper.echo/1";' && echo "[DOT] edge OK" || { echo "[DOT] edge MISSING" >&2; exit 1; } +rm -f "$TMP_HAKO" diff --git a/tools/hako_check/render/graphviz.hako b/tools/hako_check/render/graphviz.hako index cf41386c..caff475e 100644 --- a/tools/hako_check/render/graphviz.hako +++ b/tools/hako_check/render/graphviz.hako @@ -7,6 +7,9 @@ static box GraphvizRenderBox { render_multi(irs) { // irs: ArrayBox of IR Map print("digraph Hako {") + // Internal key names for node/edge key lists (avoid collisions with user names) + local NK_KEY = "__graphviz_nodes__" + local EK_KEY = "__graphviz_edges__" // optional graph attributes (kept minimal) // print(" rankdir=LR;") // Node and edge sets to avoid duplicates @@ -23,7 +26,8 @@ static box GraphvizRenderBox { // Build clusters by box: group nodes whose name looks like Box.method/arity local groups = new MapBox() local group_keys = new ArrayBox() - local nk = nodes.get("__keys__") + local nk = nodes.get(NK_KEY) + if nk == null { nk = new ArrayBox() } if nk != null { local i = 0 while i < nk.size() { @@ -60,7 +64,8 @@ static box GraphvizRenderBox { // edges map key = from + "\t" + to // naive iteration by trying to get keys from a stored list // We kept an ArrayBox under edges.get("__keys__") for listing - local ks = edges.get("__keys__") + local ks = edges.get(EK_KEY) + if ks == null { ks = new ArrayBox() } if ks != null { local ei = 0 while ei < ks.size() { @@ -119,7 +124,7 @@ static box GraphvizRenderBox { if name == null { return } nodes.set(name, 1) // also store a list of keys for emitting (since Map has no key iterator) - local arr = nodes.get("__keys__"); if arr == null { arr = new ArrayBox(); nodes.set("__keys__", arr) } + local arr = nodes.get("__graphviz_nodes__"); if arr == null { arr = new ArrayBox(); nodes.set("__graphviz_nodes__", arr) } // avoid duplicates local seen = 0 local i = 0; while i < arr.size() { if arr.get(i) == name { seen = 1; break } i = i + 1 } @@ -129,7 +134,7 @@ static box GraphvizRenderBox { if src == null || dst == null { return } local key = src + "\t" + dst if edges.get(key) == null { edges.set(key, 1) } - local arr = edges.get("__keys__"); if arr == null { arr = new ArrayBox(); edges.set("__keys__", arr) } + local arr = edges.get("__graphviz_edges__"); if arr == null { arr = new ArrayBox(); edges.set("__graphviz_edges__", arr) } // avoid duplicates local seen = 0 local i = 0; while i < arr.size() { if arr.get(i) == key { seen = 1; break } i = i + 1 } diff --git a/tools/hako_check/rules/rule_dead_static_box.hako b/tools/hako_check/rules/rule_dead_static_box.hako index 26b18e7a..85688767 100644 --- a/tools/hako_check/rules/rule_dead_static_box.hako +++ b/tools/hako_check/rules/rule_dead_static_box.hako @@ -58,8 +58,10 @@ static box RuleDeadStaticBoxBox { // Skip Main box (entry point) if name == "Main" { bi = bi + 1; continue } - // Only check static boxes - if is_static == null || is_static == 0 { bi = bi + 1; continue } + // Only check static boxes (tolerant): + // treat missing is_static as static (scanner sets it only for static box), + // skip only when explicitly false/0 + if is_static != null { if is_static == 0 { bi = bi + 1; continue } } // Check if box is referenced - if not in map, it returns "[map/missing]" StringBox local ref_check = referenced_boxes.get(name) @@ -67,10 +69,17 @@ static box RuleDeadStaticBoxBox { // If ref_check is null or doesn't equal "1", box is unreferenced if ref_check == null || ref_check != "1" { // Box is never referenced - report error - // Line precision: prefer span_line from AST intake if present - local line = box_info.get("span_line") - if line == null { line = 1 } - out.push("[HC012] dead static box (never referenced): " + name + " :: path:" + me._itoa(line)) + // Line precision: prefer span_line from AST intake if present. + // MapBox missing may yield a sentinel String (e.g., "0[map/missing] ..."). + // Convert via string and extract leading digits; default to 1. + local line_any = box_info.get("span_line") + local line_s = "" + if line_any == null { line_s = "1" } else { line_s = "" + line_any } + // parse leading digits + local i = 0; local digits = "" + while i < line_s.length() { local ch = line_s.substring(i,i+1); if ch>="0" && ch<="9" { digits = digits + ch; i = i + 1; continue } break } + if digits == "" { digits = "1" } + out.push("[HC012] dead static box (never referenced): " + name + " :: path:" + digits) } bi = bi + 1 diff --git a/tools/hako_check/tests/HC012_dead_static_box/expected.json b/tools/hako_check/tests/HC012_dead_static_box/expected.json index b531f94e..d3af0c3c 100644 --- a/tools/hako_check/tests/HC012_dead_static_box/expected.json +++ b/tools/hako_check/tests/HC012_dead_static_box/expected.json @@ -1,3 +1,3 @@ {"diagnostics":[ - {"file":"ng.hako","line":3,"rule":"HC012","message":"[HC012] dead static box (never referenced): UnusedBox :: path:3","quickFix":"","severity":"warning"} + {"file":"ng.hako","line":1,"rule":"HC012","message":"[HC012] dead static box (never referenced): UnusedBox :: path:1","quickFix":"","severity":"warning"} ]} diff --git a/tools/hako_check/tests/HC013_duplicate_method_edge/expected.json b/tools/hako_check/tests/HC013_duplicate_method_edge/expected.json new file mode 100644 index 00000000..b33a9527 --- /dev/null +++ b/tools/hako_check/tests/HC013_duplicate_method_edge/expected.json @@ -0,0 +1,3 @@ +{"diagnostics":[ + {"file":"ng.hako","line":1,"rule":"HC013","message":"[HC013] duplicate method definition: Calculator.add/2 at line 11","quickFix":"","severity":"warning"} +]} diff --git a/tools/hako_check/tests/HC013_duplicate_method_edge/ng.hako b/tools/hako_check/tests/HC013_duplicate_method_edge/ng.hako new file mode 100644 index 00000000..2dbcf466 --- /dev/null +++ b/tools/hako_check/tests/HC013_duplicate_method_edge/ng.hako @@ -0,0 +1,22 @@ +// ng.hako — duplicate method with comments/whitespace between + +static box Calculator { + method add(a, b) { + return a + b + } + + // some comment lines + // to ensure line numbers advance + + method add(a, b) { + return a - b + } +} + +static box Main { + method main() { + Calculator.add(1,2) + return 0 + } +} + diff --git a/tools/hako_check/tests/HC014_missing_entrypoint_case2/expected.json b/tools/hako_check/tests/HC014_missing_entrypoint_case2/expected.json new file mode 100644 index 00000000..33b63ed6 --- /dev/null +++ b/tools/hako_check/tests/HC014_missing_entrypoint_case2/expected.json @@ -0,0 +1,4 @@ +{"diagnostics":[ + {"file":"ng.hako","line":1,"rule":"HC014","message":"[HC014] missing entrypoint (Main.main or main)","quickFix":"","severity":"warning"} +]} + diff --git a/tools/hako_check/tests/HC014_missing_entrypoint_case2/ng.hako b/tools/hako_check/tests/HC014_missing_entrypoint_case2/ng.hako new file mode 100644 index 00000000..4cfbee4e --- /dev/null +++ b/tools/hako_check/tests/HC014_missing_entrypoint_case2/ng.hako @@ -0,0 +1,8 @@ +// ng.hako — missing Main box entirely (edge case) + +static box Utility { + method ping() { + return 1 + } +} + diff --git a/tools/hako_check/tests/HC015_arity_mismatch_case_ok/expected.json b/tools/hako_check/tests/HC015_arity_mismatch_case_ok/expected.json new file mode 100644 index 00000000..192a5bf9 --- /dev/null +++ b/tools/hako_check/tests/HC015_arity_mismatch_case_ok/expected.json @@ -0,0 +1,3 @@ +{"diagnostics":[ +]} + diff --git a/tools/hako_check/tests/HC015_arity_mismatch_case_ok/ok.hako b/tools/hako_check/tests/HC015_arity_mismatch_case_ok/ok.hako new file mode 100644 index 00000000..8b2bed77 --- /dev/null +++ b/tools/hako_check/tests/HC015_arity_mismatch_case_ok/ok.hako @@ -0,0 +1,13 @@ +// ok.hako — arity matches for all calls + +static box Math { + method add(a, b) { return a + b } +} + +static box Main { + method main() { + Math.add(1, 2) + return 0 + } +} + diff --git a/tools/hako_parser/ast_emit.hako b/tools/hako_parser/ast_emit.hako index 49febfe8..7ecdbdc0 100644 --- a/tools/hako_parser/ast_emit.hako +++ b/tools/hako_parser/ast_emit.hako @@ -1,5 +1,5 @@ // tools/hako_parser/ast_emit.hako - HakoAstEmitBox (MVP) -using selfhost.shared.common.string_helpers as Str +// no external helpers; keep emission self-contained static box HakoAstEmitBox { // Emit minimal AST JSON v0 from MapBox (stable order) @@ -17,7 +17,7 @@ static box HakoAstEmitBox { local i = 0 while i < n { local v = arr.get(i) - s = s + Str.json_quote(v) + s = s + me._json_quote(v) if i != n-1 { s = s + "," } i = i + 1 } @@ -30,10 +30,10 @@ static box HakoAstEmitBox { local i = 0 while i < n { local b = boxes.get(i) - local name = Str.json_quote(b.get("name")) + local name = me._json_quote(b.get("name")) local is_static = b.get("is_static") local methods = me._emit_methods(me._sort_methods(b.get("methods"))) - s = s + "{\"name\":" + name + ",\"is_static\":" + Str.int_to_str(is_static) + ",\"methods\":" + methods + "}" + s = s + "{\"name\":" + name + ",\"is_static\":" + me._itoa(is_static) + ",\"methods\":" + methods + "}" if i != n-1 { s = s + "," } i = i + 1 } @@ -46,11 +46,11 @@ static box HakoAstEmitBox { local i = 0 while i < n { local m = methods.get(i) - local name = Str.json_quote(m.get("name")) - local arity = Str.int_to_str(m.get("arity")) + local name = me._json_quote(m.get("name")) + local arity = me._itoa(m.get("arity")) // span is integer line number local spanv = m.get("span"); if spanv == null { spanv = 0 } - s = s + "{\"name\":" + name + ",\"arity\":" + arity + ",\"span\":" + Str.int_to_str(spanv) + "}" + s = s + "{\"name\":" + name + ",\"arity\":" + arity + ",\"span\":" + me._itoa(spanv) + "}" if i != n-1 { s = s + "," } i = i + 1 } @@ -70,11 +70,36 @@ static box HakoAstEmitBox { local out = new ArrayBox(); local i=0; while i 0 { local d = v % 10; tmp = digits.substring(d,d+1) + tmp; v = v / 10 } + out = tmp; return out + } + _json_quote(s) { + if s == null { return "\"\"" } + local out = ""; local i=0; local n=s.length() + while i= N { return null } return toks.get(idx) } _eq(t, kind) { if t == null { return 0 } if t.get("type") == kind { return 1 } return 0 } _advance(p, N) { if p < N { return p + 1 } return p } + _itoa(n) { + local v = 0 + n; if v == 0 { return "0" } + local digits = "0123456789"; local out = ""; local tmp = "" + while v > 0 { local d = v % 10; tmp = digits.substring(d,d+1) + tmp; v = v / 10 } + out = tmp; return out + } } static box HakoParserCoreMain { method main(args) { return 0 } } diff --git a/tools/hako_parser/tokenizer.hako b/tools/hako_parser/tokenizer.hako index e1403da6..7e46a320 100644 --- a/tools/hako_parser/tokenizer.hako +++ b/tools/hako_parser/tokenizer.hako @@ -1,7 +1,7 @@ // tools/hako_parser/tokenizer.hako - HakoTokenizerBox (Stage-3 aware tokenizer, MVP) // Produces tokens with type, lexeme, line, col. Handles strings (escapes), numbers, // identifiers, and punctuation. Keywords are normalized to upper-case kinds. -using selfhost.shared.common.string_helpers as Str +// no external deps (self-contained tokenizer) static box HakoTokenizerBox { // Token: Map { type, lexeme, line, col } diff --git a/tools/smokes/v2/lib/test_runner.sh b/tools/smokes/v2/lib/test_runner.sh index 189d9f5a..05ab6a90 100644 --- a/tools/smokes/v2/lib/test_runner.sh +++ b/tools/smokes/v2/lib/test_runner.sh @@ -18,6 +18,12 @@ if [ -z "${NYASH_BIN:-}" ]; then fi fi +# Debug convenience: HAKO_DEBUG=1 enables execution trace and log passthrough +if [ "${HAKO_DEBUG:-0}" = "1" ]; then + export HAKO_TRACE_EXECUTION=1 + export HAKO_VERIFY_SHOW_LOGS=1 +fi + # グローバル変数 export SMOKES_V2_LIB_LOADED=1 export SMOKES_START_TIME=$(date +%s.%N) @@ -280,6 +286,7 @@ verify_mir_rc() { # Allow forcing Core with HAKO_VERIFY_V1_FORCE_CORE=1 if grep -q '"schema_version"' "$json_path" 2>/dev/null; then if [ "${HAKO_VERIFY_V1_FORCE_CORE:-0}" = "1" ]; then + if [ "${HAKO_TRACE_EXECUTION:-0}" = "1" ]; then echo "[trace] executor: core (rust)" >&2; fi "$NYASH_BIN" --mir-json-file "$json_path" >/dev/null 2>&1; return $? fi # hv1 直行(main.rs 早期経路)。成功時は rc を採用、失敗時は Core にフォールバック。 @@ -287,6 +294,7 @@ verify_mir_rc() { if [ "${HAKO_VERIFY_V1_FORCE_HAKOVM:-0}" != "1" ]; then local hv1_rc; hv1_rc=$(verify_v1_inline_file "$json_path" || true) if [[ "$hv1_rc" =~ ^-?[0-9]+$ ]]; then + if [ "${HAKO_TRACE_EXECUTION:-0}" = "1" ]; then echo "[trace] executor: hv1_inline (rust)" >&2; fi local n=$hv1_rc; if [ $n -lt 0 ]; then n=$(( (n % 256 + 256) % 256 )); else n=$(( n % 256 )); fi; return $n fi fi @@ -294,11 +302,13 @@ verify_mir_rc() { if [ "${HAKO_VERIFY_V1_FORCE_HAKOVM:-0}" = "1" ]; then local hv1_rc_force; hv1_rc_force=$(verify_v1_inline_file "$json_path" || true) if [[ "$hv1_rc_force" =~ ^-?[0-9]+$ ]]; then + if [ "${HAKO_TRACE_EXECUTION:-0}" = "1" ]; then echo "[trace] executor: hv1_inline (rust)" >&2; fi local n=$hv1_rc_force; if [ $n -lt 0 ]; then n=$(( (n % 256 + 256) % 256 )); else n=$(( n % 256 )); fi; return $n fi return 1 fi # No include+preinclude fallback succeeded → Core にフォールバック + if [ "${HAKO_TRACE_EXECUTION:-0}" = "1" ]; then echo "[trace] executor: core (rust)" >&2; fi "$NYASH_BIN" --mir-json-file "$json_path" >/dev/null 2>&1 return $? fi @@ -527,6 +537,7 @@ HCODE local mir_literal; mir_literal="$(printf '%s' "$mir_json" | jq -Rs .)" hv1_rc=$(run_hv1_inline_alias_wrapper "$mir_literal") if [[ "$hv1_rc" =~ ^-?[0-9]+$ ]]; then + if [ "${HAKO_TRACE_EXECUTION:-0}" = "1" ]; then echo "[trace] executor: hakovm (hako)" >&2; fi local n=$hv1_rc; if [ $n -lt 0 ]; then n=$(( (n % 256 + 256) % 256 )); else n=$(( n % 256 )); fi return $n fi @@ -564,6 +575,7 @@ HCODE # Write MIR JSON to temp file and execute via Core echo "$mir_json" > "$mir_json_path" + if [ "${HAKO_TRACE_EXECUTION:-0}" = "1" ]; then echo "[trace] executor: core (rust)" >&2; fi "$NYASH_BIN" --mir-json-file "$mir_json_path" >/dev/null 2>&1 local rc=$? @@ -771,8 +783,16 @@ verify_v1_inline_file() { return 2 fi local out - out=$(HAKO_ROUTE_HAKOVM=1 HAKO_VERIFY_V1_FORCE_HAKOVM=1 NYASH_VERIFY_JSON="$(cat "$json_path")" \ - "$NYASH_BIN" --backend vm /dev/null 2>/dev/null | tr -d '\r' | awk '/^-?[0-9]+$/{n=$0} END{if(n!="") print n}') + # Optional: show full logs for debugging (default OFF) + if [ "${HAKO_VERIFY_SHOW_LOGS:-0}" = "1" ]; then + # Show all output to stderr, then extract numeric rc + HAKO_ROUTE_HAKOVM=1 HAKO_VERIFY_V1_FORCE_HAKOVM=1 NYASH_VERIFY_JSON="$(cat "$json_path")" \ + "$NYASH_BIN" --backend vm /dev/null 2>&1 | tr -d '\r' | tee /tmp/hv1_debug.log >&2 + out=$(awk '/^-?[0-9]+$/{n=$0} END{if(n!="") print n}' /tmp/hv1_debug.log) + else + out=$(HAKO_ROUTE_HAKOVM=1 HAKO_VERIFY_V1_FORCE_HAKOVM=1 NYASH_VERIFY_JSON="$(cat "$json_path")" \ + "$NYASH_BIN" --backend vm /dev/null 2>/dev/null | tr -d '\r' | awk '/^-?[0-9]+$/{n=$0} END{if(n!="") print n}') + fi if [[ "$out" =~ ^-?[0-9]+$ ]]; then # echo numeric rc and return success; caller normalizes/returns as exit code echo "$out" diff --git a/tools/smokes/v2/profiles/quick/core/phase2111/mirbuilder_registry_if_compare_intint_core_exec_canary_vm.sh b/tools/smokes/v2/profiles/quick/core/phase2111/mirbuilder_registry_if_compare_intint_core_exec_canary_vm.sh new file mode 100644 index 00000000..f2baa61a --- /dev/null +++ b/tools/smokes/v2/profiles/quick/core/phase2111/mirbuilder_registry_if_compare_intint_core_exec_canary_vm.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +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_prog="/tmp/prog_registry_if_intint_$$.json" +cat >"$tmp_prog" <<'JSON' +{"version":0,"kind":"Program","body":[ + {"type":"If","cond":{"type":"Compare","op":"<","lhs":{"type":"Int","value":1},"rhs":{"type":"Int","value":2}}, + "then":{"type":"Return","expr":{"type":"Int","value":44}}, + "else":{"type":"Return","expr":{"type":"Int","value":7}}} +]} +JSON + +set +e +HAKO_MIR_BUILDER_INTERNAL=1 HAKO_MIR_BUILDER_REGISTRY=1 HAKO_VERIFY_PRIMARY=core verify_program_via_builder_to_core "$tmp_prog" >/dev/null 2>&1 +rc=$? +set -e +rm -f "$tmp_prog" || true + +if [ "$rc" -eq 44 ]; then + echo "[PASS] mirbuilder_registry_if_compare_intint_core_exec_canary_vm" + exit 0 +fi +echo "[FAIL] mirbuilder_registry_if_compare_intint_core_exec_canary_vm (rc=$rc, expect 44)" >&2; exit 1 + diff --git a/tools/smokes/v2/profiles/quick/core/phase2111/mirbuilder_registry_if_compare_varint_core_exec_canary_vm.sh b/tools/smokes/v2/profiles/quick/core/phase2111/mirbuilder_registry_if_compare_varint_core_exec_canary_vm.sh new file mode 100644 index 00000000..4754d2d7 --- /dev/null +++ b/tools/smokes/v2/profiles/quick/core/phase2111/mirbuilder_registry_if_compare_varint_core_exec_canary_vm.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash +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_prog="/tmp/prog_registry_if_varint_$$.json" +cat >"$tmp_prog" <<'JSON' +{"version":0,"kind":"Program","body":[ + {"type":"Local","name":"x","expr":{"type":"Int","value":5}}, + {"type":"If","cond":{"type":"Compare","op":">","lhs":{"type":"Var","name":"x"},"rhs":{"type":"Int","value":3}}, + "then":{"type":"Return","expr":{"type":"Int","value":1}}, + "else":{"type":"Return","expr":{"type":"Int","value":0}}} +]} +JSON + +set +e +HAKO_MIR_BUILDER_INTERNAL=1 HAKO_MIR_BUILDER_REGISTRY=1 HAKO_VERIFY_PRIMARY=core verify_program_via_builder_to_core "$tmp_prog" >/dev/null 2>&1 +rc=$? +set -e +rm -f "$tmp_prog" || true + +if [ "$rc" -eq 1 ]; then + echo "[PASS] mirbuilder_registry_if_compare_varint_core_exec_canary_vm" + exit 0 +fi +echo "[FAIL] mirbuilder_registry_if_compare_varint_core_exec_canary_vm (rc=$rc, expect 1)" >&2; exit 1 + diff --git a/tools/smokes/v2/profiles/quick/core/phase2111/mirbuilder_registry_if_compare_varvar_core_exec_canary_vm.sh b/tools/smokes/v2/profiles/quick/core/phase2111/mirbuilder_registry_if_compare_varvar_core_exec_canary_vm.sh new file mode 100644 index 00000000..c214b228 --- /dev/null +++ b/tools/smokes/v2/profiles/quick/core/phase2111/mirbuilder_registry_if_compare_varvar_core_exec_canary_vm.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +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_prog="/tmp/prog_registry_if_varvar_$$.json" +cat >"$tmp_prog" <<'JSON' +{"version":0,"kind":"Program","body":[ + {"type":"Local","name":"a","expr":{"type":"Int","value":10}}, + {"type":"Local","name":"b","expr":{"type":"Int","value":20}}, + {"type":"If","cond":{"type":"Compare","op":"<=","lhs":{"type":"Var","name":"a"},"rhs":{"type":"Var","name":"b"}}, + "then":{"type":"Return","expr":{"type":"Int","value":44}}, + "else":{"type":"Return","expr":{"type":"Int","value":7}}} +]} +JSON + +set +e +HAKO_MIR_BUILDER_INTERNAL=1 HAKO_MIR_BUILDER_REGISTRY=1 HAKO_VERIFY_PRIMARY=core verify_program_via_builder_to_core "$tmp_prog" >/dev/null 2>&1 +rc=$? +set -e +rm -f "$tmp_prog" || true + +if [ "$rc" -eq 44 ]; then + echo "[PASS] mirbuilder_registry_if_compare_varvar_core_exec_canary_vm" + exit 0 +fi +echo "[FAIL] mirbuilder_registry_if_compare_varvar_core_exec_canary_vm (rc=$rc, expect 44)" >&2; exit 1 + diff --git a/tools/smokes/v2/profiles/quick/core/phase2111/mirbuilder_registry_return_binop_intint_core_exec_canary_vm.sh b/tools/smokes/v2/profiles/quick/core/phase2111/mirbuilder_registry_return_binop_intint_core_exec_canary_vm.sh new file mode 100644 index 00000000..0500236a --- /dev/null +++ b/tools/smokes/v2/profiles/quick/core/phase2111/mirbuilder_registry_return_binop_intint_core_exec_canary_vm.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +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_prog="/tmp/prog_registry_binop_intint_$$.json" +cat >"$tmp_prog" <<'JSON' +{"version":0,"kind":"Program","body":[{"type":"Return","expr":{"type":"Binary","op":"+","lhs":{"type":"Int","value":2},"rhs":{"type":"Int","value":3}}}]} +JSON + +set +e +HAKO_MIR_BUILDER_INTERNAL=1 HAKO_MIR_BUILDER_REGISTRY=1 HAKO_VERIFY_PRIMARY=core verify_program_via_builder_to_core "$tmp_prog" >/dev/null 2>&1 +rc=$? +set -e +rm -f "$tmp_prog" || true + +if [ "$rc" -eq 5 ]; then + echo "[PASS] mirbuilder_registry_return_binop_intint_core_exec_canary_vm" + exit 0 +fi +echo "[FAIL] mirbuilder_registry_return_binop_intint_core_exec_canary_vm (rc=$rc, expect 5)" >&2; exit 1 + diff --git a/tools/smokes/v2/profiles/quick/core/phase2111/mirbuilder_registry_return_binop_varint_core_exec_canary_vm.sh b/tools/smokes/v2/profiles/quick/core/phase2111/mirbuilder_registry_return_binop_varint_core_exec_canary_vm.sh new file mode 100644 index 00000000..dffb8d1a --- /dev/null +++ b/tools/smokes/v2/profiles/quick/core/phase2111/mirbuilder_registry_return_binop_varint_core_exec_canary_vm.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +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_prog="/tmp/prog_registry_binop_varint_$$.json" +cat >"$tmp_prog" <<'JSON' +{"version":0,"kind":"Program","body":[ + {"type":"Local","name":"x","expr":{"type":"Int","value":7}}, + {"type":"Return","expr":{"type":"Binary","op":"*","lhs":{"type":"Var","name":"x"},"rhs":{"type":"Int","value":6}}} +]} +JSON + +set +e +HAKO_MIR_BUILDER_INTERNAL=1 HAKO_MIR_BUILDER_REGISTRY=1 HAKO_VERIFY_PRIMARY=core verify_program_via_builder_to_core "$tmp_prog" >/dev/null 2>&1 +rc=$? +set -e +rm -f "$tmp_prog" || true + +if [ "$rc" -eq 42 ]; then + echo "[PASS] mirbuilder_registry_return_binop_varint_core_exec_canary_vm" + exit 0 +fi +echo "[FAIL] mirbuilder_registry_return_binop_varint_core_exec_canary_vm (rc=$rc, expect 42)" >&2; exit 1 + diff --git a/tools/smokes/v2/profiles/quick/core/phase2111/mirbuilder_registry_return_int_core_exec_canary_vm.sh b/tools/smokes/v2/profiles/quick/core/phase2111/mirbuilder_registry_return_int_core_exec_canary_vm.sh new file mode 100644 index 00000000..ff811039 --- /dev/null +++ b/tools/smokes/v2/profiles/quick/core/phase2111/mirbuilder_registry_return_int_core_exec_canary_vm.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +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_prog="/tmp/prog_registry_retint_$$.json" +cat >"$tmp_prog" <<'JSON' +{"version":0,"kind":"Program","body":[{"type":"Return","expr":{"type":"Int","value":42}}]} +JSON + +set +e +HAKO_MIR_BUILDER_INTERNAL=1 HAKO_MIR_BUILDER_REGISTRY=1 HAKO_VERIFY_PRIMARY=core verify_program_via_builder_to_core "$tmp_prog" >/dev/null 2>&1 +rc=$? +set -e +rm -f "$tmp_prog" || true + +if [ "$rc" -eq 42 ]; then + echo "[PASS] mirbuilder_registry_return_int_core_exec_canary_vm" + exit 0 +fi +echo "[FAIL] mirbuilder_registry_return_int_core_exec_canary_vm (rc=$rc, expect 42)" >&2; exit 1 + diff --git a/tools/smokes/v2/profiles/quick/core/phase2111/mirbuilder_registry_return_logical_and_varvar_core_exec_canary_vm.sh b/tools/smokes/v2/profiles/quick/core/phase2111/mirbuilder_registry_return_logical_and_varvar_core_exec_canary_vm.sh new file mode 100644 index 00000000..4ed1cc2a --- /dev/null +++ b/tools/smokes/v2/profiles/quick/core/phase2111/mirbuilder_registry_return_logical_and_varvar_core_exec_canary_vm.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +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="/tmp/prog_registry_logical_and_$$.json" +cat >"$tmp" <<'JSON' +{"version":0,"kind":"Program","body":[ + {"type":"Local","name":"x","expr":{"type":"Bool","value":0}}, + {"type":"Local","name":"y","expr":{"type":"Bool","value":1}}, + {"type":"Return","expr":{"type":"Logical","op":"&&","lhs":{"type":"Var","name":"x"},"rhs":{"type":"Var","name":"y"}}} +]} +JSON + +set +e +HAKO_MIR_BUILDER_INTERNAL=1 HAKO_MIR_BUILDER_REGISTRY=1 HAKO_VERIFY_PRIMARY=core verify_program_via_builder_to_core "$tmp" >/dev/null 2>&1 +rc=$? +set -e +rm -f "$tmp" || true + +if [ "$rc" -eq 0 ]; then + echo "[PASS] mirbuilder_registry_return_logical_and_varvar_core_exec_canary_vm" + exit 0 +fi +echo "[FAIL] mirbuilder_registry_return_logical_and_varvar_core_exec_canary_vm (rc=$rc, expect 0)" >&2; exit 1 + diff --git a/tools/smokes/v2/profiles/quick/core/phase2111/mirbuilder_registry_return_logical_or_varvar_core_exec_canary_vm.sh b/tools/smokes/v2/profiles/quick/core/phase2111/mirbuilder_registry_return_logical_or_varvar_core_exec_canary_vm.sh new file mode 100644 index 00000000..4898620e --- /dev/null +++ b/tools/smokes/v2/profiles/quick/core/phase2111/mirbuilder_registry_return_logical_or_varvar_core_exec_canary_vm.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +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="/tmp/prog_registry_logical_or_$$.json" +cat >"$tmp" <<'JSON' +{"version":0,"kind":"Program","body":[ + {"type":"Local","name":"a","expr":{"type":"Bool","value":1}}, + {"type":"Local","name":"b","expr":{"type":"Bool","value":0}}, + {"type":"Return","expr":{"type":"Logical","op":"||","lhs":{"type":"Var","name":"a"},"rhs":{"type":"Var","name":"b"}}} +]} +JSON + +set +e +HAKO_MIR_BUILDER_INTERNAL=1 HAKO_MIR_BUILDER_REGISTRY=1 HAKO_VERIFY_PRIMARY=core verify_program_via_builder_to_core "$tmp" >/dev/null 2>&1 +rc=$? +set -e +rm -f "$tmp" || true + +if [ "$rc" -eq 1 ]; then + echo "[PASS] mirbuilder_registry_return_logical_or_varvar_core_exec_canary_vm" + exit 0 +fi +echo "[FAIL] mirbuilder_registry_return_logical_or_varvar_core_exec_canary_vm (rc=$rc, expect 1)" >&2; exit 1 + diff --git a/tools/smokes/v2/profiles/quick/core/phase2170/array_len_alias_vm.sh b/tools/smokes/v2/profiles/quick/core/phase2170/array_len_alias_vm.sh new file mode 100644 index 00000000..bc35b7c4 --- /dev/null +++ b/tools/smokes/v2/profiles/quick/core/phase2170/array_len_alias_vm.sh @@ -0,0 +1,33 @@ +#!/bin/bash +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/mir_v1_array_len_alias_$$.json" +cat > "$tmp_json" <<'JSON' +{ + "schema_version": "1.0", + "functions": [ + {"name":"main","blocks":[ + {"id":0,"instructions":[ + {"op":"mir_call", "dst": 1, "mir_call": {"callee": {"type":"Constructor","box_type":"ArrayBox"}, "args": [], "effects": []}}, + {"op":"const", "dst": 2, "value": {"type": "i64", "value": 0}}, + {"op":"mir_call", "mir_call": {"callee": {"type":"Method","box_name":"ArrayBox","method":"push","receiver":1}, "args": [2], "effects": []}}, + {"op":"mir_call", "mir_call": {"callee": {"type":"Method","box_name":"ArrayBox","method":"push","receiver":1}, "args": [2], "effects": []}}, + {"op":"mir_call", "dst": 3, "mir_call": {"callee": {"type":"Method","box_name":"ArrayBox","method":"len","receiver":1}, "args": [], "effects": []}}, + {"op":"ret","value":3} + ]} + ]} + ] +} +JSON + +set +e +HAKO_VERIFY_PRIMARY=hakovm HAKO_VM_MIRCALL_SIZESTATE=1 HAKO_VM_MIRCALL_SIZESTATE_PER_RECV=1 verify_mir_rc "$tmp_json" >/dev/null 2>&1 +rc=$? +set -e +rm -f "$tmp_json" || true + +if [ "$rc" -eq 2 ]; then echo "[PASS] array_len_alias_vm"; exit 0; fi +echo "[FAIL] array_len_alias_vm (rc=$rc, want=2)" >&2; exit 1 + diff --git a/tools/smokes/v2/profiles/quick/core/phase2170/array_length_alias_vm.sh b/tools/smokes/v2/profiles/quick/core/phase2170/array_length_alias_vm.sh new file mode 100644 index 00000000..316ecf8e --- /dev/null +++ b/tools/smokes/v2/profiles/quick/core/phase2170/array_length_alias_vm.sh @@ -0,0 +1,33 @@ +#!/bin/bash +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/mir_v1_array_length_alias_$$.json" +cat > "$tmp_json" <<'JSON' +{ + "schema_version": "1.0", + "functions": [ + {"name":"main","blocks":[ + {"id":0,"instructions":[ + {"op":"mir_call", "dst": 1, "mir_call": {"callee": {"type":"Constructor","box_type":"ArrayBox"}, "args": [], "effects": []}}, + {"op":"const", "dst": 2, "value": {"type": "i64", "value": 0}}, + {"op":"mir_call", "mir_call": {"callee": {"type":"Method","box_name":"ArrayBox","method":"push","receiver":1}, "args": [2], "effects": []}}, + {"op":"mir_call", "mir_call": {"callee": {"type":"Method","box_name":"ArrayBox","method":"push","receiver":1}, "args": [2], "effects": []}}, + {"op":"mir_call", "dst": 3, "mir_call": {"callee": {"type":"Method","box_name":"ArrayBox","method":"length","receiver":1}, "args": [], "effects": []}}, + {"op":"ret","value":3} + ]} + ]} + ] +} +JSON + +set +e +HAKO_VERIFY_PRIMARY=hakovm HAKO_VM_MIRCALL_SIZESTATE=1 HAKO_VM_MIRCALL_SIZESTATE_PER_RECV=1 verify_mir_rc "$tmp_json" >/dev/null 2>&1 +rc=$? +set -e +rm -f "$tmp_json" || true + +if [ "$rc" -eq 2 ]; then echo "[PASS] array_length_alias_vm"; exit 0; fi +echo "[FAIL] array_length_alias_vm (rc=$rc, want=2)" >&2; exit 1 + diff --git a/tools/smokes/v2/profiles/quick/core/phase2170/array_push_size_10_vm.sh b/tools/smokes/v2/profiles/quick/core/phase2170/array_push_size_10_vm.sh new file mode 100644 index 00000000..36a3f084 --- /dev/null +++ b/tools/smokes/v2/profiles/quick/core/phase2170/array_push_size_10_vm.sh @@ -0,0 +1,41 @@ +#!/bin/bash +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/mir_v1_array_push_size_10_$$.json" +cat > "$tmp_json" <<'JSON' +{ + "schema_version": "1.0", + "functions": [ + {"name":"main","blocks":[ + {"id":0,"instructions":[ + {"op":"mir_call", "dst": 1, "mir_call": {"callee": {"type":"Constructor","box_type":"ArrayBox"}, "args": [], "effects": []}}, + {"op":"const", "dst": 2, "value": {"type": "i64", "value": 1}}, + {"op":"mir_call", "mir_call": {"callee": {"type":"Method","box_name":"ArrayBox","method":"push","receiver":1}, "args": [2], "effects": []}}, + {"op":"mir_call", "mir_call": {"callee": {"type":"Method","box_name":"ArrayBox","method":"push","receiver":1}, "args": [2], "effects": []}}, + {"op":"mir_call", "mir_call": {"callee": {"type":"Method","box_name":"ArrayBox","method":"push","receiver":1}, "args": [2], "effects": []}}, + {"op":"mir_call", "mir_call": {"callee": {"type":"Method","box_name":"ArrayBox","method":"push","receiver":1}, "args": [2], "effects": []}}, + {"op":"mir_call", "mir_call": {"callee": {"type":"Method","box_name":"ArrayBox","method":"push","receiver":1}, "args": [2], "effects": []}}, + {"op":"mir_call", "mir_call": {"callee": {"type":"Method","box_name":"ArrayBox","method":"push","receiver":1}, "args": [2], "effects": []}}, + {"op":"mir_call", "mir_call": {"callee": {"type":"Method","box_name":"ArrayBox","method":"push","receiver":1}, "args": [2], "effects": []}}, + {"op":"mir_call", "mir_call": {"callee": {"type":"Method","box_name":"ArrayBox","method":"push","receiver":1}, "args": [2], "effects": []}}, + {"op":"mir_call", "mir_call": {"callee": {"type":"Method","box_name":"ArrayBox","method":"push","receiver":1}, "args": [2], "effects": []}}, + {"op":"mir_call", "mir_call": {"callee": {"type":"Method","box_name":"ArrayBox","method":"push","receiver":1}, "args": [2], "effects": []}}, + {"op":"mir_call", "dst": 3, "mir_call": {"callee": {"type":"Method","box_name":"ArrayBox","method":"size","receiver":1}, "args": [], "effects": []}}, + {"op":"ret","value":3} + ]} + ]} + ] +} +JSON + +set +e +HAKO_VERIFY_PRIMARY=hakovm HAKO_VM_MIRCALL_SIZESTATE=1 HAKO_VM_MIRCALL_SIZESTATE_PER_RECV=1 verify_mir_rc "$tmp_json" >/dev/null 2>&1 +rc=$? +set -e +rm -f "$tmp_json" || true + +if [ "$rc" -eq 10 ]; then echo "[PASS] array_push_size_10_vm"; exit 0; fi +echo "[FAIL] array_push_size_10_vm (rc=$rc, want=10)" >&2; exit 1 + diff --git a/tools/smokes/v2/profiles/quick/core/phase2170/array_push_size_5_vm.sh b/tools/smokes/v2/profiles/quick/core/phase2170/array_push_size_5_vm.sh new file mode 100644 index 00000000..0cf0b16a --- /dev/null +++ b/tools/smokes/v2/profiles/quick/core/phase2170/array_push_size_5_vm.sh @@ -0,0 +1,36 @@ +#!/bin/bash +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/mir_v1_array_push_size_5_$$.json" +cat > "$tmp_json" <<'JSON' +{ + "schema_version": "1.0", + "functions": [ + {"name":"main","blocks":[ + {"id":0,"instructions":[ + {"op":"mir_call", "dst": 1, "mir_call": {"callee": {"type":"Constructor","box_type":"ArrayBox"}, "args": [], "effects": []}}, + {"op":"const", "dst": 2, "value": {"type": "i64", "value": 111}}, + {"op":"mir_call", "mir_call": {"callee": {"type":"Method","box_name":"ArrayBox","method":"push","receiver":1}, "args": [2], "effects": []}}, + {"op":"mir_call", "mir_call": {"callee": {"type":"Method","box_name":"ArrayBox","method":"push","receiver":1}, "args": [2], "effects": []}}, + {"op":"mir_call", "mir_call": {"callee": {"type":"Method","box_name":"ArrayBox","method":"push","receiver":1}, "args": [2], "effects": []}}, + {"op":"mir_call", "mir_call": {"callee": {"type":"Method","box_name":"ArrayBox","method":"push","receiver":1}, "args": [2], "effects": []}}, + {"op":"mir_call", "mir_call": {"callee": {"type":"Method","box_name":"ArrayBox","method":"push","receiver":1}, "args": [2], "effects": []}}, + {"op":"mir_call", "dst": 3, "mir_call": {"callee": {"type":"Method","box_name":"ArrayBox","method":"size","receiver":1}, "args": [], "effects": []}}, + {"op":"ret","value":3} + ]} + ]} + ] +} +JSON + +set +e +HAKO_VERIFY_PRIMARY=hakovm HAKO_VM_MIRCALL_SIZESTATE=1 HAKO_VM_MIRCALL_SIZESTATE_PER_RECV=1 verify_mir_rc "$tmp_json" >/dev/null 2>&1 +rc=$? +set -e +rm -f "$tmp_json" || true + +if [ "$rc" -eq 5 ]; then echo "[PASS] array_push_size_5_vm"; exit 0; fi +echo "[FAIL] array_push_size_5_vm (rc=$rc, want=5)" >&2; exit 1 + diff --git a/tools/smokes/v2/profiles/quick/core/phase2170/flow_across_blocks_array_size_canary_vm.sh b/tools/smokes/v2/profiles/quick/core/phase2170/flow_across_blocks_array_size_canary_vm.sh new file mode 100644 index 00000000..d219a4c4 --- /dev/null +++ b/tools/smokes/v2/profiles/quick/core/phase2170/flow_across_blocks_array_size_canary_vm.sh @@ -0,0 +1,43 @@ +#!/bin/bash +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/mir_v1_flow_across_blocks_array_$$.json" +cat > "$tmp_json" <<'JSON' +{ + "schema_version": "1.0", + "functions": [ + {"name":"main","blocks":[ + {"id":0,"instructions":[ + {"op":"mir_call", "dst": 1, "mir_call": {"callee": {"type":"Constructor","box_type":"ArrayBox"}, "args": [], "effects": []}}, + {"op":"const", "dst": 2, "value": {"type": "i64", "value": 0}}, + {"op":"mir_call", "mir_call": {"callee": {"type":"Method","box_name":"ArrayBox","method":"push","receiver":1}, "args": [2], "effects": []}}, + {"op":"mir_call", "mir_call": {"callee": {"type":"Method","box_name":"ArrayBox","method":"push","receiver":1}, "args": [2], "effects": []}}, + {"op":"mir_call", "mir_call": {"callee": {"type":"Method","box_name":"ArrayBox","method":"push","receiver":1}, "args": [2], "effects": []}}, + {"op":"const","dst":10, "value": {"type": "i64", "value": 1}}, + {"op":"const","dst":11, "value": {"type": "i64", "value": 1}}, + {"op":"compare","dst":12, "lhs":10, "rhs":11, "cmp":"Eq"}, + {"op":"branch","cond":12, "then":1, "else":2} + ]}, + {"id":1,"instructions":[ + {"op":"mir_call", "dst": 3, "mir_call": {"callee": {"type":"Method","box_name":"ArrayBox","method":"size","receiver":1}, "args": [], "effects": []}}, + {"op":"ret","value":3} + ]}, + {"id":2,"instructions":[ + {"op":"ret","value":2} + ]} + ]} + ] +} +JSON + +set +e +HAKO_VERIFY_PRIMARY=hakovm HAKO_V1_DISPATCHER_FLOW=1 HAKO_VM_MIRCALL_SIZESTATE=1 HAKO_VM_MIRCALL_SIZESTATE_PER_RECV=1 verify_mir_rc "$tmp_json" >/dev/null 2>&1 +rc=$? +set -e +rm -f "$tmp_json" || true + +if [ "$rc" -eq 3 ]; then echo "[PASS] flow_across_blocks_array_size_canary_vm"; exit 0; fi +echo "[FAIL] flow_across_blocks_array_size_canary_vm (rc=$rc, want=3)" >&2; exit 1 + diff --git a/tools/smokes/v2/profiles/quick/core/phase2170/hv1_mircall_array_push_size_state_canary_vm.sh b/tools/smokes/v2/profiles/quick/core/phase2170/hv1_mircall_array_push_size_state_canary_vm.sh new file mode 100644 index 00000000..674d07bb --- /dev/null +++ b/tools/smokes/v2/profiles/quick/core/phase2170/hv1_mircall_array_push_size_state_canary_vm.sh @@ -0,0 +1,44 @@ +#!/bin/bash +# Hakovm v1 dispatcher: ArrayBox push → size state increments (1→2→3) +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/mir_v1_array_push_size_$$.json" +cat > "$tmp_json" <<'JSON' +{ + "schema_version": "1.0", + "functions": [ + {"name":"main","blocks":[ + {"id":0,"instructions":[ + {"op":"mir_call", "dst": 1, "mir_call": {"callee": {"type":"Constructor","box_type":"ArrayBox"}, "args": [], "effects": []}}, + {"op":"const", "dst": 2, "value": {"type": "i64", "value": 111}}, + {"op":"mir_call", "mir_call": {"callee": {"type":"Method","box_name":"ArrayBox","method":"push","receiver":1}, "args": [2], "effects": []}}, + {"op":"mir_call", "mir_call": {"callee": {"type":"Method","box_name":"ArrayBox","method":"push","receiver":1}, "args": [2], "effects": []}}, + {"op":"mir_call", "mir_call": {"callee": {"type":"Method","box_name":"ArrayBox","method":"push","receiver":1}, "args": [2], "effects": []}}, + {"op":"mir_call", "dst": 3, "mir_call": {"callee": {"type":"Method","box_name":"ArrayBox","method":"size","receiver":1}, "args": [], "effects": []}}, + {"op":"ret","value":3} + ]} + ]} + ] +} +JSON + +# Expect rc=3 when stateful mir_call is ON and primary=hakovm +set +e +HAKO_VERIFY_PRIMARY=hakovm \ +HAKO_VM_MIRCALL_SIZESTATE=1 HAKO_VM_MIRCALL_SIZESTATE_PER_RECV=1 \ +verify_mir_rc "$tmp_json" >/dev/null 2>&1 +rc=$? +set -e + +rm -f "$tmp_json" || true + +if [ "$rc" -eq 3 ]; then + echo "[PASS] hv1_mircall_array_push_size_state_canary_vm" + exit 0 +fi +echo "[FAIL] hv1_mircall_array_push_size_state_canary_vm (rc=$rc, want=3)" >&2 +exit 1 + diff --git a/tools/smokes/v2/profiles/quick/core/phase2170/hv1_mircall_map_set_size_state_canary_vm.sh b/tools/smokes/v2/profiles/quick/core/phase2170/hv1_mircall_map_set_size_state_canary_vm.sh new file mode 100644 index 00000000..8d6290cc --- /dev/null +++ b/tools/smokes/v2/profiles/quick/core/phase2170/hv1_mircall_map_set_size_state_canary_vm.sh @@ -0,0 +1,46 @@ +#!/bin/bash +# Hakovm v1 dispatcher: MapBox set(new key) → size increments (1→2) +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/mir_v1_map_set_size_$$.json" +cat > "$tmp_json" <<'JSON' +{ + "schema_version": "1.0", + "functions": [ + {"name":"main","blocks":[ + {"id":0,"instructions":[ + {"op":"mir_call", "dst": 1, "mir_call": {"callee": {"type":"Constructor","box_type":"MapBox"}, "args": [], "effects": []}}, + {"op":"const", "dst": 2, "value": {"type": {"kind":"handle","box_type":"StringBox"}, "value": "k1"}}, + {"op":"const", "dst": 3, "value": {"type": "i64", "value": 100}}, + {"op":"mir_call", "mir_call": {"callee": {"type":"Method","box_name":"MapBox","method":"set","receiver":1}, "args": [2,3], "effects": []}}, + {"op":"const", "dst": 4, "value": {"type": {"kind":"handle","box_type":"StringBox"}, "value": "k2"}}, + {"op":"const", "dst": 5, "value": {"type": "i64", "value": 200}}, + {"op":"mir_call", "mir_call": {"callee": {"type":"Method","box_name":"MapBox","method":"set","receiver":1}, "args": [4,5], "effects": []}}, + {"op":"mir_call", "dst": 6, "mir_call": {"callee": {"type":"Method","box_name":"MapBox","method":"size","receiver":1}, "args": [], "effects": []}}, + {"op":"ret","value":6} + ]} + ]} + ] +} +JSON + +# Expect rc=2 when stateful mir_call (Map.set) is ON and primary=hakovm +set +e +HAKO_VERIFY_PRIMARY=hakovm \ +HAKO_VM_MIRCALL_SIZESTATE=1 HAKO_VM_MIRCALL_SIZESTATE_PER_RECV=1 \ +verify_mir_rc "$tmp_json" >/dev/null 2>&1 +rc=$? +set -e + +rm -f "$tmp_json" || true + +if [ "$rc" -eq 2 ]; then + echo "[PASS] hv1_mircall_map_set_size_state_canary_vm" + exit 0 +fi +echo "[FAIL] hv1_mircall_map_set_size_state_canary_vm (rc=$rc, want=2)" >&2 +exit 1 + diff --git a/tools/smokes/v2/profiles/quick/core/phase2170/map_set_dup_key_size_canary_vm.sh b/tools/smokes/v2/profiles/quick/core/phase2170/map_set_dup_key_size_canary_vm.sh new file mode 100644 index 00000000..06cad139 --- /dev/null +++ b/tools/smokes/v2/profiles/quick/core/phase2170/map_set_dup_key_size_canary_vm.sh @@ -0,0 +1,38 @@ +#!/bin/bash +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/mir_v1_map_set_dup_key_size_$$.json" +cat > "$tmp_json" <<'JSON' +{ + "schema_version": "1.0", + "functions": [ + {"name":"main","blocks":[ + {"id":0,"instructions":[ + {"op":"mir_call", "dst": 1, "mir_call": {"callee": {"type":"Constructor","box_type":"MapBox"}, "args": [], "effects": []}}, + {"op":"const", "dst": 2, "value": {"type": {"kind":"handle","box_type":"StringBox"}, "value": "k1"}}, + {"op":"const", "dst": 3, "value": {"type": "i64", "value": 100}}, + {"op":"mir_call", "mir_call": {"callee": {"type":"Method","box_name":"MapBox","method":"set","receiver":1}, "args": [2,3], "effects": []}}, + {"op":"const", "dst": 5, "value": {"type": "i64", "value": 200}}, + {"op":"mir_call", "mir_call": {"callee": {"type":"Method","box_name":"MapBox","method":"set","receiver":1}, "args": [2,5], "effects": []}}, + {"op":"const", "dst": 6, "value": {"type": {"kind":"handle","box_type":"StringBox"}, "value": "k2"}}, + {"op":"const", "dst": 7, "value": {"type": "i64", "value": 300}}, + {"op":"mir_call", "mir_call": {"callee": {"type":"Method","box_name":"MapBox","method":"set","receiver":1}, "args": [6,7], "effects": []}}, + {"op":"mir_call", "dst": 8, "mir_call": {"callee": {"type":"Method","box_name":"MapBox","method":"size","receiver":1}, "args": [], "effects": []}}, + {"op":"ret","value":8} + ]} + ]} + ] +} +JSON + +set +e +HAKO_VERIFY_PRIMARY=hakovm HAKO_VM_MIRCALL_SIZESTATE=1 HAKO_VM_MIRCALL_SIZESTATE_PER_RECV=1 verify_mir_rc "$tmp_json" >/dev/null 2>&1 +rc=$? +set -e +rm -f "$tmp_json" || true + +# k1 (new) -> size=1, k1 (dup) -> size stays 1, k2 (new) -> size=2 +if [ "$rc" -eq 2 ]; then echo "[PASS] map_set_dup_key_size_canary_vm"; exit 0; fi +echo "[FAIL] map_set_dup_key_size_canary_vm (rc=$rc, want=2)" >&2; exit 1 diff --git a/tools/smokes/v2/profiles/quick/core/phase2170/map_value_state_get_has_canary_vm.sh b/tools/smokes/v2/profiles/quick/core/phase2170/map_value_state_get_has_canary_vm.sh new file mode 100644 index 00000000..9492b9fd --- /dev/null +++ b/tools/smokes/v2/profiles/quick/core/phase2170/map_value_state_get_has_canary_vm.sh @@ -0,0 +1,34 @@ +#!/bin/bash +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 + +# value_state=1: Map.get returns stored value, Map.has reports presence +tmp_json="/tmp/mir_v1_map_value_state_$$.json" +cat > "$tmp_json" <<'JSON' +{ + "schema_version": "1.0", + "functions": [ + {"name":"main","blocks":[ + {"id":0,"instructions":[ + {"op":"mir_call", "dst": 1, "mir_call": {"callee": {"type":"Constructor","box_type":"MapBox"}, "args": [], "effects": []}}, + {"op":"const", "dst": 2, "value": {"type": {"kind":"handle","box_type":"StringBox"}, "value": "k2"}}, + {"op":"const", "dst": 3, "value": {"type": "i64", "value": 200}}, + {"op":"mir_call", "mir_call": {"callee": {"type":"Method","box_name":"MapBox","method":"set","receiver":1}, "args": [2,3], "effects": []}}, + {"op":"mir_call", "dst": 4, "mir_call": {"callee": {"type":"Method","box_name":"MapBox","method":"get","receiver":1}, "args": [2], "effects": []}}, + {"op":"ret","value":4} + ]} + ]} + ] +} +JSON + +set +e +HAKO_VERIFY_PRIMARY=hakovm HAKO_VM_MIRCALL_SIZESTATE=1 HAKO_VM_MIRCALL_VALUESTATE=1 HAKO_VM_MIRCALL_SIZESTATE_PER_RECV=1 verify_mir_rc "$tmp_json" >/dev/null 2>&1 +rc=$? +set -e +rm -f "$tmp_json" || true + +if [ "$rc" -eq 200 ]; then echo "[PASS] map_value_state_get_has_canary_vm"; exit 0; fi +echo "[FAIL] map_value_state_get_has_canary_vm (rc=$rc, want=200)" >&2; exit 1 + diff --git a/tools/smokes/v2/profiles/quick/core/phase2170/per_recv_global_canary_vm.sh b/tools/smokes/v2/profiles/quick/core/phase2170/per_recv_global_canary_vm.sh new file mode 100644 index 00000000..6871cf52 --- /dev/null +++ b/tools/smokes/v2/profiles/quick/core/phase2170/per_recv_global_canary_vm.sh @@ -0,0 +1,34 @@ +#!/bin/bash +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 + +# per_recv=0: global length key. push on A then size on B → 1 +tmp_json="/tmp/mir_v1_perrecv_global_$$.json" +cat > "$tmp_json" <<'JSON' +{ + "schema_version": "1.0", + "functions": [ + {"name":"main","blocks":[ + {"id":0,"instructions":[ + {"op":"mir_call", "dst": 1, "mir_call": {"callee": {"type":"Constructor","box_type":"ArrayBox"}, "args": [], "effects": []}}, + {"op":"const", "dst": 2, "value": {"type": "i64", "value": 0}}, + {"op":"mir_call", "mir_call": {"callee": {"type":"Method","box_name":"ArrayBox","method":"push","receiver":1}, "args": [2], "effects": []}}, + {"op":"mir_call", "dst": 4, "mir_call": {"callee": {"type":"Constructor","box_type":"ArrayBox"}, "args": [], "effects": []}}, + {"op":"mir_call", "dst": 5, "mir_call": {"callee": {"type":"Method","box_name":"ArrayBox","method":"size","receiver":4}, "args": [], "effects": []}}, + {"op":"ret","value":5} + ]} + ]} + ] +} +JSON + +set +e +HAKO_VERIFY_PRIMARY=hakovm HAKO_VM_MIRCALL_SIZESTATE=1 HAKO_VM_MIRCALL_SIZESTATE_PER_RECV=0 verify_mir_rc "$tmp_json" >/dev/null 2>&1 +rc=$? +set -e +rm -f "$tmp_json" || true + +if [ "$rc" -eq 1 ]; then echo "[PASS] per_recv_global_canary_vm"; exit 0; fi +echo "[FAIL] per_recv_global_canary_vm (rc=$rc, want=1)" >&2; exit 1 + diff --git a/tools/smokes/v2/profiles/quick/core/phase2170/per_recv_per_canary_vm.sh b/tools/smokes/v2/profiles/quick/core/phase2170/per_recv_per_canary_vm.sh new file mode 100644 index 00000000..bab62532 --- /dev/null +++ b/tools/smokes/v2/profiles/quick/core/phase2170/per_recv_per_canary_vm.sh @@ -0,0 +1,34 @@ +#!/bin/bash +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 + +# per_recv=1: per-receiver length key. push on A then size on B → 0 +tmp_json="/tmp/mir_v1_perrecv_per_$$.json" +cat > "$tmp_json" <<'JSON' +{ + "schema_version": "1.0", + "functions": [ + {"name":"main","blocks":[ + {"id":0,"instructions":[ + {"op":"mir_call", "dst": 1, "mir_call": {"callee": {"type":"Constructor","box_type":"ArrayBox"}, "args": [], "effects": []}}, + {"op":"const", "dst": 2, "value": {"type": "i64", "value": 0}}, + {"op":"mir_call", "mir_call": {"callee": {"type":"Method","box_name":"ArrayBox","method":"push","receiver":1}, "args": [2], "effects": []}}, + {"op":"mir_call", "dst": 4, "mir_call": {"callee": {"type":"Constructor","box_type":"ArrayBox"}, "args": [], "effects": []}}, + {"op":"mir_call", "dst": 5, "mir_call": {"callee": {"type":"Method","box_name":"ArrayBox","method":"size","receiver":4}, "args": [], "effects": []}}, + {"op":"ret","value":5} + ]} + ]} + ] +} +JSON + +set +e +HAKO_VERIFY_PRIMARY=hakovm HAKO_VM_MIRCALL_SIZESTATE=1 HAKO_VM_MIRCALL_SIZESTATE_PER_RECV=1 verify_mir_rc "$tmp_json" >/dev/null 2>&1 +rc=$? +set -e +rm -f "$tmp_json" || true + +if [ "$rc" -eq 0 ]; then echo "[PASS] per_recv_per_canary_vm"; exit 0; fi +echo "[FAIL] per_recv_per_canary_vm (rc=$rc, want=0)" >&2; exit 1 + diff --git a/tools/smokes/v2/profiles/quick/core/phase2170/run_all.sh b/tools/smokes/v2/profiles/quick/core/phase2170/run_all.sh new file mode 100644 index 00000000..3c4acfda --- /dev/null +++ b/tools/smokes/v2/profiles/quick/core/phase2170/run_all.sh @@ -0,0 +1,20 @@ +#!/bin/bash +set -euo pipefail + +DIR="$(cd "$(dirname "$0")" && pwd)" + +bash "$DIR/hv1_mircall_array_push_size_state_canary_vm.sh" +bash "$DIR/hv1_mircall_map_set_size_state_canary_vm.sh" +bash "$DIR/array_push_size_5_vm.sh" +bash "$DIR/array_push_size_10_vm.sh" +bash "$DIR/array_len_alias_vm.sh" +bash "$DIR/array_length_alias_vm.sh" +bash "$DIR/per_recv_global_canary_vm.sh" +bash "$DIR/per_recv_per_canary_vm.sh" +bash "$DIR/map_set_dup_key_size_canary_vm.sh" +bash "$DIR/map_value_state_get_has_canary_vm.sh" +bash "$DIR/flow_across_blocks_array_size_canary_vm.sh" + +# dup-key non-increment now enforced + +echo "[PASS] phase2170 all"