git.delta.rocks / jrsonnet / refs/commits / 2e6febe0ffcd

difftreelog

source

crates/jsonnet-evaluator/src/val.rs3.3 KiBsourcehistory
1use crate::{binding, rc_fn_helper, Binding, Context, FunctionDefault, FunctionRhs, ObjValue};2use closure::closure;3use jsonnet_parser::{LiteralType, ParamsDesc};4use std::{5	collections::HashMap,6	fmt::{Debug, Display},7};89rc_fn_helper!(LazyVal, lazy_val, dyn Fn() -> Val);1011#[derive(Debug, PartialEq, Clone)]12pub struct FuncDesc {13	pub ctx: Context,14	pub params: ParamsDesc,15	pub eval_rhs: FunctionRhs,16	pub eval_default: FunctionDefault,17}18impl FuncDesc {19	// TODO: Check for unset variables20	pub fn evaluate(&self, args: Vec<(Option<String>, Val)>) -> Val {21		let mut new_bindings: HashMap<String, Binding> = HashMap::new();22		let future_ctx = Context::new_future();2324		// self.params25		// 	.with_defaults()26		// 	.into_iter()27		// 	.for_each(|Param(name, default)| {28		// 		let default = Rc::new(*default.unwrap());29		// 		new_bindings.insert(30		// 			name,31		// 			binding!(move |_, _| Val::Lazy(lazy_val!(|| self32		// 				.eval_default33		// 				.034		// 				.default(future_ctx.unwrap(), *default.clone())))),35		// 		);36		// 	});37		for (name, val) in args.clone().into_iter().filter(|e| e.0.is_some()) {38			new_bindings.insert(39				name.as_ref().unwrap().clone(),40				binding!(41					closure!(clone val, |_, _| Val::Lazy(lazy_val!(closure!(clone val, || val.clone()))))42				),43			);44		}45		for (i, param) in self.params.0.iter().enumerate() {46			if let Some((None, val)) = args.get(i) {47				new_bindings.insert(48					param.0.clone(),49					binding!(50						closure!(clone val, |_, _| Val::Lazy(lazy_val!(closure!(clone val, || val.clone()))))51					),52				);53			}54		}55		let ctx = self56			.ctx57			.extend(new_bindings, None, None, None)58			.into_future(future_ctx);59		self.eval_rhs.0(ctx)60	}61}6263#[derive(Debug, PartialEq, Clone)]64pub enum Val {65	Literal(LiteralType),66	Str(String),67	Num(f64),68	Lazy(LazyVal),69	Arr(Vec<Val>),70	Obj(ObjValue),71	Func(FuncDesc),7273	// Library functions implemented in native74	Intristic(String, String),75}76impl Val {77	pub fn unwrap_if_lazy(self) -> Self {78		if let Val::Lazy(v) = self {79			v.0().unwrap_if_lazy()80		} else {81			self82		}83	}84	pub fn type_of(&self) -> &'static str {85		match self {86			Val::Str(..) => "string",87			Val::Num(..) => "number",88			Val::Arr(..) => "array",89			Val::Obj(..) => "object",90			Val::Func(..) => "function",91			_ => panic!("no native type found"),92		}93	}94}95impl Display for Val {96	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {97		match self {98			Val::Literal(v) => write!(f, "{}", v)?,99			Val::Str(str) => write!(f, "\"{}\"", str)?,100			Val::Num(n) => write!(f, "{}", n)?,101			Val::Arr(values) => {102				write!(f, "[")?;103				let mut first = true;104				for value in values {105					if first {106						first = false;107					} else {108						write!(f, ",")?;109					}110					write!(f, "{}", value)?;111				}112				write!(f, "]")?;113			}114			Val::Obj(value) => {115				write!(f, "{{")?;116				let mut first = true;117				for field in value.fields() {118					if first {119						first = false;120					} else {121						write!(f, ",")?;122					}123					write!(f, "\"{}\":", field)?;124					write!(f, "{}", value.get(&field).unwrap())?;125				}126				write!(f, "}}")?;127			}128			Val::Lazy(lazy) => {129				write!(f, "{}", lazy.0())?;130			}131			Val::Func(_) => {132				write!(f, "<<FUNC>>")?;133			}134			v => panic!("no json equivalent for {:?}", v),135		};136		Ok(())137	}138}139140pub fn bool_val(v: bool) -> Val {141	if v {142		Val::Literal(LiteralType::True)143	} else {144		Val::Literal(LiteralType::False)145	}146}