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 20 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 25 26 27 28 29 30 31 32 33 34 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 74 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}