A Rust Lisp dialect with 100% interoperability
Oxur is a Lisp that treats Rust as its compilation target and runtime. Drawing inspiration from Zetalisp, LFE, and Clojure, Oxur provides Lisp's expressiveness and metaprogramming power while leveraging Rust's type system, ownership model, and ecosystem. Simply put, Oxur lets you write your Rust as Lisp.
Early Development - Currently in the design phase.
This is a Cargo workspace containing multiple related crates:
- design/ - Design documentation and CLI tool for managing docs
- oxur-ast/ - (in progress) - Rust AST ↔ S-expression representation and CLI tool for generating S-expressions and Rust code
- oxur-cli/ - (early stages) - CLI infrastructure and unified command-line tool
- oxur-pretty/ - S-expression formatter with rustfmt-style CLI
- oxur-lang/ - (planning) - The Oxur Lisp dialect
- oxur-repl/ - (planning) - REPL server/client
- oxur-comp/ - (planning) - The Oxur compiler
- Rust 1.75 or later
- Cargo (comes with Rust)
# Build all crates
cargo build
# or
make build
# Build specific crate
cargo build -p design
# Build with optimizations
cargo build --releaseThe build includes several command-line tools:
aster- AST manipulation (Rust ↔ S-expression conversions)odm- Design documentation manageroxurfmt- S-expression formatter
Which you can also build individually:
cargo build --release --bin aster
cargo build --release --bin odm
cargo build --release --bin oxurfmtThe Oxur syntax is currently in the "actively researching, exploring, and experimenting" and stage. As part of that, we are examining the following:
- Coalton - Hindley-Milner type inference for Common Lisp
- LFE - LFE's syntax for Erlang type specs (these are type specifications that can by used by Erlang's static analyser
dialyzer; they are not static types) - Typed Racket
- Shen
Given the Zetalisp inspiration for Oxur, we are leaning heavily toward a Coalton-influenced syntax for types in a Rust Lisp.
Now, that being said, we're going to go out on a limb and show some of what we're thinking, even though we can't make any promise that any of this will survive the process of experimentation :-D Here's an example of the sort of sytnax we're exploring:
(use std::collections::hashmap)
(use std::io::error)
(deffn greet-user
(name:string count:(option u32)) -> (result string error)
"Greets a user with optional repetition"
(let (base (string::from "Hello, ") ; static String::from
greeting (string:push-str base name) ; instance method
final (match count
((some n) (string:repeat greeting n))
(none) greeting))
(ok final)))If you're curious about the development of Oxur's syntax, you're going to want to keep your eye on this doc as it moves through the design process.
The Oxur AST is really just the Rust AST in S-expression format. Here's a simple example taken from crates/oxur-ast/test-data/examples/intermediate/:
(Item
:vis Public
:kind (Fn
:sig (FnSig
:name "main"
:params ()
:return-type nil)
:body (Block
:stmts ()
:span (Span :lo 0 :hi 0)))
:span (Span :lo 0 :hi 0))The oxur-ast crate includes the aster binary which may be used to convert between Oxur and Rust ASTs:
$ ./bin/aster --help
AST manipulation and conversion tool
Usage: aster <COMMAND>
Commands:
to-ast Convert Rust source to S-expression AST [aliases: ast]
to-rust Convert S-expression to Rust source
verify Verify round-trip conversion
help Print this message or the help of the given subcommand(s)
Options:
-h, --help Print help
Use 'aster <command> --help' for more information.A full round-trip example that you can run yourself is provided in the crate README.
The oxur-pretty crate provides the oxurfmt tool for formatting S-expression files with human-readable output. It follows rustfmt conventions for a familiar workflow:
$ ./bin/oxurfmt --help
Format S-expression files
Usage: oxurfmt [OPTIONS] <FILE>...
Arguments:
<FILE>... Input files to format (use '-' for stdin)
Options:
--check Check if files are formatted correctly
--emit <MODE> What data to emit and how [possible values: files, stdout]
--backup Backup any modified files
--config <key1=val1,key2=val2> Set options from command line
--color <MODE> Use colored output [possible values: always, never, auto]
-l, --files-with-diff Prints names of mismatched files
-v, --verbose Print verbose output
-q, --quiet Print less output
-h, --help Print helpFormat files in-place, check formatting for CI/CD, or pipe through stdin/stdout:
# Format file in-place
./bin/oxurfmt my-ast.sexp
# Check if formatted (exits 1 if not)
./bin/oxurfmt --check src/*.sexp
# Stdin to stdout
echo "(Span :lo 0 :hi 10)" | ./bin/oxurfmtSee the crate README for detailed usage and configuration options.
Parts of the compile change have been explored in the AST work above (particularly with the aster tool). Other parts will be explored in early REPL work. For the latest thinking on our approach, see:
The following design docs show our current thinking with regard to separation of concerns, extensibility (protocol, clients, servers, etc.):
- Research: Building a transport-agnostic REPL protocol in Rust
- Oxur Remote REPL Protocol Design
- Recommendations for Future-proofing Multiple REPL Protocols
Exact mechanics have yet to be ironed out.
ODDs ("Oxur Design Documents"), like Erlang EEPs and Rust RFCs, document all architectural decisions, specifications, and design discussions in the crates/design/docs/ directory.
To explore Oxur's design decisions, you probably want to start here.
Current odm help text:
./bin/odm --help
An odd document manager
Usage: odm [OPTIONS] <COMMAND>
Commands:
add Add a new document with full processing
add-batch Add multiple documents (supports glob patterns)
add-headers Add or update YAML frontmatter headers [aliases: headers]
debug Debug and introspection commands
help Print this message or the help of the given subcommand(s)
index Generate the index file [aliases: gen-index]
info Show tool information and documentation
list List all design documents [aliases: ls]
new Create a new design document
remove Remove a document (moves to dustbin) [aliases: rm]
rename Rename a document file (preserves number)
replace Replace a document while preserving its ID
scan Scan filesystem and update document state [aliases: rescan]
search Search documents [aliases: grep]
show Show a specific document
sync-location Move document to directory matching its state header [aliases: sync]
transition Transition document to a new state [aliases: mv]
update-index Synchronize the index with documents on filesystem [aliases: sync-index]
validate Validate all documents [aliases: check]
Options:
-d, --docs-dir <DOCS_DIR> Path to docs directory (defaults to ./docs) [default: docs]
-h, --help Print help
Use 'odm <command> --help' for more information about a command.List all design documents:
./bin/odm listApache License, Version 2.0
Copyright © 2020-2026, Oxur Group
