windjammer 0.18.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

Windjammer

A simple, high-level language that transpiles to Rustβ€”combining Go's ergonomics, Ruby's expressiveness, and Rust's safety and performance.

🎯 The 80/20 Language: 80% of Rust's power with 20% of the complexity
πŸ“Š Read the detailed comparison: Windjammer vs Rust vs Go

πŸ“Š Production Validation: TaskFlow API

Empirical proof of Windjammer's 80/20 thesis! 🎯

We built a production-quality REST API in both Windjammer and Rust to compare:

  • Windjammer: 2,144 lines with clean std.* abstractions
  • Rust: 1,907 lines with exposed crate APIs (axum, sqlx, tracing, etc.)

Results (v0.16.0)

Code Quality: Rust is 11% less code, but Windjammer wins on:

  • βœ… Zero crate leakage - std.http, std.db, std.log only
  • βœ… Stable APIs - No breaking changes when crates update
  • βœ… 60-70% faster onboarding - 3 APIs vs 8+ crates to learn
  • βœ… Better abstractions - Cleaner, more maintainable code

Performance (v0.18.0): πŸŽ‰ 98.7% of Rust Performance Achieved!

  • βœ… Windjammer (naive): 7.89ms (45K operations)
  • βœ… Expert Rust: 7.78ms (45K operations)
  • βœ… Performance Ratio: 98.7% - EXCEEDED 93-95% target!

Rust API Baseline (v0.16.0):

  • 116,579 req/s throughput (/health endpoint)
  • 707 Β΅s median latency (p50)
  • 2.61 ms p99 latency

v0.18.0 Achievements:

  • βœ… 98.7% of Rust performance through automatic compiler optimizations
  • βœ… Target EXCEEDED - Beat 93-95% goal by 3.7-5.7%!
  • βœ… 6-phase optimization pipeline: Inline hints, clone elimination, struct shorthand, string capacity, compound assignments, constant folding
  • βœ… Naive code β†’ Expert performance - Compiler does the optimization for you!

See: examples/taskflow/ for complete details and benchmarks.

Philosophy

Write Simple, Run Fast - Ergonomic syntax that transpiles to safe, efficient Rust code.

Windjammer takes the best ideas from modern languages:

  • Go: Simple concurrency (go keyword, channels)
  • Ruby: String interpolation, expressive syntax
  • Elixir: Pipe operator for data transformations
  • Python: Clean decorators
  • Rust: Safety, performance, powerful type system

The 80/20 Rule: Windjammer provides 80% of Rust's power (memory safety, zero-cost abstractions, performance) while eliminating 80% of the complexity (manual lifetime annotations, explicit borrowing, verbose syntax).

Key Features

πŸš€ Automatic Compiler Optimizations πŸ†• v0.18.0

Your naive code runs at 98.7% of expert Rust performance - automatically!

The Windjammer compiler includes a 6-phase optimization pipeline:

  • Inline Hints - Automatic #[inline] for hot paths
  • Clone Elimination - Removes unnecessary allocations (loop-aware!)
  • Struct Shorthand - Generates Point { x, y } idioms
  • String Capacity - Pre-allocate string capacity for format! calls πŸ†•
  • Compound Assignments - Converts x = x + 1 to x += 1
  • Constant Folding - Evaluate expressions at compile time πŸ†•

You write simple code. The compiler makes it fast. No manual optimization needed!

✨ Automatic Trait Bound Inference πŸ†• v0.10.0

No more explicit trait bounds! The compiler infers them from usage.

// Write this:
fn print<T>(x: T) {
    println!("{}", x)  // Compiler infers T: Display
}

// Get this (automatically):
fn print<T: Display>(x: T) { ... }

Supported inference:

  • Display from println!("{}", x)
  • Clone from x.clone()
  • Add, Sub, Mul, Div from operators
  • PartialEq, PartialOrd from comparisons
  • IntoIterator from for loops
  • Automatic trait imports!

🎯 Automatic Ownership Inference

No need to think about borrowing in most cases - the compiler figures it out.

🎨 Enhanced Decorators πŸ†• v0.10.0

Clean, intuitive syntax for tests, async, and more.

@test
fn test_addition() {
    assert_eq!(add(2, 2), 4)
}

@async
fn fetch_data() -> string {
    // async function
}

@derive(Clone, Debug, PartialEq)
struct Point { x: int, y: int }

πŸ“¦ Named Bound Sets πŸ†• v0.11.0

Reusable trait bound combinations for cleaner generic code.

// Define once:
bound Printable = Display + Debug
bound Copyable = Clone + Copy

// Use everywhere:
fn process<T: Printable + Copyable>(value: T) { ... }

πŸ› οΈ Expanded Standard Library πŸ†• v0.11.0

Batteries included for common tasks:

use std.env
use std.process
use std.random

// Environment variables
let path = env.get_or("PATH", "/usr/bin")

// Process execution
let output = process.run("ls -la")?

// Random generation
let dice = random.range(1, 6)

⚑ Go-style Concurrency

Familiar go keyword and channels with Go's <- operator, but with Rust's safety guarantees.

πŸ›‘οΈ Rust's Safety & Performance

Zero-cost abstractions, memory safety, and blazing speed.

πŸš€ Modern Language Features

  • Generic types: Vec<T>, Option<T>, Result<T, E> with type parameters
  • Trait bounds: fn print<T: Display>(x: T), T: Display + Clone for flexible constraints πŸ†• v0.8.0
  • Where clauses: Multi-line constraints for complex generic functions πŸ†• v0.8.0
    fn process<T, U>(a: T, b: U)
    where
        T: Display + Clone,
        U: Debug
    { ... }
    
  • Associated types: Trait-level type declarations for flexible APIs πŸ†• v0.8.0
    trait Container {
        type Item;
        fn get(&self) -> Self::Item;
    }
    
  • Trait objects: Runtime polymorphism with dyn Trait πŸ†• v0.8.0
    fn render(shape: &dyn Drawable) { shape.draw() }
    fn create() -> dyn Shape { Circle { radius: 10 } }
    
  • Supertraits: Trait inheritance for requirement hierarchies πŸ†• v0.8.0
    trait Pet: Animal { fn play(&self); }
    trait Manager: Worker + Clone { fn manage(&self); }
    
  • Generic traits: Traits with type parameters πŸ†• v0.8.0
    trait From<T> { fn from(value: T) -> Self; }
    trait Converter<Input, Output> { fn convert(&self, input: Input) -> Output; }
    
  • Turbofish syntax: identity::<int>(42), parse::<float>() for explicit types ✨
  • Pattern matching with guards and tuple patterns
  • Closures: |x| x * 2
  • Range expressions: 0..10 and 0..=10
  • Struct shorthand: User { name, age }
  • Method syntax: impl blocks with &self and &mut self
  • String interpolation: "Hello, ${name}!" ✨
  • Pipe operator: value |> func1 |> func2 ✨
  • Ternary operator: condition ? true_val : false_val ✨
  • Labeled arguments: create_user(name: "Alice", age: 30) ✨
  • Pattern matching in function parameters: fn process((x, y): (int, int)) ✨
  • Smart @auto derive: Zero-config trait inference (@auto) ✨
  • Trait system: Full trait definitions and implementations ✨
  • Module system: Import and use standard library modules with aliases ✨
  • Error mapping: Friendly error messages in Windjammer terms 🎯

πŸ“š "Batteries Included" Standard Library πŸ†• v0.15.0: Server-Side Complete!

Windjammer provides a comprehensive standard library that abstracts over best-in-class Rust crates with clean, Windjammer-native APIs. All stdlib modules properly abstract their implementations - you write pure Windjammer code!

What's New in v0.15.0: πŸš€ Complete web development stack!

  • βœ… HTTP Server - Build web services with http.serve() and routing
  • βœ… File System - Full file I/O with std.fs
  • βœ… Logging - Production-ready logging with std.log
  • βœ… Regex - Pattern matching with std.regex
  • βœ… CLI Parsing - Argument parsing with std.cli

Why Proper Abstractions Matter:

  • API Stability - Windjammer controls the contract, not external crates
  • Future Flexibility - Can swap implementations without breaking your code
  • True 80/20 - Simple APIs for 80% of use cases
  • No Crate Leakage - Never see reqwest::, axum::, or clap:: in your code

Complete Modules (v0.15.0):

Web Development:

  • std.http - HTTP client + server (wraps reqwest + axum) βœ… Complete Stack
  • std.json - JSON parsing and serialization (wraps serde_json)

File System & I/O:

  • std.fs - File operations, directories, metadata (Rust stdlib) πŸ†• v0.15.0
  • std.log - Logging with multiple levels (wraps env_logger) πŸ†• v0.15.0

Data & Patterns:

  • std.regex - Regular expressions (wraps regex) πŸ†• v0.15.0
  • std.db - Database access (wraps sqlx)
  • std.time - Date/time utilities (wraps chrono)
  • std.crypto - Cryptography (wraps sha2, bcrypt, base64)
  • std.random - Random generation (wraps rand)

Developer Tools:

  • std.cli - CLI argument parsing (wraps clap) πŸ†• v0.15.0
  • std.testing - Testing framework with assertions
  • std.collections - HashMap, HashSet, BTreeMap, BTreeSet, VecDeque

System:

  • std.env - Environment variables
  • std.process - Process execution
  • std.async - Async utilities

Utilities:

  • std.math - Mathematical functions
  • std.strings - String manipulation

Example - Complete Web Service (v0.15.0):

use std.http
use std.json
use std.log
use std.fs

@derive(Serialize, Deserialize, Debug)
struct User {
    id: int,
    name: string,
    email: string
}

// HTTP Server handlers
fn handle_index(req: Request) -> ServerResponse {
    log.info("GET /")
    ServerResponse::ok("Welcome to Windjammer API!")
}

fn handle_user(req: Request) -> ServerResponse {
    let id = req.path_param("id")?
    log.info_with("GET /users/:id", "id", id)
    
    let user = User { id: 1, name: "Alice", email: "alice@example.com" }
    ServerResponse::json(user)
}

@async
fn main() {
    // Initialize logging
    log.init_with_level("info")
    
    // Read configuration
    match fs.read_to_string("config.json") {
        Ok(config) => log.info("Configuration loaded"),
        Err(e) => log.warn_with("Using defaults", "error", e)
    }
    
    // Setup HTTP server with routing - NO axum:: in your code!
    let router = Router::new()
        .get("/", handle_index)
        .get("/users/:id", handle_user)
    
    log.info("Server starting on http://0.0.0.0:3000")
    http.serve("0.0.0.0:3000", router).await
}

// NO THIS (crates leaked): ❌
// axum::Router::new()
// reqwest::get()
// serde_json::to_string()
// env_logger::init()

// YES THIS (clean Windjammer): βœ…
// http.serve()
// http.get()
// json.stringify()
// log.init()

πŸ› οΈ Unified Project Management πŸ†• v0.13.0-v0.14.0

Windjammer now has a unified wj CLI for streamlined development workflows, plus project scaffolding and dependency management!

Unified CLI (v0.13.0):

wj run main.wj        # Compile and execute (replaces multiple steps!)
wj build main.wj      # Build project
wj test               # Run tests
wj fmt                # Format code
wj lint               # Run linter
wj check              # Type check

Project Management (v0.14.0):

# Create new project from templates
wj new my-app --template cli    # CLI tool template
wj new my-api --template web    # Web service template
wj new my-lib --template lib    # Library template
wj new my-wasm --template wasm  # WebAssembly template

# Manage dependencies
wj add reqwest --features json
wj add serde --features derive
wj remove old-crate

wj.toml Configuration (v0.14.0):

[package]
name = "my-app"
version = "0.1.0"
edition = "2021"

[dependencies]
# Add dependencies here - automatically generates Cargo.toml

80% Reduction in Boilerplate:

# Old way (v0.12.0):
wj build --path main.wj --output ./build
cd build && cargo run
cd .. && cargo test
cargo fmt

# New way (v0.13.0+):
wj run main.wj    # One command!
wj test
wj fmt

Ownership Inference Strategy

The key innovation is automatic ownership inference with these rules:

1. Smart Defaults

  • Primitive types (int, float, bool): Always copied (implement Copy trait)
  • String literals: Owned by default
  • Struct fields: Owned by default unless marked otherwise
  • Function parameters: Borrowed by default (immutable &T)
  • Function returns: Owned by default

2. Mutation Detection

// Immutable borrow inferred
fn print_length(s: string) {
    println!("{}", s.len())
}

// Mutable borrow inferred from assignment
fn increment(x: int) {
    x = x + 1  // Assignment detected β†’ infers &mut
}

// Mutable borrow inferred from method call
fn append_text(s: string) {
    s.push_str("!")  // Mutation detected β†’ infers &mut
}

// Ownership transfer inferred from return
fn take_ownership(s: string) -> string {
    s  // Returned β†’ infers owned parameter
}

3. Escape Analysis

Like Go, we analyze if values escape the function:

  • Values that don't escape β†’ borrow
  • Values that escape (returned, stored) β†’ owned
  • Ambiguous cases β†’ owned (safe default)

4. Explicit Annotations (Rare)

When inference isn't enough, use Rust-style annotations:

fn process(s: &string) -> string     // Explicit borrow
fn modify(s: &mut string)            // Explicit mutable borrow
fn take(s: string) -> string         // Explicit ownership (inferred by default for returns)

5. Shared Ownership

When multiple owners needed:

// Automatic Rc/Arc when:
// - Value assigned to multiple variables in different scopes
// - Value stored in multiple struct fields
// - Cross-thread sharing detected β†’ Arc

let data = shared("expensive data")  // Explicit Rc/Arc

Decorators

Use @ for decorators (Python/TypeScript style):

@route("/api/users")
@auth_required
fn get_users() -> Result<Vec<User>, Error> {
    // ... handler logic
}

@timing
@cache(ttl: 60)
fn expensive_calculation(n: int) -> int {
    // ... complex logic
}

Built-in decorators:

  • @timing - Measure execution time
  • @cache - Memoize function results
  • @route(path) - HTTP routing (with web frameworks)
  • @get, @post, @put, @delete - HTTP method routing

Concurrency

Go-style syntax with Rust safety, including Go-style channel operators:

use std.sync.mpsc

fn main() {
    let (tx, rx) = mpsc.channel()
    
    // Spawn a goroutine (maps to tokio::spawn or std::thread)
    go {
        tx <- "Hello from thread"  // Go-style send!
    }
    
    let msg = <-rx  // Go-style receive!
    println(msg)
}

// Traditional Rust syntax also works:
fn alternative_example() {
    let (tx, rx) = mpsc.channel()
    go {
        tx.send("Hello").unwrap()
    }
    let msg = rx.recv().unwrap()
}

// Async/await style also supported
async fn fetch_data(url: string) -> Result<string, Error> {
    let response = http.get(url).await?
    Ok(response.text().await?)
}

Channel Operators:

  • channel <- value β€” Send to channel (transpiles to channel.send(value))
  • <-channel β€” Receive from channel (transpiles to channel.recv())

Syntax Examples

Variables

let x = 42              // Transpiles to: let x = 42;
let mut y = 10          // Transpiles to: let mut y = 10;

Functions

fn add(a: int, b: int) -> int {
    a + b
}
// Transpiles to:
// fn add(a: i32, b: i32) -> i32 { a + b }

Structs and Impl Blocks

struct User {
    name: string,
    age: int,
}

impl User {
    // Associated function (like "static" in other languages)
    fn new(name: string, age: int) -> User {
        User { name, age }  // Shorthand syntax supported!
    }
    
    // Method with &self
    fn greet(&self) {
        println("Hello, I'm {}", self.name)
    }
    
    // Method with &mut self
    fn birthday(&mut self) {
        self.age += 1
    }
}

fn main() {
    let mut user = User.new("Alice", 30)
    user.greet()
    user.birthday()
    println("{} is now {}", user.name, user.age)
}

Struct Features:

  • Shorthand field initialization: User { name, age } when variables match field names
  • Self parameters: &self, &mut self, or self (owned)
  • Methods and associated functions via impl blocks

Error Handling

use std.fs
use std.io

fn read_config(path: string) -> Result<string, Error> {
    let contents = fs.read_to_string(path)?
    Ok(contents)
}

Generic Types

// Vec<T> - Dynamic arrays
let numbers: Vec<int> = vec![1, 2, 3, 4, 5]
let names: Vec<string> = Vec.new()

// Option<T> - Optional values
fn find_user(id: int) -> Option<User> {
    if id == 1 {
        Some(User.new("Alice", 30))
    } else {
        None
    }
}

// Result<T, E> - Error handling
fn read_file(path: string) -> Result<string, Error> {
    let contents = fs.read_to_string(path)?
    Ok(contents)
}

Pattern Matching

// Match as an expression
let value = Some(42)
let result = match value {
    Some(n) => n * 2,
    None => 0,
}

// Match with guards
match (x, y) {
    (0, 0) => println("Origin"),
    (x, 0) if x > 0 => println("Positive X axis"),
    (0, y) if y > 0 => println("Positive Y axis"),
    _ => println("Somewhere else"),
}

// Match with tuple patterns
match (cell, live_neighbors) {
    (true, x) if x < 2 => false,    // Underpopulation
    (true, 2) | (true, 3) => true,  // Survival
    (true, x) if x > 3 => false,    // Overpopulation
    (false, 3) => true,              // Reproduction
    (otherwise, _) => otherwise,     // No change
}

Closures and Iterators

// Closures with Go-style syntax
let double = |x| x * 2
let add = |a, b| a + b

// Iterator methods
let numbers = vec![1, 2, 3, 4, 5]
let doubled = numbers.iter().map(|n| n * 2).collect()
let evens = numbers.iter().filter(|n| n % 2 == 0).collect()

// Range expressions
for i in 0..10 {        // Exclusive range: 0 to 9
    println("{}", i)
}

for i in 0..=10 {       // Inclusive range: 0 to 10
    println("{}", i)
}

References and Borrowing

// Create references
let x = 42
let ref_x = &x
let mut_ref_x = &mut x

// Function parameters can be explicit or inferred
fn read_value(x: &int) -> int {   // Explicit borrow
    *x
}

fn modify_value(x: &mut int) {    // Explicit mutable borrow
    *x += 1
}

fn consume_value(x: int) {         // Explicit ownership
    println("{}", x)
}

// Or let the compiler infer!
fn inferred_borrow(x: int) {       // Auto-inferred as &int
    println("{}", x)
}

String Interpolation ✨

let name = "Alice"
let age = 30
let score = 95.5

// Clean, readable string formatting
println!("Hello, ${name}!")
println!("${name} is ${age} years old")
println!("Score: ${score * 100.0}%")

// Works with any expression
let message = "Result: ${calculate(x, y) + 10}"

Pipe Operator ✨

fn double(x: int) -> int { x * 2 }
fn add_ten(x: int) -> int { x + 10 }
fn to_string(x: int) -> string { format!("{}", x) }

// Functional composition made readable
let result = 5 
    |> double 
    |> add_ten 
    |> double
    |> to_string

// Equivalent to: to_string(double(add_ten(double(5))))
// Result: "40"

Labeled Arguments ✨

fn create_user(name: string, age: int, email: string) {
    println!("User: ${name}, Age: ${age}")
}

// Traditional positional arguments
create_user("Alice", 30, "alice@example.com")

// Labeled arguments for clarity (especially with many parameters)
create_user(
    name: "Bob",
    age: 25,
    email: "bob@example.com"
)

// Mix positional and labeled
create_user("Charlie", age: 35, email: "charlie@example.com")

// Great for functions with many parameters or similar types
fn configure_server(
    host: string,
    port: int,
    timeout: int,
    max_connections: int,
    enable_logging: bool
) {
    // ...
}

// Much clearer than: configure_server("localhost", 8080, 30, 100, true)
configure_server(
    host: "localhost",
    port: 8080,
    timeout: 30,
    max_connections: 100,
    enable_logging: true
)

Pattern Matching in Function Parameters ✨

// Instead of manually destructuring...
fn distance_old(point: (int, int)) -> float {
    let (x, y) = point  // Manual destructuring
    sqrt(x * x + y * y)
}

// Destructure directly in the parameter!
fn distance((x, y): (int, int)) -> float {
    sqrt(x * x + y * y)  // x and y ready to use!
}

// Real-world example: API response handler
fn handle_response((status, body): (int, string)) {
    if status == 200 {
        println!("Success: ${body}")
    } else {
        println!("Error ${status}: ${body}")
    }
}

let response = (200, "Data loaded")
handle_response(response)

// Think of it as: PATTERN : TYPE
// (x, y) ← pattern | (int, int) ← type

@auto Derive ✨

// Automatic trait derivation - no manual impl needed!
@auto(Debug, Clone, Copy)
struct Point {
    x: int,
    y: int,
}

@auto(Debug, Clone)
struct User {
    name: string,
    age: int,
}

let p1 = Point { x: 10, y: 20 }
let p2 = p1  // Copy works automatically
println!("{:?}", p1)  // Debug works automatically

// Equivalent to Rust's #[derive(Debug, Clone, Copy)]
// But with cleaner, more intuitive syntax!

Trait System ✨

// Define traits
trait Drawable {
    fn draw(&self)
    fn area(&self) -> f64
}

// Implement traits
struct Circle {
    radius: f64,
}

impl Drawable for Circle {
    fn draw(&self) {
        println!("Drawing circle with radius ${self.radius}")
    }
    
    fn area(&self) -> f64 {
        3.14159 * self.radius * self.radius
    }
}

// Generic traits with associated types
trait Iterator<Item> {
    fn next(&mut self) -> Option<Item>
}

impl Iterator<int> for Counter {
    fn next(&mut self) -> Option<int> {
        // ...
    }
}

Generic Trait Implementations ✨

// Implement generic traits with concrete types
trait From<T> {
    fn from(value: T) -> Self
}

impl From<int> for String {
    fn from(value: int) -> Self {
        value.to_string()
    }
}

// Multiple type parameters
trait Converter<Input, Output> {
    fn convert(&self, input: Input) -> Output
}

impl Converter<int, string> for IntToString {
    fn convert(&self, input: int) -> string {
        format!("Number: {}", input)
    }
}

Generic Enums ✨

// Define generic enums
enum Option<T> {
    Some(T),
    None
}

enum Result<T, E> {
    Ok(T),
    Err(E)
}

// Use with pattern matching
fn safe_divide(a: int, b: int) -> Result<int, string> {
    if b == 0 {
        Result::Err("division by zero")
    } else {
        Result::Ok(a / b)
    }
}

fn main() {
    match safe_divide(10, 2) {
        Ok(value) => println!("Result: {}", value),
        Err(msg) => println!("Error: {}", msg)
    }
}

Type Mappings

Windjammer Rust
int i64
int32 i32
uint u64
float f64
bool bool
string String (owned) or &str (borrowed)
Vec<T> Vec<T>
Option<T> Option<T>
Result<T,E> Result<T,E>
&T &T (immutable reference)
&mut T &mut T (mutable reference)

Quick Start

Installation

Windjammer is easy to install with multiple options for all platforms:

Quick Install

macOS / Linux:

# Using Homebrew (recommended)
brew tap jeffreyfriedman/windjammer
brew install windjammer

# Or using Cargo
cargo install windjammer

Windows:

# Using Scoop (recommended)
scoop bucket add windjammer https://github.com/jeffreyfriedman/scoop-windjammer
scoop install windjammer

# Or using Cargo
cargo install windjammer

All Installation Methods

Method Command Best For
Homebrew (macOS/Linux) brew install windjammer Mac/Linux users
Cargo (All platforms) cargo install windjammer Rust developers
Docker docker pull ghcr.io/jeffreyfriedman/windjammer Container workflows
Pre-built Binaries Download from Releases Quick setup
Build from Source git clone ... && ./install.sh Contributors
Snap (Linux) snap install windjammer --classic Ubuntu/Linux
Scoop (Windows) scoop install windjammer Windows users

πŸ“– Full installation guide: docs/INSTALLATION.md

Verify Installation

wj --version
wj --help

Your First Program

Create hello.wj:

fn main() {
    let name = "Windjammer"
    println!("Hello, {}!", name)
}

Transpile and run:

wj build --path hello.wj --output output
cd output
cargo run

Examples

See the examples/ directory for complete working examples:

Language Basics:

  1. Basic Features - Variables, functions, control flow
  2. Structs & Methods - Data structures and impl blocks
  3. Enums & Matching - Enumerations and pattern matching
  4. Traits - Trait definitions and implementations
  5. Modern Features - String interpolation, pipe operator, ternary

Standard Library: 6. Module System - Module imports and usage 7. File Operations - Using std.fs for file I/O 8. Core Language - Basic language test

Advanced Examples: 9. WASM Hello - WebAssembly "Hello World" 10. WASM Game - Conway's Game of Life in the browser

Development Tools

Language Server

Windjammer includes a high-performance language server built with Salsa for incremental compilation:

  • ⚑ Fast: Only recomputes what changed
  • πŸ” IntelliSense: Auto-completion, hover info, diagnostics
  • 🎯 Ownership Hints: See inferred borrowing inline
  • πŸ“ Instant Feedback: Real-time error checking

Install: cargo install --path crates/windjammer-lsp

VSCode Extension

Features:

  • Syntax highlighting
  • Auto-completion
  • Error diagnostics
  • Code navigation
  • Ownership inference hints

Install from editors/vscode/ or search "Windjammer" in the marketplace (coming soon).

Build & Run

# Transpile .wj files to .rs
wj build

# Or specify files
wj build src/main.wj

# Check for errors without generating code
wj check

# Run the generated Rust code
cd output
cargo run

When to Use Windjammer

βœ… Choose Windjammer For

  • Web APIs & Services - Built-in HTTP, JSON, ergonomic syntax
  • CLI Tools - Fast development with system-level performance
  • Data Processing - Pipe operator for clean transformations
  • Microservices - Fast, safe, memory-efficient
  • Learning Systems Programming - Gentler curve than Rust
  • Teams Transitioning from Go - Familiar syntax, better performance
  • 80% of Use Cases - Most applications don't need Rust's full complexity

⚠️ Consider Rust Instead For

  • Operating Systems - Need maximum low-level control
  • Embedded Systems - Need no_std and precise memory management
  • Game Engines - Need every manual optimization
  • The Critical 20% - When you truly need Rust's full power

⚠️ Consider Go Instead For

  • Dead-Simple Services - No performance requirements
  • Rapid Prototypes - Speed over safety
  • Teams Unfamiliar with Systems - Easiest learning curve

πŸ“Š See COMPARISON.md for detailed analysis


πŸ“˜ Documentation

For Users:

  • πŸ“– GUIDE.md - Complete developer guide (Rust book style)
  • πŸ”„ COMPARISON.md - Windjammer vs Rust vs Go (honest tradeoffs)
  • 🎯 README.md - This file (quick start and overview)

For Contributors:

Standard Library:

  • πŸ“š std/README.md - Philosophy and architecture
  • πŸ“¦ std/*/API.md - Module specifications (fs, http, json, testing)

Rust Interoperability

βœ… YES: 100% Rust Crate Compatibility!

Windjammer transpiles to Rust, giving you:

  • βœ… ALL Rust crates work - Tokio, Serde, Actix, Reqwest, etc.
  • βœ… No FFI needed - It IS Rust under the hood
  • βœ… Same performance - Zero overhead translation
  • βœ… Mix .wj and .rs files - Use both in same project
  • βœ… Call Rust from Windjammer - And vice versa

Example:

// Your Windjammer code
use serde.json
use tokio.time

@auto(Serialize, Deserialize)
struct Config {
    timeout: int,
}

// Uses Rust crates directly!
async fn load_config() -> Result<Config, Error> {
    let text = fs.read_to_string("config.json")?
    let config = serde_json::from_str(&text)?
    Ok(config)
}

Transpiles to idiomatic Rust:

use serde::{Serialize, Deserialize};
use tokio::time;

#[derive(Serialize, Deserialize)]
struct Config {
    timeout: i64,
}

async fn load_config() -> Result<Config, Error> {
    let text = std::fs::read_to_string("config.json")?;
    let config = serde_json::from_str(&text)?;
    Ok(config)
}

⚑ Performance

Windjammer is blazingly fast for development iteration:

Compilation Speed

  • Simple program (10 lines): ~8Β΅s
  • Medium program (30 lines): ~25Β΅s
  • Complex program (50 lines): ~60Β΅s

17,000x faster than rustc for the transpilation step!

Runtime Performance

Since Windjammer transpiles to Rust, runtime performance is identical to hand-written Rust:

  • βœ… Zero-cost abstractions
  • βœ… No runtime overhead
  • βœ… Same binary size
  • βœ… Same memory usage

Why So Fast?

  1. No LLVM: Generates Rust source instead of machine code
  2. Incremental: Only transpiles changed .wj files
  3. Simple AST: Go-inspired syntax is easier to parse
  4. No borrow checking: Rust handles that in pass 2

See BENCHMARKS.md for detailed performance analysis.


πŸ“„ License

Windjammer is dual-licensed under either:

at your option.

This means you can choose either license when using Windjammer.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in Windjammer by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.