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

difftreelog

fix(evaluator) missing intrinsics for slice, mod

Yaroslav Bolyukin2021-01-06parent: #7c1d01a.patch.diff
in: master
Fixes #30

3 files changed

modifiedcrates/jrsonnet-evaluator/build.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/build.rs
+++ b/crates/jrsonnet-evaluator/build.rs
@@ -39,7 +39,8 @@
 								if **name == *"join" || **name == *"manifestJsonEx" ||
 								**name == *"escapeStringJson" || **name == *"equals" ||
 								**name == *"base64" || **name == *"foldl" || **name == *"foldr" ||
-								**name == *"sortImpl" || **name == *"format" || **name == *"range" || **name == *"reverse"
+								**name == *"sortImpl" || **name == *"format" || **name == *"range" ||
+								**name == *"reverse" || **name == *"slice" || **name == *"mod"
 							)
 						})
 						.collect(),
modifiedcrates/jrsonnet-evaluator/src/builtin/mod.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/builtin/mod.rs
+++ b/crates/jrsonnet-evaluator/src/builtin/mod.rs
@@ -16,6 +16,20 @@
 pub mod manifest;
 pub mod sort;
 
+fn std_format(str: Rc<str>, vals: Val) -> Result<Val> {
+	push(
+		&Some(ExprLocation(Rc::from(PathBuf::from("std.jsonnet")), 0, 0)),
+		|| format!("std.format of {}", str),
+		|| {
+			Ok(match vals {
+				Val::Arr(vals) => Val::Str(format_arr(&str, &vals)?.into()),
+				Val::Obj(obj) => Val::Str(format_obj(&str, &obj)?.into()),
+				o => Val::Str(format_arr(&str, &[o])?.into()),
+			})
+		},
+	)
+}
+
 #[allow(clippy::cognitive_complexity)]
 pub fn call_builtin(
 	context: Context,
@@ -99,6 +113,43 @@
 					.any(|(k, _v)| *k == *f),
 			))
 		})?,
+
+		// faster
+		"slice" => parse_args!(context, "slice", args, 4, [
+			0, indexable: [Val::Str | Val::Arr], vec![ValType::Str, ValType::Arr];
+			1, index, vec![ValType::Num, ValType::Null];
+			2, end, vec![ValType::Num, ValType::Null];
+			3, step, vec![ValType::Num, ValType::Null];
+		], {
+			let index = match index {
+				Val::Num(v) => v as usize,
+				Val::Null => 0,
+				_ => unreachable!(),
+			};
+			let end = match end {
+				Val::Num(v) => v as usize,
+				Val::Null => match &indexable {
+					Val::Str(s) => s.chars().count(),
+					Val::Arr(v) => v.len(),
+					_ => unreachable!()
+				},
+				_ => unreachable!()
+			};
+			let step = match step {
+				Val::Num(v) => v as usize,
+				Val::Null => 1,
+				_ => unreachable!()
+			};
+			match &indexable {
+				Val::Str(s) => {
+					Ok(Val::Str((s.chars().skip(index).take(end-index).step_by(step).collect::<String>()).into()))
+				}
+				Val::Arr(arr) => {
+					Ok(Val::Arr((arr.iter().skip(index).take(end-index).step_by(step).cloned().collect::<Vec<Val>>()).into()))
+				}
+				_ => unreachable!()
+			}
+		})?,
 		"primitiveEquals" => parse_args!(context, "std.primitiveEquals", args, 2, [
 			0, a, vec![];
 			1, b, vec![];
@@ -112,6 +163,16 @@
 		], {
 			Ok(Val::Bool(equals(&a, &b)?))
 		})?,
+		"mod" => parse_args!(context, "std.mod", args, 2, [
+			0, a: [Val::Num | Val::Str], vec![ValType::Num, ValType::Str];
+			1, b, vec![];
+		], {
+			match (a, b) {
+				(Val::Num(a), Val::Num(b)) => Ok(Val::Num(a % b)),
+				(Val::Str(str), vals) => std_format(str, vals),
+				(a, b) => throw!(BinaryOperatorDoesNotOperateOnValues(jrsonnet_parser::BinaryOpType::Mod, a.value_type()?, b.value_type()?))
+			}
+		})?,
 		"modulo" => parse_args!(context, "std.modulo", args, 2, [
 			0, a: [Val::Num]!!Val::Num, vec![ValType::Num];
 			1, b: [Val::Num]!!Val::Num, vec![ValType::Num];
@@ -219,13 +280,7 @@
 			0, str: [Val::Str]!!Val::Str, vec![ValType::Str];
 			1, vals, vec![]
 		], {
-			push(&Some(ExprLocation(Rc::from(PathBuf::from("std.jsonnet")), 0, 0)), ||format!("std.format of {}", str), ||{
-				Ok(match vals {
-					Val::Arr(vals) => Val::Str(format_arr(&str, &vals)?.into()),
-					Val::Obj(obj) => Val::Str(format_obj(&str, &obj)?.into()),
-					o => Val::Str(format_arr(&str, &[o])?.into()),
-				})
-			})
+			std_format(str, vals)
 		})?,
 		// faster
 		"range" => parse_args!(context, "std.range", args, 2, [
modifiedcrates/jrsonnet-parser/src/expr.rsdiffbeforeafterboth
97 Mul,97 Mul,
98 Div,98 Div,
99
100 Mod,
99101
100 Add,102 Add,
101 Sub,103 Sub,
124 match self {126 match self {
125 Mul => "*",127 Mul => "*",
126 Div => "/",128 Div => "/",
129 Mod => "%",
127 Add => "+",130 Add => "+",
128 Sub => "-",131 Sub => "-",
129 Lhs => "<<",132 Lhs => "<<",