knave 0.12.7

A Lisp programming language for humans and agents that infers types and ownership and compiles to readable Rust
Documentation
use std::rc::Rc;

use rustc_hash::FxHashMap;

use super::traits::TraitTable;
use super::ty::{Bound, Type};
use crate::core::BindingId;

#[derive(PartialEq)]
pub enum ClauseTarget {
    Type(Type),
    Trait(Bound),
}

impl ClauseTarget {
    pub fn covers(&self, later: &ClauseTarget, traits: &TraitTable) -> bool {
        match (self, later) {
            (Self::Type(earlier), Self::Type(later)) => earlier == later,
            (Self::Trait(earlier), Self::Type(later)) => {
                traits.satisfies(earlier, later, &|_, _| false)
            }
            (Self::Trait(earlier), Self::Trait(later)) => {
                traits.brings(later, &|brought| brought == earlier)
            }
            (Self::Type(_), Self::Trait(_)) => false,
        }
    }

    fn matches(&self, parameter: &Type, implements: &dyn Fn(&Bound) -> bool) -> bool {
        match self {
            Self::Type(exact) => exact == parameter,
            Self::Trait(bound) => implements(bound),
        }
    }
}

#[derive(Default)]
pub struct TemplateClauses {
    clauses: FxHashMap<BindingId, Vec<(ClauseTarget, Rc<str>)>>,
}

impl TemplateClauses {
    pub fn add(&mut self, binding: BindingId, clauses: Vec<(ClauseTarget, Rc<str>)>) {
        self.clauses.insert(binding, clauses);
    }

    pub fn chosen(
        &self,
        binding: BindingId,
        parameter: &Type,
        implements: &dyn Fn(&Bound) -> bool,
    ) -> Option<&Rc<str>> {
        self.clauses
            .get(&binding)?
            .iter()
            .find(|(target, _)| target.matches(parameter, implements))
            .map(|(_, template)| template)
    }
}