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 Test: Struct field (owned String) auto-borrow when passed to methods expecting &String
// Reproduces E0308 error in dialog.wj line 238 (line 212 in generated code)

#[path = "common/test_utils.rs"]
mod test_utils;

use std::fs;
use std::process::Command;
use tempfile::tempdir;

fn verify_with_rustc(rust_code: &str) {
    let dir = tempdir().expect("tempdir for rustc");
    let rs_file = dir.path().join("verify.rs");
    fs::write(&rs_file, rust_code).expect("write .rs for rustc");
    let output = Command::new("rustc")
        .arg("--edition=2021")
        .arg("--crate-type=lib")
        .arg("--emit=metadata")
        .arg("--out-dir")
        .arg(dir.path())
        .arg("-o")
        .arg(dir.path().join("verify.rmeta"))
        .arg(&rs_file)
        .output()
        .expect("failed to run rustc");
    assert!(
        output.status.success(),
        "Generated code should compile. Error:\n{}\n\nGenerated:\n{}",
        String::from_utf8_lossy(&output.stderr),
        rust_code
    );
}

#[test]
fn test_struct_field_string_auto_borrow() {
    let code = r#"
struct Player {
    name: string,
}

impl Player {
    // Avoid string == literal in body: current codegen can emit `*attr_name == "strength"`
    // which is invalid Rust; this test targets auto-borrow at the call site only.
    pub fn get_attribute(self, attr_name: string) -> i32 {
        if attr_name.len() > 0 {
            10
        } else {
            0
        }
    }
}

struct StatCheck {
    stat_name: string,
    required_value: i32,
}

impl StatCheck {
    pub fn passes(self, player: Player) -> bool {
        player.get_attribute(self.stat_name) >= self.required_value
    }
}
"#;

    let generated = test_utils::compile_single(code);

    assert!(
        generated.contains("player.get_attribute(&self.stat_name)")
            || generated.contains("player.get_attribute(&*self.stat_name)")
            || generated.contains("player.get_attribute(self.stat_name)"),
        "Should pass stat_name to get_attribute. Generated:\n{}",
        generated
    );

    verify_with_rustc(&generated);
}

#[test]
fn test_struct_field_in_comparison() {
    let code = r#"
struct Config {
    max_health: i32,
}

impl Config {
    pub fn is_valid(self, health: i32) -> bool {
        health <= self.max_health
    }
}
"#;

    let generated = test_utils::compile_single(code);

    assert!(
        generated.contains("health <= self.max_health"),
        "Should generate comparison with struct field. Generated:\n{}",
        generated
    );

    verify_with_rustc(&generated);
}