git.delta.rocks / jrsonnet / refs/commits / 32f6ee5b9541

difftreelog

source

crates/jrsonnet-evaluator/src/ctx.rs2.3 KiBsourcehistory
1use std::fmt::Debug;23use gcmodule::{Cc, Trace};4use jrsonnet_interner::IStr;56use crate::{7	cc_ptr_eq, error::Error::*, gc::GcHashMap, map::LayeredHashMap, ObjValue, Pending, Result,8	Thunk, Val,9};1011#[derive(Trace)]12struct ContextInternals {13	dollar: Option<ObjValue>,14	sup: Option<ObjValue>,15	this: Option<ObjValue>,16	bindings: LayeredHashMap,17}18impl Debug for ContextInternals {19	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {20		f.debug_struct("Context").finish()21	}22}2324#[derive(Debug, Clone, Trace)]25pub struct Context(Cc<ContextInternals>);26impl Context {27	pub fn new_future() -> Pending<Self> {28		Pending::new()29	}3031	pub fn dollar(&self) -> &Option<ObjValue> {32		&self.0.dollar33	}3435	pub fn this(&self) -> &Option<ObjValue> {36		&self.0.this37	}3839	pub fn super_obj(&self) -> &Option<ObjValue> {40		&self.0.sup41	}4243	pub fn new() -> Self {44		Self(Cc::new(ContextInternals {45			dollar: None,46			this: None,47			sup: None,48			bindings: LayeredHashMap::default(),49		}))50	}5152	pub fn binding(&self, name: IStr) -> Result<Thunk<Val>> {53		Ok(self54			.055			.bindings56			.get(&name)57			.cloned()58			.ok_or(VariableIsNotDefined(name))?)59	}60	pub fn contains_binding(&self, name: IStr) -> bool {61		self.0.bindings.contains_key(&name)62	}63	#[must_use]64	pub fn into_future(self, ctx: Pending<Self>) -> Self {65		{66			ctx.0.borrow_mut().replace(self);67		}68		ctx.unwrap()69	}7071	#[must_use]72	pub fn with_var(self, name: IStr, value: Val) -> Self {73		let mut new_bindings = GcHashMap::with_capacity(1);74		new_bindings.insert(name, Thunk::evaluated(value));75		self.extend(new_bindings, None, None, None)76	}7778	#[must_use]79	pub fn extend(80		self,81		new_bindings: GcHashMap<IStr, Thunk<Val>>,82		new_dollar: Option<ObjValue>,83		new_sup: Option<ObjValue>,84		new_this: Option<ObjValue>,85	) -> Self {86		let ctx = &self.0;87		let dollar = new_dollar.or_else(|| ctx.dollar.clone());88		let this = new_this.or_else(|| ctx.this.clone());89		let sup = new_sup.or_else(|| ctx.sup.clone());90		let bindings = if new_bindings.is_empty() {91			ctx.bindings.clone()92		} else {93			ctx.bindings.clone().extend(new_bindings)94		};95		Self(Cc::new(ContextInternals {96			dollar,97			sup,98			this,99			bindings,100		}))101	}102}103104impl Default for Context {105	fn default() -> Self {106		Self::new()107	}108}109110impl PartialEq for Context {111	fn eq(&self, other: &Self) -> bool {112		cc_ptr_eq(&self.0, &other.0)113	}114}