gollum-ir 0.4.0

Intermediate Representation for the Gollum language
Documentation
//! IR clause type.

use crate::metadata::IrMetadata;
use crate::term::IrTerm;

/// An IR-level clause (fact or rule).
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct IrClause {
    /// The head of the clause.
    pub head: IrTerm,
    /// Conjunctive body goals (empty for facts).
    pub body: Vec<IrTerm>,
    /// Optional reasoning metadata.
    pub metadata: Option<IrMetadata>,
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_fact_clause() {
        let clause = IrClause {
            head: IrTerm::Structure {
                name: "parent".into(),
                args: vec![IrTerm::Atom("alice".into()), IrTerm::Atom("bob".into())],
            },
            body: vec![],
            metadata: None,
        };
        assert!(clause.body.is_empty());
        assert!(clause.metadata.is_none());
    }

    #[test]
    fn test_rule_clause() {
        let clause = IrClause {
            head: IrTerm::Structure {
                name: "grandparent".into(),
                args: vec![IrTerm::Var("X".into()), IrTerm::Var("Y".into())],
            },
            body: vec![
                IrTerm::Structure {
                    name: "parent".into(),
                    args: vec![IrTerm::Var("X".into()), IrTerm::Var("Z".into())],
                },
                IrTerm::Structure {
                    name: "parent".into(),
                    args: vec![IrTerm::Var("Z".into()), IrTerm::Var("Y".into())],
                },
            ],
            metadata: None,
        };
        assert_eq!(clause.body.len(), 2);
    }
}