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
5 env,
6 fs::File,
7 io::Write,
8 path::{Path, PathBuf},
9};
510
6fn main() {11fn main() {
7 let parsed = parse(12 let parsed = parse(
8 STDLIB_STR,13 STDLIB_STR,
9 &ParserSettings {14 &ParserSettings {
10 file_name: "std.jsonnet".to_owned(),15 file_name: PathBuf::from("std.jsonnet"),
11 loc_data: true,16 loc_data: true,
12 },17 },
13 )18 )
modifiedcrates/jsonnet-evaluator/src/error.rsdiffbeforeafterboth
8 NoSuchField(String),8 NoSuchField(String),
99
10 RuntimeError(String),10 RuntimeError(String),
11 StackOverflow,
11}12}
1213
13#[derive(Clone, Debug)]14#[derive(Clone, Debug)]
modifiedcrates/jsonnet-evaluator/src/evaluate.rsdiffbeforeafterboth
32 b.name.clone(),32 b.name.clone(),
33 lazy_binding!(move |this, super_obj| {33 lazy_binding!(move |this, super_obj| {
34 Ok(lazy_val!(34 Ok(lazy_val!(closure!(clone context_creator, clone b, ||
35 push(b.value.clone(), "thunk".to_owned(), ||{
35 closure!(clone context_creator, clone b, || evaluate(36 evaluate(
36 context_creator.0(this.clone(), super_obj.clone())?,37 context_creator.0(this.clone(), super_obj.clone())?,
37 &b.value38 &b.value
38 ))39 )
40 })
39 ))41 )))
40 }),42 }),
41 )43 )
326 Num(v) => Val::Num(*v),328 Num(v) => Val::Num(*v),
327 BinaryOp(v1, o, v2) => evaluate_binary_op_special(context, &v1, *o, &v2)?,329 BinaryOp(v1, o, v2) => evaluate_binary_op_special(context, &v1, *o, &v2)?,
328 UnaryOp(o, v) => evaluate_unary_op(*o, &evaluate(context, v)?)?,330 UnaryOp(o, v) => evaluate_unary_op(*o, &evaluate(context, v)?)?,
329 Var(name) => Val::Lazy(context.binding(&name)).unwrap_if_lazy()?,331 Var(name) => push(locexpr, "var".to_owned(), || {
332 Val::Lazy(context.binding(&name)).unwrap_if_lazy()
333 })?,
330 Index(LocExpr(v, _), index) if matches!(&**v, Expr::Literal(LiteralType::Super)) => {334 Index(LocExpr(v, _), index) if matches!(&**v, Expr::Literal(LiteralType::Super)) => {
331 let name = evaluate(context.clone(), index)?.try_cast_str("object index")?;335 let name = evaluate(context.clone(), index)?.try_cast_str("object index")?;
332 context336 context
412 match evaluate(context, expr)? {416 match evaluate(context, expr)? {
413 Val::Str(n) => Val::Num(n.chars().count() as f64),417 Val::Str(n) => Val::Num(n.chars().count() as f64),
414 Val::Arr(i) => Val::Num(i.len() as f64),418 Val::Arr(i) => Val::Num(i.len() as f64),
419 Val::Obj(o) => Val::Num(o.fields().len() as f64),
415 v => panic!("can't get length of {:?}", v),420 v => panic!("can't get length of {:?}", v),
416 }421 }
417 }422 }
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 );