feat(joinir/dev): Phase 126 wire available_inputs into normalized builder
- AvailableInputsCollectorBox::collect() called in lower_function_body (dev-only) - try_lower_if_only() signature extended (accepts available_inputs) - EnvLayout::from_contract() now uses real available_inputs (not empty stub) - Unit tests updated (empty BTreeMap for backward compat) - All 23 normalized_shadow tests PASS
This commit is contained in:
@ -16,6 +16,8 @@
|
||||
use crate::mir::control_tree::step_tree::StepTree;
|
||||
use crate::mir::join_ir::lowering::carrier_info::{ExitMeta, 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};
|
||||
|
||||
@ -89,21 +91,27 @@ impl StepTreeNormalizedShadowLowererBox {
|
||||
/// - Uses contract information only (no AST re-analysis)
|
||||
/// - Dev-only: caller must check `joinir_dev_enabled()` before calling
|
||||
///
|
||||
/// ## Phase 122 Implementation
|
||||
/// ## Phase 122-126 Implementation
|
||||
///
|
||||
/// - Generates Normalized JoinIR (env + continuation)
|
||||
/// - env layout: writes only (SSOT)
|
||||
/// - env layout: writes + inputs (Phase 125-126)
|
||||
/// - merge = join_k(env) tail-call (no PHI)
|
||||
/// - Minimal node support: If/Return/Assign(Const/Variable/BinOp(Add))
|
||||
///
|
||||
/// ## Phase 126: available_inputs
|
||||
///
|
||||
/// - available_inputs: function params + CapturedEnv (SSOT)
|
||||
/// - inputs = reads ∩ available_inputs (deterministic order)
|
||||
pub fn try_lower_if_only(
|
||||
step_tree: &StepTree,
|
||||
available_inputs: &BTreeMap<String, ValueId>,
|
||||
) -> Result<Option<(JoinModule, JoinFragmentMeta)>, String> {
|
||||
// Phase 121 P1: Capability check (if-only scope)
|
||||
let capability = check_if_only(step_tree);
|
||||
match capability {
|
||||
CapabilityCheckResult::Supported => {
|
||||
// Phase 122-123: Generate Normalized JoinModule
|
||||
Self::lower_if_only_to_normalized(step_tree)
|
||||
// Phase 122-126: Generate Normalized JoinModule
|
||||
Self::lower_if_only_to_normalized(step_tree, available_inputs)
|
||||
}
|
||||
CapabilityCheckResult::Unsupported(_reason) => {
|
||||
// Out of scope for Phase 121/122
|
||||
@ -112,7 +120,7 @@ impl StepTreeNormalizedShadowLowererBox {
|
||||
}
|
||||
}
|
||||
|
||||
/// Lower if-only StepTree to Normalized JoinModule (Phase 122-125)
|
||||
/// Lower if-only StepTree to Normalized JoinModule (Phase 122-126)
|
||||
///
|
||||
/// ## Design
|
||||
///
|
||||
@ -120,31 +128,33 @@ impl StepTreeNormalizedShadowLowererBox {
|
||||
/// - merge 形式: `join_k(env)` への tail-call(PHI 禁止)
|
||||
/// - 対応ノード: If/Return/Assign(最小セット)
|
||||
///
|
||||
/// ## Phase 123-125 Node Support
|
||||
/// ## Phase 123-126 Node Support
|
||||
///
|
||||
/// - Return(Integer literal): `Const + Ret(Some(vid))`
|
||||
/// - Return(Variable from writes): Phase 124
|
||||
/// - Return(Variable from inputs): Phase 125 (reads-only)
|
||||
/// - Return(Variable from inputs): Phase 125-126 (reads-only)
|
||||
/// - Return(void): `Ret(None)`
|
||||
/// - If(minimal compare): Compare with Integer literal only
|
||||
///
|
||||
/// ## Phase 126: available_inputs
|
||||
///
|
||||
/// - available_inputs: function params + CapturedEnv (SSOT)
|
||||
/// - inputs = reads ∩ available_inputs (deterministic order)
|
||||
///
|
||||
/// ## Returns
|
||||
///
|
||||
/// - `Ok(Some((module, meta)))`: Normalized JoinModule生成成功
|
||||
/// - `Ok(None)`: Out of scope for Phase 123-125 (unsupported patterns)
|
||||
/// - `Ok(None)`: Out of scope for Phase 123-126 (unsupported patterns)
|
||||
/// - `Err(msg)`: 生成できるはずなのに失敗(内部エラー)
|
||||
fn lower_if_only_to_normalized(
|
||||
step_tree: &StepTree,
|
||||
available_inputs: &BTreeMap<String, ValueId>,
|
||||
) -> Result<Option<(JoinModule, JoinFragmentMeta)>, String> {
|
||||
use crate::mir::join_ir::{JoinFunction, JoinFuncId, JoinInst};
|
||||
use crate::mir::ValueId;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
// Phase 125 P2: available_inputs (P3 で配線、今は空)
|
||||
let available_inputs: BTreeMap<String, ValueId> = BTreeMap::new();
|
||||
|
||||
// Phase 125 P2: EnvLayout 生成
|
||||
let env_layout = EnvLayout::from_contract(&step_tree.contract, &available_inputs);
|
||||
// Phase 126: EnvLayout 生成(available_inputs を使用)
|
||||
let env_layout = EnvLayout::from_contract(&step_tree.contract, available_inputs);
|
||||
|
||||
let main_func_id = JoinFuncId::new(0);
|
||||
|
||||
@ -679,7 +689,8 @@ mod tests {
|
||||
#[test]
|
||||
fn test_if_only_supported() {
|
||||
let tree = make_if_only_tree();
|
||||
let result = StepTreeNormalizedShadowLowererBox::try_lower_if_only(&tree);
|
||||
let available_inputs = BTreeMap::new(); // Phase 126: empty for unit tests
|
||||
let result = StepTreeNormalizedShadowLowererBox::try_lower_if_only(&tree, &available_inputs);
|
||||
assert!(result.is_ok());
|
||||
assert!(result.unwrap().is_some());
|
||||
}
|
||||
@ -687,7 +698,8 @@ mod tests {
|
||||
#[test]
|
||||
fn test_loop_rejected() {
|
||||
let tree = make_loop_tree();
|
||||
let result = StepTreeNormalizedShadowLowererBox::try_lower_if_only(&tree);
|
||||
let available_inputs = BTreeMap::new(); // Phase 126: empty for unit tests
|
||||
let result = StepTreeNormalizedShadowLowererBox::try_lower_if_only(&tree, &available_inputs);
|
||||
assert!(result.is_ok());
|
||||
assert!(result.unwrap().is_none());
|
||||
}
|
||||
@ -728,7 +740,8 @@ mod tests {
|
||||
};
|
||||
|
||||
// Lower to JoinModule
|
||||
let result = StepTreeNormalizedShadowLowererBox::try_lower_if_only(&tree);
|
||||
let available_inputs = BTreeMap::new(); // Phase 126: empty for unit tests
|
||||
let result = StepTreeNormalizedShadowLowererBox::try_lower_if_only(&tree, &available_inputs);
|
||||
assert!(result.is_ok());
|
||||
|
||||
let (module, _meta) = result.unwrap().expect("Should generate JoinModule");
|
||||
@ -772,7 +785,8 @@ mod tests {
|
||||
};
|
||||
|
||||
// Lower to JoinModule
|
||||
let result = StepTreeNormalizedShadowLowererBox::try_lower_if_only(&tree);
|
||||
let available_inputs = BTreeMap::new(); // Phase 126: empty for unit tests
|
||||
let result = StepTreeNormalizedShadowLowererBox::try_lower_if_only(&tree, &available_inputs);
|
||||
assert!(result.is_ok());
|
||||
|
||||
let (module, _meta) = result.unwrap().expect("Should generate JoinModule");
|
||||
@ -818,7 +832,8 @@ mod tests {
|
||||
|
||||
// Phase 125 P4: Lower to JoinModule - should return Ok(None)
|
||||
// because x is in reads but not in available_inputs (not in env)
|
||||
let result = StepTreeNormalizedShadowLowererBox::try_lower_if_only(&tree);
|
||||
let available_inputs = BTreeMap::new(); // Phase 126: empty for unit tests
|
||||
let result = StepTreeNormalizedShadowLowererBox::try_lower_if_only(&tree, &available_inputs);
|
||||
assert!(result.is_ok());
|
||||
let option = result.unwrap();
|
||||
assert!(option.is_none(), "Should return None when variable is in reads but not available as input");
|
||||
@ -876,7 +891,8 @@ mod tests {
|
||||
};
|
||||
|
||||
// Lower to JoinModule
|
||||
let result = StepTreeNormalizedShadowLowererBox::try_lower_if_only(&tree);
|
||||
let available_inputs = BTreeMap::new(); // Phase 126: empty for unit tests
|
||||
let result = StepTreeNormalizedShadowLowererBox::try_lower_if_only(&tree, &available_inputs);
|
||||
assert!(result.is_ok());
|
||||
|
||||
let (module, _meta) = result.unwrap().expect("Should generate JoinModule");
|
||||
@ -924,7 +940,8 @@ mod tests {
|
||||
};
|
||||
|
||||
// Lower to JoinModule - should succeed
|
||||
let result = StepTreeNormalizedShadowLowererBox::try_lower_if_only(&tree);
|
||||
let available_inputs = BTreeMap::new(); // Phase 126: empty for unit tests
|
||||
let result = StepTreeNormalizedShadowLowererBox::try_lower_if_only(&tree, &available_inputs);
|
||||
assert!(result.is_ok());
|
||||
|
||||
let option = result.unwrap();
|
||||
@ -980,7 +997,8 @@ mod tests {
|
||||
// Phase 125 P2-P4: Lower to JoinModule
|
||||
// Because available_inputs is empty (P3 not wired), x won't be in inputs
|
||||
// So this should return Ok(None) (out of scope)
|
||||
let result = StepTreeNormalizedShadowLowererBox::try_lower_if_only(&tree);
|
||||
let available_inputs = BTreeMap::new(); // Phase 126: empty for unit tests
|
||||
let result = StepTreeNormalizedShadowLowererBox::try_lower_if_only(&tree, &available_inputs);
|
||||
assert!(result.is_ok());
|
||||
let option = result.unwrap();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user