difftreelog
perf(evaluator) "faster" feature flag
in: master
3 files changed
crates/jsonnet-evaluator/Cargo.tomldiffbeforeafterboth7# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html7# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html889[features]9[features]10default = ["serialized-stdlib"]10default = ["serialized-stdlib", "faster"]11serialized-stdlib = ["serde", "bincode"]11serialized-stdlib = ["serde", "bincode"]12# Replace some standard library functions with faster implementations13faster = []121413[dependencies]15[dependencies]14jsonnet-parser = { path = "../jsonnet-parser" }16jsonnet-parser = { path = "../jsonnet-parser" }crates/jsonnet-evaluator/build.rsdiffbeforeafterboth--- a/crates/jsonnet-evaluator/build.rs
+++ b/crates/jsonnet-evaluator/build.rs
@@ -1,11 +1,14 @@
use bincode::serialize;
-use jsonnet_parser::{parse, ParserSettings};
+use jsonnet_parser::{
+ parse, Expr, FieldMember, FieldName, LocExpr, Member, ObjBody, ParserSettings,
+};
use jsonnet_stdlib::STDLIB_STR;
use std::{
env,
fs::File,
io::Write,
path::{Path, PathBuf},
+ rc::Rc,
};
fn main() {
@@ -18,6 +21,32 @@
)
.expect("parse");
+ let parsed = if cfg!(feature = "faster") {
+ let LocExpr(expr, location) = parsed;
+ LocExpr(
+ Rc::new(match Rc::try_unwrap(expr).unwrap() {
+ Expr::Obj(ObjBody::MemberList(members)) => Expr::Obj(ObjBody::MemberList(
+ members
+ .into_iter()
+ .filter(|p| {
+ !matches!(
+ p,
+ Member::Field(FieldMember {
+ name: FieldName::Fixed(name),
+ ..
+ }) if name == "join"
+ )
+ })
+ .collect(),
+ )),
+ _ => panic!("std value should be object"),
+ }),
+ location,
+ )
+ } else {
+ parsed
+ };
+
let out_dir = env::var("OUT_DIR").unwrap();
let dest_path = Path::new(&out_dir).join("stdlib.bincode");
let mut f = File::create(&dest_path).unwrap();
crates/jsonnet-evaluator/src/evaluate.rsdiffbeforeafterboth--- a/crates/jsonnet-evaluator/src/evaluate.rs
+++ b/crates/jsonnet-evaluator/src/evaluate.rs
@@ -661,6 +661,76 @@
panic!("bad extVar call");
}
}
+ ("std", "filter") => {
+ assert_eq!(args.len(), 2);
+ if let (Val::Func(predicate), Val::Arr(arr)) = (
+ evaluate(context, &args[0].1)?,
+ evaluate(context, &args[1].1)?,
+ ) {
+ Val::Arr(
+ arr.into_iter()
+ .filter(|e| {
+ predicate
+ .evaluate_values(&context, &[e.clone()])
+ .unwrap()
+ .try_cast_bool("filter predicate")
+ .unwrap()
+ })
+ .collect(),
+ )
+ } else {
+ panic!("bad filter call");
+ }
+ }
+ // faster
+ ("std", "join") => {
+ assert_eq!(args.len(), 2);
+ let joiner = evaluate(context, &args[0].1)?.unwrap_if_lazy()?;
+ let items = evaluate(context, &args[1].1)?.unwrap_if_lazy()?;
+ println!("Before");
+ let result = match (joiner, items) {
+ (Val::Arr(joiner_items), Val::Arr(items)) => {
+ // TODO: Minimal size should be known
+ let mut out = Vec::new();
+
+ let mut first = true;
+ for item in items {
+ if let Val::Arr(items) = item.unwrap_if_lazy()? {
+ if !first {
+ out.extend(joiner_items.iter().cloned());
+ }
+ first = false;
+ out.extend(items);
+ } else {
+ panic!("all array items should be arrays")
+ }
+ }
+
+ Val::Arr(out)
+ }
+ (Val::Str(joiner), Val::Arr(items)) => {
+ let mut out = String::new();
+
+ let mut first = true;
+ for item in items {
+ if let Val::Str(item) = item.unwrap_if_lazy()? {
+ if !first {
+ out += &joiner;
+ }
+ first = false;
+ out += &item;
+ } else {
+ panic!("all array items should be strings")
+ }
+ }
+
+ Val::Str(out)
+ }
+ (joiner, items) => panic!("bad join call: {:?} {:?}", joiner, items),
+ };
+ println!("After");
+ result
+ }
(ns, name) => panic!("Intristic not found: {}.{}", ns, name),
},
Val::Func(f) => {