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

difftreelog

source

crates/jrsonnet-evaluator/src/ctx.rs3.6 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, Val,9};1011#[derive(Clone, Trace)]12pub struct ContextCreator(pub Context, pub FutureWrapper<GcHashMap<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)]25struct ContextInternals {26	dollar: Option<ObjValue>,27	this: Option<ObjValue>,28	super_obj: Option<ObjValue>,29	bindings: LayeredHashMap,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)]38pub struct Context(Cc<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(Cc::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 contains_binding(&self, name: IStr) -> bool {74		self.0.bindings.contains_key(&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 = GcHashMap::with_capacity(1);85		new_bindings.insert(name, LazyVal::new_resolved(value));86		self.extend(new_bindings, None, None, None)87	}8889	pub fn with_this_super(self, new_this: ObjValue, new_super_obj: Option<ObjValue>) -> Self {90		self.extend(GcHashMap::new(), None, Some(new_this), new_super_obj)91	}9293	pub fn extend(94		self,95		new_bindings: GcHashMap<IStr, LazyVal>,96		new_dollar: Option<ObjValue>,97		new_this: Option<ObjValue>,98		new_super_obj: Option<ObjValue>,99	) -> Self {100		let ctx = &self.0;101		let dollar = new_dollar.or_else(|| ctx.dollar.clone());102		let this = new_this.or_else(|| ctx.this.clone());103		let super_obj = new_super_obj.or_else(|| ctx.super_obj.clone());104		let bindings = if new_bindings.is_empty() {105			ctx.bindings.clone()106		} else {107			ctx.bindings.clone().extend(new_bindings)108		};109		Self(Cc::new(ContextInternals {110			dollar,111			this,112			super_obj,113			bindings,114		}))115	}116	pub fn extend_bound(self, new_bindings: GcHashMap<IStr, LazyVal>) -> Self {117		let new_this = self.0.this.clone();118		let new_super_obj = self.0.super_obj.clone();119		self.extend(new_bindings, None, new_this, new_super_obj)120	}121	pub fn extend_unbound(122		self,123		new_bindings: GcHashMap<IStr, LazyBinding>,124		new_dollar: Option<ObjValue>,125		new_this: Option<ObjValue>,126		new_super_obj: Option<ObjValue>,127	) -> Result<Self> {128		let this = new_this.or_else(|| self.0.this.clone());129		let super_obj = new_super_obj.or_else(|| self.0.super_obj.clone());130		let mut new = GcHashMap::with_capacity(new_bindings.len());131		for (k, v) in new_bindings.0.into_iter() {132			new.insert(k, v.evaluate(this.clone(), super_obj.clone())?);133		}134		Ok(self.extend(new, new_dollar, this, super_obj))135	}136}137138impl Default for Context {139	fn default() -> Self {140		Self::new()141	}142}143144impl PartialEq for Context {145	fn eq(&self, other: &Self) -> bool {146		cc_ptr_eq(&self.0, &other.0)147	}148}