Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/ekzhang/crepe
Datalog compiler embedded in Rust as a procedural macro
https://github.com/ekzhang/crepe
datalog logic-programming rust souffle static-analysis translator
Last synced: about 2 months ago
JSON representation
Datalog compiler embedded in Rust as a procedural macro
- Host: GitHub
- URL: https://github.com/ekzhang/crepe
- Owner: ekzhang
- License: apache-2.0
- Created: 2020-08-31T01:33:53.000Z (about 4 years ago)
- Default Branch: main
- Last Pushed: 2024-03-05T08:40:05.000Z (7 months ago)
- Last Synced: 2024-07-28T17:42:59.713Z (about 2 months ago)
- Topics: datalog, logic-programming, rust, souffle, static-analysis, translator
- Language: Rust
- Homepage:
- Size: 72.3 KB
- Stars: 451
- Watchers: 13
- Forks: 16
- Open Issues: 5
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE-APACHE
Awesome Lists containing this project
README
# Crepe
[](https://github.com/ekzhang/crepe)
[](https://crates.io/crates/crepe)
[](https://docs.rs/crepe)
[](https://github.com/ekzhang/crepe/actions?query=branch%3Amain)Crepe is a library that allows you to write declarative logic programs in
Rust, with a [Datalog](https://en.wikipedia.org/wiki/Datalog)-like syntax.
It provides a procedural macro that generates efficient, safe code and
interoperates seamlessly with Rust programs.## Features
- Semi-naive evaluation
- Stratified negation
- Automatic generation of indices for relations
- Easily call Rust functions from within Datalog rules
- Typesafe way to initialize `@input` relations
- Very fast, compiled directly with the rest of your Rust code## Example
The program below computes the transitive closure of a directed graph. Note
the use of the `crepe!` macro.```rust
use crepe::crepe;crepe! {
@input
struct Edge(i32, i32);@output
struct Reachable(i32, i32);Reachable(x, y) <- Edge(x, y);
Reachable(x, z) <- Edge(x, y), Reachable(y, z);
}fn main() {
let mut runtime = Crepe::new();
runtime.extend([Edge(1, 2), Edge(2, 3), Edge(3, 4), Edge(2, 5)]);let (reachable,) = runtime.run();
for Reachable(x, y) in reachable {
println!("node {} can reach node {}", x, y);
}
}
```Output:
```
node 1 can reach node 2
node 1 can reach node 3
node 1 can reach node 4
node 1 can reach node 5
node 2 can reach node 3
node 2 can reach node 4
node 2 can reach node 5
node 3 can reach node 4
```You can do much more with Crepe. The next example shows how you can use
stratified negation, Rust expression syntax, and semi-naive evaluation to find
all paths in a weighted graph with length at most `MAX_PATH_LEN`.```rust
use crepe::crepe;const MAX_PATH_LEN: u32 = 20;
crepe! {
@input
struct Edge(i32, i32, u32);@output
struct Walk(i32, i32, u32);@output
struct NoWalk(i32, i32);struct Node(i32);
Node(x) <- Edge(x, _, _);
Node(x) <- Edge(_, x, _);Walk(x, x, 0) <- Node(x);
Walk(x, z, len1 + len2) <-
Edge(x, y, len1),
Walk(y, z, len2),
(len1 + len2 <= MAX_PATH_LEN);NoWalk(x, y) <- Node(x), Node(y), !Walk(x, y, _);
}fn main() {
let n = 256;
let mut edges = Vec::new();
for i in 0..n {
for j in 0..n {
if rand::random::() < 0.02 {
edges.push(Edge(i, j, 5));
}
}
}let mut runtime = Crepe::new();
runtime.extend(edges);
let (walk, nowalk) = runtime.run();
println!("Walk: {}", walk.len());
println!("NoWalk: {}", nowalk.len());
}
```Output:
```
Walk: 89203
NoWalk: 8207
```## Notes
From initial testing, the generated code is very fast. Variants of transitive
closure for large graphs (~106 relations) run at comparable speed to
compiled [Souffle](https://souffle-lang.github.io/), and use a fraction of the
compilation time.For benchmarks, see the [`benches/` directory](benches/).
The benchmarks can be run using `cargo bench`.This macro generates a `Crepe` struct in the current module, as well as structs
for all of the declared relations. This means that to integrate Crepe inside a
larger program, you should put it in its own module with related code. See the
documentation for more information.## Acknowledgements
This project was heavily inspired by [Souffle](https://souffle-lang.github.io/)
and [Formulog](https://github.com/HarvardPL/formulog), which both use similar
models of Datalog compilation for static analysis.