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

difftreelog

feat impl ArgLike for Thunk<Val>

Yaroslav Bolyukin2023-04-08parent: #685a983.patch.diff
in: master

1 file changed

modifiedcrates/jrsonnet-evaluator/src/function/arglike.rsdiffbeforeafterboth
before · crates/jrsonnet-evaluator/src/function/arglike.rs
1use hashbrown::HashMap;2use jrsonnet_gcmodule::Trace;3use jrsonnet_interner::IStr;4use jrsonnet_parser::{ArgsDesc, LocExpr};56use crate::{7	error::Result,8	evaluate,9	gc::GcHashMap,10	typed::Typed,11	val::{StrValue, ThunkValue},12	Context, Thunk, Val,13};1415/// Marker for arguments, which can be evaluated with context set to None16pub trait OptionalContext {}1718#[derive(Trace)]19struct EvaluateThunk {20	ctx: Context,21	expr: LocExpr,22}23impl ThunkValue for EvaluateThunk {24	type Output = Val;25	fn get(self: Box<Self>) -> Result<Val> {26		evaluate(self.ctx, &self.expr)27	}28}2930pub trait ArgLike {31	fn evaluate_arg(&self, ctx: Context, tailstrict: bool) -> Result<Thunk<Val>>;32}3334impl ArgLike for &LocExpr {35	fn evaluate_arg(&self, ctx: Context, tailstrict: bool) -> Result<Thunk<Val>> {36		Ok(if tailstrict {37			Thunk::evaluated(evaluate(ctx, self)?)38		} else {39			Thunk::new(EvaluateThunk {40				ctx,41				expr: (*self).clone(),42			})43		})44	}45}4647impl<T> ArgLike for T48where49	T: Typed + Clone,50{51	fn evaluate_arg(&self, _ctx: Context, _tailstrict: bool) -> Result<Thunk<Val>> {52		let val = T::into_untyped(self.clone())?;53		Ok(Thunk::evaluated(val))54	}55}56impl<T> OptionalContext for T where T: Typed + Clone {}5758#[derive(Clone, Trace)]59pub enum TlaArg {60	String(IStr),61	Code(LocExpr),62	Val(Val),63}64impl ArgLike for TlaArg {65	fn evaluate_arg(&self, ctx: Context, tailstrict: bool) -> Result<Thunk<Val>> {66		match self {67			TlaArg::String(s) => Ok(Thunk::evaluated(Val::Str(StrValue::Flat(s.clone())))),68			TlaArg::Code(code) => Ok(if tailstrict {69				Thunk::evaluated(evaluate(ctx, code)?)70			} else {71				Thunk::new(EvaluateThunk {72					ctx,73					expr: code.clone(),74				})75			}),76			TlaArg::Val(val) => Ok(Thunk::evaluated(val.clone())),77		}78	}79}8081mod sealed {82	/// Implemented for `ArgsLike`, where only unnamed arguments present83	pub trait Unnamed {}84	/// Implemented for `ArgsLike`, where only named arguments present85	pub trait Named {}86}8788pub trait ArgsLike {89	fn unnamed_len(&self) -> usize;90	fn unnamed_iter(91		&self,92		ctx: Context,93		tailstrict: bool,94		handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,95	) -> Result<()>;96	fn named_iter(97		&self,98		ctx: Context,99		tailstrict: bool,100		handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,101	) -> Result<()>;102	fn named_names(&self, handler: &mut dyn FnMut(&IStr));103}104105impl ArgsLike for Vec<Val> {106	fn unnamed_len(&self) -> usize {107		self.len()108	}109	fn unnamed_iter(110		&self,111		_ctx: Context,112		_tailstrict: bool,113		handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,114	) -> Result<()> {115		for (idx, el) in self.iter().enumerate() {116			handler(idx, Thunk::evaluated(el.clone()))?;117		}118		Ok(())119	}120	fn named_iter(121		&self,122		_ctx: Context,123		_tailstrict: bool,124		_handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,125	) -> Result<()> {126		Ok(())127	}128	fn named_names(&self, _handler: &mut dyn FnMut(&IStr)) {}129}130131impl ArgsLike for ArgsDesc {132	fn unnamed_len(&self) -> usize {133		self.unnamed.len()134	}135136	fn unnamed_iter(137		&self,138		ctx: Context,139		tailstrict: bool,140		handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,141	) -> Result<()> {142		for (id, arg) in self.unnamed.iter().enumerate() {143			handler(144				id,145				if tailstrict {146					Thunk::evaluated(evaluate(ctx.clone(), arg)?)147				} else {148					Thunk::new(EvaluateThunk {149						ctx: ctx.clone(),150						expr: arg.clone(),151					})152				},153			)?;154		}155		Ok(())156	}157158	fn named_iter(159		&self,160		ctx: Context,161		tailstrict: bool,162		handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,163	) -> Result<()> {164		for (name, arg) in &self.named {165			handler(166				name,167				if tailstrict {168					Thunk::evaluated(evaluate(ctx.clone(), arg)?)169				} else {170					Thunk::new(EvaluateThunk {171						ctx: ctx.clone(),172						expr: arg.clone(),173					})174				},175			)?;176		}177		Ok(())178	}179180	fn named_names(&self, handler: &mut dyn FnMut(&IStr)) {181		for (name, _) in &self.named {182			handler(name);183		}184	}185}186187impl<V: ArgLike, S> sealed::Named for HashMap<IStr, V, S> {}188impl<V: ArgLike, S> ArgsLike for HashMap<IStr, V, S> {189	fn unnamed_len(&self) -> usize {190		0191	}192193	fn unnamed_iter(194		&self,195		_ctx: Context,196		_tailstrict: bool,197		_handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,198	) -> Result<()> {199		Ok(())200	}201202	fn named_iter(203		&self,204		ctx: Context,205		tailstrict: bool,206		handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,207	) -> Result<()> {208		for (name, value) in self.iter() {209			handler(name, value.evaluate_arg(ctx.clone(), tailstrict)?)?;210		}211		Ok(())212	}213214	fn named_names(&self, handler: &mut dyn FnMut(&IStr)) {215		for (name, _) in self.iter() {216			handler(name);217		}218	}219}220impl<V, S> OptionalContext for HashMap<IStr, V, S> where V: ArgLike + OptionalContext {}221222impl<A: ArgLike> ArgsLike for GcHashMap<IStr, A> {223	fn unnamed_len(&self) -> usize {224		self.0.unnamed_len()225	}226227	fn unnamed_iter(228		&self,229		ctx: Context,230		tailstrict: bool,231		handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,232	) -> Result<()> {233		self.0.unnamed_iter(ctx, tailstrict, handler)234	}235236	fn named_iter(237		&self,238		ctx: Context,239		tailstrict: bool,240		handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,241	) -> Result<()> {242		self.0.named_iter(ctx, tailstrict, handler)243	}244245	fn named_names(&self, handler: &mut dyn FnMut(&IStr)) {246		self.0.named_names(handler);247	}248}249250macro_rules! impl_args_like {251	($count:expr; $($gen:ident)*) => {252		impl<$($gen: ArgLike,)*> sealed::Unnamed for ($($gen,)*) {}253		impl<$($gen: ArgLike,)*> ArgsLike for ($($gen,)*) {254			fn unnamed_len(&self) -> usize {255				$count256			}257			#[allow(non_snake_case, unused_assignments)]258			fn unnamed_iter(259				&self,260				ctx: Context,261				tailstrict: bool,262				handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,263			) -> Result<()> {264				let mut i = 0usize;265				let ($($gen,)*) = self;266				$(267					handler(i, $gen.evaluate_arg(ctx.clone(), tailstrict)?)?;268					i+=1;269				)*270				Ok(())271			}272			fn named_iter(273				&self,274				_ctx: Context,275				_tailstrict: bool,276				_handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,277			) -> Result<()> {278				Ok(())279			}280			fn named_names(&self, _handler: &mut dyn FnMut(&IStr)) {}281		}282		impl<$($gen: ArgLike,)*> OptionalContext for ($($gen,)*) where $($gen: OptionalContext),* {}283284		impl<$($gen: ArgLike,)*> sealed::Named for ($((IStr, $gen),)*) {}285		impl<$($gen: ArgLike,)*> ArgsLike for ($((IStr, $gen),)*) {286			fn unnamed_len(&self) -> usize {287				0288			}289			fn unnamed_iter(290				&self,291				_ctx: Context,292				_tailstrict: bool,293				_handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,294			) -> Result<()> {295				Ok(())296			}297			#[allow(non_snake_case)]298			fn named_iter(299				&self,300				ctx: Context,301				tailstrict: bool,302				handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,303			) -> Result<()> {304				let ($($gen,)*) = self;305				$(306					handler(&$gen.0, $gen.1.evaluate_arg(ctx.clone(), tailstrict)?)?;307				)*308				Ok(())309			}310			#[allow(non_snake_case)]311			fn named_names(&self, handler: &mut dyn FnMut(&IStr)) {312				let ($($gen,)*) = self;313				$(314					handler(&$gen.0);315				)*316			}317		}318		impl<$($gen: ArgLike,)*> OptionalContext for ($((IStr, $gen),)*) where $($gen: OptionalContext),* {}319	};320	($count:expr; $($cur:ident)* @ $c:ident $($rest:ident)*) => {321		impl_args_like!($count; $($cur)*);322		impl_args_like!($count + 1usize; $($cur)* $c @ $($rest)*);323	};324	($count:expr; $($cur:ident)* @) => {325		impl_args_like!($count; $($cur)*);326	}327}328impl_args_like! {329	// First argument is already in position, so count starts from 1330	1usize; A @ B C D E F G H I J K L331}332333impl ArgsLike for () {334	fn unnamed_len(&self) -> usize {335		0336	}337338	fn unnamed_iter(339		&self,340		_ctx: Context,341		_tailstrict: bool,342		_handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,343	) -> Result<()> {344		Ok(())345	}346347	fn named_iter(348		&self,349		_ctx: Context,350		_tailstrict: bool,351		_handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,352	) -> Result<()> {353		Ok(())354	}355356	fn named_names(&self, _handler: &mut dyn FnMut(&IStr)) {}357}358impl OptionalContext for () {}
after · crates/jrsonnet-evaluator/src/function/arglike.rs
1use hashbrown::HashMap;2use jrsonnet_gcmodule::Trace;3use jrsonnet_interner::IStr;4use jrsonnet_parser::{ArgsDesc, LocExpr};56use crate::{7	error::Result,8	evaluate,9	gc::GcHashMap,10	typed::Typed,11	val::{StrValue, ThunkValue},12	Context, Thunk, Val,13};1415/// Marker for arguments, which can be evaluated with context set to None16pub trait OptionalContext {}1718#[derive(Trace)]19struct EvaluateThunk {20	ctx: Context,21	expr: LocExpr,22}23impl ThunkValue for EvaluateThunk {24	type Output = Val;25	fn get(self: Box<Self>) -> Result<Val> {26		evaluate(self.ctx, &self.expr)27	}28}2930pub trait ArgLike {31	fn evaluate_arg(&self, ctx: Context, tailstrict: bool) -> Result<Thunk<Val>>;32}3334impl ArgLike for &LocExpr {35	fn evaluate_arg(&self, ctx: Context, tailstrict: bool) -> Result<Thunk<Val>> {36		Ok(if tailstrict {37			Thunk::evaluated(evaluate(ctx, self)?)38		} else {39			Thunk::new(EvaluateThunk {40				ctx,41				expr: (*self).clone(),42			})43		})44	}45}4647impl<T> ArgLike for T48where49	T: Typed + Clone,50{51	fn evaluate_arg(&self, _ctx: Context, _tailstrict: bool) -> Result<Thunk<Val>> {52		let val = T::into_untyped(self.clone())?;53		Ok(Thunk::evaluated(val))54	}55}56impl<T> OptionalContext for T where T: Typed + Clone {}5758impl ArgLike for Thunk<Val> {59	fn evaluate_arg(&self, _ctx: Context, tailstrict: bool) -> Result<Thunk<Val>> {60		if tailstrict {61			self.force()?;62		}63		Ok(self.clone())64	}65}66impl OptionalContext for Thunk<Val> {}6768#[derive(Clone, Trace)]69pub enum TlaArg {70	String(IStr),71	Code(LocExpr),72	Val(Val),73}74impl ArgLike for TlaArg {75	fn evaluate_arg(&self, ctx: Context, tailstrict: bool) -> Result<Thunk<Val>> {76		match self {77			TlaArg::String(s) => Ok(Thunk::evaluated(Val::Str(StrValue::Flat(s.clone())))),78			TlaArg::Code(code) => Ok(if tailstrict {79				Thunk::evaluated(evaluate(ctx, code)?)80			} else {81				Thunk::new(EvaluateThunk {82					ctx,83					expr: code.clone(),84				})85			}),86			TlaArg::Val(val) => Ok(Thunk::evaluated(val.clone())),87		}88	}89}9091mod sealed {92	/// Implemented for `ArgsLike`, where only unnamed arguments present93	pub trait Unnamed {}94	/// Implemented for `ArgsLike`, where only named arguments present95	pub trait Named {}96}9798pub trait ArgsLike {99	fn unnamed_len(&self) -> usize;100	fn unnamed_iter(101		&self,102		ctx: Context,103		tailstrict: bool,104		handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,105	) -> Result<()>;106	fn named_iter(107		&self,108		ctx: Context,109		tailstrict: bool,110		handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,111	) -> Result<()>;112	fn named_names(&self, handler: &mut dyn FnMut(&IStr));113}114115impl ArgsLike for Vec<Val> {116	fn unnamed_len(&self) -> usize {117		self.len()118	}119	fn unnamed_iter(120		&self,121		_ctx: Context,122		_tailstrict: bool,123		handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,124	) -> Result<()> {125		for (idx, el) in self.iter().enumerate() {126			handler(idx, Thunk::evaluated(el.clone()))?;127		}128		Ok(())129	}130	fn named_iter(131		&self,132		_ctx: Context,133		_tailstrict: bool,134		_handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,135	) -> Result<()> {136		Ok(())137	}138	fn named_names(&self, _handler: &mut dyn FnMut(&IStr)) {}139}140141impl ArgsLike for ArgsDesc {142	fn unnamed_len(&self) -> usize {143		self.unnamed.len()144	}145146	fn unnamed_iter(147		&self,148		ctx: Context,149		tailstrict: bool,150		handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,151	) -> Result<()> {152		for (id, arg) in self.unnamed.iter().enumerate() {153			handler(154				id,155				if tailstrict {156					Thunk::evaluated(evaluate(ctx.clone(), arg)?)157				} else {158					Thunk::new(EvaluateThunk {159						ctx: ctx.clone(),160						expr: arg.clone(),161					})162				},163			)?;164		}165		Ok(())166	}167168	fn named_iter(169		&self,170		ctx: Context,171		tailstrict: bool,172		handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,173	) -> Result<()> {174		for (name, arg) in &self.named {175			handler(176				name,177				if tailstrict {178					Thunk::evaluated(evaluate(ctx.clone(), arg)?)179				} else {180					Thunk::new(EvaluateThunk {181						ctx: ctx.clone(),182						expr: arg.clone(),183					})184				},185			)?;186		}187		Ok(())188	}189190	fn named_names(&self, handler: &mut dyn FnMut(&IStr)) {191		for (name, _) in &self.named {192			handler(name);193		}194	}195}196197impl<V: ArgLike, S> sealed::Named for HashMap<IStr, V, S> {}198impl<V: ArgLike, S> ArgsLike for HashMap<IStr, V, S> {199	fn unnamed_len(&self) -> usize {200		0201	}202203	fn unnamed_iter(204		&self,205		_ctx: Context,206		_tailstrict: bool,207		_handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,208	) -> Result<()> {209		Ok(())210	}211212	fn named_iter(213		&self,214		ctx: Context,215		tailstrict: bool,216		handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,217	) -> Result<()> {218		for (name, value) in self.iter() {219			handler(name, value.evaluate_arg(ctx.clone(), tailstrict)?)?;220		}221		Ok(())222	}223224	fn named_names(&self, handler: &mut dyn FnMut(&IStr)) {225		for (name, _) in self.iter() {226			handler(name);227		}228	}229}230impl<V, S> OptionalContext for HashMap<IStr, V, S> where V: ArgLike + OptionalContext {}231232impl<A: ArgLike> ArgsLike for GcHashMap<IStr, A> {233	fn unnamed_len(&self) -> usize {234		self.0.unnamed_len()235	}236237	fn unnamed_iter(238		&self,239		ctx: Context,240		tailstrict: bool,241		handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,242	) -> Result<()> {243		self.0.unnamed_iter(ctx, tailstrict, handler)244	}245246	fn named_iter(247		&self,248		ctx: Context,249		tailstrict: bool,250		handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,251	) -> Result<()> {252		self.0.named_iter(ctx, tailstrict, handler)253	}254255	fn named_names(&self, handler: &mut dyn FnMut(&IStr)) {256		self.0.named_names(handler);257	}258}259260macro_rules! impl_args_like {261	($count:expr; $($gen:ident)*) => {262		impl<$($gen: ArgLike,)*> sealed::Unnamed for ($($gen,)*) {}263		impl<$($gen: ArgLike,)*> ArgsLike for ($($gen,)*) {264			fn unnamed_len(&self) -> usize {265				$count266			}267			#[allow(non_snake_case, unused_assignments)]268			fn unnamed_iter(269				&self,270				ctx: Context,271				tailstrict: bool,272				handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,273			) -> Result<()> {274				let mut i = 0usize;275				let ($($gen,)*) = self;276				$(277					handler(i, $gen.evaluate_arg(ctx.clone(), tailstrict)?)?;278					i+=1;279				)*280				Ok(())281			}282			fn named_iter(283				&self,284				_ctx: Context,285				_tailstrict: bool,286				_handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,287			) -> Result<()> {288				Ok(())289			}290			fn named_names(&self, _handler: &mut dyn FnMut(&IStr)) {}291		}292		impl<$($gen: ArgLike,)*> OptionalContext for ($($gen,)*) where $($gen: OptionalContext),* {}293294		impl<$($gen: ArgLike,)*> sealed::Named for ($((IStr, $gen),)*) {}295		impl<$($gen: ArgLike,)*> ArgsLike for ($((IStr, $gen),)*) {296			fn unnamed_len(&self) -> usize {297				0298			}299			fn unnamed_iter(300				&self,301				_ctx: Context,302				_tailstrict: bool,303				_handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,304			) -> Result<()> {305				Ok(())306			}307			#[allow(non_snake_case)]308			fn named_iter(309				&self,310				ctx: Context,311				tailstrict: bool,312				handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,313			) -> Result<()> {314				let ($($gen,)*) = self;315				$(316					handler(&$gen.0, $gen.1.evaluate_arg(ctx.clone(), tailstrict)?)?;317				)*318				Ok(())319			}320			#[allow(non_snake_case)]321			fn named_names(&self, handler: &mut dyn FnMut(&IStr)) {322				let ($($gen,)*) = self;323				$(324					handler(&$gen.0);325				)*326			}327		}328		impl<$($gen: ArgLike,)*> OptionalContext for ($((IStr, $gen),)*) where $($gen: OptionalContext),* {}329	};330	($count:expr; $($cur:ident)* @ $c:ident $($rest:ident)*) => {331		impl_args_like!($count; $($cur)*);332		impl_args_like!($count + 1usize; $($cur)* $c @ $($rest)*);333	};334	($count:expr; $($cur:ident)* @) => {335		impl_args_like!($count; $($cur)*);336	}337}338impl_args_like! {339	// First argument is already in position, so count starts from 1340	1usize; A @ B C D E F G H I J K L341}342343impl ArgsLike for () {344	fn unnamed_len(&self) -> usize {345		0346	}347348	fn unnamed_iter(349		&self,350		_ctx: Context,351		_tailstrict: bool,352		_handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,353	) -> Result<()> {354		Ok(())355	}356357	fn named_iter(358		&self,359		_ctx: Context,360		_tailstrict: bool,361		_handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,362	) -> Result<()> {363		Ok(())364	}365366	fn named_names(&self, _handler: &mut dyn FnMut(&IStr)) {}367}368impl OptionalContext for () {}