difftreelog
perf implement std.prune in native
in: master
6 files changed
cmds/jrsonnet-fmt/src/main.rsdiffbeforeafterboth--- a/cmds/jrsonnet-fmt/src/main.rs
+++ b/cmds/jrsonnet-fmt/src/main.rs
@@ -356,16 +356,16 @@
impl Printable for Member {
fn print(&self, out: &mut PrintItems) {
match self {
- Member::MemberBindStmt(b) => {
+ Self::MemberBindStmt(b) => {
p!(out, { b.obj_local() })
}
- Member::MemberAssertStmt(ass) => {
+ Self::MemberAssertStmt(ass) => {
p!(out, { ass.assertion() })
}
- Member::MemberFieldNormal(n) => {
+ Self::MemberFieldNormal(n) => {
p!(out, {n.field_name()} if(n.plus_token().is_some())({n.plus_token()}) {n.visibility()} str(" ") {n.expr()})
}
- Member::MemberFieldMethod(m) => {
+ Self::MemberFieldMethod(m) => {
p!(out, {m.field_name()} {m.params_desc()} {m.visibility()} str(" ") {m.expr()})
}
}
crates/jrsonnet-evaluator/src/manifest.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/manifest.rs
+++ b/crates/jrsonnet-evaluator/src/manifest.rs
@@ -1,6 +1,6 @@
use std::{borrow::Cow, fmt::Write};
-use crate::{bail, Result, State, Val};
+use crate::{bail, Result, ResultExt, State, Val};
pub trait ManifestFormat {
fn manifest_buf(&self, val: Val, buf: &mut String) -> Result<()>;
@@ -235,7 +235,8 @@
}
}
buf.push_str(cur_padding);
- manifest_json_ex_buf(&item?, buf, cur_padding, options)?;
+ manifest_json_ex_buf(&item?, buf, cur_padding, options)
+ .with_description(|| format!("elem <{i}> manifestification"))?;
}
cur_padding.truncate(old_len);
crates/jrsonnet-evaluator/src/obj.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/obj.rs
+++ b/crates/jrsonnet-evaluator/src/obj.rs
@@ -278,7 +278,7 @@
}
impl ObjectLike for ThisOverride {
fn with_this(&self, _me: ObjValue, this: ObjValue) -> ObjValue {
- ObjValue::new(ThisOverride {
+ ObjValue::new(Self {
inner: self.inner.clone(),
this,
})
@@ -398,7 +398,7 @@
self.get_for(key, self.0.this().unwrap_or_else(|| self.clone()))
}
- pub fn get_for(&self, key: IStr, this: ObjValue) -> Result<Option<Val>> {
+ pub fn get_for(&self, key: IStr, this: Self) -> Result<Option<Val>> {
self.0.get_for(key, this)
}
@@ -410,7 +410,7 @@
Ok(value)
}
- fn get_raw(&self, key: IStr, this: ObjValue) -> Result<Option<Val>> {
+ fn get_raw(&self, key: IStr, this: Self) -> Result<Option<Val>> {
self.0.get_for_uncached(key, this)
}
@@ -422,7 +422,7 @@
// FIXME: Should it use `self.0.this()` in case of standalone super?
self.run_assertions_raw(self.clone())
}
- fn run_assertions_raw(&self, this: ObjValue) -> Result<()> {
+ fn run_assertions_raw(&self, this: Self) -> Result<()> {
self.0.run_assertions_raw(this)
}
crates/jrsonnet-stdlib/src/arrays.rsdiffbeforeafterboth1#![allow(non_snake_case)]23use jrsonnet_evaluator::{4 bail,5 function::{builtin, FuncVal},6 runtime_error,7 typed::{BoundedI32, BoundedUsize, Either2, NativeFn, Typed},8 val::{equals, ArrValue, IndexableVal},9 Either, IStr, ObjValueBuilder, Result, ResultExt, Thunk, Val,10};1112pub(crate) fn eval_on_empty(on_empty: Option<Thunk<Val>>) -> Result<Val> {13 if let Some(on_empty) = on_empty {14 on_empty.evaluate()15 } else {16 bail!("expected non-empty array")17 }18}1920#[builtin]21pub fn builtin_make_array(sz: BoundedI32<0, { i32::MAX }>, func: FuncVal) -> Result<ArrValue> {22 if *sz == 0 {23 return Ok(ArrValue::empty());24 }25 func.evaluate_trivial().map_or_else(26 || Ok(ArrValue::range_exclusive(0, *sz).map(func)),27 |trivial| {28 let mut out = Vec::with_capacity(*sz as usize);29 for _ in 0..*sz {30 out.push(trivial.clone());31 }32 Ok(ArrValue::eager(out))33 },34 )35}3637#[builtin]38pub fn builtin_repeat(what: Either![IStr, ArrValue], count: usize) -> Result<Val> {39 Ok(match what {40 Either2::A(s) => Val::string(s.repeat(count)),41 Either2::B(arr) => Val::Arr(42 ArrValue::repeated(arr, count)43 .ok_or_else(|| runtime_error!("repeated length overflow"))?,44 ),45 })46}4748#[builtin]49pub fn builtin_slice(50 indexable: IndexableVal,51 index: Option<i32>,52 end: Option<i32>,53 step: Option<BoundedUsize<1, { i32::MAX as usize }>>,54) -> Result<Val> {55 indexable.slice(index, end, step).map(Val::from)56}5758#[builtin]59pub fn builtin_map(func: FuncVal, arr: IndexableVal) -> ArrValue {60 let arr = arr.to_array();61 arr.map(func)62}6364#[builtin]65pub fn builtin_flatmap(66 func: NativeFn<((Either![String, Val],), Val)>,67 arr: IndexableVal,68) -> Result<IndexableVal> {69 use std::fmt::Write;70 match arr {71 IndexableVal::Str(str) => {72 let mut out = String::new();73 for c in str.chars() {74 match func(Either2::A(c.to_string()))? {75 Val::Str(o) => write!(out, "{o}").unwrap(),76 Val::Null => continue,77 _ => bail!("in std.join all items should be strings"),78 };79 }80 Ok(IndexableVal::Str(out.into()))81 }82 IndexableVal::Arr(a) => {83 let mut out = Vec::new();84 for el in a.iter() {85 let el = el?;86 match func(Either2::B(el))? {87 Val::Arr(o) => {88 for oe in o.iter() {89 out.push(oe?);90 }91 }92 Val::Null => continue,93 _ => bail!("in std.join all items should be arrays"),94 };95 }96 Ok(IndexableVal::Arr(out.into()))97 }98 }99}100101#[builtin]102pub fn builtin_filter(func: FuncVal, arr: ArrValue) -> Result<ArrValue> {103 arr.filter(|val| bool::from_untyped(func.evaluate_simple(&(val.clone(),), false)?))104}105106#[builtin]107pub fn builtin_filter_map(108 filter_func: FuncVal,109 map_func: FuncVal,110 arr: ArrValue,111) -> Result<ArrValue> {112 Ok(builtin_filter(filter_func, arr)?.map(map_func))113}114115#[builtin]116pub fn builtin_foldl(func: FuncVal, arr: ArrValue, init: Val) -> Result<Val> {117 let mut acc = init;118 for i in arr.iter() {119 acc = func.evaluate_simple(&(acc, i?), false)?;120 }121 Ok(acc)122}123124#[builtin]125pub fn builtin_foldr(func: FuncVal, arr: ArrValue, init: Val) -> Result<Val> {126 let mut acc = init;127 for i in arr.iter().rev() {128 acc = func.evaluate_simple(&(i?, acc), false)?;129 }130 Ok(acc)131}132133#[builtin]134pub fn builtin_range(from: i32, to: i32) -> Result<ArrValue> {135 if to < from {136 return Ok(ArrValue::empty());137 }138 Ok(ArrValue::range_inclusive(from, to))139}140141#[builtin]142pub fn builtin_join(sep: IndexableVal, arr: ArrValue) -> Result<IndexableVal> {143 use std::fmt::Write;144 Ok(match sep {145 IndexableVal::Arr(joiner_items) => {146 let mut out = Vec::new();147148 let mut first = true;149 for item in arr.iter() {150 let item = item?.clone();151 if let Val::Arr(items) = item {152 if !first {153 out.reserve(joiner_items.len());154 // TODO: extend155 for item in joiner_items.iter() {156 out.push(item?);157 }158 }159 first = false;160 out.reserve(items.len());161 for item in items.iter() {162 out.push(item?);163 }164 } else if matches!(item, Val::Null) {165 continue;166 } else {167 bail!("in std.join all items should be arrays");168 }169 }170171 IndexableVal::Arr(out.into())172 }173 IndexableVal::Str(sep) => {174 let mut out = String::new();175176 let mut first = true;177 for item in arr.iter() {178 let item = item?.clone();179 if let Val::Str(item) = item {180 if !first {181 out += &sep;182 }183 first = false;184 write!(out, "{item}").unwrap();185 } else if matches!(item, Val::Null) {186 continue;187 } else {188 bail!("in std.join all items should be strings");189 }190 }191192 IndexableVal::Str(out.into())193 }194 })195}196197#[builtin]198pub fn builtin_reverse(arr: ArrValue) -> ArrValue {199 arr.reversed()200}201202#[builtin]203pub fn builtin_any(arr: ArrValue) -> Result<bool> {204 for v in arr.iter() {205 let v = bool::from_untyped(v?)?;206 if v {207 return Ok(true);208 }209 }210 Ok(false)211}212213#[builtin]214pub fn builtin_all(arr: ArrValue) -> Result<bool> {215 for v in arr.iter() {216 let v = bool::from_untyped(v?)?;217 if !v {218 return Ok(false);219 }220 }221 Ok(true)222}223224#[builtin]225pub fn builtin_member(arr: IndexableVal, x: Val) -> Result<bool> {226 match arr {227 IndexableVal::Str(str) => {228 let x: IStr = IStr::from_untyped(x)?;229 Ok(!x.is_empty() && str.contains(&*x))230 }231 IndexableVal::Arr(a) => {232 for item in a.iter() {233 let item = item?;234 if equals(&item, &x)? {235 return Ok(true);236 }237 }238 Ok(false)239 }240 }241}242243#[builtin]244pub fn builtin_contains(arr: IndexableVal, elem: Val) -> Result<bool> {245 builtin_member(arr, elem)246}247248#[builtin]249pub fn builtin_count(arr: ArrValue, x: Val) -> Result<usize> {250 let mut count = 0;251 for item in arr.iter() {252 if equals(&item?, &x)? {253 count += 1;254 }255 }256 Ok(count)257}258259#[builtin]260pub fn builtin_avg(arr: Vec<f64>, onEmpty: Option<Thunk<Val>>) -> Result<Val> {261 if arr.is_empty() {262 return eval_on_empty(onEmpty);263 }264 Ok(Val::Num(arr.iter().sum::<f64>() / (arr.len() as f64)))265}266267#[builtin]268pub fn builtin_remove_at(arr: ArrValue, at: usize) -> Result<ArrValue> {269 let newArrLeft = arr.clone().slice(None, Some(at), None);270 let newArrRight = arr.slice(Some(at + 1), None, None);271272 Ok(ArrValue::extended(273 newArrLeft.unwrap_or(ArrValue::empty()),274 newArrRight.unwrap_or(ArrValue::empty()),275 ))276}277278#[builtin]279pub fn builtin_remove(arr: ArrValue, elem: Val) -> Result<ArrValue> {280 for (index, item) in arr.iter().enumerate() {281 if equals(&item?, &elem)? {282 return builtin_remove_at(arr.clone(), index);283 }284 }285 Ok(arr)286}287288#[builtin]289pub fn builtin_flatten_arrays(arrs: Vec<ArrValue>) -> ArrValue {290 pub fn flatten_inner(values: &[ArrValue]) -> ArrValue {291 if values.len() == 1 {292 return values[0].clone();293 } else if values.len() == 2 {294 return ArrValue::extended(values[0].clone(), values[1].clone());295 }296 let (a, b) = values.split_at(values.len() / 2);297 ArrValue::extended(flatten_inner(a), flatten_inner(b))298 }299 if arrs.is_empty() {300 return ArrValue::empty();301 } else if arrs.len() == 1 {302 return arrs.into_iter().next().expect("single");303 }304 flatten_inner(&arrs)305}306307#[builtin]308pub fn builtin_flatten_deep_array(value: Val) -> Result<Vec<Val>> {309 fn process(value: Val, out: &mut Vec<Val>) -> Result<()> {310 match value {311 Val::Arr(arr) => {312 for ele in arr.iter() {313 process(ele?, out)?;314 }315 }316 _ => out.push(value),317 }318 Ok(())319 }320 let mut out = Vec::new();321 process(value, &mut out)?;322 Ok(out)323}324325#[builtin]326pub fn builtin_prune(327 a: Val,328 #[cfg(feature = "exp-preserve-order")] preserve_order: bool,329) -> Result<Val> {330 fn is_content(val: &Val) -> bool {331 match val {332 Val::Null => false,333 Val::Arr(a) => !a.is_empty(),334 Val::Obj(o) => !o.is_empty(),335 _ => true,336 }337 }338 Ok(match a {339 Val::Arr(a) => {340 let mut out = Vec::new();341 for (i, ele) in a.iter().enumerate() {342 let ele = ele343 .and_then(|v| {344 builtin_prune(345 v,346 #[cfg(feature = "exp-preserve-order")]347 preserve_order,348 )349 })350 .with_description(|| format!("elem <{i}> pruning"))?;351 if is_content(&ele) {352 out.push(ele);353 }354 }355 Val::Arr(ArrValue::eager(out))356 }357 Val::Obj(o) => {358 let mut out = ObjValueBuilder::new();359 for (name, value) in o.iter(360 #[cfg(feature = "exp-preserve-order")]361 preserve_order,362 ) {363 let value = value364 .and_then(|v| {365 builtin_prune(366 v,367 #[cfg(feature = "exp-preserve-order")]368 preserve_order,369 )370 })371 .with_description(|| format!("field <{name}> pruning"))?;372 if !is_content(&value) {373 continue;374 }375 out.field(name).value(value);376 }377 Val::Obj(out.build())378 }379 _ => a,380 })381}crates/jrsonnet-stdlib/src/lib.rsdiffbeforeafterboth--- a/crates/jrsonnet-stdlib/src/lib.rs
+++ b/crates/jrsonnet-stdlib/src/lib.rs
@@ -92,6 +92,7 @@
("remove", builtin_remove::INST),
("flattenArrays", builtin_flatten_arrays::INST),
("flattenDeepArray", builtin_flatten_deep_array::INST),
+ ("prune", builtin_prune::INST),
("filterMap", builtin_filter_map::INST),
// Math
("abs", builtin_abs::INST),
crates/jrsonnet-stdlib/src/std.jsonnetdiffbeforeafterboth--- a/crates/jrsonnet-stdlib/src/std.jsonnet
+++ b/crates/jrsonnet-stdlib/src/std.jsonnet
@@ -209,25 +209,6 @@
local arr = std.split(f, '/');
std.join('/', std.makeArray(std.length(arr) - 1, function(i) arr[i]) + [r]),
- prune(a)::
- local isContent(b) =
- if b == null then
- false
- else if std.isArray(b) then
- std.length(b) > 0
- else if std.isObject(b) then
- std.length(b) > 0
- else
- true;
- if std.isArray(a) then
- [std.prune(x) for x in a if isContent($.prune(x))]
- else if std.isObject(a) then {
- [x]: $.prune(a[x])
- for x in std.objectFields(a)
- if isContent(std.prune(a[x]))
- } else
- a,
-
find(value, arr)::
if !std.isArray(arr) then
error 'find second parameter should be an array, got ' + std.type(arr)