difftreelog
chore(evaluator) partial interpreter implementation
in: master
8 files changed
crates/jsonnet-evaluator/Cargo.tomldiffbeforeafterboth9[dependencies]9[dependencies]10jsonnet-parser = { path = "../jsonnet-parser" }10jsonnet-parser = { path = "../jsonnet-parser" }1112[dev-dependencies]13jsonnet-stdlib = { version = "0.1.0", path = "../jsonnet-stdlib" }1114crates/jsonnet-evaluator/src/binding.rsdiffbeforeafterbothno changes
crates/jsonnet-evaluator/src/ctx.rsdiffbeforeafterbothno changes
crates/jsonnet-evaluator/src/dynamic.rsdiffbeforeafterbothno changes
crates/jsonnet-evaluator/src/evaluate.rsdiffbeforeafterbothno changes
crates/jsonnet-evaluator/src/lib.rsdiffbeforeafterboth1#![feature(box_syntax, box_patterns)]1#![feature(box_syntax, box_patterns)]22#![feature(type_alias_impl_trait)]3use jsonnet_parser::*;45#[derive(Debug, Clone, PartialEq)]3#![feature(debug_non_exhaustive)]6pub enum Val {47 Str(String),5mod binding;8 Num(f64),6mod ctx;9}7mod dynamic;1011pub fn evaluate(expr: &Expr) -> Val {8mod evaluate;9mod obj;10mod val;1112pub use binding::*;12 use Expr::*;13pub use ctx::*;13 match expr {14pub use dynamic::*;14 Parened(e) => evaluate(e),15pub use evaluate::*;15 Str(v) => Val::Str(v.clone()),16use jsonnet_parser::*;16 Num(v) => Val::Num(*v),17pub use obj::*;17 BinaryOp(v1, o, v2) => match (evaluate(v1), o, evaluate(v2)) {18use std::fmt::Debug;19use std::rc::Rc;18 (Val::Str(v1), BinaryOpType::Add, Val::Str(v2)) => Val::Str(v1 + &v2),20pub use val::*;2122pub trait FunctionRhs: Debug {19 (Val::Str(v1), BinaryOpType::Mul, Val::Num(v2)) => {23 fn evaluate(&self, ctx: Context) -> Val;20 Val::Str(v1.repeat(v2 as usize))24}21 },22 (Val::Num(v1), BinaryOpType::Add, Val::Num(v2)) => Val::Num(v1 + v2),25dynamic_wrapper!(FunctionRhs, BoxedFunctionRhs);2627pub trait FunctionDefault: Debug {23 (Val::Num(v1), BinaryOpType::Mul, Val::Num(v2)) => Val::Num(v1 * v2),28 fn default(&self, ctx: Context, expr: Expr) -> Val;24 _ => panic!("Can't evaluate binary op: {:?} {:?} {:?}", v1, o, v2),29}25 },26 _ => panic!("Can't evaluate: {:?}", expr),30dynamic_wrapper!(FunctionDefault, BoxedFunctionDefault);27 }28}293130#[cfg(test)]32#[cfg(test)]31pub mod tests {33pub mod tests {32 use super::{evaluate, Val};34 use super::{evaluate, Context, Val};33 use jsonnet_parser::parse;35 use jsonnet_parser::*;34 #[test]3637 // macro_rules! eval {38 // ($str: expr) => {39 // evaluate(Context::new(), &parse($str).unwrap())40 // };41 // }35 fn math_evaluation() {42 macro_rules! assert_eval {43 ($str: expr) => {36 assert_eq!(evaluate(&parse("2+2*2").unwrap()), Val::Num(6.0));44 assert_eq!(45 evaluate(Context::new(), &parse($str).unwrap()),46 Val::Literal(LiteralType::True)47 )48 };37 }49 }3850 macro_rules! assert_json {39 #[test]51 ($str: expr, $out: expr) => {52 assert_eq!(53 format!("{}", evaluate(Context::new(), &parse($str).unwrap())),54 $out55 )56 };57 }40 fn math_evaluation_with_parened() {58 macro_rules! assert_eval_neg {59 ($str: expr) => {41 assert_eq!(evaluate(&parse("3+(2+2*2)").unwrap()), Val::Num(9.0));60 assert_eq!(61 evaluate(Context::new(), &parse($str).unwrap()),62 Val::Literal(LiteralType::False)63 )64 };42 }65 }6667 /// Sanity checking, before trusting to another tests68 #[test]69 fn equality_operator() {70 assert_eval!("2 == 2");71 assert_eval_neg!("2 != 2");72 assert_eval!("2 != 3");73 assert_eval_neg!("2 == 3");74 assert_eval!("'Hello' == 'Hello'");75 assert_eval_neg!("'Hello' != 'Hello'");76 assert_eval!("'Hello' != 'World'");77 assert_eval_neg!("'Hello' == 'World'");78 }437944 #[test]80 #[test]45 fn string_concat() {81 fn math_evaluation() {46 assert_eq!(82 assert_eval!("2 + 2 * 2 == 6");83 assert_eval!("3 + (2 + 2 * 2) == 9");84 }8586 #[test]87 fn string_concat() {88 assert_eval!("'Hello' + 'World' == 'HelloWorld'");89 assert_eval!("'Hello' * 3 == 'HelloHelloHello'");90 assert_eval!("'Hello' + 'World' * 3 == 'HelloWorldWorldWorld'");91 }9293 #[test]94 fn local() {95 assert_eval!("local a = 2; local b = 3; a + b == 5");96 assert_eval!("local a = 1, b = a + 1; a + b == 3");97 assert_eval!("local a = 1; local a = 2; a == 2");98 }99100 #[test]101 fn object_lazyness() {102 assert_json!("local a = {a:error 'test'}; {}", r#"{}"#);103 }104105 #[test]106 fn object_inheritance() {107 assert_json!("{a:self.b} + {b:3}", r#"{"a":3,"b":3}"#);108 }109110 #[test]111 fn test_object() {112 assert_json!("{a:2}", r#"{"a":2}"#);113 assert_json!("{a:2+2}", r#"{"a":4}"#);114 assert_json!("{a:2}+{b:2}", r#"{"a":2,"b":2}"#);115 assert_json!("{b:3}+{b:2}", r#"{"b":2}"#);116 assert_json!("{b:3}+{b+:2}", r#"{"b":5}"#);117 assert_json!("local test='a'; {[test]:2}", r#"{"a":2}"#);118 assert_json!(119 r#"120 {121 name: "Alice",122 welcome: "Hello " + self.name + "!",123 }124 "#,125 r#"{"name":"Alice","welcome":"Hello Alice!"}"#126 );127 assert_json!(128 r#"129 {130 name: "Alice",131 welcome: "Hello " + self.name + "!",132 } + {133 name: "Bob"134 }135 "#,136 r#"{"name":"Bob","welcome":"Hello Bob!"}"#137 );138 }139140 #[test]141 fn functions() {142 assert_json!(r#"local a = function(b, c = 2) b + c; a(2)"#, "4");143 assert_json!(144 r#"local a = function(b, c = "Dear") b + c + d, d = "World"; a("Hello")"#,145 r#""HelloDearWorld""#146 );147 }148149 #[test]150 fn local_methods() {151 assert_json!(r#"local a(b, c = 2) = b + c; a(2)"#, "4");152 assert_json!(153 r#"local a(b, c = "Dear") = b + c + d, d = "World"; a("Hello")"#,154 r#""HelloDearWorld""#155 );156 }157158 #[test]159 fn object_locals() {160 assert_json!(r#"{local a = 3, b: a}"#, r#"{"b":3}"#);161 assert_json!(r#"{local a = 3, local c = a, b: c}"#, r#"{"b":3}"#);162 assert_json!(163 r#"{local a = function (b) {[b]:4}, test: a("test")}"#,164 r#"{"test":{"test":4}}"#165 );166 }167168 // We can't trust other tests (And official jsonnet testsuite), if assert is not working correctly169 #[test]170 fn std_assert_ok() {171 let std = "local std = ".to_owned() + jsonnet_stdlib::STDLIB_STR + ";";47 evaluate(&parse("\"Hello\"+\"World\"").unwrap()),172 evaluate(48 Val::Str("HelloWorld".to_owned()),173 Context::new(),174 &parse(&(std + "std.assertEqual(4.5 << 2, 16,)")).unwrap(),49 );175 );50 }176 }5117752 #[test]178 #[test]179 #[should_panic]53 fn string_repeat() {180 fn std_assert_failure() {54 assert_eq!(181 let std = "local std = ".to_owned() + jsonnet_stdlib::STDLIB_STR + ";";55 evaluate(&parse("\"Hello\"*3").unwrap()),182 evaluate(56 Val::Str("HelloHelloHello".to_owned()),183 Context::new(),184 &parse(&(std + "std.assertEqual(4.5 << 2, 15,)")).unwrap(),57 );185 );58 }186 }59}187}60188crates/jsonnet-evaluator/src/obj.rsdiffbeforeafterbothno changes
crates/jsonnet-evaluator/src/val.rsdiffbeforeafterbothno changes