docs: ドキュメント配置ルール(SSOT)確立

## 追加内容
- CLAUDE.md にドキュメント配置ルール(SSOT)セクション追加
- DOCS_LAYOUT.md (SSOT): 置き場所ルール定義
- phases/README.md: Phase ドキュメント説明
- design/README.md: 設計図ドキュメント説明
- investigations/README.md: 調査ログ説明

## ルール概要
1. **Phase 文書** → phases/phase-<N>/
2. **設計図** → design/
3. **調査ログ** → investigations/ (結論を 10-Now/20-Decisions に反映)

## 導線
- CLAUDE.md で概要説明
- DOCS_LAYOUT.md で詳細定義(SSOT)
- 各フォルダ README で参照方法

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

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
nyash-codex
2025-12-14 18:27:24 +09:00
parent e4678585d5
commit 4b87b6cc88
12 changed files with 289 additions and 22 deletions

View File

@ -67,7 +67,7 @@ impl super::MirBuilder {
super::builder_calls::CallTarget::Global(name),
vec![lhs, rhs],
)?;
// 型注釈(Phase 3-B: value_origin_newbox もチェック&両方登録)
// Phase 196: TypeFacts SSOT - AddOperator call type annotation
let lhs_is_str = match self.value_types.get(&lhs) {
Some(MirType::String) => true,
Some(MirType::Box(bt)) if bt == "StringBox" => true,
@ -86,14 +86,17 @@ impl super::MirBuilder {
.map(|s| s == "StringBox")
.unwrap_or(false),
};
if lhs_is_str || rhs_is_str {
if lhs_is_str && rhs_is_str {
// BOTH are strings: result is string
self.value_types
.insert(dst, MirType::Box("StringBox".to_string()));
self.value_origin_newbox
.insert(dst, "StringBox".to_string());
} else {
} else if !lhs_is_str && !rhs_is_str {
// NEITHER is a string: numeric addition
self.value_types.insert(dst, MirType::Integer);
}
// else: Mixed - leave Unknown for use-site coercion
} else if all_call {
// Lower other arithmetic ops to operator boxes under ALL flag
let (name, guard_prefix) = match op {
@ -152,8 +155,10 @@ impl super::MirBuilder {
} else {
self.emit_instruction(MirInstruction::BinOp { dst, op, lhs, rhs })?;
}
// Phase 196: TypeFacts SSOT - BinOp type is determined by operands only
// String concatenation is handled at use-site in LLVM lowering
if matches!(op, crate::mir::BinaryOp::Add) {
// Phase 3-B: value_origin_newbox もチェック&両方登録
// Check if BOTH operands are known to be strings (TypeFacts)
let lhs_is_str = match self.value_types.get(&lhs) {
Some(MirType::String) => true,
Some(MirType::Box(bt)) if bt == "StringBox" => true,
@ -172,14 +177,18 @@ impl super::MirBuilder {
.map(|s| s == "StringBox")
.unwrap_or(false),
};
if lhs_is_str || rhs_is_str {
if lhs_is_str && rhs_is_str {
// BOTH are strings: result is definitely a string
self.value_types
.insert(dst, MirType::Box("StringBox".to_string()));
self.value_origin_newbox
.insert(dst, "StringBox".to_string());
} else {
} else if !lhs_is_str && !rhs_is_str {
// NEITHER is a string: numeric addition
self.value_types.insert(dst, MirType::Integer);
}
// else: Mixed types (string + int or int + string)
// Leave dst type as Unknown - LLVM will handle coercion at use-site
} else {
self.value_types.insert(dst, MirType::Integer);
}
@ -195,8 +204,10 @@ impl super::MirBuilder {
} else {
self.emit_instruction(MirInstruction::BinOp { dst, op, lhs, rhs })?;
}
// Phase 196: TypeFacts SSOT - BinOp type is determined by operands only
// String concatenation is handled at use-site in LLVM lowering
if matches!(op, crate::mir::BinaryOp::Add) {
// Phase 3-B: value_origin_newbox もチェック&両方登録
// Check if BOTH operands are known to be strings (TypeFacts)
let lhs_is_str = match self.value_types.get(&lhs) {
Some(MirType::String) => true,
Some(MirType::Box(bt)) if bt == "StringBox" => true,
@ -215,14 +226,18 @@ impl super::MirBuilder {
.map(|s| s == "StringBox")
.unwrap_or(false),
};
if lhs_is_str || rhs_is_str {
if lhs_is_str && rhs_is_str {
// BOTH are strings: result is definitely a string
self.value_types
.insert(dst, MirType::Box("StringBox".to_string()));
self.value_origin_newbox
.insert(dst, "StringBox".to_string());
} else {
} else if !lhs_is_str && !rhs_is_str {
// NEITHER is a string: numeric addition
self.value_types.insert(dst, MirType::Integer);
}
// else: Mixed types (string + int or int + string)
// Leave dst type as Unknown - LLVM will handle coercion at use-site
} else {
self.value_types.insert(dst, MirType::Integer);
}