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

difftreelog

source

crates/jrsonnet-evaluator/src/function/arglike.rs6.4 KiBsourcehistory
1use std::collections::HashMap;23use gcmodule::Trace;4use jrsonnet_interner::IStr;5use jrsonnet_parser::{ArgsDesc, LocExpr};67use crate::{8	error::Result, evaluate, gc::TraceBox, typed::Typed, val::LazyValValue, Context, LazyVal,9	State, Val,10};1112#[derive(Trace)]13struct EvaluateLazyVal {14	ctx: Context,15	expr: LocExpr,16}17impl LazyValValue for EvaluateLazyVal {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<LazyVal>;25}2627impl ArgLike for &LocExpr {28	fn evaluate_arg(&self, s: State, ctx: Context, tailstrict: bool) -> Result<LazyVal> {29		Ok(if tailstrict {30			LazyVal::new_resolved(evaluate(s, ctx, self)?)31		} else {32			LazyVal::new(TraceBox(Box::new(EvaluateLazyVal {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<LazyVal> {45		let val = T::into_untyped(self.clone(), s)?;46		Ok(LazyVal::new_resolved(val))47	}48}4950pub enum TlaArg {51	String(IStr),52	Code(LocExpr),53	Val(Val),54}55impl ArgLike for TlaArg {56	fn evaluate_arg(&self, s: State, ctx: Context, tailstrict: bool) -> Result<LazyVal> {57		match self {58			TlaArg::String(s) => Ok(LazyVal::new_resolved(Val::Str(s.clone()))),59			TlaArg::Code(code) => Ok(if tailstrict {60				LazyVal::new_resolved(evaluate(s, ctx, code)?)61			} else {62				LazyVal::new(TraceBox(Box::new(EvaluateLazyVal {63					ctx,64					expr: code.clone(),65				})))66			}),67			TlaArg::Val(val) => Ok(LazyVal::new_resolved(val.clone())),68		}69	}70}7172mod sealed {73	/// Implemented for `ArgsLike`, where only unnamed arguments present74	pub trait Unnamed {}75	/// Implemented for `ArgsLike`, where only named arguments present76	pub trait Named {}77}7879pub trait ArgsLike {80	fn unnamed_len(&self) -> usize;81	fn unnamed_iter(82		&self,83		s: State,84		ctx: Context,85		tailstrict: bool,86		handler: &mut dyn FnMut(usize, LazyVal) -> Result<()>,87	) -> Result<()>;88	fn named_iter(89		&self,90		s: State,91		ctx: Context,92		tailstrict: bool,93		handler: &mut dyn FnMut(&IStr, LazyVal) -> Result<()>,94	) -> Result<()>;95	fn named_names(&self, handler: &mut dyn FnMut(&IStr));96}9798impl ArgsLike for ArgsDesc {99	fn unnamed_len(&self) -> usize {100		self.unnamed.len()101	}102103	fn unnamed_iter(104		&self,105		s: State,106		ctx: Context,107		tailstrict: bool,108		handler: &mut dyn FnMut(usize, LazyVal) -> Result<()>,109	) -> Result<()> {110		for (id, arg) in self.unnamed.iter().enumerate() {111			handler(112				id,113				if tailstrict {114					LazyVal::new_resolved(evaluate(s.clone(), ctx.clone(), arg)?)115				} else {116					LazyVal::new(TraceBox(Box::new(EvaluateLazyVal {117						ctx: ctx.clone(),118						expr: arg.clone(),119					})))120				},121			)?;122		}123		Ok(())124	}125126	fn named_iter(127		&self,128		s: State,129		ctx: Context,130		tailstrict: bool,131		handler: &mut dyn FnMut(&IStr, LazyVal) -> Result<()>,132	) -> Result<()> {133		for (name, arg) in &self.named {134			handler(135				name,136				if tailstrict {137					LazyVal::new_resolved(evaluate(s.clone(), ctx.clone(), arg)?)138				} else {139					LazyVal::new(TraceBox(Box::new(EvaluateLazyVal {140						ctx: ctx.clone(),141						expr: arg.clone(),142					})))143				},144			)?;145		}146		Ok(())147	}148149	fn named_names(&self, handler: &mut dyn FnMut(&IStr)) {150		for (name, _) in &self.named {151			handler(name);152		}153	}154}155156impl<A: ArgLike, S> sealed::Named for HashMap<IStr, A, S> {}157impl<A: ArgLike, S> ArgsLike for HashMap<IStr, A, S> {158	fn unnamed_len(&self) -> usize {159		0160	}161162	fn unnamed_iter(163		&self,164		_s: State,165		_ctx: Context,166		_tailstrict: bool,167		_handler: &mut dyn FnMut(usize, LazyVal) -> Result<()>,168	) -> Result<()> {169		Ok(())170	}171172	fn named_iter(173		&self,174		s: State,175		ctx: Context,176		tailstrict: bool,177		handler: &mut dyn FnMut(&IStr, LazyVal) -> Result<()>,178	) -> Result<()> {179		for (name, value) in self.iter() {180			handler(181				name,182				value.evaluate_arg(s.clone(), ctx.clone(), tailstrict)?,183			)?;184		}185		Ok(())186	}187188	fn named_names(&self, handler: &mut dyn FnMut(&IStr)) {189		for (name, _) in self.iter() {190			handler(name);191		}192	}193}194195macro_rules! impl_args_like {196	($count:expr; $($gen:ident)*) => {197		impl<$($gen: ArgLike,)*> sealed::Unnamed for ($($gen,)*) {}198		impl<$($gen: ArgLike,)*> ArgsLike for ($($gen,)*) {199			fn unnamed_len(&self) -> usize {200				$count201			}202			#[allow(non_snake_case, unused_assignments)]203			fn unnamed_iter(204				&self,205				s: State,206				ctx: Context,207				tailstrict: bool,208				handler: &mut dyn FnMut(usize, LazyVal) -> Result<()>,209			) -> Result<()> {210				let mut i = 0usize;211				let ($($gen,)*) = self;212				$(213					handler(i, $gen.evaluate_arg(s.clone(), ctx.clone(), tailstrict)?)?;214					i+=1;215				)*216				Ok(())217			}218			fn named_iter(219				&self,220				_s: State,221				_ctx: Context,222				_tailstrict: bool,223				_handler: &mut dyn FnMut(&IStr, LazyVal) -> Result<()>,224			) -> Result<()> {225				Ok(())226			}227			fn named_names(&self, _handler: &mut dyn FnMut(&IStr)) {}228		}229		impl<$($gen: ArgLike,)*> sealed::Named for ($((IStr, $gen),)*) {}230		impl<$($gen: ArgLike,)*> ArgsLike for ($((IStr, $gen),)*) {231			fn unnamed_len(&self) -> usize {232				0233			}234			fn unnamed_iter(235				&self,236				_s: State,237				_ctx: Context,238				_tailstrict: bool,239				_handler: &mut dyn FnMut(usize, LazyVal) -> Result<()>,240			) -> Result<()> {241				Ok(())242			}243			#[allow(non_snake_case)]244			fn named_iter(245				&self,246				s: State,247				ctx: Context,248				tailstrict: bool,249				handler: &mut dyn FnMut(&IStr, LazyVal) -> Result<()>,250			) -> Result<()> {251				let ($($gen,)*) = self;252				$(253					handler(&$gen.0, $gen.1.evaluate_arg(s.clone(), ctx.clone(), tailstrict)?)?;254				)*255				Ok(())256			}257			#[allow(non_snake_case)]258			fn named_names(&self, handler: &mut dyn FnMut(&IStr)) {259				let ($($gen,)*) = self;260				$(261					handler(&$gen.0);262				)*263			}264		}265	};266	($count:expr; $($cur:ident)* @ $c:ident $($rest:ident)*) => {267		impl_args_like!($count; $($cur)*);268		impl_args_like!($count + 1usize; $($cur)* $c @ $($rest)*);269	};270	($count:expr; $($cur:ident)* @) => {271		impl_args_like!($count; $($cur)*);272	}273}274impl_args_like! {275	0usize; A @ B C D E F G H I J K L276}277278impl ArgsLike for () {279	fn unnamed_len(&self) -> usize {280		0281	}282283	fn unnamed_iter(284		&self,285		_s: State,286		_ctx: Context,287		_tailstrict: bool,288		_handler: &mut dyn FnMut(usize, LazyVal) -> Result<()>,289	) -> Result<()> {290		Ok(())291	}292293	fn named_iter(294		&self,295		_s: State,296		_ctx: Context,297		_tailstrict: bool,298		_handler: &mut dyn FnMut(&IStr, LazyVal) -> Result<()>,299	) -> Result<()> {300		Ok(())301	}302303	fn named_names(&self, _handler: &mut dyn FnMut(&IStr)) {}304}