jrsonnet-evaluator 0.5.0-pre6

jsonnet interpreter
Documentation
use jrsonnet_gcmodule::{Cc, Trace};
use jrsonnet_interner::IStr;

use crate::{GcHashMap, Thunk, Val};

#[derive(Trace)]
#[trace(tracking(force))]
pub struct LayeredHashMapInternals {
	parent: Option<LayeredHashMap>,
	current: GcHashMap<IStr, Thunk<Val>>,
}

#[derive(Trace)]
pub struct LayeredHashMap(Cc<LayeredHashMapInternals>);

impl LayeredHashMap {
	pub fn iter_keys(self, mut handler: impl FnMut(IStr)) {
		for (k, _) in self.0.current.iter() {
			handler(k.clone());
		}
		if let Some(parent) = self.0.parent.clone() {
			parent.iter_keys(handler);
		}
	}

	pub(crate) fn new(layer: GcHashMap<IStr, Thunk<Val>>) -> Self {
		Self(Cc::new(LayeredHashMapInternals {
			parent: None,
			current: layer,
		}))
	}

	pub fn extend(self, new_layer: GcHashMap<IStr, Thunk<Val>>) -> Self {
		Self(Cc::new(LayeredHashMapInternals {
			parent: Some(self),
			current: new_layer,
		}))
	}

	pub fn get(&self, key: &IStr) -> Option<&Thunk<Val>> {
		(self.0)
			.current
			.get(key)
			.or_else(|| self.0.parent.as_ref().and_then(|p| p.get(key)))
	}

	pub fn contains_key(&self, key: &IStr) -> bool {
		(self.0).current.contains_key(key)
			|| self
				.0
				.parent
				.as_ref()
				.map_or(false, |p| p.contains_key(key))
	}
}

impl Clone for LayeredHashMap {
	fn clone(&self) -> Self {
		Self(self.0.clone())
	}
}

impl Default for LayeredHashMap {
	fn default() -> Self {
		Self(Cc::new(LayeredHashMapInternals {
			parent: None,
			current: GcHashMap::new(),
		}))
	}
}