## Summary Implemented fail-fast validation for PHI ordering and value resolution in strict mode. ## Changes ### P1-1: Strict mode for "PHI after terminator" - File: `src/llvm_py/phi_wiring/wiring.py::ensure_phi` - Behavior: `NYASH_LLVM_PHI_STRICT=1` → RuntimeError if PHI created after terminator - Default: Warning only (no regression) ### P1-2: Strict mode for "fallback 0" - File: `src/llvm_py/phi_wiring/wiring.py::wire_incomings` - Behavior: Strict mode forbids silent fallback to 0 (2 locations) - Location 1: Unresolvable incoming value - Location 2: Type coercion failure - Error messages point to next debug file: `llvm_builder.py::_value_at_end_i64` ### P1-3: Connect verify_phi_ordering() to execution path - File: `src/llvm_py/builders/function_lower.py` - Behavior: Verify PHI ordering after all instructions emitted - Debug mode: Shows "✅ All N blocks have correct PHI ordering" - Strict mode: Raises RuntimeError with block list if violations found ## Testing ✅ Test 1: strict=OFF - passes without errors ✅ Test 2: strict=ON - passes without errors (no violations in test fixtures) ✅ Test 3: debug mode - verify_phi_ordering() connected and running ## Scope - LLVM harness (Python) changes only - No new environment variables (uses existing 3 from Phase 277 P2) - No JoinIR/Rust changes (root fix is Phase 279) - Default behavior unchanged (strict mode opt-in) ## Next Steps - Phase 278: Remove deprecated env var support - Phase 279: Root fix - unify "2本のコンパイラ" pipelines 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
4.4 KiB
4.4 KiB
Phase 274 (active): Type SSOT Alignment (local + dynamic runtime)
Status: active / design-first
Goal: make the language-level type semantics and the runtime behavior consistent and easy to reason about, without turning Nyash into a statically typed language.
This phase is about:
- clarifying SSOT docs,
- closing “frontend emits it but VM can’t run it” gaps,
- and preventing “type facts / resolver guessing” from silently becoming language semantics.
Background (why this exists)
Current state:
- Nyash is dynamic at runtime (VM executes tagged values).
- MIR builder attaches type metadata (
value_types,value_origin_newbox) for routing/optimization. - Some docs describe stricter semantics than the VM actually implements.
TypeOpis emitted by the frontend foris/as.
Problems:
- Spec drift: quick docs vs runtime behavior differ (truthiness / equality / compare /
+). - Capability drift across backends: “VM is correct” but “LLVM harness differs” (TypeOp).
- Type metadata risks becoming implicit semantics via resolver fallback chains.
SSOT decisions should be expressed in:
- language docs (meaning),
- runtime (execution),
- and only then optimization facts (rewrite / routing).
SSOT references
- Language type semantics (SSOT):
docs/reference/language/types.md - VM semantics source:
src/backend/abi_util.rs,src/backend/mir_interpreter/helpers.rs - MIR type vocabulary:
src/mir/types.rs - Call certainty vocabulary:
src/mir/definitions/call_unified.rs
Scope (P0/P1/P2/P3)
P0 (docs-only): establish SSOT and remove contradictions
Deliverables:
docs/reference/language/types.md(SSOT)- Quick-reference points to SSOT and stops contradicting runtime
Acceptance:
- docs no longer claim semantics that the Rust VM clearly violates.
P1 (impl): make TypeOp runnable on Rust VM
Goal:
x.is("T")/x.as("T")lowering exists already; make it executable on the primary backend (Rust VM).
Acceptance (minimum):
- Rust VM implements
MirInstruction::TypeOp { op: Check|Cast, value, ty } - Add a small executable fixture/smoke that exercises
is/as - No new env vars; fail-fast errors on unsupported casts/checks
Implementation guide:
docs/development/current/main/phases/phase-274/P1-INSTRUCTIONS.md
Status: ✅ done (2025-12-22)
Artifacts:
- Fixture:
apps/tests/phase274_p1_typeop_is_as_min.hako - Smoke:
tools/smokes/v2/profiles/integration/apps/phase274_p1_typeop_is_as_vm.sh - VM handler:
src/backend/mir_interpreter/handlers/type_ops.rs
P2 (impl): align LLVM (llvmlite harness) TypeOp to SSOT
Goal:
- Make LLVM harness behavior match Rust VM (SSOT) for
TypeOp(Check/Cast).
Current mismatch:
src/llvm_py/instructions/typeop.pyis stubbed:isreturns 0 for most types (special-casesIntegerBoxas “non-zero”)cast/asare pass-through
Acceptance (minimum):
- With
NYASH_LLVM_USE_HARNESS=1+--backend llvm, the P1 fixture has the same observable result as Rust VM. - Unsupported cases fail-fast (TypeError), not silent 0/“passthrough”.
- No new environment-variable toggles; differences must be fixed or explicitly documented.
Implementation guide:
docs/development/current/main/phases/phase-274/P2-INSTRUCTIONS.md
Status: ✅ done (2025-12-22)
Artifacts:
- Kernel type check helper:
crates/nyash_kernel/src/lib.rs(nyash.any.is_type_h) - LLVM TypeOp lowering:
src/llvm_py/instructions/typeop.py - MIR JSON emission fix (bin):
src/runner/mir_json_emit.rs(emitop:"typeop") - Fixture (LLVM-safe):
apps/tests/phase274_p2_typeop_primitives_only.hako - Smoke (LLVM):
tools/smokes/v2/profiles/integration/apps/phase274_p2_typeop_is_as_llvm.sh
P3 (decision + optional impl): tighten or document coercions
Decision points to settle (SSOT):
- Truthiness for arbitrary BoxRef (allow “any object is truthy” vs fail-fast)
- Equality cross-coercions (
int↔bool,int↔float) — keep, restrict, or gate behind a profile +mixed numeric types (int+float) — keep TypeError or add explicit conversions
Acceptance:
- whichever behavior is chosen becomes consistent across backends and docs.
Decision memo (P3):
docs/development/current/main/phases/phase-274/P3-DECISIONS.md
Status:
- P3 decisions are ✅ accepted; implementation is tracked in Phase 275.
Non-goals
- Full static typing / inference engine
- Widening the language surface area (new keywords) as the first move
- Adding more environment-variable toggles as a long-term solution