git.delta.rocks / jrsonnet / refs/commits / 4ab075dbe65c

difftreelog

fix std function argument names

Yaroslav Bolyukin2023-08-10parent: #cfa49ab.patch.diff
in: master

6 files changed

modifiedcrates/jrsonnet-stdlib/src/arrays.rsdiffbeforeafterboth
before · crates/jrsonnet-stdlib/src/arrays.rs
1#![allow(non_snake_case)]23use jrsonnet_evaluator::{4	error::{ErrorKind::RuntimeError, Result},5	function::{builtin, FuncVal},6	throw,7	typed::{BoundedI32, BoundedUsize, Either2, NativeFn, Typed},8	val::{equals, ArrValue, IndexableVal, StrValue},9	Either, IStr, 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		throw!("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	if let Some(trivial) = func.evaluate_trivial() {26		let mut out = Vec::with_capacity(*sz as usize);27		for _ in 0..*sz {28			out.push(trivial.clone())29		}30		Ok(ArrValue::eager(out))31	} else {32		Ok(ArrValue::range_exclusive(0, *sz).map(func))33	}34}3536#[builtin]37pub fn builtin_repeat(what: Either![IStr, ArrValue], count: usize) -> Result<Val> {38	Ok(match what {39		Either2::A(s) => Val::Str(StrValue::Flat(s.repeat(count).into())),40		Either2::B(arr) => Val::Arr(41			ArrValue::repeated(arr, count)42				.ok_or_else(|| RuntimeError("repeated length overflow".into()))?,43		),44	})45}4647#[builtin]48pub fn builtin_slice(49	indexable: IndexableVal,50	index: Option<BoundedUsize<0, { i32::MAX as usize }>>,51	end: Option<BoundedUsize<0, { i32::MAX as usize }>>,52	step: Option<BoundedUsize<1, { i32::MAX as usize }>>,53) -> Result<Val> {54	indexable.slice(index, end, step).map(Val::from)55}5657#[builtin]58pub fn builtin_map(func: FuncVal, arr: IndexableVal) -> ArrValue {59	let arr = arr.to_array();60	arr.map(func)61}6263#[builtin]64pub fn builtin_flatmap(65	func: NativeFn<((Either![String, Val],), Val)>,66	arr: IndexableVal,67) -> Result<IndexableVal> {68	use std::fmt::Write;69	match arr {70		IndexableVal::Str(str) => {71			let mut out = String::new();72			for c in str.chars() {73				match func(Either2::A(c.to_string()))? {74					Val::Str(o) => write!(out, "{o}").unwrap(),75					Val::Null => continue,76					_ => throw!("in std.join all items should be strings"),77				};78			}79			Ok(IndexableVal::Str(out.into()))80		}81		IndexableVal::Arr(a) => {82			let mut out = Vec::new();83			for el in a.iter() {84				let el = el?;85				match func(Either2::B(el))? {86					Val::Arr(o) => {87						for oe in o.iter() {88							out.push(oe?);89						}90					}91					Val::Null => continue,92					_ => throw!("in std.join all items should be arrays"),93				};94			}95			Ok(IndexableVal::Arr(out.into()))96		}97	}98}99100#[builtin]101pub fn builtin_filter(func: FuncVal, arr: ArrValue) -> Result<ArrValue> {102	arr.filter(|val| bool::from_untyped(func.evaluate_simple(&(val.clone(),), false)?))103}104105#[builtin]106pub fn builtin_foldl(func: FuncVal, arr: ArrValue, init: Val) -> Result<Val> {107	let mut acc = init;108	for i in arr.iter() {109		acc = func.evaluate_simple(&(acc, i?), false)?;110	}111	Ok(acc)112}113114#[builtin]115pub fn builtin_foldr(func: FuncVal, arr: ArrValue, init: Val) -> Result<Val> {116	let mut acc = init;117	for i in arr.iter().rev() {118		acc = func.evaluate_simple(&(i?, acc), false)?;119	}120	Ok(acc)121}122123#[builtin]124pub fn builtin_range(from: i32, to: i32) -> Result<ArrValue> {125	if to < from {126		return Ok(ArrValue::empty());127	}128	Ok(ArrValue::range_inclusive(from, to))129}130131#[builtin]132pub fn builtin_join(sep: IndexableVal, arr: ArrValue) -> Result<IndexableVal> {133	use std::fmt::Write;134	Ok(match sep {135		IndexableVal::Arr(joiner_items) => {136			let mut out = Vec::new();137138			let mut first = true;139			for item in arr.iter() {140				let item = item?.clone();141				if let Val::Arr(items) = item {142					if !first {143						out.reserve(joiner_items.len());144						// TODO: extend145						for item in joiner_items.iter() {146							out.push(item?);147						}148					}149					first = false;150					out.reserve(items.len());151					for item in items.iter() {152						out.push(item?);153					}154				} else if matches!(item, Val::Null) {155					continue;156				} else {157					throw!("in std.join all items should be arrays");158				}159			}160161			IndexableVal::Arr(out.into())162		}163		IndexableVal::Str(sep) => {164			let mut out = String::new();165166			let mut first = true;167			for item in arr.iter() {168				let item = item?.clone();169				if let Val::Str(item) = item {170					if !first {171						out += &sep;172					}173					first = false;174					write!(out, "{item}").unwrap()175				} else if matches!(item, Val::Null) {176					continue;177				} else {178					throw!("in std.join all items should be strings");179				}180			}181182			IndexableVal::Str(out.into())183		}184	})185}186187#[builtin]188pub fn builtin_reverse(arr: ArrValue) -> ArrValue {189	arr.reversed()190}191192#[builtin]193pub fn builtin_any(arr: ArrValue) -> Result<bool> {194	for v in arr.iter() {195		let v = bool::from_untyped(v?)?;196		if v {197			return Ok(true);198		}199	}200	Ok(false)201}202203#[builtin]204pub fn builtin_all(arr: ArrValue) -> Result<bool> {205	for v in arr.iter() {206		let v = bool::from_untyped(v?)?;207		if !v {208			return Ok(false);209		}210	}211	Ok(true)212}213214#[builtin]215pub fn builtin_member(arr: IndexableVal, x: Val) -> Result<bool> {216	match arr {217		IndexableVal::Str(str) => {218			let x: IStr = IStr::from_untyped(x)?;219			Ok(!x.is_empty() && str.contains(&*x))220		}221		IndexableVal::Arr(a) => {222			for item in a.iter() {223				let item = item?;224				if equals(&item, &x)? {225					return Ok(true);226				}227			}228			Ok(false)229		}230	}231}232233#[builtin]234pub fn builtin_contains(arr: IndexableVal, elem: Val) -> Result<bool> {235	builtin_member(arr, elem)236}237238#[builtin]239pub fn builtin_count(arr: ArrValue, x: Val) -> Result<usize> {240	let mut count = 0;241	for item in arr.iter() {242		if equals(&item?, &x)? {243			count += 1;244		}245	}246	Ok(count)247}248249#[builtin]250pub fn builtin_avg(arr: Vec<f64>, onEmpty: Option<Thunk<Val>>) -> Result<Val> {251	if arr.is_empty() {252		return eval_on_empty(onEmpty);253	}254	Ok(Val::Num(arr.iter().sum::<f64>() / (arr.len() as f64)))255}256257#[builtin]258pub fn builtin_remove_at(arr: ArrValue, index: usize) -> Result<ArrValue> {259	let newArrLeft = arr.clone().slice(None, Some(index), None);260	let newArrRight = arr.slice(Some(index + 1), None, None);261262	Ok(ArrValue::extended(263		newArrLeft.unwrap_or(ArrValue::empty()),264		newArrRight.unwrap_or(ArrValue::empty()),265	))266}267268#[builtin]269pub fn builtin_remove(arr: ArrValue, elem: Val) -> Result<ArrValue> {270	for (index, item) in arr.iter().enumerate() {271		if equals(&item?, &elem)? {272			return builtin_remove_at(arr.clone(), index);273		}274	}275	Ok(arr)276}
after · crates/jrsonnet-stdlib/src/arrays.rs
1#![allow(non_snake_case)]23use jrsonnet_evaluator::{4	error::{ErrorKind::RuntimeError, Result},5	function::{builtin, FuncVal},6	throw,7	typed::{BoundedI32, BoundedUsize, Either2, NativeFn, Typed},8	val::{equals, ArrValue, IndexableVal, StrValue},9	Either, IStr, 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		throw!("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	if let Some(trivial) = func.evaluate_trivial() {26		let mut out = Vec::with_capacity(*sz as usize);27		for _ in 0..*sz {28			out.push(trivial.clone())29		}30		Ok(ArrValue::eager(out))31	} else {32		Ok(ArrValue::range_exclusive(0, *sz).map(func))33	}34}3536#[builtin]37pub fn builtin_repeat(what: Either![IStr, ArrValue], count: usize) -> Result<Val> {38	Ok(match what {39		Either2::A(s) => Val::Str(StrValue::Flat(s.repeat(count).into())),40		Either2::B(arr) => Val::Arr(41			ArrValue::repeated(arr, count)42				.ok_or_else(|| RuntimeError("repeated length overflow".into()))?,43		),44	})45}4647#[builtin]48pub fn builtin_slice(49	indexable: IndexableVal,50	index: Option<BoundedUsize<0, { i32::MAX as usize }>>,51	end: Option<BoundedUsize<0, { i32::MAX as usize }>>,52	step: Option<BoundedUsize<1, { i32::MAX as usize }>>,53) -> Result<Val> {54	indexable.slice(index, end, step).map(Val::from)55}5657#[builtin]58pub fn builtin_map(func: FuncVal, arr: IndexableVal) -> ArrValue {59	let arr = arr.to_array();60	arr.map(func)61}6263#[builtin]64pub fn builtin_flatmap(65	func: NativeFn<((Either![String, Val],), Val)>,66	arr: IndexableVal,67) -> Result<IndexableVal> {68	use std::fmt::Write;69	match arr {70		IndexableVal::Str(str) => {71			let mut out = String::new();72			for c in str.chars() {73				match func(Either2::A(c.to_string()))? {74					Val::Str(o) => write!(out, "{o}").unwrap(),75					Val::Null => continue,76					_ => throw!("in std.join all items should be strings"),77				};78			}79			Ok(IndexableVal::Str(out.into()))80		}81		IndexableVal::Arr(a) => {82			let mut out = Vec::new();83			for el in a.iter() {84				let el = el?;85				match func(Either2::B(el))? {86					Val::Arr(o) => {87						for oe in o.iter() {88							out.push(oe?);89						}90					}91					Val::Null => continue,92					_ => throw!("in std.join all items should be arrays"),93				};94			}95			Ok(IndexableVal::Arr(out.into()))96		}97	}98}99100#[builtin]101pub fn builtin_filter(func: FuncVal, arr: ArrValue) -> Result<ArrValue> {102	arr.filter(|val| bool::from_untyped(func.evaluate_simple(&(val.clone(),), false)?))103}104105#[builtin]106pub fn builtin_foldl(func: FuncVal, arr: ArrValue, init: Val) -> Result<Val> {107	let mut acc = init;108	for i in arr.iter() {109		acc = func.evaluate_simple(&(acc, i?), false)?;110	}111	Ok(acc)112}113114#[builtin]115pub fn builtin_foldr(func: FuncVal, arr: ArrValue, init: Val) -> Result<Val> {116	let mut acc = init;117	for i in arr.iter().rev() {118		acc = func.evaluate_simple(&(i?, acc), false)?;119	}120	Ok(acc)121}122123#[builtin]124pub fn builtin_range(from: i32, to: i32) -> Result<ArrValue> {125	if to < from {126		return Ok(ArrValue::empty());127	}128	Ok(ArrValue::range_inclusive(from, to))129}130131#[builtin]132pub fn builtin_join(sep: IndexableVal, arr: ArrValue) -> Result<IndexableVal> {133	use std::fmt::Write;134	Ok(match sep {135		IndexableVal::Arr(joiner_items) => {136			let mut out = Vec::new();137138			let mut first = true;139			for item in arr.iter() {140				let item = item?.clone();141				if let Val::Arr(items) = item {142					if !first {143						out.reserve(joiner_items.len());144						// TODO: extend145						for item in joiner_items.iter() {146							out.push(item?);147						}148					}149					first = false;150					out.reserve(items.len());151					for item in items.iter() {152						out.push(item?);153					}154				} else if matches!(item, Val::Null) {155					continue;156				} else {157					throw!("in std.join all items should be arrays");158				}159			}160161			IndexableVal::Arr(out.into())162		}163		IndexableVal::Str(sep) => {164			let mut out = String::new();165166			let mut first = true;167			for item in arr.iter() {168				let item = item?.clone();169				if let Val::Str(item) = item {170					if !first {171						out += &sep;172					}173					first = false;174					write!(out, "{item}").unwrap()175				} else if matches!(item, Val::Null) {176					continue;177				} else {178					throw!("in std.join all items should be strings");179				}180			}181182			IndexableVal::Str(out.into())183		}184	})185}186187#[builtin]188pub fn builtin_reverse(arr: ArrValue) -> ArrValue {189	arr.reversed()190}191192#[builtin]193pub fn builtin_any(arr: ArrValue) -> Result<bool> {194	for v in arr.iter() {195		let v = bool::from_untyped(v?)?;196		if v {197			return Ok(true);198		}199	}200	Ok(false)201}202203#[builtin]204pub fn builtin_all(arr: ArrValue) -> Result<bool> {205	for v in arr.iter() {206		let v = bool::from_untyped(v?)?;207		if !v {208			return Ok(false);209		}210	}211	Ok(true)212}213214#[builtin]215pub fn builtin_member(arr: IndexableVal, x: Val) -> Result<bool> {216	match arr {217		IndexableVal::Str(str) => {218			let x: IStr = IStr::from_untyped(x)?;219			Ok(!x.is_empty() && str.contains(&*x))220		}221		IndexableVal::Arr(a) => {222			for item in a.iter() {223				let item = item?;224				if equals(&item, &x)? {225					return Ok(true);226				}227			}228			Ok(false)229		}230	}231}232233#[builtin]234pub fn builtin_contains(arr: IndexableVal, elem: Val) -> Result<bool> {235	builtin_member(arr, elem)236}237238#[builtin]239pub fn builtin_count(arr: ArrValue, x: Val) -> Result<usize> {240	let mut count = 0;241	for item in arr.iter() {242		if equals(&item?, &x)? {243			count += 1;244		}245	}246	Ok(count)247}248249#[builtin]250pub fn builtin_avg(arr: Vec<f64>, onEmpty: Option<Thunk<Val>>) -> Result<Val> {251	if arr.is_empty() {252		return eval_on_empty(onEmpty);253	}254	Ok(Val::Num(arr.iter().sum::<f64>() / (arr.len() as f64)))255}256257#[builtin]258pub fn builtin_remove_at(arr: ArrValue, at: usize) -> Result<ArrValue> {259	let newArrLeft = arr.clone().slice(None, Some(at), None);260	let newArrRight = arr.slice(Some(at + 1), None, None);261262	Ok(ArrValue::extended(263		newArrLeft.unwrap_or(ArrValue::empty()),264		newArrRight.unwrap_or(ArrValue::empty()),265	))266}267268#[builtin]269pub fn builtin_remove(arr: ArrValue, elem: Val) -> Result<ArrValue> {270	for (index, item) in arr.iter().enumerate() {271		if equals(&item?, &elem)? {272			return builtin_remove_at(arr.clone(), index);273		}274	}275	Ok(arr)276}
modifiedcrates/jrsonnet-stdlib/src/hash.rsdiffbeforeafterboth
--- a/crates/jrsonnet-stdlib/src/hash.rs
+++ b/crates/jrsonnet-stdlib/src/hash.rs
@@ -6,25 +6,25 @@
 }
 
 #[builtin]
-pub fn builtin_sha256(s: IStr) -> String {
+pub fn builtin_sha256(str: IStr) -> String {
 	use sha2::digest::Digest;
-	format!("{:x}", sha2::Sha256::digest(s.as_bytes()))
+	format!("{:x}", sha2::Sha256::digest(str.as_bytes()))
 }
 
 #[builtin]
-pub fn builtin_sha512(s: IStr) -> String {
+pub fn builtin_sha512(str: IStr) -> String {
 	use sha2::digest::Digest;
-	format!("{:x}", sha2::Sha512::digest(s.as_bytes()))
+	format!("{:x}", sha2::Sha512::digest(str.as_bytes()))
 }
 
 #[builtin]
-pub fn builtin_sha1(s: IStr) -> String {
+pub fn builtin_sha1(str: IStr) -> String {
 	use sha1::digest::Digest;
-	format!("{:x}", sha1::Sha1::digest(s.as_bytes()))
+	format!("{:x}", sha1::Sha1::digest(str.as_bytes()))
 }
 
 #[builtin]
-pub fn builtin_sha3(s: IStr) -> String {
+pub fn builtin_sha3(str: IStr) -> String {
 	use sha3::digest::Digest;
-	format!("{:x}", sha3::Sha3_512::digest(s.as_bytes()))
+	format!("{:x}", sha3::Sha3_512::digest(str.as_bytes()))
 }
modifiedcrates/jrsonnet-stdlib/src/lib.rsdiffbeforeafterboth
--- a/crates/jrsonnet-stdlib/src/lib.rs
+++ b/crates/jrsonnet-stdlib/src/lib.rs
@@ -80,7 +80,7 @@
 		("any", builtin_any::INST),
 		("all", builtin_all::INST),
 		("member", builtin_member::INST),
-		("contains", builtin_member::INST),
+		("contains", builtin_contains::INST),
 		("count", builtin_count::INST),
 		("avg", builtin_avg::INST),
 		("removeAt", builtin_remove_at::INST),
modifiedcrates/jrsonnet-stdlib/src/misc.rsdiffbeforeafterboth
--- a/crates/jrsonnet-stdlib/src/misc.rs
+++ b/crates/jrsonnet-stdlib/src/misc.rs
@@ -57,12 +57,12 @@
 	this: &builtin_trace,
 	loc: CallLocation,
 	str: Val,
-	rest: Thunk<Val>,
+	rest: Option<Thunk<Val>>,
 ) -> Result<Val> {
 	this.settings.borrow().trace_printer.print_trace(
 		loc,
-		match str {
-			Val::Str(s) => s.into_flat(),
+		match &str {
+			Val::Str(s) => s.clone().into_flat(),
 			Val::Func(f) => format!("{f:?}").into(),
 			v => v
 				.manifest(JsonFormat::std_to_json(
@@ -75,7 +75,11 @@
 				.into(),
 		},
 	);
-	rest.evaluate()
+	if let Some(rest) = rest {
+		rest.evaluate()
+	} else {
+		Ok(str)
+	}
 }
 
 #[allow(clippy::comparison_chain)]
modifiedcrates/jrsonnet-stdlib/src/strings.rsdiffbeforeafterboth
--- a/crates/jrsonnet-stdlib/src/strings.rs
+++ b/crates/jrsonnet-stdlib/src/strings.rs
@@ -33,8 +33,8 @@
 }
 
 #[builtin]
-pub fn builtin_equals_ignore_case(x: String, y: String) -> bool {
-	x.to_ascii_lowercase() == y.to_ascii_lowercase()
+pub fn builtin_equals_ignore_case(str1: String, str2: String) -> bool {
+	str1.to_ascii_lowercase() == str2.to_ascii_lowercase()
 }
 
 #[builtin]
modifiedtests/suite/std_param_names.jsonnetdiffbeforeafterboth
--- a/tests/suite/std_param_names.jsonnet
+++ b/tests/suite/std_param_names.jsonnet
@@ -126,8 +126,33 @@
     decodeUTF8: ['arr'],
 
     sum: ['arr'],
+    avg: ['arr', 'onEmpty'],
+    minArray: ['arr', 'keyF', 'onEmpty'],
+    maxArray: ['arr', 'keyF', 'onEmpty'],
+    remove: ['arr', 'elem'],
+    contains: ['arr', 'elem'],
+    removeAt: ['arr', 'at'],
+
+    equalsIgnoreCase: ['str1', 'str2'],
+    isEmpty: ['str'],
+
     xor: ['x', 'y'],
+    xnor: ['x', 'y'],
+    isInteger: ['x'],
+    isDecimal: ['x'],
+    isEven: ['x'],
+    isOdd: ['x'],
+    round: ['x'],
 
+    sha1: ['str'],
+    sha256: ['str'],
+    sha512: ['str'],
+    sha3: ['str'],
+
+    objectKeysValues: ['o'],
+    objectKeysValuesAll: ['o'],
+    objectRemoveKey: ['obj', 'key'],
+
     // C++ jsonnet undocumented
     __compare: ['v1', 'v2'],
     __compare_array: ['arr1', 'arr2'],
@@ -138,3 +163,9 @@
 };
 
 std.all(std.map(function(key) assertNames(key, names[key]), std.objectFields(names)))
+&& std.all([
+    assert std.objectHasAll(names, key): ('function "%s" is not defined in names'
+        % key); true,
+    for key in std.objectFieldsAll(std)
+    if key != 'thisFile'
+])