///|
/// A validated set of alternatives, not simultaneous relations.
pub struct RelSet {
priv bits : Int32
} derive(Eq, Debug)
///|
pub extend RelSet with Eq::{equal, not_equal}
///|
pub extend RelSet with @debug.Debug::{to_repr}
///|
pub fn RelSet::empty() -> RelSet {
{ bits: 0, }
}
///|
pub fn RelSet::all() -> RelSet {
{ bits: 8191, }
}
///|
pub fn RelSet::single(r : Relation) -> RelSet {
{ bits: 1 << r.index(), }
}
///|
pub fn RelSet::from_mask(mask : Int32) -> RelSet raise AllenError {
if mask < 0 || mask > 8191 {
raise InvalidMask(mask)
}
{ bits: mask, }
}
///|
pub fn RelSet::of(items : Array[Relation]) -> RelSet {
let mut bits = 0
for r in items {
bits = bits | (1 << r.index())
}
{ bits, }
}
///|
pub fn RelSet::mask(self : RelSet) -> Int32 {
self.bits
}
///|
pub fn RelSet::has(self : RelSet, r : Relation) -> Bool {
(self.bits & (1 << r.index())) != 0
}
///|
pub fn RelSet::union(self : RelSet, other : RelSet) -> RelSet {
{ bits: self.bits | other.bits, }
}
///|
pub fn RelSet::intersect(self : RelSet, other : RelSet) -> RelSet {
{ bits: self.bits & other.bits, }
}
///|
pub fn RelSet::difference(self : RelSet, other : RelSet) -> RelSet {
{ bits: self.bits & (8191 ^ other.bits), }
}
///|
pub fn RelSet::subset_of(self : RelSet, other : RelSet) -> Bool {
(self.bits & other.bits) == self.bits
}
///|
pub fn RelSet::is_empty(self : RelSet) -> Bool {
self.bits == 0
}
///|
pub fn RelSet::size(self : RelSet) -> Int32 {
let mut n = 0
for r in relations() {
if self.has(r) {
n = n + 1
}
}
n
}
///|
pub fn RelSet::items(self : RelSet) -> Array[Relation] {
let out = []
for r in relations() {
if self.has(r) {
out.push(r)
}
}
out
}
///|
pub fn RelSet::converse(self : RelSet) -> RelSet {
RelSet::of(self.items().map(r => r.converse()))
}
///|
pub fn RelSet::render(self : RelSet) -> String {
if self.is_empty() {
return "-"
}
if self.bits == 8191 {
return "*"
}
self.items().map(r => r.token()).join("|")
}
///|
pub fn parse_relset(text : String) -> RelSet raise AllenError {
if text == "-" {
return RelSet::empty()
}
if text == "*" {
return RelSet::all()
}
if text == "" {
raise InvalidRelation(text)
}
let mut set = RelSet::empty()
for part in text.split("|") {
set = set.union(RelSet::single(parse_relation(part.to_owned())))
}
set
}