git.delta.rocks / jrsonnet / refs/commits / eff1bc234bfb

difftreelog

perf(evaluator) remove unnecessary cloning

Лач2020-06-25parent: #ce9e7d9.patch.diff
in: master

4 files changed

modifiedcrates/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 {
modifiedcrates/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)))
 		};
modifiedcrates/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) {
modifiedcrates/jsonnet-evaluator/src/val.rsdiffbeforeafterboth
after · crates/jsonnet-evaluator/src/val.rs
1use 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}