| Crates.io | datalog_ast |
| lib.rs | datalog_ast |
| version | 0.2.7 |
| created_at | 2025-11-25 14:03:33.91041+00 |
| updated_at | 2025-11-25 21:55:50.403809+00 |
| description | Abstract Syntax Tree types for Datalog programs |
| homepage | |
| repository | https://github.com/jsam/datalog_ast |
| max_upload_size | |
| id | 1949816 |
| size | 79,635 |
Abstract Syntax Tree types for Datalog programs.
datalog_ast provides a set of Rust data structures for representing Datalog programs. It is designed as a shared, reusable component that can be used across parsers, evaluators, and analyzers for consistency in Datalog program representation.
Term, Atom, Constraint, BodyPredicate, Rule, and Program<, <=, >, >=, ==, !=)Add this to your Cargo.toml:
[dependencies]
datalog_ast = "0.1"
use datalog_ast::{Atom, BodyPredicate, Program, Rule, Term};
// Build a simple transitive closure program:
// reach(x) :- source(x).
// reach(y) :- reach(x), edge(x, y).
let mut program = Program::new();
// reach(x) :- source(x).
program.add_rule(Rule::new_simple(
Atom::new("reach".into(), vec![Term::Variable("x".into())]),
vec![Atom::new("source".into(), vec![Term::Variable("x".into())])],
vec![],
));
// reach(y) :- reach(x), edge(x, y).
program.add_rule(Rule::new_simple(
Atom::new("reach".into(), vec![Term::Variable("y".into())]),
vec![
Atom::new("reach".into(), vec![Term::Variable("x".into())]),
Atom::new("edge".into(), vec![
Term::Variable("x".into()),
Term::Variable("y".into()),
]),
],
vec![],
));
// Analyze the program
assert!(program.is_safe());
assert_eq!(program.idbs(), vec!["reach"]);
assert_eq!(program.edbs(), vec!["edge", "source"]);
Represents variables, constants, or placeholders in Datalog:
use datalog_ast::Term;
let var = Term::Variable("x".into());
let constant = Term::Constant(42);
let placeholder = Term::Placeholder; // Represents "_"
assert!(var.is_variable());
assert!(constant.is_constant());
Represents a relation with arguments, like edge(x, y):
use datalog_ast::{Atom, Term};
let atom = Atom::new(
"edge".into(),
vec![Term::Variable("x".into()), Term::Variable("y".into())],
);
assert_eq!(atom.relation, "edge");
assert_eq!(atom.arity(), 2);
assert!(atom.variables().contains("x"));
Represents comparison constraints in rule bodies:
use datalog_ast::{Constraint, Term};
let constraint = Constraint::LessThan(
Term::Variable("x".into()),
Term::Constant(100),
);
Available constraint types:
Equal, NotEqualLessThan, LessOrEqualGreaterThan, GreaterOrEqualRepresents positive or negated atoms in rule bodies (for stratified negation):
use datalog_ast::{Atom, BodyPredicate, Term};
let positive = BodyPredicate::Positive(
Atom::new("edge".into(), vec![Term::Variable("x".into())])
);
let negated = BodyPredicate::Negated(
Atom::new("visited".into(), vec![Term::Variable("x".into())])
);
assert!(positive.is_positive());
assert!(negated.is_negated());
Represents a Datalog rule with head, body predicates, and constraints:
use datalog_ast::{Atom, BodyPredicate, Constraint, Rule, Term};
// path(x, z) :- edge(x, y), path(y, z), x != z.
let rule = Rule::new(
Atom::new("path".into(), vec![
Term::Variable("x".into()),
Term::Variable("z".into()),
]),
vec![
BodyPredicate::Positive(Atom::new("edge".into(), vec![
Term::Variable("x".into()),
Term::Variable("y".into()),
])),
BodyPredicate::Positive(Atom::new("path".into(), vec![
Term::Variable("y".into()),
Term::Variable("z".into()),
])),
],
vec![Constraint::NotEqual(
Term::Variable("x".into()),
Term::Variable("z".into()),
)],
);
assert!(rule.is_safe());
assert!(rule.is_recursive());
Represents a complete Datalog program:
use datalog_ast::Program;
let program = Program::new();
// Program analysis methods:
// - program.idbs() - Get IDB (derived) relations
// - program.edbs() - Get EDB (base) relations
// - program.all_relations() - Get all relation names
// - program.is_safe() - Check if all rules are safe
// - program.recursive_rules() - Get recursive rules
A Datalog rule is safe if every variable in the head appears in at least one positive body atom. This library provides built-in safety checking:
use datalog_ast::{Atom, Rule, Term};
// Safe rule: y appears in edge(x, y)
let safe_rule = Rule::new_simple(
Atom::new("reach".into(), vec![Term::Variable("y".into())]),
vec![Atom::new("edge".into(), vec![
Term::Variable("x".into()),
Term::Variable("y".into()),
])],
vec![],
);
assert!(safe_rule.is_safe());
// Unsafe rule: z doesn't appear in any positive body atom
let unsafe_rule = Rule::new_simple(
Atom::new("bad".into(), vec![Term::Variable("z".into())]),
vec![Atom::new("edge".into(), vec![
Term::Variable("x".into()),
Term::Variable("y".into()),
])],
vec![],
);
assert!(!unsafe_rule.is_safe());
Licensed under either of:
at your option.
Contributions are welcome! Please feel free to submit a Pull Request.