fix(llvm): Use nyash.any.toString_h for universal slot #0 - Phase 287 P4

SSOT unification: All toString calls now use nyash.any.toString_h(handle)
instead of plugin invoke system. This works for ALL types:
- IntegerBox, FloatBox, BoolBox, StringBox
- ArrayBox, MapBox, user-defined boxes

Changes:
- LLVM boxcall.py: Replace plugin invoke with direct nyash.any.toString_h call
- Deleted complex 6-argument plugin invoke for method_id=0
- Primitive i64 → box via nyash.box.from_i64 → toString via universal SSOT

Test Results (VM/LLVM parity achieved):
 VM: local x = 1; print(x.toString()) → "1"
 LLVM: local x = 1; print(x.toString()) → "1"
 VM: array_length (boxed Integer) → "0\n1\n2\n3"
 LLVM: array_length (boxed Integer) → "0\n1\n2\n3"

SSOT: nyash.any.toString_h = universal slot #0 handler (kernel)

Files changed:
- src/llvm_py/instructions/boxcall.py (universal slot #0 handler)

🎊 Generated with Claude Code
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-25 11:46:48 +09:00
parent c117a04035
commit b696f6c4c4

View File

@ -103,8 +103,8 @@ def lower_boxcall(
if recv_val is None:
recv_val = ir.Constant(i64, 0)
# Phase 287 P4: Box primitive i64 first, then invoke toString via universal slot #0
# SSOT: nyash_box_from_i64 creates IntegerBox handle, then plugin invoke with method_id=0
# Phase 287 P4: Box primitive i64 first, then call universal slot #0 SSOT
# SSOT: nyash.any.toString_h(handle) -> StringBox handle (works for ALL types)
if hasattr(recv_val, 'type') and isinstance(recv_val.type, ir.IntType) and recv_val.type.width == 64:
# Step 1: Box primitive i64 → IntegerBox handle
box_i64_fn = _declare(module, "nyash.box.from_i64", i64, [i64])
@ -116,16 +116,12 @@ def lower_boxcall(
# Already a handle
recv_h = _ensure_handle(builder, module, recv_val)
# Step 2: Invoke toString via universal slot #0 using plugin system
invoke_fn = _declare(module, "nyash_plugin_invoke3_i64", i64, [i64, i64, i64, i64, i64, i64])
type_id = ir.Constant(i64, 0) # Type resolution deferred to runtime
mid = ir.Constant(i64, 0) # method_id=0 for toString (universal slot)
argc = ir.Constant(i64, 0) # No args for toString
a1 = ir.Constant(i64, 0)
a2 = ir.Constant(i64, 0)
result = builder.call(invoke_fn, [type_id, mid, argc, recv_h, a1, a2], name="slot0_tostring")
# Step 2: Call universal slot #0 via nyash.any.toString_h (SSOT - no plugin invoke)
# This works for IntegerBox, FloatBox, BoolBox, StringBox, ArrayBox, etc.
tostring_fn = _declare(module, "nyash.any.toString_h", i64, [i64])
result = builder.call(tostring_fn, [recv_h], name="slot0_tostring")
if os.environ.get('NYASH_LLVM_TRACE_SLOT') == '1':
print(f"[llvm-py/slot] Invoked toString via plugin (method_id=0) on handle", file=sys.stderr)
print(f"[llvm-py/slot] Called nyash.any.toString_h (universal slot #0)", file=sys.stderr)
if dst_vid is not None:
vmap[dst_vid] = result