feat(joinir): Phase 183 LoopBodyLocal role separation + test fixes

Phase 183 Implementation:
- Added is_var_used_in_condition() helper for AST variable detection
- Implemented LoopBodyLocal filtering in TrimLoopLowerer
- Created 4 test files for P1/P2 patterns
- Added 5 unit tests for variable detection

Test Fixes:
- Fixed test_is_outer_scope_variable_pinned (BasicBlockId import)
- Fixed test_pattern2_accepts_loop_param_only (literal node usage)

Refactoring:
- Unified pattern detection documentation
- Consolidated CarrierInfo initialization
- Documented LoopScopeShape construction paths

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
nyash-codex
2025-12-08 23:43:26 +09:00
parent a3df5ecc7a
commit 440f8646b1
66 changed files with 279 additions and 183 deletions

View File

@ -547,7 +547,8 @@ mod tests {
fn test_filehandlebox_multiple_writes() {
init_test_provider();
let tmp_path = "/tmp/phase110_test_multiple_writes.txt";
// Use a dedicated path to avoid races with other write tests sharing the same file.
let tmp_path = "/tmp/phase110_test_multiple_writes_truncate.txt";
let mut h = FileHandleBox::new();
h.open(tmp_path, "w").expect("open");

View File

@ -93,7 +93,11 @@ impl FileBox {
use crate::providers::ring1::file::ring0_fs_fileio::Ring0FsFileIo;
let ring0 = get_global_ring0();
let provider: Arc<dyn FileIo> = Arc::new(Ring0FsFileIo::new(ring0));
// Default mode: writable (matches legacy FileBox semantics used by tests)
let ring0_io = Ring0FsFileIo::new(ring0);
ring0_io.set_mode("w".to_string());
let provider: Arc<dyn FileIo> = Arc::new(ring0_io);
provider
.open(path)
@ -226,7 +230,7 @@ impl std::fmt::Display for FileBox {
#[cfg(test)]
mod tests {
use super::*;
use crate::runtime::ring0::default_ring0;
use crate::runtime::ring0::{default_ring0, GLOBAL_RING0};
use crate::providers::ring1::file::ring0_fs_fileio::Ring0FsFileIo;
use std::fs;
use std::io::Write;
@ -242,15 +246,11 @@ mod tests {
/// Helper: Initialize FileBox provider for tests
fn init_test_provider() {
use crate::runtime::ring0::{get_global_ring0, init_global_ring0};
use std::sync::Once;
use crate::runtime::ring0::get_global_ring0;
static INIT: Once = Once::new();
INIT.call_once(|| {
let ring0 = default_ring0();
init_global_ring0(ring0);
});
// Use GLOBAL_RING0 as the single source of truth; avoid double-init panics when
// other tests already set up Ring0.
GLOBAL_RING0.get_or_init(|| Arc::new(default_ring0()));
// Get the initialized Ring0 context
let ring0_arc = get_global_ring0();