difftreelog
fix(evaluator) missing intrinsics for slice, mod
in: master
Fixes #30
3 files changed
crates/jrsonnet-evaluator/build.rsdiffbeforeafterboth1use 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};13use structdump::CodegenResult;1415fn main() {16 let parsed = parse(17 STDLIB_STR,18 &ParserSettings {19 file_name: Rc::new(PathBuf::from("std.jsonnet")),20 loc_data: true,21 },22 )23 .expect("parse");2425 let parsed = if cfg!(feature = "faster") {26 let LocExpr(expr, location) = parsed;27 LocExpr(28 Rc::new(match Rc::try_unwrap(expr).unwrap() {29 Expr::Obj(ObjBody::MemberList(members)) => Expr::Obj(ObjBody::MemberList(30 members31 .into_iter()32 .filter(|p| {33 !matches!(34 p,35 Member::Field(FieldMember {36 name: FieldName::Fixed(name),37 ..38 })39 if **name == *"join" || **name == *"manifestJsonEx" ||40 **name == *"escapeStringJson" || **name == *"equals" ||41 **name == *"base64" || **name == *"foldl" || **name == *"foldr" ||42 **name == *"sortImpl" || **name == *"format" || **name == *"range" ||43 **name == *"reverse" || **name == *"slice" || **name == *"mod"44 )45 })46 .collect(),47 )),48 _ => panic!("std value should be object"),49 }),50 location,51 )52 } else {53 parsed54 };55 {56 let mut codegen = CodegenResult::default();57 let code = codegen.codegen(&parsed);5859 let out_dir = env::var("OUT_DIR").unwrap();60 let dest_path = Path::new(&out_dir).join("stdlib.rs");61 let mut f = File::create(&dest_path).unwrap();62 f.write_all(&code.as_bytes()).unwrap();63 }64 {65 let out_dir = env::var("OUT_DIR").unwrap();66 let dest_path = Path::new(&out_dir).join("stdlib.bincode");67 let mut f = File::create(&dest_path).unwrap();68 f.write_all(&serialize(&parsed).unwrap()).unwrap();69 }70}crates/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, [
crates/jrsonnet-parser/src/expr.rsdiffbeforeafterboth--- a/crates/jrsonnet-parser/src/expr.rs
+++ b/crates/jrsonnet-parser/src/expr.rs
@@ -97,6 +97,8 @@
Mul,
Div,
+ Mod,
+
Add,
Sub,
@@ -124,6 +126,7 @@
match self {
Mul => "*",
Div => "/",
+ Mod => "%",
Add => "+",
Sub => "-",
Lhs => "<<",