From e40474661262e784d9790c4ead69511dc468f7cb Mon Sep 17 00:00:00 2001 From: nyash-codex Date: Tue, 16 Dec 2025 07:02:14 +0900 Subject: [PATCH] =?UTF-8?q?refactor(mir):=20Phase=20139-P3-B=20-=20Routing?= =?UTF-8?q?Decision=20=E3=82=92=20enum=20=E5=AF=BE=E5=BF=9C=20+=20?= =?UTF-8?q?=E3=83=AC=E3=82=AC=E3=82=B7=E3=83=BC=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - RoutingDecision の missing_caps を Vec に変更(型安全化) - error_tags は to_tag() メソッドで自動生成 - 全 callsite を enum variant に修正 - capability_tags モジュール(文字列定数群)を完全削除 - 全テスト PASS(型安全性向上を確認) - フォーマット適用 --- src/config/env.rs | 8 +- src/config/env/joinir_flags.rs | 3 +- src/grammar/generated.rs | 34 +--- src/mir/builder.rs | 73 +++++--- src/mir/builder/calls/annotation.rs | 3 +- src/mir/builder/calls/build.rs | 6 +- src/mir/builder/calls/lowering.rs | 8 +- src/mir/builder/calls/unified_emitter.rs | 6 +- src/mir/builder/compilation_context.rs | 5 +- .../joinir/merge/carrier_init_builder.rs | 85 +++++++-- .../joinir/merge/exit_line/reconnector.rs | 6 +- .../joinir/merge/instruction_rewriter.rs | 17 +- .../joinir/merge/loop_header_phi_builder.rs | 30 ++-- .../control_flow/joinir/parity_checker.rs | 26 ++- .../joinir/patterns/exit_binding.rs | 5 +- .../joinir/patterns/pattern1_minimal.rs | 11 +- .../joinir/patterns/pattern2_with_break.rs | 65 ++++--- .../joinir/patterns/pattern3_with_if_phi.rs | 11 +- .../patterns/pattern5_infinite_early_exit.rs | 165 +++++++++++++----- .../joinir/patterns/trim_loop_lowering.rs | 16 +- .../builder/control_flow/joinir/routing.rs | 45 +++-- src/mir/builder/decls.rs | 20 ++- src/mir/builder/emission/constant.rs | 27 ++- src/mir/builder/exprs.rs | 44 +++-- src/mir/builder/exprs_lambda.rs | 3 +- src/mir/builder/exprs_peek.rs | 4 +- src/mir/builder/fields.rs | 68 ++++++-- src/mir/builder/if_form.rs | 16 +- src/mir/builder/lifecycle.rs | 21 ++- src/mir/builder/method_call_handlers.rs | 3 +- src/mir/builder/observe/resolve.rs | 6 +- src/mir/builder/observe/ssa.rs | 9 +- src/mir/builder/ops.rs | 42 +++-- src/mir/builder/origin/infer.rs | 5 +- src/mir/builder/phi.rs | 13 +- src/mir/builder/phi_merge.rs | 14 +- src/mir/builder/receiver.rs | 6 +- src/mir/builder/rewrite/known.rs | 40 ++++- src/mir/builder/schedule/block.rs | 5 +- src/mir/builder/scope_context.rs | 3 +- src/mir/builder/ssa/local.rs | 11 +- src/mir/builder/stmts.rs | 24 ++- src/mir/builder/utils.rs | 15 +- src/mir/builder/vars/assignment_resolver.rs | 1 - src/mir/builder/vars/lexical_scope.rs | 4 +- .../loop_patterns/break_pattern.rs | 31 ++-- .../ast_lowerer/loop_patterns/common.rs | 7 +- .../loop_patterns/continue_pattern.rs | 23 +-- .../loop_patterns/continue_return_pattern.rs | 33 ++-- .../loop_patterns/if_sum_break_pattern.rs | 153 ++++++++-------- .../frontend/ast_lowerer/loop_patterns/mod.rs | 2 +- .../loop_patterns/step_calculator.rs | 10 +- src/mir/join_ir/frontend/ast_lowerer/mod.rs | 10 +- .../lowering/carrier_binding_assigner.rs | 56 ++++-- src/mir/join_ir/lowering/carrier_info.rs | 9 +- src/mir/join_ir/lowering/condition_env.rs | 28 ++- src/mir/join_ir/lowering/condition_lowerer.rs | 18 +- .../lowering/condition_lowering_box.rs | 4 +- src/mir/join_ir/lowering/condition_pattern.rs | 23 ++- src/mir/join_ir/lowering/expr_lowerer.rs | 32 ++-- .../lowering/expr_lowerer/scope_resolution.rs | 2 +- src/mir/join_ir/lowering/inline_boundary.rs | 6 +- .../loop_to_join/case_a_entrypoints.rs | 1 - src/mir/join_ir/lowering/loop_to_join/core.rs | 8 +- src/mir/join_ir/lowering/loop_to_join/mod.rs | 3 +- .../lowering/loop_with_break_minimal.rs | 8 +- .../lowering/loop_with_break_minimal/tests.rs | 4 +- .../lowering/loop_with_continue_minimal.rs | 4 +- src/mir/join_ir/lowering/mod.rs | 10 +- src/mir/join_ir/lowering/scope_manager.rs | 21 ++- .../scope_manager_bindingid_poc/mod.rs | 17 +- .../join_ir/lowering/simple_while_minimal.rs | 4 +- src/mir/join_ir/lowering/step_schedule.rs | 36 ++-- src/mir/join_ir/normalized.rs | 115 ++++++------ src/mir/join_ir/normalized/dev_fixtures.rs | 15 +- src/mir/join_ir/normalized/fixtures.rs | 101 +++++------ .../join_ir/normalized/loop_step_inspector.rs | 45 +++-- src/mir/join_ir/normalized/shape_guard.rs | 70 +++++--- src/mir/join_ir/ownership/analyzer.rs | 93 +++++++--- src/mir/join_ir/ownership/mod.rs | 16 +- src/mir/join_ir/ownership/plan_to_lowering.rs | 48 ++--- src/mir/join_ir/ownership/plan_validator.rs | 2 +- src/mir/join_ir/ownership/types.rs | 6 +- src/mir/join_ir/verify_phi_reserved.rs | 4 +- src/mir/join_ir_runner.rs | 10 +- src/mir/join_ir_vm_bridge/bridge.rs | 20 +-- .../joinir_block_converter.rs | 5 +- src/mir/join_ir_vm_bridge/mod.rs | 2 +- .../join_ir_vm_bridge/normalized_bridge.rs | 6 +- .../normalized_bridge/direct.rs | 16 +- src/mir/loop_canonicalizer/canonicalizer.rs | 34 ++-- .../loop_canonicalizer/capability_guard.rs | 48 +---- src/mir/loop_canonicalizer/mod.rs | 24 +-- src/mir/loop_canonicalizer/skeleton_types.rs | 21 +-- .../digitpos_detector.rs | 6 +- .../function_scope_capture/helpers.rs | 4 +- .../loop_body_carrier_promoter.rs | 16 +- .../loop_body_digitpos_promoter.rs | 17 +- src/mir/loop_pattern_detection/tests.rs | 2 +- .../loop_pattern_detection/trim_detector.rs | 6 +- src/mir/region/observer.rs | 20 ++- src/mir/utils/phi_helpers.rs | 8 +- src/runner/mir_json_emit.rs | 77 ++++---- tests/normalized_joinir_min.rs | 6 +- tests/normalized_joinir_min/shapes.rs | 19 +- tests/phase72_phi_observation.rs | 15 +- 106 files changed, 1475 insertions(+), 1017 deletions(-) diff --git a/src/config/env.rs b/src/config/env.rs index 56d9687d..a0b87647 100644 --- a/src/config/env.rs +++ b/src/config/env.rs @@ -26,11 +26,11 @@ pub mod stage1; // New modular organization mod joinir_flags; mod mir_flags; -mod vm_backend_flags; mod parser_flags; +mod selfhost_flags; mod using_flags; mod verification_flags; -mod selfhost_flags; +mod vm_backend_flags; pub use catalog::{env_vars, AppliesTo, EnvVarMeta}; pub use dump::*; @@ -42,11 +42,11 @@ pub use stage1::*; // Backward-compatible re-exports (NO BREAKING CHANGES!) pub use joinir_flags::*; pub use mir_flags::*; -pub use vm_backend_flags::*; pub use parser_flags::*; +pub use selfhost_flags::*; pub use using_flags::*; pub use verification_flags::*; -pub use selfhost_flags::*; +pub use vm_backend_flags::*; use std::collections::BTreeMap; diff --git a/src/config/env/joinir_flags.rs b/src/config/env/joinir_flags.rs index add59f2e..b3f74812 100644 --- a/src/config/env/joinir_flags.rs +++ b/src/config/env/joinir_flags.rs @@ -181,6 +181,5 @@ pub fn loopform_normalize() -> bool { /// /// For fine-grained control, use `joinir_debug_level()` which returns 0-3. pub fn is_joinir_debug() -> bool { - std::env::var("HAKO_JOINIR_DEBUG").is_ok() - || std::env::var("NYASH_JOINIR_DEBUG").is_ok() + std::env::var("HAKO_JOINIR_DEBUG").is_ok() || std::env::var("NYASH_JOINIR_DEBUG").is_ok() } diff --git a/src/grammar/generated.rs b/src/grammar/generated.rs index d94cb9c1..25bb6e51 100644 --- a/src/grammar/generated.rs +++ b/src/grammar/generated.rs @@ -36,37 +36,15 @@ pub static OPERATORS_DIV_RULES: &[(&str, &str, &str, &str)] = &[ ]; pub fn lookup_keyword(word: &str) -> Option<&'static str> { for (k, t) in KEYWORDS { - if *k == word { return Some(*t); } + if *k == word { + return Some(*t); + } } None } pub static SYNTAX_ALLOWED_STATEMENTS: &[&str] = &[ - "box", - "global", - "function", - "static", - "if", - "loop", - "break", - "return", - "print", - "nowait", - "include", - "local", - "outbox", - "try", - "throw", - "using", - "from", + "box", "global", "function", "static", "if", "loop", "break", "return", "print", "nowait", + "include", "local", "outbox", "try", "throw", "using", "from", ]; -pub static SYNTAX_ALLOWED_BINOPS: &[&str] = &[ - "add", - "sub", - "mul", - "div", - "and", - "or", - "eq", - "ne", -]; \ No newline at end of file +pub static SYNTAX_ALLOWED_BINOPS: &[&str] = &["add", "sub", "mul", "div", "and", "or", "eq", "ne"]; diff --git a/src/mir/builder.rs b/src/mir/builder.rs index 40831dbd..cc89417d 100644 --- a/src/mir/builder.rs +++ b/src/mir/builder.rs @@ -15,20 +15,20 @@ use crate::mir::region::function_slot_registry::FunctionSlotRegistry; use crate::mir::region::RegionId; use std::collections::HashSet; use std::collections::{BTreeMap, HashMap}; +mod binding_context; // Phase 136 follow-up (Step 4/7): BindingContext extraction mod builder_calls; mod call_resolution; // ChatGPT5 Pro: Type-safe call resolution utilities mod calls; // Call system modules (refactored from builder_calls) -mod binding_context; // Phase 136 follow-up (Step 4/7): BindingContext extraction mod compilation_context; // Phase 136 follow-up (Step 7/7): CompilationContext extraction mod context; // BoxCompilationContext - 箱理論による静的Boxコンパイル時のコンテキスト分離 mod core_context; // Phase 136 follow-up (Step 2/7): CoreContext extraction -mod metadata_context; // Phase 136 follow-up (Step 6/7): MetadataContext extraction -mod variable_context; // Phase 136 follow-up (Step 5/7): VariableContext extraction mod decls; // declarations lowering split mod exprs; // expression lowering split mod exprs_call; -mod method_call_handlers; // Method call handler separation (Phase 3) // call(expr) - // include lowering removed (using is handled in runner) +mod metadata_context; // Phase 136 follow-up (Step 6/7): MetadataContext extraction +mod method_call_handlers; +mod variable_context; // Phase 136 follow-up (Step 5/7): VariableContext extraction // Method call handler separation (Phase 3) // call(expr) + // include lowering removed (using is handled in runner) mod control_flow; // thin wrappers to centralize control-flow entrypoints mod exprs_lambda; // lambda lowering mod exprs_peek; // peek expression @@ -55,9 +55,9 @@ mod receiver; // ReceiverMaterializationBox(Method recv の pin+LocalSSA 集 mod rewrite; // P1: Known rewrite & special consolidation mod router; // RouterPolicyBox(Unified vs BoxCall) mod schedule; // BlockScheduleBox(物理順序: PHI→materialize→body) +mod scope_context; // Phase 136 follow-up (Step 3/7): ScopeContext extraction mod ssa; // LocalSSA helpers (in-block materialization) mod stmts; -mod scope_context; // Phase 136 follow-up (Step 3/7): ScopeContext extraction mod type_context; // Phase 136 follow-up: TypeContext extraction mod type_facts; // Phase 136 follow-up: Type inference facts box pub(crate) mod type_registry; @@ -86,8 +86,6 @@ pub struct MirBuilder { /// Direct field access for backward compatibility (migration in progress). pub(super) core_ctx: core_context::CoreContext, - - /// Phase 136 follow-up: Type information context /// Consolidates value_types, value_kinds, value_origin_newbox for better organization. /// Direct field access for backward compatibility (migration in progress). @@ -125,7 +123,6 @@ pub struct MirBuilder { #[allow(dead_code)] pub(super) pending_phis: Vec<(BasicBlockId, ValueId, String)>, - // Phase 2-5: binding_map removed - use binding_ctx.binding_map instead // include guards removed @@ -153,7 +150,6 @@ pub struct MirBuilder { // ---------------------- // Debug scope context (dev only; zero-cost when unused) // ---------------------- - /// Local SSA cache: ensure per-block materialization for critical operands (e.g., recv) /// Key: (bb, original ValueId, kind) -> local ValueId /// kind: 0=recv, 1+ reserved for future (args etc.) @@ -196,7 +192,8 @@ impl MirBuilder { let core_ctx = core_context::CoreContext::new(); // Phase 136 Step 7/7: Compilation context (new SSOT) - let comp_ctx = compilation_context::CompilationContext::with_plugin_sigs(plugin_method_sigs.clone()); + let comp_ctx = + compilation_context::CompilationContext::with_plugin_sigs(plugin_method_sigs.clone()); // フェーズM: no_phi_mode初期化削除 #[allow(deprecated)] @@ -384,7 +381,8 @@ impl MirBuilder { if let (Some(dot), Some(slash)) = (name.rfind('.'), name.rfind('/')) { if slash > dot { let tail = &name[dot..]; - self.comp_ctx.method_tail_index + self.comp_ctx + .method_tail_index .entry(tail.to_string()) .or_insert_with(Vec::new) .push(name.clone()); @@ -399,7 +397,9 @@ impl MirBuilder { fn ensure_method_tail_index(&mut self) { let need_rebuild = match self.current_module { - Some(ref refmod) => self.comp_ctx.method_tail_index_source_len != refmod.functions.len(), + Some(ref refmod) => { + self.comp_ctx.method_tail_index_source_len != refmod.functions.len() + } None => self.comp_ctx.method_tail_index_source_len != 0, }; if need_rebuild { @@ -410,7 +410,8 @@ impl MirBuilder { pub(super) fn method_candidates(&mut self, method: &str, arity: usize) -> Vec { self.ensure_method_tail_index(); let tail = format!(".{}{}", method, format!("/{}", arity)); - self.comp_ctx.method_tail_index + self.comp_ctx + .method_tail_index .get(&tail) .cloned() .unwrap_or_default() @@ -418,7 +419,8 @@ impl MirBuilder { pub(super) fn method_candidates_tail>(&mut self, tail: S) -> Vec { self.ensure_method_tail_index(); - self.comp_ctx.method_tail_index + self.comp_ctx + .method_tail_index .get(tail.as_ref()) .cloned() .unwrap_or_default() @@ -527,7 +529,9 @@ impl MirBuilder { if !suggest.is_empty() { msg.push_str("\nHint: symbol appears in using module(s): "); msg.push_str(&suggest.join(", ")); - msg.push_str("\nConsider adding 'using [as Alias]' or check nyash.toml [using]."); + msg.push_str( + "\nConsider adding 'using [as Alias]' or check nyash.toml [using].", + ); } msg @@ -567,7 +571,9 @@ impl MirBuilder { // Result: VM would try to read undefined ValueIds (e.g., ValueId(270) at bb303). if !var_name.starts_with("__pin$") { // In SSA form, each assignment creates a new value - self.variable_ctx.variable_map.insert(var_name.clone(), value_id); + self.variable_ctx + .variable_map + .insert(var_name.clone(), value_id); } Ok(value_id) @@ -582,7 +588,8 @@ impl MirBuilder { // Precompute debug metadata to avoid borrow conflicts later let _dbg_fn_name = self - .scope_ctx.current_function + .scope_ctx + .current_function .as_ref() .map(|f| f.signature.name.clone()); let _dbg_region_id = self.debug_current_region_id(); @@ -694,7 +701,8 @@ impl MirBuilder { }) = callee { let names: Vec = self - .variable_ctx.variable_map + .variable_ctx + .variable_map .iter() .filter(|(_, &vid)| vid == *r) .map(|(k, _)| k.clone()) @@ -760,7 +768,10 @@ impl MirBuilder { ); } // Phase 136 Step 6/7: Use metadata_ctx for span - block.add_instruction_with_span(instruction.clone(), self.metadata_ctx.current_span()); + block.add_instruction_with_span( + instruction.clone(), + self.metadata_ctx.current_span(), + ); // Drop the mutable borrow of `block` before updating other blocks } // Update predecessor sets for branch/jump immediately so that @@ -854,7 +865,8 @@ impl MirBuilder { effects: EffectMask::PURE, })?; // 型注釈(最小) - self.type_ctx.value_types + self.type_ctx + .value_types .insert(dst, super::MirType::Box(class.clone())); return Ok(dst); } @@ -872,7 +884,9 @@ impl MirBuilder { dst, value: ConstValue::Integer(n), })?; - self.type_ctx.value_types.insert(dst, super::MirType::Integer); + self.type_ctx + .value_types + .insert(dst, super::MirType::Integer); return Ok(dst); } } @@ -897,7 +911,8 @@ impl MirBuilder { })?; // Phase 15.5: Unified box type handling // All boxes (including former core boxes) are treated uniformly as Box types - self.type_ctx.value_types + self.type_ctx + .value_types .insert(dst, super::MirType::Box(class.clone())); // Record origin for optimization: dst was created by NewBox of class @@ -954,7 +969,9 @@ impl MirBuilder { /// Check if the current basic block is terminated fn is_current_block_terminated(&self) -> bool { - if let (Some(block_id), Some(ref function)) = (self.current_block, &self.scope_ctx.current_function) { + if let (Some(block_id), Some(ref function)) = + (self.current_block, &self.scope_ctx.current_function) + { if let Some(block) = function.get_block(block_id) { return block.is_terminated(); } @@ -1018,13 +1035,17 @@ use crate::mir::loop_pattern_detection::BindingMapProvider; impl BindingMapProvider for MirBuilder { #[cfg(feature = "normalized_dev")] - fn get_binding_map(&self) -> Option<&std::collections::BTreeMap> { + fn get_binding_map( + &self, + ) -> Option<&std::collections::BTreeMap> { // Phase 136 Step 4/7: Use binding_ctx (SSOT) Some(self.binding_ctx.binding_map()) } #[cfg(not(feature = "normalized_dev"))] - fn get_binding_map(&self) -> Option<&std::collections::BTreeMap> { + fn get_binding_map( + &self, + ) -> Option<&std::collections::BTreeMap> { None } } diff --git a/src/mir/builder/calls/annotation.rs b/src/mir/builder/calls/annotation.rs index d8ae64ee..4d500494 100644 --- a/src/mir/builder/calls/annotation.rs +++ b/src/mir/builder/calls/annotation.rs @@ -40,7 +40,8 @@ pub(in super::super) fn annotate_call_result_from_func_name>( || std::env::var("NYASH_BUILDER_DEBUG").ok().as_deref() == Some("1") { let bx = builder - .type_ctx.value_origin_newbox + .type_ctx + .value_origin_newbox .get(&dst) .cloned() .unwrap_or_default(); diff --git a/src/mir/builder/calls/build.rs b/src/mir/builder/calls/build.rs index 2bf17e60..8a2892ae 100644 --- a/src/mir/builder/calls/build.rs +++ b/src/mir/builder/calls/build.rs @@ -21,7 +21,8 @@ impl MirBuilder { // Dev trace if std::env::var("NYASH_CLI_VERBOSE").ok().as_deref() == Some("1") { let cur_fun = self - .scope_ctx.current_function + .scope_ctx + .current_function .as_ref() .map(|f| f.signature.name.clone()) .unwrap_or_else(|| "".to_string()); @@ -270,7 +271,8 @@ impl MirBuilder { if let Err(e) = self.emit_constructor_call(math_recv, "MathBox".to_string(), vec![]) { return Some(Err(e)); } - self.type_ctx.value_origin_newbox + self.type_ctx + .value_origin_newbox .insert(math_recv, "MathBox".to_string()); // birth() if let Err(e) = self.emit_method_call(None, math_recv, "birth".to_string(), vec![]) { diff --git a/src/mir/builder/calls/lowering.rs b/src/mir/builder/calls/lowering.rs index 3544fd1d..8c6f4135 100644 --- a/src/mir/builder/calls/lowering.rs +++ b/src/mir/builder/calls/lowering.rs @@ -307,8 +307,12 @@ impl MirBuilder { // me let me_id = f.params[0]; - self.variable_ctx.variable_map.insert("me".to_string(), me_id); - self.type_ctx.value_origin_newbox.insert(me_id, box_name.to_string()); + self.variable_ctx + .variable_map + .insert("me".to_string(), me_id); + self.type_ctx + .value_origin_newbox + .insert(me_id, box_name.to_string()); slot_regs.push(("me".to_string(), None)); // 通常パラメータ diff --git a/src/mir/builder/calls/unified_emitter.rs b/src/mir/builder/calls/unified_emitter.rs index 0c2ba991..e4f9c656 100644 --- a/src/mir/builder/calls/unified_emitter.rs +++ b/src/mir/builder/calls/unified_emitter.rs @@ -208,7 +208,8 @@ impl UnifiedCallEmitterBox { crate::mir::MirType::Box(box_name.to_string()), ); builder - .type_ctx.value_origin_newbox + .type_ctx + .value_origin_newbox .insert(singleton_id, box_name.to_string()); // Cache for future use builder @@ -296,7 +297,8 @@ impl UnifiedCallEmitterBox { // Try to retrieve origin info for receiver let recv_meta = receiver.and_then(|r| { builder - .type_ctx.value_origin_newbox + .type_ctx + .value_origin_newbox .get(&r) .cloned() .map(|cls| (r, cls)) diff --git a/src/mir/builder/compilation_context.rs b/src/mir/builder/compilation_context.rs index e50d8121..419ff111 100644 --- a/src/mir/builder/compilation_context.rs +++ b/src/mir/builder/compilation_context.rs @@ -394,7 +394,10 @@ mod tests { let base_id = ValueId::new(10); ctx.set_field_origin_class(base_id, "name".to_string(), "StringBox".to_string()); - assert_eq!(ctx.get_field_origin_class(base_id, "name"), Some("StringBox")); + assert_eq!( + ctx.get_field_origin_class(base_id, "name"), + Some("StringBox") + ); assert_eq!(ctx.get_field_origin_class(base_id, "other"), None); } diff --git a/src/mir/builder/control_flow/joinir/merge/carrier_init_builder.rs b/src/mir/builder/control_flow/joinir/merge/carrier_init_builder.rs index ea5f2217..e5fb4c60 100644 --- a/src/mir/builder/control_flow/joinir/merge/carrier_init_builder.rs +++ b/src/mir/builder/control_flow/joinir/merge/carrier_init_builder.rs @@ -13,11 +13,10 @@ /// - **SSOT**: Single function for all CarrierInit → ValueId generation /// - **Testability**: Pure function, easy to unit test /// - **Consistency**: Uniform debug output format - use crate::mir::builder::MirBuilder; use crate::mir::join_ir::lowering::carrier_info::CarrierInit; -use crate::mir::value_id::ValueId; use crate::mir::types::ConstValue; +use crate::mir::value_id::ValueId; use crate::mir::MirInstruction; /// Generate a ValueId for the given CarrierInit policy @@ -120,7 +119,13 @@ mod tests { let mut builder = MirBuilder::new(); let host_id = ValueId(999); // Dummy host_id (not used for BoolConst) - let result = init_value(&mut builder, &CarrierInit::BoolConst(true), host_id, "test", false); + let result = init_value( + &mut builder, + &CarrierInit::BoolConst(true), + host_id, + "test", + false, + ); assert_ne!(result, host_id, "BoolConst should emit new ValueId"); } @@ -131,7 +136,13 @@ mod tests { let mut builder = MirBuilder::new(); let host_id = ValueId(999); - let result = init_value(&mut builder, &CarrierInit::BoolConst(false), host_id, "flag", false); + let result = init_value( + &mut builder, + &CarrierInit::BoolConst(false), + host_id, + "flag", + false, + ); assert_ne!(result, host_id, "BoolConst should emit new ValueId"); } @@ -142,7 +153,13 @@ mod tests { let mut builder = MirBuilder::new(); let host_id = ValueId(999); - let result = init_value(&mut builder, &CarrierInit::LoopLocalZero, host_id, "digit", false); + let result = init_value( + &mut builder, + &CarrierInit::LoopLocalZero, + host_id, + "digit", + false, + ); assert_ne!(result, host_id, "LoopLocalZero should emit new ValueId"); } @@ -153,12 +170,36 @@ mod tests { let mut builder = MirBuilder::new(); let host_id = ValueId(100); - let result1 = init_value(&mut builder, &CarrierInit::BoolConst(true), host_id, "flag1", false); - let result2 = init_value(&mut builder, &CarrierInit::BoolConst(false), host_id, "flag2", false); - let result3 = init_value(&mut builder, &CarrierInit::LoopLocalZero, host_id, "counter", false); + let result1 = init_value( + &mut builder, + &CarrierInit::BoolConst(true), + host_id, + "flag1", + false, + ); + let result2 = init_value( + &mut builder, + &CarrierInit::BoolConst(false), + host_id, + "flag2", + false, + ); + let result3 = init_value( + &mut builder, + &CarrierInit::LoopLocalZero, + host_id, + "counter", + false, + ); - assert_ne!(result1, result2, "Different BoolConst calls should produce different ValueIds"); - assert_ne!(result2, result3, "BoolConst and LoopLocalZero should produce different ValueIds"); + assert_ne!( + result1, result2, + "Different BoolConst calls should produce different ValueIds" + ); + assert_ne!( + result2, result3, + "BoolConst and LoopLocalZero should produce different ValueIds" + ); assert_ne!(result1, result3, "All ValueIds should be unique"); } @@ -168,7 +209,13 @@ mod tests { let mut builder = MirBuilder::new(); let host_id = ValueId(42); - let _ = init_value(&mut builder, &CarrierInit::FromHost, host_id, "debug_test", true); + let _ = init_value( + &mut builder, + &CarrierInit::FromHost, + host_id, + "debug_test", + true, + ); // Expected stderr output: "[carrier_init_builder] 'debug_test': FromHost -> ValueId(42)" // (This test just verifies it doesn't crash) } @@ -179,7 +226,13 @@ mod tests { let mut builder = MirBuilder::new(); let host_id = ValueId(999); - let _result = init_value(&mut builder, &CarrierInit::BoolConst(true), host_id, "debug_bool", true); + let _result = init_value( + &mut builder, + &CarrierInit::BoolConst(true), + host_id, + "debug_bool", + true, + ); // Expected stderr output: "[carrier_init_builder] 'debug_bool': BoolConst(true) -> ValueId(N)" // (This test just verifies it doesn't crash) } @@ -190,7 +243,13 @@ mod tests { let mut builder = MirBuilder::new(); let host_id = ValueId(999); - let _result = init_value(&mut builder, &CarrierInit::LoopLocalZero, host_id, "debug_zero", true); + let _result = init_value( + &mut builder, + &CarrierInit::LoopLocalZero, + host_id, + "debug_zero", + true, + ); // Expected stderr output: "[carrier_init_builder] 'debug_zero': LoopLocalZero -> ValueId(N)" // (This test just verifies it doesn't crash) } diff --git a/src/mir/builder/control_flow/joinir/merge/exit_line/reconnector.rs b/src/mir/builder/control_flow/joinir/merge/exit_line/reconnector.rs index 67b9c308..146142a9 100644 --- a/src/mir/builder/control_flow/joinir/merge/exit_line/reconnector.rs +++ b/src/mir/builder/control_flow/joinir/merge/exit_line/reconnector.rs @@ -143,7 +143,11 @@ impl ExitLineReconnector { // Update variable_ctx.variable_map with PHI dst if let Some(&phi_value) = phi_dst { - if let Some(var_vid) = builder.variable_ctx.variable_map.get_mut(&binding.carrier_name) { + if let Some(var_vid) = builder + .variable_ctx + .variable_map + .get_mut(&binding.carrier_name) + { // Phase 177-STRUCT: Always log for debugging if verbose { eprintln!( diff --git a/src/mir/builder/control_flow/joinir/merge/instruction_rewriter.rs b/src/mir/builder/control_flow/joinir/merge/instruction_rewriter.rs index ac9ea9ec..8c2702cd 100644 --- a/src/mir/builder/control_flow/joinir/merge/instruction_rewriter.rs +++ b/src/mir/builder/control_flow/joinir/merge/instruction_rewriter.rs @@ -149,14 +149,15 @@ pub(super) fn merge_and_rewrite( // Phase 195 FIX: Reuse existing block if present (preserves PHI from JoinIR Select lowering) // ultrathink "finalizer集約案": Don't overwrite blocks with BasicBlock::new() - let mut new_block = if let Some(ref mut current_func) = builder.scope_ctx.current_function { - current_func - .blocks - .remove(&new_block_id) - .unwrap_or_else(|| BasicBlock::new(new_block_id)) - } else { - BasicBlock::new(new_block_id) - }; + let mut new_block = + if let Some(ref mut current_func) = builder.scope_ctx.current_function { + current_func + .blocks + .remove(&new_block_id) + .unwrap_or_else(|| BasicBlock::new(new_block_id)) + } else { + BasicBlock::new(new_block_id) + }; // Phase 33-16: Identify loop entry point // diff --git a/src/mir/builder/control_flow/joinir/merge/loop_header_phi_builder.rs b/src/mir/builder/control_flow/joinir/merge/loop_header_phi_builder.rs index 9fe24e45..e046a4ff 100644 --- a/src/mir/builder/control_flow/joinir/merge/loop_header_phi_builder.rs +++ b/src/mir/builder/control_flow/joinir/merge/loop_header_phi_builder.rs @@ -96,12 +96,17 @@ impl LoopHeaderPhiBuilder { // Phase 131-11-H: Set PHI type from entry incoming (init value) only // Ignore backedge to avoid circular dependency in type inference if let Some(init_type) = builder.type_ctx.value_types.get(&loop_var_init).cloned() { - builder.type_ctx.value_types.insert(loop_var_phi_dst, init_type.clone()); + builder + .type_ctx + .value_types + .insert(loop_var_phi_dst, init_type.clone()); if debug || std::env::var("NYASH_CARRIER_PHI_DEBUG").ok().as_deref() == Some("1") { eprintln!( "[carrier/phi] Loop var '{}': dst=%{} entry_type={:?} (backedge ignored)", - loop_var_name, loop_var_phi_dst.as_u32(), init_type + loop_var_name, + loop_var_phi_dst.as_u32(), + init_type ); } } @@ -128,13 +133,8 @@ impl LoopHeaderPhiBuilder { // Allocate PHIs for other carriers for (name, host_id, init, role) in carriers { // Phase 86: Use centralized CarrierInit builder - let init_value = super::carrier_init_builder::init_value( - builder, - &init, - *host_id, - &name, - debug, - ); + let init_value = + super::carrier_init_builder::init_value(builder, &init, *host_id, &name, debug); let phi_dst = builder.next_value_id(); @@ -145,12 +145,17 @@ impl LoopHeaderPhiBuilder { // Phase 131-11-H: Set PHI type from entry incoming (init value) only // Ignore backedge to avoid circular dependency in type inference if let Some(init_type) = builder.type_ctx.value_types.get(&init_value).cloned() { - builder.type_ctx.value_types.insert(phi_dst, init_type.clone()); + builder + .type_ctx + .value_types + .insert(phi_dst, init_type.clone()); if debug || std::env::var("NYASH_CARRIER_PHI_DEBUG").ok().as_deref() == Some("1") { eprintln!( "[carrier/phi] Carrier '{}': dst=%{} entry_type={:?} (backedge ignored)", - name, phi_dst.as_u32(), init_type + name, + phi_dst.as_u32(), + init_type ); } } @@ -223,7 +228,8 @@ impl LoopHeaderPhiBuilder { // Get the header block from current function let current_func = builder - .scope_ctx.current_function + .scope_ctx + .current_function .as_mut() .ok_or("Phase 33-16: No current function when finalizing header PHIs")?; diff --git a/src/mir/builder/control_flow/joinir/parity_checker.rs b/src/mir/builder/control_flow/joinir/parity_checker.rs index 34e6cdd6..98126401 100644 --- a/src/mir/builder/control_flow/joinir/parity_checker.rs +++ b/src/mir/builder/control_flow/joinir/parity_checker.rs @@ -141,20 +141,24 @@ mod tests { #[test] fn test_parity_check_skip_whitespace_match() { - use crate::mir::loop_canonicalizer::canonicalize_loop_expr; use crate::mir::builder::control_flow::joinir::patterns::ast_feature_extractor as ast_features; + use crate::mir::loop_canonicalizer::canonicalize_loop_expr; let loop_ast = build_skip_whitespace_loop(); // Extract condition and body let (condition, body) = match &loop_ast { - ASTNode::Loop { condition, body, .. } => (condition.as_ref(), body.as_slice()), + ASTNode::Loop { + condition, body, .. + } => (condition.as_ref(), body.as_slice()), _ => panic!("Expected loop node"), }; // Run canonicalizer let (_, canonical_decision) = canonicalize_loop_expr(&loop_ast).unwrap(); - let canonical_pattern = canonical_decision.chosen.expect("Canonicalizer should succeed"); + let canonical_pattern = canonical_decision + .chosen + .expect("Canonicalizer should succeed"); // Run router's pattern detection let has_continue = ast_features::detect_continue_in_body(body); @@ -175,13 +179,16 @@ mod tests { crate::mir::loop_pattern_detection::LoopPatternKind::Pattern2Break, "Router should classify as Pattern2Break for has_break=true" ); - assert_eq!(canonical_pattern, actual_pattern, "Phase 137-5: Canonicalizer and router should agree (SSOT policy)"); + assert_eq!( + canonical_pattern, actual_pattern, + "Phase 137-5: Canonicalizer and router should agree (SSOT policy)" + ); } #[test] fn test_parity_check_match_simple_while() { - use crate::mir::loop_canonicalizer::canonicalize_loop_expr; use crate::mir::builder::control_flow::joinir::patterns::ast_feature_extractor as ast_features; + use crate::mir::loop_canonicalizer::canonicalize_loop_expr; // Simple while loop: no break, no continue, no if let loop_ast = ASTNode::Loop { @@ -221,7 +228,9 @@ mod tests { // Extract condition and body let (condition, body) = match &loop_ast { - ASTNode::Loop { condition, body, .. } => (condition.as_ref(), body.as_slice()), + ASTNode::Loop { + condition, body, .. + } => (condition.as_ref(), body.as_slice()), _ => panic!("Expected loop node"), }; @@ -243,6 +252,9 @@ mod tests { // Canonicalizer should fail (not implemented yet for Pattern1) assert!(canonical_result.is_ok()); let (_, decision) = canonical_result.unwrap(); - assert!(decision.is_fail_fast(), "Canonicalizer should fail for simple patterns (Phase 3 only supports skip_whitespace)"); + assert!( + decision.is_fail_fast(), + "Canonicalizer should fail for simple patterns (Phase 3 only supports skip_whitespace)" + ); } } diff --git a/src/mir/builder/control_flow/joinir/patterns/exit_binding.rs b/src/mir/builder/control_flow/joinir/patterns/exit_binding.rs index 17947d0e..939c03ac 100644 --- a/src/mir/builder/control_flow/joinir/patterns/exit_binding.rs +++ b/src/mir/builder/control_flow/joinir/patterns/exit_binding.rs @@ -106,7 +106,10 @@ impl<'a> ExitBindingBuilder<'a> { /// /// Success or error if boundary cannot be updated #[allow(dead_code)] - pub(crate) fn apply_to_boundary(&self, boundary: &mut JoinInlineBoundary) -> Result<(), String> { + pub(crate) fn apply_to_boundary( + &self, + boundary: &mut JoinInlineBoundary, + ) -> Result<(), String> { // Phase 222.5-C: Delegate to applicator module apply_exit_bindings_to_boundary( self.carrier_info, diff --git a/src/mir/builder/control_flow/joinir/patterns/pattern1_minimal.rs b/src/mir/builder/control_flow/joinir/patterns/pattern1_minimal.rs index adcf8228..c0d5a690 100644 --- a/src/mir/builder/control_flow/joinir/patterns/pattern1_minimal.rs +++ b/src/mir/builder/control_flow/joinir/patterns/pattern1_minimal.rs @@ -77,14 +77,17 @@ impl MirBuilder { // // Phase 132: Add exit_bindings to enable ExitLineReconnector // This ensures `return i` after loop returns the final value (3) instead of initial (0) - use crate::mir::join_ir::lowering::JoinInlineBoundaryBuilder; - use crate::mir::join_ir::lowering::inline_boundary::LoopExitBinding; use crate::mir::join_ir::lowering::carrier_info::CarrierRole; + use crate::mir::join_ir::lowering::inline_boundary::LoopExitBinding; use crate::mir::join_ir::lowering::join_value_space::PARAM_MIN; + use crate::mir::join_ir::lowering::JoinInlineBoundaryBuilder; // Phase 132-Post: Extract k_exit's parameter ValueId from join_module (Box-First) let k_exit_func = join_module.require_function("k_exit", "Pattern 1"); - let join_exit_value = k_exit_func.params.first().copied() + let join_exit_value = k_exit_func + .params + .first() + .copied() .expect("k_exit must have parameter for exit value"); // Phase 132: Create exit binding for loop variable @@ -98,7 +101,7 @@ impl MirBuilder { let boundary = JoinInlineBoundaryBuilder::new() .with_inputs( vec![ValueId(PARAM_MIN)], // JoinIR's main() parameter (loop variable, Param region) - vec![ctx.loop_var_id], // Host's loop variable + vec![ctx.loop_var_id], // Host's loop variable ) .with_exit_bindings(vec![exit_binding]) // Phase 132: Enable exit PHI & variable_map update .with_loop_var_name(Some(ctx.loop_var_name.clone())) // Phase 33-16: Enable header PHI generation for SSA correctness diff --git a/src/mir/builder/control_flow/joinir/patterns/pattern2_with_break.rs b/src/mir/builder/control_flow/joinir/patterns/pattern2_with_break.rs index 98cdd4f4..0a45d80c 100644 --- a/src/mir/builder/control_flow/joinir/patterns/pattern2_with_break.rs +++ b/src/mir/builder/control_flow/joinir/patterns/pattern2_with_break.rs @@ -9,8 +9,8 @@ use crate::mir::join_ir::lowering::join_value_space::JoinValueSpace; use crate::mir::join_ir::lowering::loop_body_local_env::LoopBodyLocalEnv; use crate::mir::join_ir::lowering::loop_scope_shape::LoopScopeShape; use crate::mir::join_ir::lowering::loop_update_analyzer::UpdateExpr; -use crate::mir::loop_pattern_detection::function_scope_capture::CapturedEnv; use crate::mir::loop_pattern_detection::error_messages; +use crate::mir::loop_pattern_detection::function_scope_capture::CapturedEnv; use crate::mir::ValueId; use std::collections::BTreeMap; @@ -42,7 +42,9 @@ fn prepare_pattern2_inputs( verbose: bool, ) -> Result { use super::condition_env_builder::ConditionEnvBuilder; - use crate::mir::loop_pattern_detection::function_scope_capture::{analyze_captured_vars_v2, CapturedEnv}; + use crate::mir::loop_pattern_detection::function_scope_capture::{ + analyze_captured_vars_v2, CapturedEnv, + }; let loop_var_name = ctx.loop_var_name.clone(); let loop_var_id = ctx.loop_var_id; @@ -88,7 +90,10 @@ fn prepare_pattern2_inputs( log_pattern2( verbose, "capture", - format!("Phase 200-C: Captured {} variables", captured_env.vars.len()), + format!( + "Phase 200-C: Captured {} variables", + captured_env.vars.len() + ), ); for var in &captured_env.vars { log_pattern2( @@ -747,16 +752,8 @@ impl MirBuilder { trace::trace().varmap("pattern2_start", &self.variable_ctx.variable_map); - let mut inputs = - prepare_pattern2_inputs(self, condition, _body, fn_body, &ctx, verbose)?; - promote_and_prepare_carriers( - self, - condition, - _body, - &mut inputs, - debug, - verbose, - )?; + let mut inputs = prepare_pattern2_inputs(self, condition, _body, fn_body, &ctx, verbose)?; + promote_and_prepare_carriers(self, condition, _body, &mut inputs, debug, verbose)?; let (effective_break_condition, normalized_body) = apply_trim_and_normalize(self, condition, _body, &mut inputs, verbose)?; let analysis_body = normalized_body.as_deref().unwrap_or(_body); @@ -771,10 +768,10 @@ impl MirBuilder { verbose, "updates", format!( - "Phase 176-3: Analyzed {} carrier updates", - carrier_updates.len() - ), - ); + "Phase 176-3: Analyzed {} carrier updates", + carrier_updates.len() + ), + ); let original_carrier_count = inputs.carrier_info.carriers.len(); filter_carriers_for_updates(&mut inputs.carrier_info, &carrier_updates); @@ -977,11 +974,26 @@ mod tests { use crate::mir::ValueId; let mut builder = MirBuilder::new(); - builder.variable_ctx.variable_map.insert("i".to_string(), ValueId(1)); - builder.variable_ctx.variable_map.insert("len".to_string(), ValueId(2)); - builder.variable_ctx.variable_map.insert("s".to_string(), ValueId(3)); - builder.variable_ctx.variable_map.insert("digits".to_string(), ValueId(4)); - builder.variable_ctx.variable_map.insert("result".to_string(), ValueId(5)); + builder + .variable_ctx + .variable_map + .insert("i".to_string(), ValueId(1)); + builder + .variable_ctx + .variable_map + .insert("len".to_string(), ValueId(2)); + builder + .variable_ctx + .variable_map + .insert("s".to_string(), ValueId(3)); + builder + .variable_ctx + .variable_map + .insert("digits".to_string(), ValueId(4)); + builder + .variable_ctx + .variable_map + .insert("result".to_string(), ValueId(5)); let condition = bin(BinaryOperator::Less, var("i"), var("len")); @@ -1008,7 +1020,9 @@ mod tests { let break_if = ASTNode::If { condition: Box::new(bin(BinaryOperator::Less, var("digit_pos"), lit_i(0))), - then_body: vec![ASTNode::Break { span: Span::unknown() }], + then_body: vec![ASTNode::Break { + span: Span::unknown(), + }], else_body: None, span: Span::unknown(), }; @@ -1035,9 +1049,8 @@ mod tests { let ctx = build_pattern_context(&mut builder, &condition, &body, PatternVariant::Pattern2) .expect("build_pattern_context"); - let mut inputs = - prepare_pattern2_inputs(&builder, &condition, &body, None, &ctx, false) - .expect("prepare_pattern2_inputs"); + let mut inputs = prepare_pattern2_inputs(&builder, &condition, &body, None, &ctx, false) + .expect("prepare_pattern2_inputs"); promote_and_prepare_carriers(&mut builder, &condition, &body, &mut inputs, false, false) .expect("promote_and_prepare_carriers"); diff --git a/src/mir/builder/control_flow/joinir/patterns/pattern3_with_if_phi.rs b/src/mir/builder/control_flow/joinir/patterns/pattern3_with_if_phi.rs index 896205d5..d1145234 100644 --- a/src/mir/builder/control_flow/joinir/patterns/pattern3_with_if_phi.rs +++ b/src/mir/builder/control_flow/joinir/patterns/pattern3_with_if_phi.rs @@ -183,7 +183,8 @@ impl MirBuilder { // Collect parent-defined variables from function scope // For now, use all variables in variable_map except loop_var let parent_defined: Vec = self - .variable_ctx.variable_map + .variable_ctx + .variable_map .keys() .filter(|name| *name != &loop_var_name) .cloned() @@ -196,9 +197,11 @@ impl MirBuilder { condition_bindings.iter().map(|b| b.name.clone()).collect(); // Run consistency checks - if let Err(e) = - check_ownership_plan_consistency(&plan, &ctx.carrier_info, &condition_binding_names) - { + if let Err(e) = check_ownership_plan_consistency( + &plan, + &ctx.carrier_info, + &condition_binding_names, + ) { eprintln!("[phase64/ownership] Consistency check failed: {}", e); return Err(e); } diff --git a/src/mir/builder/control_flow/joinir/patterns/pattern5_infinite_early_exit.rs b/src/mir/builder/control_flow/joinir/patterns/pattern5_infinite_early_exit.rs index 7cf1eb02..98726a02 100644 --- a/src/mir/builder/control_flow/joinir/patterns/pattern5_infinite_early_exit.rs +++ b/src/mir/builder/control_flow/joinir/patterns/pattern5_infinite_early_exit.rs @@ -50,7 +50,13 @@ fn count_breaks_and_continues(body: &[ASTNode]) -> (usize, usize, bool) { let mut continue_count = 0; let mut has_nested_loop = false; - fn scan_node(node: &ASTNode, break_count: &mut usize, continue_count: &mut usize, has_nested_loop: &mut bool, depth: usize) { + fn scan_node( + node: &ASTNode, + break_count: &mut usize, + continue_count: &mut usize, + has_nested_loop: &mut bool, + depth: usize, + ) { match node { ASTNode::Break { .. } => { *break_count += 1; @@ -61,13 +67,29 @@ fn count_breaks_and_continues(body: &[ASTNode]) -> (usize, usize, bool) { ASTNode::Loop { .. } if depth > 0 => { *has_nested_loop = true; } - ASTNode::If { then_body, else_body, .. } => { + ASTNode::If { + then_body, + else_body, + .. + } => { for stmt in then_body { - scan_node(stmt, break_count, continue_count, has_nested_loop, depth + 1); + scan_node( + stmt, + break_count, + continue_count, + has_nested_loop, + depth + 1, + ); } if let Some(else_body) = else_body { for stmt in else_body { - scan_node(stmt, break_count, continue_count, has_nested_loop, depth + 1); + scan_node( + stmt, + break_count, + continue_count, + has_nested_loop, + depth + 1, + ); } } } @@ -76,7 +98,13 @@ fn count_breaks_and_continues(body: &[ASTNode]) -> (usize, usize, bool) { } for stmt in body { - scan_node(stmt, &mut break_count, &mut continue_count, &mut has_nested_loop, 0); + scan_node( + stmt, + &mut break_count, + &mut continue_count, + &mut has_nested_loop, + 0, + ); } (break_count, continue_count, has_nested_loop) @@ -95,7 +123,12 @@ fn validate_continue_position(body: &[ASTNode]) -> bool { /// Phase 131-11-D: Validate break is in simple if pattern fn validate_break_pattern(body: &[ASTNode]) -> bool { for stmt in body { - if let ASTNode::If { then_body, else_body, .. } = stmt { + if let ASTNode::If { + then_body, + else_body, + .. + } = stmt + { // Check then branch for simple break if then_body.len() == 1 && matches!(then_body[0], ASTNode::Break { .. }) { // Ensure no else-break pattern @@ -132,13 +165,17 @@ pub(crate) fn can_lower(_builder: &MirBuilder, ctx: &LoopPatternContext) -> bool // Step 2: Shape guard - infinite loop condition (true literal) if !ctx.features.is_infinite_loop { if debug { - trace::trace().debug("pattern5/detect", "Not an infinite loop (condition != true)"); + trace::trace().debug( + "pattern5/detect", + "Not an infinite loop (condition != true)", + ); } return false; } // Phase 131-11-D: Enhanced real count validation - let (real_break_count, real_continue_count, has_nested_loop) = count_breaks_and_continues(ctx.body); + let (real_break_count, real_continue_count, has_nested_loop) = + count_breaks_and_continues(ctx.body); // Step 3: Shape guard - exactly 1 break (real count) if real_break_count != 1 { @@ -232,11 +269,21 @@ fn extract_counter_name(body: &[ASTNode]) -> Result { use crate::ast::BinaryOperator; for stmt in body { - if let ASTNode::If { condition, then_body, .. } = stmt { + if let ASTNode::If { + condition, + then_body, + .. + } = stmt + { // Check if then_body contains just break if then_body.len() == 1 && matches!(then_body[0], ASTNode::Break { .. }) { // Extract counter from condition - if let ASTNode::BinaryOp { operator: BinaryOperator::Equal, left, .. } = condition.as_ref() { + if let ASTNode::BinaryOp { + operator: BinaryOperator::Equal, + left, + .. + } = condition.as_ref() + { if let ASTNode::Variable { name, .. } = left.as_ref() { return Ok(name.clone()); } @@ -256,12 +303,26 @@ fn extract_limit_value(body: &[ASTNode]) -> Result { use crate::ast::{BinaryOperator, LiteralValue}; for stmt in body { - if let ASTNode::If { condition, then_body, .. } = stmt { + if let ASTNode::If { + condition, + then_body, + .. + } = stmt + { // Check if then_body contains just break if then_body.len() == 1 && matches!(then_body[0], ASTNode::Break { .. }) { // Extract limit from condition - if let ASTNode::BinaryOp { operator: BinaryOperator::Equal, right, .. } = condition.as_ref() { - if let ASTNode::Literal { value: LiteralValue::Integer(limit), .. } = right.as_ref() { + if let ASTNode::BinaryOp { + operator: BinaryOperator::Equal, + right, + .. + } = condition.as_ref() + { + if let ASTNode::Literal { + value: LiteralValue::Integer(limit), + .. + } = right.as_ref() + { return Ok(*limit); } } @@ -317,9 +378,17 @@ pub(crate) fn lower( } // Step 2: Get counter ValueId from variable_ctx.variable_map - let counter_id = builder.variable_ctx.variable_map.get(&counter_name).copied().ok_or_else(|| { - format!("Counter variable '{}' not found in variable_ctx.variable_map", counter_name) - })?; + let counter_id = builder + .variable_ctx + .variable_map + .get(&counter_name) + .copied() + .ok_or_else(|| { + format!( + "Counter variable '{}' not found in variable_ctx.variable_map", + counter_name + ) + })?; if debug { trace::trace().debug( @@ -340,7 +409,8 @@ pub(crate) fn lower( // Step 4: Generate JoinIR use crate::mir::join_ir::lowering::join_value_space::JoinValueSpace; use crate::mir::join_ir::{ - BinOpKind, CompareOp, ConstValue, JoinFuncId, JoinFunction, JoinInst, JoinModule, MirLikeInst, + BinOpKind, CompareOp, ConstValue, JoinFuncId, JoinFunction, JoinInst, JoinModule, + MirLikeInst, }; let mut join_value_space = JoinValueSpace::new(); @@ -356,14 +426,14 @@ pub(crate) fn lower( // ValueId allocation // main() locals let counter_init = alloc_value(); // ValueId(1000) - initial counter - let loop_result = alloc_value(); // ValueId(1001) - result from loop_step + let loop_result = alloc_value(); // ValueId(1001) - result from loop_step // loop_step locals let counter_param = alloc_value(); // ValueId(1002) - parameter - let const_1 = alloc_value(); // ValueId(1003) - increment constant - let counter_next = alloc_value(); // ValueId(1004) - counter + 1 - let const_limit = alloc_value(); // ValueId(1005) - limit constant - let break_cond = alloc_value(); // ValueId(1006) - counter_next == LIMIT + let const_1 = alloc_value(); // ValueId(1003) - increment constant + let counter_next = alloc_value(); // ValueId(1004) - counter + 1 + let const_limit = alloc_value(); // ValueId(1005) - limit constant + let break_cond = alloc_value(); // ValueId(1006) - counter_next == LIMIT // k_exit locals let counter_exit = alloc_value(); // ValueId(1007) - exit parameter @@ -397,33 +467,42 @@ pub(crate) fn lower( // ================================================================== // loop_step(counter) function - post-increment pattern // ================================================================== - let mut loop_step_func = JoinFunction::new(loop_step_id, "loop_step".to_string(), vec![counter_param]); + let mut loop_step_func = + JoinFunction::new(loop_step_id, "loop_step".to_string(), vec![counter_param]); // counter_next = counter + 1 - loop_step_func.body.push(JoinInst::Compute(MirLikeInst::Const { - dst: const_1, - value: ConstValue::Integer(1), - })); + loop_step_func + .body + .push(JoinInst::Compute(MirLikeInst::Const { + dst: const_1, + value: ConstValue::Integer(1), + })); - loop_step_func.body.push(JoinInst::Compute(MirLikeInst::BinOp { - dst: counter_next, - op: BinOpKind::Add, - lhs: counter_param, - rhs: const_1, - })); + loop_step_func + .body + .push(JoinInst::Compute(MirLikeInst::BinOp { + dst: counter_next, + op: BinOpKind::Add, + lhs: counter_param, + rhs: const_1, + })); // break_cond = (counter_next == LIMIT) - loop_step_func.body.push(JoinInst::Compute(MirLikeInst::Const { - dst: const_limit, - value: ConstValue::Integer(limit), - })); + loop_step_func + .body + .push(JoinInst::Compute(MirLikeInst::Const { + dst: const_limit, + value: ConstValue::Integer(limit), + })); - loop_step_func.body.push(JoinInst::Compute(MirLikeInst::Compare { - dst: break_cond, - op: CompareOp::Eq, - lhs: counter_next, - rhs: const_limit, - })); + loop_step_func + .body + .push(JoinInst::Compute(MirLikeInst::Compare { + dst: break_cond, + op: CompareOp::Eq, + lhs: counter_next, + rhs: const_limit, + })); // Jump(k_exit, [counter_next], cond=break_cond) loop_step_func.body.push(JoinInst::Jump { diff --git a/src/mir/builder/control_flow/joinir/patterns/trim_loop_lowering.rs b/src/mir/builder/control_flow/joinir/patterns/trim_loop_lowering.rs index ac03762b..52100fae 100644 --- a/src/mir/builder/control_flow/joinir/patterns/trim_loop_lowering.rs +++ b/src/mir/builder/control_flow/joinir/patterns/trim_loop_lowering.rs @@ -241,7 +241,8 @@ impl TrimLoopLowerer { // Step 3: Convert to CarrierInfo and merge #[cfg(feature = "normalized_dev")] // Phase 136 Step 4/7: Use binding_ctx for binding_map reference - let promoted_carrier = trim_info.to_carrier_info(Some(builder.binding_ctx.binding_map())); + let promoted_carrier = + trim_info.to_carrier_info(Some(builder.binding_ctx.binding_map())); #[cfg(not(feature = "normalized_dev"))] let promoted_carrier = trim_info.to_carrier_info(); carrier_info.merge_from(&promoted_carrier); @@ -352,10 +353,12 @@ impl TrimLoopLowerer { ); // Get ValueIds for string and start - let s_id = - builder.variable_ctx.variable_map.get(&s_name).copied().ok_or_else(|| { - format!("[TrimLoopLowerer] String variable '{}' not found", s_name) - })?; + let s_id = builder + .variable_ctx + .variable_map + .get(&s_name) + .copied() + .ok_or_else(|| format!("[TrimLoopLowerer] String variable '{}' not found", s_name))?; // Compile start expression to get ValueId let start_id = builder.build_expression_impl(*start_expr)?; @@ -403,7 +406,8 @@ impl TrimLoopLowerer { // Register carrier in variable_ctx.variable_map builder - .variable_ctx.variable_map + .variable_ctx + .variable_map .insert(trim_helper.carrier_name.clone(), is_ch_match0); Ok(()) diff --git a/src/mir/builder/control_flow/joinir/routing.rs b/src/mir/builder/control_flow/joinir/routing.rs index b3d1cb50..2ea0274b 100644 --- a/src/mir/builder/control_flow/joinir/routing.rs +++ b/src/mir/builder/control_flow/joinir/routing.rs @@ -6,7 +6,6 @@ use crate::mir::builder::MirBuilder; use crate::mir::ValueId; impl MirBuilder { - /// Phase 49: Try JoinIR Frontend for mainline integration /// /// Returns `Ok(Some(value))` if the loop is successfully lowered via JoinIR, @@ -29,7 +28,8 @@ impl MirBuilder { ) -> Result, String> { // Get current function name let func_name = self - .scope_ctx.current_function + .scope_ctx + .current_function .as_ref() .map(|f| f.signature.name.clone()) .unwrap_or_default(); @@ -138,17 +138,38 @@ impl MirBuilder { match canonicalize_loop_expr(&loop_ast) { Ok((skeleton, decision)) => { eprintln!("[loop_canonicalizer] Function: {}", func_name); - eprintln!("[loop_canonicalizer] Skeleton steps: {}", skeleton.steps.len()); - eprintln!("[loop_canonicalizer] Carriers: {}", skeleton.carriers.len()); - eprintln!("[loop_canonicalizer] Has exits: {}", skeleton.exits.has_any_exit()); - eprintln!("[loop_canonicalizer] Decision: {}", - if decision.is_success() { "SUCCESS" } else { "FAIL_FAST" }); + eprintln!( + "[loop_canonicalizer] Skeleton steps: {}", + skeleton.steps.len() + ); + eprintln!( + "[loop_canonicalizer] Carriers: {}", + skeleton.carriers.len() + ); + eprintln!( + "[loop_canonicalizer] Has exits: {}", + skeleton.exits.has_any_exit() + ); + eprintln!( + "[loop_canonicalizer] Decision: {}", + if decision.is_success() { + "SUCCESS" + } else { + "FAIL_FAST" + } + ); if let Some(pattern) = decision.chosen { eprintln!("[loop_canonicalizer] Chosen pattern: {:?}", pattern); } - eprintln!("[loop_canonicalizer] Missing caps: {:?}", decision.missing_caps); + eprintln!( + "[loop_canonicalizer] Missing caps: {:?}", + decision.missing_caps + ); if decision.is_fail_fast() { - eprintln!("[loop_canonicalizer] Reason: {}", decision.notes.join("; ")); + eprintln!( + "[loop_canonicalizer] Reason: {}", + decision.notes.join("; ") + ); } // Phase 137-4: Router parity verification @@ -183,7 +204,11 @@ impl MirBuilder { func_name, &format!( "fn_body_ast is {}", - if fn_body_clone.is_some() { "SOME" } else { "NONE" } + if fn_body_clone.is_some() { + "SOME" + } else { + "NONE" + } ), ); let ctx = if let Some(ref fn_body) = fn_body_clone { diff --git a/src/mir/builder/decls.rs b/src/mir/builder/decls.rs index 7cf1b88b..2cfdf886 100644 --- a/src/mir/builder/decls.rs +++ b/src/mir/builder/decls.rs @@ -47,7 +47,10 @@ impl super::MirBuilder { ); eprintln!("[DEBUG] params.len() = {}", params.len()); eprintln!("[DEBUG] body.len() = {}", body.len()); - eprintln!("[DEBUG] variable_map = {:?}", self.variable_ctx.variable_map); + eprintln!( + "[DEBUG] variable_map = {:?}", + self.variable_ctx.variable_map + ); // Note: Metadata clearing is now handled by BoxCompilationContext (箱理論) // See lifecycle.rs and builder_calls.rs for context swap implementation let _ = self.lower_static_method_as_function( @@ -58,7 +61,10 @@ impl super::MirBuilder { eprintln!( "[DEBUG] build_static_main_box: After lower_static_method_as_function" ); - eprintln!("[DEBUG] variable_map = {:?}", self.variable_ctx.variable_map); + eprintln!( + "[DEBUG] variable_map = {:?}", + self.variable_ctx.variable_map + ); } // Initialize local variables for Main.main() parameters // Note: These are local variables in the wrapper main() function, NOT parameters @@ -75,8 +81,11 @@ impl super::MirBuilder { box_type: "ArrayBox".to_string(), args: vec![], })?; - self.type_ctx.value_origin_newbox.insert(pid, "ArrayBox".to_string()); - self.type_ctx.value_types + self.type_ctx + .value_origin_newbox + .insert(pid, "ArrayBox".to_string()); + self.type_ctx + .value_types .insert(pid, super::MirType::Box("ArrayBox".to_string())); // Explicitly call birth() to initialize internal state self.emit_instruction(MirInstruction::BoxCall { @@ -206,7 +215,8 @@ impl super::MirBuilder { if let Some((k, prop)) = kind_and_prop { use std::collections::HashMap; let entry: &mut HashMap = self - .comp_ctx.property_getters_by_box + .comp_ctx + .property_getters_by_box .entry(name.clone()) .or_insert_with(HashMap::new); entry.insert(prop, k); diff --git a/src/mir/builder/emission/constant.rs b/src/mir/builder/emission/constant.rs index 90745722..eb5fe8ea 100644 --- a/src/mir/builder/emission/constant.rs +++ b/src/mir/builder/emission/constant.rs @@ -14,7 +14,9 @@ pub fn emit_integer(b: &mut MirBuilder, val: i64) -> ValueId { value: ConstValue::Integer(val), }); // Phase 84-1: Integer constant type annotation - b.type_ctx.value_types.insert(dst, crate::mir::MirType::Integer); + b.type_ctx + .value_types + .insert(dst, crate::mir::MirType::Integer); dst } @@ -26,7 +28,9 @@ pub fn emit_bool(b: &mut MirBuilder, val: bool) -> ValueId { value: ConstValue::Bool(val), }); // Phase 84-1: Bool constant type annotation - b.type_ctx.value_types.insert(dst, crate::mir::MirType::Bool); + b.type_ctx + .value_types + .insert(dst, crate::mir::MirType::Bool); dst } @@ -38,7 +42,9 @@ pub fn emit_float(b: &mut MirBuilder, val: f64) -> ValueId { value: ConstValue::Float(val), }); // Phase 84-1: Float constant type annotation - b.type_ctx.value_types.insert(dst, crate::mir::MirType::Float); + b.type_ctx + .value_types + .insert(dst, crate::mir::MirType::Float); dst } @@ -51,9 +57,12 @@ pub fn emit_string>(b: &mut MirBuilder, s: S) -> ValueId { }); // 🎯 Phase 3-A: String constant type annotation // Ensures string constants have proper Box type for method resolution - b.type_ctx.value_types + b.type_ctx + .value_types .insert(dst, crate::mir::MirType::Box("StringBox".to_string())); - b.type_ctx.value_origin_newbox.insert(dst, "StringBox".to_string()); + b.type_ctx + .value_origin_newbox + .insert(dst, "StringBox".to_string()); dst } @@ -66,7 +75,9 @@ pub fn emit_null(b: &mut MirBuilder) -> ValueId { }); // Phase 84-1: Null constant type annotation // Note: MirType has no Null variant, using Unknown as fallback - b.type_ctx.value_types.insert(dst, crate::mir::MirType::Unknown); + b.type_ctx + .value_types + .insert(dst, crate::mir::MirType::Unknown); dst } @@ -78,6 +89,8 @@ pub fn emit_void(b: &mut MirBuilder) -> ValueId { value: ConstValue::Void, }); // Phase 84-1: Void constant type annotation - b.type_ctx.value_types.insert(dst, crate::mir::MirType::Void); + b.type_ctx + .value_types + .insert(dst, crate::mir::MirType::Void); dst } diff --git a/src/mir/builder/exprs.rs b/src/mir/builder/exprs.rs index ecdc1c08..83d8911f 100644 --- a/src/mir/builder/exprs.rs +++ b/src/mir/builder/exprs.rs @@ -222,7 +222,8 @@ impl super::MirBuilder { body.clone(), )?; // Index static method for fallback resolution of bare calls - self.comp_ctx.static_method_index + self.comp_ctx + .static_method_index .entry(method_name.clone()) .or_insert_with(Vec::new) .push((name.clone(), params.len())); @@ -306,14 +307,18 @@ impl super::MirBuilder { args: vec![], effects: super::EffectMask::MUT, })?; - self.type_ctx.value_origin_newbox + self.type_ctx + .value_origin_newbox .insert(arr_id, "ArrayBox".to_string()); - self.type_ctx.value_types + self.type_ctx + .value_types .insert(arr_id, super::MirType::Box("ArrayBox".to_string())); // TypeRegistry + trace for deterministic debug - self.comp_ctx.type_registry + self.comp_ctx + .type_registry .record_newbox(arr_id, "ArrayBox".to_string()); - self.comp_ctx.type_registry + self.comp_ctx + .type_registry .record_type(arr_id, super::MirType::Box("ArrayBox".to_string())); type_trace::origin("newbox:ArrayLiteral", arr_id, "ArrayBox"); type_trace::ty( @@ -350,13 +355,17 @@ impl super::MirBuilder { args: vec![], effects: super::EffectMask::MUT, })?; - self.type_ctx.value_origin_newbox + self.type_ctx + .value_origin_newbox .insert(map_id, "MapBox".to_string()); - self.type_ctx.value_types + self.type_ctx + .value_types .insert(map_id, super::MirType::Box("MapBox".to_string())); - self.comp_ctx.type_registry + self.comp_ctx + .type_registry .record_newbox(map_id, "MapBox".to_string()); - self.comp_ctx.type_registry + self.comp_ctx + .type_registry .record_type(map_id, super::MirType::Box("MapBox".to_string())); type_trace::origin("newbox:MapLiteral", map_id, "MapBox"); type_trace::ty( @@ -404,13 +413,16 @@ impl super::MirBuilder { if let Some(cls) = self.type_ctx.value_origin_newbox.get(&target_val) { return Some(cls.clone()); } - self.type_ctx.value_types.get(&target_val).and_then(|ty| match ty { - super::MirType::Box(name) => Some(name.clone()), - super::MirType::String => Some("String".to_string()), - super::MirType::Integer => Some("Integer".to_string()), - super::MirType::Float => Some("Float".to_string()), - _ => None, - }) + self.type_ctx + .value_types + .get(&target_val) + .and_then(|ty| match ty { + super::MirType::Box(name) => Some(name.clone()), + super::MirType::String => Some("String".to_string()), + super::MirType::Integer => Some("Integer".to_string()), + super::MirType::Float => Some("Float".to_string()), + _ => None, + }) } fn format_index_target_kind(class_hint: Option<&String>) -> String { diff --git a/src/mir/builder/exprs_lambda.rs b/src/mir/builder/exprs_lambda.rs index 076fe64a..ae6643f0 100644 --- a/src/mir/builder/exprs_lambda.rs +++ b/src/mir/builder/exprs_lambda.rs @@ -170,7 +170,8 @@ impl super::MirBuilder { captures, me, })?; - self.type_ctx.value_types + self.type_ctx + .value_types .insert(dst, crate::mir::MirType::Box("FunctionBox".to_string())); Ok(dst) } diff --git a/src/mir/builder/exprs_peek.rs b/src/mir/builder/exprs_peek.rs index 1457debf..3f25236a 100644 --- a/src/mir/builder/exprs_peek.rs +++ b/src/mir/builder/exprs_peek.rs @@ -118,7 +118,9 @@ impl super::MirBuilder { // Merge and yield result self.start_new_block(merge_block)?; // フェーズM: PHI はブロック先頭に配置(cf_common 統一) - if let (Some(func), Some(cur_bb)) = (self.scope_ctx.current_function.as_mut(), self.current_block) { + if let (Some(func), Some(cur_bb)) = + (self.scope_ctx.current_function.as_mut(), self.current_block) + { crate::mir::ssot::cf_common::insert_phi_at_head_spanned( func, cur_bb, diff --git a/src/mir/builder/fields.rs b/src/mir/builder/fields.rs index 410837a3..f45bae7c 100644 --- a/src/mir/builder/fields.rs +++ b/src/mir/builder/fields.rs @@ -16,7 +16,12 @@ impl super::MirBuilder { // Unified members: if object class is known and has a synthetic getter for `field`, // rewrite to method call `__get_()`. - if let Some(class_name) = self.type_ctx.value_origin_newbox.get(&object_value).cloned() { + if let Some(class_name) = self + .type_ctx + .value_origin_newbox + .get(&object_value) + .cloned() + { if let Some(map) = self.comp_ctx.property_getters_by_box.get(&class_name) { if let Some(kind) = map.get(&field) { let mname = match kind { @@ -53,15 +58,24 @@ impl super::MirBuilder { // Propagate recorded origin class for this field if any (ValueId-scoped) if let Some(class_name) = self - .comp_ctx.field_origin_class + .comp_ctx + .field_origin_class .get(&(object_value, field.clone())) .cloned() { - self.type_ctx.value_origin_newbox.insert(field_val, class_name); - } else if let Some(base_cls) = self.type_ctx.value_origin_newbox.get(&object_value).cloned() { + self.type_ctx + .value_origin_newbox + .insert(field_val, class_name); + } else if let Some(base_cls) = self + .type_ctx + .value_origin_newbox + .get(&object_value) + .cloned() + { // Cross-function heuristic: use class-level field origin mapping if let Some(fcls) = self - .comp_ctx.field_origin_by_box + .comp_ctx + .field_origin_by_box .get(&(base_cls.clone(), field.clone())) .cloned() { @@ -78,8 +92,11 @@ impl super::MirBuilder { } // If base is a known newbox and field is weak, emit WeakLoad (+ optional barrier) - let mut inferred_class: Option = - self.type_ctx.value_origin_newbox.get(&object_value).cloned(); + let mut inferred_class: Option = self + .type_ctx + .value_origin_newbox + .get(&object_value) + .cloned(); if inferred_class.is_none() { if let ASTNode::FieldAccess { object: inner_obj, @@ -89,7 +106,8 @@ impl super::MirBuilder { { if let Ok(base_id) = self.build_expression(*inner_obj.clone()) { if let Some(cls) = self - .comp_ctx.field_origin_class + .comp_ctx + .field_origin_class .get(&(base_id, inner_field)) .cloned() { @@ -128,7 +146,12 @@ impl super::MirBuilder { value_result = self.local_arg(value_result); // If base is known and field is weak, create WeakRef before store - if let Some(class_name) = self.type_ctx.value_origin_newbox.get(&object_value).cloned() { + if let Some(class_name) = self + .type_ctx + .value_origin_newbox + .get(&object_value) + .cloned() + { if let Some(weak_set) = self.comp_ctx.weak_fields_by_box.get(&class_name) { if weak_set.contains(&field) { value_result = self.emit_weak_new(value_result)?; @@ -158,7 +181,12 @@ impl super::MirBuilder { })?; // Write barrier if weak field - if let Some(class_name) = self.type_ctx.value_origin_newbox.get(&object_value).cloned() { + if let Some(class_name) = self + .type_ctx + .value_origin_newbox + .get(&object_value) + .cloned() + { if let Some(weak_set) = self.comp_ctx.weak_fields_by_box.get(&class_name) { if weak_set.contains(&field) { let _ = self.emit_barrier_write(value_result); @@ -167,12 +195,24 @@ impl super::MirBuilder { } // Record origin class for this field value if known - if let Some(val_cls) = self.type_ctx.value_origin_newbox.get(&value_result).cloned() { - self.comp_ctx.field_origin_class + if let Some(val_cls) = self + .type_ctx + .value_origin_newbox + .get(&value_result) + .cloned() + { + self.comp_ctx + .field_origin_class .insert((object_value, field.clone()), val_cls.clone()); // Also record class-level mapping if base object class is known - if let Some(base_cls) = self.type_ctx.value_origin_newbox.get(&object_value).cloned() { - self.comp_ctx.field_origin_by_box + if let Some(base_cls) = self + .type_ctx + .value_origin_newbox + .get(&object_value) + .cloned() + { + self.comp_ctx + .field_origin_by_box .insert((base_cls, field.clone()), val_cls); } } diff --git a/src/mir/builder/if_form.rs b/src/mir/builder/if_form.rs index 8a3964aa..c1a734eb 100644 --- a/src/mir/builder/if_form.rs +++ b/src/mir/builder/if_form.rs @@ -22,9 +22,10 @@ impl<'a> PhiBuilderOps for ToplevelOps<'a> { inputs: Vec<(BasicBlockId, ValueId)>, ) -> Result<(), String> { // merge ブロックの先頭に PHI を挿入 - if let (Some(func), Some(_cur_bb)) = - (self.0.scope_ctx.current_function.as_mut(), self.0.current_block) - { + if let (Some(func), Some(_cur_bb)) = ( + self.0.scope_ctx.current_function.as_mut(), + self.0.current_block, + ) { crate::mir::ssot::cf_common::insert_phi_at_head_spanned( func, block, @@ -170,7 +171,11 @@ impl MirBuilder { } } let val = self.build_expression(else_ast.clone())?; - (val, Some(else_ast), Some(self.variable_ctx.variable_map.clone())) + ( + val, + Some(else_ast), + Some(self.variable_ctx.variable_map.clone()), + ) } else { // No else branch: materialize PHI nodes for the empty else block self.variable_ctx.variable_map = pre_if_var_map.clone(); @@ -222,7 +227,8 @@ impl MirBuilder { // 関数名ガードチェック let func_name = self - .scope_ctx.current_function + .scope_ctx + .current_function .as_ref() .map(|f| f.signature.name.as_str()) .unwrap_or(""); diff --git a/src/mir/builder/lifecycle.rs b/src/mir/builder/lifecycle.rs index 02a3ff79..7b81c563 100644 --- a/src/mir/builder/lifecycle.rs +++ b/src/mir/builder/lifecycle.rs @@ -92,7 +92,8 @@ impl super::MirBuilder { } else { for (mname, mast) in methods { if let ASTNode::FunctionDeclaration { params, .. } = mast { - self.comp_ctx.static_method_index + self.comp_ctx + .static_method_index .entry(mname.clone()) .or_insert_with(Vec::new) .push((name.clone(), params.len())); @@ -207,7 +208,8 @@ impl super::MirBuilder { params.clone(), body.clone(), )?; - self.comp_ctx.static_method_index + self.comp_ctx + .static_method_index .entry(mname.clone()) .or_insert_with(Vec::new) .push((name.clone(), params.len())); @@ -447,7 +449,8 @@ impl super::MirBuilder { // PHI + Copy の小グラフを DFS 探索し、1 種類の型に収束する場合のみ返す。 // これにより Loop edge copy / If merge 後の型推論が解決できる。 if hint.is_none() { - let phi_resolver = PhiTypeResolver::new(&function, &self.type_ctx.value_types); + let phi_resolver = + PhiTypeResolver::new(&function, &self.type_ctx.value_types); if let Some(mt) = phi_resolver.resolve(*v) { if std::env::var("NYASH_P4_DEBUG").is_ok() { eprintln!( @@ -461,9 +464,11 @@ impl super::MirBuilder { } // Phase 67: P3-C 対象なら GenericTypeResolver を優先使用 if hint.is_none() && TypeHintPolicy::is_p3c_target(&function.signature.name) { - if let Some(mt) = - GenericTypeResolver::resolve_from_phi(&function, *v, &self.type_ctx.value_types) - { + if let Some(mt) = GenericTypeResolver::resolve_from_phi( + &function, + *v, + &self.type_ctx.value_types, + ) { if std::env::var("NYASH_P3C_DEBUG").is_ok() { eprintln!( "[lifecycle/p3c] {} type inferred via GenericTypeResolver: {:?}", @@ -650,7 +655,9 @@ impl super::MirBuilder { .unwrap_or(MirType::Unknown), Callee::Constructor { box_type } => { let ret = MirType::Box(box_type.clone()); - self.type_ctx.value_origin_newbox.insert(*dst, box_type.clone()); + self.type_ctx + .value_origin_newbox + .insert(*dst, box_type.clone()); ret } _ => MirType::Unknown, diff --git a/src/mir/builder/method_call_handlers.rs b/src/mir/builder/method_call_handlers.rs index 02893962..9c58e27c 100644 --- a/src/mir/builder/method_call_handlers.rs +++ b/src/mir/builder/method_call_handlers.rs @@ -24,7 +24,8 @@ impl MeCallPolicyBox { ) -> Result, String> { // Instance box: prefer enclosing box method (lowered function) if存在 let enclosing_cls: Option = builder - .scope_ctx.current_function + .scope_ctx + .current_function .as_ref() .and_then(|f| f.signature.name.split('.').next().map(|s| s.to_string())); diff --git a/src/mir/builder/observe/resolve.rs b/src/mir/builder/observe/resolve.rs index dc3a93d8..c17d9c9c 100644 --- a/src/mir/builder/observe/resolve.rs +++ b/src/mir/builder/observe/resolve.rs @@ -25,7 +25,8 @@ fn sample_every() -> usize { /// Dev‑only: emit a resolve.try event(candidates inspection)。 pub(crate) fn emit_try(builder: &MirBuilder, meta: serde_json::Value) { let fn_name = builder - .scope_ctx.current_function + .scope_ctx + .current_function .as_ref() .map(|f| f.signature.name.as_str()); let region = builder.debug_current_region_id(); @@ -35,7 +36,8 @@ pub(crate) fn emit_try(builder: &MirBuilder, meta: serde_json::Value) { /// Dev‑only: emit a resolve.choose event(decision)。 pub(crate) fn emit_choose(builder: &MirBuilder, meta: serde_json::Value) { let fn_name = builder - .scope_ctx.current_function + .scope_ctx + .current_function .as_ref() .map(|f| f.signature.name.as_str()); let region = builder.debug_current_region_id(); diff --git a/src/mir/builder/observe/ssa.rs b/src/mir/builder/observe/ssa.rs index b4ceaa86..c26672a7 100644 --- a/src/mir/builder/observe/ssa.rs +++ b/src/mir/builder/observe/ssa.rs @@ -18,13 +18,15 @@ pub(crate) fn emit_phi(builder: &MirBuilder, dst: ValueId, inputs: &Vec<(BasicBl }) .collect(); let decided_t = builder - .type_ctx.value_types + .type_ctx + .value_types .get(&dst) .cloned() .map(|tt| format!("{:?}", tt)) .unwrap_or_default(); let decided_o = builder - .type_ctx.value_origin_newbox + .type_ctx + .value_origin_newbox .get(&dst) .cloned() .unwrap_or_default(); @@ -35,7 +37,8 @@ pub(crate) fn emit_phi(builder: &MirBuilder, dst: ValueId, inputs: &Vec<(BasicBl "decided_origin": decided_o, }); let fn_name = builder - .scope_ctx.current_function + .scope_ctx + .current_function .as_ref() .map(|f| f.signature.name.as_str()); let region = builder.debug_current_region_id(); diff --git a/src/mir/builder/ops.rs b/src/mir/builder/ops.rs index d6b82175..de6c2e1d 100644 --- a/src/mir/builder/ops.rs +++ b/src/mir/builder/ops.rs @@ -48,7 +48,8 @@ impl super::MirBuilder { BinaryOpType::Arithmetic(op) => { // Dev: Lower '+' を演算子ボックス呼び出しに置換(既定OFF) let in_add_op = self - .scope_ctx.current_function + .scope_ctx + .current_function .as_ref() .map(|f| f.signature.name.starts_with("AddOperator.apply/")) .unwrap_or(false); @@ -80,9 +81,11 @@ impl super::MirBuilder { match (lhs_type, rhs_type) { (String, String) => { // BOTH are strings: result is string - self.type_ctx.value_types + self.type_ctx + .value_types .insert(dst, MirType::Box("StringBox".to_string())); - self.type_ctx.value_origin_newbox + self.type_ctx + .value_origin_newbox .insert(dst, "StringBox".to_string()); } (Integer, Integer) | (Integer, Unknown) | (Unknown, Integer) => { @@ -121,7 +124,8 @@ impl super::MirBuilder { }; if !name.is_empty() { let in_guard = self - .scope_ctx.current_function + .scope_ctx + .current_function .as_ref() .map(|f| f.signature.name.starts_with(guard_prefix)) .unwrap_or(false); @@ -172,9 +176,11 @@ impl super::MirBuilder { match (lhs_type, rhs_type) { (String, String) => { // BOTH are strings: result is definitely a string - self.type_ctx.value_types + self.type_ctx + .value_types .insert(dst, MirType::Box("StringBox".to_string())); - self.type_ctx.value_origin_newbox + self.type_ctx + .value_origin_newbox .insert(dst, "StringBox".to_string()); } (Integer, Integer) | (Integer, Unknown) | (Unknown, Integer) => { @@ -217,7 +223,8 @@ impl super::MirBuilder { Some(MirType::String) => true, Some(MirType::Box(bt)) if bt == "StringBox" => true, _ => self - .type_ctx.value_origin_newbox + .type_ctx + .value_origin_newbox .get(&lhs) .map(|s| s == "StringBox") .unwrap_or(false), @@ -226,16 +233,19 @@ impl super::MirBuilder { Some(MirType::String) => true, Some(MirType::Box(bt)) if bt == "StringBox" => true, _ => self - .type_ctx.value_origin_newbox + .type_ctx + .value_origin_newbox .get(&rhs) .map(|s| s == "StringBox") .unwrap_or(false), }; if lhs_is_str && rhs_is_str { // BOTH are strings: result is definitely a string - self.type_ctx.value_types + self.type_ctx + .value_types .insert(dst, MirType::Box("StringBox".to_string())); - self.type_ctx.value_origin_newbox + self.type_ctx + .value_origin_newbox .insert(dst, "StringBox".to_string()); } else if !lhs_is_str && !rhs_is_str { // NEITHER is a string: numeric addition @@ -252,7 +262,8 @@ impl super::MirBuilder { BinaryOpType::Comparison(op) => { // Dev: Lower 比較 を演算子ボックス呼び出しに置換(既定OFF) let in_cmp_op = self - .scope_ctx.current_function + .scope_ctx + .current_function .as_ref() .map(|f| f.signature.name.starts_with("CompareOperator.apply/")) .unwrap_or(false); @@ -285,12 +296,14 @@ impl super::MirBuilder { } else { // 既存の比較経路(安全のための型注釈/slot化含む) let (lhs2_raw, rhs2_raw) = if self - .type_ctx.value_origin_newbox + .type_ctx + .value_origin_newbox .get(&lhs) .map(|s| s == "IntegerBox") .unwrap_or(false) && self - .type_ctx.value_origin_newbox + .type_ctx + .value_origin_newbox .get(&rhs) .map(|s| s == "IntegerBox") .unwrap_or(false) @@ -541,7 +554,8 @@ impl super::MirBuilder { }; if !name.is_empty() { let in_guard = self - .scope_ctx.current_function + .scope_ctx + .current_function .as_ref() .map(|f| f.signature.name.starts_with(guard_prefix)) .unwrap_or(false); diff --git a/src/mir/builder/origin/infer.rs b/src/mir/builder/origin/infer.rs index 6acd1934..9268fc6a 100644 --- a/src/mir/builder/origin/infer.rs +++ b/src/mir/builder/origin/infer.rs @@ -23,7 +23,10 @@ pub(crate) fn annotate_me_origin(builder: &mut MirBuilder, me_id: ValueId) { } if let Some(c) = cls { // Record both origin class and a Box type hint for downstream passes(観測用)。 - builder.type_ctx.value_origin_newbox.insert(me_id, c.clone()); + builder + .type_ctx + .value_origin_newbox + .insert(me_id, c.clone()); builder.type_ctx.value_types.insert(me_id, MirType::Box(c)); } } diff --git a/src/mir/builder/phi.rs b/src/mir/builder/phi.rs index 749cbc4c..709b6920 100644 --- a/src/mir/builder/phi.rs +++ b/src/mir/builder/phi.rs @@ -70,7 +70,8 @@ impl MirBuilder { if let Some(func) = self.scope_ctx.current_function.as_mut() { func.update_cfg(); } - if let (Some(func), Some(cur_bb)) = (&self.scope_ctx.current_function, self.current_block) + if let (Some(func), Some(cur_bb)) = + (&self.scope_ctx.current_function, self.current_block) { crate::mir::phi_core::common::debug_verify_phi_inputs( func, cur_bb, &inputs, @@ -94,7 +95,9 @@ impl MirBuilder { type_hint: None, // Phase 63-6: Legacy path, no type hint })?; } - self.variable_ctx.variable_map.insert(pin_name.clone(), merged); + self.variable_ctx + .variable_map + .insert(pin_name.clone(), merged); } } } @@ -172,7 +175,8 @@ impl MirBuilder { if let Some(func) = self.scope_ctx.current_function.as_mut() { func.update_cfg(); } - if let (Some(func), Some(cur_bb)) = (&self.scope_ctx.current_function, self.current_block) + if let (Some(func), Some(cur_bb)) = + (&self.scope_ctx.current_function, self.current_block) { crate::mir::phi_core::common::debug_verify_phi_inputs( func, cur_bb, &inputs, @@ -205,7 +209,8 @@ impl MirBuilder { if let Some(func) = self.scope_ctx.current_function.as_mut() { func.update_cfg(); } - if let (Some(func), Some(cur_bb)) = (&self.scope_ctx.current_function, self.current_block) + if let (Some(func), Some(cur_bb)) = + (&self.scope_ctx.current_function, self.current_block) { crate::mir::phi_core::common::debug_verify_phi_inputs( func, cur_bb, &inputs, diff --git a/src/mir/builder/phi_merge.rs b/src/mir/builder/phi_merge.rs index 1485348b..d93d78c0 100644 --- a/src/mir/builder/phi_merge.rs +++ b/src/mir/builder/phi_merge.rs @@ -89,9 +89,10 @@ impl<'a> PhiMergeHelper<'a> { if let Some(func) = self.builder.scope_ctx.current_function.as_mut() { func.update_cfg(); } - if let (Some(func), Some(cur_bb)) = - (&self.builder.scope_ctx.current_function, self.builder.current_block) - { + if let (Some(func), Some(cur_bb)) = ( + &self.builder.scope_ctx.current_function, + self.builder.current_block, + ) { crate::mir::phi_core::common::debug_verify_phi_inputs(func, cur_bb, &inputs); } let merged = self.builder.insert_phi(inputs)?; @@ -135,9 +136,10 @@ impl<'a> PhiMergeHelper<'a> { if let Some(func) = self.builder.scope_ctx.current_function.as_mut() { func.update_cfg(); } - if let (Some(func), Some(cur_bb)) = - (&self.builder.scope_ctx.current_function, self.builder.current_block) - { + if let (Some(func), Some(cur_bb)) = ( + &self.builder.scope_ctx.current_function, + self.builder.current_block, + ) { crate::mir::phi_core::common::debug_verify_phi_inputs(func, cur_bb, &inputs); } self.builder.insert_phi_with_dst(dst, inputs)?; diff --git a/src/mir/builder/receiver.rs b/src/mir/builder/receiver.rs index c053d79f..75d39b06 100644 --- a/src/mir/builder/receiver.rs +++ b/src/mir/builder/receiver.rs @@ -23,13 +23,15 @@ pub fn finalize_method_receiver(builder: &mut MirBuilder, callee: &mut Callee) { // Optional dev trace for receiver aliases if std::env::var("NYASH_BUILDER_TRACE_RECV").ok().as_deref() == Some("1") { let current_fn = builder - .scope_ctx.current_function + .scope_ctx + .current_function .as_ref() .map(|f| f.signature.name.clone()) .unwrap_or_else(|| "".to_string()); let bb = builder.current_block; let names: Vec = builder - .variable_ctx.variable_map + .variable_ctx + .variable_map .iter() .filter(|(_, &vid)| vid == r) .map(|(k, _)| k.clone()) diff --git a/src/mir/builder/rewrite/known.rs b/src/mir/builder/rewrite/known.rs index 84af77e8..df1b036b 100644 --- a/src/mir/builder/rewrite/known.rs +++ b/src/mir/builder/rewrite/known.rs @@ -40,7 +40,12 @@ pub(crate) fn try_known_rewrite( return None; } // Receiver must be Known (origin 由来) - if builder.type_ctx.value_origin_newbox.get(&object_value).is_none() { + if builder + .type_ctx + .value_origin_newbox + .get(&object_value) + .is_none() + { return None; } // Only user-defined boxes (plugin/core boxesは対象外) @@ -54,7 +59,11 @@ pub(crate) fn try_known_rewrite( .ok() .as_deref() == Some("1"); - let from_new_origin = builder.type_ctx.value_origin_newbox.get(&object_value).is_some(); + let from_new_origin = builder + .type_ctx + .value_origin_newbox + .get(&object_value) + .is_some(); let arity = arg_values.len(); let fname = crate::mir::builder::calls::function_lowering::generate_method_function_name( cls, method, arity, @@ -107,7 +116,12 @@ pub(crate) fn try_known_rewrite_to_dst( if !rewrite_enabled() { return None; } - if builder.type_ctx.value_origin_newbox.get(&object_value).is_none() { + if builder + .type_ctx + .value_origin_newbox + .get(&object_value) + .is_none() + { return None; } if !builder.comp_ctx.user_defined_boxes.contains(cls) { @@ -119,7 +133,11 @@ pub(crate) fn try_known_rewrite_to_dst( .ok() .as_deref() == Some("1"); - let from_new_origin = builder.type_ctx.value_origin_newbox.get(&object_value).is_some(); + let from_new_origin = builder + .type_ctx + .value_origin_newbox + .get(&object_value) + .is_some(); let arity = arg_values.len(); let fname = crate::mir::builder::calls::function_lowering::generate_method_function_name( cls, method, arity, @@ -171,7 +189,12 @@ pub(crate) fn try_unique_suffix_rewrite( return None; } // Only attempt if receiver is Known (keeps behavior stable and avoids surprises) - if builder.type_ctx.value_origin_newbox.get(&object_value).is_none() { + if builder + .type_ctx + .value_origin_newbox + .get(&object_value) + .is_none() + { return None; } let mut cands: Vec = builder.method_candidates(method, arg_values.len()); @@ -222,7 +245,12 @@ pub(crate) fn try_unique_suffix_rewrite_to_dst( if !rewrite_enabled() { return None; } - if builder.type_ctx.value_origin_newbox.get(&object_value).is_none() { + if builder + .type_ctx + .value_origin_newbox + .get(&object_value) + .is_none() + { return None; } let mut cands: Vec = builder.method_candidates(method, arg_values.len()); diff --git a/src/mir/builder/schedule/block.rs b/src/mir/builder/schedule/block.rs index 2ec30c8d..98b458de 100644 --- a/src/mir/builder/schedule/block.rs +++ b/src/mir/builder/schedule/block.rs @@ -64,7 +64,10 @@ impl BlockScheduleBox { if std::env::var("NYASH_BLOCK_SCHEDULE_VERIFY").ok().as_deref() != Some("1") { return; } - let (f_opt, bb_opt) = (builder.scope_ctx.current_function.as_ref(), builder.current_block); + let (f_opt, bb_opt) = ( + builder.scope_ctx.current_function.as_ref(), + builder.current_block, + ); let (Some(fun), Some(bb_id)) = (f_opt, bb_opt) else { return; }; diff --git a/src/mir/builder/scope_context.rs b/src/mir/builder/scope_context.rs index 2a5dddca..e864abc1 100644 --- a/src/mir/builder/scope_context.rs +++ b/src/mir/builder/scope_context.rs @@ -72,8 +72,7 @@ impl ScopeContext { /// Push new lexical scope frame #[inline] pub(super) fn push_lexical_scope(&mut self) { - self.lexical_scope_stack - .push(LexicalScopeFrame::default()); + self.lexical_scope_stack.push(LexicalScopeFrame::default()); } /// Pop lexical scope frame (returns frame for restoration) diff --git a/src/mir/builder/ssa/local.rs b/src/mir/builder/ssa/local.rs index 22fef79a..e87fc95c 100644 --- a/src/mir/builder/ssa/local.rs +++ b/src/mir/builder/ssa/local.rs @@ -63,7 +63,8 @@ pub fn ensure(builder: &mut MirBuilder, v: ValueId, kind: LocalKind) -> ValueId let mut slot_name_opt: Option = None; let names_for_v: Vec = builder - .variable_ctx.variable_map + .variable_ctx + .variable_map .iter() .filter(|(k, &vid)| vid == v && k.starts_with("__pin$")) .map(|(k, _)| k.clone()) @@ -116,13 +117,17 @@ pub fn ensure(builder: &mut MirBuilder, v: ValueId, kind: LocalKind) -> ValueId builder.type_ctx.value_types.insert(loc, t); } if let Some(cls) = builder.type_ctx.value_origin_newbox.get(&v).cloned() { - builder.type_ctx.value_origin_newbox.insert(loc, cls.clone()); + builder + .type_ctx + .value_origin_newbox + .insert(loc, cls.clone()); // CRITICAL FIX: For receiver kind, if type is missing but origin exists, // infer MirType::Box from origin if kind == LocalKind::Recv && builder.type_ctx.value_types.get(&loc).is_none() { builder - .type_ctx.value_types + .type_ctx + .value_types .insert(loc, crate::mir::MirType::Box(cls)); } } diff --git a/src/mir/builder/stmts.rs b/src/mir/builder/stmts.rs index 23199966..2461320a 100644 --- a/src/mir/builder/stmts.rs +++ b/src/mir/builder/stmts.rs @@ -181,7 +181,8 @@ impl super::MirBuilder { idx + 1, total, self.current_block, - self.scope_ctx.current_function + self.scope_ctx + .current_function .as_ref() .map(|f| f.signature.name.as_str()) .unwrap_or("none") @@ -427,9 +428,12 @@ impl super::MirBuilder { })?; // Future spawn returns a Future; the inner type is not statically known here. // Register at least Future to avoid later fail-fast type inference panics. - self.type_ctx.value_types + self.type_ctx + .value_types .insert(future_id, MirType::Future(Box::new(MirType::Unknown))); - self.variable_ctx.variable_map.insert(variable.clone(), future_id); + self.variable_ctx + .variable_map + .insert(variable.clone(), future_id); if let Some(reg) = self.comp_ctx.current_slot_registry.as_mut() { reg.ensure_slot(&variable, None); } @@ -442,13 +446,17 @@ impl super::MirBuilder { value: expression_value, })?; let inner = self - .type_ctx.value_types + .type_ctx + .value_types .get(&expression_value) .cloned() .unwrap_or(MirType::Unknown); - self.type_ctx.value_types + self.type_ctx + .value_types .insert(future_id, MirType::Future(Box::new(inner))); - self.variable_ctx.variable_map.insert(variable.clone(), future_id); + self.variable_ctx + .variable_map + .insert(variable.clone(), future_id); if let Some(reg) = self.comp_ctx.current_slot_registry.as_mut() { reg.ensure_slot(&variable, None); } @@ -487,7 +495,9 @@ impl super::MirBuilder { "__me__".to_string() }; let me_value = crate::mir::builder::emission::constant::emit_string(self, me_tag); - self.variable_ctx.variable_map.insert("me".to_string(), me_value); + self.variable_ctx + .variable_map + .insert("me".to_string(), me_value); if let Some(reg) = self.comp_ctx.current_slot_registry.as_mut() { reg.ensure_slot("me", None); } diff --git a/src/mir/builder/utils.rs b/src/mir/builder/utils.rs index 176c7ab1..24858bbd 100644 --- a/src/mir/builder/utils.rs +++ b/src/mir/builder/utils.rs @@ -149,7 +149,8 @@ impl super::MirBuilder { // Second pass: update any user variables that pointed to old pin ids to the new ones if !pin_renames.is_empty() { let snapshot: Vec<(String, super::ValueId)> = self - .variable_ctx.variable_map + .variable_ctx + .variable_map .iter() .filter(|(k, _)| !k.starts_with("__pin$")) .map(|(k, &v)| (k.clone(), v)) @@ -316,7 +317,8 @@ impl super::MirBuilder { effects, })?; if let Some(d) = dst { - let mut recv_box: Option = self.type_ctx.value_origin_newbox.get(&box_val).cloned(); + let mut recv_box: Option = + self.type_ctx.value_origin_newbox.get(&box_val).cloned(); if recv_box.is_none() { if let Some(t) = self.type_ctx.value_types.get(&box_val) { match t { @@ -327,7 +329,11 @@ impl super::MirBuilder { } } if let Some(bt) = recv_box { - if let Some(mt) = self.comp_ctx.plugin_method_sigs.get(&(bt.clone(), method.clone())) { + if let Some(mt) = self + .comp_ctx + .plugin_method_sigs + .get(&(bt.clone(), method.clone())) + { self.type_ctx.value_types.insert(d, mt.clone()); } else { // Phase 84-4-B: ビルトイン Box のメソッド戻り値型推論 @@ -489,7 +495,8 @@ impl super::MirBuilder { dst: super::ValueId, src: super::ValueId, ) -> Result<(), String> { - if let (Some(ref mut function), Some(bb)) = (&mut self.scope_ctx.current_function, self.current_block) + if let (Some(ref mut function), Some(bb)) = + (&mut self.scope_ctx.current_function, self.current_block) { if std::env::var("NYASH_SCHEDULE_TRACE").ok().as_deref() == Some("1") { eprintln!( diff --git a/src/mir/builder/vars/assignment_resolver.rs b/src/mir/builder/vars/assignment_resolver.rs index 81387d1d..c5c95832 100644 --- a/src/mir/builder/vars/assignment_resolver.rs +++ b/src/mir/builder/vars/assignment_resolver.rs @@ -26,4 +26,3 @@ impl AssignmentResolverBox { Err(msg) } } - diff --git a/src/mir/builder/vars/lexical_scope.rs b/src/mir/builder/vars/lexical_scope.rs index b20f8ac2..6257f666 100644 --- a/src/mir/builder/vars/lexical_scope.rs +++ b/src/mir/builder/vars/lexical_scope.rs @@ -97,7 +97,9 @@ impl super::super::MirBuilder { } // Update both ValueId and BindingId mappings - self.variable_ctx.variable_map.insert(name.to_string(), value); + self.variable_ctx + .variable_map + .insert(name.to_string(), value); // Phase 74: Allocate and register new BindingId for this binding let binding_id = self.allocate_binding_id(); diff --git a/src/mir/join_ir/frontend/ast_lowerer/loop_patterns/break_pattern.rs b/src/mir/join_ir/frontend/ast_lowerer/loop_patterns/break_pattern.rs index f89a2cbe..f2f06c22 100644 --- a/src/mir/join_ir/frontend/ast_lowerer/loop_patterns/break_pattern.rs +++ b/src/mir/join_ir/frontend/ast_lowerer/loop_patterns/break_pattern.rs @@ -24,17 +24,15 @@ use super::common::{ build_join_module, create_k_exit_function, create_loop_context, parse_program_json, process_local_inits, }; -use super::param_guess::{build_param_order, compute_param_guess}; #[cfg(feature = "normalized_dev")] use super::if_sum_break_pattern; +use super::param_guess::{build_param_order, compute_param_guess}; use super::{AstToJoinIrLowerer, JoinModule, LoweringError}; use crate::mir::join_ir::{JoinFunction, JoinInst}; use crate::mir::ValueId; #[cfg(feature = "normalized_dev")] -use crate::mir::join_ir::ownership::{ - plan_to_p2_inputs_with_relay, OwnershipAnalyzer, -}; +use crate::mir::join_ir::ownership::{plan_to_p2_inputs_with_relay, OwnershipAnalyzer}; /// Break パターンを JoinModule に変換 /// @@ -217,7 +215,11 @@ fn compute_param_order_from_ownership( // Fallback: any loop plan with relay_writes .or_else(|| plans.iter().find(|p| !p.relay_writes.is_empty())) // Last resort: any plan that owns loop_var_name (loop-local case) - .or_else(|| plans.iter().find(|p| p.owned_vars.iter().any(|v| v.name == loop_var_name)))?; + .or_else(|| { + plans + .iter() + .find(|p| p.owned_vars.iter().any(|v| v.name == loop_var_name)) + })?; let inputs = plan_to_p2_inputs_with_relay(loop_plan, loop_var_name).ok()?; @@ -316,18 +318,19 @@ fn create_loop_step_function_break( let mut body = Vec::new(); - let (loop_cond_var, loop_cond_insts) = - lowerer.extract_value(loop_cond_expr, &mut step_ctx); + let (loop_cond_var, loop_cond_insts) = lowerer.extract_value(loop_cond_expr, &mut step_ctx); body.extend(loop_cond_insts); let acc_current = step_ctx .get_var(acc_name) .unwrap_or_else(|| panic!("{} must be initialized", acc_name)); let header_exit_flag = step_ctx.alloc_var(); - body.push(JoinInst::Compute(crate::mir::join_ir::MirLikeInst::UnaryOp { - dst: header_exit_flag, - op: crate::mir::join_ir::UnaryOp::Not, - operand: loop_cond_var, - })); + body.push(JoinInst::Compute( + crate::mir::join_ir::MirLikeInst::UnaryOp { + dst: header_exit_flag, + op: crate::mir::join_ir::UnaryOp::Not, + operand: loop_cond_var, + }, + )); body.push(JoinInst::Jump { cont: ctx.k_exit_id.as_cont(), args: vec![acc_current], @@ -398,9 +401,7 @@ fn create_loop_step_function_break( Ok(JoinFunction { id: ctx.loop_step_id, name: format!("{}_loop_step", func_name), - params: (0..param_names.len()) - .map(|i| ValueId(i as u32)) - .collect(), + params: (0..param_names.len()).map(|i| ValueId(i as u32)).collect(), body, exit_cont: None, }) diff --git a/src/mir/join_ir/frontend/ast_lowerer/loop_patterns/common.rs b/src/mir/join_ir/frontend/ast_lowerer/loop_patterns/common.rs index 760bfc6e..50def367 100644 --- a/src/mir/join_ir/frontend/ast_lowerer/loop_patterns/common.rs +++ b/src/mir/join_ir/frontend/ast_lowerer/loop_patterns/common.rs @@ -12,8 +12,8 @@ //! - `create_entry_function()`: entry 関数生成 //! - `create_k_exit_function()`: k_exit 関数生成 -use super::{AstToJoinIrLowerer, JoinModule}; use super::super::stmt_handlers::StatementEffect; +use super::{AstToJoinIrLowerer, JoinModule}; use crate::mir::join_ir::JoinIrPhase; use crate::mir::join_ir::{JoinFuncId, JoinFunction, JoinInst}; use crate::mir::ValueId; @@ -127,7 +127,10 @@ pub fn process_local_inits( if let StatementEffect::VarUpdate { name, value_id } = effect { ctx.register_param(name, value_id); } else if matches!(effect, StatementEffect::SideEffect) { - panic!("Unexpected side-effecting statement before Loop: {}", stmt_type); + panic!( + "Unexpected side-effecting statement before Loop: {}", + stmt_type + ); } } _ => panic!("Unexpected statement type before Loop: {}", stmt_type), diff --git a/src/mir/join_ir/frontend/ast_lowerer/loop_patterns/continue_pattern.rs b/src/mir/join_ir/frontend/ast_lowerer/loop_patterns/continue_pattern.rs index f831a90c..03a2064d 100644 --- a/src/mir/join_ir/frontend/ast_lowerer/loop_patterns/continue_pattern.rs +++ b/src/mir/join_ir/frontend/ast_lowerer/loop_patterns/continue_pattern.rs @@ -205,11 +205,12 @@ fn create_loop_step_function_continue( // Phase 89-2: StepCalculator Box に抽出済み(再利用性向上) let mut i_next_continue = i_next; - let continue_then = continue_if_stmt["then"] - .as_array() - .ok_or_else(|| LoweringError::InvalidLoopBody { - message: "Continue pattern If must have 'then' array".to_string(), - })?; + let continue_then = + continue_if_stmt["then"] + .as_array() + .ok_or_else(|| LoweringError::InvalidLoopBody { + message: "Continue pattern If must have 'then' array".to_string(), + })?; if let Some(then_i_local) = continue_then .iter() .find(|stmt| stmt["type"].as_str() == Some("Local") && stmt["name"].as_str() == Some("i")) @@ -283,10 +284,12 @@ fn create_loop_step_function_continue( // Phase 88: Continue 分岐側でも acc を更新できるようにする(例: acc += 1) let mut acc_then_val = step_acc; - if let Some(then_acc_local) = continue_then.iter().find(|stmt| { - stmt["type"].as_str() == Some("Local") && stmt["name"].as_str() == Some("acc") - }) { - let (acc_then, acc_then_insts) = lowerer.extract_value(&then_acc_local["expr"], &mut step_ctx); + if let Some(then_acc_local) = continue_then + .iter() + .find(|stmt| stmt["type"].as_str() == Some("Local") && stmt["name"].as_str() == Some("acc")) + { + let (acc_then, acc_then_insts) = + lowerer.extract_value(&then_acc_local["expr"], &mut step_ctx); body.extend(acc_then_insts); acc_then_val = acc_then; } @@ -298,7 +301,7 @@ fn create_loop_step_function_continue( cond: continue_cond_var, then_val: acc_then_val, else_val: acc_increment, - type_hint: None, // Phase 63-3 + type_hint: None, // Phase 63-3 }); // Phase 88: Continue/通常 で次 i を切り替える diff --git a/src/mir/join_ir/frontend/ast_lowerer/loop_patterns/continue_return_pattern.rs b/src/mir/join_ir/frontend/ast_lowerer/loop_patterns/continue_return_pattern.rs index 700688c1..2dd17bae 100644 --- a/src/mir/join_ir/frontend/ast_lowerer/loop_patterns/continue_return_pattern.rs +++ b/src/mir/join_ir/frontend/ast_lowerer/loop_patterns/continue_return_pattern.rs @@ -128,11 +128,12 @@ pub fn lower( let return_if_stmt = return_if_stmts[0]; // 5-2. Return が then にあることを確認(Fail-Fast) - let return_then = return_if_stmt["then"] - .as_array() - .ok_or_else(|| LoweringError::InvalidLoopBody { - message: "Return If must have 'then' array".to_string(), - })?; + let return_then = + return_if_stmt["then"] + .as_array() + .ok_or_else(|| LoweringError::InvalidLoopBody { + message: "Return If must have 'then' array".to_string(), + })?; let return_stmt = return_then .iter() @@ -318,11 +319,12 @@ fn create_loop_step_function_continue_return( // 3. Continue pattern: i のインクリメント処理 // Continue If の then 内に i の更新がある場合、それを使う(例: i = i + 1) - let continue_then = continue_if_stmt["then"] - .as_array() - .ok_or_else(|| LoweringError::InvalidLoopBody { - message: "Continue If must have 'then' array".to_string(), - })?; + let continue_then = + continue_if_stmt["then"] + .as_array() + .ok_or_else(|| LoweringError::InvalidLoopBody { + message: "Continue If must have 'then' array".to_string(), + })?; let i_update_in_continue = continue_then .iter() @@ -411,9 +413,7 @@ fn create_loop_step_function_continue_return( // 5. acc の更新値を計算(通常パス) let acc_update_local = loop_body .iter() - .find(|stmt| { - stmt["type"].as_str() == Some("Local") && stmt["name"].as_str() == Some("acc") - }) + .find(|stmt| stmt["type"].as_str() == Some("Local") && stmt["name"].as_str() == Some("acc")) .ok_or_else(|| LoweringError::InvalidLoopBody { message: format!( "ContinueReturn pattern validation failed: missing accumulator update.\n\ @@ -429,9 +429,10 @@ fn create_loop_step_function_continue_return( // Continue 分岐側でも acc を更新できる場合(例: acc += 1) let mut acc_then_val = step_acc; - if let Some(then_acc_local) = continue_then.iter().find(|stmt| { - stmt["type"].as_str() == Some("Local") && stmt["name"].as_str() == Some("acc") - }) { + if let Some(then_acc_local) = continue_then + .iter() + .find(|stmt| stmt["type"].as_str() == Some("Local") && stmt["name"].as_str() == Some("acc")) + { let (acc_then, acc_then_insts) = lowerer.extract_value(&then_acc_local["expr"], &mut step_ctx); body.extend(acc_then_insts); diff --git a/src/mir/join_ir/frontend/ast_lowerer/loop_patterns/if_sum_break_pattern.rs b/src/mir/join_ir/frontend/ast_lowerer/loop_patterns/if_sum_break_pattern.rs index 9f9f4663..090e687c 100644 --- a/src/mir/join_ir/frontend/ast_lowerer/loop_patterns/if_sum_break_pattern.rs +++ b/src/mir/join_ir/frontend/ast_lowerer/loop_patterns/if_sum_break_pattern.rs @@ -17,9 +17,9 @@ use super::common::{ process_local_inits, }; use super::{AstToJoinIrLowerer, JoinModule, LoweringError}; +use crate::mir::join_ir::ownership::{plan_to_p3_inputs_with_relay, OwnershipAnalyzer}; use crate::mir::join_ir::{BinOpKind, JoinFunction, JoinInst, MirLikeInst}; use crate::mir::ValueId; -use crate::mir::join_ir::ownership::{plan_to_p3_inputs_with_relay, OwnershipAnalyzer}; pub fn try_lower_if_sum_break( lowerer: &mut AstToJoinIrLowerer, @@ -65,10 +65,7 @@ pub fn try_lower_if_sum_break( None => return Ok(None), }; - let counter_update_stmt = loop_body - .last() - .expect("loop_body len checked") - .clone(); + let counter_update_stmt = loop_body.last().expect("loop_body len checked").clone(); let loop_var_name = detect_counter_update_loop_var(loop_body).ok_or_else(|| { LoweringError::InvalidLoopBody { @@ -92,14 +89,17 @@ pub fn try_lower_if_sum_break( let loop_plan = plans .iter() .find(|p| p.relay_writes.iter().any(|r| r.name == loop_var_name)) - .or_else(|| plans.iter().find(|p| p.owned_vars.iter().any(|v| v.name == loop_var_name))) + .or_else(|| { + plans + .iter() + .find(|p| p.owned_vars.iter().any(|v| v.name == loop_var_name)) + }) .ok_or_else(|| LoweringError::InvalidLoopBody { message: "if-sum-break: failed to find loop ownership plan".to_string(), })?; - let inputs = plan_to_p3_inputs_with_relay(loop_plan, &loop_var_name).map_err(|e| { - LoweringError::JsonParseError { message: e } - })?; + let inputs = plan_to_p3_inputs_with_relay(loop_plan, &loop_var_name) + .map_err(|e| LoweringError::JsonParseError { message: e })?; // Ensure carriers are exactly the return vars (fail-fast mixing protection). let carrier_names: std::collections::BTreeSet = @@ -119,20 +119,25 @@ pub fn try_lower_if_sum_break( let mut param_order: Vec<(String, ValueId)> = Vec::new(); let mut seen = std::collections::BTreeSet::::new(); - let loop_var_id = entry_ctx - .get_var(&loop_var_name) - .ok_or_else(|| LoweringError::InvalidLoopBody { - message: format!("loop var '{}' must be initialized before loop", loop_var_name), - })?; + let loop_var_id = + entry_ctx + .get_var(&loop_var_name) + .ok_or_else(|| LoweringError::InvalidLoopBody { + message: format!( + "loop var '{}' must be initialized before loop", + loop_var_name + ), + })?; param_order.push((loop_var_name.clone(), loop_var_id)); seen.insert(loop_var_name.clone()); for carrier in &inputs.carriers { - let id = entry_ctx - .get_var(&carrier.name) - .ok_or_else(|| LoweringError::InvalidLoopBody { - message: format!("carrier '{}' must be initialized before loop", carrier.name), - })?; + let id = + entry_ctx + .get_var(&carrier.name) + .ok_or_else(|| LoweringError::InvalidLoopBody { + message: format!("carrier '{}' must be initialized before loop", carrier.name), + })?; param_order.push((carrier.name.clone(), id)); seen.insert(carrier.name.clone()); } @@ -155,13 +160,8 @@ pub fn try_lower_if_sum_break( } } - let entry_func = create_entry_function_if_sum_break( - &ctx, - &parsed, - init_insts, - &mut entry_ctx, - ¶m_order, - ); + let entry_func = + create_entry_function_if_sum_break(&ctx, &parsed, init_insts, &mut entry_ctx, ¶m_order); let loop_step_func = create_loop_step_function_if_sum_break( lowerer, @@ -179,12 +179,14 @@ pub fn try_lower_if_sum_break( let k_exit_func = create_k_exit_function(&ctx, &parsed.func_name); - Ok(Some(build_join_module(entry_func, loop_step_func, k_exit_func))) + Ok(Some(build_join_module( + entry_func, + loop_step_func, + k_exit_func, + ))) } -fn parse_return_var_plus_var( - expr: Option<&serde_json::Value>, -) -> Option<(String, String)> { +fn parse_return_var_plus_var(expr: Option<&serde_json::Value>) -> Option<(String, String)> { let expr = expr?; if expr["type"].as_str()? != "Binary" { return None; @@ -300,11 +302,12 @@ fn create_loop_step_function_if_sum_break( .ok_or_else(|| LoweringError::InvalidLoopBody { message: format!("{} must exist", sum_name), })?; - let count_before = step_ctx - .get_var(count_name) - .ok_or_else(|| LoweringError::InvalidLoopBody { - message: format!("{} must exist", count_name), - })?; + let count_before = + step_ctx + .get_var(count_name) + .ok_or_else(|| LoweringError::InvalidLoopBody { + message: format!("{} must exist", count_name), + })?; let acc_before = step_ctx.alloc_var(); body.push(JoinInst::Compute(MirLikeInst::BinOp { dst: acc_before, @@ -333,19 +336,14 @@ fn create_loop_step_function_if_sum_break( lowerer.extract_value(update_cond_expr, &mut step_ctx); body.extend(update_cond_insts); - let (sum_then_expr, sum_else_expr) = - extract_if_branch_assignment(update_if_stmt, sum_name)?; + let (sum_then_expr, sum_else_expr) = extract_if_branch_assignment(update_if_stmt, sum_name)?; let (count_then_expr, count_else_expr) = extract_if_branch_assignment(update_if_stmt, count_name)?; - let (sum_then_val, sum_then_insts) = - lowerer.extract_value(&sum_then_expr, &mut step_ctx); - let (sum_else_val, sum_else_insts) = - lowerer.extract_value(&sum_else_expr, &mut step_ctx); - let (count_then_val, count_then_insts) = - lowerer.extract_value(&count_then_expr, &mut step_ctx); - let (count_else_val, count_else_insts) = - lowerer.extract_value(&count_else_expr, &mut step_ctx); + let (sum_then_val, sum_then_insts) = lowerer.extract_value(&sum_then_expr, &mut step_ctx); + let (sum_else_val, sum_else_insts) = lowerer.extract_value(&sum_else_expr, &mut step_ctx); + let (count_then_val, count_then_insts) = lowerer.extract_value(&count_then_expr, &mut step_ctx); + let (count_else_val, count_else_insts) = lowerer.extract_value(&count_else_expr, &mut step_ctx); body.extend(sum_then_insts); body.extend(sum_else_insts); body.extend(count_then_insts); @@ -370,11 +368,12 @@ fn create_loop_step_function_if_sum_break( step_ctx.register_param(count_name.to_string(), count_next); // Counter update (must update loop var) - let counter_expr = counter_update_stmt.get("expr").ok_or_else(|| { - LoweringError::InvalidLoopBody { - message: "counter update must have 'expr'".to_string(), - } - })?; + let counter_expr = + counter_update_stmt + .get("expr") + .ok_or_else(|| LoweringError::InvalidLoopBody { + message: "counter update must have 'expr'".to_string(), + })?; let (i_next, i_insts) = lowerer.extract_value(counter_expr, &mut step_ctx); body.extend(i_insts); step_ctx.register_param(loop_var_name.to_string(), i_next); @@ -401,9 +400,7 @@ fn create_loop_step_function_if_sum_break( Ok(JoinFunction { id: ctx.loop_step_id, name: format!("{}_loop_step", func_name), - params: (0..param_names.len()) - .map(|i| ValueId(i as u32)) - .collect(), + params: (0..param_names.len()).map(|i| ValueId(i as u32)).collect(), body, exit_cont: None, }) @@ -432,14 +429,20 @@ fn extract_if_branch_assignment( if_stmt: &serde_json::Value, target: &str, ) -> Result<(serde_json::Value, serde_json::Value), LoweringError> { - fn find_assignment_expr(branch: &[serde_json::Value], target: &str) -> Result, LoweringError> { + fn find_assignment_expr( + branch: &[serde_json::Value], + target: &str, + ) -> Result, LoweringError> { let mut found: Option = None; for stmt in branch { match stmt["type"].as_str() { Some("Local") => { - let name = stmt["name"].as_str().ok_or_else(|| LoweringError::InvalidLoopBody { - message: "Local must have 'name'".to_string(), - })?; + let name = + stmt["name"] + .as_str() + .ok_or_else(|| LoweringError::InvalidLoopBody { + message: "Local must have 'name'".to_string(), + })?; if name != target { continue; } @@ -448,15 +451,20 @@ fn extract_if_branch_assignment( message: format!("if-sum-break: multiple assignments to '{}'", target), }); } - let expr = stmt.get("expr").ok_or_else(|| LoweringError::InvalidLoopBody { - message: "Local must have 'expr'".to_string(), - })?; + let expr = stmt + .get("expr") + .ok_or_else(|| LoweringError::InvalidLoopBody { + message: "Local must have 'expr'".to_string(), + })?; found = Some(expr.clone()); } Some("Assignment") | Some("Assign") => { - let name = stmt["target"].as_str().ok_or_else(|| LoweringError::InvalidLoopBody { - message: "Assignment must have 'target'".to_string(), - })?; + let name = + stmt["target"] + .as_str() + .ok_or_else(|| LoweringError::InvalidLoopBody { + message: "Assignment must have 'target'".to_string(), + })?; if name != target { continue; } @@ -465,11 +473,12 @@ fn extract_if_branch_assignment( message: format!("if-sum-break: multiple assignments to '{}'", target), }); } - let expr = stmt.get("expr").or_else(|| stmt.get("value")).ok_or_else(|| { - LoweringError::InvalidLoopBody { + let expr = stmt + .get("expr") + .or_else(|| stmt.get("value")) + .ok_or_else(|| LoweringError::InvalidLoopBody { message: "Assignment must have 'expr' or 'value'".to_string(), - } - })?; + })?; found = Some(expr.clone()); } _ => { @@ -493,11 +502,9 @@ fn extract_if_branch_assignment( message: "If must have 'else' array".to_string(), })?; - let then_expr = find_assignment_expr(then_branch, target)?.unwrap_or_else(|| { - serde_json::json!({"type":"Var","name":target}) - }); - let else_expr = find_assignment_expr(else_branch, target)?.unwrap_or_else(|| { - serde_json::json!({"type":"Var","name":target}) - }); + let then_expr = find_assignment_expr(then_branch, target)? + .unwrap_or_else(|| serde_json::json!({"type":"Var","name":target})); + let else_expr = find_assignment_expr(else_branch, target)? + .unwrap_or_else(|| serde_json::json!({"type":"Var","name":target})); Ok((then_expr, else_expr)) } diff --git a/src/mir/join_ir/frontend/ast_lowerer/loop_patterns/mod.rs b/src/mir/join_ir/frontend/ast_lowerer/loop_patterns/mod.rs index f4fe8dfc..d67367ab 100644 --- a/src/mir/join_ir/frontend/ast_lowerer/loop_patterns/mod.rs +++ b/src/mir/join_ir/frontend/ast_lowerer/loop_patterns/mod.rs @@ -22,9 +22,9 @@ pub mod continue_return_pattern; pub mod filter; #[cfg(feature = "normalized_dev")] pub mod if_sum_break_pattern; +pub mod param_guess; #[cfg(feature = "normalized_dev")] pub mod parse_string_composite_pattern; -pub mod param_guess; pub mod print_tokens; pub mod simple; pub mod step_calculator; diff --git a/src/mir/join_ir/frontend/ast_lowerer/loop_patterns/step_calculator.rs b/src/mir/join_ir/frontend/ast_lowerer/loop_patterns/step_calculator.rs index ecfdef45..3c026f5e 100644 --- a/src/mir/join_ir/frontend/ast_lowerer/loop_patterns/step_calculator.rs +++ b/src/mir/join_ir/frontend/ast_lowerer/loop_patterns/step_calculator.rs @@ -103,7 +103,10 @@ mod tests { "lhs": {"type": "Var", "name": "i"}, "rhs": {"type": "Int", "value": 2} }); - assert_eq!(StepCalculator::extract_linear_increment(&expr, "i"), Some(2)); + assert_eq!( + StepCalculator::extract_linear_increment(&expr, "i"), + Some(2) + ); } #[test] @@ -114,7 +117,10 @@ mod tests { "lhs": {"type": "Int", "value": 3}, "rhs": {"type": "Var", "name": "i"} }); - assert_eq!(StepCalculator::extract_linear_increment(&expr, "i"), Some(3)); + assert_eq!( + StepCalculator::extract_linear_increment(&expr, "i"), + Some(3) + ); } #[test] diff --git a/src/mir/join_ir/frontend/ast_lowerer/mod.rs b/src/mir/join_ir/frontend/ast_lowerer/mod.rs index 452b7c77..15a1642c 100644 --- a/src/mir/join_ir/frontend/ast_lowerer/mod.rs +++ b/src/mir/join_ir/frontend/ast_lowerer/mod.rs @@ -87,15 +87,13 @@ impl AstToJoinIrLowerer { .as_str() .expect("Function must have 'name'"); - let route = resolve_function_route(func_name) - .unwrap_or_else(|msg| panic!("{msg}")); + let route = resolve_function_route(func_name).unwrap_or_else(|msg| panic!("{msg}")); match route { FunctionRoute::IfReturn => self.lower_if_return_pattern(program_json), - FunctionRoute::LoopFrontend => loop_frontend_binding::lower_loop_by_function_name( - self, - program_json, - ), + FunctionRoute::LoopFrontend => { + loop_frontend_binding::lower_loop_by_function_name(self, program_json) + } FunctionRoute::NestedIf => self.lower_nested_if_pattern(program_json), FunctionRoute::ReadQuoted => self.lower_read_quoted_pattern(program_json), } diff --git a/src/mir/join_ir/lowering/carrier_binding_assigner.rs b/src/mir/join_ir/lowering/carrier_binding_assigner.rs index 99c99009..872a7132 100644 --- a/src/mir/join_ir/lowering/carrier_binding_assigner.rs +++ b/src/mir/join_ir/lowering/carrier_binding_assigner.rs @@ -57,8 +57,8 @@ //! // - carrier_info.carriers["is_digit_pos"].binding_id = Some(BindingId(10)) //! ``` -use crate::mir::MirBuilder; use crate::mir::join_ir::lowering::carrier_info::CarrierInfo; +use crate::mir::MirBuilder; #[derive(Debug)] pub enum CarrierBindingError { @@ -87,9 +87,7 @@ impl CarrierBindingAssigner { Some(bid) => bid, None => { let bid = builder.allocate_binding_id(); - builder - .binding_map - .insert(original_name.to_string(), bid); + builder.binding_map.insert(original_name.to_string(), bid); bid } }; @@ -189,14 +187,16 @@ mod tests { #[test] fn test_assign_promoted_binding_success() { - use crate::mir::join_ir::lowering::carrier_info::{CarrierVar, CarrierRole, CarrierInit}; + use crate::mir::join_ir::lowering::carrier_info::{CarrierInit, CarrierRole, CarrierVar}; // Create a MirBuilder with binding_map let mut builder = MirBuilder::new(); // Add original binding to builder.binding_map let original_bid = builder.allocate_binding_id(); - builder.binding_map.insert("digit_pos".to_string(), original_bid); + builder + .binding_map + .insert("digit_pos".to_string(), original_bid); // Create CarrierInfo with promoted carrier let mut carrier_info = CarrierInfo::with_carriers( @@ -227,7 +227,11 @@ mod tests { assert!(promoted_bid.is_some()); // Verify: carrier.binding_id was set - let carrier = carrier_info.carriers.iter().find(|c| c.name == "is_digit_pos").unwrap(); + let carrier = carrier_info + .carriers + .iter() + .find(|c| c.name == "is_digit_pos") + .unwrap(); assert_eq!(carrier.binding_id, promoted_bid); } @@ -238,16 +242,18 @@ mod tests { // Create MirBuilder WITHOUT adding "digit_pos" to binding_map let mut builder = MirBuilder::new(); - let mut carrier_info = CarrierInfo::with_carriers("test_loop".to_string(), ValueId(0), vec![ - CarrierVar { + let mut carrier_info = CarrierInfo::with_carriers( + "test_loop".to_string(), + ValueId(0), + vec![CarrierVar { name: "is_digit_pos".to_string(), host_id: ValueId(0), join_id: None, role: CarrierRole::ConditionOnly, init: CarrierInit::BoolConst(false), binding_id: None, - }, - ]); + }], + ); // Should succeed (original/promoted BindingId are allocated on demand). let result = CarrierBindingAssigner::assign_promoted_binding( @@ -270,12 +276,14 @@ mod tests { #[test] fn test_assign_promoted_binding_multiple_carriers() { - use crate::mir::join_ir::lowering::carrier_info::{CarrierVar, CarrierRole, CarrierInit}; + use crate::mir::join_ir::lowering::carrier_info::{CarrierInit, CarrierRole, CarrierVar}; let mut builder = MirBuilder::new(); // Add two original bindings let digit_pos_bid = builder.allocate_binding_id(); - builder.binding_map.insert("digit_pos".to_string(), digit_pos_bid); + builder + .binding_map + .insert("digit_pos".to_string(), digit_pos_bid); let ch_bid = builder.allocate_binding_id(); builder.binding_map.insert("ch".to_string(), ch_bid); @@ -309,24 +317,36 @@ mod tests { &mut carrier_info, "digit_pos", "is_digit_pos", - ).unwrap(); + ) + .unwrap(); CarrierBindingAssigner::assign_promoted_binding( &mut builder, &mut carrier_info, "ch", "is_ch_match", - ).unwrap(); + ) + .unwrap(); // Verify both mappings exist - assert!(carrier_info.resolve_promoted_with_binding(digit_pos_bid).is_some()); + assert!(carrier_info + .resolve_promoted_with_binding(digit_pos_bid) + .is_some()); assert!(carrier_info.resolve_promoted_with_binding(ch_bid).is_some()); // Verify both carriers have binding_id set - let is_digit_pos = carrier_info.carriers.iter().find(|c| c.name == "is_digit_pos").unwrap(); + let is_digit_pos = carrier_info + .carriers + .iter() + .find(|c| c.name == "is_digit_pos") + .unwrap(); assert!(is_digit_pos.binding_id.is_some()); - let is_ch_match = carrier_info.carriers.iter().find(|c| c.name == "is_ch_match").unwrap(); + let is_ch_match = carrier_info + .carriers + .iter() + .find(|c| c.name == "is_ch_match") + .unwrap(); assert!(is_ch_match.binding_id.is_some()); } } diff --git a/src/mir/join_ir/lowering/carrier_info.rs b/src/mir/join_ir/lowering/carrier_info.rs index 37102c0d..9240d0b8 100644 --- a/src/mir/join_ir/lowering/carrier_info.rs +++ b/src/mir/join_ir/lowering/carrier_info.rs @@ -649,7 +649,11 @@ impl CarrierInfo { /// don't have access to binding_map. Actual population happens in a future phase when /// we integrate BindingId tracking into the promotion pipeline. #[cfg(feature = "normalized_dev")] - pub fn record_promoted_binding(&mut self, original_binding: BindingId, promoted_binding: BindingId) { + pub fn record_promoted_binding( + &mut self, + original_binding: BindingId, + promoted_binding: BindingId, + ) { use super::debug_output_box::DebugOutputBox; // Phase 86: Use DebugOutputBox for consistent debug output @@ -663,7 +667,8 @@ impl CarrierInfo { original_binding, promoted_binding ); } - self.promoted_bindings.insert(original_binding, promoted_binding); + self.promoted_bindings + .insert(original_binding, promoted_binding); } } diff --git a/src/mir/join_ir/lowering/condition_env.rs b/src/mir/join_ir/lowering/condition_env.rs index ccbc1504..fc8b56e1 100644 --- a/src/mir/join_ir/lowering/condition_env.rs +++ b/src/mir/join_ir/lowering/condition_env.rs @@ -191,11 +191,7 @@ impl ConditionEnv { /// } /// ``` #[cfg(feature = "normalized_dev")] - pub fn register_carrier_binding( - &mut self, - binding_id: BindingId, - join_value_id: ValueId, - ) { + pub fn register_carrier_binding(&mut self, binding_id: BindingId, join_value_id: ValueId) { self.binding_id_map.insert(binding_id, join_value_id); } @@ -219,11 +215,7 @@ impl ConditionEnv { /// } /// ``` #[cfg(feature = "normalized_dev")] - pub fn register_loop_var_binding( - &mut self, - binding_id: BindingId, - value_id: ValueId, - ) { + pub fn register_loop_var_binding(&mut self, binding_id: BindingId, value_id: ValueId) { self.binding_id_map.insert(binding_id, value_id); } @@ -250,11 +242,7 @@ impl ConditionEnv { /// } /// ``` #[cfg(feature = "normalized_dev")] - pub fn register_condition_binding( - &mut self, - binding_id: BindingId, - value_id: ValueId, - ) { + pub fn register_condition_binding(&mut self, binding_id: BindingId, value_id: ValueId) { self.binding_id_map.insert(binding_id, value_id); } @@ -315,7 +303,10 @@ impl ConditionEnv { if let Some(&value_id) = self.binding_id_map.get(&bid) { debug.log( "hit", - &format!("BindingId({}) -> ValueId({}) for '{}'", bid.0, value_id.0, name), + &format!( + "BindingId({}) -> ValueId({}) for '{}'", + bid.0, value_id.0, name + ), ); return Some(value_id); } else { @@ -330,7 +321,10 @@ impl ConditionEnv { } else { // Legacy: no BindingId, use name lookup let result = self.get(name); - debug.log("legacy", &format!("No BindingId, name '{}' -> {:?}", name, result)); + debug.log( + "legacy", + &format!("No BindingId, name '{}' -> {:?}", name, result), + ); return result; } } diff --git a/src/mir/join_ir/lowering/condition_lowerer.rs b/src/mir/join_ir/lowering/condition_lowerer.rs index 2a407773..e8a1ba3d 100644 --- a/src/mir/join_ir/lowering/condition_lowerer.rs +++ b/src/mir/join_ir/lowering/condition_lowerer.rs @@ -129,8 +129,7 @@ fn lower_comparison( alloc_value: &mut dyn FnMut() -> ValueId, env: &ConditionEnv, instructions: &mut Vec, -) -> Result -{ +) -> Result { // Lower left and right sides let lhs = lower_value_expression(left, alloc_value, env, instructions)?; let rhs = lower_value_expression(right, alloc_value, env, instructions)?; @@ -164,8 +163,7 @@ fn lower_logical_and( alloc_value: &mut dyn FnMut() -> ValueId, env: &ConditionEnv, instructions: &mut Vec, -) -> Result -{ +) -> Result { // Logical AND: evaluate both sides and combine let lhs = lower_condition_recursive(left, alloc_value, env, instructions)?; let rhs = lower_condition_recursive(right, alloc_value, env, instructions)?; @@ -189,8 +187,7 @@ fn lower_logical_or( alloc_value: &mut dyn FnMut() -> ValueId, env: &ConditionEnv, instructions: &mut Vec, -) -> Result -{ +) -> Result { // Logical OR: evaluate both sides and combine let lhs = lower_condition_recursive(left, alloc_value, env, instructions)?; let rhs = lower_condition_recursive(right, alloc_value, env, instructions)?; @@ -213,8 +210,7 @@ fn lower_not_operator( alloc_value: &mut dyn FnMut() -> ValueId, env: &ConditionEnv, instructions: &mut Vec, -) -> Result -{ +) -> Result { let operand_val = lower_condition_recursive(operand, alloc_value, env, instructions)?; let dst = alloc_value(); @@ -233,8 +229,7 @@ fn lower_literal( value: &LiteralValue, alloc_value: &mut dyn FnMut() -> ValueId, instructions: &mut Vec, -) -> Result -{ +) -> Result { let dst = alloc_value(); let const_value = match value { LiteralValue::Integer(n) => ConstValue::Integer(*n), @@ -322,8 +317,7 @@ fn lower_arithmetic_binop( alloc_value: &mut dyn FnMut() -> ValueId, env: &ConditionEnv, instructions: &mut Vec, -) -> Result -{ +) -> Result { let lhs = lower_value_expression(left, alloc_value, env, instructions)?; let rhs = lower_value_expression(right, alloc_value, env, instructions)?; let dst = alloc_value(); diff --git a/src/mir/join_ir/lowering/condition_lowering_box.rs b/src/mir/join_ir/lowering/condition_lowering_box.rs index caf11cb2..076524f7 100644 --- a/src/mir/join_ir/lowering/condition_lowering_box.rs +++ b/src/mir/join_ir/lowering/condition_lowering_box.rs @@ -206,7 +206,7 @@ mod tests { carriers: vec![], trim_helper: None, promoted_loopbodylocals: vec![], -#[cfg(feature = "normalized_dev")] + #[cfg(feature = "normalized_dev")] promoted_bindings: std::collections::BTreeMap::new(), }; @@ -262,7 +262,7 @@ mod tests { carriers: vec![], trim_helper: None, promoted_loopbodylocals: vec![], -#[cfg(feature = "normalized_dev")] + #[cfg(feature = "normalized_dev")] promoted_bindings: std::collections::BTreeMap::new(), }; diff --git a/src/mir/join_ir/lowering/condition_pattern.rs b/src/mir/join_ir/lowering/condition_pattern.rs index 608ceb11..a1474e1d 100644 --- a/src/mir/join_ir/lowering/condition_pattern.rs +++ b/src/mir/join_ir/lowering/condition_pattern.rs @@ -49,16 +49,21 @@ fn is_if_sum_value_expr(expr: &ASTNode) -> bool { match expr { ASTNode::Variable { .. } | ASTNode::Literal { .. } => true, ASTNode::BinaryOp { - operator, left, right, .. - } => matches!( operator, - BinaryOperator::Add - | BinaryOperator::Subtract - | BinaryOperator::Multiply - | BinaryOperator::Divide - | BinaryOperator::Modulo - ) && is_if_sum_value_expr(left.as_ref()) - && is_if_sum_value_expr(right.as_ref()), + left, + right, + .. + } => { + matches!( + operator, + BinaryOperator::Add + | BinaryOperator::Subtract + | BinaryOperator::Multiply + | BinaryOperator::Divide + | BinaryOperator::Modulo + ) && is_if_sum_value_expr(left.as_ref()) + && is_if_sum_value_expr(right.as_ref()) + } _ => false, } } diff --git a/src/mir/join_ir/lowering/expr_lowerer.rs b/src/mir/join_ir/lowering/expr_lowerer.rs index b60cd612..817d09c1 100644 --- a/src/mir/join_ir/lowering/expr_lowerer.rs +++ b/src/mir/join_ir/lowering/expr_lowerer.rs @@ -192,7 +192,11 @@ impl<'env, 'builder, S: ScopeManager> ExprLowerer<'env, 'builder, S> { // 2. Build ConditionEnv from ScopeManager // Phase 79-1: Use BindingId-aware version when available #[cfg(feature = "normalized_dev")] - let condition_env = scope_resolution::build_condition_env_from_scope_with_binding(self.scope, ast, self.builder)?; + let condition_env = scope_resolution::build_condition_env_from_scope_with_binding( + self.scope, + ast, + self.builder, + )?; #[cfg(not(feature = "normalized_dev"))] let condition_env = scope_resolution::build_condition_env_from_scope(self.scope, ast)?; @@ -279,13 +283,17 @@ impl<'env, 'builder, S: ScopeManager> ConditionLoweringBox for ExprLowerer<'e // Build ConditionEnv from the provided scope (the caller controls the scope + allocator). #[cfg(feature = "normalized_dev")] - let condition_env = - scope_resolution::build_condition_env_from_scope_with_binding(context.scope, condition, self.builder) - .map_err(|e| e.to_string())?; + let condition_env = scope_resolution::build_condition_env_from_scope_with_binding( + context.scope, + condition, + self.builder, + ) + .map_err(|e| e.to_string())?; #[cfg(not(feature = "normalized_dev"))] - let condition_env = scope_resolution::build_condition_env_from_scope(context.scope, condition) - .map_err(|e| e.to_string())?; + let condition_env = + scope_resolution::build_condition_env_from_scope(context.scope, condition) + .map_err(|e| e.to_string())?; // Delegate to the well-tested lowerer, but use the caller-provided allocator (SSOT). let (result_value, instructions) = @@ -347,7 +355,7 @@ mod tests { carriers: vec![], trim_helper: None, promoted_loopbodylocals: vec![], -#[cfg(feature = "normalized_dev")] + #[cfg(feature = "normalized_dev")] promoted_bindings: std::collections::BTreeMap::new(), }; @@ -393,7 +401,7 @@ mod tests { carriers: vec![], trim_helper: None, promoted_loopbodylocals: vec![], -#[cfg(feature = "normalized_dev")] + #[cfg(feature = "normalized_dev")] promoted_bindings: std::collections::BTreeMap::new(), }; @@ -439,7 +447,7 @@ mod tests { carriers: vec![], trim_helper: None, promoted_loopbodylocals: vec![], -#[cfg(feature = "normalized_dev")] + #[cfg(feature = "normalized_dev")] promoted_bindings: std::collections::BTreeMap::new(), }; @@ -521,7 +529,7 @@ mod tests { carriers: vec![], trim_helper: None, promoted_loopbodylocals: vec![], -#[cfg(feature = "normalized_dev")] + #[cfg(feature = "normalized_dev")] promoted_bindings: std::collections::BTreeMap::new(), }; let boxed_carrier: Box = Box::new(carrier_info); @@ -550,7 +558,7 @@ mod tests { carriers: vec![], trim_helper: None, promoted_loopbodylocals: vec![], -#[cfg(feature = "normalized_dev")] + #[cfg(feature = "normalized_dev")] promoted_bindings: std::collections::BTreeMap::new(), }; let boxed_carrier: Box = Box::new(carrier_info); @@ -701,7 +709,7 @@ mod tests { carriers: vec![], trim_helper: None, promoted_loopbodylocals: vec![], -#[cfg(feature = "normalized_dev")] + #[cfg(feature = "normalized_dev")] promoted_bindings: std::collections::BTreeMap::new(), }; diff --git a/src/mir/join_ir/lowering/expr_lowerer/scope_resolution.rs b/src/mir/join_ir/lowering/expr_lowerer/scope_resolution.rs index 4100dfd4..78dfaeba 100644 --- a/src/mir/join_ir/lowering/expr_lowerer/scope_resolution.rs +++ b/src/mir/join_ir/lowering/expr_lowerer/scope_resolution.rs @@ -1,8 +1,8 @@ use super::{ExprLoweringError, ScopeManager}; use crate::ast::ASTNode; -use crate::mir::join_ir::lowering::condition_env::ConditionEnv; #[cfg(feature = "normalized_dev")] use crate::mir::builder::MirBuilder; +use crate::mir::join_ir::lowering::condition_env::ConditionEnv; /// Phase 79-1: Build ConditionEnv with BindingId support (dev-only) /// diff --git a/src/mir/join_ir/lowering/inline_boundary.rs b/src/mir/join_ir/lowering/inline_boundary.rs index 723f890e..a10b398b 100644 --- a/src/mir/join_ir/lowering/inline_boundary.rs +++ b/src/mir/join_ir/lowering/inline_boundary.rs @@ -116,9 +116,9 @@ pub struct LoopExitBinding { pub struct JoinInlineBoundary { /// JoinIR-local ValueIds that act as "input slots" /// -/// These are the ValueIds used **inside** the JoinIR fragment to refer -/// to values that come from the host. They should be in the JoinValueSpace -/// Param region (100-999). (They are typically allocated sequentially.) + /// These are the ValueIds used **inside** the JoinIR fragment to refer + /// to values that come from the host. They should be in the JoinValueSpace + /// Param region (100-999). (They are typically allocated sequentially.) /// /// Example: For a loop variable `i`, JoinIR uses ValueId(100) as the parameter. pub join_inputs: Vec, diff --git a/src/mir/join_ir/lowering/loop_to_join/case_a_entrypoints.rs b/src/mir/join_ir/lowering/loop_to_join/case_a_entrypoints.rs index c3c64e5f..d85062eb 100644 --- a/src/mir/join_ir/lowering/loop_to_join/case_a_entrypoints.rs +++ b/src/mir/join_ir/lowering/loop_to_join/case_a_entrypoints.rs @@ -70,4 +70,3 @@ impl LoopToJoinLowerer { ) } } - diff --git a/src/mir/join_ir/lowering/loop_to_join/core.rs b/src/mir/join_ir/lowering/loop_to_join/core.rs index 5d641600..89b76a3d 100644 --- a/src/mir/join_ir/lowering/loop_to_join/core.rs +++ b/src/mir/join_ir/lowering/loop_to_join/core.rs @@ -108,9 +108,10 @@ impl LoopToJoinLowerer { } if !generic_case_a_enabled() { - if !func_name - .map_or(false, super::super::loop_scope_shape::is_case_a_minimal_target) - { + if !func_name.map_or( + false, + super::super::loop_scope_shape::is_case_a_minimal_target, + ) { if self.debug { eprintln!( "[LoopToJoinLowerer] rejected by name filter (generic disabled): {:?}", @@ -163,4 +164,3 @@ mod tests { assert!(!lowerer.debug || lowerer.debug); } } - diff --git a/src/mir/join_ir/lowering/loop_to_join/mod.rs b/src/mir/join_ir/lowering/loop_to_join/mod.rs index 209f4f90..1d25a66b 100644 --- a/src/mir/join_ir/lowering/loop_to_join/mod.rs +++ b/src/mir/join_ir/lowering/loop_to_join/mod.rs @@ -12,8 +12,7 @@ //! - Phase 進捗ログはここに混ぜない(現役の導線のみ)。 //! - “とりあえず通す”フォールバックは増やさない。失敗は `None` で上位に返す。 -mod core; mod case_a_entrypoints; +mod core; pub use core::LoopToJoinLowerer; - diff --git a/src/mir/join_ir/lowering/loop_with_break_minimal.rs b/src/mir/join_ir/lowering/loop_with_break_minimal.rs index 9d8ecbf5..7cd6c644 100644 --- a/src/mir/join_ir/lowering/loop_with_break_minimal.rs +++ b/src/mir/join_ir/lowering/loop_with_break_minimal.rs @@ -261,9 +261,7 @@ pub(crate) fn lower_loop_with_break_minimal( "[joinir/pattern2] Phase 201: loop_step params - i_param={:?}, carrier_params={:?}", i_param, carrier_param_ids ); - if crate::config::env::joinir_dev_enabled() - || crate::config::env::joinir_test_debug_enabled() - { + if crate::config::env::joinir_dev_enabled() || crate::config::env::joinir_test_debug_enabled() { eprintln!( "[joinir/pattern2/debug] loop_var='{}' env.get(loop_var)={:?}, carriers={:?}", loop_var_name, @@ -668,7 +666,9 @@ pub(crate) fn lower_loop_with_break_minimal( Pattern2StepKind::Updates => loop_step_func.body.append(&mut carrier_update_block), Pattern2StepKind::Tail => loop_step_func.body.append(&mut tail_block), // Phase 47-A: P3 steps not used in P2 lowering (handled in Pattern3 lowerer) - Pattern2StepKind::IfCond | Pattern2StepKind::ThenUpdates | Pattern2StepKind::ElseUpdates => { + Pattern2StepKind::IfCond + | Pattern2StepKind::ThenUpdates + | Pattern2StepKind::ElseUpdates => { panic!("Pattern3 step kinds should not appear in Pattern2 lowering"); } // Phase 48-A: P4 steps not used in P2 lowering (handled in Pattern4 lowerer) diff --git a/src/mir/join_ir/lowering/loop_with_break_minimal/tests.rs b/src/mir/join_ir/lowering/loop_with_break_minimal/tests.rs index 84cc7a44..9a96d01a 100644 --- a/src/mir/join_ir/lowering/loop_with_break_minimal/tests.rs +++ b/src/mir/join_ir/lowering/loop_with_break_minimal/tests.rs @@ -127,8 +127,8 @@ fn test_pattern2_header_condition_via_exprlowerer() { carriers: vec![], trim_helper: None, promoted_loopbodylocals: vec![], -#[cfg(feature = "normalized_dev")] - promoted_bindings: std::collections::BTreeMap::new(), + #[cfg(feature = "normalized_dev")] + promoted_bindings: std::collections::BTreeMap::new(), }; let carrier_updates = BTreeMap::new(); diff --git a/src/mir/join_ir/lowering/loop_with_continue_minimal.rs b/src/mir/join_ir/lowering/loop_with_continue_minimal.rs index a0ad16fe..c7decd58 100644 --- a/src/mir/join_ir/lowering/loop_with_continue_minimal.rs +++ b/src/mir/join_ir/lowering/loop_with_continue_minimal.rs @@ -126,7 +126,9 @@ pub(crate) fn lower_loop_with_continue_minimal( carrier_info: &CarrierInfo, carrier_updates: &BTreeMap, // Phase 222.5-D: HashMap → BTreeMap for determinism join_value_space: &mut JoinValueSpace, - #[cfg(feature = "normalized_dev")] binding_map: Option<&std::collections::BTreeMap>, + #[cfg(feature = "normalized_dev")] binding_map: Option< + &std::collections::BTreeMap, + >, ) -> Result<(JoinModule, ExitMeta), String> { // Phase 170-D-impl-3: Validate that loop condition only uses supported variable scopes // LoopConditionScopeBox checks that loop conditions don't reference loop-body-local variables diff --git a/src/mir/join_ir/lowering/mod.rs b/src/mir/join_ir/lowering/mod.rs index 590a5f1e..ff7123d4 100644 --- a/src/mir/join_ir/lowering/mod.rs +++ b/src/mir/join_ir/lowering/mod.rs @@ -25,8 +25,6 @@ pub mod carrier_info; // Phase 196: Carrier metadata for loop lowering pub(crate) mod carrier_update_emitter; // Phase 179: Carrier update instruction emission pub(crate) mod common; // Internal lowering utilities pub mod complex_addend_normalizer; // Phase 192: Complex addend normalization (AST preprocessing) -pub mod debug_output_box; // Phase 85: Centralized debug output management -pub mod error_tags; // Phase 86: Centralized error message formatting pub mod condition_env; // Phase 171-fix: Condition expression environment pub(crate) mod condition_lowerer; // Phase 171-fix: Core condition lowering logic pub mod condition_lowering_box; // Phase 244: Unified condition lowering interface (trait-based) @@ -34,7 +32,9 @@ pub mod condition_pattern; // Phase 219-fix: If condition pattern detection (sim pub mod condition_to_joinir; // Phase 169: JoinIR condition lowering orchestrator (refactored) pub(crate) mod condition_var_extractor; // Phase 171-fix: Variable extraction from condition AST pub mod continue_branch_normalizer; // Phase 33-19: Continue branch normalization for Pattern B +pub mod debug_output_box; // Phase 85: Centralized debug output management pub mod digitpos_condition_normalizer; // Phase 224-E: DigitPos condition normalizer (digit_pos < 0 → !is_digit_pos) +pub mod error_tags; // Phase 86: Centralized error message formatting pub(crate) mod exit_args_resolver; // Internal exit argument resolution pub mod expr_lowerer; // Phase 231: Unified expression lowering with scope management pub mod funcscanner_append_defs; @@ -64,12 +64,12 @@ pub(crate) mod loop_view_builder; // Phase 33-23: Loop lowering dispatch pub mod loop_with_break_minimal; // Phase 188-Impl-2: Pattern 2 minimal lowerer pub mod loop_with_continue_minimal; pub mod method_call_lowerer; // Phase 224-B: MethodCall lowering (metadata-driven) -pub(crate) mod step_schedule; // Phase 47-A: Generic step scheduler for P2/P3 (renamed from pattern2_step_schedule) pub mod method_return_hint; // Phase 83: P3-D 既知メソッド戻り値型推論箱 pub mod scope_manager; // Phase 231: Unified variable scope management // Phase 195: Pattern 4 minimal lowerer #[cfg(feature = "normalized_dev")] -pub mod scope_manager_bindingid_poc; // Phase 73: BindingId-based scope PoC (dev-only) - // Phase 242-EX-A: loop_with_if_phi_minimal removed - replaced by loop_with_if_phi_if_sum +pub mod scope_manager_bindingid_poc; +pub(crate) mod step_schedule; // Phase 47-A: Generic step scheduler for P2/P3 (renamed from pattern2_step_schedule) // Phase 73: BindingId-based scope PoC (dev-only) + // Phase 242-EX-A: loop_with_if_phi_minimal removed - replaced by loop_with_if_phi_if_sum pub mod loop_with_if_phi_if_sum; // Phase 213: Pattern 3 AST-based if-sum lowerer (Phase 242-EX-A: supports complex conditions) pub mod min_loop; pub mod simple_while_minimal; // Phase 188-Impl-1: Pattern 1 minimal lowerer diff --git a/src/mir/join_ir/lowering/scope_manager.rs b/src/mir/join_ir/lowering/scope_manager.rs index 1c3d59ad..a09a2183 100644 --- a/src/mir/join_ir/lowering/scope_manager.rs +++ b/src/mir/join_ir/lowering/scope_manager.rs @@ -274,7 +274,10 @@ impl<'a> ScopeManager for Pattern2ScopeManager<'a> { if let Some(value_id) = self.condition_env.resolve_var_with_binding(Some(bid), name) { debug.log( "direct", - &format!("BindingId({}) -> ValueId({}) for '{}'", bid.0, value_id.0, name), + &format!( + "BindingId({}) -> ValueId({}) for '{}'", + bid.0, value_id.0, name + ), ); return Some(value_id); } @@ -282,7 +285,10 @@ impl<'a> ScopeManager for Pattern2ScopeManager<'a> { // Step 2: **NEW (Phase 76)**: Check promoted_bindings map if let Some(promoted_bid) = self.carrier_info.resolve_promoted_with_binding(bid) { // Promoted BindingId found, lookup in ConditionEnv - if let Some(value_id) = self.condition_env.resolve_var_with_binding(Some(promoted_bid), name) { + if let Some(value_id) = self + .condition_env + .resolve_var_with_binding(Some(promoted_bid), name) + { debug.log( "promoted", &format!( @@ -304,7 +310,10 @@ impl<'a> ScopeManager for Pattern2ScopeManager<'a> { #[cfg(not(feature = "normalized_dev"))] debug.log( "fallback", - &format!("BindingId({}) miss, falling back to name '{}' lookup", bid.0, name), + &format!( + "BindingId({}) miss, falling back to name '{}' lookup", + bid.0, name + ), ); } @@ -331,7 +340,7 @@ mod tests { carriers: vec![], trim_helper: None, promoted_loopbodylocals: vec![], -#[cfg(feature = "normalized_dev")] + #[cfg(feature = "normalized_dev")] promoted_bindings: std::collections::BTreeMap::new(), }; @@ -429,7 +438,7 @@ mod tests { carriers: vec![], trim_helper: None, promoted_loopbodylocals: vec![], -#[cfg(feature = "normalized_dev")] + #[cfg(feature = "normalized_dev")] promoted_bindings: std::collections::BTreeMap::new(), }; @@ -464,7 +473,7 @@ mod tests { carriers: vec![], trim_helper: None, promoted_loopbodylocals: vec![], -#[cfg(feature = "normalized_dev")] + #[cfg(feature = "normalized_dev")] promoted_bindings: std::collections::BTreeMap::new(), }; diff --git a/src/mir/join_ir/lowering/scope_manager_bindingid_poc/mod.rs b/src/mir/join_ir/lowering/scope_manager_bindingid_poc/mod.rs index 25f42090..0072c036 100644 --- a/src/mir/join_ir/lowering/scope_manager_bindingid_poc/mod.rs +++ b/src/mir/join_ir/lowering/scope_manager_bindingid_poc/mod.rs @@ -29,8 +29,8 @@ pub struct ConditionEnvV2 { name_to_join: BTreeMap, // Phase 73+: NEW - BindingId-based tracking - binding_to_join: BTreeMap, // BindingId → JoinIR ValueId - name_to_binding: BTreeMap, // Name → current BindingId (shadowing) + binding_to_join: BTreeMap, // BindingId → JoinIR ValueId + name_to_binding: BTreeMap, // Name → current BindingId (shadowing) } impl ConditionEnvV2 { @@ -93,7 +93,7 @@ pub struct CarrierVarV2 { pub join_id: Option, // Phase 73+: NEW - BindingId tracking - pub host_binding: Option, // HOST function's BindingId + pub host_binding: Option, // HOST function's BindingId } /// Phase 73 PoC: CarrierInfo with BindingId-based promotion @@ -104,7 +104,7 @@ pub struct CarrierInfoV2 { pub carriers: Vec, // Phase 73+: Replace string list with BindingId map - pub promoted_bindings: BTreeMap, // Original → Promoted + pub promoted_bindings: BTreeMap, // Original → Promoted } impl CarrierInfoV2 { @@ -225,7 +225,10 @@ mod tests { let promoted = BindingId(10); carrier_info.add_promoted_binding(original, promoted); - assert_eq!(carrier_info.resolve_promoted_binding(original), Some(promoted)); + assert_eq!( + carrier_info.resolve_promoted_binding(original), + Some(promoted) + ); assert_eq!(carrier_info.resolve_promoted_binding(BindingId(99)), None); } @@ -308,7 +311,7 @@ mod tests { env.insert_by_binding("new_var".to_string(), binding, ValueId(888)); // Unified lookup should find both - assert_eq!(env.lookup("legacy_var"), Some(ValueId(999))); // Fallback to name - assert_eq!(env.lookup("new_var"), Some(ValueId(888))); // BindingId first + assert_eq!(env.lookup("legacy_var"), Some(ValueId(999))); // Fallback to name + assert_eq!(env.lookup("new_var"), Some(ValueId(888))); // BindingId first } } diff --git a/src/mir/join_ir/lowering/simple_while_minimal.rs b/src/mir/join_ir/lowering/simple_while_minimal.rs index d25ac8a2..8165f33e 100644 --- a/src/mir/join_ir/lowering/simple_while_minimal.rs +++ b/src/mir/join_ir/lowering/simple_while_minimal.rs @@ -193,7 +193,9 @@ pub(crate) fn lower_simple_while_minimal( // Phase 188-Impl-1-E: Use Print instruction loop_step_func .body - .push(JoinInst::Compute(MirLikeInst::Print { value: i_step_param })); + .push(JoinInst::Compute(MirLikeInst::Print { + value: i_step_param, + })); // i_next = i + 1 // Step 1: const 1 diff --git a/src/mir/join_ir/lowering/step_schedule.rs b/src/mir/join_ir/lowering/step_schedule.rs index a675f1cb..d59be342 100644 --- a/src/mir/join_ir/lowering/step_schedule.rs +++ b/src/mir/join_ir/lowering/step_schedule.rs @@ -17,16 +17,16 @@ use crate::mir::join_ir::lowering::loop_body_local_env::LoopBodyLocalEnv; #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub(crate) enum Pattern2StepKind { // P2 (Pattern2 Break) steps - HeaderCond, // loop(cond) - BodyInit, // local ch = ... - BreakCheck, // if (cond) break - Updates, // sum = sum + 1 - Tail, // i = i + 1 + HeaderCond, // loop(cond) + BodyInit, // local ch = ... + BreakCheck, // if (cond) break + Updates, // sum = sum + 1 + Tail, // i = i + 1 // Phase 47-A: P3 (Pattern3 If-Sum) steps - IfCond, // if (cond) in body - ThenUpdates, // carrier updates in then branch - ElseUpdates, // carrier updates in else branch (if any) + IfCond, // if (cond) in body + ThenUpdates, // carrier updates in then branch + ElseUpdates, // carrier updates in else branch (if any) // Phase 48-A: P4 (Pattern4 Continue) steps ContinueCheck, // if (cond) continue @@ -158,11 +158,11 @@ fn log_schedule(ctx: &Pattern2ScheduleContext, schedule: &Pattern2StepSchedule) #[allow(dead_code)] pub(crate) fn pattern3_if_sum_schedule() -> Vec { vec![ - Pattern2StepKind::HeaderCond, // loop(i < n) - Pattern2StepKind::IfCond, // if (i > 0) - Pattern2StepKind::ThenUpdates, // sum = sum + i + Pattern2StepKind::HeaderCond, // loop(i < n) + Pattern2StepKind::IfCond, // if (i > 0) + Pattern2StepKind::ThenUpdates, // sum = sum + i // ElseUpdates omitted for minimal (no else branch) - Pattern2StepKind::Tail, // i = i + 1 + Pattern2StepKind::Tail, // i = i + 1 ] } @@ -189,12 +189,7 @@ mod tests { } else { CarrierInit::FromHost }; - CarrierVar::with_role_and_init( - "c".to_string(), - ValueId(1), - CarrierRole::LoopState, - init, - ) + CarrierVar::with_role_and_init("c".to_string(), ValueId(1), CarrierRole::LoopState, init) } fn carrier_info(carriers: Vec) -> CarrierInfo { @@ -204,7 +199,7 @@ mod tests { carriers, trim_helper: None, promoted_loopbodylocals: vec![], -#[cfg(feature = "normalized_dev")] + #[cfg(feature = "normalized_dev")] promoted_bindings: std::collections::BTreeMap::new(), } } @@ -249,8 +244,7 @@ mod tests { #[test] fn loop_local_carrier_triggers_body_first() { - let ctx = - Pattern2ScheduleContext::from_env(None, &carrier_info(vec![carrier(true)])); + let ctx = Pattern2ScheduleContext::from_env(None, &carrier_info(vec![carrier(true)])); let schedule = build_pattern2_schedule(&ctx); assert_eq!( schedule.steps(), diff --git a/src/mir/join_ir/normalized.rs b/src/mir/join_ir/normalized.rs index 7cd0f544..8e4b1240 100644 --- a/src/mir/join_ir/normalized.rs +++ b/src/mir/join_ir/normalized.rs @@ -15,13 +15,13 @@ use std::collections::HashMap; #[cfg(feature = "normalized_dev")] use std::panic::{catch_unwind, AssertUnwindSafe}; -#[cfg(feature = "normalized_dev")] -pub mod fixtures; #[cfg(feature = "normalized_dev")] pub mod dev_env; #[cfg(feature = "normalized_dev")] pub mod dev_fixtures; #[cfg(feature = "normalized_dev")] +pub mod fixtures; +#[cfg(feature = "normalized_dev")] pub mod loop_step_inspector; #[cfg(feature = "normalized_dev")] pub mod shape_guard; @@ -97,7 +97,10 @@ pub enum JpOp { BinOp(BinOpKind), Unary(UnaryOp), Compare(CompareOp), - BoxCall { box_name: String, method: String }, + BoxCall { + box_name: String, + method: String, + }, /// 三項演算子(cond ? then : else) Select, } @@ -462,13 +465,11 @@ pub fn normalize_pattern2_minimal(structured: &JoinModule) -> NormalizedModule { cond, then_val, else_val, - }) => { - body.push(JpInst::Let { - dst: *dst, - op: JpOp::Select, - args: vec![*cond, *then_val, *else_val], - }) - } + }) => body.push(JpInst::Let { + dst: *dst, + op: JpOp::Select, + args: vec![*cond, *then_val, *else_val], + }), JoinInst::Jump { cont, args, cond } => { if let Some(cond_val) = cond { body.push(JpInst::If { @@ -497,7 +498,9 @@ pub fn normalize_pattern2_minimal(structured: &JoinModule) -> NormalizedModule { args: vec![*cond, *then_val, *else_val], }); } - JoinInst::Call { func, args, k_next, .. } => { + JoinInst::Call { + func, args, k_next, .. + } => { if k_next.is_none() { body.push(JpInst::TailCallFn { target: JpFuncId(func.0), @@ -620,9 +623,7 @@ pub fn normalize_pattern3_if_sum_json_minimal( /// Phase 50: selfhost if-sum P3 を Normalized に載せる(dev-only)。 #[cfg(feature = "normalized_dev")] -pub fn normalize_selfhost_if_sum_p3( - structured: &JoinModule, -) -> Result { +pub fn normalize_selfhost_if_sum_p3(structured: &JoinModule) -> Result { normalize_pattern3_if_sum_shape(structured, NormalizedDevShape::SelfhostIfSumP3) } @@ -769,14 +770,12 @@ pub fn normalized_pattern2_to_structured(norm: &NormalizedModule) -> JoinModule op: *op, operand: args.get(0).copied().unwrap_or(ValueId(0)), })), - JpOp::Select => func - .body - .push(JoinInst::Compute(MirLikeInst::Select { - dst: *dst, - cond: args.get(0).copied().unwrap_or(ValueId(0)), - then_val: args.get(1).copied().unwrap_or(ValueId(0)), - else_val: args.get(2).copied().unwrap_or(ValueId(0)), - })), + JpOp::Select => func.body.push(JoinInst::Compute(MirLikeInst::Select { + dst: *dst, + cond: args.get(0).copied().unwrap_or(ValueId(0)), + then_val: args.get(1).copied().unwrap_or(ValueId(0)), + else_val: args.get(2).copied().unwrap_or(ValueId(0)), + })), JpOp::Compare(op) => func.body.push(JoinInst::Compute(MirLikeInst::Compare { dst: *dst, op: *op, @@ -832,9 +831,7 @@ fn verify_normalized_pattern2( max_env_fields: usize, ) -> Result<(), String> { if module.phase != JoinIrPhase::Normalized { - return Err( - "[joinir/normalized-dev] pattern2: phase must be Normalized".to_string(), - ); + return Err("[joinir/normalized-dev] pattern2: phase must be Normalized".to_string()); } let mut layout_sizes: HashMap = HashMap::new(); @@ -871,10 +868,8 @@ fn verify_normalized_pattern2( | JpInst::If { env, .. } => { if let Some(expected) = expected_env_len { if env.is_empty() { - return Err( - "[joinir/normalized-dev] pattern2: env must not be empty" - .to_string(), - ); + return Err("[joinir/normalized-dev] pattern2: env must not be empty" + .to_string()); } let _ = expected; } @@ -885,9 +880,7 @@ fn verify_normalized_pattern2( if let Some(last) = func.body.last() { match last { - JpInst::TailCallFn { .. } - | JpInst::TailCallKont { .. } - | JpInst::If { .. } => {} + JpInst::TailCallFn { .. } | JpInst::TailCallKont { .. } | JpInst::If { .. } => {} _ => { return Err(format!( "[joinir/normalized-dev] pattern2: function '{}' does not end with tail call/if", @@ -1069,7 +1062,9 @@ pub(crate) fn normalized_dev_roundtrip_structured( let shapes = shape_guard::supported_shapes(module); if shapes.is_empty() { - return Err("[joinir/normalized-dev] module shape is not supported by normalized_dev".into()); + return Err( + "[joinir/normalized-dev] module shape is not supported by normalized_dev".into(), + ); } let debug = dev_env::normalized_dev_logs_enabled() && crate::config::env::joinir_dev_enabled(); @@ -1092,15 +1087,15 @@ pub(crate) fn normalized_dev_roundtrip_structured( | NormalizedDevShape::JsonparserSkipWsReal | NormalizedDevShape::JsonparserAtoiMini | NormalizedDevShape::JsonparserAtoiReal - | NormalizedDevShape::JsonparserParseNumberReal => catch_unwind(AssertUnwindSafe( - || { + | NormalizedDevShape::JsonparserParseNumberReal => { + catch_unwind(AssertUnwindSafe(|| { let norm = normalize_pattern2_minimal(module); normalized_pattern2_to_structured(&norm) - }, - )), + })) + } NormalizedDevShape::SelfhostTokenScanP2 => catch_unwind(AssertUnwindSafe(|| { - let norm = - normalize_selfhost_token_scan_p2(module).expect("selfhost P2 normalization failed"); + let norm = normalize_selfhost_token_scan_p2(module) + .expect("selfhost P2 normalization failed"); normalized_pattern2_to_structured(&norm) })), NormalizedDevShape::SelfhostTokenScanP2Accum => catch_unwind(AssertUnwindSafe(|| { @@ -1110,8 +1105,8 @@ pub(crate) fn normalized_dev_roundtrip_structured( })), // Phase 47-A: P3 minimal (delegates to P2 for now, but uses proper guard) NormalizedDevShape::Pattern3IfSumMinimal => catch_unwind(AssertUnwindSafe(|| { - let norm = normalize_pattern3_if_sum_minimal(module) - .expect("P3 normalization failed"); + let norm = + normalize_pattern3_if_sum_minimal(module).expect("P3 normalization failed"); normalized_pattern2_to_structured(&norm) })), NormalizedDevShape::Pattern3IfSumMulti => catch_unwind(AssertUnwindSafe(|| { @@ -1125,8 +1120,8 @@ pub(crate) fn normalized_dev_roundtrip_structured( normalized_pattern2_to_structured(&norm) })), NormalizedDevShape::SelfhostIfSumP3 => catch_unwind(AssertUnwindSafe(|| { - let norm = normalize_selfhost_if_sum_p3(module) - .expect("selfhost P3 normalization failed"); + let norm = + normalize_selfhost_if_sum_p3(module).expect("selfhost P3 normalization failed"); normalized_pattern2_to_structured(&norm) })), NormalizedDevShape::SelfhostIfSumP3Ext => catch_unwind(AssertUnwindSafe(|| { @@ -1156,36 +1151,38 @@ pub(crate) fn normalized_dev_roundtrip_structured( })), // Phase 48-A: P4 minimal (delegates to P2 for now, but uses proper guard) NormalizedDevShape::Pattern4ContinueMinimal => catch_unwind(AssertUnwindSafe(|| { - let norm = normalize_pattern4_continue_minimal(module) - .expect("P4 normalization failed"); + let norm = + normalize_pattern4_continue_minimal(module).expect("P4 normalization failed"); normalized_pattern2_to_structured(&norm) })), NormalizedDevShape::JsonparserParseArrayContinueSkipWs => { catch_unwind(AssertUnwindSafe(|| { - let norm = - normalize_jsonparser_parse_array_continue_skip_ws(module) - .expect("P4 array normalization failed"); + let norm = normalize_jsonparser_parse_array_continue_skip_ws(module) + .expect("P4 array normalization failed"); normalized_pattern2_to_structured(&norm) })) } NormalizedDevShape::JsonparserParseObjectContinueSkipWs => { catch_unwind(AssertUnwindSafe(|| { - let norm = - normalize_jsonparser_parse_object_continue_skip_ws(module) - .expect("P4 object normalization failed"); + let norm = normalize_jsonparser_parse_object_continue_skip_ws(module) + .expect("P4 object normalization failed"); normalized_pattern2_to_structured(&norm) })) } // Phase 89: Continue + Early Return pattern (dev-only, delegates to P2 for now) - NormalizedDevShape::PatternContinueReturnMinimal => catch_unwind(AssertUnwindSafe(|| { - let norm = normalize_pattern2_minimal(module); - normalized_pattern2_to_structured(&norm) - })), + NormalizedDevShape::PatternContinueReturnMinimal => { + catch_unwind(AssertUnwindSafe(|| { + let norm = normalize_pattern2_minimal(module); + normalized_pattern2_to_structured(&norm) + })) + } // Phase 90: Parse String Composite pattern (dev-only, delegates to P2 for now) - NormalizedDevShape::ParseStringCompositeMinimal => catch_unwind(AssertUnwindSafe(|| { - let norm = normalize_pattern2_minimal(module); - normalized_pattern2_to_structured(&norm) - })), + NormalizedDevShape::ParseStringCompositeMinimal => { + catch_unwind(AssertUnwindSafe(|| { + let norm = normalize_pattern2_minimal(module); + normalized_pattern2_to_structured(&norm) + })) + } }; match attempt { diff --git a/src/mir/join_ir/normalized/dev_fixtures.rs b/src/mir/join_ir/normalized/dev_fixtures.rs index ae368fb3..39320fd2 100644 --- a/src/mir/join_ir/normalized/dev_fixtures.rs +++ b/src/mir/join_ir/normalized/dev_fixtures.rs @@ -132,8 +132,8 @@ impl NormalizedDevFixture { use super::super::frontend::ast_lowerer::AstToJoinIrLowerer; let fixture_json = self.fixture_content(); - let program_json: serde_json::Value = serde_json::from_str(fixture_json) - .unwrap_or_else(|e| { + let program_json: serde_json::Value = + serde_json::from_str(fixture_json).unwrap_or_else(|e| { panic!( "{} fixture should be valid JSON: {}", self.function_name(), @@ -165,11 +165,12 @@ mod tests { #[test] fn test_all_fixtures_have_unique_names() { use std::collections::HashSet; - let names: HashSet<_> = ALL_DEV_FIXTURES - .iter() - .map(|f| f.function_name()) - .collect(); - assert_eq!(names.len(), ALL_DEV_FIXTURES.len(), "Fixture names must be unique"); + let names: HashSet<_> = ALL_DEV_FIXTURES.iter().map(|f| f.function_name()).collect(); + assert_eq!( + names.len(), + ALL_DEV_FIXTURES.len(), + "Fixture names must be unique" + ); } #[test] diff --git a/src/mir/join_ir/normalized/fixtures.rs b/src/mir/join_ir/normalized/fixtures.rs index f086374f..baea86d9 100644 --- a/src/mir/join_ir/normalized/fixtures.rs +++ b/src/mir/join_ir/normalized/fixtures.rs @@ -24,7 +24,12 @@ fn const_i64(func: &mut JoinFunction, dst: ValueId, value: i64) { } fn compare(func: &mut JoinFunction, dst: ValueId, op: CompareOp, lhs: ValueId, rhs: ValueId) { - func.body.push(JoinInst::Compute(MirLikeInst::Compare { dst, op, lhs, rhs })); + func.body.push(JoinInst::Compute(MirLikeInst::Compare { + dst, + op, + lhs, + rhs, + })); } fn unary_not(func: &mut JoinFunction, dst: ValueId, operand: ValueId) { @@ -44,7 +49,13 @@ fn bin_add(func: &mut JoinFunction, dst: ValueId, lhs: ValueId, rhs: ValueId) { })); } -fn select(func: &mut JoinFunction, dst: ValueId, cond: ValueId, then_val: ValueId, else_val: ValueId) { +fn select( + func: &mut JoinFunction, + dst: ValueId, + cond: ValueId, + then_val: ValueId, + else_val: ValueId, +) { func.body.push(JoinInst::Compute(MirLikeInst::Select { dst, cond, @@ -165,8 +176,8 @@ pub fn build_jsonparser_skip_ws_real_structured_for_normalized_dev() -> JoinModu "../../../../docs/private/roadmap2/phases/normalized_dev/fixtures/jsonparser_skip_ws_real.program.json" ); - let program_json: serde_json::Value = - serde_json::from_str(FIXTURE).expect("jsonparser skip_ws real fixture should be valid JSON"); + let program_json: serde_json::Value = serde_json::from_str(FIXTURE) + .expect("jsonparser skip_ws real fixture should be valid JSON"); let mut lowerer = AstToJoinIrLowerer::new(); let module = lowerer.lower_program_json(&program_json); @@ -189,8 +200,8 @@ pub fn build_jsonparser_parse_number_real_structured_for_normalized_dev() -> Joi "../../../../docs/private/roadmap2/phases/normalized_dev/fixtures/jsonparser_parse_number_real.program.json" ); - let program_json: serde_json::Value = - serde_json::from_str(FIXTURE).expect("jsonparser parse_number real fixture should be valid JSON"); + let program_json: serde_json::Value = serde_json::from_str(FIXTURE) + .expect("jsonparser parse_number real fixture should be valid JSON"); let mut lowerer = AstToJoinIrLowerer::new(); let module = lowerer.lower_program_json(&program_json); @@ -319,13 +330,7 @@ pub fn build_pattern3_if_sum_multi_min_structured_for_normalized_dev() -> JoinMo let cond_cmp = alloc(); let zero_const = alloc(); const_i64(&mut loop_step, zero_const, 0); - compare( - &mut loop_step, - cond_cmp, - CompareOp::Gt, - i_param, - zero_const, - ); + compare(&mut loop_step, cond_cmp, CompareOp::Gt, i_param, zero_const); // then: sum = sum + 1, count = count + 1 let one_const = alloc(); @@ -415,18 +420,17 @@ pub fn build_pattern3_json_if_sum_min_structured_for_normalized_dev() -> JoinMod // loop_step params: i, sum let i_param = alloc(); let sum_param = alloc(); - let mut loop_step = JoinFunction::new(loop_id, "loop_step".to_string(), vec![i_param, sum_param]); + let mut loop_step = + JoinFunction::new(loop_id, "loop_step".to_string(), vec![i_param, sum_param]); // loop condition: i < 5 let limit_const = alloc(); let cmp_loop = alloc(); let exit_cond = alloc(); - loop_step - .body - .push(JoinInst::Compute(MirLikeInst::Const { - dst: limit_const, - value: ConstValue::Integer(5), - })); + loop_step.body.push(JoinInst::Compute(MirLikeInst::Const { + dst: limit_const, + value: ConstValue::Integer(5), + })); compare( &mut loop_step, cmp_loop, @@ -445,13 +449,7 @@ pub fn build_pattern3_json_if_sum_min_structured_for_normalized_dev() -> JoinMod let cond_cmp = alloc(); let zero_const = alloc(); const_i64(&mut loop_step, zero_const, 0); - compare( - &mut loop_step, - cond_cmp, - CompareOp::Gt, - i_param, - zero_const, - ); + compare(&mut loop_step, cond_cmp, CompareOp::Gt, i_param, zero_const); // then: sum = sum + i let sum_then = alloc(); @@ -524,8 +522,8 @@ pub fn build_selfhost_if_sum_p3_ext_structured_for_normalized_dev() -> JoinModul "../../../../docs/private/roadmap2/phases/normalized_dev/fixtures/selfhost_if_sum_p3_ext.program.json" ); - let program_json: serde_json::Value = serde_json::from_str(FIXTURE) - .expect("selfhost if_sum P3 ext fixture should be valid JSON"); + let program_json: serde_json::Value = + serde_json::from_str(FIXTURE).expect("selfhost if_sum P3 ext fixture should be valid JSON"); let mut lowerer = AstToJoinIrLowerer::new(); let module = lowerer.lower_program_json(&program_json); @@ -548,8 +546,8 @@ pub fn build_selfhost_args_parse_p2_structured_for_normalized_dev() -> JoinModul "../../../../docs/private/roadmap2/phases/normalized_dev/fixtures/selfhost_args_parse_p2.program.json" ); - let program_json: serde_json::Value = serde_json::from_str(FIXTURE) - .expect("selfhost args_parse P2 fixture should be valid JSON"); + let program_json: serde_json::Value = + serde_json::from_str(FIXTURE).expect("selfhost args_parse P2 fixture should be valid JSON"); let mut lowerer = AstToJoinIrLowerer::new(); let module = lowerer.lower_program_json(&program_json); @@ -572,8 +570,8 @@ pub fn build_selfhost_stmt_count_p3_structured_for_normalized_dev() -> JoinModul "../../../../docs/private/roadmap2/phases/normalized_dev/fixtures/selfhost_stmt_count_p3.program.json" ); - let program_json: serde_json::Value = serde_json::from_str(FIXTURE) - .expect("selfhost stmt_count P3 fixture should be valid JSON"); + let program_json: serde_json::Value = + serde_json::from_str(FIXTURE).expect("selfhost stmt_count P3 fixture should be valid JSON"); let mut lowerer = AstToJoinIrLowerer::new(); let module = lowerer.lower_program_json(&program_json); @@ -604,7 +602,7 @@ pub fn build_jsonparser_atoi_structured_for_normalized_dev() -> JoinModule { if joinir_dev_enabled() && joinir_test_debug_enabled() { eprintln!( - "[joinir/normalized-dev] jsonparser_atoi_mini structured module: {:#?}", + "[joinir/normalized-dev] jsonparser_atoi_mini structured module: {:#?}", module ); } @@ -679,18 +677,9 @@ pub fn build_pattern3_if_sum_min_structured_for_normalized_dev() -> JoinModule { let loop_condition = bin(BinaryOperator::Less, var("i"), int_lit(3)); let if_condition = bin(BinaryOperator::Greater, var("i"), int_lit(0)); - let then_update = assignment( - var("sum"), - bin(BinaryOperator::Add, var("sum"), int_lit(1)), - ); - let else_update = assignment( - var("sum"), - bin(BinaryOperator::Add, var("sum"), int_lit(0)), - ); - let counter_update = assignment( - var("i"), - bin(BinaryOperator::Add, var("i"), int_lit(1)), - ); + let then_update = assignment(var("sum"), bin(BinaryOperator::Add, var("sum"), int_lit(1))); + let else_update = assignment(var("sum"), bin(BinaryOperator::Add, var("sum"), int_lit(0))); + let counter_update = assignment(var("i"), bin(BinaryOperator::Add, var("i"), int_lit(1))); let if_stmt = ASTNode::If { condition: Box::new(if_condition), @@ -707,9 +696,14 @@ pub fn build_pattern3_if_sum_min_structured_for_normalized_dev() -> JoinModule { let i_id = join_value_space.alloc_param(); cond_env.insert("i".to_string(), i_id); - let (module, _meta) = - lower_if_sum_pattern(&loop_condition, &if_stmt, &body, &cond_env, &mut join_value_space) - .expect("if-sum lowering should succeed for minimal pattern3"); + let (module, _meta) = lower_if_sum_pattern( + &loop_condition, + &if_stmt, + &body, + &cond_env, + &mut join_value_space, + ) + .expect("if-sum lowering should succeed for minimal pattern3"); if joinir_dev_enabled() && joinir_test_debug_enabled() { eprintln!( @@ -743,7 +737,8 @@ pub fn build_jsonparser_parse_array_continue_skip_ws_structured_for_normalized_d /// JsonParser _parse_object の whitespace continue ループを Structured で組み立てるヘルパー(dev-only)。 /// /// Fixture: docs/private/roadmap2/phases/normalized_dev/fixtures/jsonparser_parse_object_continue_skip_ws.program.json -pub fn build_jsonparser_parse_object_continue_skip_ws_structured_for_normalized_dev() -> JoinModule { +pub fn build_jsonparser_parse_object_continue_skip_ws_structured_for_normalized_dev() -> JoinModule +{ use super::dev_fixtures::NormalizedDevFixture; NormalizedDevFixture::Pattern4JsonParserParseObjectContinueSkipWs.load_and_lower() } @@ -818,15 +813,15 @@ pub mod prelude { build_jsonparser_skip_ws_real_structured_for_normalized_dev, build_jsonparser_skip_ws_structured_for_normalized_dev, build_jsonparser_unescape_string_step2_min_structured_for_normalized_dev, + build_parse_array_min_structured_for_normalized_dev, + build_parse_object_min_structured_for_normalized_dev, + build_parse_string_composite_min_structured_for_normalized_dev, build_pattern2_break_fixture_structured, build_pattern2_minimal_structured, build_pattern3_if_sum_min_structured_for_normalized_dev, build_pattern3_if_sum_multi_min_structured_for_normalized_dev, build_pattern3_json_if_sum_min_structured_for_normalized_dev, build_pattern4_continue_min_structured_for_normalized_dev, build_pattern_continue_return_min_structured_for_normalized_dev, - build_parse_string_composite_min_structured_for_normalized_dev, - build_parse_array_min_structured_for_normalized_dev, - build_parse_object_min_structured_for_normalized_dev, build_selfhost_if_sum_p3_ext_structured_for_normalized_dev, build_selfhost_if_sum_p3_structured_for_normalized_dev, build_selfhost_token_scan_p2_accum_structured_for_normalized_dev, diff --git a/src/mir/join_ir/normalized/loop_step_inspector.rs b/src/mir/join_ir/normalized/loop_step_inspector.rs index 4ef8edbd..acf20a78 100644 --- a/src/mir/join_ir/normalized/loop_step_inspector.rs +++ b/src/mir/join_ir/normalized/loop_step_inspector.rs @@ -29,12 +29,10 @@ impl LoopStepInspector { /// /// ループ条件や continue/break 判定で使用される。 pub fn has_compare_instruction(loop_step_func: &JoinFunction) -> bool { - loop_step_func.body.iter().any(|inst| { - matches!( - inst, - JoinInst::Compute(MirLikeInst::Compare { .. }) - ) - }) + loop_step_func + .body + .iter() + .any(|inst| matches!(inst, JoinInst::Compute(MirLikeInst::Compare { .. }))) } /// 条件付き Jump の個数をカウント @@ -77,10 +75,7 @@ mod tests { use super::*; use crate::mir::join_ir::{JoinFuncId, VarId}; - fn make_dummy_loop_step( - body: Vec, - param_count: usize, - ) -> JoinFunction { + fn make_dummy_loop_step(body: Vec, param_count: usize) -> JoinFunction { let params: Vec<_> = (0..param_count).map(|i| VarId(i as u32)).collect(); JoinFunction { id: JoinFuncId(1), @@ -105,7 +100,9 @@ mod tests { assert!(LoopStepInspector::has_select_instruction(&func_with_select)); let func_without_select = make_dummy_loop_step(vec![], 2); - assert!(!LoopStepInspector::has_select_instruction(&func_without_select)); + assert!(!LoopStepInspector::has_select_instruction( + &func_without_select + )); } #[test] @@ -124,7 +121,7 @@ mod tests { }, JoinInst::Jump { target: JoinFuncId(2), - cond: None, // 無条件は含まれない + cond: None, // 無条件は含まれない args: vec![], }, ], @@ -139,7 +136,7 @@ mod tests { vec![JoinInst::Call { target: JoinFuncId(1), args: vec![], - k_next: None, // tail call + k_next: None, // tail call results: vec![], }], 2, @@ -150,7 +147,7 @@ mod tests { vec![JoinInst::Call { target: JoinFuncId(1), args: vec![], - k_next: Some(JoinFuncId(3)), // not tail call + k_next: Some(JoinFuncId(3)), // not tail call results: vec![], }], 2, @@ -160,10 +157,20 @@ mod tests { #[test] fn test_has_reasonable_param_count() { - assert!(!LoopStepInspector::has_reasonable_param_count(&make_dummy_loop_step(vec![], 1))); - assert!(LoopStepInspector::has_reasonable_param_count(&make_dummy_loop_step(vec![], 2))); - assert!(LoopStepInspector::has_reasonable_param_count(&make_dummy_loop_step(vec![], 3))); - assert!(LoopStepInspector::has_reasonable_param_count(&make_dummy_loop_step(vec![], 4))); - assert!(!LoopStepInspector::has_reasonable_param_count(&make_dummy_loop_step(vec![], 5))); + assert!(!LoopStepInspector::has_reasonable_param_count( + &make_dummy_loop_step(vec![], 1) + )); + assert!(LoopStepInspector::has_reasonable_param_count( + &make_dummy_loop_step(vec![], 2) + )); + assert!(LoopStepInspector::has_reasonable_param_count( + &make_dummy_loop_step(vec![], 3) + )); + assert!(LoopStepInspector::has_reasonable_param_count( + &make_dummy_loop_step(vec![], 4) + )); + assert!(!LoopStepInspector::has_reasonable_param_count( + &make_dummy_loop_step(vec![], 5) + )); } } diff --git a/src/mir/join_ir/normalized/shape_guard.rs b/src/mir/join_ir/normalized/shape_guard.rs index bcef6d27..1ae70886 100644 --- a/src/mir/join_ir/normalized/shape_guard.rs +++ b/src/mir/join_ir/normalized/shape_guard.rs @@ -37,7 +37,6 @@ pub enum ShapeCapabilityKind { /// Selfhost P3 if-sum family SelfhostP3IfSum, - // Future: Other P2 patterns // P2MidAtOfLoop, // P2HeavyString, @@ -100,8 +99,14 @@ pub enum NormalizedDevShape { type Detector = fn(&JoinModule) -> bool; const SHAPE_DETECTORS: &[(NormalizedDevShape, Detector)] = &[ - (NormalizedDevShape::Pattern1Mini, detectors::is_pattern1_mini), - (NormalizedDevShape::Pattern2Mini, detectors::is_pattern2_mini), + ( + NormalizedDevShape::Pattern1Mini, + detectors::is_pattern1_mini, + ), + ( + NormalizedDevShape::Pattern2Mini, + detectors::is_pattern2_mini, + ), ( NormalizedDevShape::JsonparserSkipWsMini, detectors::is_jsonparser_skip_ws_mini, @@ -552,18 +557,16 @@ mod detectors { let has_select = loop_func.body.iter().any(|inst| match inst { JoinInst::Select { .. } => true, - JoinInst::Compute(mir_inst) => matches!( - mir_inst, - crate::mir::join_ir::MirLikeInst::Select { .. } - ), + JoinInst::Compute(mir_inst) => { + matches!(mir_inst, crate::mir::join_ir::MirLikeInst::Select { .. }) + } _ => false, }); let has_boxcall = loop_func.body.iter().any(|inst| match inst { - JoinInst::Compute(mir_inst) => matches!( - mir_inst, - crate::mir::join_ir::MirLikeInst::BoxCall { .. } - ), + JoinInst::Compute(mir_inst) => { + matches!(mir_inst, crate::mir::join_ir::MirLikeInst::BoxCall { .. }) + } _ => false, }); @@ -601,8 +604,7 @@ mod detectors { .iter() .any(|inst| matches!(inst, JoinInst::Call { k_next: None, .. })); - let param_set: std::collections::BTreeSet<_> = - loop_step.params.iter().copied().collect(); + let param_set: std::collections::BTreeSet<_> = loop_step.params.iter().copied().collect(); let has_ge_compare_between_params = loop_step.body.iter().any(|inst| match inst { JoinInst::Compute(mir_inst) => match mir_inst { @@ -617,10 +619,9 @@ mod detectors { }); let has_boxcall = loop_step.body.iter().any(|inst| match inst { - JoinInst::Compute(mir_inst) => matches!( - mir_inst, - crate::mir::join_ir::MirLikeInst::BoxCall { .. } - ), + JoinInst::Compute(mir_inst) => { + matches!(mir_inst, crate::mir::join_ir::MirLikeInst::BoxCall { .. }) + } _ => false, }); @@ -667,10 +668,9 @@ mod detectors { // Phase 220: Select can be either JoinInst::Select or Compute(MirLikeInst::Select) let has_select = loop_step.body.iter().any(|inst| match inst { JoinInst::Select { .. } => true, - JoinInst::Compute(mir_inst) => matches!( - mir_inst, - crate::mir::join_ir::MirLikeInst::Select { .. } - ), + JoinInst::Compute(mir_inst) => { + matches!(mir_inst, crate::mir::join_ir::MirLikeInst::Select { .. }) + } _ => false, }); @@ -896,7 +896,7 @@ mod detectors { && has_select && has_tail_call && reasonable_param_count - && k_exit_jumps_count == 1 // Exactly one loop break (not early return) + && k_exit_jumps_count == 1 // Exactly one loop break (not early return) } pub(crate) fn is_jsonparser_parse_array_continue_skip_ws(module: &JoinModule) -> bool { @@ -952,7 +952,7 @@ mod detectors { && has_select && has_tail_call && reasonable_param_count - && k_exit_jumps_count >= 2 // At least 2: loop break + early return + && k_exit_jumps_count >= 2 // At least 2: loop break + early return } /// Phase 90: Check if module matches Parse String Composite pattern @@ -993,8 +993,12 @@ mod detectors { // Check if rhs is a const value 2 (indicating i+=2 for escape) // We need to check if rhs points to a Const instruction with value 2 loop_step.body.iter().any(|other_inst| match other_inst { - JoinInst::Compute(crate::mir::join_ir::MirLikeInst::Const { dst, value }) => { - dst == rhs && matches!(value, crate::mir::join_ir::ConstValue::Integer(2)) + JoinInst::Compute(crate::mir::join_ir::MirLikeInst::Const { + dst, + value, + }) => { + dst == rhs + && matches!(value, crate::mir::join_ir::ConstValue::Integer(2)) } _ => false, }) @@ -1171,7 +1175,9 @@ mod tests { shapes ); assert!( - !shapes.iter().any(|s| matches!(s, NormalizedDevShape::Pattern3IfSumMinimal)), + !shapes + .iter() + .any(|s| matches!(s, NormalizedDevShape::Pattern3IfSumMinimal)), "selfhost_if_sum_p3 should not rely on canonical P3 minimal detection: {:?}", shapes ); @@ -1286,7 +1292,9 @@ mod tests { k_next: None, dst: Some(ValueId(2)), }, - JoinInst::Ret { value: Some(ValueId(2)) }, + JoinInst::Ret { + value: Some(ValueId(2)), + }, ], exit_cont: None, }; @@ -1348,7 +1356,9 @@ mod tests { k_next: None, dst: Some(ValueId(40)), }, - JoinInst::Ret { value: Some(ValueId(40)) }, + JoinInst::Ret { + value: Some(ValueId(40)), + }, ], exit_cont: None, }; @@ -1358,7 +1368,9 @@ mod tests { id: JoinFuncId::new(2), name: "k_exit".to_string(), params: vec![ValueId(0)], - body: vec![JoinInst::Ret { value: Some(ValueId(0)) }], + body: vec![JoinInst::Ret { + value: Some(ValueId(0)), + }], exit_cont: None, }; diff --git a/src/mir/join_ir/ownership/analyzer.rs b/src/mir/join_ir/ownership/analyzer.rs index 24dacde4..4b39d9a4 100644 --- a/src/mir/join_ir/ownership/analyzer.rs +++ b/src/mir/join_ir/ownership/analyzer.rs @@ -77,7 +77,9 @@ impl OwnershipAnalyzer { return Err("OwnershipAnalyzer: no FunctionDef found in 'defs'".to_string()); } } else { - return Err("OwnershipAnalyzer: expected top-level 'functions' or 'defs' array".to_string()); + return Err( + "OwnershipAnalyzer: expected top-level 'functions' or 'defs' array".to_string(), + ); } // Convert ScopeInfo to OwnershipPlan @@ -87,26 +89,37 @@ impl OwnershipAnalyzer { fn alloc_scope(&mut self, kind: ScopeKind, parent: Option) -> ScopeId { let id = ScopeId(self.next_scope_id); self.next_scope_id += 1; - self.scopes.insert(id, ScopeInfo { + self.scopes.insert( id, - kind, - parent, - defined: BTreeSet::new(), - reads: BTreeSet::new(), - writes: BTreeSet::new(), - condition_reads: BTreeSet::new(), - }); + ScopeInfo { + id, + kind, + parent, + defined: BTreeSet::new(), + reads: BTreeSet::new(), + writes: BTreeSet::new(), + condition_reads: BTreeSet::new(), + }, + ); id } - fn analyze_function(&mut self, func: &Value, parent: Option) -> Result { + fn analyze_function( + &mut self, + func: &Value, + parent: Option, + ) -> Result { let scope_id = self.alloc_scope(ScopeKind::Function, parent); // Collect function parameters as defined if let Some(params) = func.get("params").and_then(|p| p.as_array()) { for param in params { if let Some(name) = param.as_str() { - self.scopes.get_mut(&scope_id).unwrap().defined.insert(name.to_string()); + self.scopes + .get_mut(&scope_id) + .unwrap() + .defined + .insert(name.to_string()); } } } @@ -156,7 +169,11 @@ impl OwnershipAnalyzer { } "Assign" | "Assignment" => { if let Some(target) = stmt.get("target").and_then(|t| t.as_str()) { - self.scopes.get_mut(¤t_scope).unwrap().writes.insert(target.to_string()); + self.scopes + .get_mut(¤t_scope) + .unwrap() + .writes + .insert(target.to_string()); } if let Some(value) = stmt.get("value").or_else(|| stmt.get("expr")) { self.analyze_expression(value, current_scope, false)?; @@ -234,7 +251,12 @@ impl OwnershipAnalyzer { Ok(()) } - fn analyze_expression(&mut self, expr: &Value, current_scope: ScopeId, is_condition: bool) -> Result<(), String> { + fn analyze_expression( + &mut self, + expr: &Value, + current_scope: ScopeId, + is_condition: bool, + ) -> Result<(), String> { let kind = expr .get("kind") .or_else(|| expr.get("type")) @@ -372,8 +394,11 @@ impl OwnershipAnalyzer { // owned_vars: defined in this scope for name in &scope.defined { let is_written = scope.writes.contains(name); - let is_condition_only = scope.condition_reads.contains(name) && - !scope.writes.iter().any(|w| w == name && !scope.condition_reads.contains(w)); + let is_condition_only = scope.condition_reads.contains(name) + && !scope + .writes + .iter() + .any(|w| w == name && !scope.condition_reads.contains(w)); plan.owned_vars.push(ScopeOwnedVar { name: name.clone(), @@ -530,10 +555,15 @@ mod tests { // Find the loop plan let loop_plan = plans.iter().find(|p| { - p.relay_writes.iter().any(|r| r.name == "sum" || r.name == "i") + p.relay_writes + .iter() + .any(|r| r.name == "sum" || r.name == "i") }); - assert!(loop_plan.is_some(), "Should have a loop plan with relay writes"); + assert!( + loop_plan.is_some(), + "Should have a loop plan with relay writes" + ); let loop_plan = loop_plan.unwrap(); // sum and i are written in loop but owned by function -> relay_writes @@ -576,15 +606,19 @@ mod tests { let plans = analyzer.analyze_json(&json).unwrap(); // Find loop plan - let loop_plan = plans.iter().find(|p| { - p.owned_vars.iter().any(|v| v.name == "count") - }); + let loop_plan = plans + .iter() + .find(|p| p.owned_vars.iter().any(|v| v.name == "count")); assert!(loop_plan.is_some(), "Loop should own 'count'"); let loop_plan = loop_plan.unwrap(); // count is owned AND written -> carrier - let count_var = loop_plan.owned_vars.iter().find(|v| v.name == "count").unwrap(); + let count_var = loop_plan + .owned_vars + .iter() + .find(|v| v.name == "count") + .unwrap(); assert!(count_var.is_written, "count should be marked as written"); // No relay for count (it's owned) @@ -631,9 +665,9 @@ mod tests { let plans = analyzer.analyze_json(&json).unwrap(); // Find loop plan - let loop_plan = plans.iter().find(|p| { - p.captures.iter().any(|c| c.name == "limit") - }); + let loop_plan = plans + .iter() + .find(|p| p.captures.iter().any(|c| c.name == "limit")); assert!(loop_plan.is_some(), "Loop should capture 'limit'"); let loop_plan = loop_plan.unwrap(); @@ -642,7 +676,10 @@ mod tests { assert!(loop_plan.captures.iter().any(|c| c.name == "limit")); // limit should also be in condition_captures - assert!(loop_plan.condition_captures.iter().any(|c| c.name == "limit")); + assert!(loop_plan + .condition_captures + .iter() + .any(|c| c.name == "limit")); // limit is NOT in relay_writes (not written) assert!(!loop_plan.relay_writes.iter().any(|r| r.name == "limit")); @@ -687,9 +724,9 @@ mod tests { let plans = analyzer.analyze_json(&json).unwrap(); // At least one loop should relay total - let any_relay = plans.iter().any(|p| { - p.relay_writes.iter().any(|r| r.name == "total") - }); + let any_relay = plans + .iter() + .any(|p| p.relay_writes.iter().any(|r| r.name == "total")); assert!(any_relay, "Some loop should relay 'total' to function"); } diff --git a/src/mir/join_ir/ownership/mod.rs b/src/mir/join_ir/ownership/mod.rs index 8f402d96..c9cdf544 100644 --- a/src/mir/join_ir/ownership/mod.rs +++ b/src/mir/join_ir/ownership/mod.rs @@ -26,20 +26,20 @@ //! - Phase 59: plan_to_lowering helper for P3 (if-sum patterns) //! - Phase 71-Pre: plan_validator box (reusable validation) -mod types; mod analyzer; #[cfg(feature = "normalized_dev")] -mod plan_to_lowering; -#[cfg(feature = "normalized_dev")] mod ast_analyzer; #[cfg(feature = "normalized_dev")] -mod plan_validator; - -pub use types::*; -pub use analyzer::*; +mod plan_to_lowering; #[cfg(feature = "normalized_dev")] -pub use plan_to_lowering::*; +mod plan_validator; +mod types; + +pub use analyzer::*; #[cfg(feature = "normalized_dev")] pub use ast_analyzer::*; #[cfg(feature = "normalized_dev")] +pub use plan_to_lowering::*; +#[cfg(feature = "normalized_dev")] pub use plan_validator::*; +pub use types::*; diff --git a/src/mir/join_ir/ownership/plan_to_lowering.rs b/src/mir/join_ir/ownership/plan_to_lowering.rs index 9f15767d..d24f52ee 100644 --- a/src/mir/join_ir/ownership/plan_to_lowering.rs +++ b/src/mir/join_ir/ownership/plan_to_lowering.rs @@ -34,15 +34,15 @@ pub struct P3LoweringInputs { /// # Errors /// Returns Err if relay_writes is non-empty (Phase 58 scope limitation). #[cfg(feature = "normalized_dev")] -pub fn plan_to_p2_inputs( - plan: &OwnershipPlan, - loop_var: &str, -) -> Result { +pub fn plan_to_p2_inputs(plan: &OwnershipPlan, loop_var: &str) -> Result { // Fail-Fast: relay_writes not supported in Phase 58 if !plan.relay_writes.is_empty() { return Err(format!( "Phase 58 limitation: relay_writes not yet supported. Found: {:?}", - plan.relay_writes.iter().map(|r| &r.name).collect::>() + plan.relay_writes + .iter() + .map(|r| &r.name) + .collect::>() )); } @@ -68,7 +68,7 @@ pub fn plan_to_p2_inputs( carriers.push(CarrierVar { name: var.name.clone(), role, - init: CarrierInit::FromHost, // Default (Phase 228) + init: CarrierInit::FromHost, // Default (Phase 228) host_id: crate::mir::ValueId(0), // Placeholder - not used in dev analysis join_id: None, #[cfg(feature = "normalized_dev")] @@ -206,15 +206,15 @@ pub fn plan_to_p2_inputs_with_relay( /// # Errors /// Returns Err if relay_writes is non-empty (Phase 59 scope limitation). #[cfg(feature = "normalized_dev")] -pub fn plan_to_p3_inputs( - plan: &OwnershipPlan, - loop_var: &str, -) -> Result { +pub fn plan_to_p3_inputs(plan: &OwnershipPlan, loop_var: &str) -> Result { // Fail-Fast: relay_writes not supported in Phase 59 if !plan.relay_writes.is_empty() { return Err(format!( "Phase 59 limitation: relay_writes not yet supported for P3. Found: {:?}", - plan.relay_writes.iter().map(|r| &r.name).collect::>() + plan.relay_writes + .iter() + .map(|r| &r.name) + .collect::>() )); } @@ -240,7 +240,7 @@ pub fn plan_to_p3_inputs( carriers.push(CarrierVar { name: var.name.clone(), role, - init: CarrierInit::FromHost, // Default (Phase 228) + init: CarrierInit::FromHost, // Default (Phase 228) host_id: crate::mir::ValueId(0), // Placeholder - not used in dev analysis join_id: None, #[cfg(feature = "normalized_dev")] @@ -378,11 +378,12 @@ mod tests { let mut plan = OwnershipPlan::new(ScopeId(1)); plan.relay_writes.push(RelayVar { name: "counter".to_string(), - owner_scope: ScopeId(0), // L1 owns + owner_scope: ScopeId(0), // L1 owns relay_path: vec![ScopeId(1), ScopeId(2)], // L3 → L2 → L1 }); - let inputs = plan_to_p2_inputs_with_relay(&plan, "i").expect("Phase 66: multihop should be accepted"); + let inputs = plan_to_p2_inputs_with_relay(&plan, "i") + .expect("Phase 66: multihop should be accepted"); assert_eq!(inputs.carriers.len(), 1); assert_eq!(inputs.carriers[0].name, "counter"); assert_eq!(inputs.carriers[0].role, CarrierRole::LoopState); @@ -433,7 +434,9 @@ mod tests { let result = plan_to_p2_inputs_with_relay(&plan, "i"); assert!(result.is_err()); - assert!(result.unwrap_err().contains("relay cannot be owned by same scope")); + assert!(result + .unwrap_err() + .contains("relay cannot be owned by same scope")); } #[test] @@ -454,7 +457,9 @@ mod tests { let result = plan_to_p2_inputs_with_relay(&plan, "i"); assert!(result.is_err()); - assert!(result.unwrap_err().contains("appears in both owned_vars and relay_writes")); + assert!(result + .unwrap_err() + .contains("appears in both owned_vars and relay_writes")); } #[test] @@ -546,12 +551,11 @@ mod tests { fn test_p3_five_plus_carriers() { // Selfhost P3 pattern: 5+ carriers let mut plan = OwnershipPlan::new(ScopeId(1)); - plan.owned_vars - .push(ScopeOwnedVar { - name: "i".to_string(), - is_written: true, - is_condition_only: false, - }); + plan.owned_vars.push(ScopeOwnedVar { + name: "i".to_string(), + is_written: true, + is_condition_only: false, + }); plan.owned_vars.push(ScopeOwnedVar { name: "total".to_string(), is_written: true, diff --git a/src/mir/join_ir/ownership/plan_validator.rs b/src/mir/join_ir/ownership/plan_validator.rs index 800c7ec1..141ef5d0 100644 --- a/src/mir/join_ir/ownership/plan_validator.rs +++ b/src/mir/join_ir/ownership/plan_validator.rs @@ -297,7 +297,7 @@ mod tests { )], trim_helper: None, promoted_loopbodylocals: vec![], -#[cfg(feature = "normalized_dev")] + #[cfg(feature = "normalized_dev")] promoted_bindings: std::collections::BTreeMap::new(), }; diff --git a/src/mir/join_ir/ownership/types.rs b/src/mir/join_ir/ownership/types.rs index adfed160..4f1b6003 100644 --- a/src/mir/join_ir/ownership/types.rs +++ b/src/mir/join_ir/ownership/types.rs @@ -82,7 +82,9 @@ impl OwnershipPlan { /// Get condition-only carriers (owned, written, condition-only). pub fn condition_only_carriers(&self) -> impl Iterator { - self.owned_vars.iter().filter(|v| v.is_written && v.is_condition_only) + self.owned_vars + .iter() + .filter(|v| v.is_written && v.is_condition_only) } /// Check invariant: no variable appears in multiple categories. @@ -134,7 +136,7 @@ mod tests { }); plan.owned_vars.push(ScopeOwnedVar { name: "limit".to_string(), - is_written: false, // read-only owned + is_written: false, // read-only owned is_condition_only: false, }); diff --git a/src/mir/join_ir/verify_phi_reserved.rs b/src/mir/join_ir/verify_phi_reserved.rs index f5bbb20c..799e61a5 100644 --- a/src/mir/join_ir/verify_phi_reserved.rs +++ b/src/mir/join_ir/verify_phi_reserved.rs @@ -59,9 +59,7 @@ pub fn disable_observation() { /// Analyze PHI dst distribution #[cfg(debug_assertions)] pub fn analyze_distribution(observations: &[u32]) -> PhiDistributionReport { - use crate::mir::join_ir::lowering::join_value_space::{ - PHI_RESERVED_MAX, PARAM_MIN, LOCAL_MIN, - }; + use crate::mir::join_ir::lowering::join_value_space::{LOCAL_MIN, PARAM_MIN, PHI_RESERVED_MAX}; let mut in_reserved = 0; let mut in_param = 0; diff --git a/src/mir/join_ir_runner.rs b/src/mir/join_ir_runner.rs index a3feacf6..82d1a8d7 100644 --- a/src/mir/join_ir_runner.rs +++ b/src/mir/join_ir_runner.rs @@ -32,11 +32,9 @@ use std::collections::HashMap; #[cfg(feature = "normalized_dev")] use crate::config::env::joinir_dev::{current_joinir_mode, JoinIrMode}; -use crate::mir::join_ir::{ConstValue, JoinFuncId, JoinInst, JoinModule, MirLikeInst, VarId}; #[cfg(feature = "normalized_dev")] -use crate::mir::join_ir::normalized::{ - dev_env, normalized_dev_roundtrip_structured, shape_guard, -}; +use crate::mir::join_ir::normalized::{dev_env, normalized_dev_roundtrip_structured, shape_guard}; +use crate::mir::join_ir::{ConstValue, JoinFuncId, JoinInst, JoinModule, MirLikeInst, VarId}; // Phase 27.8: ops box からの再エクスポート pub use crate::mir::join_ir_ops::{JoinIrOpError, JoinValue}; @@ -104,7 +102,9 @@ fn run_joinir_function_normalized_dev( let shapes = shape_guard::supported_shapes(module); if shapes.is_empty() { if debug { - eprintln!("[joinir/normalized-dev/runner] shape unsupported; staying on Structured path"); + eprintln!( + "[joinir/normalized-dev/runner] shape unsupported; staying on Structured path" + ); } return execute_function(vm, module, entry, args_vec); } diff --git a/src/mir/join_ir_vm_bridge/bridge.rs b/src/mir/join_ir_vm_bridge/bridge.rs index cd1f9efe..9dc3bf0f 100644 --- a/src/mir/join_ir_vm_bridge/bridge.rs +++ b/src/mir/join_ir_vm_bridge/bridge.rs @@ -7,13 +7,13 @@ use std::collections::BTreeMap; #[cfg(feature = "normalized_dev")] use crate::config::env::joinir_dev::{current_joinir_mode, JoinIrMode}; #[cfg(feature = "normalized_dev")] -use crate::mir::join_ir::JoinIrPhase; +use crate::mir::join_ir::normalized::shape_guard::{self, NormalizedDevShape}; #[cfg(feature = "normalized_dev")] use crate::mir::join_ir::normalized::{ normalize_pattern1_minimal, normalize_pattern2_minimal, NormalizedModule, }; #[cfg(feature = "normalized_dev")] -use crate::mir::join_ir::normalized::shape_guard::{self, NormalizedDevShape}; +use crate::mir::join_ir::JoinIrPhase; #[cfg(feature = "normalized_dev")] use crate::mir::join_ir_vm_bridge::lower_normalized_to_mir_minimal; #[cfg(feature = "normalized_dev")] @@ -124,22 +124,22 @@ fn normalize_for_shape( .expect("P4 normalization failed") })), // Phase 48-B: JsonParser continue skip_ws (array/object) - NormalizedDevShape::JsonparserParseArrayContinueSkipWs => catch_unwind(AssertUnwindSafe( - || { + NormalizedDevShape::JsonparserParseArrayContinueSkipWs => { + catch_unwind(AssertUnwindSafe(|| { crate::mir::join_ir::normalized::normalize_jsonparser_parse_array_continue_skip_ws( module, ) .expect("P4 array normalization failed") - }, - )), - NormalizedDevShape::JsonparserParseObjectContinueSkipWs => catch_unwind(AssertUnwindSafe( - || { + })) + } + NormalizedDevShape::JsonparserParseObjectContinueSkipWs => { + catch_unwind(AssertUnwindSafe(|| { crate::mir::join_ir::normalized::normalize_jsonparser_parse_object_continue_skip_ws( module, ) .expect("P4 object normalization failed") - }, - )), + })) + } // Phase 89: Continue + Early Return pattern (dev-only, delegates to P2 for now) NormalizedDevShape::PatternContinueReturnMinimal => { catch_unwind(AssertUnwindSafe(|| normalize_pattern2_minimal(module))) diff --git a/src/mir/join_ir_vm_bridge/joinir_block_converter.rs b/src/mir/join_ir_vm_bridge/joinir_block_converter.rs index da436cc9..678e77eb 100644 --- a/src/mir/join_ir_vm_bridge/joinir_block_converter.rs +++ b/src/mir/join_ir_vm_bridge/joinir_block_converter.rs @@ -72,7 +72,10 @@ impl JoinIrBlockConverter { continue; } // Debug: show what instruction we're processing - log_dbg(format!("[joinir_block] Compute instruction: {:?}", mir_like)); + log_dbg(format!( + "[joinir_block] Compute instruction: {:?}", + mir_like + )); let mir_inst = convert_mir_like_inst(mir_like)?; self.current_instructions.push(mir_inst); } diff --git a/src/mir/join_ir_vm_bridge/mod.rs b/src/mir/join_ir_vm_bridge/mod.rs index 2c429f6a..ba36540f 100644 --- a/src/mir/join_ir_vm_bridge/mod.rs +++ b/src/mir/join_ir_vm_bridge/mod.rs @@ -55,9 +55,9 @@ pub(crate) use bridge::{bridge_joinir_to_mir, bridge_joinir_to_mir_with_meta}; pub(crate) use convert::convert_joinir_to_mir; pub(crate) use convert::convert_mir_like_inst; // helper for sub-modules pub(crate) use joinir_function_converter::JoinIrFunctionConverter; +pub use meta::convert_join_module_to_mir_with_meta; #[cfg(feature = "normalized_dev")] pub(crate) use normalized_bridge::lower_normalized_to_mir_minimal; -pub use meta::convert_join_module_to_mir_with_meta; pub use runner::run_joinir_via_vm; /// Phase 27-shortterm S-4 エラー型 diff --git a/src/mir/join_ir_vm_bridge/normalized_bridge.rs b/src/mir/join_ir_vm_bridge/normalized_bridge.rs index 9a86ad44..df86ff62 100644 --- a/src/mir/join_ir_vm_bridge/normalized_bridge.rs +++ b/src/mir/join_ir_vm_bridge/normalized_bridge.rs @@ -19,7 +19,11 @@ fn dev_debug_enabled() -> bool { pub(super) fn log_dev(category: &str, message: impl AsRef, important: bool) { let debug = dev_debug_enabled(); if debug || important { - eprintln!("[joinir/normalized-dev/bridge/{}] {}", category, message.as_ref()); + eprintln!( + "[joinir/normalized-dev/bridge/{}] {}", + category, + message.as_ref() + ); } } diff --git a/src/mir/join_ir_vm_bridge/normalized_bridge/direct.rs b/src/mir/join_ir_vm_bridge/normalized_bridge/direct.rs index 30d28f1b..8cb87e3f 100644 --- a/src/mir/join_ir_vm_bridge/normalized_bridge/direct.rs +++ b/src/mir/join_ir_vm_bridge/normalized_bridge/direct.rs @@ -1,8 +1,8 @@ #![cfg(feature = "normalized_dev")] +use super::super::convert_mir_like_inst; use super::super::join_func_name; use super::super::JoinIrVmBridgeError; -use super::super::convert_mir_like_inst; use crate::ast::Span; use crate::mir::join_ir::normalized::{JpFuncId, JpFunction, JpInst, JpOp, NormalizedModule}; use crate::mir::join_ir::{JoinFuncId, JoinIrPhase, MirLikeInst}; @@ -83,7 +83,9 @@ fn lower_normalized_function_direct( let remap = |id: ValueId, map: &mut BTreeMap| remap_value(id, map); let remap_vec = |ids: &[ValueId], map: &mut BTreeMap| { - ids.iter().map(|id| remap_value(*id, map)).collect::>() + ids.iter() + .map(|id| remap_value(*id, map)) + .collect::>() }; let remapped_params = remap_vec(¶ms, &mut value_map); @@ -188,7 +190,8 @@ fn lower_normalized_function_direct( } JpInst::TailCallFn { target, env } => { let env_remapped = remap_vec(env, &mut value_map); - let (instructions, terminator) = build_tail_call(&mut mir_func, target, &env_remapped); + let (instructions, terminator) = + build_tail_call(&mut mir_func, target, &env_remapped); finalize_block( &mut mir_func, current_block_id, @@ -371,7 +374,12 @@ fn build_tail_call( effects: EffectMask::PURE, }); - (instructions, MirInstruction::Return { value: Some(result_id) }) + ( + instructions, + MirInstruction::Return { + value: Some(result_id), + }, + ) } fn build_exit_or_tail_branch( diff --git a/src/mir/loop_canonicalizer/canonicalizer.rs b/src/mir/loop_canonicalizer/canonicalizer.rs index 04eadf9e..34398185 100644 --- a/src/mir/loop_canonicalizer/canonicalizer.rs +++ b/src/mir/loop_canonicalizer/canonicalizer.rs @@ -6,7 +6,7 @@ use crate::ast::ASTNode; use crate::mir::loop_pattern_detection::LoopPatternKind; -use super::capability_guard::{capability_tags, RoutingDecision}; +use super::capability_guard::{CapabilityTag, RoutingDecision}; use super::pattern_recognizer::try_extract_skip_whitespace_pattern; use super::skeleton_types::{ CarrierRole, CarrierSlot, ExitContract, LoopSkeleton, SkeletonStep, UpdateKind, @@ -63,9 +63,9 @@ pub fn canonicalize_loop_expr( // Step 2: Body statements (if any) if !body_stmts.is_empty() { - skeleton.steps.push(SkeletonStep::Body { - stmts: body_stmts, - }); + skeleton + .steps + .push(SkeletonStep::Body { stmts: body_stmts }); } // Step 3: Update step @@ -100,7 +100,7 @@ pub fn canonicalize_loop_expr( Ok(( LoopSkeleton::new(span), RoutingDecision::fail_fast( - vec![capability_tags::CAP_MISSING_CONST_STEP], + vec![CapabilityTag::ConstStep], "Phase 3: Loop does not match skip_whitespace pattern".to_string(), ), )) @@ -192,14 +192,8 @@ mod tests { // Verify skeleton structure assert_eq!(skeleton.steps.len(), 2); // HeaderCond + Update - assert!(matches!( - skeleton.steps[0], - SkeletonStep::HeaderCond { .. } - )); - assert!(matches!( - skeleton.steps[1], - SkeletonStep::Update { .. } - )); + assert!(matches!(skeleton.steps[0], SkeletonStep::HeaderCond { .. })); + assert!(matches!(skeleton.steps[1], SkeletonStep::Update { .. })); // Verify carrier assert_eq!(skeleton.carriers.len(), 1); @@ -300,15 +294,9 @@ mod tests { // Verify skeleton has Body step assert_eq!(skeleton.steps.len(), 3); // HeaderCond + Body + Update - assert!(matches!( - skeleton.steps[0], - SkeletonStep::HeaderCond { .. } - )); + assert!(matches!(skeleton.steps[0], SkeletonStep::HeaderCond { .. })); assert!(matches!(skeleton.steps[1], SkeletonStep::Body { .. })); - assert!(matches!( - skeleton.steps[2], - SkeletonStep::Update { .. } - )); + assert!(matches!(skeleton.steps[2], SkeletonStep::Update { .. })); // Verify body contains 1 statement match &skeleton.steps[1] { @@ -360,9 +348,7 @@ mod tests { let (_, decision) = result.unwrap(); assert!(decision.is_fail_fast()); - assert!(decision - .notes[0] - .contains("does not match skip_whitespace pattern")); + assert!(decision.notes[0].contains("does not match skip_whitespace pattern")); } #[test] diff --git a/src/mir/loop_canonicalizer/capability_guard.rs b/src/mir/loop_canonicalizer/capability_guard.rs index f8aab126..7da91777 100644 --- a/src/mir/loop_canonicalizer/capability_guard.rs +++ b/src/mir/loop_canonicalizer/capability_guard.rs @@ -18,8 +18,8 @@ pub struct RoutingDecision { /// Selected pattern (None = Fail-Fast) pub chosen: Option, - /// Missing capabilities that prevented other patterns - pub missing_caps: Vec<&'static str>, + /// Missing capabilities that prevented other patterns (type-safe!) + pub missing_caps: Vec, /// Selection reasoning (for debugging) pub notes: Vec, @@ -40,12 +40,17 @@ impl RoutingDecision { } /// Create a failed routing decision (Fail-Fast) - pub fn fail_fast(missing_caps: Vec<&'static str>, reason: String) -> Self { + pub fn fail_fast(missing_caps: Vec, reason: String) -> Self { + let error_tags = missing_caps + .iter() + .map(|cap| cap.to_tag().to_string()) + .collect(); + Self { chosen: None, missing_caps, notes: vec![reason.clone()], - error_tags: vec![format!("[loop_canonicalizer/fail_fast] {}", reason)], + error_tags, } } @@ -125,38 +130,3 @@ impl CapabilityTag { } } } - -// ============================================================================ -// Legacy Capability Tags (Deprecated - will be removed in Phase 139-P3-B) -// ============================================================================ - -/// Legacy capability tags - Standardized vocabulary for Fail-Fast reasons -/// -/// ⚠️ DEPRECATED: Use CapabilityTag enum instead for type safety. -/// This module will be removed in Phase 139-P3-B. -#[deprecated(since = "Phase 139-P3-A", note = "Use CapabilityTag enum instead")] -pub mod capability_tags { - /// Requires: Carrier update is constant step (`i = i + const`) - pub const CAP_MISSING_CONST_STEP: &str = "CAP_MISSING_CONST_STEP"; - - /// Requires: Single break point only - pub const CAP_MISSING_SINGLE_BREAK: &str = "CAP_MISSING_SINGLE_BREAK"; - - /// Requires: Single continue point only - pub const CAP_MISSING_SINGLE_CONTINUE: &str = "CAP_MISSING_SINGLE_CONTINUE"; - - /// Requires: Loop header condition has no side effects - pub const CAP_MISSING_PURE_HEADER: &str = "CAP_MISSING_PURE_HEADER"; - - /// Requires: Condition variable defined in outer local scope - pub const CAP_MISSING_OUTER_LOCAL_COND: &str = "CAP_MISSING_OUTER_LOCAL_COND"; - - /// Requires: All exit bindings are complete (no missing values) - pub const CAP_MISSING_EXIT_BINDINGS: &str = "CAP_MISSING_EXIT_BINDINGS"; - - /// Requires: LoopBodyLocal can be promoted to carrier - pub const CAP_MISSING_CARRIER_PROMOTION: &str = "CAP_MISSING_CARRIER_PROMOTION"; - - /// Requires: Break value types are consistent across all break points - pub const CAP_MISSING_BREAK_VALUE_TYPE: &str = "CAP_MISSING_BREAK_VALUE_TYPE"; -} diff --git a/src/mir/loop_canonicalizer/mod.rs b/src/mir/loop_canonicalizer/mod.rs index c4f1415b..c7a35165 100644 --- a/src/mir/loop_canonicalizer/mod.rs +++ b/src/mir/loop_canonicalizer/mod.rs @@ -34,10 +34,10 @@ // Module Declarations // ============================================================================ -mod skeleton_types; +mod canonicalizer; mod capability_guard; mod pattern_recognizer; -mod canonicalizer; +mod skeleton_types; // ============================================================================ // Public Re-exports @@ -45,20 +45,11 @@ mod canonicalizer; // Skeleton Types pub use skeleton_types::{ - CarrierRole, - CarrierSlot, - CapturedSlot, - ExitContract, - LoopSkeleton, - SkeletonStep, - UpdateKind, + CapturedSlot, CarrierRole, CarrierSlot, ExitContract, LoopSkeleton, SkeletonStep, UpdateKind, }; // Capability Guard -pub use capability_guard::{ - capability_tags, - RoutingDecision, -}; +pub use capability_guard::{CapabilityTag, RoutingDecision}; // Canonicalization Entry Point pub use canonicalizer::canonicalize_loop_expr; @@ -97,13 +88,12 @@ mod tests { assert!(success.is_success()); assert!(!success.is_fail_fast()); - let fail = RoutingDecision::fail_fast( - vec![capability_tags::CAP_MISSING_CONST_STEP], - "Test failure".to_string(), - ); + let fail = + RoutingDecision::fail_fast(vec![CapabilityTag::ConstStep], "Test failure".to_string()); assert!(!fail.is_success()); assert!(fail.is_fail_fast()); assert_eq!(fail.missing_caps.len(), 1); + assert_eq!(fail.missing_caps[0], CapabilityTag::ConstStep); } #[test] diff --git a/src/mir/loop_canonicalizer/skeleton_types.rs b/src/mir/loop_canonicalizer/skeleton_types.rs index 1a619c8d..c4e3f2d2 100644 --- a/src/mir/loop_canonicalizer/skeleton_types.rs +++ b/src/mir/loop_canonicalizer/skeleton_types.rs @@ -39,20 +39,13 @@ pub struct LoopSkeleton { #[derive(Debug, Clone)] pub enum SkeletonStep { /// Loop continuation condition (the `cond` in `loop(cond)`) - HeaderCond { - expr: Box, - }, + HeaderCond { expr: Box }, /// Early exit check (`if cond { break }`) - BreakCheck { - cond: Box, - has_value: bool, - }, + BreakCheck { cond: Box, has_value: bool }, /// Skip check (`if cond { continue }`) - ContinueCheck { - cond: Box, - }, + ContinueCheck { cond: Box }, /// Carrier update (`i = i + 1`, etc.) Update { @@ -61,9 +54,7 @@ pub enum SkeletonStep { }, /// Loop body (all other statements) - Body { - stmts: Vec, - }, + Body { stmts: Vec }, } /// Update kind - How a carrier variable is updated @@ -72,9 +63,7 @@ pub enum SkeletonStep { #[derive(Debug, Clone)] pub enum UpdateKind { /// Constant step (`i = i + const`) - ConstStep { - delta: i64, - }, + ConstStep { delta: i64 }, /// Conditional update (`if cond { x = a } else { x = b }`) Conditional { diff --git a/src/mir/loop_pattern_detection/digitpos_detector.rs b/src/mir/loop_pattern_detection/digitpos_detector.rs index e7ab46e7..705695b0 100644 --- a/src/mir/loop_pattern_detection/digitpos_detector.rs +++ b/src/mir/loop_pattern_detection/digitpos_detector.rs @@ -441,11 +441,7 @@ mod tests { let result = DigitPosDetector::detect(&condition, &loop_body, "p"); - assert!( - result.is_some(), - "Expected detection for operator {:?}", - op - ); + assert!(result.is_some(), "Expected detection for operator {:?}", op); } } diff --git a/src/mir/loop_pattern_detection/function_scope_capture/helpers.rs b/src/mir/loop_pattern_detection/function_scope_capture/helpers.rs index 20853f5d..7240e791 100644 --- a/src/mir/loop_pattern_detection/function_scope_capture/helpers.rs +++ b/src/mir/loop_pattern_detection/function_scope_capture/helpers.rs @@ -56,9 +56,7 @@ pub(super) fn body_matches(a: &[ASTNode], b: &[ASTNode]) -> bool { /// Collect local variable declarations from statements /// /// Returns Vec<(name, init_expr)> for each variable declared with `local`. -pub(super) fn collect_local_declarations( - stmts: &[ASTNode], -) -> Vec<(String, Option>)> { +pub(super) fn collect_local_declarations(stmts: &[ASTNode]) -> Vec<(String, Option>)> { let mut locals = Vec::new(); for stmt in stmts { diff --git a/src/mir/loop_pattern_detection/loop_body_carrier_promoter.rs b/src/mir/loop_pattern_detection/loop_body_carrier_promoter.rs index 04a9aa81..f2eeea17 100644 --- a/src/mir/loop_pattern_detection/loop_body_carrier_promoter.rs +++ b/src/mir/loop_pattern_detection/loop_body_carrier_promoter.rs @@ -80,8 +80,9 @@ impl TrimPatternInfo { /// - JoinInlineBoundary will handle the boundary mapping pub fn to_carrier_info( &self, - #[cfg(feature = "normalized_dev")] - binding_map: Option<&std::collections::BTreeMap>, + #[cfg(feature = "normalized_dev")] binding_map: Option< + &std::collections::BTreeMap, + >, ) -> crate::mir::join_ir::lowering::carrier_info::CarrierInfo { use super::trim_loop_helper::TrimLoopHelper; use crate::mir::join_ir::lowering::carrier_info::CarrierInfo; @@ -110,11 +111,9 @@ impl TrimPatternInfo { #[cfg(not(feature = "normalized_dev"))] let recorder = PromotedBindingRecorder::new(); - if let Err(e) = recorder.record_promotion( - &mut carrier_info, - &self.var_name, - &self.carrier_name, - ) { + if let Err(e) = + recorder.record_promotion(&mut carrier_info, &self.var_name, &self.carrier_name) + { log_trim_promotion_error(&e); } @@ -195,8 +194,7 @@ impl LoopBodyCarrierPromoter { // 3. 各 LoopBodyLocal に対して TrimDetector で検出を試行 for var_name in &body_locals { // Phase 79: Use TrimDetector for pure detection logic - if let Some(detection) = TrimDetector::detect(break_cond, request.loop_body, var_name) - { + if let Some(detection) = TrimDetector::detect(break_cond, request.loop_body, var_name) { if is_joinir_debug() || std::env::var("JOINIR_TEST_DEBUG").is_ok() { eprintln!( "[promoter/pattern5] Trim pattern detected! var='{}', literals={:?}", diff --git a/src/mir/loop_pattern_detection/loop_body_digitpos_promoter.rs b/src/mir/loop_pattern_detection/loop_body_digitpos_promoter.rs index 89238f36..18a117cd 100644 --- a/src/mir/loop_pattern_detection/loop_body_digitpos_promoter.rs +++ b/src/mir/loop_pattern_detection/loop_body_digitpos_promoter.rs @@ -148,11 +148,8 @@ impl DigitPosPromoter { } // Step 3: Use DigitPosDetector for pure detection - let detection = DigitPosDetector::detect( - condition.unwrap(), - req.loop_body, - req.loop_param_name, - ); + let detection = + DigitPosDetector::detect(condition.unwrap(), req.loop_body, req.loop_param_name); if detection.is_none() { return DigitPosPromotionResult::CannotPromote { @@ -171,16 +168,14 @@ impl DigitPosPromoter { } // Step 4: Build CarrierInfo - use crate::mir::join_ir::lowering::carrier_info::{ - CarrierInit, CarrierRole, CarrierVar, - }; + use crate::mir::join_ir::lowering::carrier_info::{CarrierInit, CarrierRole, CarrierVar}; // Boolean carrier (condition-only, for break) let promoted_carrier_bool = CarrierVar { name: detection.bool_carrier_name.clone(), - host_id: ValueId(0), // Placeholder (will be remapped) - join_id: None, // Will be allocated later - role: CarrierRole::ConditionOnly, // Phase 227: DigitPos is condition-only + host_id: ValueId(0), // Placeholder (will be remapped) + 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 diff --git a/src/mir/loop_pattern_detection/tests.rs b/src/mir/loop_pattern_detection/tests.rs index 541d2578..479530ce 100644 --- a/src/mir/loop_pattern_detection/tests.rs +++ b/src/mir/loop_pattern_detection/tests.rs @@ -116,7 +116,7 @@ fn classify_body(body: &[ASTNode]) -> LoopPatternKind { carrier_count: carrier_count(body), break_count: if has_break_flag { 1 } else { 0 }, continue_count: if has_continue_flag { 1 } else { 0 }, - is_infinite_loop: false, // テストでは通常ループを想定 + is_infinite_loop: false, // テストでは通常ループを想定 update_summary: None, }; classify(&features) diff --git a/src/mir/loop_pattern_detection/trim_detector.rs b/src/mir/loop_pattern_detection/trim_detector.rs index 7489d225..11befbe2 100644 --- a/src/mir/loop_pattern_detection/trim_detector.rs +++ b/src/mir/loop_pattern_detection/trim_detector.rs @@ -424,7 +424,11 @@ mod tests { let result = TrimDetector::detect(&condition, &loop_body, var_name); - assert!(result.is_some(), "Expected detection for var '{}'", var_name); + assert!( + result.is_some(), + "Expected detection for var '{}'", + var_name + ); let result = result.unwrap(); assert_eq!(result.match_var, var_name); assert_eq!(result.carrier_name, format!("is_{}_match", var_name)); diff --git a/src/mir/region/observer.rs b/src/mir/region/observer.rs index 17e7a050..01574435 100644 --- a/src/mir/region/observer.rs +++ b/src/mir/region/observer.rs @@ -37,7 +37,8 @@ pub fn observe_control_form(builder: &mut MirBuilder, form: &ControlForm) { } let func_name = builder - .scope_ctx.current_function + .scope_ctx + .current_function .as_ref() .map(|f| f.signature.name.as_str()) .unwrap_or(""); @@ -60,11 +61,12 @@ pub fn observe_control_form(builder: &mut MirBuilder, form: &ControlForm) { // 変数スロットは SlotRegistry があればそれを優先し、なければ // variable_map と value_types から best-effort で推定するよ。 - let slots: Vec = if let Some(reg) = builder.comp_ctx.current_slot_registry.as_mut() { - classify_slots_from_registry(reg) - } else { - classify_slots_from_variable_map(builder) - }; + let slots: Vec = + if let Some(reg) = builder.comp_ctx.current_slot_registry.as_mut() { + classify_slots_from_registry(reg) + } else { + classify_slots_from_variable_map(builder) + }; let parent = builder.metadata_ctx.current_region_stack().last().copied(); @@ -94,7 +96,8 @@ pub fn observe_function_region(builder: &mut MirBuilder) { } let func_name = builder - .scope_ctx.current_function + .scope_ctx + .current_function .as_ref() .map(|f| f.signature.name.as_str()) .unwrap_or(""); @@ -107,7 +110,8 @@ pub fn observe_function_region(builder: &mut MirBuilder) { let id = RegionId(NEXT_REGION_ID.fetch_add(1, Ordering::Relaxed)); let entry_block = builder - .scope_ctx.current_function + .scope_ctx + .current_function .as_ref() .map(|f| f.entry_block) .unwrap_or_else(|| crate::mir::BasicBlockId::new(0)); diff --git a/src/mir/utils/phi_helpers.rs b/src/mir/utils/phi_helpers.rs index 3dbcdb72..eb9532fd 100644 --- a/src/mir/utils/phi_helpers.rs +++ b/src/mir/utils/phi_helpers.rs @@ -70,7 +70,9 @@ impl MirBuilder { }; // 統一された挿入ロジック(既存パターンと完全互換) - if let (Some(func), Some(cur_bb)) = (self.scope_ctx.current_function.as_mut(), self.current_block) { + if let (Some(func), Some(cur_bb)) = + (self.scope_ctx.current_function.as_mut(), self.current_block) + { // CFG経由の正規化挿入(predecessor順序の正規化を含む) crate::mir::ssot::cf_common::insert_phi_at_head_spanned( func, @@ -136,7 +138,9 @@ impl MirBuilder { inputs: Vec<(BasicBlockId, ValueId)>, ) -> Result<(), String> { // 統一された挿入ロジック(既存パターンと完全互換) - if let (Some(func), Some(cur_bb)) = (self.scope_ctx.current_function.as_mut(), self.current_block) { + if let (Some(func), Some(cur_bb)) = + (self.scope_ctx.current_function.as_mut(), self.current_block) + { // CFG経由の正規化挿入(predecessor順序の正規化を含む) crate::mir::ssot::cf_common::insert_phi_at_head_spanned( func, diff --git a/src/runner/mir_json_emit.rs b/src/runner/mir_json_emit.rs index dcbeae53..21854ff1 100644 --- a/src/runner/mir_json_emit.rs +++ b/src/runner/mir_json_emit.rs @@ -201,7 +201,8 @@ pub fn emit_mir_json_for_harness( .map(|(b, v)| json!([v.as_u32(), b.as_u32()])) .collect(); // Phase 131-11-F: Add dst_type hint from metadata for all PHI instructions - let mut phi_inst = json!({"op":"phi","dst": dst.as_u32(), "incoming": incoming}); + let mut phi_inst = + json!({"op":"phi","dst": dst.as_u32(), "incoming": incoming}); if let Some(dst_type) = f.metadata.value_types.get(dst) { let type_json = match dst_type { MirType::Integer => json!("i64"), @@ -227,7 +228,9 @@ pub fn emit_mir_json_for_harness( continue; } I::Copy { dst, src } => { - insts.push(json!({"op":"copy","dst": dst.as_u32(), "src": src.as_u32()})); + insts.push( + json!({"op":"copy","dst": dst.as_u32(), "src": src.as_u32()}), + ); } I::UnaryOp { dst, op, operand } => { let kind = match op { @@ -422,8 +425,7 @@ pub fn emit_mir_json_for_harness( obj["dst_type"] = t; } insts.push(obj); - if let Some(d) = dst.map(|v| v.as_u32()) { - } + if let Some(d) = dst.map(|v| v.as_u32()) {} } _ => { // Other callee types: emit generic call @@ -496,8 +498,7 @@ pub fn emit_mir_json_for_harness( obj["dst_type"] = t; } insts.push(obj); - if let Some(d) = dst.map(|v| v.as_u32()) { - } + if let Some(d) = dst.map(|v| v.as_u32()) {} } I::NewBox { dst, @@ -622,7 +623,8 @@ pub fn emit_mir_json_for_harness_bin( .map(|(b, v)| json!([v.as_u32(), b.as_u32()])) .collect(); // Phase 131-11-F: Add dst_type hint from metadata for all PHI instructions - let mut phi_inst = json!({"op":"phi","dst": dst.as_u32(), "incoming": incoming}); + let mut phi_inst = + json!({"op":"phi","dst": dst.as_u32(), "incoming": incoming}); if let Some(dst_type) = f.metadata.value_types.get(dst) { let type_json = match dst_type { MirType::Integer => json!("i64"), @@ -648,34 +650,34 @@ pub fn emit_mir_json_for_harness_bin( continue; } I::Copy { dst, src } => { - insts.push(json!({"op":"copy","dst": dst.as_u32(), "src": src.as_u32()})); + insts.push( + json!({"op":"copy","dst": dst.as_u32(), "src": src.as_u32()}), + ); } - I::Const { dst, value } => { - match value { - crate::mir::ConstValue::Integer(i) => { - insts.push(json!({"op":"const","dst": dst.as_u32(), "value": {"type": "i64", "value": i}})); - } - crate::mir::ConstValue::Float(fv) => { - insts.push(json!({"op":"const","dst": dst.as_u32(), "value": {"type": "f64", "value": fv}})); - } - crate::mir::ConstValue::Bool(b) => { - insts.push(json!({"op":"const","dst": dst.as_u32(), "value": {"type": "i64", "value": if *b {1} else {0}}})); - } - crate::mir::ConstValue::String(s) => { - insts.push(json!({ - "op":"const", - "dst": dst.as_u32(), - "value": { - "type": {"kind":"handle","box_type":"StringBox"}, - "value": s - } - })); - } - crate::mir::ConstValue::Null | crate::mir::ConstValue::Void => { - insts.push(json!({"op":"const","dst": dst.as_u32(), "value": {"type": "void", "value": 0}})); - } + I::Const { dst, value } => match value { + crate::mir::ConstValue::Integer(i) => { + insts.push(json!({"op":"const","dst": dst.as_u32(), "value": {"type": "i64", "value": i}})); } - } + crate::mir::ConstValue::Float(fv) => { + insts.push(json!({"op":"const","dst": dst.as_u32(), "value": {"type": "f64", "value": fv}})); + } + crate::mir::ConstValue::Bool(b) => { + insts.push(json!({"op":"const","dst": dst.as_u32(), "value": {"type": "i64", "value": if *b {1} else {0}}})); + } + crate::mir::ConstValue::String(s) => { + insts.push(json!({ + "op":"const", + "dst": dst.as_u32(), + "value": { + "type": {"kind":"handle","box_type":"StringBox"}, + "value": s + } + })); + } + crate::mir::ConstValue::Null | crate::mir::ConstValue::Void => { + insts.push(json!({"op":"const","dst": dst.as_u32(), "value": {"type": "void", "value": 0}})); + } + }, I::BinOp { dst, op, lhs, rhs } => { let op_s = match op { B::Add => "+", @@ -794,8 +796,7 @@ pub fn emit_mir_json_for_harness_bin( obj["dst_type"] = t; } insts.push(obj); - if let Some(d) = dst.map(|v| v.as_u32()) { - } + if let Some(d) = dst.map(|v| v.as_u32()) {} } _ => { // Other callee types: emit generic call @@ -829,8 +830,7 @@ pub fn emit_mir_json_for_harness_bin( } } insts.push(obj); - if let Some(d) = dst.map(|v| v.as_u32()) { - } + if let Some(d) = dst.map(|v| v.as_u32()) {} } I::BoxCall { dst, @@ -860,8 +860,7 @@ pub fn emit_mir_json_for_harness_bin( obj["dst_type"] = t; } insts.push(obj); - if let Some(d) = dst.map(|v| v.as_u32()) { - } + if let Some(d) = dst.map(|v| v.as_u32()) {} } I::NewBox { dst, diff --git a/tests/normalized_joinir_min.rs b/tests/normalized_joinir_min.rs index 179b59a3..8daa6760 100644 --- a/tests/normalized_joinir_min.rs +++ b/tests/normalized_joinir_min.rs @@ -13,15 +13,15 @@ use nyash_rust::mir::join_ir::normalized::fixtures::{ build_jsonparser_skip_ws_real_structured_for_normalized_dev, build_jsonparser_skip_ws_structured_for_normalized_dev, build_jsonparser_unescape_string_step2_min_structured_for_normalized_dev, + build_parse_array_min_structured_for_normalized_dev, + build_parse_object_min_structured_for_normalized_dev, + build_parse_string_composite_min_structured_for_normalized_dev, build_pattern2_break_fixture_structured, build_pattern2_minimal_structured, build_pattern3_if_sum_min_structured_for_normalized_dev, build_pattern3_if_sum_multi_min_structured_for_normalized_dev, build_pattern3_json_if_sum_min_structured_for_normalized_dev, build_pattern4_continue_min_structured_for_normalized_dev, build_pattern_continue_return_min_structured_for_normalized_dev, - build_parse_string_composite_min_structured_for_normalized_dev, - build_parse_array_min_structured_for_normalized_dev, - build_parse_object_min_structured_for_normalized_dev, build_selfhost_args_parse_p2_structured_for_normalized_dev, build_selfhost_if_sum_p3_ext_structured_for_normalized_dev, build_selfhost_if_sum_p3_structured_for_normalized_dev, diff --git a/tests/normalized_joinir_min/shapes.rs b/tests/normalized_joinir_min/shapes.rs index 9958e1a0..de66c65a 100644 --- a/tests/normalized_joinir_min/shapes.rs +++ b/tests/normalized_joinir_min/shapes.rs @@ -366,7 +366,8 @@ fn test_phase88_jsonparser_unescape_string_step2_min_rejects_non_const_then_i_up assert!(res.is_err(), "expected fail-fast panic"); let msg = panic_message(res.err().unwrap()); assert!( - msg.contains("then' branch step increment") || msg.contains("then i update of form (i + const)"), + msg.contains("then' branch step increment") + || msg.contains("then i update of form (i + const)"), "unexpected panic message: {}", msg ); @@ -549,7 +550,10 @@ fn test_normalized_pattern_continue_return_min_vm_bridge_direct_matches_structur let base = run_joinir_vm_bridge(&structured, entry, &input, false); let dev = run_joinir_vm_bridge(&structured, entry, &input, true); - assert_eq!(base, dev, "vm bridge mismatch for pattern continue+return min"); + assert_eq!( + base, dev, + "vm bridge mismatch for pattern continue+return min" + ); } /// Phase 89 P1: Pattern Continue + Return minimal - expected output test @@ -580,7 +584,10 @@ fn test_parse_string_composite_min_vm_bridge_direct_matches_structured() { let base = run_joinir_vm_bridge(&structured, entry, &input, false); let dev = run_joinir_vm_bridge(&structured, entry, &input, true); - assert_eq!(base, dev, "vm bridge mismatch for parse_string composite min"); + assert_eq!( + base, dev, + "vm bridge mismatch for parse_string composite min" + ); } /// Phase 90 P0: Parse String Composite minimal - expected output test @@ -614,7 +621,11 @@ fn test_continue_return_multi_min_returns_null_at_first_match() { // Tests: // - Refactor-A: Null literal support (returns ConstValue::Null → JoinValue::Unit) // - Refactor-B: Multiple return-if with same value (i==3, i==7 both return null) - assert_eq!(result, JoinValue::Unit, "Expected Unit (null) from first return-if at i=3"); + assert_eq!( + result, + JoinValue::Unit, + "Expected Unit (null) from first return-if at i=3" + ); } /// Phase Next: Parse Array minimal - vm_bridge direct vs structured diff --git a/tests/phase72_phi_observation.rs b/tests/phase72_phi_observation.rs index 618d4da3..0690afc1 100644 --- a/tests/phase72_phi_observation.rs +++ b/tests/phase72_phi_observation.rs @@ -73,15 +73,12 @@ fn test_phase72_observe_phi_dst_via_builder() { eprintln!("{}", report.summary()); eprintln!(); eprintln!("Detailed breakdown:"); - eprintln!(" - Reserved region (0-99): {} PHI dsts", report.in_reserved); eprintln!( - " - Param region (100-999): {} PHI dsts", - report.in_param - ); - eprintln!( - " - Local region (1000+): {} PHI dsts", - report.in_local + " - Reserved region (0-99): {} PHI dsts", + report.in_reserved ); + eprintln!(" - Param region (100-999): {} PHI dsts", report.in_param); + eprintln!(" - Local region (1000+): {} PHI dsts", report.in_local); eprintln!(); if report.is_all_reserved() { @@ -89,9 +86,7 @@ fn test_phase72_observe_phi_dst_via_builder() { eprintln!(" → Safe to strengthen verifier with reserved region check"); } else { eprintln!("⚠️ CONCLUSION: Some PHI dsts are OUTSIDE reserved region"); - eprintln!( - " → PHI dst allocation does NOT respect reserved boundary" - ); + eprintln!(" → PHI dst allocation does NOT respect reserved boundary"); eprintln!(" → Document this finding and skip verifier strengthening"); if let (Some(min), Some(max)) = (report.min_val, report.max_val) {