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

difftreelog

source

crates/jrsonnet-evaluator/src/function/arglike.rs7.0 KiBsourcehistory
1use std::collections::HashMap;23use jrsonnet_gcmodule::Trace;4use jrsonnet_interner::IStr;5use jrsonnet_parser::{ArgsDesc, LocExpr};67use crate::{8	error::Result, evaluate, tb, typed::Typed, val::ThunkValue, Context, State, Thunk, Val,9};1011#[derive(Trace)]12struct EvaluateThunk {13	ctx: Context,14	expr: LocExpr,15}16impl ThunkValue for EvaluateThunk {17	type Output = Val;18	fn get(self: Box<Self>, s: State) -> Result<Val> {19		evaluate(s, self.ctx, &self.expr)20	}21}2223pub trait ArgLike {24	fn evaluate_arg(&self, s: State, ctx: Context, tailstrict: bool) -> Result<Thunk<Val>>;25}2627impl ArgLike for &LocExpr {28	fn evaluate_arg(&self, s: State, ctx: Context, tailstrict: bool) -> Result<Thunk<Val>> {29		Ok(if tailstrict {30			Thunk::evaluated(evaluate(s, ctx, self)?)31		} else {32			Thunk::new(tb!(EvaluateThunk {33				ctx,34				expr: (*self).clone(),35			}))36		})37	}38}3940impl<T> ArgLike for T41where42	T: Typed + Clone,43{44	fn evaluate_arg(&self, s: State, _ctx: Context, _tailstrict: bool) -> Result<Thunk<Val>> {45		let val = T::into_untyped(self.clone(), s)?;46		Ok(Thunk::evaluated(val))47	}48}4950#[derive(Clone)]51pub enum TlaArg {52	String(IStr),53	Code(LocExpr),54	Val(Val),55}56impl ArgLike for TlaArg {57	fn evaluate_arg(&self, s: State, ctx: Context, tailstrict: bool) -> Result<Thunk<Val>> {58		match self {59			TlaArg::String(s) => Ok(Thunk::evaluated(Val::Str(s.clone()))),60			TlaArg::Code(code) => Ok(if tailstrict {61				Thunk::evaluated(evaluate(s, ctx, code)?)62			} else {63				Thunk::new(tb!(EvaluateThunk {64					ctx,65					expr: code.clone(),66				}))67			}),68			TlaArg::Val(val) => Ok(Thunk::evaluated(val.clone())),69		}70	}71}7273mod sealed {74	/// Implemented for `ArgsLike`, where only unnamed arguments present75	pub trait Unnamed {}76	/// Implemented for `ArgsLike`, where only named arguments present77	pub trait Named {}78}7980pub trait ArgsLike {81	fn unnamed_len(&self) -> usize;82	fn unnamed_iter(83		&self,84		s: State,85		ctx: Context,86		tailstrict: bool,87		handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,88	) -> Result<()>;89	fn named_iter(90		&self,91		s: State,92		ctx: Context,93		tailstrict: bool,94		handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,95	) -> Result<()>;96	fn named_names(&self, handler: &mut dyn FnMut(&IStr));97}9899impl ArgsLike for Vec<Val> {100	fn unnamed_len(&self) -> usize {101		self.len()102	}103	fn unnamed_iter(104		&self,105		_s: State,106		_ctx: Context,107		_tailstrict: bool,108		handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,109	) -> Result<()> {110		for (idx, el) in self.iter().enumerate() {111			handler(idx, Thunk::evaluated(el.clone()))?;112		}113		Ok(())114	}115	fn named_iter(116		&self,117		_s: State,118		_ctx: Context,119		_tailstrict: bool,120		_handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,121	) -> Result<()> {122		Ok(())123	}124	fn named_names(&self, _handler: &mut dyn FnMut(&IStr)) {}125}126127impl ArgsLike for ArgsDesc {128	fn unnamed_len(&self) -> usize {129		self.unnamed.len()130	}131132	fn unnamed_iter(133		&self,134		s: State,135		ctx: Context,136		tailstrict: bool,137		handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,138	) -> Result<()> {139		for (id, arg) in self.unnamed.iter().enumerate() {140			handler(141				id,142				if tailstrict {143					Thunk::evaluated(evaluate(s.clone(), ctx.clone(), arg)?)144				} else {145					Thunk::new(tb!(EvaluateThunk {146						ctx: ctx.clone(),147						expr: arg.clone(),148					}))149				},150			)?;151		}152		Ok(())153	}154155	fn named_iter(156		&self,157		s: State,158		ctx: Context,159		tailstrict: bool,160		handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,161	) -> Result<()> {162		for (name, arg) in &self.named {163			handler(164				name,165				if tailstrict {166					Thunk::evaluated(evaluate(s.clone(), ctx.clone(), arg)?)167				} else {168					Thunk::new(tb!(EvaluateThunk {169						ctx: ctx.clone(),170						expr: arg.clone(),171					}))172				},173			)?;174		}175		Ok(())176	}177178	fn named_names(&self, handler: &mut dyn FnMut(&IStr)) {179		for (name, _) in &self.named {180			handler(name);181		}182	}183}184185impl<A: ArgLike, S> sealed::Named for HashMap<IStr, A, S> {}186impl<A: ArgLike, S> ArgsLike for HashMap<IStr, A, S> {187	fn unnamed_len(&self) -> usize {188		0189	}190191	fn unnamed_iter(192		&self,193		_s: State,194		_ctx: Context,195		_tailstrict: bool,196		_handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,197	) -> Result<()> {198		Ok(())199	}200201	fn named_iter(202		&self,203		s: State,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(210				name,211				value.evaluate_arg(s.clone(), ctx.clone(), tailstrict)?,212			)?;213		}214		Ok(())215	}216217	fn named_names(&self, handler: &mut dyn FnMut(&IStr)) {218		for (name, _) in self.iter() {219			handler(name);220		}221	}222}223224macro_rules! impl_args_like {225	($count:expr; $($gen:ident)*) => {226		impl<$($gen: ArgLike,)*> sealed::Unnamed for ($($gen,)*) {}227		impl<$($gen: ArgLike,)*> ArgsLike for ($($gen,)*) {228			fn unnamed_len(&self) -> usize {229				$count230			}231			#[allow(non_snake_case, unused_assignments)]232			fn unnamed_iter(233				&self,234				s: State,235				ctx: Context,236				tailstrict: bool,237				handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,238			) -> Result<()> {239				let mut i = 0usize;240				let ($($gen,)*) = self;241				$(242					handler(i, $gen.evaluate_arg(s.clone(), ctx.clone(), tailstrict)?)?;243					i+=1;244				)*245				Ok(())246			}247			fn named_iter(248				&self,249				_s: State,250				_ctx: Context,251				_tailstrict: bool,252				_handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,253			) -> Result<()> {254				Ok(())255			}256			fn named_names(&self, _handler: &mut dyn FnMut(&IStr)) {}257		}258		impl<$($gen: ArgLike,)*> sealed::Named for ($((IStr, $gen),)*) {}259		impl<$($gen: ArgLike,)*> ArgsLike for ($((IStr, $gen),)*) {260			fn unnamed_len(&self) -> usize {261				0262			}263			fn unnamed_iter(264				&self,265				_s: State,266				_ctx: Context,267				_tailstrict: bool,268				_handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,269			) -> Result<()> {270				Ok(())271			}272			#[allow(non_snake_case)]273			fn named_iter(274				&self,275				s: State,276				ctx: Context,277				tailstrict: bool,278				handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,279			) -> Result<()> {280				let ($($gen,)*) = self;281				$(282					handler(&$gen.0, $gen.1.evaluate_arg(s.clone(), ctx.clone(), tailstrict)?)?;283				)*284				Ok(())285			}286			#[allow(non_snake_case)]287			fn named_names(&self, handler: &mut dyn FnMut(&IStr)) {288				let ($($gen,)*) = self;289				$(290					handler(&$gen.0);291				)*292			}293		}294	};295	($count:expr; $($cur:ident)* @ $c:ident $($rest:ident)*) => {296		impl_args_like!($count; $($cur)*);297		impl_args_like!($count + 1usize; $($cur)* $c @ $($rest)*);298	};299	($count:expr; $($cur:ident)* @) => {300		impl_args_like!($count; $($cur)*);301	}302}303impl_args_like! {304	// First argument is already in position, so count starts from 1305	1usize; A @ B C D E F G H I J K L306}307308impl ArgsLike for () {309	fn unnamed_len(&self) -> usize {310		0311	}312313	fn unnamed_iter(314		&self,315		_s: State,316		_ctx: Context,317		_tailstrict: bool,318		_handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,319	) -> Result<()> {320		Ok(())321	}322323	fn named_iter(324		&self,325		_s: State,326		_ctx: Context,327		_tailstrict: bool,328		_handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,329	) -> Result<()> {330		Ok(())331	}332333	fn named_names(&self, _handler: &mut dyn FnMut(&IStr)) {}334}