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

difftreelog

feat(evaluator) eval methods in EvaluationState

Лач2020-06-03parent: #4aecc22.patch.diff
in: master

1 file changed

modifiedcrates/jsonnet-evaluator/src/lib.rsdiffbeforeafterboth
9mod obj;9mod obj;
10mod val;10mod val;
1111
12use closure::closure;
12pub use ctx::*;13pub use ctx::*;
13pub use dynamic::*;14pub use dynamic::*;
14pub use error::*;15pub use error::*;
35 dyn Fn(Context, LocExpr) -> Val36 dyn Fn(Context, LocExpr) -> Val
36);37);
3738
38#[derive(Default, Clone)]39#[derive(Default)]
39pub struct EvaluationState {40pub struct EvaluationStateInternals {
40 /// Used for stack-overflows and stacktraces41 /// Used for stack-overflows and stacktraces
41 pub stack: Rc<RefCell<Vec<(LocExpr, String)>>>,42 stack: RefCell<Vec<(LocExpr, String)>>,
42 /// Contains file source codes and evaluated results for imports and pretty printing stacktraces43 /// Contains file source codes and evaluated results for imports and pretty printing stacktraces
43 pub files: Rc<RefCell<HashMap<String, (String, Option<Val>)>>>,44 files: RefCell<HashMap<String, (String, LocExpr, Option<Val>)>>,
45 globals: RefCell<HashMap<String, Val>>,
44}46}
47
48#[derive(Default, Clone)]
49pub struct EvaluationState(Rc<EvaluationStateInternals>);
45impl EvaluationState {50impl EvaluationState {
51 pub fn add_file(&self, name: String, code: String) -> Result<(), Box<dyn std::error::Error>> {
52 self.0.files.borrow_mut().insert(
53 name.clone(),
54 (
55 code.clone(),
56 parse(
57 &code,
58 &ParserSettings {
59 file_name: name.clone(),
60 loc_data: true,
61 },
62 )?,
63 None,
64 ),
65 );
66
67 Ok(())
68 }
69 pub fn evaluate_file(&self, name: &str) -> Result<Val, Box<dyn std::error::Error>> {
70 let expr: LocExpr = {
71 let ro_map = self.0.files.borrow();
72 let value = ro_map
73 .get(name)
74 .unwrap_or_else(|| panic!("file not added: {:?}", name));
75 if value.2.is_some() {
76 return Ok(value.2.clone().unwrap());
77 }
78 value.1.clone()
79 };
80 let value = evaluate(self.create_default_context(), self.clone(), &expr);
81 {
82 self.0
83 .files
84 .borrow_mut()
85 .get_mut(name)
86 .unwrap()
87 .2
88 .replace(value.clone());
89 }
90 Ok(value)
91 }
92
93 pub fn parse_evaluate_raw(&self, code: &str) -> Val {
94 let parsed = parse(
95 &code,
96 &ParserSettings {
97 file_name: "raw.jsonnet".to_owned(),
98 loc_data: true,
99 },
100 );
101 evaluate(
102 self.create_default_context(),
103 self.clone(),
104 &parsed.unwrap(),
105 )
106 }
107
108 pub fn add_stdlib(&self) {
109 use jsonnet_stdlib::STDLIB_STR;
110 self.add_file("std.jsonnet".to_owned(), STDLIB_STR.to_owned())
111 .unwrap();
112 let val = self.evaluate_file("std.jsonnet").unwrap();
113 self.0.globals.borrow_mut().insert("std".to_owned(), val);
114 }
115
116 pub fn create_default_context(&self) -> Context {
117 let globals = self.0.globals.borrow();
118 let mut new_bindings: HashMap<String, LazyBinding> = HashMap::new();
119 for (name, value) in globals.iter() {
120 new_bindings.insert(
121 name.clone(),
122 lazy_binding!(
123 closure!(clone value, |_self, _super_obj| lazy_val!(closure!(clone value, ||value.clone())))
124 ),
125 );
126 }
127 Context::new().extend(new_bindings, None, None, None)
128 }
129
46 pub fn push<T>(&self, e: LocExpr, comment: String, f: impl FnOnce() -> T) -> T {130 pub fn push<T>(&self, e: LocExpr, comment: String, f: impl FnOnce() -> T) -> T {
47 self.stack.borrow_mut().push((e, comment));131 self.0.stack.borrow_mut().push((e, comment));
48 let result = f();132 let result = f();
49 self.stack.borrow_mut().pop();133 self.0.stack.borrow_mut().pop();
50 result134 result
51 }135 }
52 pub fn print_stack_trace(&self) {136 pub fn print_stack_trace(&self) {
53 for e in self137 for e in self.stack_trace() {
54 .stack
55 .borrow()
56 .iter()
57 .rev()
58 .map(|(loc, comment)| loc.1.clone().map(|v| (v, comment.clone())))
59 .flatten()
60 {
61 println!("{:?} - {:?}", e.0, e.1)138 println!("{:?} - {:?}", e.0, e.1)
62 }139 }
63 }140 }
64 pub fn stack_trace(&self) -> Vec<(LocExpr, String)> {141 pub fn stack_trace(&self) -> Vec<(LocExpr, String)> {
65 self.stack142 self.0
143 .stack
66 .borrow()144 .borrow()
67 .iter()145 .iter()
93 );171 );
94 }172 }
173
174 #[test]
175 fn eval_state_standard() {
176 let state = EvaluationState::default();
177 state.add_stdlib();
178 assert_eq!(
179 state.parse_evaluate_raw(r#"std.base64("test") == "dGVzdA==""#),
180 Val::Bool(true)
181 );
182 }
95183
96 macro_rules! eval {184 macro_rules! eval {
97 ($str: expr) => {185 ($str: expr) => {
359447
360 #[test]448 #[test]
361 fn json() {449 fn json() {
362 println!("{:?}", eval_stdlib!(r#"std.manifestJsonEx({a:3, b:4, c:6},"")"#));450 assert_json_stdlib!(
451 r#"std.manifestJsonEx({a:3, b:4, c:6},"")"#,
452 r#""{\n"a": 3,\n"b": 4,\n"c": 6\n}""#
453 );
363 }454 }
364455
365 #[test]456 #[test]
366 fn test() {457 fn test() {
367 assert_json_stdlib!(r#"[[a, b] for a in [1,2,3] for b in [4,5,6]]"#, "");458 assert_json_stdlib!(
459 r#"[[a, b] for a in [1,2,3] for b in [4,5,6]]"#,
460 "[[1,4],[1,5],[1,6],[2,4],[2,5],[2,6],[3,4],[3,5],[3,6]]"
461 );
368 }462 }
369463