1use crate::{lazy_binding, Context, FunctionDefault, FunctionRhs, LazyBinding, ObjValue};2use closure::closure;3use jsonnet_parser::ParamsDesc;4use std::{5 cell::RefCell,6 collections::HashMap,7 fmt::{Debug, Display},8 rc::Rc,9};1011struct LazyValInternals {12 pub f: Box<dyn Fn() -> Val>,13 pub cached: RefCell<Option<Val>>,14}15#[derive(Clone)]16pub struct LazyVal(Rc<LazyValInternals>);17impl LazyVal {18 pub fn new(f: Box<dyn Fn() -> Val>) -> Self {19 LazyVal(Rc::new(LazyValInternals {20 f,21 cached: RefCell::new(None),22 }))23 }24 pub fn evaluate(&self) -> Val {25 {26 let cached = self.0.cached.borrow();27 if cached.is_some() {28 return cached.clone().unwrap();29 }30 }31 let result = (self.0.f)();32 self.0.cached.borrow_mut().replace(result.clone());33 result34 }35}36#[macro_export]37macro_rules! lazy_val {38 ($f: expr) => {39 $crate::LazyVal::new(Box::new($f))40 };41}42impl Debug for LazyVal {43 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {44 write!(f, "Lazy")45 }46}47impl PartialEq for LazyVal {48 fn eq(&self, other: &Self) -> bool {49 Rc::ptr_eq(&self.0, &other.0)50 }51}5253#[derive(Debug, PartialEq, Clone)]54pub struct FuncDesc {55 pub ctx: Context,56 pub params: ParamsDesc,57 pub eval_rhs: FunctionRhs,58 pub eval_default: FunctionDefault,59}60impl FuncDesc {61 62 pub fn evaluate(&self, args: Vec<(Option<String>, Val)>) -> Val {63 let mut new_bindings: HashMap<String, LazyBinding> = HashMap::new();64 let future_ctx = Context::new_future();6566 67 68 69 70 71 72 73 74 75 76 77 78 79 for (name, val) in args.clone().into_iter().filter(|e| e.0.is_some()) {80 new_bindings.insert(81 name.as_ref().unwrap().clone(),82 lazy_binding!(83 closure!(clone val, |_, _| lazy_val!(closure!(clone val, || val.clone())))84 ),85 );86 }87 for (i, param) in self.params.0.iter().enumerate() {88 if let Some((None, val)) = args.get(i) {89 new_bindings.insert(90 param.0.clone(),91 lazy_binding!(92 closure!(clone val, |_, _| lazy_val!(closure!(clone val, || val.clone())))93 ),94 );95 }96 }97 let ctx = self98 .ctx99 .extend(new_bindings, None, None, None)100 .into_future(future_ctx);101 self.eval_rhs.0(ctx)102 }103}104105#[derive(Debug, PartialEq, Clone)]106pub enum Val {107 Bool(bool),108 Null,109 Str(String),110 Num(f64),111 Lazy(LazyVal),112 Arr(Vec<Val>),113 Obj(ObjValue),114 Func(FuncDesc),115116 117 Intristic(String, String),118}119impl Val {120 pub fn unwrap_if_lazy(self) -> Self {121 if let Val::Lazy(v) = self {122 v.evaluate().unwrap_if_lazy()123 } else {124 self125 }126 }127 pub fn type_of(&self) -> &'static str {128 match self {129 Val::Str(..) => "string",130 Val::Num(..) => "number",131 Val::Arr(..) => "array",132 Val::Obj(..) => "object",133 Val::Func(..) => "function",134 _ => panic!("no native type found"),135 }136 }137}138impl Display for Val {139 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {140 match self {141 Val::Str(str) => write!(f, "\"{}\"", str)?,142 Val::Num(n) => write!(f, "{}", n)?,143 Val::Arr(values) => {144 write!(f, "[")?;145 let mut first = true;146 for value in values {147 if first {148 first = false;149 } else {150 write!(f, ",")?;151 }152 write!(f, "{}", value)?;153 }154 write!(f, "]")?;155 }156 Val::Obj(value) => {157 write!(f, "{{")?;158 let mut first = true;159 for field in value.fields() {160 if first {161 first = false;162 } else {163 write!(f, ",")?;164 }165 write!(f, "\"{}\":", field)?;166 write!(f, "{}", value.get(&field).unwrap())?;167 }168 write!(f, "}}")?;169 }170 Val::Lazy(lazy) => {171 write!(f, "{}", lazy.evaluate())?;172 }173 Val::Func(_) => {174 write!(f, "<<FUNC>>")?;175 }176 v => panic!("no json equivalent for {:?}", v),177 };178 Ok(())179 }180}181182pub fn bool_val(v: bool) -> Val {183 Val::Bool(v)184}