git.delta.rocks / jrsonnet / refs/commits / 11643ec5f009

difftreelog

source

crates/jrsonnet-evaluator/src/ctx.rs3.8 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, FutureWrapper, LazyBinding,8	LazyVal, ObjValue, Result, State, Val,9};1011#[derive(Clone, Trace)]12pub struct ContextCreator(pub Context, pub FutureWrapper<GcHashMap<IStr, LazyBinding>>);13impl ContextCreator {14	pub fn create(15		&self,16		s: State,17		this: Option<ObjValue>,18		super_obj: Option<ObjValue>,19	) -> Result<Context> {20		self.0.clone().extend_unbound(21			s,22			self.1.clone().unwrap(),23			self.0.dollar().clone().or_else(|| this.clone()),24			this,25			super_obj,26		)27	}28}2930#[derive(Trace)]31struct ContextInternals {32	dollar: Option<ObjValue>,33	this: Option<ObjValue>,34	super_obj: Option<ObjValue>,35	bindings: LayeredHashMap,36}37impl Debug for ContextInternals {38	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {39		f.debug_struct("Context").finish()40	}41}4243#[derive(Debug, Clone, Trace)]44pub struct Context(Cc<ContextInternals>);45impl Context {46	pub fn new_future() -> FutureWrapper<Self> {47		FutureWrapper::new()48	}4950	pub fn dollar(&self) -> &Option<ObjValue> {51		&self.0.dollar52	}5354	pub fn this(&self) -> &Option<ObjValue> {55		&self.0.this56	}5758	pub fn super_obj(&self) -> &Option<ObjValue> {59		&self.0.super_obj60	}6162	pub fn new() -> Self {63		Self(Cc::new(ContextInternals {64			dollar: None,65			this: None,66			super_obj: None,67			bindings: LayeredHashMap::default(),68		}))69	}7071	pub fn binding(&self, name: IStr) -> Result<LazyVal> {72		Ok(self73			.074			.bindings75			.get(&name)76			.cloned()77			.ok_or(VariableIsNotDefined(name))?)78	}79	pub fn contains_binding(&self, name: IStr) -> bool {80		self.0.bindings.contains_key(&name)81	}82	#[must_use]83	pub fn into_future(self, ctx: FutureWrapper<Self>) -> Self {84		{85			ctx.0.borrow_mut().replace(self);86		}87		ctx.unwrap()88	}8990	#[must_use]91	pub fn with_var(self, name: IStr, value: Val) -> Self {92		let mut new_bindings = GcHashMap::with_capacity(1);93		new_bindings.insert(name, LazyVal::new_resolved(value));94		self.extend(new_bindings, None, None, None)95	}9697	#[must_use]98	pub fn with_this_super(self, new_this: ObjValue, new_super_obj: Option<ObjValue>) -> Self {99		self.extend(GcHashMap::new(), None, Some(new_this), new_super_obj)100	}101102	#[must_use]103	pub fn extend(104		self,105		new_bindings: GcHashMap<IStr, LazyVal>,106		new_dollar: Option<ObjValue>,107		new_this: Option<ObjValue>,108		new_super_obj: Option<ObjValue>,109	) -> Self {110		let ctx = &self.0;111		let dollar = new_dollar.or_else(|| ctx.dollar.clone());112		let this = new_this.or_else(|| ctx.this.clone());113		let super_obj = new_super_obj.or_else(|| ctx.super_obj.clone());114		let bindings = if new_bindings.is_empty() {115			ctx.bindings.clone()116		} else {117			ctx.bindings.clone().extend(new_bindings)118		};119		Self(Cc::new(ContextInternals {120			dollar,121			this,122			super_obj,123			bindings,124		}))125	}126	#[must_use]127	pub fn extend_bound(self, new_bindings: GcHashMap<IStr, LazyVal>) -> Self {128		let new_this = self.0.this.clone();129		let new_super_obj = self.0.super_obj.clone();130		self.extend(new_bindings, None, new_this, new_super_obj)131	}132	pub fn extend_unbound(133		self,134		s: State,135		new_bindings: GcHashMap<IStr, LazyBinding>,136		new_dollar: Option<ObjValue>,137		new_this: Option<ObjValue>,138		new_super_obj: Option<ObjValue>,139	) -> Result<Self> {140		let this = new_this.or_else(|| self.0.this.clone());141		let super_obj = new_super_obj.or_else(|| self.0.super_obj.clone());142		let mut new = GcHashMap::with_capacity(new_bindings.len());143		for (k, v) in new_bindings.0 {144			new.insert(k, v.evaluate(s.clone(), this.clone(), super_obj.clone())?);145		}146		Ok(self.extend(new, new_dollar, this, super_obj))147	}148}149150impl Default for Context {151	fn default() -> Self {152		Self::new()153	}154}155156impl PartialEq for Context {157	fn eq(&self, other: &Self) -> bool {158		cc_ptr_eq(&self.0, &other.0)159	}160}