git.delta.rocks / jrsonnet / refs/commits / 476a9c192b8a

difftreelog

source

crates/jrsonnet-evaluator/src/ctx.rs3.5 KiBsourcehistory
1use crate::{2	create_error, future_wrapper, map::LayeredHashMap, rc_fn_helper, resolved_lazy_val, Error,3	LazyBinding, LazyVal, ObjValue, Result, Val,4};5use std::{6	cell::RefCell,7	collections::HashMap,8	fmt::Debug,9	rc::{Rc, Weak},10};1112rc_fn_helper!(13	ContextCreator,14	context_creator,15	dyn Fn(Option<ObjValue>, Option<ObjValue>) -> Result<Context>16);1718future_wrapper!(Context, FutureContext);1920struct ContextInternals {21	dollar: Option<ObjValue>,22	this: Option<ObjValue>,23	super_obj: Option<ObjValue>,24	bindings: LayeredHashMap<Rc<str>, LazyVal>,25}26impl Debug for ContextInternals {27	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {28		f.debug_struct("Context")29			.field("this", &self.this.as_ref().map(|e| Rc::as_ptr(&e.0)))30			.field("bindings", &self.bindings)31			.finish()32	}33}3435#[derive(Debug, Clone)]36pub struct Context(Rc<ContextInternals>);37impl Context {38	pub fn new_future() -> FutureContext {39		FutureContext(Rc::new(RefCell::new(None)))40	}4142	pub fn dollar(&self) -> &Option<ObjValue> {43		&self.0.dollar44	}4546	pub fn this(&self) -> &Option<ObjValue> {47		&self.0.this48	}4950	pub fn super_obj(&self) -> &Option<ObjValue> {51		&self.0.super_obj52	}5354	pub fn new() -> Context {55		Context(Rc::new(ContextInternals {56			dollar: None,57			this: None,58			super_obj: None,59			bindings: LayeredHashMap::default(),60		}))61	}6263	pub fn binding(&self, name: Rc<str>) -> Result<LazyVal> {64		self.065			.bindings66			.get(&name)67			.cloned()68			.ok_or_else(|| create_error(Error::UnknownVariable(name)))69	}70	pub fn into_future(self, ctx: FutureContext) -> Context {71		{72			ctx.0.borrow_mut().replace(self);73		}74		ctx.unwrap()75	}7677	pub fn with_var(&self, name: Rc<str>, value: Val) -> Result<Context> {78		let mut new_bindings = HashMap::with_capacity(1);79		new_bindings.insert(name, resolved_lazy_val!(value));80		self.extend(new_bindings, None, None, None)81	}8283	pub fn extend(84		&self,85		new_bindings: HashMap<Rc<str>, LazyVal>,86		new_dollar: Option<ObjValue>,87		new_this: Option<ObjValue>,88		new_super_obj: Option<ObjValue>,89	) -> Result<Context> {90		let dollar = new_dollar.or_else(|| self.0.dollar.clone());91		let this = new_this.or_else(|| self.0.this.clone());92		let super_obj = new_super_obj.or_else(|| self.0.super_obj.clone());93		let bindings = if new_bindings.is_empty() {94			self.0.bindings.clone()95		} else {96			self.0.bindings.extend(new_bindings)97		};98		Ok(Context(Rc::new(ContextInternals {99			dollar,100			this,101			super_obj,102			bindings,103		})))104	}105	pub fn extend_unbound(106		&self,107		new_bindings: HashMap<Rc<str>, LazyBinding>,108		new_dollar: Option<ObjValue>,109		new_this: Option<ObjValue>,110		new_super_obj: Option<ObjValue>,111	) -> Result<Context> {112		let this = new_this.or_else(|| self.0.this.clone());113		let super_obj = new_super_obj.or_else(|| self.0.super_obj.clone());114		let mut new = HashMap::with_capacity(new_bindings.len());115		for (k, v) in new_bindings.into_iter() {116			new.insert(k, v.evaluate(this.clone(), super_obj.clone())?);117		}118		self.extend(new, new_dollar, this, super_obj)119	}120	pub fn into_weak(self) -> WeakContext {121		WeakContext(Rc::downgrade(&self.0))122	}123}124125impl Default for Context {126	fn default() -> Self {127		Self::new()128	}129}130131impl PartialEq for Context {132	fn eq(&self, other: &Self) -> bool {133		Rc::ptr_eq(&self.0, &other.0)134	}135}136137#[derive(Debug, Clone)]138pub struct WeakContext(Weak<ContextInternals>);139impl WeakContext {140	pub fn upgrade(&self) -> Context {141		Context(self.0.upgrade().expect("context is removed"))142	}143}144impl PartialEq for WeakContext {145	fn eq(&self, other: &Self) -> bool {146		self.0.ptr_eq(&other.0)147	}148}