chase-rs/src/chase/term.rs

80 lines
2.0 KiB
Rust
Raw Normal View History

2026-03-09 09:59:10 +01:00
//! Terms represent values in the chase: constants or labeled nulls.
use std::fmt;
/// A term is either a constant (from the input) or a null (invented during chase).
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Term {
/// A constant value from the domain.
Constant(String),
/// A labeled null (invented value) created during the chase.
/// The usize is a unique identifier for this null.
Null(usize),
/// A variable (used in rule bodies/heads, not in instances).
Variable(String),
}
impl Term {
/// Create a new constant term.
pub fn constant(value: impl Into<String>) -> Self {
Term::Constant(value.into())
}
/// Create a new null term with the given id.
pub fn null(id: usize) -> Self {
Term::Null(id)
}
/// Create a new variable term.
pub fn var(name: impl Into<String>) -> Self {
Term::Variable(name.into())
}
/// Returns true if this term is a variable.
pub fn is_variable(&self) -> bool {
matches!(self, Term::Variable(_))
}
/// Returns true if this term is ground (not a variable).
pub fn is_ground(&self) -> bool {
!self.is_variable()
}
}
impl fmt::Display for Term {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Term::Constant(c) => write!(f, "{}", c),
Term::Null(id) => write!(f, "⊥{}", id),
Term::Variable(v) => write!(f, "?{}", v),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_term_creation() {
let c = Term::constant("alice");
let n = Term::null(1);
let v = Term::var("X");
assert!(matches!(c, Term::Constant(_)));
assert!(matches!(n, Term::Null(1)));
assert!(matches!(v, Term::Variable(_)));
}
#[test]
fn test_term_properties() {
let c = Term::constant("alice");
let v = Term::var("X");
assert!(c.is_ground());
assert!(!c.is_variable());
assert!(!v.is_ground());
assert!(v.is_variable());
}
}