proto_vulcan/operator/
mod.rs

1//! # Operators
2//!
3//! The signature of operators is different from relations. Operators have different kinds of
4//! parameters, of which only `OperatorParam` and `PatternMatchOperatorParam` are of interest
5//! to user; the parser generates these parameter types for regular operators and pattern-match
6//! operators, respectively.
7//! ```rust
8//! # extern crate proto_vulcan;
9//! # use proto_vulcan::prelude::*;
10//! # use proto_vulcan::goal::AnyGoal;
11//! # use std::marker::PhantomData;
12//! pub struct OperatorParam<'a, U: User, E: Engine<U>, G: AnyGoal<U, E>> {
13//!     pub body: &'a [&'a [G]],
14//!     _phantom: PhantomData<U>,
15//!     _phantom2: PhantomData<E>,
16//! }
17//!
18//! // operator <term> {
19//! //    <pattern0> | <pattern1> => <body0/1>,
20//! //    <pattern2> => <body2>,
21//! //    ...
22//! //    _ => <body_default>,
23//! // }
24//! pub struct PatternMatchOperatorParam<'a, U: User, E: Engine<U>, G: AnyGoal<U, E>> {
25//!     // First goal of each arm is the match-goal
26//!     pub arms: &'a [&'a [G]],
27//!     _phantom: PhantomData<U>,
28//!     _phantom2: PhantomData<E>,
29//! }
30//! ```
31//! Even though the structs are identical, the first goal on each arm of
32//! `PatternMatchOperatorParam` is the pattern and the match-term equality.
33//!
34//! For example `onceo` can be implemented as:
35//! ```rust
36//! extern crate proto_vulcan;
37//! use proto_vulcan::prelude::*;
38//! use proto_vulcan::operator::condu;
39//! use proto_vulcan::operator::OperatorParam;
40//!
41//! pub fn onceo<U: User, E: Engine<U>>(param: OperatorParam<U, E, Goal<U, E>>) -> Goal<U, E> {
42//!    let g = proto_vulcan::operator::conj::Conj::from_conjunctions(param.body);
43//!    proto_vulcan!(condu { g })
44//! }
45//! # fn main() {}
46//! ```
47//!
48
49use crate::engine::Engine;
50use crate::goal::AnyGoal;
51use crate::lterm::LTerm;
52use crate::solver::Solver;
53use crate::state::State;
54use crate::stream::Stream;
55use crate::user::User;
56use std::fmt::Debug;
57use std::marker::PhantomData;
58
59// operator { <body> }
60pub struct OperatorParam<'a, U, E, G>
61where
62    U: User,
63    E: Engine<U>,
64    G: AnyGoal<U, E>,
65{
66    pub body: &'a [&'a [G]],
67    _phantom: PhantomData<U>,
68    _phantom2: PhantomData<E>,
69}
70
71impl<'a, U, E, G> OperatorParam<'a, U, E, G>
72where
73    U: User,
74    E: Engine<U>,
75    G: AnyGoal<U, E>,
76{
77    #[inline]
78    pub fn new(body: &'a [&'a [G]]) -> OperatorParam<'a, U, E, G> {
79        OperatorParam {
80            body,
81            _phantom: PhantomData,
82            _phantom2: PhantomData,
83        }
84    }
85}
86
87// operator <term> {
88//    <pattern0> | <pattern1> => <body0/1>,
89//    <pattern2> => <body2>,
90//    ...
91//    _ => <body_default>,
92// }
93pub struct PatternMatchOperatorParam<'a, U, E, G>
94where
95    U: User,
96    E: Engine<U>,
97    G: AnyGoal<U, E>,
98{
99    // First goal of each arm is the match-goal
100    pub arms: &'a [&'a [G]],
101    _phantom: PhantomData<U>,
102    _phantom2: PhantomData<E>,
103}
104
105impl<'a, U, E, G> PatternMatchOperatorParam<'a, U, E, G>
106where
107    U: User,
108    E: Engine<U>,
109    G: AnyGoal<U, E>,
110{
111    #[inline]
112    pub fn new(arms: &'a [&'a [G]]) -> PatternMatchOperatorParam<'a, U, E, G> {
113        PatternMatchOperatorParam {
114            arms,
115            _phantom: PhantomData,
116            _phantom2: PhantomData,
117        }
118    }
119}
120
121// fngoal [move]* |engine, state| { <rust> }
122pub struct FnOperatorParam<U: User, E: Engine<U>>
123where
124    U: User,
125    E: Engine<U>,
126{
127    pub f: Box<dyn Fn(&Solver<U, E>, State<U, E>) -> Stream<U, E>>,
128}
129
130// closure { <body> }
131pub struct ClosureOperatorParam<U, E, G>
132where
133    U: User,
134    E: Engine<U>,
135    G: AnyGoal<U, E>,
136{
137    pub f: Box<dyn Fn() -> G>,
138    _phantom: PhantomData<U>,
139    _phantom2: PhantomData<E>,
140}
141
142impl<U, E, G> ClosureOperatorParam<U, E, G>
143where
144    U: User,
145    E: Engine<U>,
146    G: AnyGoal<U, E>,
147{
148    #[inline]
149    pub fn new(f: Box<dyn Fn() -> G>) -> ClosureOperatorParam<U, E, G> {
150        ClosureOperatorParam {
151            f,
152            _phantom: PhantomData,
153            _phantom2: PhantomData,
154        }
155    }
156}
157
158// for x in coll { <body> }
159pub struct ForOperatorParam<T, U, E, G>
160where
161    E: Engine<U>,
162    U: User,
163    G: AnyGoal<U, E>,
164    T: Debug + 'static,
165    for<'b> &'b T: IntoIterator<Item = &'b LTerm<U, E>>,
166{
167    pub coll: T,
168    // Goal generator: generates a goal for each cycle of the "loop" given element from the
169    // collection.
170    pub g: Box<dyn Fn(LTerm<U, E>) -> G>,
171}
172
173impl<T, U, E, G> ForOperatorParam<T, U, E, G>
174where
175    U: User,
176    E: Engine<U>,
177    G: AnyGoal<U, E>,
178    T: Debug + 'static,
179    for<'b> &'b T: IntoIterator<Item = &'b LTerm<U, E>>,
180{
181    #[inline]
182    pub fn new(coll: T, g: Box<dyn Fn(LTerm<U, E>) -> G>) -> ForOperatorParam<T, U, E, G> {
183        ForOperatorParam { coll, g }
184    }
185}
186
187#[cfg(feature = "core")]
188#[doc(hidden)]
189pub mod anyo;
190#[cfg(feature = "core")]
191#[doc(hidden)]
192pub mod closure;
193#[doc(hidden)]
194pub mod conda;
195#[cfg(feature = "core")]
196#[doc(hidden)]
197pub mod conde;
198#[doc(hidden)]
199pub mod condu;
200
201#[cfg(feature = "core")]
202#[doc(hidden)]
203pub mod conj;
204
205#[cfg(feature = "core")]
206#[doc(hidden)]
207pub mod disj;
208
209#[cfg(feature = "core")]
210#[doc(hidden)]
211pub mod everyg;
212
213#[cfg(feature = "core")]
214#[doc(hidden)]
215pub mod fngoal;
216
217#[cfg(feature = "core")]
218#[doc(hidden)]
219pub mod dfs;
220
221#[cfg(feature = "core")]
222#[doc(hidden)]
223pub mod fresh;
224
225#[cfg(feature = "extras")]
226#[doc(hidden)]
227pub mod matcha;
228
229#[cfg(feature = "core")]
230#[doc(hidden)]
231pub mod matche;
232
233#[cfg(feature = "extras")]
234#[doc(hidden)]
235pub mod matchu;
236
237#[cfg(any(feature = "extras", feature = "clpfd"))]
238#[doc(hidden)]
239pub mod onceo;
240
241#[cfg(feature = "core")]
242#[doc(hidden)]
243pub mod project;
244
245#[cfg(feature = "core")]
246#[doc(inline)]
247pub use dfs::dfs;
248
249#[cfg(feature = "core")]
250#[doc(inline)]
251pub use anyo::anyo;
252
253#[cfg(feature = "extras")]
254#[doc(inline)]
255pub use conda::conda;
256
257#[cfg(feature = "core")]
258#[doc(inline)]
259pub use conde::conde;
260
261#[cfg(feature = "core")]
262#[doc(inline)]
263pub use conde::cond;
264
265#[cfg(feature = "extras")]
266#[doc(inline)]
267pub use condu::condu;
268
269#[cfg(any(feature = "extras", feature = "clpfd"))]
270#[doc(inline)]
271pub use onceo::onceo;
272
273#[cfg(feature = "core")]
274#[doc(inline)]
275pub use matche::matche;
276
277#[cfg(feature = "extras")]
278#[doc(inline)]
279pub use matchu::matchu;
280
281#[cfg(feature = "extras")]
282#[doc(inline)]
283pub use matcha::matcha;
284
285#[cfg(feature = "core")]
286#[doc(inline)]
287pub use everyg::everyg;