difftreelog
perf(evaluator) remove unnecessary cloning
in: master
4 files changed
crates/jsonnet-evaluator/src/evaluate.rsdiffbeforeafterboth--- a/crates/jsonnet-evaluator/src/evaluate.rs
+++ b/crates/jsonnet-evaluator/src/evaluate.rs
@@ -211,9 +211,9 @@
let future_this = FutureObjValue::new();
let context_creator = context_creator!(
closure!(clone context, clone new_bindings, |this: Option<ObjValue>, super_obj: Option<ObjValue>| {
- Ok(context.clone().extend_unbound(
+ Ok(context.extend_unbound(
new_bindings.clone().unwrap(),
- context.clone().dollar().clone().or_else(||this.clone()),
+ context.dollar().clone().or_else(||this.clone()),
Some(this.unwrap()),
super_obj
)?)
@@ -318,9 +318,9 @@
let new_bindings = FutureNewBindings::new();
let context_creator = context_creator!(
closure!(clone context, clone new_bindings, |this: Option<ObjValue>, super_obj: Option<ObjValue>| {
- Ok(context.clone().extend_unbound(
+ Ok(context.extend_unbound(
new_bindings.clone().unwrap(),
- context.clone().dollar().clone().or_else(||this.clone()),
+ context.dollar().clone().or_else(||this.clone()),
None,
super_obj
)?)
@@ -664,14 +664,14 @@
("std", "filter") => {
assert_eq!(args.len(), 2);
if let (Val::Func(predicate), Val::Arr(arr)) = (
- evaluate(context, &args[0].1)?,
- evaluate(context, &args[1].1)?,
+ evaluate(context.clone(), &args[0].1)?,
+ evaluate(context.clone(), &args[1].1)?,
) {
Val::Arr(
arr.into_iter()
.filter(|e| {
predicate
- .evaluate_values(&context, &[e.clone()])
+ .evaluate_values(context.clone(), &[e.clone()])
.unwrap()
.try_cast_bool("filter predicate")
.unwrap()
@@ -685,7 +685,7 @@
// faster
("std", "join") => {
assert_eq!(args.len(), 2);
- let joiner = evaluate(context, &args[0].1)?.unwrap_if_lazy()?;
+ let joiner = evaluate(context.clone(), &args[0].1)?.unwrap_if_lazy()?;
let items = evaluate(context, &args[1].1)?.unwrap_if_lazy()?;
println!("Before");
let result = match (joiner, items) {
@@ -775,7 +775,9 @@
cond_then,
cond_else,
} => {
- if evaluate(context, &cond.0)?.try_cast_bool("if condition should be boolean")? {
+ if evaluate(context.clone(), &cond.0)?
+ .try_cast_bool("if condition should be boolean")?
+ {
evaluate(context, cond_then)?
} else {
match cond_else {
crates/jsonnet-evaluator/src/function.rsdiffbeforeafterboth--- a/crates/jsonnet-evaluator/src/function.rs
+++ b/crates/jsonnet-evaluator/src/function.rs
@@ -69,7 +69,7 @@
unreachable!()
};
let val = if tailstrict {
- resolved_lazy_val!(evaluate(ctx.clone(), expr)?)
+ resolved_lazy_val!(evaluate(ctx, expr)?)
} else {
lazy_val!(closure!(clone ctx, clone expr, ||evaluate(ctx.clone(), &expr)))
};
crates/jsonnet-evaluator/src/lib.rsdiffbeforeafterboth--- a/crates/jsonnet-evaluator/src/lib.rs
+++ b/crates/jsonnet-evaluator/src/lib.rs
@@ -154,7 +154,7 @@
}
value.1.clone()
};
- let value = evaluate(&self.create_default_context()?, &expr)?;
+ let value = evaluate(self.create_default_context()?, &expr)?;
{
self.0
.files
@@ -205,7 +205,7 @@
}
pub fn evaluate_raw(&self, code: LocExpr) -> Result<Val> {
- self.run_in_state(|| evaluate(&self.create_default_context()?, &code))
+ self.run_in_state(|| evaluate(self.create_default_context()?, &code))
}
pub fn add_global(&self, name: String, value: Val) {
crates/jsonnet-evaluator/src/val.rsdiffbeforeafterboth1use crate::{2 create_error, evaluate, function::inline_parse_function_call, Context, Error, ObjValue, Result,3};4use jsonnet_parser::{el, Arg, ArgsDesc, Expr, LocExpr, ParamsDesc};5use std::{6 cell::RefCell,7 fmt::{Debug, Display},8 rc::Rc,9};1011struct LazyValInternals {12 pub f: Option<Box<dyn Fn() -> Result<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() -> Result<Val>>) -> Self {19 LazyVal(Rc::new(LazyValInternals {20 f: Some(f),21 cached: RefCell::new(None),22 }))23 }24 pub fn new_resolved(val: Val) -> Self {25 LazyVal(Rc::new(LazyValInternals {26 f: None,27 cached: RefCell::new(Some(val)),28 }))29 }30 pub fn evaluate(&self) -> Result<Val> {31 {32 let cached = self.0.cached.borrow();33 if cached.is_some() {34 return Ok(cached.clone().unwrap());35 }36 }37 let result = (self.0.f.as_ref().unwrap())()?;38 self.0.cached.borrow_mut().replace(result.clone());39 Ok(result)40 }41}4243#[macro_export]44macro_rules! lazy_val {45 ($f: expr) => {46 $crate::LazyVal::new(Box::new($f))47 };48}49#[macro_export]50macro_rules! resolved_lazy_val {51 ($f: expr) => {52 $crate::LazyVal::new_resolved($f)53 };54}55impl Debug for LazyVal {56 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {57 if self.0.cached.borrow().is_some() {58 write!(f, "{:?}", self.0.cached.borrow().clone().unwrap())59 } else {60 write!(f, "Lazy")61 }62 }63}64impl PartialEq for LazyVal {65 fn eq(&self, other: &Self) -> bool {66 Rc::ptr_eq(&self.0, &other.0)67 }68}6970#[derive(Debug, PartialEq, Clone)]71pub struct FuncDesc {72 pub ctx: Context,73 pub params: ParamsDesc,74 pub body: LocExpr,75}76impl FuncDesc {77 /// This function is always inlined to make tailstrict work78 #[inline(always)]79 pub fn evaluate(&self, call_ctx: Context, args: &ArgsDesc, tailstrict: bool) -> Result<Val> {80 let ctx = inline_parse_function_call(81 call_ctx,82 Some(self.ctx.clone()),83 &self.params,84 args,85 tailstrict,86 )?;87 evaluate(ctx, &self.body)88 }89}9091#[derive(Debug)]92pub enum ValType {93 Bool,94 Null,95 Str,96 Num,97 Arr,98 Obj,99 Func,100}101impl ValType {102 pub fn name(&self) -> &'static str {103 use ValType::*;104 match self {105 Bool => "boolean",106 Null => "null",107 Str => "string",108 Num => "number",109 Arr => "array",110 Obj => "object",111 Func => "function",112 }113 }114}115impl Display for ValType {116 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {117 write!(f, "{}", self.name())118 }119}120121#[derive(Debug, PartialEq, Clone)]122pub enum Val {123 Bool(bool),124 Null,125 Str(String),126 Num(f64),127 Lazy(LazyVal),128 Arr(Vec<Val>),129 Obj(ObjValue),130 Func(FuncDesc),131132 // Library functions implemented in native133 Intristic(String, String),134}135impl Val {136 pub fn try_cast_bool(self, context: &'static str) -> Result<bool> {137 match self.unwrap_if_lazy()? {138 Val::Bool(v) => Ok(v),139 v => create_error(Error::TypeMismatch(140 context,141 vec![ValType::Bool],142 v.value_type()?,143 )),144 }145 }146 pub fn try_cast_str(self, context: &'static str) -> Result<String> {147 match self.unwrap_if_lazy()? {148 Val::Str(v) => Ok(v),149 v => create_error(Error::TypeMismatch(150 context,151 vec![ValType::Str],152 v.value_type()?,153 )),154 }155 }156 pub fn unwrap_if_lazy(self) -> Result<Self> {157 Ok(if let Val::Lazy(v) = self {158 v.evaluate()?.unwrap_if_lazy()?159 } else {160 self161 })162 }163 pub fn value_type(&self) -> Result<ValType> {164 Ok(match self {165 Val::Str(..) => ValType::Str,166 Val::Num(..) => ValType::Num,167 Val::Arr(..) => ValType::Arr,168 Val::Obj(..) => ValType::Obj,169 Val::Func(..) => ValType::Func,170 Val::Bool(_) => ValType::Bool,171 Val::Null => ValType::Null,172 Val::Intristic(_, _) => ValType::Func,173 Val::Lazy(_) => self.clone().unwrap_if_lazy()?.value_type()?,174 })175 }176 pub fn into_json(self, padding: usize) -> Result<String> {177 with_state(|s| {178 let ctx = s179 .create_default_context()?180 .with_var("__tmp__to_json__".to_owned(), self)?;181 if let Val::Str(result) = evaluate(182 ctx,183 &el!(Expr::Apply(184 el!(Expr::Index(185 el!(Expr::Var("std".to_owned())),186 el!(Expr::Str("manifestJsonEx".to_owned()))187 )),188 ArgsDesc(vec![189 Arg(None, el!(Expr::Var("__tmp__to_json__".to_owned()))),190 Arg(None, el!(Expr::Str(" ".repeat(padding))))191 ]),192 false193 )),194 )? {195 Ok(result)196 } else {197 unreachable!()198 }199 })200 }201}