git.delta.rocks / jrsonnet / refs/commits / 50ca1d2d134a

difftreelog

source

crates/jrsonnet-evaluator/src/function/arglike.rs6.5 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 ArgsDesc {100	fn unnamed_len(&self) -> usize {101		self.unnamed.len()102	}103104	fn unnamed_iter(105		&self,106		s: State,107		ctx: Context,108		tailstrict: bool,109		handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,110	) -> Result<()> {111		for (id, arg) in self.unnamed.iter().enumerate() {112			handler(113				id,114				if tailstrict {115					Thunk::evaluated(evaluate(s.clone(), ctx.clone(), arg)?)116				} else {117					Thunk::new(tb!(EvaluateThunk {118						ctx: ctx.clone(),119						expr: arg.clone(),120					}))121				},122			)?;123		}124		Ok(())125	}126127	fn named_iter(128		&self,129		s: State,130		ctx: Context,131		tailstrict: bool,132		handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,133	) -> Result<()> {134		for (name, arg) in &self.named {135			handler(136				name,137				if tailstrict {138					Thunk::evaluated(evaluate(s.clone(), ctx.clone(), arg)?)139				} else {140					Thunk::new(tb!(EvaluateThunk {141						ctx: ctx.clone(),142						expr: arg.clone(),143					}))144				},145			)?;146		}147		Ok(())148	}149150	fn named_names(&self, handler: &mut dyn FnMut(&IStr)) {151		for (name, _) in &self.named {152			handler(name);153		}154	}155}156157impl<A: ArgLike, S> sealed::Named for HashMap<IStr, A, S> {}158impl<A: ArgLike, S> ArgsLike for HashMap<IStr, A, S> {159	fn unnamed_len(&self) -> usize {160		0161	}162163	fn unnamed_iter(164		&self,165		_s: State,166		_ctx: Context,167		_tailstrict: bool,168		_handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,169	) -> Result<()> {170		Ok(())171	}172173	fn named_iter(174		&self,175		s: State,176		ctx: Context,177		tailstrict: bool,178		handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,179	) -> Result<()> {180		for (name, value) in self.iter() {181			handler(182				name,183				value.evaluate_arg(s.clone(), ctx.clone(), tailstrict)?,184			)?;185		}186		Ok(())187	}188189	fn named_names(&self, handler: &mut dyn FnMut(&IStr)) {190		for (name, _) in self.iter() {191			handler(name);192		}193	}194}195196macro_rules! impl_args_like {197	($count:expr; $($gen:ident)*) => {198		impl<$($gen: ArgLike,)*> sealed::Unnamed for ($($gen,)*) {}199		impl<$($gen: ArgLike,)*> ArgsLike for ($($gen,)*) {200			fn unnamed_len(&self) -> usize {201				$count202			}203			#[allow(non_snake_case, unused_assignments)]204			fn unnamed_iter(205				&self,206				s: State,207				ctx: Context,208				tailstrict: bool,209				handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,210			) -> Result<()> {211				let mut i = 0usize;212				let ($($gen,)*) = self;213				$(214					handler(i, $gen.evaluate_arg(s.clone(), ctx.clone(), tailstrict)?)?;215					i+=1;216				)*217				Ok(())218			}219			fn named_iter(220				&self,221				_s: State,222				_ctx: Context,223				_tailstrict: bool,224				_handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,225			) -> Result<()> {226				Ok(())227			}228			fn named_names(&self, _handler: &mut dyn FnMut(&IStr)) {}229		}230		impl<$($gen: ArgLike,)*> sealed::Named for ($((IStr, $gen),)*) {}231		impl<$($gen: ArgLike,)*> ArgsLike for ($((IStr, $gen),)*) {232			fn unnamed_len(&self) -> usize {233				0234			}235			fn unnamed_iter(236				&self,237				_s: State,238				_ctx: Context,239				_tailstrict: bool,240				_handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,241			) -> Result<()> {242				Ok(())243			}244			#[allow(non_snake_case)]245			fn named_iter(246				&self,247				s: State,248				ctx: Context,249				tailstrict: bool,250				handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,251			) -> Result<()> {252				let ($($gen,)*) = self;253				$(254					handler(&$gen.0, $gen.1.evaluate_arg(s.clone(), ctx.clone(), tailstrict)?)?;255				)*256				Ok(())257			}258			#[allow(non_snake_case)]259			fn named_names(&self, handler: &mut dyn FnMut(&IStr)) {260				let ($($gen,)*) = self;261				$(262					handler(&$gen.0);263				)*264			}265		}266	};267	($count:expr; $($cur:ident)* @ $c:ident $($rest:ident)*) => {268		impl_args_like!($count; $($cur)*);269		impl_args_like!($count + 1usize; $($cur)* $c @ $($rest)*);270	};271	($count:expr; $($cur:ident)* @) => {272		impl_args_like!($count; $($cur)*);273	}274}275impl_args_like! {276	// First argument is already in position, so count starts from 1277	1usize; A @ B C D E F G H I J K L278}279280impl ArgsLike for () {281	fn unnamed_len(&self) -> usize {282		0283	}284285	fn unnamed_iter(286		&self,287		_s: State,288		_ctx: Context,289		_tailstrict: bool,290		_handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,291	) -> Result<()> {292		Ok(())293	}294295	fn named_iter(296		&self,297		_s: State,298		_ctx: Context,299		_tailstrict: bool,300		_handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,301	) -> Result<()> {302		Ok(())303	}304305	fn named_names(&self, _handler: &mut dyn FnMut(&IStr)) {}306}