git.delta.rocks / jrsonnet / refs/commits / 1dbd15d5102e

difftreelog

feat import support

Лач2020-06-10parent: #ff03a2a.patch.diff
in: master

3 files changed

modifiedcmds/jrsonnet/src/main.rsdiffbeforeafterboth
1pub mod location;1pub mod location;
22
3use 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};
111111
112fn 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 }
modifiedcrates/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())
modifiedcrates/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(