rusty-alto 0.1.0

Weighted tree automata and interpreted regular tree grammars with Alto-compatible I/O
Documentation
use super::RightStateInterner;
use crate::{
    CondensedTa, FxHashMap, KeySet, StateId,
    materialize::{IndexedCondensedIntersectionStats, OwnedCondensedRule},
};
use fixedbitset::FixedBitSet;
use std::hash::Hash;

#[derive(Default)]
pub(super) struct GenericCandidateSource;

#[derive(Default)]
pub(super) struct ChildStateRightRuleIndex {
    cache: FxHashMap<(usize, StateId), Vec<usize>>,
}

impl ChildStateRightRuleIndex {
    #[allow(clippy::too_many_arguments)]
    pub(super) fn rule_ids_for_trigger_into<R, I>(
        &mut self,
        right: &R,
        right_interner: &mut I,
        right_rules: &mut Vec<OwnedCondensedRule<StateId>>,
        stats: &mut IndexedCondensedIntersectionStats,
        position: usize,
        right_state: StateId,
        out: &mut Vec<usize>,
    ) where
        R: CondensedTa,
        R::State: Clone + Eq + Hash,
        I: RightStateInterner<R::State>,
    {
        out.clear();
        let cache_key = (position, right_state);
        if !self.cache.contains_key(&cache_key) {
            stats.right_indexed_queries += 1;
            let raw_state = right_interner.resolve(right_state).clone();
            let mut collected = Vec::new();
            right.condensed_rules_by_child(
                position,
                &raw_state,
                &mut |children, symbols, result| {
                    let rule_id = right_rules.len();
                    right_rules.push(OwnedCondensedRule {
                        children: children
                            .iter()
                            .cloned()
                            .map(|child| right_interner.intern(child))
                            .collect(),
                        symbols: symbols.clone(),
                        result: right_interner.intern(result),
                    });
                    collected.push(rule_id);
                },
            );
            self.cache.insert(cache_key, collected);
        }
        out.extend_from_slice(
            self.cache
                .get(&cache_key)
                .expect("cache entry was just inserted"),
        );
    }
}

#[derive(Default)]
pub(super) struct PartnerSet {
    states: Vec<StateId>,
    bits: FixedBitSet,
    products_by_left: Vec<Option<StateId>>,
}

impl PartnerSet {
    pub(super) fn insert(&mut self, state: StateId, product: StateId) -> bool {
        if self.bits.len() <= state.index() {
            self.bits.grow(state.index() + 1);
        }
        if self.products_by_left.len() <= state.index() {
            self.products_by_left.resize(state.index() + 1, None);
        }
        if self.bits.contains(state.index()) {
            return false;
        }
        self.bits.set(state.index(), true);
        self.products_by_left[state.index()] = Some(product);
        self.states.push(state);
        true
    }

    pub(super) fn len(&self) -> usize {
        self.states.len()
    }

    pub(super) fn product_for(&self, state: StateId) -> Option<StateId> {
        self.products_by_left.get(state.index()).and_then(|&p| p)
    }
}

impl KeySet<StateId> for PartnerSet {
    fn len(&self) -> usize {
        self.states.len()
    }

    fn contains(&self, key: &StateId) -> bool {
        key.index() < self.bits.len() && self.bits.contains(key.index())
    }

    fn for_each(&self, out: &mut dyn FnMut(&StateId)) {
        for state in &self.states {
            out(state);
        }
    }
}