aiken/crates/aiken-lang/src/gen_uplc/scope.rs

148 lines
3.6 KiB
Rust

#[derive(Debug, Clone, Default, Eq, PartialEq)]
pub struct Scope(pub(self) Vec<u64>);
impl From<Vec<u64>> for Scope {
fn from(value: Vec<u64>) -> Self {
Self(value)
}
}
impl Scope {
pub fn push(&mut self, value: u64) {
self.0.push(value);
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
/// Find the common ancestor with the replacement,
/// remove it from `self`, and then prepend the
/// `replacement` to `self`.
pub fn replace(&mut self, mut replacement: Scope) {
let common = self.common_ancestor(&replacement);
// we know that common will always be in the front of the
// scope Vec so we can always drain `0..common.len()`.
self.0.drain(0..common.0.len());
replacement.0.extend(self.0.iter());
self.0 = replacement.0;
}
pub fn common_ancestor(&self, other: &Self) -> Scope {
let longest_length = self.0.len().max(other.0.len());
if *self.0 == *other.0 {
return self.clone();
}
for index in 0..longest_length {
if self.0.get(index).is_none() {
return self.clone();
} else if other.0.get(index).is_none() {
return other.clone();
} else if self.0[index] != other.0[index] {
return Scope(self.0[0..index].to_vec());
}
}
Scope::default()
}
}
#[cfg(test)]
mod test {
use pretty_assertions::assert_eq;
use super::Scope;
#[test]
fn common_ancestor_equal_vecs() {
let ancestor = Scope(vec![1, 2, 3, 4, 5, 6]);
let descendant = Scope(vec![1, 2, 3, 4, 5, 6]);
let result = ancestor.common_ancestor(&descendant);
assert_eq!(result, Scope(vec![1, 2, 3, 4, 5, 6]))
}
#[test]
fn common_ancestor_equal_ancestor() {
let ancestor = Scope(vec![1, 2, 3, 4]);
let descendant = Scope(vec![1, 2, 3, 4, 5, 6]);
let result = ancestor.common_ancestor(&descendant);
assert_eq!(result, Scope(vec![1, 2, 3, 4]));
}
#[test]
fn common_ancestor_not_subset() {
let ancestor = Scope(vec![1, 2, 3, 4, 5]);
let descendant = Scope(vec![1, 2, 3, 7, 8]);
let result = ancestor.common_ancestor(&descendant);
assert_eq!(result, Scope(vec![1, 2, 3]));
}
#[test]
fn common_ancestor_not_found() {
let ancestor = Scope(vec![1, 2, 3, 4, 5, 6]);
let descendant = Scope(vec![4, 5, 6]);
let result = ancestor.common_ancestor(&descendant);
assert_eq!(result, Scope::default());
}
#[test]
fn common_ancestor_no_shared_values() {
let ancestor = Scope(vec![1, 2, 3]);
let descendant = Scope(vec![4, 5, 6]);
let result = ancestor.common_ancestor(&descendant);
assert_eq!(result, Scope::default());
}
#[test]
fn replace_same_value() {
let mut value = Scope(vec![1, 2, 3, 4, 5, 6]);
let replacement = Scope(vec![1, 2, 3, 4, 5, 6]);
value.replace(replacement);
assert_eq!(value, Scope(vec![1, 2, 3, 4, 5, 6]));
}
#[test]
fn replace_with_pattern() {
let mut value = Scope(vec![1, 2, 3, 4, 5]);
let replacement = Scope(vec![1, 2, 8, 9]);
value.replace(replacement);
assert_eq!(value, Scope(vec![1, 2, 8, 9, 3, 4, 5]));
}
#[test]
fn replace_with_no_pattern() {
let mut value = Scope(vec![1, 2, 3, 4, 5]);
let replacement = Scope(vec![8, 9]);
value.replace(replacement);
assert_eq!(value, Scope(vec![8, 9, 1, 2, 3, 4, 5]));
}
}