Skip to content

billosys/oxur

 
 

Repository files navigation

Oxur

Build Status Tags

Our mascot, Orux! ('Ruxxy' to his friends)

A Rust Lisp dialect with 100% interoperability

Overview

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.

Project Status

Early Development - Currently in the design phase.

Repository Structure

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

Getting Started

Prerequisites

  • Rust 1.75 or later
  • Cargo (comes with Rust)

Building

# Build all crates
cargo build

# or
make build

# Build specific crate
cargo build -p design

# Build with optimizations
cargo build --release

The build includes several command-line tools:

  • aster - AST manipulation (Rust ↔ S-expression conversions)
  • odm - Design documentation manager
  • oxurfmt - S-expression formatter

Which you can also build individually:

cargo build --release --bin aster
cargo build --release --bin odm
cargo build --release --bin oxurfmt

Oxur Syntax

The 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

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.

S-Expression Formatting

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 help

Format 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/oxurfmt

See the crate README for detailed usage and configuration options.

The Oxur Compiler

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 Oxur REPL

The following design docs show our current thinking with regard to separation of concerns, extensibility (protocol, clients, servers, etc.):

Exact mechanics have yet to be ironed out.

Design Documents

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.

Design Documentation CLI

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 list

odm cli tool screenshot of list command

License

Apache License, Version 2.0

Copyright © 2020-2026, Oxur Group

About

WIP: A Rust Lisp dialect with 100% interoperability

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • Rust 98.5%
  • Other 1.5%