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

difftreelog

source

crates/jrsonnet-evaluator/src/function/arglike.rs4.6 KiBsourcehistory
1use std::collections::HashMap;2use std::rc::Rc;34use jrsonnet_gcmodule::Trace;5use jrsonnet_interner::IStr;6use jrsonnet_parser::{ArgsDesc, Expr, SourceFifo, SourcePath, Spanned};78use crate::{evaluate, typed::Typed, with_state, Context, Result, Thunk, Val};910pub trait ArgLike {11	fn evaluate_arg(&self, ctx: Context, tailstrict: bool) -> Result<Thunk<Val>>;12}1314impl ArgLike for &Rc<Spanned<Expr>> {15	fn evaluate_arg(&self, ctx: Context, tailstrict: bool) -> Result<Thunk<Val>> {16		Ok(if tailstrict {17			Thunk::evaluated(evaluate(ctx, self)?)18		} else {19			let expr = (*self).clone();20			Thunk!(move || evaluate(ctx, &expr))21		})22	}23}2425impl<T> ArgLike for T26where27	T: Typed + Clone,28{29	fn evaluate_arg(&self, _ctx: Context, tailstrict: bool) -> Result<Thunk<Val>> {30		if T::provides_lazy() && !tailstrict {31			return Ok(T::into_lazy_untyped(self.clone()));32		}33		let val = T::into_untyped(self.clone())?;34		Ok(Thunk::evaluated(val))35	}36}3738#[derive(Clone, Trace)]39pub enum TlaArg {40	String(IStr),41	Val(Val),42	Lazy(Thunk<Val>),43	Import(String),44	ImportStr(String),45	InlineCode(String),46}47impl TlaArg {48	pub fn evaluate_tailstrict(&self) -> Result<Val> {49		match self {50			Self::String(s) => Ok(Val::string(s.clone())),51			Self::Val(val) => Ok(val.clone()),52			Self::Lazy(lazy) => Ok(lazy.evaluate()?),53			Self::Import(p) => with_state(|s| {54				let resolved = s.resolve_from_default(&p.as_str())?;55				s.import_resolved(resolved)56			}),57			Self::ImportStr(p) => with_state(|s| {58				let resolved = s.resolve_from_default(&p.as_str())?;59				s.import_resolved_str(resolved).map(Val::string)60			}),61			Self::InlineCode(p) => with_state(|s| {62				let resolved =63					SourcePath::new(SourceFifo("<inline code>".to_owned(), p.as_bytes().into()));64				s.import_resolved(resolved)65			}),66		}67	}68	pub fn evaluate(&self) -> Result<Thunk<Val>> {69		match self {70			Self::String(s) => Ok(Thunk::evaluated(Val::string(s.clone()))),71			Self::Val(val) => Ok(Thunk::evaluated(val.clone())),72			Self::Lazy(lazy) => Ok(lazy.clone()),73			Self::Import(p) => with_state(|s| {74				let resolved = s.resolve_from_default(&p.as_str())?;75				Ok(Thunk!(move || s.import_resolved(resolved)))76			}),77			Self::ImportStr(p) => with_state(|s| {78				let resolved = s.resolve_from_default(&p.as_str())?;79				Ok(Thunk!(move || s80					.import_resolved_str(resolved)81					.map(Val::string)))82			}),83			Self::InlineCode(p) => with_state(|s| {84				let resolved =85					SourcePath::new(SourceFifo("<inline code>".to_owned(), p.as_bytes().into()));86				Ok(Thunk!(move || s.import_resolved(resolved)))87			}),88		}89	}90}9192pub trait ArgsLike {93	fn unnamed_len(&self) -> usize;94	fn unnamed_iter(95		&self,96		ctx: Context,97		tailstrict: bool,98		handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,99	) -> Result<()>;100	fn named_iter(101		&self,102		ctx: Context,103		tailstrict: bool,104		handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,105	) -> Result<()>;106	fn named_names(&self, handler: &mut dyn FnMut(&IStr));107	fn is_empty(&self) -> bool;108}109110impl ArgsLike for Vec<Val> {111	fn unnamed_len(&self) -> usize {112		self.len()113	}114	fn unnamed_iter(115		&self,116		_ctx: Context,117		_tailstrict: bool,118		handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,119	) -> Result<()> {120		for (idx, el) in self.iter().enumerate() {121			handler(idx, Thunk::evaluated(el.clone()))?;122		}123		Ok(())124	}125	fn named_iter(126		&self,127		_ctx: Context,128		_tailstrict: bool,129		_handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,130	) -> Result<()> {131		Ok(())132	}133	fn named_names(&self, _handler: &mut dyn FnMut(&IStr)) {}134	fn is_empty(&self) -> bool {135		self.is_empty()136	}137}138139impl ArgsLike for ArgsDesc {140	fn unnamed_len(&self) -> usize {141		self.unnamed.len()142	}143144	fn unnamed_iter(145		&self,146		ctx: Context,147		tailstrict: bool,148		handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,149	) -> Result<()> {150		for (id, arg) in self.unnamed.iter().enumerate() {151			handler(152				id,153				if tailstrict {154					Thunk::evaluated(evaluate(ctx.clone(), arg)?)155				} else {156					let ctx = ctx.clone();157					let arg = arg.clone();158159					Thunk!(move || evaluate(ctx, &arg))160				},161			)?;162		}163		Ok(())164	}165166	fn named_iter(167		&self,168		ctx: Context,169		tailstrict: bool,170		handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,171	) -> Result<()> {172		for (name, arg) in &self.named {173			handler(174				name,175				if tailstrict {176					Thunk::evaluated(evaluate(ctx.clone(), arg)?)177				} else {178					let ctx = ctx.clone();179					let arg = arg.clone();180181					Thunk!(move || evaluate(ctx, &arg))182				},183			)?;184		}185		Ok(())186	}187188	fn named_names(&self, handler: &mut dyn FnMut(&IStr)) {189		for (name, _) in &self.named {190			handler(name);191		}192	}193194	fn is_empty(&self) -> bool {195		self.unnamed.is_empty() && self.named.is_empty()196	}197}