difftreelog
feat(evaluator) stacktrace preparation
in: master
3 files changed
crates/jsonnet-evaluator/src/evaluate.rsdiffbeforeafterboth--- a/crates/jsonnet-evaluator/src/evaluate.rs
+++ b/crates/jsonnet-evaluator/src/evaluate.rs
@@ -67,37 +67,25 @@
pub fn evaluate_unary_op(op: UnaryOpType, b: &Val) -> Val {
match (op, b) {
- (o, Val::Lazy(l)) => evaluate_unary_op(o, &l.0()),
- (UnaryOpType::Not, Val::Literal(LiteralType::True)) => Val::Literal(LiteralType::False),
- (UnaryOpType::Not, Val::Literal(LiteralType::False)) => Val::Literal(LiteralType::True),
+ (o, Val::Lazy(l)) => evaluate_unary_op(o, &l.evaluate()),
+ (UnaryOpType::Not, Val::Bool(v)) => Val::Bool(!v),
(op, o) => panic!("unary op not implemented: {:?} {:?}", op, o),
}
}
pub fn evaluate_binary_op(a: &Val, op: BinaryOpType, b: &Val) -> Val {
match (a, op, b) {
- (Val::Lazy(a), o, b) => evaluate_binary_op(&a.0(), o, b),
- (a, o, Val::Lazy(b)) => evaluate_binary_op(a, o, &b.0()),
+ (Val::Lazy(a), o, b) => evaluate_binary_op(&a.evaluate(), o, b),
+ (a, o, Val::Lazy(b)) => evaluate_binary_op(a, o, &b.evaluate()),
(Val::Str(v1), BinaryOpType::Add, Val::Str(v2)) => Val::Str(v1.to_owned() + &v2),
- (Val::Str(v1), BinaryOpType::Eq, Val::Str(v2)) => bool_val(v1 == v2),
(Val::Str(v1), BinaryOpType::Ne, Val::Str(v2)) => bool_val(v1 != v2),
(Val::Str(v1), BinaryOpType::Add, Val::Num(v2)) => Val::Str(format!("{}{}", v1, v2)),
(Val::Str(v1), BinaryOpType::Mul, Val::Num(v2)) => Val::Str(v1.repeat(*v2 as usize)),
- (Val::Literal(LiteralType::False), BinaryOpType::And, Val::Literal(LiteralType::False)) => {
- bool_val(false)
- }
- (Val::Literal(LiteralType::False), BinaryOpType::And, Val::Literal(LiteralType::True)) => {
- bool_val(false)
- }
- (Val::Literal(LiteralType::True), BinaryOpType::And, Val::Literal(LiteralType::False)) => {
- bool_val(false)
- }
- (Val::Literal(LiteralType::True), BinaryOpType::And, Val::Literal(LiteralType::True)) => {
- bool_val(true)
- }
+ (Val::Bool(a), BinaryOpType::And, Val::Bool(b)) => Val::Bool(*a && *b),
+ (Val::Bool(a), BinaryOpType::Or, Val::Bool(b)) => Val::Bool(*a || *b),
(Val::Obj(v1), BinaryOpType::Add, Val::Obj(v2)) => Val::Obj(v2.with_super(v1.clone())),
@@ -134,6 +122,8 @@
(Val::Num(v1), BinaryOpType::BitXor, Val::Num(v2)) => {
Val::Num(((*v1 as i32) ^ (*v2 as i32)) as f64)
}
+ (a, BinaryOpType::Eq, b) => bool_val(a == b),
+ (a, BinaryOpType::Ne, b) => bool_val(a != b),
_ => panic!("no rules for binary operation: {:?} {:?} {:?}", a, op, b),
}
}
@@ -238,7 +228,7 @@
pub fn evaluate(context: Context, expr: &LocExpr) -> Val {
use Expr::*;
- let LocExpr(expr, _location) = expr;
+ let LocExpr(expr, loc) = expr;
match &**expr {
Literal(LiteralType::This) => Val::Obj(
context
@@ -252,7 +242,9 @@
.clone()
.unwrap_or_else(|| panic!("super not found")),
),
- Literal(t) => Val::Literal(t.clone()),
+ Literal(LiteralType::True) => Val::Bool(true),
+ Literal(LiteralType::False) => Val::Bool(false),
+ Literal(LiteralType::Null) => Val::Null,
Parened(e) => evaluate(context, e),
Str(v) => Val::Str(v.clone()),
Num(v) => Val::Num(*v),
@@ -383,13 +375,16 @@
cond_then,
cond_else,
} => match evaluate(context.clone(), &cond.0).unwrap_if_lazy() {
- Val::Literal(LiteralType::True) => evaluate(context, cond_then),
- Val::Literal(LiteralType::False) => match cond_else {
+ Val::Bool(true) => evaluate(context, cond_then),
+ Val::Bool(false) => match cond_else {
Some(v) => evaluate(context, v),
- None => Val::Literal(LiteralType::False),
+ None => Val::Bool(false),
},
v => panic!("if condition evaluated to {:?} (boolean needed instead)", v),
},
- _ => panic!("evaluation not implemented: {:?}", expr),
+ _ => panic!(
+ "evaluation not implemented: {:?}",
+ LocExpr(expr.clone(), loc.clone())
+ ),
}
}
crates/jsonnet-evaluator/src/lib.rsdiffbeforeafterboth13pub use evaluate::*;13pub use evaluate::*;14use jsonnet_parser::*;14use jsonnet_parser::*;15pub use obj::*;15pub use obj::*;16use std::{cell::RefCell, collections::HashMap, rc::Rc};16pub use val::*;17pub use val::*;171818rc_fn_helper!(19rc_fn_helper!(32 dyn Fn(Context, LocExpr) -> Val33 dyn Fn(Context, LocExpr) -> Val33);34);3536pub struct ExitGuard<'s>(&'s EvaluationState);37impl<'s> Drop for ExitGuard<'s> {38 fn drop(&mut self) {39 self.0.stack.borrow_mut().pop();40 }41}4243pub struct EvaluationState {44 pub stack: Rc<RefCell<Vec<LocExpr>>>,45 pub files: Rc<RefCell<HashMap<String, String>>>,46}47impl EvaluationState {48 #[must_use = "should keep exit guard before exit from function"]49 pub fn push(&self, e: LocExpr) -> ExitGuard {50 self.stack.borrow_mut().push(e);51 ExitGuard(self)52 }53 pub fn print_stack_trace(&self) {54 for e in self55 .stack56 .borrow()57 .iter()58 .rev()59 .map(|e| e.1.clone())60 .flatten()61 {62 println!("{:?}", e)63 }64 }65}66impl Default for EvaluationState {67 fn default() -> Self {68 EvaluationState {69 stack: Rc::new(RefCell::new(Vec::new())),70 files: Rc::new(RefCell::new(HashMap::new())),71 }72 }73}347435#[cfg(test)]75#[cfg(test)]36pub mod tests {76pub mod tests {37 use super::{evaluate, Context, Val};77 use super::{evaluate, Context, Val};78 use crate::EvaluationState;38 use jsonnet_parser::*;79 use jsonnet_parser::*;8081 #[test]82 fn eval_state_stacktrace() {83 let state = EvaluationState::default();84 let _v = state.push(loc_expr!(85 Expr::Num(0.0),86 true,87 ("test.jsonnet".to_owned(), 10, 20)88 ));8990 state.print_stack_trace()91 }399240 macro_rules! eval {93 macro_rules! eval {41 ($str: expr) => {94 ($str: expr) => {42 evaluate(Context::new(), &parse($str, &ParserSettings {95 evaluate(96 Context::new(),97 &parse(98 $str,99 &ParserSettings {43 loc_data: false,100 loc_data: true,44 file_name: "test.jsonnet".to_owned(),101 file_name: "test.jsonnet".to_owned(),45 }).unwrap())102 },103 )114 &parse(115 &(std + $str),116 &ParserSettings {53 loc_data: false,117 loc_data: true,54 file_name: "test.jsonnet".to_owned(),118 file_name: "test.jsonnet".to_owned(),55 }).unwrap())119 },120 )131 &parse(132 $str,133 &ParserSettings {63 loc_data: false,134 loc_data: true,64 file_name: "test.jsonnet".to_owned(),135 file_name: "test.jsonnet".to_owned(),65 }).unwrap()),136 }137 )138 .unwrap()139 ),66 Val::Literal(LiteralType::True)140 Val::Bool(true)67 )141 )68 };142 };69 }143 }70 macro_rules! assert_json {144 macro_rules! assert_json {71 ($str: expr, $out: expr) => {145 ($str: expr, $out: expr) => {72 assert_eq!(146 assert_eq!(73 format!("{}", evaluate(Context::new(), &parse($str, &ParserSettings {147 format!(148 "{}",149 evaluate(150 Context::new(),151 &parse(152 $str,153 &ParserSettings {74 loc_data: false,154 loc_data: true,75 file_name: "test.jsonnet".to_owned(),155 file_name: "test.jsonnet".to_owned(),76 }).unwrap())),156 }157 )175 &parse(176 $str,177 &ParserSettings {90 loc_data: false,178 loc_data: true,91 file_name: "test.jsonnet".to_owned(),179 file_name: "test.jsonnet".to_owned(),92 }).unwrap()),180 }181 )182 .unwrap()183 ),93 Val::Literal(LiteralType::False)184 Val::Bool(false)94 )185 )95 };186 };96 }187 }241 fn string_is_string() {332 fn string_is_string() {242 assert_eq!(333 assert_eq!(243 eval_stdlib!("local arr = 'hello'; (!std.isArray(arr)) && (!std.isString(arr))"),334 eval_stdlib!("local arr = 'hello'; (!std.isArray(arr)) && (!std.isString(arr))"),244 Val::Literal(LiteralType::False)335 Val::Bool(false)245 );336 );246 }337 }247338258 )349 )259 }350 }351352 #[test]353 fn json() {354 println!("{:?}", eval_stdlib!(r#"std.manifestJson({a:3, b:4, c:6})"#));355 }356357 #[test]358 fn sjsonnet() {359 eval!(360 r#"361 local x0 = {k: 1};362 local x1 = {k: x0.k + x0.k};363 local x2 = {k: x1.k + x1.k};364 local x3 = {k: x2.k + x2.k};365 local x4 = {k: x3.k + x3.k};366 local x5 = {k: x4.k + x4.k};367 local x6 = {k: x5.k + x5.k};368 local x7 = {k: x6.k + x6.k};369 local x8 = {k: x7.k + x7.k};370 local x9 = {k: x8.k + x8.k};371 local x10 = {k: x9.k + x9.k};372 local x11 = {k: x10.k + x10.k};373 local x12 = {k: x11.k + x11.k};374 local x13 = {k: x12.k + x12.k};375 local x14 = {k: x13.k + x13.k};376 local x15 = {k: x14.k + x14.k};377 local x16 = {k: x15.k + x15.k};378 local x17 = {k: x16.k + x16.k};379 local x18 = {k: x17.k + x17.k};380 local x19 = {k: x18.k + x18.k};381 local x20 = {k: x19.k + x19.k};382 local x21 = {k: x20.k + x20.k};383 x21.k384 "#385 );386 }260}387}261388crates/jsonnet-parser/src/expr.rsdiffbeforeafterboth--- a/crates/jsonnet-parser/src/expr.rs
+++ b/crates/jsonnet-parser/src/expr.rs
@@ -1,7 +1,4 @@
-use std::{
- fmt::{Debug, Display},
- rc::Rc,
-};
+use std::{fmt::Debug, rc::Rc};
#[derive(Debug, Clone, PartialEq)]
pub enum FieldName {
@@ -135,18 +132,6 @@
True,
False,
}
-impl Display for LiteralType {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- use LiteralType::*;
- match self {
- This => write!(f, "this"),
- Null => write!(f, "null"),
- True => write!(f, "true"),
- False => write!(f, "false"),
- _ => panic!("non printable item"),
- }
- }
-}
#[derive(Debug, Clone, PartialEq)]
pub struct SliceDesc {
@@ -241,7 +226,7 @@
pub struct ExprLocation(pub String, pub usize, pub usize);
impl Debug for ExprLocation {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- write!(f, "{}:{:?}", self.0, self.1)
+ write!(f, "{}:{:?}-{:?}", self.0, self.1, self.2)
}
}
@@ -259,13 +244,13 @@
macro_rules! loc_expr {
($expr:expr, $need_loc:expr, ($name:expr, $start:expr, $end:expr)) => {
LocExpr(
- Rc::new($expr),
+ std::rc::Rc::new($expr),
if $need_loc {
- Some(Rc::new(ExprLocation($name.to_owned(), $start, $end)))
+ Some(std::rc::Rc::new(ExprLocation($name.to_owned(), $start, $end)))
} else {
None
- },
- )
+ },
+ )
};
}