--- /dev/null +++ b/crates/jrsonnet-evaluator/src/builtin/mod.rs @@ -0,0 +1,2 @@ +pub mod stdlib; +pub use stdlib::*; --- /dev/null +++ b/crates/jrsonnet-evaluator/src/builtin/stdlib.rs @@ -0,0 +1,37 @@ +use jrsonnet_parser::{LocExpr, ParserSettings}; +use std::{path::PathBuf, rc::Rc}; + +thread_local! { + /// To avoid parsing again when issued from same thread + #[allow(unreachable_code)] + static PARSED_STDLIB: LocExpr = { + #[cfg(feature = "codegenerated-stdlib")] + { + #[allow(clippy::all)] + return { + use jrsonnet_parser::*; + include!(concat!(env!("OUT_DIR"), "/stdlib.rs")) + }; + } + + #[cfg(feature = "serialized-stdlib")] + { + // Should not panic, stdlib.bincode is generated in build.rs + return bincode::deserialize(include_bytes!(concat!(env!("OUT_DIR"), "/stdlib.bincode"))) + .unwrap(); + } + + jrsonnet_parser::parse( + &jrsonnet_stdlib::STDLIB_STR, + &ParserSettings { + loc_data: true, + file_name: Rc::new(PathBuf::from("std.jsonnet")), + }, + ) + .unwrap() + } +} + +pub fn get_parsed_stdlib() -> LocExpr { + PARSED_STDLIB.with(|t| t.clone()) +} --- a/crates/jrsonnet-evaluator/src/lib.rs +++ b/crates/jrsonnet-evaluator/src/lib.rs @@ -262,57 +262,19 @@ self.run_in_state(|| evaluate(self.create_default_context()?, &code)) } - pub fn add_global(&self, name: Rc, value: Val) { - self.settings_mut().globals.insert(name, value); - } - pub fn add_ext_var(&self, name: Rc, value: Val) { - self.settings_mut().ext_vars.insert(name, value); - } - pub fn set_max_trace(&self, max_trace: usize) { - self.settings_mut().max_stack_trace_size = max_trace; - } - pub fn set_max_stack(&self, max_stack: usize) { - self.settings_mut().max_stack_frames = max_stack; - } - + /// Adds standard library global variable (std) to this evaluator pub fn with_stdlib(&self) -> &Self { + use jrsonnet_stdlib::STDLIB_STR; let std_path = Rc::new(PathBuf::from("std.jsonnet")); self.run_in_state(|| { - use jrsonnet_stdlib::STDLIB_STR; - let mut parsed = false; - #[cfg(feature = "codegenerated-stdlib")] - if !parsed { - parsed = true; - #[allow(clippy::all)] - let stdlib = { - use jrsonnet_parser::*; - include!(concat!(env!("OUT_DIR"), "/stdlib.rs")) - }; - self.add_parsed_file(std_path.clone(), STDLIB_STR.to_owned().into(), stdlib) - .unwrap(); - } - - #[cfg(feature = "serialized-stdlib")] - if !parsed { - parsed = true; - self.add_parsed_file( - std_path.clone(), - STDLIB_STR.to_owned().into(), - bincode::deserialize(include_bytes!(concat!( - env!("OUT_DIR"), - "/stdlib.bincode" - ))) - .expect("deserialize stdlib"), - ) - .unwrap(); - } - - if !parsed { - self.add_file(std_path, STDLIB_STR.to_owned().into()) - .unwrap(); - } - let val = self.evaluate_file(&PathBuf::from("std.jsonnet")).unwrap(); - self.add_global("std".into(), val); + self.add_parsed_file( + std_path.clone(), + STDLIB_STR.to_owned().into(), + builtin::get_parsed_stdlib(), + ) + .unwrap(); + let val = self.evaluate_file(&std_path).unwrap(); + self.settings_mut().globals.insert("std".into(), val); }); self }