Files
hakorune/src/mir/control_tree/normalized_shadow/builder.rs

83 lines
3.2 KiB
Rust
Raw Normal View History

//! Phase 121: StepTree → JoinModule shadow lowering (if-only)
//!
//! ## Responsibility
//!
//! - Convert StepTree to JoinModule (Normalized dialect)
//! - Only for if-only patterns (no loops)
//! - Returns None for out-of-scope patterns
//! - Returns Err for patterns that should be supported but conversion failed
use crate::mir::control_tree::normalized_shadow::env_layout::{
expected_env_field_count as calc_expected_env_fields, EnvLayout,
};
use crate::mir::control_tree::normalized_shadow::if_as_last_join_k::IfAsLastJoinKLowererBox;
use crate::mir::control_tree::normalized_shadow::legacy::LegacyLowerer;
use crate::mir::control_tree::step_tree::StepTree;
use crate::mir::join_ir::lowering::carrier_info::JoinFragmentMeta;
use crate::mir::join_ir::JoinModule;
use crate::mir::ValueId; // Phase 126
use std::collections::BTreeMap; // Phase 126
use super::contracts::{check_if_only, CapabilityCheckResult};
/// Box-First: StepTree → Normalized shadow lowering
pub struct StepTreeNormalizedShadowLowererBox;
impl StepTreeNormalizedShadowLowererBox {
/// Phase 129-B: Expected env field count (writes + inputs)
pub fn expected_env_field_count(
step_tree: &StepTree,
available_inputs: &BTreeMap<String, ValueId>,
) -> usize {
calc_expected_env_fields(step_tree, available_inputs)
}
/// Phase 129-B: If-as-last shape detection (no post-if)
pub fn expects_join_k_as_last(step_tree: &StepTree) -> bool {
IfAsLastJoinKLowererBox::expects_join_k_as_last(step_tree)
}
/// Try to lower an if-only StepTree to normalized form
///
/// - `Ok(None)`: Out of scope (e.g., contains loops)
/// - `Ok(Some(...))`: Shadow generation succeeded
/// - `Err(...)`: Should be supported but conversion failed (internal error)
pub fn try_lower_if_only(
step_tree: &StepTree,
available_inputs: &BTreeMap<String, ValueId>,
) -> Result<Option<(JoinModule, JoinFragmentMeta)>, String> {
let capability = check_if_only(step_tree);
match capability {
CapabilityCheckResult::Supported => {
Self::lower_if_only_to_normalized(step_tree, available_inputs)
}
CapabilityCheckResult::Unsupported(_reason) => Ok(None),
}
}
/// Lower if-only StepTree to Normalized JoinModule (Phase 122-126)
fn lower_if_only_to_normalized(
step_tree: &StepTree,
available_inputs: &BTreeMap<String, ValueId>,
feat(control_tree): Phase 123 if-only compare+return lowering (Normalized, dev-only) Implements Phase 123 P3: If(cond_ast) minimal lowering with graceful degradation. **What's Implemented**: - If node lowering with minimal binary comparison (Variable op Integer) - Supported operators: ==, !=, <, <=, >, >= - Generates: Compare + Const + Ret structure - Graceful degradation: returns Ok(None) for unsupported patterns **Key Design Decisions**: 1. **Graceful Degradation**: Phase 123 limitations return `Ok(None)` instead of failing - Allows dev-only mode to coexist with legacy code - Error messages prefixed with `[phase123/...]` are caught 2. **Fail-Fast with Structured Errors**: All limitations use structured error codes - Format: `[phase123/category/specific]` 3. **Box-First Principles**: - `parse_minimal_compare`: Single responsibility parser - `verify_branch_is_return_literal`: Branch validation box - `lower_if_node`: If lowering box **Implementation**: - Added `lower_if_node`: If lowering with minimal compare - Added `parse_minimal_compare`: Binary comparison parser - Added `verify_branch_is_return_literal`: Branch validator - Updated `lower_if_only_to_normalized` return type: `Result<Option<...>, ...>` - Updated `test_return_variable_out_of_scope`: Verifies graceful degradation - Added `test_if_minimal_compare`: Verifies If lowering structure **Tests**: 8 passed (including graceful degradation test) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 05:50:09 +09:00
) -> Result<Option<(JoinModule, JoinFragmentMeta)>, String> {
// Phase 126: EnvLayout 生成available_inputs を使用)
let env_layout = EnvLayout::from_contract(&step_tree.contract, available_inputs);
refactor(control_tree): Phase 125 P2-P4 introduce EnvLayout (writes+inputs) + Return(Variable) from inputs Phase 125 P2: EnvLayout introduction - Add EnvLayout struct (writes + inputs) - from_contract() creates layout from StepTreeContract + available_inputs - SSOT: inputs = reads ∩ available_inputs (deterministic order) - No AST inference (don't capture from AST, use provided available_inputs) Phase 125 P2: Builder env mapping - lower_if_only_to_normalized: Use EnvLayout to create env map - writes: Generate ValueId (as before) - inputs: Reference ValueId from available_inputs (placeholder for P3) - Function params: writes only (inputs come from outer scope) Phase 125 P4: Return(Variable) resolution extended - lower_return_value: Check env (writes + inputs) - If found: return it (Phase 124 for writes, Phase 125 for inputs) - If not found: Fail-Fast with structured error + hint - Hint: "Pass as param, add to pinned capture, or define before if" - Phase 125 errors return Ok(None) (out of scope, graceful degradation) Unit tests: - test_return_variable_from_env: PASS (Phase 124 regression) - test_return_variable_out_of_scope: PASS (updated for Phase 125) - test_return_variable_from_inputs_stub: PASS (P3 not wired yet) - All 1160 lib tests PASS (no regression) Note: - P3 (available_inputs wiring) not implemented yet - available_inputs is empty BTreeMap (stub) - EnvLayout.inputs will be empty until P3 is wired - Structured error tags: [phase125/return/var_not_in_env] Ref: docs/development/current/main/phases/phase-125/README.md
2025-12-18 06:30:55 +09:00
// Phase 129-B: If-as-last join_k lowering (dev-only)
if let Some((module, meta)) = IfAsLastJoinKLowererBox::lower(step_tree, &env_layout)? {
return Ok(Some((module, meta)));
}
// Legacy path (Phase 123-128 scope)
LegacyLowerer::lower_if_only_to_normalized(step_tree, &env_layout)
}
/// Dev log helper for out-of-scope cases
pub fn get_status_string(step_tree: &StepTree) -> String {
format!(
"shadow=skipped signature_basis={}",
step_tree.signature_basis_string()
)
refactor(control_tree): Phase 125 P2-P4 introduce EnvLayout (writes+inputs) + Return(Variable) from inputs Phase 125 P2: EnvLayout introduction - Add EnvLayout struct (writes + inputs) - from_contract() creates layout from StepTreeContract + available_inputs - SSOT: inputs = reads ∩ available_inputs (deterministic order) - No AST inference (don't capture from AST, use provided available_inputs) Phase 125 P2: Builder env mapping - lower_if_only_to_normalized: Use EnvLayout to create env map - writes: Generate ValueId (as before) - inputs: Reference ValueId from available_inputs (placeholder for P3) - Function params: writes only (inputs come from outer scope) Phase 125 P4: Return(Variable) resolution extended - lower_return_value: Check env (writes + inputs) - If found: return it (Phase 124 for writes, Phase 125 for inputs) - If not found: Fail-Fast with structured error + hint - Hint: "Pass as param, add to pinned capture, or define before if" - Phase 125 errors return Ok(None) (out of scope, graceful degradation) Unit tests: - test_return_variable_from_env: PASS (Phase 124 regression) - test_return_variable_out_of_scope: PASS (updated for Phase 125) - test_return_variable_from_inputs_stub: PASS (P3 not wired yet) - All 1160 lib tests PASS (no regression) Note: - P3 (available_inputs wiring) not implemented yet - available_inputs is empty BTreeMap (stub) - EnvLayout.inputs will be empty until P3 is wired - Structured error tags: [phase125/return/var_not_in_env] Ref: docs/development/current/main/phases/phase-125/README.md
2025-12-18 06:30:55 +09:00
}
}