emlex 0.1.0

A zero-cost S-expression mathematical DSL engine for Rust. Provides compile-time evaluation, AST preservation, optimization, and reverse DSL reconstruction.
Documentation
  • Coverage
  • 4.76%
    1 out of 21 items documented1 out of 3 items with examples
  • Size
  • Source code size: 47.6 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 5.34 MB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 42s Average build duration of successful builds.
  • all releases: 42s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • rhetro/emlex
    0 0 0
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • rhetro

Emlex

A mathematical S-expression Domain Specific Language (DSL) compiler embedded in Rust macros.

emlex provides two compile-time evaluation environments:

  • eml!: A single-form DSL for real number evaluations.
  • ceml!: A comprehensive DSL for complex number operations.

The library evaluates S-expressions into native Rust operations at compile-time while preserving the Abstract Syntax Tree (AST) for structural optimization and Reverse DSL transformations.

Architecture & Performance

The macros generate purely native Rust code. To handle AST preservation (EExpr / CExpr) without runtime allocation overhead, the library utilizes lazy evaluation via static function pointers (LazyEExpr / LazyCExpr). If the AST is not explicitly consumed at runtime, LLVM's Dead Code Elimination (DCE) removes the allocation instructions, resulting in zero-overhead execution matching handwritten native operations.

Recursion Limit

emlex performs full S-expression parsing using macro_rules!, which relies on recursive macro expansion. For deeply nested expressions, the default Rust recursion limit (#[recursion_limit = "128"]) may be insufficient.

If you encounter a compilation error such as:

recursion limit reached while expanding the macro

add the following attribute to your crate root (lib.rs or main.rs):

#![recursion_limit = "512"]

Most projects will not require this, but complex or deeply nested DSL inputs may.

Features

  • Dual Evaluation Engines:
  • eml!: Evaluates (eml x y) as exp(x) - ln(y).
  • ceml!: Evaluates standard operations backed by num_complex::Complex<f64>.
  • Reverse DSL (AST Reconstruction): Parses inputs into ASTs that can be reconstructed back into their original S-expression strings using .to_eml() and .to_ceml().
  • AST Optimization: Automatically reduces redundant mathematical structures (e.g., simplifying exp(ln(x)) to x) through structural pattern matching.

Usage

Real Number DSL (eml!)

use emlex::prelude::*;

fn main() {
    let x: f64 = 2.0;
    let y: f64 = 3.0;
    
    // Returns (LazyEExpr, f64)
    let (ast, val) = eml!((eml x y));
    
    assert_eq!(val, x.exp() - y.ln());
    assert_eq!(ast.to_eml(), "(eml x y)");
    
    // AST Optimization
    let z: f64 = 5.0;
    let (opt_ast, _) = eml!((eml (eml 1.0 (eml (eml 1.0 z) 1.0)) 1.0));
    assert_eq!(opt_ast.optimize().to_eml(), "z");
}

Complex Number DSL (ceml!)

use emlex::prelude::*;

fn main() {
    let z1 = Complex::new(1.0, 2.0);
    
    // Returns (LazyCExpr, Complex<f64>)
    let (ast, val) = ceml!((add z1 (i)));
    
    assert_eq!(val, z1 + Complex::new(0.0, 1.0));
    assert_eq!(ast.to_ceml(), "(add z1 (i))");
}

License

This project is licensed under either of

at your option.