use hashbrown::{hash_map::RawEntryMut, HashMap};
use std::sync::RwLock;
use crate::{
decl_engine::*, engine_threading::*, monomorphize::priv_prelude::*, namespace, TypeEngine,
};
pub(crate) struct GatherContext<'a> {
pub(crate) namespace: &'a GatherNamespace<'a>,
pub(crate) type_engine: &'a TypeEngine,
pub(crate) decl_engine: &'a DeclEngine,
constraints: &'a RwLock<HashMap<Constraint, usize>>,
}
impl<'a> GatherContext<'a> {
pub(crate) fn from_root(
root_namespace: &'a GatherNamespace<'a>,
engines: Engines<'a>,
constraints: &'a RwLock<HashMap<Constraint, usize>>,
) -> GatherContext<'a> {
Self::from_module_namespace(root_namespace, engines, constraints)
}
fn from_module_namespace(
namespace: &'a GatherNamespace<'a>,
engines: Engines<'a>,
constraints: &'a RwLock<HashMap<Constraint, usize>>,
) -> Self {
let (type_engine, decl_engine) = engines.unwrap();
Self {
namespace,
type_engine,
decl_engine,
constraints,
}
}
pub(crate) fn by_ref(&mut self) -> GatherContext<'_> {
GatherContext {
namespace: self.namespace,
type_engine: self.type_engine,
decl_engine: self.decl_engine,
constraints: self.constraints,
}
}
pub(crate) fn scoped(self, namespace: &'a GatherNamespace<'a>) -> GatherContext<'a> {
GatherContext {
namespace,
type_engine: self.type_engine,
decl_engine: self.decl_engine,
constraints: self.constraints,
}
}
pub(crate) fn add_constraint(&self, constraint: Constraint) {
let engines = Engines::new(self.type_engine, self.decl_engine);
let mut constraints = self.constraints.write().unwrap();
let hash_builder = constraints.hasher().clone();
let constraint_hash = make_hasher(&hash_builder, engines)(&constraint);
let raw_entry = constraints
.raw_entry_mut()
.from_hash(constraint_hash, |x| x.eq(&constraint, engines));
if let RawEntryMut::Vacant(v) = raw_entry {
v.insert_with_hasher(
constraint_hash,
constraint,
0,
make_hasher(&hash_builder, engines),
);
}
}
}
#[derive(Debug)]
pub(crate) struct GatherNamespace<'a> {
pub(crate) root: &'a namespace::Module,
pub(crate) mod_path: PathBuf,
}
impl<'a> GatherNamespace<'a> {
pub(crate) fn init_root(root: &'a namespace::Module) -> GatherNamespace<'a> {
let mod_path = vec![];
Self { root, mod_path }
}
pub(crate) fn new_with_module(&self, module: &namespace::Module) -> GatherNamespace<'_> {
let mut mod_path = self.mod_path.clone();
if let Some(name) = &module.name {
mod_path.push(name.clone());
}
GatherNamespace {
root: self.root,
mod_path,
}
}
pub(crate) fn module(&self) -> &namespace::Module {
&self.root[&self.mod_path]
}
}
impl<'a> std::ops::Deref for GatherNamespace<'a> {
type Target = namespace::Module;
fn deref(&self) -> &Self::Target {
self.module()
}
}