feat(joinir): Phase 240-EX - Pattern2 header condition ExprLowerer integration

Implementation:
- Add make_pattern2_scope_manager() helper for DRY
- Header conditions use ExprLowerer for supported patterns
- Legacy fallback for unsupported patterns
- Fail-Fast on supported patterns that fail

Tests:
- 4 new tests (all pass)
- test_expr_lowerer_supports_simple_header_condition_i_less_literal
- test_expr_lowerer_supports_header_condition_var_less_var
- test_expr_lowerer_header_condition_generates_expected_instructions
- test_pattern2_header_condition_via_exprlowerer

Also: Archive old phase documentation (34k lines removed)

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
nyash-codex
2025-12-11 00:33:04 +09:00
parent 448bf3d8c5
commit a7dbc15878
116 changed files with 401 additions and 18 deletions

View File

@ -268,7 +268,8 @@ impl<'env, 'builder, S: ScopeManager> ExprLowerer<'env, 'builder, S> {
/// Check if an AST node is supported in condition context
///
/// Phase 231: Conservative whitelist. We only support patterns we know work.
fn is_supported_condition(ast: &ASTNode) -> bool {
/// Phase 240-EX: Made public to allow callers to check before attempting lowering.
pub fn is_supported_condition(ast: &ASTNode) -> bool {
match ast {
// Literals: Integer, Bool
ASTNode::Literal { .. } => true,
@ -727,4 +728,69 @@ mod tests {
"MethodCall should fail-fast with UnsupportedNode"
);
}
// Phase 240-EX: Header condition patterns
#[test]
fn test_expr_lowerer_supports_simple_header_condition_i_less_literal() {
// header pattern: i < 10
let ast = bin(BinaryOperator::Less, var("i"), lit_i(10));
assert!(
ExprLowerer::<Pattern2ScopeManager>::is_supported_condition(&ast),
"i < 10 should be supported for Pattern2 header condition"
);
// lower and verify success
let scope = make_basic_scope();
let mut builder = create_test_builder();
let mut lowerer = ExprLowerer::new(&scope, ExprContext::Condition, &mut builder);
let result = lowerer.lower(&ast);
assert!(result.is_ok(), "i < 10 should lower successfully");
// Compare instruction should be present
let instructions = lowerer.take_last_instructions();
assert_has_compare(&instructions);
}
#[test]
fn test_expr_lowerer_supports_header_condition_var_less_var() {
// header pattern: i < n (variable vs variable)
let ast = bin(BinaryOperator::Less, var("i"), var("j"));
assert!(
ExprLowerer::<Pattern2ScopeManager>::is_supported_condition(&ast),
"i < n should be supported for Pattern2 header condition"
);
// lower and verify success
let scope = make_basic_scope();
let mut builder = create_test_builder();
let mut lowerer = ExprLowerer::new(&scope, ExprContext::Condition, &mut builder);
let result = lowerer.lower(&ast);
assert!(result.is_ok(), "i < n should lower successfully");
// Compare instruction should be present
let instructions = lowerer.take_last_instructions();
assert_has_compare(&instructions);
}
#[test]
fn test_expr_lowerer_header_condition_generates_expected_instructions() {
// Test that header condition i < 10 generates proper Compare instruction
let scope = make_basic_scope();
let mut builder = create_test_builder();
let ast = bin(BinaryOperator::Less, var("i"), lit_i(10));
let mut lowerer = ExprLowerer::new(&scope, ExprContext::Condition, &mut builder);
let result = lowerer.lower(&ast);
assert!(result.is_ok());
let instructions = lowerer.take_last_instructions();
assert!(!instructions.is_empty(), "Should generate instructions");
// Should have Compare instruction
assert_has_compare(&instructions);
}
}