Lines
90.77 %
Functions
20 %
use crate::ast::domains::Int;
use crate::ast::domains::range::Range;
use itertools::Itertools;
use polyquine::Quine;
use serde::{Deserialize, Serialize};
use std::fmt::{Display, Formatter};
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, Quine)]
#[path_prefix(conjure_cp::ast)]
pub struct SetAttr<A = Int> {
pub size: Range<A>,
}
impl<A> SetAttr<A> {
pub fn new(size: Range<A>) -> Self {
Self { size }
pub fn new_min_max_size(min: A, max: A) -> Self {
Self::new(Range::Bounded(min, max))
pub fn new_min_size(min: A) -> Self {
Self::new(Range::UnboundedR(min))
pub fn new_max_size(max: A) -> Self {
Self::new(Range::UnboundedL(max))
pub fn new_size(sz: A) -> Self {
Self::new(Range::Single(sz))
impl<A> Default for SetAttr<A> {
fn default() -> Self {
SetAttr {
size: Range::Unbounded,
impl<A: Display> Display for SetAttr<A> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match &self.size {
Range::Single(x) => write!(f, "(size {x})"),
Range::Bounded(l, r) => write!(f, "(minSize {l}, maxSize {r})"),
Range::UnboundedL(r) => write!(f, "(maxSize {r})"),
Range::UnboundedR(l) => write!(f, "(minSize {l})"),
Range::Unbounded => write!(f, ""),
pub struct MSetAttr<A = Int> {
pub occurrence: Range<A>,
impl<A> MSetAttr<A> {
pub fn new(size: Range<A>, occurrence: Range<A>) -> Self {
Self { size, occurrence }
Self::new(Range::Bounded(min, max), Range::Unbounded)
Self::new(Range::UnboundedR(min), Range::Unbounded)
Self::new(Range::UnboundedL(max), Range::Unbounded)
Self::new(Range::Single(sz), Range::Unbounded)
impl<A: Display> Display for MSetAttr<A> {
let size_str = match &self.size {
Range::Single(x) => format!("size {x}"),
Range::Bounded(l, r) => format!("minSize {l}, maxSize {r}"),
Range::UnboundedL(r) => format!("maxSize {r}"),
Range::UnboundedR(l) => format!("minSize {l}"),
Range::Unbounded => "".to_string(),
};
// It only makes sense in terms of min and max occurrence for the essence language,
// so for single ranges it is still presented as min and max occurrence.
let occ_str = match &self.occurrence {
Range::Single(x) => format!("minOccur {x}, maxOccur {x}"),
Range::Bounded(l, r) => format!("minOccur {l} , maxOccur {r}"),
Range::UnboundedL(r) => format!("maxOccur {r}"),
Range::UnboundedR(l) => format!("minOccur {l}"),
let mut strs = [size_str, occ_str]
.iter()
.filter(|s| !s.is_empty())
.join(", ");
if !strs.is_empty() {
strs = format!("({})", strs);
write!(f, "{strs}")
impl<A> Default for MSetAttr<A> {
MSetAttr {
occurrence: Range::Unbounded,
pub struct FuncAttr<A = Int> {
pub partiality: PartialityAttr,
pub jectivity: JectivityAttr,
impl<A: Display> Display for FuncAttr<A> {
Range::Single(x) => format!("size({x})"),
Range::Bounded(l, r) => format!("minSize({l}), maxSize({r})"),
Range::UnboundedL(r) => format!("maxSize({r})"),
Range::UnboundedR(l) => format!("minSize({l})"),
let mut strs = [
size_str,
self.partiality.to_string(),
self.jectivity.to_string(),
]
pub struct SequenceAttr<A = Int> {
impl<A> Default for SequenceAttr<A> {
SequenceAttr {
jectivity: JectivityAttr::None,
impl<A: Display> Display for SequenceAttr<A> {
let mut strs = [size_str, self.jectivity.to_string()]
pub struct PartitionAttr<A = Int> {
pub num_parts: Range<A>, // i.e. how many parts there are in the partition
pub part_len: Range<A>, // i.e. the size of each constitutent part
pub is_regular: bool,
impl<A: Display> Display for PartitionAttr<A> {
let num_parts_str = match &self.num_parts {
Range::Single(x) => format!("numParts {x}"),
Range::Bounded(l, r) => format!("minNumParts {l}, maxNumParts {r}"),
Range::UnboundedL(r) => format!("maxNumParts {r}"),
Range::UnboundedR(l) => format!("minNumParts {l}"),
let part_len_str = match &self.part_len {
Range::Single(x) => format!("partSize {x}"),
Range::Bounded(l, r) => format!("minPartSize {l} , maxPartSize {r}"),
Range::UnboundedL(r) => format!("maxPartSize {r}"),
Range::UnboundedR(l) => format!("minPartSize {l}"),
let regular_str = match &self.is_regular {
true => "regular".to_string(),
false => String::new(),
let mut strs = [num_parts_str, part_len_str, regular_str]
impl<A> Default for PartitionAttr<A> {
PartitionAttr {
num_parts: Range::Unbounded,
part_len: Range::Unbounded,
is_regular: false,
pub enum PartialityAttr {
Total,
Partial,
impl Display for PartialityAttr {
match self {
PartialityAttr::Total => write!(f, "total"),
PartialityAttr::Partial => write!(f, ""),
pub enum JectivityAttr {
None,
Injective,
Surjective,
Bijective,
impl Display for JectivityAttr {
JectivityAttr::None => write!(f, ""),
JectivityAttr::Injective => write!(f, "injective"),
JectivityAttr::Surjective => write!(f, "surjective"),
JectivityAttr::Bijective => write!(f, "bijective"),
pub struct RelAttr<A = Int> {
pub binary: Vec<BinaryAttr>,
impl<A> Default for RelAttr<A> {
RelAttr {
binary: Vec::new(),
impl<A: Display> Display for RelAttr<A> {
let mut strs = [size_str, self.binary.iter().join(", ")]
pub enum BinaryAttr {
Reflexive,
Irreflexive,
Coreflexive,
Symmetric,
AntiSymmetric,
ASymmetric,
Transitive,
Connex,
Euclidean,
Serial,
Equivalence,
PartialOrder,
impl Display for BinaryAttr {
BinaryAttr::Reflexive => write!(f, "reflexive"),
BinaryAttr::Irreflexive => write!(f, "irreflexive"),
BinaryAttr::Coreflexive => write!(f, "coreflexive"),
BinaryAttr::Symmetric => write!(f, "symmetric"),
BinaryAttr::AntiSymmetric => write!(f, "antiSymmetric"),
BinaryAttr::ASymmetric => write!(f, "aSymmetric"),
BinaryAttr::Transitive => write!(f, "transitive"),
BinaryAttr::Total => write!(f, "total"),
BinaryAttr::Connex => write!(f, "connex"),
BinaryAttr::Euclidean => write!(f, "Euclidean"),
BinaryAttr::Serial => write!(f, "serial"),
BinaryAttr::Equivalence => write!(f, "equivalence"),
BinaryAttr::PartialOrder => write!(f, "partialOrder"),