feat(joinir): Phase 78 - BindingId infrastructure for promoted carriers (dev-only)
Phase 78 adds infrastructure to assign BindingIds to synthetic promoted carriers (e.g., is_digit_pos, is_ch_match), enabling type-safe promoted variable lookup without string-based naming conventions. Key Changes: 1. CarrierVar.binding_id field (dev-only): - Added Option<BindingId> to track BindingId for each carrier - Updated all constructors and struct instantiations 2. CarrierBindingAssigner Box (new file, 273 lines): - Allocates BindingIds for promoted carriers via builder.allocate_binding_id() - Records original → promoted mapping in promoted_bindings - Sets binding_id field on promoted CarrierVar - Includes 3 comprehensive unit tests 3. ConditionEnv.register_carrier_binding() (new method): - Registers carrier BindingId → ValueId mappings - Enables type-safe lookup via binding_id_map 4. Logging cleanup: - Gated 6 eprintln! statements with NYASH_JOINIR_DEBUG - Unified logging tags to [binding_pilot/*] Design Decisions: - Promoters create CarrierInfo, lowering code assigns BindingIds - CarrierBindingAssigner called from Pattern2/4 lowering (has builder access) - Clear documentation prevents misuse (promoters lack builder access) Files modified (18): - carrier_info.rs: binding_id field added to CarrierVar - carrier_binding_assigner.rs: New Box for BindingId allocation - condition_env.rs: register_carrier_binding() method - mod.rs: Module exports - pattern2_with_break.rs, pattern4_with_continue.rs: Updated for binding_id - loop_body_*_promoter.rs: Logging cleanup + binding_id in structs - phase78-bindingid-promoted-carriers.md: Architecture documentation Tests: 970/970 PASS (zero regressions) Status: Infrastructure complete, integration deferred to Phase 79 Next Phase: Wire CarrierBindingAssigner in Pattern2/4 lowering + E2E tests 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@ -173,11 +173,13 @@ impl LoopBodyCarrierPromoter {
|
||||
};
|
||||
}
|
||||
|
||||
eprintln!(
|
||||
"[promoter/pattern5] Phase 171-C: Found {} LoopBodyLocal variables: {:?}",
|
||||
body_locals.len(),
|
||||
body_locals
|
||||
);
|
||||
if std::env::var("NYASH_JOINIR_DEBUG").is_ok() || std::env::var("JOINIR_TEST_DEBUG").is_ok() {
|
||||
eprintln!(
|
||||
"[promoter/pattern5] Phase 171-C: Found {} LoopBodyLocal variables: {:?}",
|
||||
body_locals.len(),
|
||||
body_locals
|
||||
);
|
||||
}
|
||||
|
||||
// 2. break 条件を取得
|
||||
if request.break_cond.is_none() {
|
||||
@ -194,10 +196,12 @@ impl LoopBodyCarrierPromoter {
|
||||
// Phase 79: Use TrimDetector for pure detection logic
|
||||
if let Some(detection) = TrimDetector::detect(break_cond, request.loop_body, var_name)
|
||||
{
|
||||
eprintln!(
|
||||
"[promoter/pattern5] Trim pattern detected! var='{}', literals={:?}",
|
||||
detection.match_var, detection.comparison_literals
|
||||
);
|
||||
if std::env::var("NYASH_JOINIR_DEBUG").is_ok() || std::env::var("JOINIR_TEST_DEBUG").is_ok() {
|
||||
eprintln!(
|
||||
"[promoter/pattern5] Trim pattern detected! var='{}', literals={:?}",
|
||||
detection.match_var, detection.comparison_literals
|
||||
);
|
||||
}
|
||||
|
||||
// 昇格成功!
|
||||
let trim_info = TrimPatternInfo {
|
||||
@ -224,21 +228,23 @@ impl LoopBodyCarrierPromoter {
|
||||
// - extract_equality_literals
|
||||
}
|
||||
|
||||
/// Phase 78: Log promotion errors with clear messages (for Trim pattern)
|
||||
/// Phase 78: Log promotion errors with clear messages (for Trim pattern, gated)
|
||||
#[cfg(feature = "normalized_dev")]
|
||||
fn log_trim_promotion_error(error: &BindingRecordError) {
|
||||
match error {
|
||||
BindingRecordError::OriginalNotFound(name) => {
|
||||
eprintln!(
|
||||
"[trim_lowerer/warning] Original variable '{}' not found in binding_map",
|
||||
name
|
||||
);
|
||||
}
|
||||
BindingRecordError::PromotedNotFound(name) => {
|
||||
eprintln!(
|
||||
"[trim_lowerer/warning] Promoted variable '{}' not found in binding_map",
|
||||
name
|
||||
);
|
||||
if std::env::var("NYASH_JOINIR_DEBUG").is_ok() || std::env::var("JOINIR_TEST_DEBUG").is_ok() {
|
||||
match error {
|
||||
BindingRecordError::OriginalNotFound(name) => {
|
||||
eprintln!(
|
||||
"[binding_pilot/trim] Original variable '{}' not found in binding_map",
|
||||
name
|
||||
);
|
||||
}
|
||||
BindingRecordError::PromotedNotFound(name) => {
|
||||
eprintln!(
|
||||
"[binding_pilot/trim] Promoted variable '{}' not found in binding_map",
|
||||
name
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -129,11 +129,13 @@ impl DigitPosPromoter {
|
||||
};
|
||||
}
|
||||
|
||||
eprintln!(
|
||||
"[digitpos_promoter] Phase 224: Found {} LoopBodyLocal variables: {:?}",
|
||||
body_locals.len(),
|
||||
body_locals
|
||||
);
|
||||
if std::env::var("NYASH_JOINIR_DEBUG").is_ok() || std::env::var("JOINIR_TEST_DEBUG").is_ok() {
|
||||
eprintln!(
|
||||
"[digitpos_promoter] Phase 224: Found {} LoopBodyLocal variables: {:?}",
|
||||
body_locals.len(),
|
||||
body_locals
|
||||
);
|
||||
}
|
||||
|
||||
// Step 2: Get condition AST
|
||||
let condition = req.break_cond.or(req.continue_cond);
|
||||
@ -160,10 +162,12 @@ impl DigitPosPromoter {
|
||||
}
|
||||
|
||||
let detection = detection.unwrap();
|
||||
eprintln!(
|
||||
"[digitpos_promoter] Pattern detected: {} → {} (bool) + {} (int)",
|
||||
detection.var_name, detection.bool_carrier_name, detection.int_carrier_name
|
||||
);
|
||||
if std::env::var("NYASH_JOINIR_DEBUG").is_ok() || std::env::var("JOINIR_TEST_DEBUG").is_ok() {
|
||||
eprintln!(
|
||||
"[digitpos_promoter] Pattern detected: {} → {} (bool) + {} (int)",
|
||||
detection.var_name, detection.bool_carrier_name, detection.int_carrier_name
|
||||
);
|
||||
}
|
||||
|
||||
// Step 4: Build CarrierInfo
|
||||
use crate::mir::join_ir::lowering::carrier_info::{
|
||||
@ -177,6 +181,8 @@ impl DigitPosPromoter {
|
||||
join_id: None, // Will be allocated later
|
||||
role: CarrierRole::ConditionOnly, // Phase 227: DigitPos is condition-only
|
||||
init: CarrierInit::BoolConst(false), // Phase 228: Initialize with false
|
||||
#[cfg(feature = "normalized_dev")]
|
||||
binding_id: None, // Phase 78: Set by CarrierBindingAssigner
|
||||
};
|
||||
|
||||
// Integer carrier (loop-state, for NumberAccumulation)
|
||||
@ -186,6 +192,8 @@ impl DigitPosPromoter {
|
||||
join_id: None, // Will be allocated later
|
||||
role: CarrierRole::LoopState, // Phase 247-EX: LoopState for accumulation
|
||||
init: CarrierInit::LoopLocalZero, // Derived in-loop carrier (no host binding)
|
||||
#[cfg(feature = "normalized_dev")]
|
||||
binding_id: None, // Phase 78: Set by CarrierBindingAssigner
|
||||
};
|
||||
|
||||
// Create CarrierInfo with a dummy loop_var_name (will be ignored during merge)
|
||||
@ -214,14 +222,16 @@ impl DigitPosPromoter {
|
||||
log_promotion_error(&e);
|
||||
}
|
||||
|
||||
eprintln!(
|
||||
"[digitpos_promoter] Phase 247-EX: A-4 DigitPos pattern promoted: {} → {} (bool) + {} (i64)",
|
||||
detection.var_name, detection.bool_carrier_name, detection.int_carrier_name
|
||||
);
|
||||
eprintln!(
|
||||
"[digitpos_promoter] Phase 229: Recorded promoted variable '{}' (carriers: '{}', '{}')",
|
||||
detection.var_name, detection.bool_carrier_name, detection.int_carrier_name
|
||||
);
|
||||
if std::env::var("NYASH_JOINIR_DEBUG").is_ok() || std::env::var("JOINIR_TEST_DEBUG").is_ok() {
|
||||
eprintln!(
|
||||
"[digitpos_promoter] Phase 247-EX: A-4 DigitPos pattern promoted: {} → {} (bool) + {} (i64)",
|
||||
detection.var_name, detection.bool_carrier_name, detection.int_carrier_name
|
||||
);
|
||||
eprintln!(
|
||||
"[digitpos_promoter] Phase 229: Recorded promoted variable '{}' (carriers: '{}', '{}')",
|
||||
detection.var_name, detection.bool_carrier_name, detection.int_carrier_name
|
||||
);
|
||||
}
|
||||
|
||||
DigitPosPromotionResult::Promoted {
|
||||
carrier_info,
|
||||
@ -239,21 +249,23 @@ impl DigitPosPromoter {
|
||||
// - is_substring_method_call
|
||||
}
|
||||
|
||||
/// Phase 78: Log promotion errors with clear messages
|
||||
/// Phase 78: Log promotion errors with clear messages (gated)
|
||||
#[cfg(feature = "normalized_dev")]
|
||||
fn log_promotion_error(error: &BindingRecordError) {
|
||||
match error {
|
||||
BindingRecordError::OriginalNotFound(name) => {
|
||||
eprintln!(
|
||||
"[digitpos_promoter/warning] Original variable '{}' not found in binding_map",
|
||||
name
|
||||
);
|
||||
}
|
||||
BindingRecordError::PromotedNotFound(name) => {
|
||||
eprintln!(
|
||||
"[digitpos_promoter/warning] Promoted variable '{}' not found in binding_map",
|
||||
name
|
||||
);
|
||||
if std::env::var("NYASH_JOINIR_DEBUG").is_ok() || std::env::var("JOINIR_TEST_DEBUG").is_ok() {
|
||||
match error {
|
||||
BindingRecordError::OriginalNotFound(name) => {
|
||||
eprintln!(
|
||||
"[binding_pilot/digitpos] Original variable '{}' not found in binding_map",
|
||||
name
|
||||
);
|
||||
}
|
||||
BindingRecordError::PromotedNotFound(name) => {
|
||||
eprintln!(
|
||||
"[binding_pilot/digitpos] Promoted variable '{}' not found in binding_map",
|
||||
name
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user