Skip to main content

tensorlogic_adapters/
predicate.rs

1//! Predicate metadata.
2
3use serde::{Deserialize, Serialize};
4use tensorlogic_ir::Term;
5
6use crate::constraint::PredicateConstraints;
7use crate::error::AdapterError;
8use crate::metadata::Metadata;
9
10/// Predicate metadata including arity and domain types
11#[derive(Clone, Debug, Serialize, Deserialize)]
12pub struct PredicateInfo {
13    pub name: String,
14    pub arity: usize,
15    pub arg_domains: Vec<String>,
16    pub description: Option<String>,
17    pub constraints: Option<PredicateConstraints>,
18    /// Rich metadata including provenance, documentation, tags
19    pub metadata: Option<Metadata>,
20}
21
22impl PredicateInfo {
23    pub fn new(name: impl Into<String>, arg_domains: Vec<String>) -> Self {
24        let arity = arg_domains.len();
25        PredicateInfo {
26            name: name.into(),
27            arity,
28            arg_domains,
29            description: None,
30            constraints: None,
31            metadata: None,
32        }
33    }
34
35    pub fn with_description(mut self, desc: impl Into<String>) -> Self {
36        self.description = Some(desc.into());
37        self
38    }
39
40    pub fn with_constraints(mut self, constraints: PredicateConstraints) -> Self {
41        self.constraints = Some(constraints);
42        self
43    }
44
45    pub fn with_metadata(mut self, metadata: Metadata) -> Self {
46        self.metadata = Some(metadata);
47        self
48    }
49
50    pub fn validate_args(&self, args: &[Term]) -> Result<(), AdapterError> {
51        if args.len() != self.arity {
52            return Err(AdapterError::ArityMismatch {
53                name: self.name.clone(),
54                expected: self.arity,
55                found: args.len(),
56            });
57        }
58        Ok(())
59    }
60}