Files
hakorune/tools/hako_check/render/graphviz.hako

114 lines
3.6 KiB
Plaintext
Raw Normal View History

Phase 21.2 Complete: VM Adapter正規実装 + devブリッジ完全撤去 ## 🎉 Phase 21.2完全達成 ### ✅ 実装完了 - VM static box 永続化(singleton infrastructure) - devブリッジ完全撤去(adapter_dev.rs削除、by-name dispatch削除) - .hako正規実装(MirCallV1Handler, AbiAdapterRegistry等) - text-merge経路完全動作 - 全phase2120 adapter reps PASS(7テスト) ### 🐛 バグ修正 1. strip_local_decl修正 - トップレベルのみlocal削除、メソッド内は保持 - src/runner/modes/common_util/hako.rs:29 2. static box フィールド永続化 - MirInterpreter singleton storage実装 - me parameter binding修正(1:1マッピング) - getField/setField string→singleton解決 - src/backend/mir_interpreter/{mod,exec,handlers/boxes_object_fields}.rs 3. Map.len alias rc=0修正 - [map/missing]パターン検出でnull扱い(4箇所) - lang/src/vm/boxes/mir_call_v1_handler.hako:91-93,131-133,151-153,199-201 ### 📁 主要変更ファイル #### Rust(VM Runtime) - src/backend/mir_interpreter/mod.rs - static box singleton storage - src/backend/mir_interpreter/exec.rs - parameter binding fix - src/backend/mir_interpreter/handlers/boxes_object_fields.rs - singleton resolution - src/backend/mir_interpreter/handlers/calls.rs - dev bridge removal - src/backend/mir_interpreter/utils/mod.rs - adapter_dev module removal - src/backend/mir_interpreter/utils/adapter_dev.rs - DELETED (7555 bytes) - src/runner/modes/vm.rs - static box declaration collection - src/runner/modes/common_util/hako.rs - strip_local_decl fix - src/instance_v2.rs - Clone implementation #### Hako (.hako実装) - lang/src/vm/boxes/mir_call_v1_handler.hako - [map/missing] detection - lang/src/vm/boxes/abi_adapter_registry.hako - NEW (adapter registry) - lang/src/vm/helpers/method_alias_policy.hako - method alias support #### テスト - tools/smokes/v2/profiles/quick/core/phase2120/s3_vm_adapter_*.sh - 7 new tests ### 🎯 テスト結果 ``` ✅ s3_vm_adapter_array_len_canary_vm.sh ✅ s3_vm_adapter_array_len_per_recv_canary_vm.sh ✅ s3_vm_adapter_array_length_alias_canary_vm.sh ✅ s3_vm_adapter_array_size_alias_canary_vm.sh ✅ s3_vm_adapter_map_len_alias_state_canary_vm.sh ✅ s3_vm_adapter_map_length_alias_state_canary_vm.sh ✅ s3_vm_adapter_map_size_struct_canary_vm.sh ``` 環境フラグ: HAKO_ABI_ADAPTER=1 HAKO_ABI_ADAPTER_DEV=0 ### 🏆 設計品質 - ✅ ハードコード禁止(AGENTS.md 5.1)完全準拠 - ✅ 構造的・一般化設計(特定Box名のif分岐なし) - ✅ 後方互換性保持(既存コード破壊ゼロ) - ✅ text-merge経路(.hako依存関係正しくマージ) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-07 19:32:44 +09:00
// tools/hako_check/render/graphviz.hako — GraphvizRenderBox (MVP)
// Render minimal DOT graph from one or more Analysis IRs.
using selfhost.shared.common.string_helpers as Str
static box GraphvizRenderBox {
render_multi(irs) {
// irs: ArrayBox of IR Map
print("digraph Hako {")
// optional graph attributes (kept minimal)
// print(" rankdir=LR;")
// Node and edge sets to avoid duplicates
local nodes = new MapBox()
local edges = new MapBox()
if irs != null {
local gi = 0
while gi < irs.size() {
local ir = irs.get(gi)
me._render_ir(ir, nodes, edges)
gi = gi + 1
}
}
// Emit nodes
local itn = nodes
// Map iteration: keys() not available → store labels as keys in map
// Use a synthetic loop by scanning a known list captured during _render_ir
// For MVP, nodes map has key=name, value=1
// We cannot iterate map keys deterministically; accept arbitrary order.
// Re-emitting by re-collecting from edges as well (ensures endpoints appear).
// Emit edges
if edges != null {
// 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__")
if ks != null {
local ei = 0
while ei < ks.size() {
local key = ks.get(ei)
local tab = key.indexOf("\t")
if tab > 0 {
local src = key.substring(0, tab)
local dst = key.substring(tab+1)
print(" \"" + src + "\" -> \"" + dst + "\";")
// also register nodes (in case they werent explicitly collected)
nodes.set(src, 1)
nodes.set(dst, 1)
}
ei = ei + 1
}
}
}
// Now emit nodes at the end for any isolated methods
// Rebuild a list of node keys from a synthetic array stored under nodes.get("__keys__")
local nk = nodes.get("__keys__")
if nk != null {
local ni = 0
while ni < nk.size() {
local name = nk.get(ni)
print(" \"" + name + "\";")
ni = ni + 1
}
}
print("}")
return 0
}
_render_ir(ir, nodes, edges) {
if ir == null { return }
// methods
local ms = ir.get("methods")
if ms != null {
local mi = 0
while mi < ms.size() {
me._add_node(nodes, ms.get(mi))
mi = mi + 1
}
}
// calls
local cs = ir.get("calls")
if cs != null {
local ci = 0
while ci < cs.size() {
local c = cs.get(ci)
local f = c.get("from")
local t = c.get("to")
me._add_edge(edges, f, t)
ci = ci + 1
}
}
}
_add_node(nodes, name) {
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) }
// avoid duplicates
local seen = 0
local i = 0; while i < arr.size() { if arr.get(i) == name { seen = 1; break } i = i + 1 }
if seen == 0 { arr.push(name) }
}
_add_edge(edges, src, dst) {
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) }
// avoid duplicates
local seen = 0
local i = 0; while i < arr.size() { if arr.get(i) == key { seen = 1; break } i = i + 1 }
if seen == 0 { arr.push(key) }
}
}
static box GraphvizRenderMain { method main(args) { return 0 } }