meplang 0.1.8

An EVM low-level language that gives full control over the control flow of the smart contract.
Documentation
use std::collections::{HashMap, HashSet};
use std::fmt::Debug;
use std::hash::Hash;

use indexmap::IndexSet;

#[derive(Debug, Clone)]
pub struct DepsGraph<T: Debug + Clone> {
    parents: HashMap<T, HashSet<T>>,
    children: HashMap<T, HashSet<T>>,
    leaves: IndexSet<T>,
}

impl<T: Default + Debug + Clone> Default for DepsGraph<T> {
    fn default() -> Self {
        Self {
            parents: HashMap::new(),
            children: HashMap::new(),
            leaves: IndexSet::new(),
        }
    }
}

impl<T: Default + Debug + Clone + Eq + Hash> DepsGraph<T> {
    pub fn new() -> Self {
        Self::default()
    }

    pub fn add_node_if_needed(&mut self, item: &T) {
        if let Some(set) = self.children.get(item) {
            if set.len() > 0 {
                return;
            }
        }
        if let Some(set) = self.parents.get(item) {
            if set.len() > 0 {
                return;
            }
        }
        self.leaves.insert(item.clone());
    }

    pub fn insert_if_needed(&mut self, item: &T, dependency: &T) -> bool {
        let res = self.insert_child(item, dependency);
        assert!(self.insert_parent(item, dependency));
        if let Some(set) = self.children.get(dependency) {
            if set.len() > 0 {
                self.leaves.swap_remove(dependency);
                return res;
            }
        }
        self.leaves.insert(dependency.clone());
        res
    }

    pub fn pop_leaf(&mut self) -> Option<T> {
        let Some(leaf) = self.leaves.pop() else {
            return None;
        };
        assert!(self.children.get(&leaf).is_none());
        if let Some(parents) = self.parents.remove(&leaf) {
            for parent in parents {
                let set = self.children.get_mut(&parent).unwrap();
                if set.len() == 1 {
                    assert!(self.children.remove(&parent).is_some());
                    self.leaves.insert(parent);
                } else {
                    assert!(set.remove(&leaf));
                }
            }
        }
        Some(leaf)
    }

    pub fn is_empty(&self) -> bool {
        self.children.len() == 0 && self.parents.len() == 0
    }

    pub fn leaves(&self) -> impl Iterator<Item = &T> {
        self.leaves.iter()
    }

    fn insert_child(&mut self, parent: &T, child: &T) -> bool {
        self.leaves.swap_remove(parent);
        insert_or_create(&mut self.children, parent, child)
    }

    fn insert_parent(&mut self, parent: &T, child: &T) -> bool {
        self.leaves.swap_remove(child);
        insert_or_create(&mut self.parents, child, parent)
    }
}

fn insert_or_create<X, Y>(hash_map: &mut HashMap<X, HashSet<Y>>, x: &X, y: &Y) -> bool
where
    X: Clone + Eq + Hash,
    Y: Clone + Eq + Hash,
{
    let Some(set) = hash_map.get_mut(x) else {
        hash_map.insert(x.clone(), [y.clone()].into());
        return true;
    };
    if set.contains(y) {
        return false;
    }
    set.insert(y.clone());
    return true;
}