windjammer 0.48.0

A simple language inspired by Go, Ruby, and Elixir that transpiles to Rust - 80% of Rust's power with 20% of the complexity
Documentation
#![cfg(any(
    not(any(
        feature = "parser_tests",
        feature = "analyzer_tests",
        feature = "codegen_tests",
        feature = "interpreter_tests",
        feature = "conformance_tests",
        feature = "integration_tests",
    )),
    feature = "analyzer_tests",
))]

/// Bug #13: Early return statement parsing
///
/// When a function has an early return followed by other statements,
/// the parser fails with "Unexpected token: Semicolon"
///
/// This is a common pattern in Rust for guard clauses and error handling.
#[path = "common/test_utils.rs"]
mod test_utils;

#[cfg_attr(tarpaulin, ignore)]
#[test]
fn test_early_return_with_subsequent_statements() {
    let code = r#"
pub fn check_positive(x: i32) -> bool {
    if x < 0 {
        return false;
    }
    
    // Should be able to continue after early return
    println!("x is positive: {}", x);
    true
}
"#;

    let result = test_utils::compile_single_result(code);
    assert!(
        result.is_ok(),
        "Early return with subsequent statements should compile. Error: {:?}",
        result.err()
    );
}

#[cfg_attr(tarpaulin, ignore)]
#[test]
fn test_multiple_early_returns() {
    let code = r#"
pub fn classify(x: i32) -> string {
    if x < 0 {
        return "negative";
    }
    
    if x == 0 {
        return "zero";
    }
    
    "positive"
}
"#;

    let result = test_utils::compile_single_result(code);
    assert!(
        result.is_ok(),
        "Multiple early returns should compile. Error: {:?}",
        result.err()
    );
}

#[cfg_attr(tarpaulin, ignore)]
#[test]
fn test_early_return_in_nested_blocks() {
    let code = r#"
pub fn validate(x: i32, y: i32) -> bool {
    if x < 0 {
        if y < 0 {
            return false;
        }
        return true;
    }
    
    x + y > 0
}
"#;

    let result = test_utils::compile_single_result(code);
    assert!(
        result.is_ok(),
        "Early returns in nested blocks should compile. Error: {:?}",
        result.err()
    );
}

#[cfg_attr(tarpaulin, ignore)]
#[test]
fn test_early_return_with_variable_assignment() {
    let code = r#"
pub fn compute(x: i32) -> i32 {
    if x < 0 {
        return 0;
    }
    
    let result = x * 2;
    result + 1
}
"#;

    let result = test_utils::compile_single_result(code);
    assert!(
        result.is_ok(),
        "Early return followed by variable assignment should compile. Error: {:?}",
        result.err()
    );
}

#[cfg_attr(tarpaulin, ignore)]
#[test]
fn test_early_return_in_match_arm() {
    let code = r#"
pub fn handle(x: Option<i32>) -> i32 {
    match x {
        Some(val) => {
            if val < 0 {
                return 0;
            }
            val * 2
        }
        None => 0,
    }
}
"#;

    let result = test_utils::compile_single_result(code);
    assert!(
        result.is_ok(),
        "Early return in match arm should compile. Error: {:?}",
        result.err()
    );
}

#[cfg_attr(tarpaulin, ignore)]
#[test]
fn test_early_return_in_loop() {
    let code = r#"
pub fn find_first_positive(nums: Vec<i32>) -> Option<i32> {
    for num in nums {
        if num > 0 {
            return Some(num);
        }
    }
    None
}
"#;

    let result = test_utils::compile_single_result(code);
    assert!(
        result.is_ok(),
        "Early return in loop should compile. Error: {:?}",
        result.err()
    );
}

#[cfg_attr(tarpaulin, ignore)]
#[test]
fn test_early_return_with_method_call() {
    let code = r#"
pub struct Data {
    value: i32,
}

impl Data {
    pub fn process(self) -> i32 {
        if self.value < 0 {
            return 0;
        }
        
        self.value * 2
    }
}
"#;

    let result = test_utils::compile_single_result(code);
    assert!(
        result.is_ok(),
        "Early return in method should compile. Error: {:?}",
        result.err()
    );
}

#[cfg_attr(tarpaulin, ignore)]
#[test]
fn test_voxel_bounds_check_pattern() {
    // This is the exact pattern we hit in voxel_chunk.wj
    let code = r#"
use std::collections::HashMap;

pub struct VoxelChunk {
    size: i32,
    data: HashMap<(i32, i32, i32), i32>,
}

impl VoxelChunk {
    pub fn set_voxel(self, x: i32, y: i32, z: i32, value: i32) {
        if x < 0 || x >= self.size || y < 0 || y >= self.size || z < 0 || z >= self.size {
            return;
        }
        
        self.data.insert((x, y, z), value);
    }
}
"#;

    let result = test_utils::compile_single_result(code);
    assert!(
        result.is_ok(),
        "Voxel bounds check pattern should compile. Error: {:?}",
        result.err()
    );
}