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

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 gc::{Finalize, Gc, Trace};6use jrsonnet_interner::IStr;7use rustc_hash::FxHashMap;8use std::fmt::Debug;9use std::hash::BuildHasherDefault;1011#[derive(Clone, Trace, Finalize)]12pub struct ContextCreator(pub Context, pub FutureWrapper<FxHashMap<IStr, LazyBinding>>);13impl ContextCreator {14	pub fn create(&self, this: Option<ObjValue>, super_obj: Option<ObjValue>) -> Result<Context> {15		self.0.clone().extend_unbound(16			self.1.clone().unwrap(),17			self.0.dollar().clone().or_else(|| this.clone()),18			this,19			super_obj,20		)21	}22}2324#[derive(Trace, Finalize)]25struct ContextInternals {26	dollar: Option<ObjValue>,27	this: Option<ObjValue>,28	super_obj: Option<ObjValue>,29	bindings: LayeredHashMap<LazyVal>,30}31impl Debug for ContextInternals {32	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {33		f.debug_struct("Context").finish()34	}35}3637#[derive(Debug, Clone, Trace, Finalize)]38pub struct Context(Gc<ContextInternals>);39impl Context {40	pub fn new_future() -> FutureWrapper<Self> {41		FutureWrapper::new()42	}4344	pub fn dollar(&self) -> &Option<ObjValue> {45		&self.0.dollar46	}4748	pub fn this(&self) -> &Option<ObjValue> {49		&self.0.this50	}5152	pub fn super_obj(&self) -> &Option<ObjValue> {53		&self.0.super_obj54	}5556	pub fn new() -> Self {57		Self(Gc::new(ContextInternals {58			dollar: None,59			this: None,60			super_obj: None,61			bindings: LayeredHashMap::default(),62		}))63	}6465	pub fn binding(&self, name: IStr) -> Result<LazyVal> {66		Ok(self67			.068			.bindings69			.get(&name)70			.cloned()71			.ok_or(VariableIsNotDefined(name))?)72	}73	pub fn into_future(self, ctx: FutureWrapper<Self>) -> Self {74		{75			ctx.0.borrow_mut().replace(self);76		}77		ctx.unwrap()78	}7980	pub fn with_var(self, name: IStr, value: Val) -> Self {81		let mut new_bindings =82			FxHashMap::with_capacity_and_hasher(1, BuildHasherDefault::default());83		new_bindings.insert(name, LazyVal::new_resolved(value));84		self.extend(new_bindings, None, None, None)85	}8687	pub fn with_this_super(self, new_this: ObjValue, new_super_obj: Option<ObjValue>) -> Self {88		self.extend(FxHashMap::default(), None, Some(new_this), new_super_obj)89	}9091	pub fn extend(92		self,93		new_bindings: FxHashMap<IStr, LazyVal>,94		new_dollar: Option<ObjValue>,95		new_this: Option<ObjValue>,96		new_super_obj: Option<ObjValue>,97	) -> Self {98		let ctx = &self.0;99		let dollar = new_dollar.or_else(|| ctx.dollar.clone());100		let this = new_this.or_else(|| ctx.this.clone());101		let super_obj = new_super_obj.or_else(|| ctx.super_obj.clone());102		let bindings = if new_bindings.is_empty() {103			ctx.bindings.clone()104		} else {105			ctx.bindings.clone().extend(new_bindings)106		};107		Self(Gc::new(ContextInternals {108			dollar,109			this,110			super_obj,111			bindings,112		}))113	}114	pub fn extend_bound(self, new_bindings: FxHashMap<IStr, LazyVal>) -> Self {115		let new_this = self.0.this.clone();116		let new_super_obj = self.0.super_obj.clone();117		self.extend(new_bindings, None, new_this, new_super_obj)118	}119	pub fn extend_unbound(120		self,121		new_bindings: FxHashMap<IStr, LazyBinding>,122		new_dollar: Option<ObjValue>,123		new_this: Option<ObjValue>,124		new_super_obj: Option<ObjValue>,125	) -> Result<Self> {126		let this = new_this.or_else(|| self.0.this.clone());127		let super_obj = new_super_obj.or_else(|| self.0.super_obj.clone());128		let mut new =129			FxHashMap::with_capacity_and_hasher(new_bindings.len(), BuildHasherDefault::default());130		for (k, v) in new_bindings.into_iter() {131			new.insert(k, v.evaluate(this.clone(), super_obj.clone())?);132		}133		Ok(self.extend(new, new_dollar, this, super_obj))134	}135	#[cfg(feature = "unstable")]136	pub fn into_weak(self) -> WeakContext {137		WeakContext(Rc::downgrade(&self.0))138	}139}140141impl Default for Context {142	fn default() -> Self {143		Self::new()144	}145}146147impl PartialEq for Context {148	fn eq(&self, other: &Self) -> bool {149		Gc::ptr_eq(&self.0, &other.0)150	}151}