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

difftreelog

perf faster std.map

Yaroslav Bolyukin2021-02-20parent: #643b007.patch.diff
in: master

3 files changed

modifiedcrates/jrsonnet-evaluator/build.rsdiffbeforeafterboth
before · crates/jrsonnet-evaluator/build.rs
1use bincode::serialize;2use jrsonnet_parser::{3	parse, Expr, FieldMember, FieldName, LocExpr, Member, ObjBody, ParserSettings,4};5use jrsonnet_stdlib::STDLIB_STR;6use std::{7	env,8	fs::File,9	io::Write,10	path::{Path, PathBuf},11	rc::Rc,12};1314fn main() {15	let parsed = parse(16		STDLIB_STR,17		&ParserSettings {18			file_name: Rc::new(PathBuf::from("std.jsonnet")),19			loc_data: true,20		},21	)22	.expect("parse");2324	let parsed = if cfg!(feature = "faster") {25		let LocExpr(expr, location) = parsed;26		LocExpr(27			Rc::new(match Rc::try_unwrap(expr).unwrap() {28				Expr::Obj(ObjBody::MemberList(members)) => Expr::Obj(ObjBody::MemberList(29					members30						.into_iter()31						.filter(|p| {32							!matches!(33								p,34								Member::Field(FieldMember {35									name: FieldName::Fixed(name),36									..37								})38								if name == "join" || name == "manifestJsonEx" ||39								name == "escapeStringJson" || name == "equals" ||40								name == "base64" || name == "foldl" || name == "foldr" ||41								name == "sortImpl" || name == "format" || name == "range" ||42								name == "reverse" || name == "slice" || name == "mod" ||43								name == "strReplace"44							)45						})46						.collect(),47				)),48				_ => panic!("std value should be object"),49			}),50			location,51		)52	} else {53		parsed54	};55	{56		let out_dir = env::var("OUT_DIR").unwrap();57		let dest_path = Path::new(&out_dir).join("stdlib.bincode");58		let mut f = File::create(&dest_path).unwrap();59		f.write_all(&serialize(&parsed).unwrap()).unwrap();60	}61}
after · crates/jrsonnet-evaluator/build.rs
1use bincode::serialize;2use jrsonnet_parser::{3	parse, Expr, FieldMember, FieldName, LocExpr, Member, ObjBody, ParserSettings,4};5use jrsonnet_stdlib::STDLIB_STR;6use std::{7	env,8	fs::File,9	io::Write,10	path::{Path, PathBuf},11	rc::Rc,12};1314fn main() {15	let parsed = parse(16		STDLIB_STR,17		&ParserSettings {18			file_name: Rc::new(PathBuf::from("std.jsonnet")),19			loc_data: true,20		},21	)22	.expect("parse");2324	let parsed = if cfg!(feature = "faster") {25		let LocExpr(expr, location) = parsed;26		LocExpr(27			Rc::new(match Rc::try_unwrap(expr).unwrap() {28				Expr::Obj(ObjBody::MemberList(members)) => Expr::Obj(ObjBody::MemberList(29					members30						.into_iter()31						.filter(|p| {32							!matches!(33								p,34								Member::Field(FieldMember {35									name: FieldName::Fixed(name),36									..37								})38								if name == "join" || name == "manifestJsonEx" ||39								name == "escapeStringJson" || name == "equals" ||40								name == "base64" || name == "foldl" || name == "foldr" ||41								name == "sortImpl" || name == "format" || name == "range" ||42								name == "reverse" || name == "slice" || name == "mod" ||43								name == "strReplace" || name == "map"44							)45						})46						.collect(),47				)),48				_ => panic!("std value should be object"),49			}),50			location,51		)52	} else {53		parsed54	};55	{56		let out_dir = env::var("OUT_DIR").unwrap();57		let dest_path = Path::new(&out_dir).join("stdlib.bincode");58		let mut f = File::create(&dest_path).unwrap();59		f.write_all(&serialize(&parsed).unwrap()).unwrap();60	}61}
modifiedcrates/jrsonnet-evaluator/src/builtin/mod.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/builtin/mod.rs
+++ b/crates/jrsonnet-evaluator/src/builtin/mod.rs
@@ -57,6 +57,7 @@
 			("extVar".into(), builtin_ext_var),
 			("native".into(), builtin_native),
 			("filter".into(), builtin_filter),
+			("map".into(), builtin_map),
 			("foldl".into(), builtin_foldl),
 			("foldr".into(), builtin_foldr),
 			("sortImpl".into(), builtin_sort_impl),
@@ -294,16 +295,19 @@
 		0, func: ty!(function) => Val::Func;
 		1, arr: ty!(array) => Val::Arr;
 	], {
-		let mut out = Vec::new();
-		for item in arr.iter() {
-			let item = item?;
-			if func
-						.evaluate_values(context.clone(), &[item.clone()])?
-						.try_cast_bool("filter predicate")? {
-							out.push(item);
-						}
-		}
-		Ok(Val::Arr(out.into()))
+		Ok(Val::Arr(arr.filter(|val| func
+			.evaluate_values(context.clone(), &[val.clone()])?
+			.try_cast_bool("filter predicate"))?))
+	})
+}
+
+fn builtin_map(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+	parse_args!(context, "map", args, 2, [
+		0, func: ty!(function) => Val::Func;
+		1, arr: ty!(array) => Val::Arr;
+	], {
+		Ok(Val::Arr(arr.map(|val| func
+			.evaluate_values(context.clone(), &[val]))?))
 	})
 }
 
modifiedcrates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/val.rs
+++ b/crates/jrsonnet-evaluator/src/val.rs
@@ -283,6 +283,29 @@
 		}
 	}
 
+	pub fn map(self, mapper: impl Fn(Val) -> Result<Val>) -> Result<Self> {
+		let mut out = Vec::with_capacity(self.len());
+
+		for value in self.iter() {
+			out.push(mapper(value?)?);
+		}
+
+		Ok(Self::Eager(Rc::new(out)))
+	}
+
+	pub fn filter(self, filter: impl Fn(&Val) -> Result<bool>) -> Result<Self> {
+		let mut out = Vec::with_capacity(self.len());
+
+		for value in self.iter() {
+			let value = value?;
+			if filter(&value)? {
+				out.push(value);
+			}
+		}
+
+		Ok(Self::Eager(Rc::new(out)))
+	}
+
 	pub fn ptr_eq(a: &Self, b: &Self) -> bool {
 		match (a, b) {
 			(Self::Lazy(a), Self::Lazy(b)) => Rc::ptr_eq(a, b),