difftreelog
feat import support
in: master
3 files changed
cmds/jrsonnet/src/main.rsdiffbeforeafterboth1pub mod location;1pub mod location;223use clap::Clap;3use clap::Clap;4use jsonnet_evaluator::{EvaluationState, LocError, StackTrace, Val};4use jsonnet_evaluator::{EvaluationSettings, EvaluationState, LocError, StackTrace, Val};5use location::{offset_to_location, CodeLocation};5use location::{offset_to_location, CodeLocation};6use std::env::current_dir;6use std::env::current_dir;7use std::{path::PathBuf, str::FromStr};7use std::{path::PathBuf, str::FromStr};111111112fn main() {112fn main() {113 let opts: Opts = Opts::parse();113 let opts: Opts = Opts::parse();114 let evaluator = jsonnet_evaluator::EvaluationState::default();114 let evaluator = jsonnet_evaluator::EvaluationState::new(EvaluationSettings {115 import_resolver: Box::new(|path| String::from_utf8(std::fs::read(path).unwrap()).unwrap()),116 ..Default::default()117 });115 if !opts.no_stdlib {118 if !opts.no_stdlib {116 evaluator.with_stdlib();119 evaluator.with_stdlib();117 }120 }crates/jsonnet-evaluator/src/evaluate.rsdiffbeforeafterboth--- a/crates/jsonnet-evaluator/src/evaluate.rs
+++ b/crates/jsonnet-evaluator/src/evaluate.rs
@@ -1,5 +1,5 @@
use crate::{
- binding, context_creator, create_error, future_wrapper, lazy_val, push, Context,
+ binding, context_creator, create_error, future_wrapper, lazy_val, push, with_state, Context,
ContextCreator, FuncDesc, LazyBinding, ObjMember, ObjValue, Result, Val,
};
use closure::closure;
@@ -607,6 +607,16 @@
}
}
}
+ Import(path) => {
+ let mut lib_path = loc
+ .clone()
+ .expect("imports can't be used without loc_data")
+ .0
+ .clone();
+ lib_path.pop();
+ lib_path.push(path);
+ with_state(|s| s.import_file(&lib_path))?
+ }
_ => panic!(
"evaluation not implemented: {:?}",
LocExpr(expr.clone(), loc.clone())
crates/jsonnet-evaluator/src/lib.rsdiffbeforeafterboth--- a/crates/jsonnet-evaluator/src/lib.rs
+++ b/crates/jsonnet-evaluator/src/lib.rs
@@ -50,14 +50,18 @@
}
pub struct EvaluationSettings {
- max_stack_frames: usize,
- max_stack_trace_size: usize,
+ pub max_stack_frames: usize,
+ pub max_stack_trace_size: usize,
+ pub import_resolver: Box<dyn Fn(&PathBuf) -> String>,
}
impl Default for EvaluationSettings {
fn default() -> Self {
EvaluationSettings {
max_stack_frames: 200,
max_stack_trace_size: 20,
+ import_resolver: Box::new(|path| {
+ panic!("default EvaluationSettings have no support for import resolution, can't import {:?}", path)
+ }),
}
}
}
@@ -102,6 +106,12 @@
#[derive(Default, Clone)]
pub struct EvaluationState(Rc<EvaluationStateInternals>);
impl EvaluationState {
+ pub fn new(settings: EvaluationSettings) -> Self {
+ EvaluationState(Rc::new(EvaluationStateInternals {
+ settings,
+ ..Default::default()
+ }))
+ }
pub fn add_file(&self, name: PathBuf, code: String) -> std::result::Result<(), ParseError> {
self.0.files.borrow_mut().insert(
name.clone(),
@@ -139,6 +149,11 @@
}
pub fn evaluate_file(&self, name: &PathBuf) -> Result<Val> {
self.begin_state();
+ let value = self.evaluate_file_in_current_state(name)?;
+ self.end_state();
+ Ok(value)
+ }
+ pub(crate) fn evaluate_file_in_current_state(&self, name: &PathBuf) -> Result<Val> {
let expr: LocExpr = {
let ro_map = self.0.files.borrow();
let value = ro_map
@@ -159,9 +174,15 @@
.2
.replace(value.clone());
}
- self.end_state();
Ok(value)
}
+ pub(crate) fn import_file(&self, path: &PathBuf) -> Result<Val> {
+ if !self.0.files.borrow().contains_key(path) {
+ let file_str = (self.0.settings.import_resolver)(path);
+ self.add_file(path.clone(), file_str).unwrap();
+ }
+ self.evaluate_file_in_current_state(path)
+ }
pub fn parse_evaluate_raw(&self, code: &str) -> Result<Val> {
let parsed = parse(