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 22 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 27 28 29 30 31 32 33 34 35 36 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 76 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}