GitHub - cemreefe/dust: A programming language that compiles to Rust · GitHub
Skip to content

cemreefe/dust

Repository files navigation

Dust logo

Dust

A programming language that compiles to Rust. Python-influenced syntax, indentation-based blocks, smart ownership defaults.

struct Stack
  values: Vec<f64>

  fn push(self, n: f64)
    self.values.push(n)

  fn pop(self) -> Option<f64>
    self.values.pop()

fn main()
  mut stack = Stack()
  stack.push(3.0)
  stack.push(4.0)
  println!(stack.pop())

Install

Requires Rust / Cargo.

git clone https://github.com/cemreefe/dust
cd dust
cargo install --path .

Usage

dust run     hello.dust        # compile and run
dust compile hello.dust        # compile to binary
dust build   hello.dust        # emit hello.rs

vs Rust

Consistently ~20–45% less code across real programs, measured by lines, characters, and tokens:

Dust vs Rust comparison

Program Lines Chars Tokens
Shapes (enum) −26% −23% −23%
RPN calculator −31% −28% −22%
Word frequency −37% −28% −27%
Caesar cipher −18% −14% −9%
This comparison script −18% −12% −11%

Syntax

Variables

let x = compute()   # immutable by default
mut x = compute()   # explicitly mutable
const X: i32 = 1    # compile-time constant, requires type annotation

let is immutable and works for any value including runtime results. mut opts into mutability. const is for compile-time constants only.

Functions

fn add(a: i32, b: i32) -> i32
  a + b

All non-primitive params are auto-borrowed. Use keep to take ownership, mut for a mutable borrow:

fn consume(keep name: str)     # name: String      — owns the value
fn read(name: str)             # name: &str        — borrows (default)
fn update(mut f: Formatter)    # f: &mut Formatter — mutable borrow

Structs & Methods

struct Point
  x: f64
  y: f64

  fn distance(self) -> f64
    (self.x ** 2 + self.y ** 2).sqrt()

fn new is auto-generated from fields — Point(3.0, 4.0) just works.

Control Flow

if x > 0
  println!("positive")
elif x < 0
  println!("negative")
else
  println!("zero")

Inline form:

let label = if x > 0 then "pos" else "neg"

Match

match status
  "ok"  -> println!("good")
  "err" -> println!("bad")
  _     -> println!("unknown")

match result
  Ok(val)  -> val
  Err(_)   -> return "failed"

Loops

for item in collection
  println!(item)

for (key, val) in map
  println!("{key}: {val}")

for line in stdin.lock().lines()
  let line = line.unwrap!
  println!(line)

Operators

x++   x--          # increment / decrement
x += n   x -= n    # compound assign
x ||= y  x &&= y   # logical assign
x ** n              # power (x.powi(n) for int exponent, x.powf(n) for float)

Closures

items.map(x -> x * 2)
items.sort_by(a, b -> a.cmp(b))

Error handling

let val = risky().unwrap!      # .unwrap()
let val = risky()?             # propagate

String interpolation

Any expression works inside {}. Format specs are passed through:

println!("Hello, {name}!")
println!("result: {stack.pop()}")
println!("x squared: {x * x}")
println!("{name:<12} {score:>5}")

Casts & byte literals

let n = c as u8
let c = 65u8 as char
let byte = b'A'        # 65

Tuples

fn minmax(v: Vec<i32>) -> (i32, i32)
  ...

for (key, val) in map
  ...

let x = pair.0
let y = pair.1

let (x, y) = pair     # destructure
let x, y   = pair     # same

Ownership

fn consume(keep buf: Vec<u8>)   # takes ownership
fn read(data: str)              # borrows (&str, default)
fn update(mut f: Formatter)     # mutable borrow (&mut Formatter)

Enums

enum Shape
  Circle(f64)
  Rect(f64, f64)
  Point

Traits

Define a trait:

trait Animal
  fn sound(self) -> str
  fn name(self) -> str

Implement it with is:

struct Dog
  is Animal

  fn Animal.sound(self) -> str
    "woof"

  fn Animal.name(self) -> str
    "dog"

Implement stdlib traits the same way:

struct Point
  x: f64
  y: f64
  is Display

  fn Display.fmt(self, mut f: Formatter) -> Result
    write!(f, "({self.x}, {self.y})")

Examples

File Description
examples/hello.dust Hello world
examples/shapes.dust Shapes enum
examples/rpn.dust RPN calculator (stdin)
examples/caesar.dust Caesar cipher (stdin)
examples/wordfreq.dust Word frequency counter (stdin)
examples/compare.dust Dust vs Rust comparison script
examples/todo_server.dust HTTP todo server with web frontend

How it works

Dust is a source-to-source transpiler:

.dust → Lexer → Parser → Semantic pass → Emitter → .rs → rustc → binary
  • Lexer — indentation-aware (INDENT/DEDENT tokens), handles macros, char literals, byte literals, escape sequences
  • Parser — recursive descent, produces a typed AST
  • Semantic pass — auto-borrows params, infers mutability for let bindings, catches const mutation
  • Emitter — walks AST, emits Rust source

The output is valid Rust. You can inspect it with dust build.

About

A programming language that compiles to Rust

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

Contributors

Languages