16 KiB
Phase 20.6 — Execution Plan (VM Core Complete + Dispatch Unification)
Status: Planning Duration: 12 weeks (2026-03-01 → 2026-05-24) Prerequisite: Phase 20.5 complete (VM Foundations PoC + op_eq Migration)
Executive Summary (5 lines)
- Goal: Complete Hakorune VM Core (16 MIR instructions) + Unify Dispatch (single Resolver path).
- Strategy: Phase B (Week 1-6) = All instructions; Phase C (Week 7-12) = Resolver integration.
- Verification: Golden Tests (100+ cases) ensure Rust-VM vs Hako-VM 100% output parity.
- Performance: Target ≥ 50% of Rust-VM speed (acceptable for PoC, optimize later).
- Policy: Fail-Fast (unknown methods → RuntimeError), no special-case dispatch, Everything is Box.
Phase Breakdown
Phase B Complete: VM Core (Week 1-6)
Objective: Implement MIR core ops and unify calls via MirCall in Hakorune.
Week 1-2: Memory Operations (2026-03-01 - 03-14)
Instructions:
load: Load value from memorystore: Store value to memorycopy: Copy value between registers
Deliverables:
load_handler.hakoimplementationstore_handler.hakoimplementationcopy_handler.hakoimplementation- 10 test cases (memory operations)
Testing:
# Memory operation tests
tests/golden/phase-b/memory/
├── test_load_store.hako
├── test_copy_register.hako
├── test_memory_aliasing.hako
└── ... (7 more)
Week 3-4: Unified Call (MirCall) (2026-03-15 - 03-28)
Semantics:
- MirCall with typed Callee variants:
Callee::Method(受領者付きメソッド)Callee::ModuleFunction("Box.method/arity")Callee::Extern("iface.method")Callee::Constructor{box_type}(new はここへ統一)
Deliverables:
mir_call_handler.hako(単一エントリ)実装- Callee::Method/ModuleFunction/Extern/Constructor 分岐
- 受領者/引数の素材化(Fail‑Fast)
- 15 テスト(MirCall:Method/Module/Extern/Constructor)
Testing:
# MirCall tests
tests/golden/phase-b/calls/
├── test_method_call.hako
├── test_module_function.hako
├── test_closure_call.hako
├── test_extern_call.hako
├── test_constructor_call.hako
└── ... (10 more)
Key Design:
// Unified MirCall handler (call instruction)
static box MirCallHandlerBox {
handle(inst_json, regs, mem) {
local callee_type = extract_callee_type(inst_json)
return match callee_type {
"Global" => me._handle_global(inst_json, regs)
"ModuleFunction" => me._handle_module(inst_json, regs)
"Closure" => me._handle_closure(inst_json, regs, mem)
_ => Result.Err("Unknown callee type")
}
}
}
Week 5: Type Operations (2026-03-29 - 04-04)
Instructions:
typeop: Type conversion/checking (Box生成は MirCall::Constructor に統一し、ここでは扱わない)
Deliverables:
typeop_handler.hakoimplementation- 10 test cases (type operations)
Testing:
# Type operation tests
tests/golden/phase-b/types/
├── test_type_check.hako
├── test_type_cast.hako
└── ... (6 more)
Week 6: Control Flow Optimizations + Golden Tests (2026-04-05 - 04-11)
Instructions:
barrier: GC barriersafepoint: GC safepointloopform: Loop detection hintunaryop: Unary operations
Golden Test Suite (100+ tests):
tests/golden/hakorune-vm/
├── arithmetic/ # 10 tests (add, mul, div, mod, ...)
├── control_flow/ # 10 tests (if, loop, branch, ...)
├── collections/ # 10 tests (array, map operations)
├── recursion/ # 5 tests (factorial, fibonacci, ...)
├── closures/ # 5 tests (capture, nested, ...)
├── strings/ # 10 tests (concat, substring, ...)
├── types/ # 10 tests (type checks, casts)
├── memory/ # 10 tests (load, store, aliasing)
└── complex/ # 30 tests (integration scenarios)
Deliverables:
- Remaining instruction implementations
- Golden Test Suite complete (100+ tests)
- Performance measurement: Hako-VM ≥ 50% of Rust-VM
Golden Test Execution:
# Run Golden Tests
bash tools/golden_test_hakorune_vm.sh
# Expected output:
# ✅ arithmetic: 10/10 PASS
# ✅ control_flow: 10/10 PASS
# ✅ collections: 10/10 PASS
# ✅ recursion: 5/5 PASS
# ✅ closures: 5/5 PASS
# ✅ strings: 10/10 PASS
# ✅ types: 10/10 PASS
# ✅ memory: 10/10 PASS
# ✅ complex: 30/30 PASS
# ────────────────────────────
# Total: 100/100 PASS (100%)
Phase C: Dispatch Unification (Week 7-12)
Objective: Unify all method calls through single Resolver path.
Week 7-8: Resolver Integration (2026-04-12 - 04-25)
Goal: Implement Resolver.lookup(type_id, method, arity) -> MethodHandle
Design:
// Resolver: Single resolution path for all method calls
static box ResolverBox {
_method_registry: MapBox // type_id -> method_name -> MethodHandle
// Main entry point
lookup(type_id: IntegerBox,
method: StringBox,
arity: IntegerBox) {
// 1. Search type registry
local type_methods = me._method_registry.get(type_id)
if type_methods.is_null() {
return Result.Err("Unknown type: " + type_id)
}
// 2. Lookup method by name + arity
local method_key = method + "/" + arity
local handle = type_methods.get(method_key)
if handle.is_null() {
// Fail-Fast: No fallback
return Result.Err("Method not found: " + method_key)
}
return Result.Ok(handle)
}
// Registration (called at startup)
register_type(type_id: IntegerBox,
methods: MapBox) {
me._method_registry.set(type_id, methods)
}
}
---
## C‑ABI Unification (design‑only in 20.6)
### Goals
- Provide SSOT for Basic boxes (String/Array/Map/Int/Bool/Null/Void) via C‑ABI so both Rust VM and Hako VM call the same implementation.
- Do not change behavior in 20.6 (flags default OFF). Implementation rollout is in 20.7.
### Deliverables (20.6)
- [ ] ABI header draft (`docs/abi/hako_abi_v1.md` or `include/hako_abi_v1.h`): TypeId/Handle/Result/Dispatch/Allocator minimal set
- [ ] Two‑Layer Export policy document (Stable ABI + Inlinable API)
- [ ] Flags documented: `NYASH_ABI_BASIC_ON`, `NYASH_ABI_BUILTIN_LINK`
- [ ] Build presets documented: default/embedded/research
- [ ] No runtime behavior change (flags remain OFF)
### Acceptance Criteria
- Quick/Integration remain green with flags OFF
- Docs provide rollback and gating policy; CI does not depend on ABI flags yet
### Out of Scope (move to 20.7)
- Actual ABI binding for String/Array/Map
- Router rewrite to call ABI by default
- Performance validation under ABI path
Deliverables:
resolver_box.hakoimplementationmethod_handle_box.hakoimplementation- Type registry initialization
- 20 integration tests
Testing:
tests/golden/phase-c/resolver/
├── test_lookup_success.hako
├── test_lookup_failure.hako (Fail-Fast)
├── test_arity_mismatch.hako
├── test_type_not_found.hako
└── ... (16 more)
Week 9-10: CallableBox Refactoring (2026-04-26 - 05-09)
Goal: Single entry point for all invocations.
Design:
// ExecBox: Unified invocation
static box ExecBox {
call_by_handle(handle: MethodHandleBox,
args: ArrayBox,
guard: NoOperatorGuard) {
// 1. Extract implementation from handle
local impl_func = handle.get_implementation()
// 2. Validate arguments
local expected_arity = handle.get_arity()
if args.size() != expected_arity {
return Result.Err("Arity mismatch")
}
// 3. NoOperatorGuard prevents recursion (e.g., in op_eq)
if guard.is_active() {
// Prevent re-entry
return Result.Err("Recursive operator call")
}
// 4. Invoke
guard.activate()
local result = impl_func.call(args)
guard.deactivate()
return result
}
}
Macro Desugaring:
// Before (user code):
local result = arr.push(value)
// After (desugared by compiler):
local method_ref = Callable.ref_method(arr, :push, 1)
local result = method_ref.call([value])
// Which internally calls:
// Resolver.lookup(arr.type_id, "push", 1) -> handle
// ExecBox.call_by_handle(handle, [value], NoOperatorGuard)
Deliverables:
exec_box.hakoimplementationno_operator_guard_box.hakoimplementation- Macro desugaring implementation (compiler side)
- 25 test cases
Testing:
tests/golden/phase-c/callable/
├── test_call_by_handle.hako
├── test_no_operator_guard.hako
├── test_macro_desugar_method.hako
├── test_macro_desugar_operator.hako
└── ... (21 more)
Week 11: Universal Route Minimization (2026-05-10 - 05-16)
Goal: Remove all special-case dispatch, delegate everything to Resolver.
Before (multiple dispatch paths):
// Rust VM (old approach)
match call_type {
Global => dispatch_global(...),
BoxMethod => dispatch_box_method(...),
Closure => dispatch_closure(...),
Constructor => dispatch_constructor(...),
ModuleFunction => dispatch_module_function(...),
// 5 different code paths!
}
After (single dispatch path):
// Hakorune VM (unified approach)
// All calls:
local handle = Resolver.lookup(type_id, method, arity)
local result = ExecBox.call_by_handle(handle, args, NoOperatorGuard)
// No special cases!
Removal List:
- ❌ Remove: Special-case dispatch (Global/Box/Closure/Constructor/Module)
- ❌ Remove: Hardcoded method tables
- ❌ Remove: Fallback implementations (use Fail-Fast instead)
Deliverables:
- Special-case dispatch removal complete
- Codebase cleanup (reduce complexity)
- 30 edge case tests (ensure Fail-Fast works)
Testing:
tests/golden/phase-c/unification/
├── test_no_global_special_case.hako
├── test_no_box_special_case.hako
├── test_fail_fast_unknown_method.hako
├── test_fail_fast_wrong_arity.hako
└── ... (26 more)
Week 12: Integration + Documentation (2026-05-17 - 05-24)
Goal: Phase 20.6 completion report.
Integration Testing:
- Re-run all Golden Tests (100+ tests ALL PASS)
- Performance testing (≥ 50% of Rust-VM)
- Stress testing (large programs)
- Regression testing (no breakage)
Performance Benchmark:
# Benchmark script
bash tools/benchmark_hakorune_vm.sh
# Expected output:
# Rust-VM: 10.2s
# Hako-VM: 18.5s (55% of Rust-VM) ✅
# Memory: 180MB (< 200MB target) ✅
Documentation:
- VM Core Complete Reference
- Dispatch Unification Design Doc
- Performance Report
- Phase 20.6 Completion Report
- Phase 20.7 Planning Doc
Success Criteria (DoD)
Technical
-
VM Core Complete:
- All 16 MIR instructions working
- Control flow complete (branch, phi, loopform)
- Memory operations complete (load, store, copy)
-
Golden Tests:
- 100+ test cases ALL PASS
- Rust-VM vs Hako-VM: 100% output match
- Edge cases covered
-
Dispatch Unified:
- All method calls go through Resolver
- Special-case dispatch completely removed
- Fail-Fast verified (unknown methods → immediate error)
Performance
- Hako-VM ≥ 50% of Rust-VM (execution speed)
- Memory usage: < 200MB (typical programs)
- Compile time: < 10s (small programs)
Quality
- Test coverage: All instructions and control paths covered
- Documentation: Architecture, design, migration guide complete
- Code review: Approved by ChatGPT + Claude
Risk Mitigation
Risk 1: Implementation Complexity
Issue: Implementing all 16 instructions is complex.
Impact: HIGH
Mitigation:
- Use Rust VM as reference implementation
- Incremental implementation (2-4 instructions/week)
- Dedicated test suite per instruction
- Golden Tests catch bugs early
Risk 2: Dispatch Unification Difficulty
Issue: Removing special cases has wide impact.
Impact: MEDIUM
Mitigation:
- Gradual migration: Add new code → Test → Remove old code
- Implement and test Resolver first
- Feature flag for toggle
- Strengthen regression tests
Risk 3: Performance Degradation
Issue: Hako-VM may be slower than Rust-VM.
Impact: MEDIUM
Mitigation:
- Initial target: 50% (acceptable)
- Weekly benchmark measurements
- Early bottleneck identification
- Optimization deferred to Phase 20.7
Risk 4: Golden Test Mismatches
Issue: Rust-VM and Hako-VM outputs may differ.
Impact: HIGH
Mitigation:
- Ensure determinism (JSON normalization, sorted keys)
- Replace float operations with integers
- Eliminate randomness (timestamps, PIDs)
- Detailed diff logging
Test Strategy
Golden Test Framework
Goal: Prove Hakorune-VM produces identical output to Rust-VM.
Test Suite Structure:
tests/golden/
├── phase-b/ # Week 1-6 (VM Core)
│ ├── memory/ # 10 tests (load, store, copy)
│ ├── calls/ # 15 tests (call, boxcall, externcall)
│ ├── types/ # 10 tests (typeop, newbox)
│ └── control/ # 15 tests (barrier, safepoint, loopform)
├── phase-c/ # Week 7-12 (Dispatch)
│ ├── resolver/ # 20 tests (lookup, registration)
│ ├── callable/ # 25 tests (call_by_handle, guard)
│ └── unification/ # 30 tests (edge cases, Fail-Fast)
└── integration/ # Week 12
├── arithmetic.hako # Basic arithmetic
├── control_flow.hako # if/loop/branch
├── collections.hako # Array/Map operations
├── recursion.hako # Recursive functions
├── strings.hako # String manipulation
├── enums.hako # @enum types
└── closures.hako # Closure capture
Verification Script:
#!/bin/bash
# tools/golden_test_hakorune_vm.sh
for test in tests/golden/**/*.hako; do
echo "Testing: $test"
# Run on Rust VM
./hako --backend vm-rust "$test" > /tmp/rust_out.txt 2>&1
rust_exit=$?
# Run on Hakorune VM
./hako --backend vm "$test" > /tmp/hako_out.txt 2>&1
hako_exit=$?
# Compare outputs
if diff /tmp/rust_out.txt /tmp/hako_out.txt && [ $rust_exit -eq $hako_exit ]; then
echo " ✅ PASS"
else
echo " ❌ FAIL"
exit 1
fi
done
echo "✅ All Golden Tests PASSED!"
CI Integration
# .github/workflows/golden_tests.yml
name: Golden Tests (Phase 20.6)
on: [push, pull_request]
jobs:
golden-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build Hakorune
run: cargo build --release
- name: Run Golden Tests
run: bash tools/golden_test_hakorune_vm.sh
- name: Performance Benchmark
run: |
bash tools/benchmark_hakorune_vm.sh
# Verify: Hako-VM ≥ 50% of Rust-VM
Dependencies
From Phase 20.5
- HostBridge API (C-ABI boundary)
- op_eq Migration (NoOperatorGuard)
- VM Foundations PoC (5 instructions)
For Phase 20.6
- Resolver design finalized (Week 7)
- MethodHandle design finalized (Week 7)
- Golden Test infrastructure ready (Week 1)
- Benchmark infrastructure ready (Week 1)
Next Steps (Actionable)
-
Week 1 Preparation (before 2026-03-01):
- Lock Golden Test list (100+ tests)
- Set up test infrastructure
- Prepare benchmark suite
- Review Phase 20.5 deliverables
-
Week 1-6 Execution:
- Implement instructions incrementally
- Run Golden Tests continuously
- Measure performance weekly
-
Week 7-12 Execution:
- Implement Resolver + CallableBox
- Remove special-case dispatch
- Verify Fail-Fast behavior
-
Week 12 Completion:
- All Golden Tests PASS
- Performance ≥ 50% verified
- Documentation complete
- Phase 20.7 planning doc ready
Created: 2025-10-14 Phase Start: 2026-03-01 Phase End: 2026-05-24 Duration: 12 weeks Prerequisite: Phase 20.5 complete Success: VM Core Complete + Dispatch Unified ✅