conjure_cp_core/lib.rs
1#[doc(hidden)]
2pub extern crate self as conjure_cp_core;
3
4#[doc(hidden)]
5pub use ast::Model;
6
7pub mod ast;
8
9// NOTE: this module defines the bug! macro, which is exported at the crate level, and has no other
10// contents.
11pub mod bug;
12
13pub mod context;
14pub mod domain_tightening;
15pub mod error;
16pub mod instantiate;
17pub mod objective;
18pub mod parse;
19pub mod representation;
20pub mod rule_engine;
21pub mod settings;
22pub mod solver;
23pub mod stats;
24
25// Various internal helper functions
26pub mod utils;
27
28/// Creates a [`Domain::Int`](ast::Domain::Int).
29///
30/// # Examples
31/// ```
32/// use conjure_cp_core::{domain_int,range,ast::Domain};
33///
34/// let a = 2*10;
35/// assert_eq!(domain_int!(1..5,a+2,), Domain::int(vec![range!(1..5),range!(a+2)]));
36/// assert_eq!(domain_int!(), Domain::int_ground(vec![]))
37/// ```
38#[macro_export]
39macro_rules! domain_int {
40 () => {$crate::ast::Domain::int_ground(vec![])};
41
42 // when parsing expressions, rust groups 1..2 into a single token tree, (1..2)
43 // however, we want it to be three seperate token trees [1,..,2] for parsing.
44 // use defile to turn it back into 3 token trees
45 ($($e:expr),+ $(,)?) => {::defile::defile! { $crate::ast::Domain::int(vec![$($crate::range!(@$e)),+]) } };
46}
47
48/// Creates a [`GroundDomain::Int`]
49#[macro_export]
50macro_rules! domain_int_ground {
51 () => {$crate::ast::GroundDomain::Int(vec![]).into()};
52
53 // when parsing expressions, rust groups 1..2 into a single token tree, (1..2)
54 // however, we want it to be three seperate token trees [1,..,2] for parsing.
55 // use defile to turn it back into 3 token trees
56 ($($e:expr),+ $(,)?) => {::defile::defile! { $crate::ast::GroundDomain::Int(vec![$($crate::range!(@$e)),+]).into() } };
57}
58
59/// Creates a [`Range`](ast::Range).
60///
61/// # Examples
62///
63/// ```
64/// use conjure_cp_core::{range,ast::Range};
65///
66/// let a = 2*10;
67/// assert_eq!(range!(..a),Range::UnboundedL(a));
68/// assert_eq!(range!(2*5..),Range::UnboundedR(10));
69/// assert_eq!(range!(..10),Range::UnboundedL(10));
70/// assert_eq!(range!(1..5),Range::Bounded(1,5));
71/// assert_eq!(range!(Some(10).unwrap()),Range::Single(10));
72/// ```
73#[macro_export]
74macro_rules! range {
75 // decl macros have no lookahead, hence this nonsense with pushdown automata.
76
77 // @hasLowerbound: have atleast one token of the lower bound on the stack
78 (@hasLowerBound [$($lower:tt)+] -> ..) => {$crate::ast::Range::UnboundedR($crate::as_expr!($($lower)+))};
79 (@hasLowerBound [$($lower:tt)+] -> .. $($tail:tt)+) => {$crate::ast::Range::Bounded($crate::as_expr!($($lower)+),$crate::as_expr!($($tail)+))};
80 (@hasLowerBound [$($lower:tt)+] -> $b:tt $($tail:tt)*) => {range!(@hasLowerBound [$($lower)+ $b] -> $($tail)*)};
81 (@hasLowerBound [$($lower:tt)+] ->) => {$crate::ast::Range::Single($crate::as_expr!($($lower)+))};
82
83 // initial tokens
84 (.. $($a:tt)+) => {$crate::ast::Range::UnboundedL($crate::as_expr!($($a)+))};
85
86 ($a:tt $($tail:tt)*) => {range!(@hasLowerBound [$a] -> $($tail)*)};
87
88}
89
90// coorce a tt fragment into a expr fragment
91// https://lukaswirth.dev/tlborm/decl-macros/building-blocks/ast-coercion.html
92#[macro_export]
93#[doc(hidden)]
94macro_rules! as_expr {
95 ($e:expr) => {
96 $e
97 };
98}