difftreelog
refactor(evaluator) use PathBuf for file paths
in: master
4 files changed
crates/jsonnet-evaluator/build.rsdiffbeforeafterboth--- a/crates/jsonnet-evaluator/build.rs
+++ b/crates/jsonnet-evaluator/build.rs
@@ -1,13 +1,18 @@
use bincode::serialize;
use jsonnet_parser::{parse, ParserSettings};
use jsonnet_stdlib::STDLIB_STR;
-use std::{env, fs::File, io::Write, path::Path};
+use std::{
+ env,
+ fs::File,
+ io::Write,
+ path::{Path, PathBuf},
+};
fn main() {
let parsed = parse(
STDLIB_STR,
&ParserSettings {
- file_name: "std.jsonnet".to_owned(),
+ file_name: PathBuf::from("std.jsonnet"),
loc_data: true,
},
)
crates/jsonnet-evaluator/src/error.rsdiffbeforeafterboth--- a/crates/jsonnet-evaluator/src/error.rs
+++ b/crates/jsonnet-evaluator/src/error.rs
@@ -8,6 +8,7 @@
NoSuchField(String),
RuntimeError(String),
+ StackOverflow,
}
#[derive(Clone, Debug)]
crates/jsonnet-evaluator/src/evaluate.rsdiffbeforeafterboth--- a/crates/jsonnet-evaluator/src/evaluate.rs
+++ b/crates/jsonnet-evaluator/src/evaluate.rs
@@ -31,12 +31,14 @@
(
b.name.clone(),
lazy_binding!(move |this, super_obj| {
- Ok(lazy_val!(
- closure!(clone context_creator, clone b, || evaluate(
- context_creator.0(this.clone(), super_obj.clone())?,
- &b.value
- ))
- ))
+ Ok(lazy_val!(closure!(clone context_creator, clone b, ||
+ push(b.value.clone(), "thunk".to_owned(), ||{
+ evaluate(
+ context_creator.0(this.clone(), super_obj.clone())?,
+ &b.value
+ )
+ })
+ )))
}),
)
}
@@ -326,7 +328,9 @@
Num(v) => Val::Num(*v),
BinaryOp(v1, o, v2) => evaluate_binary_op_special(context, &v1, *o, &v2)?,
UnaryOp(o, v) => evaluate_unary_op(*o, &evaluate(context, v)?)?,
- Var(name) => Val::Lazy(context.binding(&name)).unwrap_if_lazy()?,
+ Var(name) => push(locexpr, "var".to_owned(), || {
+ Val::Lazy(context.binding(&name)).unwrap_if_lazy()
+ })?,
Index(LocExpr(v, _), index) if matches!(&**v, Expr::Literal(LiteralType::Super)) => {
let name = evaluate(context.clone(), index)?.try_cast_str("object index")?;
context
@@ -412,6 +416,7 @@
match evaluate(context, expr)? {
Val::Str(n) => Val::Num(n.chars().count() as f64),
Val::Arr(i) => Val::Num(i.len() as f64),
+ Val::Obj(o) => Val::Num(o.fields().len() as f64),
v => panic!("can't get length of {:?}", v),
}
}
crates/jsonnet-evaluator/src/lib.rsdiffbeforeafterboth16pub use evaluate::*;16pub use evaluate::*;17use jsonnet_parser::*;17use jsonnet_parser::*;18pub use obj::*;18pub use obj::*;19use std::{cell::RefCell, collections::HashMap, rc::Rc};19use std::{cell::RefCell, collections::HashMap, path::PathBuf, rc::Rc};20pub use val::*;20pub use val::*;212122rc_fn_helper!(22rc_fn_helper!(43 stack: RefCell<Vec<StackTraceElement>>,43 stack: RefCell<Vec<StackTraceElement>>,44 /// Contains file source codes and evaluated results for imports and pretty44 /// Contains file source codes and evaluated results for imports and pretty45 /// printing stacktraces45 /// printing stacktraces46 files: RefCell<HashMap<String, FileData>>,46 files: RefCell<HashMap<PathBuf, FileData>>,47 globals: RefCell<HashMap<String, Val>>,47 globals: RefCell<HashMap<String, Val>>,48}48}494956pub(crate) fn create_error<T>(err: Error) -> Result<T> {56pub(crate) fn create_error<T>(err: Error) -> Result<T> {57 with_state(|s| s.error(err))57 with_state(|s| s.error(err))58}58}59pub(crate) fn push<T>(e: LocExpr, comment: String, f: impl FnOnce() -> T) -> T {59pub(crate) fn push<T>(e: LocExpr, comment: String, f: impl FnOnce() -> Result<T>) -> Result<T> {60 with_state(|s| s.push(e, comment, f))60 with_state(|s| s.push(e, comment, f))61}61}626265impl EvaluationState {65impl EvaluationState {66 pub fn add_file(66 pub fn add_file(67 &self,67 &self,68 name: String,68 name: PathBuf,69 code: String,69 code: String,70 ) -> std::result::Result<(), Box<dyn std::error::Error>> {70 ) -> std::result::Result<(), Box<dyn std::error::Error>> {71 self.0.files.borrow_mut().insert(71 self.0.files.borrow_mut().insert(87 }87 }88 pub fn add_parsed_file(88 pub fn add_parsed_file(89 &self,89 &self,90 name: String,90 name: PathBuf,91 code: String,91 code: String,92 parsed: LocExpr,92 parsed: LocExpr,93 ) -> std::result::Result<(), Box<dyn std::error::Error>> {93 ) -> std::result::Result<(), Box<dyn std::error::Error>> {989899 Ok(())99 Ok(())100 }100 }101 pub fn get_source(&self, name: &str) -> String {101 pub fn get_source(&self, name: &PathBuf) -> Option<String> {102 let ro_map = self.0.files.borrow();102 let ro_map = self.0.files.borrow();103 let value = ro_map103 ro_map104 .get(name)104 .get(name)105 .unwrap_or_else(|| panic!("file not added: {:?}", name));105 .map(|value|value.0.clone())106 value.0.clone()107 }106 }108 pub fn evaluate_file(&self, name: &str) -> Result<Val> {107 pub fn evaluate_file(&self, name: &PathBuf) -> Result<Val> {109 self.begin_state();108 self.begin_state();110 let expr: LocExpr = {109 let expr: LocExpr = {111 let ro_map = self.0.files.borrow();110 let ro_map = self.0.files.borrow();135 let parsed = parse(134 let parsed = parse(136 &code,135 &code,137 &ParserSettings {136 &ParserSettings {138 file_name: "raw.jsonnet".to_owned(),137 file_name: PathBuf::from("raw.jsonnet"),139 loc_data: true,138 loc_data: true,140 },139 },141 );140 );154 use jsonnet_stdlib::STDLIB_STR;153 use jsonnet_stdlib::STDLIB_STR;155 if cfg!(feature = "serialized-stdlib") {154 if cfg!(feature = "serialized-stdlib") {156 self.add_parsed_file(155 self.add_parsed_file(157 "std.jsonnet".to_owned(),156 PathBuf::from("std.jsonnet"),158 STDLIB_STR.to_owned(),157 STDLIB_STR.to_owned(),159 bincode::deserialize(include_bytes!(concat!(env!("OUT_DIR"), "/stdlib.bincode")))158 bincode::deserialize(include_bytes!(concat!(env!("OUT_DIR"), "/stdlib.bincode")))160 .expect("deserialize stdlib"),159 .expect("deserialize stdlib"),161 )160 )162 .unwrap();161 .unwrap();163 } else {162 } else {164 self.add_file("std.jsonnet".to_owned(), STDLIB_STR.to_owned())163 self.add_file(PathBuf::from("std.jsonnet"), STDLIB_STR.to_owned())165 .unwrap();164 .unwrap();166 }165 }167 let val = self.evaluate_file("std.jsonnet").unwrap();166 let val = self.evaluate_file(&PathBuf::from("std.jsonnet")).unwrap();168 self.add_global("std".to_owned(), val);167 self.add_global("std".to_owned(), val);169 self.end_state();168 self.end_state();170 }169 }183 Context::new().extend(new_bindings, None, None, None)182 Context::new().extend(new_bindings, None, None, None)184 }183 }185184186 pub fn push<T>(&self, e: LocExpr, comment: String, f: impl FnOnce() -> T) -> T {185 pub fn push<T>(&self, e: LocExpr, comment: String, f: impl FnOnce() -> Result<T>) -> Result<T> {186 {187 self.0187 let mut stack = self.0.stack.borrow_mut();188 .stack188 if stack.len() > 5000 {189 .borrow_mut()189 drop(stack);190 return self.error(Error::StackOverflow);191 } else {190 .push(StackTraceElement(e, comment));192 stack.push(StackTraceElement(e, comment));193 }194 }191 let result = f();195 let result = f();192 self.0.stack.borrow_mut().pop();196 self.0.stack.borrow_mut().pop();193 result197 result217 use super::Val;221 use super::Val;218 use crate::EvaluationState;222 use crate::EvaluationState;219 use jsonnet_parser::*;223 use jsonnet_parser::*;224 use std::path::PathBuf;220225221 #[test]226 #[test]222 fn eval_state_stacktrace() {227 fn eval_state_stacktrace() {223 let state = EvaluationState::default();228 let state = EvaluationState::default();224 state.push(229 state230 .push(225 loc_expr!(Expr::Num(0.0), true, ("test1.jsonnet".to_owned(), 10, 20)),231 loc_expr!(232 Expr::Num(0.0),233 true,234 (PathBuf::from("test1.jsonnet"), 10, 20)235 ),226 "outer".to_owned(),236 "outer".to_owned(),227 || {237 || {228 state.push(238 state.push(229 loc_expr!(Expr::Num(0.0), true, ("test2.jsonnet".to_owned(), 30, 40)),239 loc_expr!(240 Expr::Num(0.0),241 true,242 (PathBuf::from("test2.jsonnet"), 30, 40)243 ),230 "inner".to_owned(),244 "inner".to_owned(),231 || state.print_stack_trace(),245 || {246 state.print_stack_trace();247 Ok(())248 },232 );249 )?;250 Ok(())233 },251 },234 );252 )253 .unwrap();235 }254 }236255237 #[test]256 #[test]240 state.add_stdlib();259 state.add_stdlib();241 assert_eq!(260 assert_eq!(242 state261 state243 .parse_evaluate_raw(r#"std.assertEqual(std.base64("test"), "dGVzdA==w")"#)262 .parse_evaluate_raw(r#"std.assertEqual(std.base64("test"), "dGVzdA==")"#)244 .unwrap(),263 .unwrap(),245 Val::Bool(true)264 Val::Bool(true)246 );265 );