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",
))]

/// TDD Tests for Phase 3 Parameter Decorators
///
/// These tests verify manual override decorators:
/// - @str_ref forces &str (developer promises it's safe)
/// - @string_ref forces &String (conservative override)
#[path = "common/test_utils.rs"]
mod test_utils;

#[test]
fn test_str_ref_decorator_forces_str() {
    // TDD: @str_ref forces &str even if function uses Vec<String> methods
    // NOTE: This will cause rustc E0308, but that's the developer's responsibility
    let code = r#"
pub fn log(@str_ref msg: string) {
    println!("{}", msg)
}

fn main() {
    log("Hello")
}
"#;

    let generated = test_utils::compile_single_result(code).expect("Compilation failed");

    println!("Generated:\n{}", generated);

    // PHASE 3: @str_ref forces &str
    assert!(
        generated.contains("fn log(msg: &str)"),
        "Expected @str_ref to force &str parameter. Generated:\n{}",
        generated
    );

    // String literal should pass directly (no conversion)
    assert!(
        generated.contains(r#"log("Hello")"#),
        "Expected direct string literal with &str param. Generated:\n{}",
        generated
    );
}

#[test]
fn test_string_ref_decorator_forces_string() {
    // TDD: @string_ref forces &String even if auto-optimization would choose &str
    let code = r#"
pub fn log(@string_ref msg: string) {
    println!("{}", msg)
}

fn main() {
    log("Hello")
}
"#;

    let generated = test_utils::compile_single_result(code).expect("Compilation failed");

    println!("Generated:\n{}", generated);

    // PHASE 3: @string_ref forces &String
    assert!(
        generated.contains("fn log(msg: &String)"),
        "Expected @string_ref to force &String parameter. Generated:\n{}",
        generated
    );

    // String literal must be converted
    assert!(
        generated.contains(r#"log(&"Hello".to_string())"#),
        "Expected converted string literal with &String param. Generated:\n{}",
        generated
    );
}

#[test]
fn test_mixed_decorated_and_inferred_params() {
    // TDD: Mix of decorated and inferred parameters
    let code = r#"
pub fn process(@str_ref fast: string, @string_ref safe: string, inferred: string) {
    println!("{} {} {}", fast, safe, inferred)
}

fn main() {
    process("a", "b", "c")
}
"#;

    let generated = test_utils::compile_single_result(code).expect("Compilation failed");

    println!("Generated:\n{}", generated);

    // PHASE 3: Decorators override, inferred uses Phase 2 automatic optimization
    // With Phase 2 enabled globally, non-decorated params are optimized to &str when safe
    assert!(
        generated.contains("fn process(fast: &str, safe: &String, inferred: &str)"),
        "Expected mixed decorators: fast=&str (decorator), safe=&String (decorator), inferred=&str (Phase 2 auto-opt). Generated:\n{}",
        generated
    );
}

#[test]
fn test_decorator_overrides_automatic_analysis() {
    // TDD: @str_ref overrides automatic analysis even when it would choose &String
    // This test will be relevant when automatic analysis is fully implemented
    let code = r#"
struct Store {
    items: Vec<string>
}

impl Store {
    // Developer promises this is safe (maybe they know Vec methods aren't called)
    pub fn check(@str_ref item_id: string) -> bool {
        // In reality, if this calls self.items.contains(item_id), rustc will error
        // But that's the developer's responsibility when using @str_ref
        item_id.len() > 0
    }
}

fn main() {
    let store = Store { items: Vec::new() }
    let result = store.check("test")
    println!("{}", result)
}
"#;

    let generated = test_utils::compile_single_result(code).expect("Compilation failed");

    println!("Generated:\n{}", generated);

    // PHASE 3: @str_ref forces &str (even as static method)
    // Note: Method defined without self, so it's a static method
    assert!(
        generated.contains("fn check(item_id: &str)"),
        "Expected @str_ref to force &str in static method. Generated:\n{}",
        generated
    );
}