git.delta.rocks / jrsonnet / refs/commits / bf70e2e2a045

difftreelog

source

crates/jrsonnet-evaluator/src/ctx.rs3.8 KiBsourcehistory
1use crate::{2	error::Error::*, map::LayeredHashMap, FutureWrapper, LazyBinding, LazyVal, ObjValue, Result,3	Val,4};5use jrsonnet_gc::{Gc, Trace};6use jrsonnet_interner::IStr;7use rustc_hash::FxHashMap;8use std::fmt::Debug;9use std::hash::BuildHasherDefault;1011#[derive(Clone, Trace)]12#[trivially_drop]13pub struct ContextCreator(pub Context, pub FutureWrapper<FxHashMap<IStr, LazyBinding>>);14impl ContextCreator {15	pub fn create(&self, this: Option<ObjValue>, super_obj: Option<ObjValue>) -> Result<Context> {16		self.0.clone().extend_unbound(17			self.1.clone().unwrap(),18			self.0.dollar().clone().or_else(|| this.clone()),19			this,20			super_obj,21		)22	}23}2425#[derive(Trace)]26#[trivially_drop]27struct ContextInternals {28	dollar: Option<ObjValue>,29	this: Option<ObjValue>,30	super_obj: Option<ObjValue>,31	bindings: LayeredHashMap,32}33impl Debug for ContextInternals {34	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {35		f.debug_struct("Context").finish()36	}37}3839#[derive(Debug, Clone, Trace)]40#[trivially_drop]41pub struct Context(Gc<ContextInternals>);42impl Context {43	pub fn new_future() -> FutureWrapper<Self> {44		FutureWrapper::new()45	}4647	pub fn dollar(&self) -> &Option<ObjValue> {48		&self.0.dollar49	}5051	pub fn this(&self) -> &Option<ObjValue> {52		&self.0.this53	}5455	pub fn super_obj(&self) -> &Option<ObjValue> {56		&self.0.super_obj57	}5859	pub fn new() -> Self {60		Self(Gc::new(ContextInternals {61			dollar: None,62			this: None,63			super_obj: None,64			bindings: LayeredHashMap::default(),65		}))66	}6768	pub fn binding(&self, name: IStr) -> Result<LazyVal> {69		Ok(self70			.071			.bindings72			.get(&name)73			.cloned()74			.ok_or(VariableIsNotDefined(name))?)75	}76	pub fn into_future(self, ctx: FutureWrapper<Self>) -> Self {77		{78			ctx.0.borrow_mut().replace(self);79		}80		ctx.unwrap()81	}8283	pub fn with_var(self, name: IStr, value: Val) -> Self {84		let mut new_bindings =85			FxHashMap::with_capacity_and_hasher(1, BuildHasherDefault::default());86		new_bindings.insert(name, LazyVal::new_resolved(value));87		self.extend(new_bindings, None, None, None)88	}8990	pub fn with_this_super(self, new_this: ObjValue, new_super_obj: Option<ObjValue>) -> Self {91		self.extend(FxHashMap::default(), None, Some(new_this), new_super_obj)92	}9394	pub fn extend(95		self,96		new_bindings: FxHashMap<IStr, LazyVal>,97		new_dollar: Option<ObjValue>,98		new_this: Option<ObjValue>,99		new_super_obj: Option<ObjValue>,100	) -> Self {101		let ctx = &self.0;102		let dollar = new_dollar.or_else(|| ctx.dollar.clone());103		let this = new_this.or_else(|| ctx.this.clone());104		let super_obj = new_super_obj.or_else(|| ctx.super_obj.clone());105		let bindings = if new_bindings.is_empty() {106			ctx.bindings.clone()107		} else {108			ctx.bindings.clone().extend(new_bindings)109		};110		Self(Gc::new(ContextInternals {111			dollar,112			this,113			super_obj,114			bindings,115		}))116	}117	pub fn extend_bound(self, new_bindings: FxHashMap<IStr, LazyVal>) -> Self {118		let new_this = self.0.this.clone();119		let new_super_obj = self.0.super_obj.clone();120		self.extend(new_bindings, None, new_this, new_super_obj)121	}122	pub fn extend_unbound(123		self,124		new_bindings: FxHashMap<IStr, LazyBinding>,125		new_dollar: Option<ObjValue>,126		new_this: Option<ObjValue>,127		new_super_obj: Option<ObjValue>,128	) -> Result<Self> {129		let this = new_this.or_else(|| self.0.this.clone());130		let super_obj = new_super_obj.or_else(|| self.0.super_obj.clone());131		let mut new =132			FxHashMap::with_capacity_and_hasher(new_bindings.len(), BuildHasherDefault::default());133		for (k, v) in new_bindings.into_iter() {134			new.insert(k, v.evaluate(this.clone(), super_obj.clone())?);135		}136		Ok(self.extend(new, new_dollar, this, super_obj))137	}138	#[cfg(feature = "unstable")]139	pub fn into_weak(self) -> WeakContext {140		WeakContext(Rc::downgrade(&self.0))141	}142}143144impl Default for Context {145	fn default() -> Self {146		Self::new()147	}148}149150impl PartialEq for Context {151	fn eq(&self, other: &Self) -> bool {152		Gc::ptr_eq(&self.0, &other.0)153	}154}