difftreelog
perf(evaluator) faster std.equals
in: master
4 files changed
crates/jrsonnet-evaluator/build.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/build.rs
+++ b/crates/jrsonnet-evaluator/build.rs
@@ -35,7 +35,7 @@
Member::Field(FieldMember {
name: FieldName::Fixed(name),
..
- }) if **name == *"join" || **name == *"manifestJsonEx" || **name == *"escapeStringJson"
+ }) if **name == *"join" || **name == *"manifestJsonEx" || **name == *"escapeStringJson" || **name == *"equals"
)
})
.collect(),
crates/jrsonnet-evaluator/src/evaluate.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/evaluate.rs
+++ b/crates/jrsonnet-evaluator/src/evaluate.rs
@@ -484,7 +484,14 @@
0, a, vec![];
1, b, vec![];
], {
- Val::Bool(a == b)
+ Val::Bool(primitive_equals(&a, &b)?)
+ }),
+ // faster
+ ("std", "equals") => parse_args!(context, "std.equals", args, 2, [
+ 0, a, vec![];
+ 1, b, vec![];
+ ], {
+ Val::Bool(equals(&a, &b)?)
}),
("std", "modulo") => parse_args!(context, "std.modulo", args, 2, [
0, a: [Val::Num]!!Val::Num, vec![ValType::Num];
crates/jrsonnet-evaluator/src/lib.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/lib.rs
+++ b/crates/jrsonnet-evaluator/src/lib.rs
@@ -380,7 +380,7 @@
#[cfg(test)]
pub mod tests {
use super::Val;
- use crate::EvaluationState;
+ use crate::{create_error, EvaluationState, primitive_equals};
use jrsonnet_parser::*;
use std::{path::PathBuf, rc::Rc};
@@ -411,11 +411,11 @@
fn eval_state_standard() {
let state = EvaluationState::default();
state.with_stdlib();
- assert_eq!(
- state
- .parse_evaluate_raw(r#"std.assertEqual(std.base64("test"), "dGVzdA==")"#)
- .unwrap(),
- Val::Bool(true)
+ assert!(
+ primitive_equals(
+ &state.parse_evaluate_raw(r#"std.assertEqual(std.base64("test"), "dGVzdA==")"#).unwrap(),
+ &Val::Bool(true),
+ ).unwrap()
);
}
@@ -445,14 +445,14 @@
/// Asserts given code returns `true`
macro_rules! assert_eval {
($str: expr) => {
- assert_eq!(eval!($str), Val::Bool(true))
+ assert!(primitive_equals(&eval!($str), &Val::Bool(true)).unwrap())
};
}
/// Asserts given code returns `false`
macro_rules! assert_eval_neg {
($str: expr) => {
- assert_eq!(eval!($str), Val::Bool(false))
+ assert!(primitive_equals(&eval!($str), &Val::Bool(false)).unwrap())
};
}
macro_rules! assert_json {
@@ -663,9 +663,11 @@
#[test]
fn string_is_string() {
- assert_eq!(
- eval!("local arr = 'hello'; (!std.isArray(arr)) && (!std.isString(arr))"),
- Val::Bool(false)
+ assert!(
+ primitive_equals(
+ &eval!("local arr = 'hello'; (!std.isArray(arr)) && (!std.isString(arr))"),
+ &Val::Bool(false),
+ ).unwrap()
);
}
@@ -767,4 +769,10 @@
)
})
}
+
+ #[test]
+ fn equality(){
+ println!("{:?}", jrsonnet_parser::parse("{ x: 1, y: 2 } == { x: 1, y: 2 }", &ParserSettings::default()));
+ assert_eval!("{ x: 1, y: 2 } == { x: 1, y: 2 }")
+ }
}
crates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth111 }111 }112}112}113113114#[derive(Debug, PartialEq, Clone)]114#[derive(Debug, Clone)]115pub enum Val {115pub enum Val {116 Bool(bool),116 Bool(bool),117 Null,117 Null,212 }212 }213}213}214215fn is_function_like(val: &Val) -> bool {216 matches!(val, Val::Func(_) | Val::Intristic(_, _))217}218219/// Implements std.primitiveEquals builtin220pub fn primitive_equals(val_a: &Val, val_b: &Val) -> Result<bool> {221 Ok(match (val_a.unwrap_if_lazy()?, val_b.unwrap_if_lazy()?) {222 (Val::Bool(a), Val::Bool(b)) => a == b,223 (Val::Null, Val::Null) => true,224 (Val::Str(a), Val::Str(b)) => a == b,225 (Val::Num(a), Val::Num(b)) => (a - b).abs() <= f64::EPSILON,226 (Val::Arr(_), Val::Arr(_)) => create_error_result(Error::RuntimeError(227 "primitiveEquals operates on primitive types, got array".into(),228 ))?,229 (Val::Obj(_), Val::Obj(_)) => create_error_result(Error::RuntimeError(230 "primitiveEquals operates on primitive types, got object".into(),231 ))?,232 (a, b) if is_function_like(&a) && is_function_like(&b) => create_error_result(233 Error::RuntimeError("cannot test equality of functions".into()),234 )?,235 (_, _) => false,236 })237}238239/// Native implementation of std.equals240pub fn equals(val_a: &Val, val_b: &Val) -> Result<bool> {241 let val_a = val_a.unwrap_if_lazy()?;242 let val_b = val_b.unwrap_if_lazy()?;243244 if val_a.value_type()? != val_b.value_type()? {245 return Ok(false);246 }247 match (val_a, val_b) {248 // Cant test for ptr equality, because all fields needs to be evaluated249 (Val::Arr(a), Val::Arr(b)) => {250 if a.len() != b.len() {251 return Ok(false);252 }253 for (a, b) in a.iter().zip(b.iter()) {254 if !equals(&a.unwrap_if_lazy()?, &b.unwrap_if_lazy()?)? {255 return Ok(false);256 }257 }258 Ok(true)259 }260 (Val::Obj(a), Val::Obj(b)) => {261 let fields = a.visible_fields();262 if fields != b.visible_fields() {263 return Ok(false);264 }265 for field in fields {266 if !equals(&a.get(field.clone())?.unwrap(), &b.get(field)?.unwrap())? {267 return Ok(false);268 }269 }270 Ok(true)271 }272 (a, b) => Ok(primitive_equals(&a, &b)?),273 }274}214275215pub fn manifest_json_ex(val: &Val, padding: &str) -> Result<String> {276pub fn manifest_json_ex(val: &Val, padding: &str) -> Result<String> {216 let mut out = String::new();277 let mut out = String::new();