git.delta.rocks / jrsonnet / refs/commits / 9af1f59feaab

difftreelog

perf move std.setInter to native

Yaroslav Bolyukin2023-04-08parent: #e88030d.patch.diff
in: master

3 files changed

modifiedcrates/jrsonnet-stdlib/src/lib.rsdiffbeforeafterboth
42pub use misc::*;42pub use misc::*;
43mod sets;43mod sets;
44pub use sets::*;44pub use sets::*;
45mod compat;
46pub use compat::*;
4547
46pub fn stdlib_uncached(settings: Rc<RefCell<Settings>>) -> ObjValue {48pub fn stdlib_uncached(settings: Rc<RefCell<Settings>>) -> ObjValue {
47 let mut builder = ObjValueBuilder::new();49 let mut builder = ObjValueBuilder::new();
147 ("endsWith", builtin_ends_with::INST),149 ("endsWith", builtin_ends_with::INST),
148 // Sets150 // Sets
149 ("setMember", builtin_set_member::INST),151 ("setMember", builtin_set_member::INST),
152 ("setInter", builtin_set_inter::INST),
150 ]153 ]
151 .iter()154 .iter()
152 .cloned()155 .cloned()
modifiedcrates/jrsonnet-stdlib/src/sets.rsdiffbeforeafterboth
--- a/crates/jrsonnet-stdlib/src/sets.rs
+++ b/crates/jrsonnet-stdlib/src/sets.rs
@@ -5,23 +5,27 @@
 	function::{builtin, FuncVal},
 	operator::evaluate_compare_op,
 	val::ArrValue,
-	Val,
+	Thunk, Val,
 };
+use jrsonnet_gcmodule::Cc;
 use jrsonnet_parser::BinaryOpType;
 
 #[builtin]
 #[allow(non_snake_case)]
-pub fn builtin_set_member(x: Val, arr: ArrValue, keyF: Option<FuncVal>) -> Result<bool> {
+pub fn builtin_set_member(x: Thunk<Val>, arr: ArrValue, keyF: Option<FuncVal>) -> Result<bool> {
 	let mut low = 0;
 	let mut high = arr.len();
 
-	let keyF = keyF.unwrap_or(FuncVal::Id).into_native::<((Val,), Val)>();
+	let keyF = keyF
+		.unwrap_or(FuncVal::Id)
+		.into_native::<((Thunk<Val>,), Val)>();
 
 	let x = keyF(x)?;
 
 	while low < high {
 		let middle = (high + low) / 2;
-		match evaluate_compare_op(&arr.get(middle)?.expect("in bounds"), &x, BinaryOpType::Lt)? {
+		let comp = keyF(arr.get_lazy(middle).expect("in bounds"))?;
+		match evaluate_compare_op(&comp, &x, BinaryOpType::Lt)? {
 			Ordering::Less => low = middle + 1,
 			Ordering::Equal => return Ok(true),
 			Ordering::Greater => high = middle,
@@ -29,3 +33,42 @@
 	}
 	Ok(false)
 }
+
+#[builtin]
+#[allow(non_snake_case)]
+pub fn builtin_set_inter(a: ArrValue, b: ArrValue, keyF: Option<FuncVal>) -> Result<ArrValue> {
+	let mut a = a.iter_lazy();
+	let mut b = b.iter_lazy();
+
+	let keyF = keyF
+		.unwrap_or(FuncVal::identity())
+		.into_native::<((Thunk<Val>,), Val)>();
+	let keyF = |v| keyF(v);
+
+	let mut av = a.next();
+	let mut bv = b.next();
+	let mut ak = av.clone().map(keyF).transpose()?;
+	let mut bk = bv.map(keyF).transpose()?;
+
+	let mut out = Vec::new();
+	while let (Some(ac), Some(bc)) = (&ak, &bk) {
+		match evaluate_compare_op(ac, bc, BinaryOpType::Lt)? {
+			Ordering::Less => {
+				av = a.next();
+				ak = av.clone().map(keyF).transpose()?;
+			}
+			Ordering::Greater => {
+				bv = b.next();
+				bk = bv.map(keyF).transpose()?;
+			}
+			Ordering::Equal => {
+				out.push(av.clone().expect("ak != None => av != None"));
+				av = a.next();
+				ak = av.clone().map(keyF).transpose()?;
+				bv = b.next();
+				bk = bv.map(keyF).transpose()?;
+			}
+		};
+	}
+	Ok(ArrValue::lazy(Cc::new(out)))
+}
modifiedcrates/jrsonnet-stdlib/src/std.jsonnetdiffbeforeafterboth
--- a/crates/jrsonnet-stdlib/src/std.jsonnet
+++ b/crates/jrsonnet-stdlib/src/std.jsonnet
@@ -214,19 +214,6 @@
           aux(a, b, i, j + 1, acc + [b[j]]) tailstrict;
     aux(a, b, 0, 0, []),
 
-  setInter(a, b, keyF=id)::
-    local aux(a, b, i, j, acc) =
-      if i >= std.length(a) || j >= std.length(b) then
-        acc
-      else
-        if keyF(a[i]) == keyF(b[j]) then
-          aux(a, b, i + 1, j + 1, acc + [a[i]]) tailstrict
-        else if keyF(a[i]) < keyF(b[j]) then
-          aux(a, b, i + 1, j, acc) tailstrict
-        else
-          aux(a, b, i, j + 1, acc) tailstrict;
-    aux(a, b, 0, 0, []) tailstrict,
-
   setDiff(a, b, keyF=id)::
     local aux(a, b, i, j, acc) =
       if i >= std.length(a) then