git.delta.rocks / jrsonnet / refs/commits / e614efaa7567

difftreelog

refactor(evaluator) use PathBuf for file paths

Лач2020-06-06parent: #30ce98e.patch.diff
in: master

4 files changed

modifiedcrates/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,
 		},
 	)
modifiedcrates/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)]
modifiedcrates/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),
 						}
 					}
modifiedcrates/jsonnet-evaluator/src/lib.rsdiffbeforeafterboth
16pub 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::*;
2121
22rc_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 pretty
45 /// printing stacktraces45 /// printing stacktraces
46 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}
4949
56pub(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}
6262
65impl 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>> {
9898
99 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_map
104 .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 }
185184
186 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 result
217 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;
220225
221 #[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 state
230 .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 }
236255
237 #[test]256 #[test]
240 state.add_stdlib();259 state.add_stdlib();
241 assert_eq!(260 assert_eq!(
242 state261 state
243 .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 );