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 try_cast_bool(self) -> bool {121 match self.unwrap_if_lazy() {122 Val::Bool(v) => v,123 v => panic!("expected bool, got {:?}", v),124 }125 }126 pub fn try_cast_str(self) -> String {127 match self.unwrap_if_lazy() {128 Val::Str(v) => v,129 v => panic!("expected bool, got {:?}", v),130 }131 }132 pub fn unwrap_if_lazy(self) -> Self {133 if let Val::Lazy(v) = self {134 v.evaluate().unwrap_if_lazy()135 } else {136 self137 }138 }139 pub fn type_of(&self) -> &'static str {140 match self {141 Val::Str(..) => "string",142 Val::Num(..) => "number",143 Val::Arr(..) => "array",144 Val::Obj(..) => "object",145 Val::Func(..) => "function",146 _ => panic!("no native type found"),147 }148 }149}150impl Display for Val {151 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {152 match self {153 Val::Str(str) => write!(f, "\"{}\"", str)?,154 Val::Num(n) => write!(f, "{}", n)?,155 Val::Arr(values) => {156 write!(f, "[")?;157 let mut first = true;158 for value in values {159 if first {160 first = false;161 } else {162 write!(f, ",")?;163 }164 write!(f, "{}", value)?;165 }166 write!(f, "]")?;167 }168 Val::Obj(value) => {169 write!(f, "{{")?;170 let mut first = true;171 for field in value.fields() {172 if first {173 first = false;174 } else {175 write!(f, ",")?;176 }177 write!(f, "\"{}\":", field)?;178 write!(f, "{}", value.get(&field).unwrap())?;179 }180 write!(f, "}}")?;181 }182 Val::Lazy(lazy) => {183 write!(f, "{}", lazy.evaluate())?;184 }185 Val::Func(_) => {186 write!(f, "<<FUNC>>")?;187 }188 v => panic!("no json equivalent for {:?}", v),189 };190 Ok(())191 }192}193194pub fn bool_val(v: bool) -> Val {195 Val::Bool(v)196}