git.delta.rocks / jrsonnet / refs/commits / 2cecfb0ba471

difftreelog

refactor remove GeneralOpts/ConfigureState

Yaroslav Bolyukin2023-01-20parent: #1f5d87f.patch.diff
in: master
Because many options were removed from global state, everything should
be configured manually now

6 files changed

modifiedcmds/jrsonnet/src/main.rsdiffbeforeafterboth
--- a/cmds/jrsonnet/src/main.rs
+++ b/cmds/jrsonnet/src/main.rs
@@ -5,7 +5,7 @@
 
 use clap::{CommandFactory, Parser};
 use clap_complete::Shell;
-use jrsonnet_cli::{ConfigureState, GeneralOpts, ManifestOpts, OutputOpts, TraceOpts};
+use jrsonnet_cli::{ManifestOpts, OutputOpts, TraceOpts, MiscOpts, TlaOpts, StdOpts, GcOpts};
 use jrsonnet_evaluator::{
 	apply_tla,
 	error::{Error as JrError, ErrorKind},
@@ -60,7 +60,13 @@
 	#[clap(flatten)]
 	input: InputOpts,
 	#[clap(flatten)]
-	general: GeneralOpts,
+	misc: MiscOpts,
+	#[clap(flatten)]
+	tla: TlaOpts,
+	#[clap(flatten)]
+	std: StdOpts,
+	#[clap(flatten)]
+	gc: GcOpts,
 
 	#[clap(flatten)]
 	trace: TraceOpts,
@@ -129,8 +135,7 @@
 	let s = State::default();
 	let trace = opts
 		.trace
-		.configure(&s)
-		.expect("this configurator doesn't fail");
+		.trace_format();
 	if let Err(e) = main_real(&s, opts) {
 		if let Error::Evaluation(e) = e {
 			let mut out = String::new();
@@ -145,8 +150,17 @@
 }
 
 fn main_real(s: &State, opts: Opts) -> Result<(), Error> {
-	let (tla, _gc_guard) = opts.general.configure(s)?;
-	let manifest_format = opts.manifest.configure(s)?;
+	let _gc_leak_guard= opts.gc.leak_on_exit();
+	let _gc_print_stats = opts.gc.stats_printer();
+	let _stack_depth_override = opts.misc.stack_size_override();
+
+	let import_resolver = opts.misc.import_resolver();
+	s.set_import_resolver(import_resolver);
+
+	let std = opts.std.context_initializer(s)?;
+	if let Some(std) = std {
+		s.set_context_initializer(std);
+	}
 
 	let input = opts.input.input.ok_or(Error::MissingInputArgument)?;
 	let val = if opts.input.exec {
@@ -160,8 +174,10 @@
 		s.import(&input)?
 	};
 
+	let tla = opts.tla.tla_opts()?;
 	let val = apply_tla(s.clone(), &tla, val)?;
 
+	let manifest_format = opts.manifest.manifest_format();
 	if let Some(multi) = opts.output.multi {
 		if opts.output.create_output_dirs {
 			let mut dir = multi.clone();
modifiedcrates/jrsonnet-cli/src/lib.rsdiffbeforeafterboth
before · crates/jrsonnet-cli/src/lib.rs
1mod manifest;2mod stdlib;3mod tla;4mod trace;56use std::{env, marker::PhantomData, path::PathBuf};78use clap::Parser;9use jrsonnet_evaluator::{error::Result, stack::set_stack_depth_limit, FileImportResolver, State};10use jrsonnet_gcmodule::with_thread_object_space;11pub use manifest::*;12pub use stdlib::*;13pub use tla::*;14pub use trace::*;1516pub trait ConfigureState {17	type Guards;1819	fn configure(&self, s: &State) -> Result<Self::Guards>;20}2122#[derive(Parser)]23#[clap(next_help_heading = "INPUT")]24pub struct InputOpts {25	/// Treat input as code, evaluate them instead of reading file26	#[clap(long, short = 'e')]27	pub exec: bool,2829	/// Path to the file to be compiled if `--evaluate` is unset, otherwise code itself30	pub input: String,31}3233#[derive(Parser)]34#[clap(next_help_heading = "OPTIONS")]35pub struct MiscOpts {36	/// Maximal allowed number of stack frames,37	/// stack overflow error will be raised if this number gets exceeded.38	#[clap(long, short = 's', default_value = "200")]39	max_stack: usize,4041	/// Library search dirs. (right-most wins)42	/// Any not found `imported` file will be searched in these.43	/// This can also be specified via `JSONNET_PATH` variable,44	/// which should contain a colon-separated (semicolon-separated on Windows) list of directories.45	#[clap(long, short = 'J')]46	jpath: Vec<PathBuf>,47}48impl ConfigureState for MiscOpts {49	type Guards = ();50	fn configure(&self, s: &State) -> Result<Self::Guards> {51		let mut library_paths = self.jpath.clone();52		library_paths.reverse();53		if let Some(path) = env::var_os("JSONNET_PATH") {54			library_paths.extend(env::split_paths(path.as_os_str()));55		}5657		s.set_import_resolver(FileImportResolver::new(library_paths));5859		set_stack_depth_limit(self.max_stack);60		Ok(())61	}62}6364/// General configuration of jsonnet65#[derive(Parser)]66#[clap(name = "jrsonnet", version, author)]67pub struct GeneralOpts {68	#[clap(flatten)]69	misc: MiscOpts,7071	#[clap(flatten)]72	tla: TlaOpts,73	#[clap(flatten)]74	std: StdOpts,7576	#[clap(flatten)]77	gc: GcOpts,78}7980impl ConfigureState for GeneralOpts {81	type Guards = (82		<TlaOpts as ConfigureState>::Guards,83		<GcOpts as ConfigureState>::Guards,84	);85	fn configure(&self, s: &State) -> Result<Self::Guards> {86		// Configure trace first, because tla-code/ext-code can throw87		self.misc.configure(s)?;88		let tla_guards = self.tla.configure(s)?;89		self.std.configure(s)?;90		let gc_guards = self.gc.configure(s)?;91		Ok((tla_guards, gc_guards))92	}93}9495#[derive(Parser)]96#[clap(next_help_heading = "GARBAGE COLLECTION")]97pub struct GcOpts {98	/// Do not skip gc on exit99	#[clap(long)]100	gc_collect_on_exit: bool,101	/// Print gc stats before exit102	#[clap(long)]103	gc_print_stats: bool,104	/// Force garbage collection before printing stats105	/// Useful for checking for memory leaks106	/// Does nothing useless --gc-print-stats is specified107	#[clap(long)]108	gc_collect_before_printing_stats: bool,109}110impl ConfigureState for GcOpts {111	type Guards = (Option<GcStatsPrinter>, Option<LeakSpace>);112113	fn configure(&self, _s: &State) -> Result<Self::Guards> {114		// Constructed structs have side-effects in Drop impl115		#[allow(clippy::unnecessary_lazy_evaluations)]116		Ok((117			self.gc_print_stats.then(|| GcStatsPrinter {118				collect_before_printing_stats: self.gc_collect_before_printing_stats,119			}),120			(!self.gc_collect_on_exit).then(|| LeakSpace(PhantomData)),121		))122	}123}124125pub struct LeakSpace(PhantomData<()>);126127impl Drop for LeakSpace {128	fn drop(&mut self) {129		with_thread_object_space(|s| s.leak())130	}131}132133pub struct GcStatsPrinter {134	collect_before_printing_stats: bool,135}136impl Drop for GcStatsPrinter {137	fn drop(&mut self) {138		eprintln!("=== GC STATS ===");139		if self.collect_before_printing_stats {140			let collected = jrsonnet_gcmodule::collect_thread_cycles();141			eprintln!("Collected: {}", collected);142		}143		eprintln!("Tracked: {}", jrsonnet_gcmodule::count_thread_tracked())144	}145}
after · crates/jrsonnet-cli/src/lib.rs
1mod manifest;2mod stdlib;3mod tla;4mod trace;56use std::{env, marker::PhantomData, path::PathBuf};78use clap::Parser;9use jrsonnet_evaluator::{error::Result, stack::{set_stack_depth_limit, StackDepthLimitOverrideGuard, limit_stack_depth}, FileImportResolver, State, ImportResolver};10use jrsonnet_gcmodule::with_thread_object_space;11pub use manifest::*;12pub use stdlib::*;13pub use tla::*;14pub use trace::*;1516#[derive(Parser)]17#[clap(next_help_heading = "INPUT")]18pub struct InputOpts {19	/// Treat input as code, evaluate them instead of reading file20	#[clap(long, short = 'e')]21	pub exec: bool,2223	/// Path to the file to be compiled if `--evaluate` is unset, otherwise code itself24	pub input: String,25}2627#[derive(Parser)]28#[clap(next_help_heading = "OPTIONS")]29pub struct MiscOpts {30	/// Maximal allowed number of stack frames,31	/// stack overflow error will be raised if this number gets exceeded.32	#[clap(long, short = 's', default_value = "200")]33	max_stack: usize,3435	/// Library search dirs. (right-most wins)36	/// Any not found `imported` file will be searched in these.37	/// This can also be specified via `JSONNET_PATH` variable,38	/// which should contain a colon-separated (semicolon-separated on Windows) list of directories.39	#[clap(long, short = 'J')]40	jpath: Vec<PathBuf>,41}42impl MiscOpts {43	pub fn import_resolver(&self) -> FileImportResolver {44		let mut library_paths = self.jpath.clone();45		library_paths.reverse();46		if let Some(path) = env::var_os("JSONNET_PATH") {47			library_paths.extend(env::split_paths(path.as_os_str()));48		}4950		FileImportResolver::new(library_paths)51	}52	pub fn stack_size_override(&self) -> StackDepthLimitOverrideGuard {53		limit_stack_depth(self.max_stack)54	}55}5657#[derive(Parser)]58#[clap(next_help_heading = "GARBAGE COLLECTION")]59pub struct GcOpts {60	/// Do not skip gc on exit61	#[clap(long)]62	gc_collect_on_exit: bool,63	/// Print gc stats before exit64	#[clap(long)]65	gc_print_stats: bool,66	/// Force garbage collection before printing stats67	/// Useful for checking for memory leaks68	/// Does nothing useless --gc-print-stats is specified69	#[clap(long)]70	gc_collect_before_printing_stats: bool,71}72impl GcOpts {73	pub fn stats_printer(&self) -> Option<GcStatsPrinter> {74		self.gc_print_stats.then(|| GcStatsPrinter {75			collect_before_printing_stats: self.gc_collect_before_printing_stats,76		})77	}78	pub fn leak_on_exit(&self) -> Option<LeakSpace> {79		(!self.gc_collect_on_exit).then(|| LeakSpace(PhantomData))80	}81}8283pub struct LeakSpace(PhantomData<()>);8485impl Drop for LeakSpace {86	fn drop(&mut self) {87		with_thread_object_space(|s| s.leak())88	}89}9091pub struct GcStatsPrinter {92	collect_before_printing_stats: bool,93}94impl Drop for GcStatsPrinter {95	fn drop(&mut self) {96		eprintln!("=== GC STATS ===");97		if self.collect_before_printing_stats {98			let collected = jrsonnet_gcmodule::collect_thread_cycles();99			eprintln!("Collected: {}", collected);100		}101		eprintln!("Tracked: {}", jrsonnet_gcmodule::count_thread_tracked())102	}103}
modifiedcrates/jrsonnet-cli/src/manifest.rsdiffbeforeafterboth
--- a/crates/jrsonnet-cli/src/manifest.rs
+++ b/crates/jrsonnet-cli/src/manifest.rs
@@ -8,8 +8,6 @@
 };
 use jrsonnet_stdlib::{TomlFormat, YamlFormat};
 
-use crate::ConfigureState;
-
 #[derive(Clone, ValueEnum)]
 pub enum ManifestFormatName {
 	/// Expect string as output, and write them directly
@@ -41,9 +39,8 @@
 	#[clap(long)]
 	pub preserve_order: bool,
 }
-impl ConfigureState for ManifestOpts {
-	type Guards = Box<dyn ManifestFormat>;
-	fn configure(&self, _s: &State) -> Result<Self::Guards> {
+impl ManifestOpts {
+	pub fn manifest_format(&self) -> Box<dyn ManifestFormat> {
 		let format: Box<dyn ManifestFormat> = if self.string {
 			Box::new(StringFormat)
 		} else {
@@ -68,11 +65,11 @@
 				)),
 			}
 		};
-		Ok(if self.yaml_stream {
+		if self.yaml_stream {
 			Box::new(YamlStreamFormat(format))
 		} else {
 			format
-		})
+		}
 	}
 }
 
modifiedcrates/jrsonnet-cli/src/stdlib.rsdiffbeforeafterboth
--- a/crates/jrsonnet-cli/src/stdlib.rs
+++ b/crates/jrsonnet-cli/src/stdlib.rs
@@ -2,8 +2,7 @@
 
 use clap::Parser;
 use jrsonnet_evaluator::{error::Result, tb, trace::PathResolver, State};
-
-use crate::ConfigureState;
+use jrsonnet_stdlib::ContextInitializer;
 
 #[derive(Clone)]
 pub struct ExtStr {
@@ -82,14 +81,13 @@
 	#[clap(long, name = "name=var code path", number_of_values = 1)]
 	ext_code_file: Vec<ExtFile>,
 }
-impl ConfigureState for StdOpts {
-	type Guards = ();
-	fn configure(&self, s: &State) -> Result<()> {
+impl StdOpts {
+	pub fn context_initializer(&self, s: &State) -> Result<Option<ContextInitializer>> {
 		if self.no_stdlib {
-			return Ok(());
+			return Ok(None);
 		}
 		let ctx =
-			jrsonnet_stdlib::ContextInitializer::new(s.clone(), PathResolver::new_cwd_fallback());
+			ContextInitializer::new(s.clone(), PathResolver::new_cwd_fallback());
 		for ext in self.ext_str.iter() {
 			ctx.add_ext_str((&ext.name as &str).into(), (&ext.value as &str).into());
 		}
@@ -102,7 +100,6 @@
 		for ext in self.ext_code_file.iter() {
 			ctx.add_ext_code(&ext.name as &str, &ext.value as &str)?;
 		}
-		s.settings_mut().context_initializer = tb!(ctx);
-		Ok(())
+		Ok(Some(ctx))
 	}
 }
modifiedcrates/jrsonnet-cli/src/tla.rsdiffbeforeafterboth
--- a/crates/jrsonnet-cli/src/tla.rs
+++ b/crates/jrsonnet-cli/src/tla.rs
@@ -7,7 +7,7 @@
 };
 use jrsonnet_parser::{ParserSettings, Source};
 
-use crate::{ConfigureState, ExtFile, ExtStr};
+use crate::{ExtFile, ExtStr};
 
 #[derive(Parser)]
 #[clap(next_help_heading = "TOP LEVEL ARGUMENTS")]
@@ -31,9 +31,8 @@
 	#[clap(long, name = "name=tla code path", number_of_values = 1)]
 	tla_code_file: Vec<ExtFile>,
 }
-impl ConfigureState for TlaOpts {
-	type Guards = GcHashMap<IStr, TlaArg>;
-	fn configure(&self, _s: &State) -> Result<Self::Guards> {
+impl TlaOpts {
+	pub fn tla_opts(&self) -> Result<GcHashMap<IStr, TlaArg>> {
 		let mut out = GcHashMap::new();
 		for (name, value) in self
 			.tla_str
modifiedcrates/jrsonnet-cli/src/trace.rsdiffbeforeafterboth
--- a/crates/jrsonnet-cli/src/trace.rs
+++ b/crates/jrsonnet-cli/src/trace.rs
@@ -5,8 +5,6 @@
 	State,
 };
 
-use crate::ConfigureState;
-
 #[derive(PartialEq, Eq, ValueEnum, Clone)]
 pub enum TraceFormatName {
 	/// Only show `filename:line:column`
@@ -26,9 +24,8 @@
 	#[clap(long, short = 't', default_value = "20")]
 	max_trace: usize,
 }
-impl ConfigureState for TraceOpts {
-	type Guards = Box<dyn TraceFormat>;
-	fn configure(&self, _s: &State) -> Result<Self::Guards> {
+impl TraceOpts {
+	pub fn trace_format(&self) -> Box<dyn TraceFormat> {
 		let resolver = PathResolver::new_cwd_fallback();
 		let max_trace = self.max_trace;
 		let format: Box<dyn TraceFormat> = match self
@@ -46,6 +43,6 @@
 				max_trace,
 			}),
 		};
-		Ok(format)
+		format
 	}
 }