Files
hakorune/tests/phase246_json_atoi.rs
nyash-codex eb00d97fdb feat(joinir): Phase 246-EX Part 2 - Exit PHI & step scheduling fixes
Phase 246-EX Part 2 completes the _atoi JoinIR integration:

Key fixes:
- Exit PHI connection: ExitLineReconnector now correctly uses exit PHI dsts
- Jump args preservation: BasicBlock.jump_args field stores JoinIR exit values
- instruction_rewriter: Reads jump_args, remaps JoinIR→HOST values by carrier order
- step_schedule.rs: New module for body-local init step ordering

Files changed:
- reconnector.rs: Exit PHI connection improvements
- instruction_rewriter.rs: Jump args reading & carrier value mapping
- loop_with_break_minimal.rs: Refactored step scheduling
- step_schedule.rs: NEW - Step ordering logic extracted

Tests: 931/931 PASS (no regression)

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-11 17:16:10 +09:00

143 lines
3.7 KiB
Rust

//! Phase 246-EX Step 5: E2E tests for JsonParser _atoi JoinIR integration
//!
//! Tests the complete _atoi loop lowering using Pattern 2 (Break) + NumberAccumulation.
//!
//! Test cases cover:
//! - Single digit zero: "0" → 0
//! - Two digits: "42" → 42
//! - Multiple digits: "123" → 123
//! - Leading zeros: "007" → 7
//! - Break at non-digit: "123abc" → 123
//! - Immediate break (no digits): "abc" → 0
use std::fs;
use std::process::Command;
/// Helper function to run _atoi implementation via hakorune binary
fn run_atoi_test(input: &str, expected: i64, test_name: &str) {
let code = format!(
r#"
static box Main {{
main() {{
local result = me._atoi("{}", {})
print(result)
return result
}}
method _atoi(s, len) {{
local result = 0
local digits = "0123456789"
local i = 0
loop(i < len) {{
local ch = s.substring(i, i + 1)
local digit_pos = digits.indexOf(ch)
if digit_pos < 0 {{ break }}
result = result * 10 + digit_pos
i = i + 1
}}
return result
}}
}}
"#,
input,
input.len()
);
// Write test file
let test_file = format!("local_tests/phase246_atoi_{}.hako", test_name);
fs::write(&test_file, &code).expect("Failed to write test file");
// Run hakorune
let bin = env!("CARGO_BIN_EXE_hakorune");
let output = Command::new(bin)
.arg("--backend")
.arg("vm")
.arg(&test_file)
.env("NYASH_JOINIR_CORE", "1")
.env("NYASH_DISABLE_PLUGINS", "1")
.output()
.expect("Failed to run hakorune");
// Clean up test file
let _ = fs::remove_file(&test_file);
// Accept non-zero exit codes (program returns parsed value as exit code). Only fail on signal.
if output.status.code().is_none() {
panic!(
"[phase246/atoi/{}] Test failed (terminated by signal?):\nstdout: {}\nstderr: {}",
test_name,
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr),
);
}
// Verify output
let stdout = String::from_utf8_lossy(&output.stdout);
let output_value: i64 = stdout
.trim()
.parse()
.unwrap_or_else(|_| panic!("Failed to parse output '{}' as integer", stdout.trim()));
assert_eq!(
output_value, expected,
"Failed for input '{}': expected {}, got {}",
input, expected, output_value
);
}
#[test]
fn test_atoi_single_digit_zero() {
// Phase 246-EX: Test case "0" → 0
run_atoi_test("0", 0, "zero");
}
#[test]
fn test_atoi_two_digits() {
// Phase 246-EX: Test case "42" → 42
run_atoi_test("42", 42, "two_digits");
}
#[test]
fn test_atoi_multiple_digits() {
// Phase 246-EX: Test case "123" → 123
run_atoi_test("123", 123, "multiple_digits");
}
#[test]
fn test_atoi_leading_zeros() {
// Phase 246-EX: Test case "007" → 7
run_atoi_test("007", 7, "leading_zeros");
}
#[test]
fn test_atoi_break_at_non_digit() {
// Phase 246-EX: Test case "123abc" → 123 (break at 'a')
run_atoi_test("123abc", 123, "break_non_digit");
}
#[test]
fn test_atoi_immediate_break_no_digits() {
// Phase 246-EX: Test case "abc" → 0 (immediate break, no digits parsed)
run_atoi_test("abc", 0, "immediate_break");
}
#[test]
fn test_atoi_empty_string() {
// Phase 246-EX: Test case "" → 0 (empty string, no iterations)
run_atoi_test("", 0, "empty");
}
#[test]
fn test_atoi_single_digit_nine() {
// Phase 246-EX: Additional test case "9" → 9 (max single digit)
run_atoi_test("9", 9, "nine");
}
#[test]
fn test_atoi_large_number() {
// Phase 246-EX: Test case "999999" → 999999 (large number)
run_atoi_test("999999", 999999, "large");
}