difftreelog
perf move std.setInter to native
in: master
3 files changed
crates/jrsonnet-stdlib/src/lib.rsdiffbeforeafterboth--- a/crates/jrsonnet-stdlib/src/lib.rs
+++ b/crates/jrsonnet-stdlib/src/lib.rs
@@ -42,6 +42,8 @@
pub use misc::*;
mod sets;
pub use sets::*;
+mod compat;
+pub use compat::*;
pub fn stdlib_uncached(settings: Rc<RefCell<Settings>>) -> ObjValue {
let mut builder = ObjValueBuilder::new();
@@ -147,6 +149,7 @@
("endsWith", builtin_ends_with::INST),
// Sets
("setMember", builtin_set_member::INST),
+ ("setInter", builtin_set_inter::INST),
]
.iter()
.cloned()
crates/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)))
+}
crates/jrsonnet-stdlib/src/std.jsonnetdiffbeforeafterboth214 aux(a, b, i, j + 1, acc + [b[j]]) tailstrict;214 aux(a, b, i, j + 1, acc + [b[j]]) tailstrict;215 aux(a, b, 0, 0, []),215 aux(a, b, 0, 0, []),216216217 setInter(a, b, keyF=id)::218 local aux(a, b, i, j, acc) =219 if i >= std.length(a) || j >= std.length(b) then220 acc221 else222 if keyF(a[i]) == keyF(b[j]) then223 aux(a, b, i + 1, j + 1, acc + [a[i]]) tailstrict224 else if keyF(a[i]) < keyF(b[j]) then225 aux(a, b, i + 1, j, acc) tailstrict226 else227 aux(a, b, i, j + 1, acc) tailstrict;228 aux(a, b, 0, 0, []) tailstrict,229230 setDiff(a, b, keyF=id)::217 setDiff(a, b, keyF=id)::231 local aux(a, b, i, j, acc) =218 local aux(a, b, i, j, acc) =232 if i >= std.length(a) then219 if i >= std.length(a) then