difftreelog
feat(evaluator) create evaluator crate BREAKING CHANGE: rename Expr internals to not match Expr variants
in: master
6 files changed
Cargo.lockdiffbeforeafterboth--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1,6 +1,13 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
+name = "jsonnet-evaluator"
+version = "0.1.0"
+dependencies = [
+ "jsonnet-parser",
+]
+
+[[package]]
name = "jsonnet-parser"
version = "0.1.0"
dependencies = [
Cargo.tomldiffbeforeafterboth--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,2 +1,5 @@
[workspace]
-members = ["crates/jsonnet-parser"]
+members = [
+ "crates/jsonnet-parser",
+ "crates/jsonnet-evaluator",
+]
crates/jsonnet-evaluator/Cargo.tomldiffbeforeafterboth--- /dev/null
+++ b/crates/jsonnet-evaluator/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+name = "jsonnet-evaluator"
+version = "0.1.0"
+authors = ["Лач <iam@lach.pw>"]
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+jsonnet-parser = { path = "../jsonnet-parser" }
crates/jsonnet-evaluator/src/lib.rsdiffbeforeafterboth--- /dev/null
+++ b/crates/jsonnet-evaluator/src/lib.rs
@@ -0,0 +1,59 @@
+#![feature(box_syntax, box_patterns)]
+
+use jsonnet_parser::*;
+
+#[derive(Debug, Clone, PartialEq)]
+pub enum Val {
+ Str(String),
+ Num(f64),
+}
+
+pub fn evaluate(expr: &Expr) -> Val {
+ use Expr::*;
+ match expr {
+ Parened(e) => evaluate(e),
+ Str(v) => Val::Str(v.clone()),
+ Num(v) => Val::Num(*v),
+ BinaryOp(v1, o, v2) => match (evaluate(v1), o, evaluate(v2)) {
+ (Val::Str(v1), BinaryOpType::Add, Val::Str(v2)) => Val::Str(v1 + &v2),
+ (Val::Str(v1), BinaryOpType::Mul, Val::Num(v2)) => {
+ Val::Str(v1.repeat(v2 as usize))
+ },
+ (Val::Num(v1), BinaryOpType::Add, Val::Num(v2)) => Val::Num(v1 + v2),
+ (Val::Num(v1), BinaryOpType::Mul, Val::Num(v2)) => Val::Num(v1 * v2),
+ _ => panic!("Can't evaluate binary op: {:?} {:?} {:?}", v1, o, v2),
+ },
+ _ => panic!("Can't evaluate: {:?}", expr),
+ }
+}
+
+#[cfg(test)]
+pub mod tests {
+ use super::{evaluate, Val};
+ use jsonnet_parser::parse;
+ #[test]
+ fn math_evaluation() {
+ assert_eq!(evaluate(&parse("2+2*2").unwrap()), Val::Num(6.0));
+ }
+
+ #[test]
+ fn math_evaluation_with_parened() {
+ assert_eq!(evaluate(&parse("3+(2+2*2)").unwrap()), Val::Num(9.0));
+ }
+
+ #[test]
+ fn string_concat() {
+ assert_eq!(
+ evaluate(&parse("\"Hello\"+\"World\"").unwrap()),
+ Val::Str("HelloWorld".to_owned()),
+ );
+ }
+
+ #[test]
+ fn string_repeat() {
+ assert_eq!(
+ evaluate(&parse("\"Hello\"*3").unwrap()),
+ Val::Str("HelloHelloHello".to_owned()),
+ );
+ }
+}
crates/jsonnet-parser/src/expr.rsdiffbeforeafterboth--- a/crates/jsonnet-parser/src/expr.rs
+++ b/crates/jsonnet-parser/src/expr.rs
@@ -43,7 +43,7 @@
}
#[derive(Debug, Clone, PartialEq)]
-pub enum UnaryOp {
+pub enum UnaryOpType {
Plus,
Minus,
BitNot,
@@ -51,7 +51,7 @@
}
#[derive(Debug, Clone, PartialEq)]
-pub enum BinaryOp {
+pub enum BinaryOpType {
Mul,
Div,
Mod,
@@ -129,10 +129,14 @@
}
#[derive(Debug, Clone, PartialEq)]
-pub enum Literal {
+pub enum ValueType {
Null,
True,
False,
+}
+
+#[derive(Debug, Clone, PartialEq)]
+pub enum LiteralType {
This,
Super,
Dollar,
@@ -141,8 +145,9 @@
/// Syntax base
#[derive(Debug, Clone, PartialEq)]
pub enum Expr {
+ Value(ValueType),
/// Plain value: null/true/false
- Literal(Literal),
+ Literal(LiteralType),
/// String value: "hello"
Str(String),
@@ -177,8 +182,8 @@
Params(Params),
Args(Args),
- UnaryOp(UnaryOp, Box<Expr>),
- BinaryOp(Box<Expr>, BinaryOp, Box<Expr>),
+ UnaryOp(UnaryOpType, Box<Expr>),
+ BinaryOp(Box<Expr>, BinaryOpType, Box<Expr>),
AssertExpr(AssertStmt, Box<Expr>),
LocalExpr(Vec<Bind>, Box<Expr>),
crates/jsonnet-parser/src/lib.rsdiffbeforeafterboth1use peg::parser;1use peg::parser;223pub mod expr;3mod expr;4use expr::{Expr, Literal};4pub use expr::*;556enum Suffix {6enum Suffix {7 String(String),7 String(String),101 cond_else,101 cond_else,102 }}102 }}103 pub rule expr_basic() -> Expr103 pub rule expr_basic() -> Expr104 = "null" {Expr::Literal(Literal::Null)}104 = "null" {Expr::Value(ValueType::Null)}105 / "true" {Expr::Literal(Literal::True)} / "false" {Expr::Literal(Literal::False)}105 / "true" {Expr::Value(ValueType::True)} / "false" {Expr::Value(ValueType::False)}106106 / "self" {Expr::Literal(Literal::This)} / "$" {Expr::Literal(Literal::Dollar)}107 / "self" {Expr::Literal(LiteralType::This)} / "$" {Expr::Literal(LiteralType::Dollar)}107 / "super" {Expr::Literal(Literal::Super)}108 / "super" {Expr::Literal(LiteralType::Super)}108109109 / string_expr() / number_expr()110 / string_expr() / number_expr()110 / array_expr()111 / array_expr()124125125 rule expr() -> Expr126 rule expr() -> Expr126 = a:precedence! {127 = a:precedence! {127 a:(@) __() "||" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOp::Or, Box::new(b))}128 a:(@) __() "||" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOpType::Or, Box::new(b))}128 --129 --129 a:(@) __() "&&" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOp::And, Box::new(b))}130 a:(@) __() "&&" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOpType::And, Box::new(b))}130 --131 --131 a:(@) __() "|" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOp::BitOr, Box::new(b))}132 a:(@) __() "|" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOpType::BitOr, Box::new(b))}132 --133 --133 a:@ __() "^" __() b:(@) {Expr::BinaryOp(Box::new(a), expr::BinaryOp::BitXor, Box::new(b))}134 a:@ __() "^" __() b:(@) {Expr::BinaryOp(Box::new(a), expr::BinaryOpType::BitXor, Box::new(b))}134 --135 --135 a:(@) __() "&" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOp::BitAnd, Box::new(b))}136 a:(@) __() "&" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOpType::BitAnd, Box::new(b))}136 --137 --137 a:(@) __() "==" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOp::Eq, Box::new(b))}138 a:(@) __() "==" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOpType::Eq, Box::new(b))}138 a:(@) __() "!=" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOp::Ne, Box::new(b))}139 a:(@) __() "!=" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOpType::Ne, Box::new(b))}139 --140 --140 a:(@) __() "<" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOp::Lt, Box::new(b))}141 a:(@) __() "<" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOpType::Lt, Box::new(b))}141 a:(@) __() ">" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOp::Gt, Box::new(b))}142 a:(@) __() ">" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOpType::Gt, Box::new(b))}142 a:(@) __() "<=" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOp::Lte, Box::new(b))}143 a:(@) __() "<=" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOpType::Lte, Box::new(b))}143 a:(@) __() ">=" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOp::Gte, Box::new(b))}144 a:(@) __() ">=" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOpType::Gte, Box::new(b))}144 --145 --145 a:(@) __() "<<" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOp::Lhs, Box::new(b))}146 a:(@) __() "<<" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOpType::Lhs, Box::new(b))}146 a:(@) __() ">>" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOp::Rhs, Box::new(b))}147 a:(@) __() ">>" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOpType::Rhs, Box::new(b))}147 --148 --148 a:(@) __() "+" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOp::Add, Box::new(b))}149 a:(@) __() "+" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOpType::Add, Box::new(b))}149 a:(@) __() "-" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOp::Sub, Box::new(b))}150 a:(@) __() "-" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOpType::Sub, Box::new(b))}150 --151 --151 a:(@) __() "*" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOp::Mul, Box::new(b))}152 a:(@) __() "*" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOpType::Mul, Box::new(b))}152 a:(@) __() "/" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOp::Div, Box::new(b))}153 a:(@) __() "/" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOpType::Div, Box::new(b))}153 a:(@) __() "%" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOp::Mod, Box::new(b))}154 a:(@) __() "%" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOpType::Mod, Box::new(b))}154 --155 --155 e:expr_basic() {e}156 e:expr_basic() {e}156 "(" __() e:expr_basic() __() ")" {Expr::Parened(Box::new(e))}157 "(" __() e:boxed_expr() __() ")" {Expr::Parened(e)}157 } suffixes:(__() suffix:expr_suffix() {suffix})* {158 } suffixes:(__() suffix:expr_suffix() {suffix})* {158 let mut cur = a;159 let mut cur = a;159 for suffix in suffixes {160 for suffix in suffixes {196 parse("2+2*2").unwrap(),197 parse("2+2*2").unwrap(),197 Expr::BinaryOp(198 Expr::BinaryOp(198 Box::new(Expr::Num(2.0)),199 Box::new(Expr::Num(2.0)),199 BinaryOp::Add,200 BinaryOpType::Add,200 Box::new(Expr::BinaryOp(201 Box::new(Expr::BinaryOp(201 Box::new(Expr::Num(2.0)),202 Box::new(Expr::Num(2.0)),202 BinaryOp::Mul,203 BinaryOpType::Mul,203 Box::new(Expr::Num(2.0))204 Box::new(Expr::Num(2.0))204 ))205 ))205 )206 )