Hello World

Every RustScript program starts with a main function in src/main.rts.

Create a project

rustscript init hello
cd hello

This gives you:

hello/
  rustscript.json
  Cargo.toml
  .gitignore
  src/
    main.rts

Write your first program

Open src/main.rts and replace its contents:

function main() {
  console.log("Hello from RustScript!");
}

Run it

rustscript run

Output:

Hello from RustScript!

What just happened

The compiler:

  1. Parsed main.rts into a RustScript AST
  2. Type-checked the program
  3. Lowered the AST to Rust IR
  4. Emitted a .rs file in-place next to main.rts
  5. Ran cargo build on the generated Rust project
  6. Executed the resulting native binary

The generated Rust looks like this:

fn main() {
    println!("{}", "Hello from RustScript!");
}

No V8. No garbage collector. You just compiled TypeScript syntax to a native binary.

A slightly bigger example

function greet(name: string): string {
  return `Hello, ${name}!`;
}

function main() {
  const names: Array<string> = ["Alice", "Bob", "Charlie"];

  for (const name of names) {
    console.log(greet(name));
  }

  console.log(`Greeted ${names.length} people`);
}
rustscript run
Hello, Alice!
Hello, Bob!
Hello, Charlie!
Greeted 3 people

Template literals, typed arrays, for-of loops, and string interpolation -- all compiling to idiomatic Rust.

Async main

If your program needs async (HTTP servers, network calls, timers), make main async:

async function main() {
  console.log("Starting...");
  // async operations work here
}

The compiler adds #[tokio::main] to the generated Rust, giving you the tokio async runtime.

Next steps