6 releases (stable)
Uses new Rust 2024
| 1.4.0 | Feb 9, 2026 |
|---|---|
| 1.3.2 | Feb 9, 2026 |
| 0.1.1 | Jan 29, 2026 |
#91 in #scheme
Used in 7 crates
(2 directly)
21KB
369 lines
Procedural macros for grift_parser standard library
This crate provides the include_stdlib! macro which parses a .scm file
containing function definitions and transforms them into the format expected
by the define_stdlib! macro.
Example
Given a file stdlib.scm:
;;; (map f lst) - Apply f to each element of lst
(define (map f lst) (if (null? lst) '() (cons (f (car lst)) (map f (cdr lst)))))
The macro:
include_stdlib!("stdlib.scm");
Expands to:
define_stdlib! {
/// (map f lst) - Apply f to each element of lst
Map("map", ["f", "lst"], "(if (null? lst) '() (cons (f (car lst)) (map f (cdr lst))))"),
}
grift
a lisp interpreter implementing vau calculus, suitable for bare metal devices and embedded use
Features
no_std,no_alloc,#![forbid(unsafe_code)]- Fixed-size arena with free-list allocation and linked-list string storage
- Vau calculus: first-class operatives (fexprs) subsume both functions and macros
- First-class mutable environments with lexical parent chains
- Applicative/operative combiner distinction (Kernel-style)
- Tail-call optimization via trampoline
- Mark-and-sweep garbage collection
- Immutable pairs, call-by-value evaluation
- Symbol interning
- Checked integer arithmetic
Usage (Rust API)
use grift::{Lisp, Value};
let lisp: Lisp<20000> = Lisp::new();
assert_eq!(lisp.eval("(+ 1 2)"), Ok(Value::Number(3)));
assert_eq!(lisp.eval("(car (cons 1 2))"), Ok(Value::Number(1)));
The const generic parameter (20000) sets the arena capacity in slots.
Usage (Lisp)
Grift's distinguishing feature is the vau operative, which receives its operands
unevaluated along with the caller's environment. lambda is derived from vau
and wrap:
;; vau creates an operative (fexpr) — operands are not evaluated
(define! my-quote (vau (x) #ignore x))
(my-quote (+ 1 2)) ; → (+ 1 2), not 3
;; lambda is sugar for (wrap (vau params #ignore body))
(define! double (lambda (x) (* x 2)))
(double 5) ; → 10
;; An operative that selectively evaluates using the caller's environment
(define! my-if (vau (test then else) e
(if (eval test e)
(eval then e)
(eval else e))))
;; Tail-recursive fibonacci
(define! fib (lambda (n a b)
(if (= n 0) a
(fib (- n 1) b (+ a b)))))
(fib 50 0 1) ; → 12586269025
Architecture
Grift stores all values in a flat [Cell<Slot<Value>>; N] array. Each Value
variant fits in two machine words plus a tag. The evaluator is a trampoline loop:
tail-position combiners update expr and env and re-enter the loop rather than
recursing. Garbage collection uses a mark bitmap and mark stack allocated on the
Rust stack (not the arena), triggered when occupancy exceeds 75%. Environments are
the sole mutable type — pairs, symbols, strings, and combiners are all immutable
once allocated. See ARCHITECTURE.md for full details.
Build
cargo build --workspace
cargo test --workspace
Run the benchmark suite:
cargo run -p grift --example fib_bench --release
Run the REPL (requires the repl feature):
cargo run -p grift --features repl
Documentation
- Kernel Spec -- Revised-1 Report on the Kernel Programming Language
- $vau the ultimate -- Fexprs as the basis of Lisp function application or $vau : the ultimate abstraction
- ARCHITECTURE.md -- System architecture, arena design, GC, TCO
- LANGUAGE.md -- Language reference: types, primitives, evaluation rules
- INTERNALS.md -- Contributor guide: module structure, adding builtins
License
MIT OR Apache-2.0