Skip to main content

gollum_ast/
term.rs

1//! Term type for the Gollum AST.
2use std::fmt;
3
4/// A term in Gollum logic.
5#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
6pub enum Term {
7    /// A logic variable (e.g., `X`, `_`).
8    Variable(String),
9    /// An atom (e.g., `alice`, `'Bob'`).
10    Atom(String),
11    /// An integer literal (e.g., `42`).
12    Integer(i64),
13    /// A floating-point literal (e.g., `3.14`).
14    Float(f64),
15    /// A string literal (e.g., `"hello"`).
16    Str(String),
17    /// An anonymous variable (wildcard, `_`).
18    Anon,
19    /// A list literal (e.g., `[a, b, c]`).
20    List(Vec<Term>),
21    /// A list construction (e.g., `[a, b | Tail]`).
22    ListCons(Vec<Term>, Box<Term>),
23    /// A compound term (e.g., `point(X, Y)`).
24    Compound(String, Vec<Term>),
25    /// A term with a type annotation (e.g., `X:person`).
26    /// The type_name should be an atom (lowercase, possibly quoted).
27    TypeAnnotated {
28        /// The underlying term.
29        term: Box<Term>,
30        /// The type name.
31        type_name: String,
32    },
33    /// A dense tensor / embedding literal (e.g., `#[1.0, 0.5, -0.3]`).
34    Tensor(Vec<f32>),
35    /// A neural term with gradient tracking (e.g., `X :: "model" :: "grad"`).
36    /// Combines neural model execution with bidirectional gradient flow.
37    NeuralGradient {
38        /// The underlying term.
39        term: Box<Term>,
40        /// The neural model identifier.
41        model_id: String,
42        /// The gradient identifier for backpropagation.
43        grad_id: String,
44    },
45}
46
47impl Term {
48    /// Returns true if this term contains any neural gradient annotation.
49    pub fn contains_neural(&self) -> bool {
50        match self {
51            Term::NeuralGradient { .. } => true,
52            Term::TypeAnnotated { term, .. } => term.contains_neural(),
53            Term::Compound(_, args) => args.iter().any(|t| t.contains_neural()),
54            Term::List(items) => items.iter().any(|t| t.contains_neural()),
55            Term::ListCons(head, tail) => {
56                head.iter().any(|t| t.contains_neural()) || tail.contains_neural()
57            }
58            _ => false,
59        }
60    }
61}
62
63impl fmt::Display for Term {
64    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
65        match self {
66            Term::Variable(v) => write!(f, "{}", v),
67            Term::Atom(a) => write!(f, "{}", a),
68            Term::Integer(i) => write!(f, "{}", i),
69            Term::Float(fl) => write!(f, "{}", fl),
70            Term::Str(s) => write!(f, "\"{}\"", s),
71            Term::Anon => write!(f, "_"),
72            Term::List(items) => {
73                write!(f, "[")?;
74                for (i, item) in items.iter().enumerate() {
75                    if i > 0 {
76                        write!(f, ", ")?;
77                    }
78                    write!(f, "{}", item)?;
79                }
80                write!(f, "]")
81            }
82            Term::ListCons(head, tail) => {
83                write!(f, "[")?;
84                for (i, item) in head.iter().enumerate() {
85                    if i > 0 {
86                        write!(f, ", ")?;
87                    }
88                    write!(f, "{}", item)?;
89                }
90                write!(f, "|{}]", tail)
91            }
92            Term::Compound(name, args) => {
93                write!(f, "{}(", name)?;
94                for (i, arg) in args.iter().enumerate() {
95                    if i > 0 {
96                        write!(f, ", ")?;
97                    }
98                    write!(f, "{}", arg)?;
99                }
100                write!(f, ")")
101            }
102            Term::TypeAnnotated { term, type_name } => {
103                write!(f, "{}:{}", term, type_name)
104            }
105            Term::Tensor(elems) => {
106                write!(f, "#[")?;
107                for (i, v) in elems.iter().enumerate() {
108                    if i > 0 { write!(f, ", ")?; }
109                    write!(f, "{}", v)?;
110                }
111                write!(f, "]")
112            }
113            Term::NeuralGradient {
114                term,
115                model_id,
116                grad_id,
117            } => {
118                write!(f, "{} :: \"{}\" :: \"{}\"", term, model_id, grad_id)
119            }
120        }
121    }
122}