git.delta.rocks / jrsonnet / refs/commits / 64fb3950ee00

difftreelog

source

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