difftreelog
feat(evaluator) tailstrict functions
in: master
5 files changed
crates/jsonnet-evaluator/src/ctx.rsdiffbeforeafterboth1use crate::{1use crate::{2 future_wrapper, lazy_binding, lazy_val, rc_fn_helper, LazyBinding, LazyVal, ObjValue, Result,2 future_wrapper, rc_fn_helper, resolved_lazy_val, LazyBinding, LazyVal, ObjValue, Result, Val,3 Val,4};3};5use closure::closure;6use std::{cell::RefCell, collections::HashMap, fmt::Debug, rc::Rc};4use std::{cell::RefCell, collections::HashMap, fmt::Debug, rc::Rc};758rc_fn_helper!(6rc_fn_helper!(686669 pub fn with_var(&self, name: String, value: Val) -> Result<Context> {67 pub fn with_var(&self, name: String, value: Val) -> Result<Context> {70 let mut new_bindings: HashMap<_, LazyBinding> = HashMap::new();68 let mut new_bindings: HashMap<_, LazyBinding> = HashMap::new();71 new_bindings.insert(69 new_bindings.insert(name, LazyBinding::Bound(resolved_lazy_val!(value.clone())));72 name,73 lazy_binding!(74 closure!(clone value, |_t, _s|Ok(lazy_val!(closure!(clone value, ||Ok(value.clone())))))75 ),76 );77 self.extend(new_bindings, None, None, None)70 self.extend(new_bindings, None, None, None)95 new.insert(k.clone(), v.clone());88 new.insert(k.clone(), v.clone());96 }89 }97 for (k, v) in new_bindings.into_iter() {90 for (k, v) in new_bindings.into_iter() {98 new.insert(k, v.0(this.clone(), super_obj.clone())?);91 new.insert(k, v.evaluate(this.clone(), super_obj.clone())?);99 }92 }100 Rc::new(new)93 Rc::new(new)101 };94 };crates/jsonnet-evaluator/src/evaluate.rsdiffbeforeafterboth1use crate::{1use crate::{2 binding, context_creator, create_error, function_default, function_rhs, future_wrapper,2 binding, context_creator, create_error, function_default, function_rhs, future_wrapper,3 lazy_binding, lazy_val, push, Context, ContextCreator, FuncDesc, LazyBinding, ObjMember,3 lazy_val, push, Context, ContextCreator, FuncDesc, LazyBinding, LazyVal, ObjMember, ObjValue,4 ObjValue, Result, Val,4 Result, Val,5};5};6use closure::closure;6use closure::closure;19 let args = args.clone();19 let args = args.clone();20 (20 (21 b.name.clone(),21 b.name.clone(),22 lazy_binding!(move |this, super_obj| Ok(lazy_val!(22 LazyBinding::Bindable(Rc::new(move |this, super_obj| {23 Ok(lazy_val!(23 closure!(clone b, clone args, clone context_creator, || Ok(evaluate_method(24 closure!(clone b, clone args, clone context_creator, || Ok(evaluate_method(24 context_creator.0(this.clone(), super_obj.clone())?,25 context_creator.0(this.clone(), super_obj.clone())?,25 &b.value,26 &b.value,26 args.clone()27 args.clone()27 )))28 )))28 ))),29 ))30 })),29 )31 )30 } else {32 } else {31 (33 (32 b.name.clone(),34 b.name.clone(),33 lazy_binding!(move |this, super_obj| {35 LazyBinding::Bindable(Rc::new(move |this, super_obj| {34 Ok(lazy_val!(closure!(clone context_creator, clone b, ||36 Ok(lazy_val!(closure!(clone context_creator, clone b, ||35 push(b.value.clone(), "thunk".to_owned(), ||{37 push(b.value.clone(), "thunk".to_owned(), ||{36 evaluate(38 evaluate(39 )41 )40 })42 })41 )))43 )))42 }),44 })),43 )45 )44 }46 }45}47}405 &evaluate(context.clone(), s)?,407 &evaluate(context.clone(), s)?,406 &Val::Obj(evaluate_object(context, t.clone())?),408 &Val::Obj(evaluate_object(context, t.clone())?),407 )?,409 )?,408 Apply(value, ArgsDesc(args)) => {410 Apply(value, ArgsDesc(args), tailstrict) => {409 let value = evaluate(context.clone(), value)?.unwrap_if_lazy()?;411 let value = evaluate(context.clone(), value)?.unwrap_if_lazy()?;410 match value {412 match value {411 Val::Intristic(ns, name) => match (&ns as &str, &name as &str) {413 Val::Intristic(ns, name) => match (&ns as &str, &name as &str) {502 evaluate(context.clone(), &args[0].1)?,504 evaluate(context.clone(), &args[0].1)?,503 evaluate(context, &args[1].1)?,505 evaluate(context, &args[1].1)?,504 ) {506 ) {507 // TODO: Line numbers as in original jsonnet505 println!("{}", a);508 println!("TRACE: {}", a);506 b509 b507 } else {510 } else {508 panic!("bad trace call");511 panic!("bad trace call");517 .map(move |a| {520 .map(move |a| {518 (521 (519 a.clone().0,522 a.clone().0,523 if *tailstrict {524 Val::Lazy(LazyVal::new_resolved(525 evaluate(context.clone(), &a.1).unwrap(),526 ))527 } else {520 Val::Lazy(lazy_val!(528 Val::Lazy(lazy_val!(521 closure!(clone context, clone a, || evaluate(context.clone(), &a.clone().1))529 closure!(clone context, clone a, || evaluate(context.clone(), &a.clone().1))522 )),530 ))531 },523 )532 )524 })533 })525 .collect(),534 .collect(),crates/jsonnet-evaluator/src/function.rsdiffbeforeafterbothno syntactic changes
crates/jsonnet-evaluator/src/lib.rsdiffbeforeafterboth6mod dynamic;6mod dynamic;7mod error;7mod error;8mod evaluate;8mod evaluate;9mod function;9mod obj;10mod obj;10mod val;11mod val;111212use closure::closure;13pub use ctx::*;13pub use ctx::*;14pub use dynamic::*;14pub use dynamic::*;15pub use error::*;15pub use error::*;16pub use evaluate::*;16pub use evaluate::*;17use jsonnet_parser::*;17use jsonnet_parser::*;18pub use obj::*;18pub use obj::*;19use std::{cell::RefCell, collections::HashMap, path::PathBuf, rc::Rc};19use std::{cell::RefCell, collections::HashMap, fmt::Debug, path::PathBuf, rc::Rc};20pub use val::*;20pub use val::*;212122rc_fn_helper!(22rc_fn_helper!(23 Binding,23 Binding,24 binding,24 binding,25 dyn Fn(Option<ObjValue>, Option<ObjValue>) -> Result<Val>25 dyn Fn(Option<ObjValue>, Option<ObjValue>) -> Result<Val>26);26);27rc_fn_helper!(28 LazyBinding,29 lazy_binding,30 dyn Fn(Option<ObjValue>, Option<ObjValue>) -> Result<LazyVal>31);32rc_fn_helper!(FunctionRhs, function_rhs, dyn Fn(Context) -> Result<Val>);27rc_fn_helper!(FunctionRhs, function_rhs, dyn Fn(Context) -> Result<Val>);33rc_fn_helper!(28rc_fn_helper!(34 FunctionDefault,29 FunctionDefault,35 function_default,30 function_default,36 dyn Fn(Context, LocExpr) -> Result<Val>31 dyn Fn(Context, LocExpr) -> Result<Val>37);32);3334#[derive(Clone)]35pub enum LazyBinding {36 Bindable(Rc<dyn Fn(Option<ObjValue>, Option<ObjValue>) -> Result<LazyVal>>),37 Bound(LazyVal),38}3940impl Debug for LazyBinding {41 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {42 write!(f, "LazyBinding")43 }44}45impl LazyBinding {46 pub fn evaluate(&self, this: Option<ObjValue>, super_obj: Option<ObjValue>) -> Result<LazyVal> {47 match self {48 LazyBinding::Bindable(v) => v(this, super_obj),49 LazyBinding::Bound(v) => Ok(v.clone()),50 }51 }52}385339pub struct FileData(String, LocExpr, Option<Val>);54pub struct FileData(String, LocExpr, Option<Val>);40#[derive(Default)]55#[derive(Default)]168 for (name, value) in globals.iter() {183 for (name, value) in globals.iter() {169 new_bindings.insert(184 new_bindings.insert(170 name.clone(),185 name.clone(),171 lazy_binding!(186 LazyBinding::Bound(resolved_lazy_val!(value.clone())),172 closure!(clone value, |_self, _super_obj| Ok(lazy_val!(closure!(clone value, ||Ok(value.clone())))))173 ),174 );187 );175 }188 }179 pub fn push<T>(&self, e: LocExpr, comment: String, f: impl FnOnce() -> Result<T>) -> Result<T> {192 pub fn push<T>(&self, e: LocExpr, comment: String, f: impl FnOnce() -> Result<T>) -> Result<T> {180 {193 {181 let mut stack = self.0.stack.borrow_mut();194 let mut stack = self.0.stack.borrow_mut();182 if stack.len() > 5000 {195 if stack.len() > 500 {183 drop(stack);196 drop(stack);184 return self.error(Error::StackOverflow);197 return self.error(Error::StackOverflow);185 } else {198 } else {crates/jsonnet-evaluator/src/val.rsdiffbeforeafterboth1use crate::{1use crate::{2 create_error, lazy_binding, Context, Error, FunctionDefault, FunctionRhs, LazyBinding,2 create_error, Context, Error, FunctionDefault, FunctionRhs, LazyBinding, ObjValue, Result,3 ObjValue, Result,4};3};5use closure::closure;4use closure::closure;12};11};131214struct LazyValInternals {13struct LazyValInternals {15 pub f: Box<dyn Fn() -> Result<Val>>,14 pub f: Option<Box<dyn Fn() -> Result<Val>>>,16 pub cached: RefCell<Option<Val>>,15 pub cached: RefCell<Option<Val>>,17}16}18#[derive(Clone)]17#[derive(Clone)]19pub struct LazyVal(Rc<LazyValInternals>);18pub struct LazyVal(Rc<LazyValInternals>);20impl LazyVal {19impl LazyVal {21 pub fn new(f: Box<dyn Fn() -> Result<Val>>) -> Self {20 pub fn new(f: Box<dyn Fn() -> Result<Val>>) -> Self {22 LazyVal(Rc::new(LazyValInternals {21 LazyVal(Rc::new(LazyValInternals {23 f,22 f: Some(f),24 cached: RefCell::new(None),23 cached: RefCell::new(None),25 }))24 }))26 }25 }26 pub fn new_resolved(val: Val) -> Self {27 LazyVal(Rc::new(LazyValInternals {28 f: None,29 cached: RefCell::new(Some(val)),30 }))31 }27 pub fn evaluate(&self) -> Result<Val> {32 pub fn evaluate(&self) -> Result<Val> {28 {33 {29 let cached = self.0.cached.borrow();34 let cached = self.0.cached.borrow();30 if cached.is_some() {35 if cached.is_some() {31 return Ok(cached.clone().unwrap());36 return Ok(cached.clone().unwrap());32 }37 }33 }38 }34 let result = (self.0.f)()?;39 let result = (self.0.f.as_ref().unwrap())()?;35 self.0.cached.borrow_mut().replace(result.clone());40 self.0.cached.borrow_mut().replace(result.clone());36 Ok(result)41 Ok(result)37 }42 }42 $crate::LazyVal::new(Box::new($f))48 $crate::LazyVal::new(Box::new($f))43 };49 };44}50}51#[macro_export]52macro_rules! resolved_lazy_val {53 ($f: expr) => {54 $crate::LazyVal::new_resolved($f)55 };56}45impl Debug for LazyVal {57impl Debug for LazyVal {46 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {58 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {47 if self.0.cached.borrow().is_some() {59 if self.0.cached.borrow().is_some() {75 let eval_default = self.eval_default.clone();87 let eval_default = self.eval_default.clone();76 new_bindings.insert(88 new_bindings.insert(77 name,89 name,78 lazy_binding!(closure!(clone future_ctx, clone default, clone eval_default, |_, _| Ok(lazy_val!(closure!(clone future_ctx, clone eval_default, clone default, || (eval_default.clone()).090 LazyBinding::Bound(lazy_val!(91 closure!(clone future_ctx, clone eval_default, clone default, || (eval_default.clone()).079 (future_ctx.clone().unwrap(), default.clone())))))),92 (future_ctx.clone().unwrap(), default.clone()))93 )),80 );94 );81 }95 }82 for (name, val) in args.clone().into_iter().filter(|e| e.0.is_some()) {96 for (name, val) in args.clone().into_iter().filter(|e| e.0.is_some()) {83 new_bindings.insert(97 new_bindings.insert(84 name.as_ref().unwrap().clone(),98 name.as_ref().unwrap().clone(),85 lazy_binding!(99 LazyBinding::Bound(resolved_lazy_val!(val.clone())),86 closure!(clone val, |_, _| Ok(lazy_val!(closure!(clone val, || Ok(val.clone())))))87 ),88 );100 );89 }101 }90 for (i, param) in self.params.0.iter().enumerate() {102 for (i, param) in self.params.0.iter().enumerate() {91 if let Some((None, val)) = args.get(i) {103 if let Some((None, val)) = args.get(i) {92 new_bindings.insert(104 new_bindings.insert(93 param.0.clone(),105 param.0.clone(),94 lazy_binding!(106 LazyBinding::Bound(resolved_lazy_val!(val.clone())),95 closure!(clone val, |_, _| Ok(lazy_val!(closure!(clone val, || Ok(val.clone())))))96 ),97 );107 );98 }108 }