## Overview
`cl-rust-generator` is a Common Lisp metaprogramming system that generates Rust source code from S-expressions. The system translates Lisp-based syntax trees into syntactically correct, type-safe Rust code, enabling developers to write Rust programs using Lisp’s symbolic programming capabilities while maintaining Rust’s type system, ownership model, and idiomatic patterns.
## Supported Lisp Expressions
The following table lists all supported Common Lisp expressions and their corresponding Rust translations:
### Basic Operations
| Lisp Expression | Rust Output | Example |
|---|---|---|
| `(+ a b)` | `(a + b)` | `(emit-rs :code ‘(+ 1 2))` → `(1 + 2)` |
| `(- a b)` | `(a - b)` | `(emit-rs :code ‘(- 5 3))` → `(5 - 3)` |
| `(* a b)` | `(a * b)` | `(emit-rs :code ‘(* 2 3))` → `((2) * (3))` |
| `(/ a b)` | `(a / b)` | `(emit-rs :code ‘(/ 10 2))` → `((10) / (2))` |
### Comparison and Logical Operations
| Lisp Expression | Rust Output | Example | ||||
|---|---|---|---|---|---|---|
| `(= a b)` | `a=b` | `(emit-rs :code ‘(= x 5))` → `x=5` | ||||
| `(!= a b)` | `(a)!=(b)` | `(emit-rs :code ‘(!= x 5))` → `(x)!=(5)` | ||||
| `(== a b)` | `(a)==(b)` | `(emit-rs :code ‘(== x 5))` → `(x)==(5)` | ||||
| `(< a b)` | `a<b` | `(emit-rs :code ‘(< 3 5))` → `3<5` | ||||
| `(and a b)` | `(a)&&(b)` | `(emit-rs :code ‘(and true false))` → `(true)&&(false)` | ||||
| `(or a b)` | `(a) | (b)` | `(emit-rs :code ‘(or true false))` → `(true) | (false)` |
### Control Flow
| Lisp Expression | Rust Output | Example |
|---|---|---|
| `(if condition true-branch false-branch)` | `if condition { true-branch } else { false-branch }` | `(emit-rs :code ‘(if (> x 0) (return x) (return 0)))` |
| `(when condition body…)` | `if condition { body… }` | `(emit-rs :code ‘(when (> x 0) (return x)))` |
| `(unless condition body…)` | `if (!condition) { body… }` | `(emit-rs :code ‘(unless (> x 0) (return 0)))` |
| `(while condition body…)` | `while (condition) { body… }` | `(emit-rs :code ‘(while (> i 0) (decf i)))` |
| `(for (item collection) body…)` | `for item in collection { body… }` | `(emit-rs :code ‘(for (x vec) (print x)))` |
| `(case keyform (key body…) (t default-body…))` | `match keyform { key => { body… }, _ => { default-body… } }` | `(emit-rs :code ‘(case x (1 (print “one”)) (t (print “other”))))` |
### Variable Declarations and Bindings
| Lisp Expression | Rust Output | Example |
|---|---|---|
| `(let ((var value)) body…)` | `let var = value; body…` | `(emit-rs :code ‘(let ((x 5)) (print x)))` |
| `(let* ((var value)) body…)` | `let mut var = value; body…` | `(emit-rs :code ‘(let* ((x 5)) (setf x 10)))` |
| `(setf var value)` | `var = value;` | `(emit-rs :code ‘(setf x 10))` |
### Function Definitions
| Lisp Expression | Rust Output | Example | ||
|---|---|---|---|---|
| `(defun name (args) (declare (type type arg)) (declare (values return-type)) body…)` | `fn name(arg: type) -> return_type { body… }` | `(emit-rs :code ‘(defun gcd (n m) (declare (type u64 n m) (values u64)) (return n)))` | ||
| `(lambda (args) body…)` | ` | args | { body… }` | `(emit-rs :code ‘(lambda (x) (* x 2)))` |
### Data Structures
| Lisp Expression | Rust Output | Example |
|---|---|---|
| `(defstruct0 name (slot1 type1) (slot2 type2))` | `struct name { slot1: type1, slot2: type2, }` | `(emit-rs :code ‘(defstruct0 Point (x f64) (y f64)))` |
| `(make-instance Point :x 1.0 :y 2.0)` | `Point { x: 1.0, y: 2.0 }` | `(emit-rs :code ‘(make-instance Point :x 1.0 :y 2.0))` |
| `(aref array index)` | `array[index]` | `(emit-rs :code ‘(aref arr 0))` |
### Special Forms and Modules
| Lisp Expression | Rust Output | Example |
|---|---|---|
| `(use ((std io)))` | `use std::io;` | `(emit-rs :code ‘(use ((std io))))` |
| `(mod module1 module2)` | `mod module1; mod module2;` | `(emit-rs :code ‘(mod utils main))` |
| `(unsafe body…)` | `unsafe { body… }` | `(emit-rs :code ‘(unsafe (setf x 5)))` |
| `(extern body…)` | `extern { body… }` | `(emit-rs :code ‘(extern (defun printf (s string))))` |
### String and Character Operations
| Lisp Expression | Rust Output | Example |
|---|---|---|
| `(string “hello”)` | `”hello”` | `(emit-rs :code ‘(string “hello”))` |
| `(char ‘a’)` | `’a’` | `(emit-rs :code ‘(char ‘a’))` |
| `(hex 255)` | `0xff` | `(emit-rs :code ‘(hex 255))` |
## Examples
### Basic Function Example
“`lisp (defun gcd (n m) (declare (type u64 n m) (values u64)) (if (= m 0) (return n) (gcd m (% n m)))) “`
Generates: “`rust fn gcd(n: u64, m: u64) -> u64 { if m == 0 { return n; } gcd(m, (n % m)) } “`
### Struct Example
“`lisp (defstruct0 Point (x f64) (y f64))
(defun distance (p1 p2) (declare (type Point p1 p2) (values f64)) (let ((dx (- (dot p1 x) (dot p2 x))) (dy (- (dot p1 y) (dot p2 y)))) (declare (type f64 dx dy)) (return (sqrt (+ (* dx dx) (* dy dy)))))) “`
Generates: “`rust struct Point { x: f64, y: f64, }
fn distance(p1: Point, p2: Point) -> f64 { let dx = (p1.x - p2.x); let dy = (p1.y - p2.y); return sqrt(((dx * dx) + (dy * dy))); } “`
## Installation and Usage
- Install the ASDF system: “`lisp (ql:quickload :cl-rust-generator) “`
- Use the `emit-rs` function to generate Rust code: “`lisp (emit-rs :code ‘(defun main () (declare (values i32)) (return 0))) “`
- Write generated code to files: “`lisp (write-source “src/main.rs” (emit-rs :code ‘(defun main () (declare (values i32)) (return 0)))) “`
## Project Structure
The system consists of:
- `rs.lisp` - Core translation engine with `emit-rs` function
- `cl-rust-generator.asd` - ASDF system definition
- `examples/` - Collection of example projects demonstrating various patterns
## Example Projects
| Example | Description | Status |
|---|---|---|
| `01_gcd` | Basic GCD function with tests | Finished |
| `02_webgcd` | Web server with GCD calculation | Finished |
| `06_parallel_text` | Multi-file project with threading | Finished |
| `08_glfw` | GLFW windowing with ImGui | Finished |
| `09_wasm` | WebAssembly example | Basic |
| `11_cuda` | CUDA GPU computing | Basic |
## Notes
- The system uses hash-based change detection to avoid unnecessary file rewrites
- Generated code is automatically formatted using `rustfmt`
- Type declarations are processed through `consume-declare` function for type safety
- The readtable case is inverted to preserve Rust naming conventions
Wiki pages you might want to explore:
- [Overview (plops/cl-rust-generator)](/wiki/plops/cl-rust-generator#1)