Files
hakorune/docs/development/current/main/phase56-ownership-relay-design.md
nyash-codex 2d10c5ce3f docs(joinir): Phase 56 - Ownership-Relay Design + interface skeleton
「読むのは自由、管理は直下 owned だけ」アーキテクチャの設計文書と型定義。

Key changes:
- Design doc: phase56-ownership-relay-design.md
  - Core definitions: owned/carriers/captures/relay
  - Invariants: Ownership Uniqueness, Carrier Locality, Relay Propagation
  - Shadowing rules, multi-writer merge semantics
  - JoinIR mapping from current system to new system
  - Implementation phases roadmap (56-61)

- New module: src/mir/join_ir/ownership/
  - types.rs: ScopeId, ScopeOwnedVar, RelayVar, CapturedVar, OwnershipPlan
  - mod.rs: Module documentation with responsibility boundaries
  - README.md: Usage guide and examples

- API methods:
  - OwnershipPlan::carriers() - owned AND written variables
  - OwnershipPlan::condition_only_carriers() - condition-only carriers
  - OwnershipPlan::verify_invariants() - invariant checking

Tests: 942/942 PASS (+3 unit tests)
Zero behavioral change - analysis module skeleton only.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-12 17:39:59 +09:00

225 lines
5.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Phase 56: Ownership-Relay Design
## Overview
「読むのは自由、管理は直下 owned だけ」アーキテクチャの設計文書。
Phase 56 は **インターフェース設計のみ**。実装は Phase 57 以降。
## Core Definitions
### owned (所有)
- 変数を定義したスコープが唯一の owner
- Loop直下の `local x` → そのループが owned
- body-localif/block内の local→ 最も内側の enclosing loop が owned
**例**:
```rust
fn outer() {
local a = 0 // owned by outer
loop {
local b = 0 // owned by this loop
if cond {
local c = 0 // owned by enclosing loop (not if!)
}
}
}
```
### carriers (管理対象)
- `carriers = writes ∩ owned`
- そのスコープが定義 AND 更新する変数のみ
- loop_step の引数として管理
**重要**: Carrier は「所有 AND 更新」のみ。読み取り専用の owned 変数は carrier ではない。
### captures (読み取り参照)
- `captures = reads \ owned` (かつ carriers ではない)
- 祖先スコープの変数への read-only アクセス
- CapturedEnv / ConditionEnv 経由
**例**:
```rust
local limit = 100
loop {
local sum = 0
if sum < limit { // limit は capture (read-only)
sum++ // sum は carrier (owned + written)
}
}
```
### relay (中継)
- 内側スコープが祖先 owned を更新する場合
- 更新責務を owner へ昇格relay up
- 中間ループは引数として素通し
**例**:
```rust
loop outer {
local total = 0 // owned by outer
loop inner {
total++ // relay to outer (inner doesn't own total)
}
}
// outer の exit PHI で total を merge
```
## Invariants (不変条件)
1. **Ownership Uniqueness**: 各変数は唯一の owner を持つ
2. **Carrier Locality**: carriers = writes ∩ owned (借用なし)
3. **Relay Propagation**: writes \ owned → owner に昇格
4. **Capture Read-Only**: captures は read-only (PHI 不要)
## Shadowing Rules
```nyash
local x = 0 // outer owned
loop {
local x = 1 // inner owned (shadows outer)
// 外の x は capture 可能だが、inner の x が優先
print(x) // inner の x (1)
}
print(x) // outer の x (0)
```
- Shadowing = 新しい ownership 発生
- 名前解決は最内スコープ優先
- 外の x は capture として参照可能だが、内の x が存在する限り内が優先
## Multi-Writer Merge
```nyash
loop outer {
local total = 0
if a { loop inner1 { total++ } } // relay to outer
if b { loop inner2 { total-- } } // relay to outer
}
// outer の exit PHI で merge
```
- Relay は「更新意図の伝達」
- 実際の PHI merge は owner 側で実行
- 複数の内側ループが同じ変数を relay → owner の exit PHI で統合
## JoinIR Mapping
### Current System → New System
| Current | New |
|---------|-----|
| CarrierInfo.carriers | OwnershipPlan.owned_carriers |
| promoted_loopbodylocals | (absorbed into owned analysis) |
| CapturedEnv | OwnershipPlan.captures |
| ConditionEnv | OwnershipPlan.condition_captures |
| (implicit) | OwnershipPlan.relay_writes |
### OwnershipPlan Structure
```rust
pub struct OwnershipPlan {
pub scope_id: ScopeId,
pub owned_carriers: Vec<ScopeOwnedVar>,
pub relay_writes: Vec<RelayVar>,
pub captures: Vec<CapturedVar>,
pub condition_captures: Vec<CapturedVar>,
}
```
**設計意図**:
- `owned_carriers`: このスコープが所有 AND 更新する変数
- `relay_writes`: 祖先の変数への書き込みowner へ昇格)
- `captures`: 祖先の変数への読み取り専用参照
- `condition_captures`: captures のうち、条件式で使われるもの
## Implementation Phases
- **Phase 56**: Design + interface skeleton (this phase) ✅
- **Phase 57**: OwnershipAnalyzer implementation (dev-only)
- **Phase 58**: P2 plumbing (dev-only)
- **Phase 59**: P3 plumbing (dev-only)
- **Phase 60**: Cleanup dev heuristics
- **Phase 61**: Canonical promotion decision
## Module Boundary
`src/mir/join_ir/ownership/` - 責務は「解析のみ」
**This module does**:
- ✅ Collect reads/writes from AST/ProgramJSON
- ✅ Determine variable ownership (owned/relay/capture)
- ✅ Produce OwnershipPlan for downstream lowering
**This module does NOT**:
- ❌ Generate MIR instructions
- ❌ Modify JoinIR structures
- ❌ Perform lowering transformations
Lowering/MIR生成は既存モジュールが担当。
## Example Ownership Plans
### Example 1: Simple Loop
```nyash
local sum = 0
loop {
sum++
}
```
**OwnershipPlan (loop scope)**:
- `owned_carriers`: [`sum` (written)]
- `relay_writes`: []
- `captures`: []
### Example 2: Nested Loop with Relay
```nyash
local total = 0
loop outer {
loop inner {
total++
}
}
```
**OwnershipPlan (inner loop)**:
- `owned_carriers`: []
- `relay_writes`: [`total` → relay to outer]
- `captures`: []
**OwnershipPlan (outer loop)**:
- `owned_carriers`: [`total` (written via relay)]
- `relay_writes`: []
- `captures`: []
### Example 3: Capture + Carrier
```nyash
local limit = 100
loop {
local sum = 0
if sum < limit {
sum++
}
}
```
**OwnershipPlan (loop scope)**:
- `owned_carriers`: [`sum` (written)]
- `relay_writes`: []
- `captures`: [`limit` (read-only)]
- `condition_captures`: [`limit`]
## References
- **Phase 53-54**: Structural axis expansion
- **Phase 43/245B**: Normalized JoinIR completion
- **ChatGPT discussion**: 「読むのは自由、管理は直下だけ」設計
- **JoinIR Architecture**: [joinir-architecture-overview.md](joinir-architecture-overview.md)
## Status
- ✅ Phase 56 (this): Design + interface skeleton completed
- ⏳ Phase 57+: Implementation pending