Skip to main content

prolog2/predicate_modules/
mod.rs

1/// Built-in maths predicates (`is/2`).
2pub mod maths;
3/// Built-in meta-predicates (`not/1`).
4pub mod meta_predicates;
5
6use crate::{
7    heap::{query_heap::QueryHeap, symbol_db::SymbolDB},
8    program::{hypothesis::Hypothesis, predicate_table::PredicateTable},
9    Config,
10};
11
12/// Return type for predicate functions.
13///
14/// A predicate either succeeds ([`PredReturn::True`]), fails ([`PredReturn::False`]),
15/// or succeeds with variable bindings ([`PredReturn::Binding`]).
16pub enum PredReturn {
17    True,
18    False,
19    /// Success with a list of `(source_addr, target_addr)` bindings to apply on the heap.
20    Binding(Vec<(usize, usize)>),
21}
22
23impl PredReturn {
24    /// Convenience: convert a bool into [`PredReturn::True`] or [`PredReturn::False`].
25    pub fn bool(value: bool) -> PredReturn {
26        if value {
27            PredReturn::True
28        } else {
29            PredReturn::False
30        }
31    }
32}
33
34/// Signature for a predicate function.
35///
36/// Arguments:
37/// - `&mut QueryHeap` — the current proof's working heap
38/// - `&mut Hypothesis` — the current learned hypothesis (may be extended)
39/// - `usize` — heap address of the goal term being resolved
40/// - `&PredicateTable` — the program's predicate table
41/// - `Config` — engine configuration
42pub type PredicateFunction =
43    for<'a> fn(&mut QueryHeap<'a>, &mut Hypothesis, usize, &PredicateTable, Config) -> PredReturn;
44
45/// A predicate module: a static slice of `(name, arity, function)` entries.
46///
47/// # Example
48///
49/// ```
50/// use prolog2::predicate_modules::{PredicateModule, PredReturn};
51///
52/// static MY_MODULE: PredicateModule = &[
53///     ("always_true", 0, |_heap, _hyp, _goal, _pt, _cfg| PredReturn::True),
54/// ];
55/// ```
56pub type PredicateModule = &'static [(&'static str, usize, PredicateFunction)];
57
58/// Register all entries from a predicate module into the predicate table.
59pub fn load_predicate_module(
60    predicate_table: &mut PredicateTable,
61    predicate_module: &PredicateModule,
62) {
63    for (symbol, arity, pred_fn) in predicate_module.iter() {
64        let _ = predicate_table.insert_predicate_function(
65            (SymbolDB::set_const((*symbol).to_string()), *arity),
66            *pred_fn,
67        );
68    }
69}
70
71/// Built-in maths predicates: `is/2` for arithmetic evaluation.
72pub static MATHS: PredicateModule = &[("is", 2, maths::is_pred)];
73
74/// Built-in meta-predicates: `not/1` (negation as failure).
75pub static META_PREDICATES: PredicateModule = &[("not", 1, meta_predicates::not)];
76
77/// Load all built-in predicate modules into the predicate table.
78pub fn load_all_modules(predicate_table: &mut PredicateTable) {
79    load_predicate_module(predicate_table, &MATHS);
80    load_predicate_module(predicate_table, &META_PREDICATES);
81}