git.delta.rocks / jrsonnet / refs/commits / 06bf1b38ec36

difftreelog

refactor remove trace format from state

Yaroslav Bolyukin2022-11-09parent: #78be616.patch.diff
in: master

5 files changed

modifiedcmds/jrsonnet/src/main.rsdiffbeforeafterboth
--- a/cmds/jrsonnet/src/main.rs
+++ b/cmds/jrsonnet/src/main.rs
@@ -51,6 +51,9 @@
 	input: InputOpts,
 	#[clap(flatten)]
 	general: GeneralOpts,
+
+	#[clap(flatten)]
+	trace: TraceOpts,
 	#[clap(flatten)]
 	manifest: ManifestOpts,
 	#[clap(flatten)]
@@ -114,9 +117,15 @@
 
 fn main_catch(opts: Opts) -> bool {
 	let s = State::default();
+	let trace = opts
+		.trace
+		.configure(&s)
+		.expect("this configurator doesn't fail");
 	if let Err(e) = main_real(&s, opts) {
 		if let Error::Evaluation(e) = e {
-			eprintln!("{}", s.stringify_err(&e));
+			let mut out = String::new();
+			trace.write_trace(&mut out, &e).expect("format error");
+			eprintln!("{out}")
 		} else {
 			eprintln!("{}", e);
 		}
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::{10	error::Result, stack::StackDepthLimitOverrideGuard, FileImportResolver, State,11};12use jrsonnet_gcmodule::with_thread_object_space;13pub use manifest::*;14pub use stdlib::*;15pub use tla::*;16pub use trace::*;1718pub trait ConfigureState {19	type Guards;2021	fn configure(&self, s: &State) -> Result<Self::Guards>;22}2324#[derive(Parser)]25#[clap(next_help_heading = "INPUT")]26pub struct InputOpts {27	/// Treat input as code, evaluate them instead of reading file28	#[clap(long, short = 'e')]29	pub exec: bool,3031	/// Path to the file to be compiled if `--evaluate` is unset, otherwise code itself32	pub input: String,33}3435#[derive(Parser)]36#[clap(next_help_heading = "OPTIONS")]37pub struct MiscOpts {38	/// Maximal allowed number of stack frames,39	/// stack overflow error will be raised if this number gets exceeded.40	#[clap(long, short = 's', default_value = "200")]41	max_stack: usize,4243	/// Library search dirs. (right-most wins)44	/// Any not found `imported` file will be searched in these.45	/// This can also be specified via `JSONNET_PATH` variable,46	/// which should contain a colon-separated (semicolon-separated on Windows) list of directories.47	#[clap(long, short = 'J')]48	jpath: Vec<PathBuf>,49}50impl ConfigureState for MiscOpts {51	type Guards = StackDepthLimitOverrideGuard;52	fn configure(&self, s: &State) -> Result<Self::Guards> {53		let mut library_paths = self.jpath.clone();54		library_paths.reverse();55		if let Some(path) = env::var_os("JSONNET_PATH") {56			library_paths.extend(env::split_paths(path.as_os_str()));57		}5859		s.set_import_resolver(Box::new(FileImportResolver::new(library_paths)));6061		let _depth_limit = jrsonnet_evaluator::stack::limit_stack_depth(self.max_stack);62		Ok(_depth_limit)63	}64}6566/// General configuration of jsonnet67#[derive(Parser)]68#[clap(name = "jrsonnet", version, author)]69pub struct GeneralOpts {70	#[clap(flatten)]71	misc: MiscOpts,7273	#[clap(flatten)]74	tla: TlaOpts,75	#[clap(flatten)]76	std: StdOpts,7778	#[clap(flatten)]79	trace: TraceOpts,8081	#[clap(flatten)]82	gc: GcOpts,83}8485impl ConfigureState for GeneralOpts {86	type Guards = (87		<MiscOpts as ConfigureState>::Guards,88		<TlaOpts as ConfigureState>::Guards,89		<GcOpts as ConfigureState>::Guards,90	);91	fn configure(&self, s: &State) -> Result<Self::Guards> {92		// Configure trace first, because tla-code/ext-code can throw93		self.trace.configure(s)?;94		let misc_guards = self.misc.configure(s)?;95		let tla_guards = self.tla.configure(s)?;96		self.std.configure(s)?;97		let gc_guards = self.gc.configure(s)?;98		Ok((misc_guards, tla_guards, gc_guards))99	}100}101102#[derive(Parser)]103#[clap(next_help_heading = "GARBAGE COLLECTION")]104pub struct GcOpts {105	/// Do not skip gc on exit106	#[clap(long)]107	gc_collect_on_exit: bool,108	/// Print gc stats before exit109	#[clap(long)]110	gc_print_stats: bool,111	/// Force garbage collection before printing stats112	/// Useful for checking for memory leaks113	/// Does nothing useless --gc-print-stats is specified114	#[clap(long)]115	gc_collect_before_printing_stats: bool,116}117impl ConfigureState for GcOpts {118	type Guards = (Option<GcStatsPrinter>, Option<LeakSpace>);119120	fn configure(&self, _s: &State) -> Result<Self::Guards> {121		// Constructed structs have side-effects in Drop impl122		#[allow(clippy::unnecessary_lazy_evaluations)]123		Ok((124			self.gc_print_stats.then(|| GcStatsPrinter {125				collect_before_printing_stats: self.gc_collect_before_printing_stats,126			}),127			(!self.gc_collect_on_exit).then(|| LeakSpace(PhantomData)),128		))129	}130}131132pub struct LeakSpace(PhantomData<()>);133134impl Drop for LeakSpace {135	fn drop(&mut self) {136		with_thread_object_space(|s| s.leak())137	}138}139140pub struct GcStatsPrinter {141	collect_before_printing_stats: bool,142}143impl Drop for GcStatsPrinter {144	fn drop(&mut self) {145		eprintln!("=== GC STATS ===");146		if self.collect_before_printing_stats {147			let collected = jrsonnet_gcmodule::collect_thread_cycles();148			eprintln!("Collected: {}", collected);149		}150		eprintln!("Tracked: {}", jrsonnet_gcmodule::count_thread_tracked())151	}152}
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::{10	error::Result, stack::StackDepthLimitOverrideGuard, FileImportResolver, State,11};12use jrsonnet_gcmodule::with_thread_object_space;13pub use manifest::*;14pub use stdlib::*;15pub use tla::*;16pub use trace::*;1718pub trait ConfigureState {19	type Guards;2021	fn configure(&self, s: &State) -> Result<Self::Guards>;22}2324#[derive(Parser)]25#[clap(next_help_heading = "INPUT")]26pub struct InputOpts {27	/// Treat input as code, evaluate them instead of reading file28	#[clap(long, short = 'e')]29	pub exec: bool,3031	/// Path to the file to be compiled if `--evaluate` is unset, otherwise code itself32	pub input: String,33}3435#[derive(Parser)]36#[clap(next_help_heading = "OPTIONS")]37pub struct MiscOpts {38	/// Maximal allowed number of stack frames,39	/// stack overflow error will be raised if this number gets exceeded.40	#[clap(long, short = 's', default_value = "200")]41	max_stack: usize,4243	/// Library search dirs. (right-most wins)44	/// Any not found `imported` file will be searched in these.45	/// This can also be specified via `JSONNET_PATH` variable,46	/// which should contain a colon-separated (semicolon-separated on Windows) list of directories.47	#[clap(long, short = 'J')]48	jpath: Vec<PathBuf>,49}50impl ConfigureState for MiscOpts {51	type Guards = StackDepthLimitOverrideGuard;52	fn configure(&self, s: &State) -> Result<Self::Guards> {53		let mut library_paths = self.jpath.clone();54		library_paths.reverse();55		if let Some(path) = env::var_os("JSONNET_PATH") {56			library_paths.extend(env::split_paths(path.as_os_str()));57		}5859		s.set_import_resolver(Box::new(FileImportResolver::new(library_paths)));6061		let _depth_limit = jrsonnet_evaluator::stack::limit_stack_depth(self.max_stack);62		Ok(_depth_limit)63	}64}6566/// General configuration of jsonnet67#[derive(Parser)]68#[clap(name = "jrsonnet", version, author)]69pub struct GeneralOpts {70	#[clap(flatten)]71	misc: MiscOpts,7273	#[clap(flatten)]74	tla: TlaOpts,75	#[clap(flatten)]76	std: StdOpts,7778	#[clap(flatten)]79	gc: GcOpts,80}8182impl ConfigureState for GeneralOpts {83	type Guards = (84		<MiscOpts as ConfigureState>::Guards,85		<TlaOpts as ConfigureState>::Guards,86		<GcOpts as ConfigureState>::Guards,87	);88	fn configure(&self, s: &State) -> Result<Self::Guards> {89		// Configure trace first, because tla-code/ext-code can throw90		let misc_guards = self.misc.configure(s)?;91		let tla_guards = self.tla.configure(s)?;92		self.std.configure(s)?;93		let gc_guards = self.gc.configure(s)?;94		Ok((misc_guards, tla_guards, gc_guards))95	}96}9798#[derive(Parser)]99#[clap(next_help_heading = "GARBAGE COLLECTION")]100pub struct GcOpts {101	/// Do not skip gc on exit102	#[clap(long)]103	gc_collect_on_exit: bool,104	/// Print gc stats before exit105	#[clap(long)]106	gc_print_stats: bool,107	/// Force garbage collection before printing stats108	/// Useful for checking for memory leaks109	/// Does nothing useless --gc-print-stats is specified110	#[clap(long)]111	gc_collect_before_printing_stats: bool,112}113impl ConfigureState for GcOpts {114	type Guards = (Option<GcStatsPrinter>, Option<LeakSpace>);115116	fn configure(&self, _s: &State) -> Result<Self::Guards> {117		// Constructed structs have side-effects in Drop impl118		#[allow(clippy::unnecessary_lazy_evaluations)]119		Ok((120			self.gc_print_stats.then(|| GcStatsPrinter {121				collect_before_printing_stats: self.gc_collect_before_printing_stats,122			}),123			(!self.gc_collect_on_exit).then(|| LeakSpace(PhantomData)),124		))125	}126}127128pub struct LeakSpace(PhantomData<()>);129130impl Drop for LeakSpace {131	fn drop(&mut self) {132		with_thread_object_space(|s| s.leak())133	}134}135136pub struct GcStatsPrinter {137	collect_before_printing_stats: bool,138}139impl Drop for GcStatsPrinter {140	fn drop(&mut self) {141		eprintln!("=== GC STATS ===");142		if self.collect_before_printing_stats {143			let collected = jrsonnet_gcmodule::collect_thread_cycles();144			eprintln!("Collected: {}", collected);145		}146		eprintln!("Tracked: {}", jrsonnet_gcmodule::count_thread_tracked())147	}148}
modifiedcrates/jrsonnet-cli/src/trace.rsdiffbeforeafterboth
--- a/crates/jrsonnet-cli/src/trace.rs
+++ b/crates/jrsonnet-cli/src/trace.rs
@@ -1,7 +1,7 @@
 use clap::{Parser, ValueEnum};
 use jrsonnet_evaluator::{
 	error::Result,
-	trace::{CompactFormat, ExplainingFormat, PathResolver},
+	trace::{CompactFormat, ExplainingFormat, PathResolver, TraceFormat},
 	State,
 };
 
@@ -27,21 +27,25 @@
 	max_trace: usize,
 }
 impl ConfigureState for TraceOpts {
-	type Guards = ();
-	fn configure(&self, s: &State) -> Result<()> {
+	type Guards = Box<dyn TraceFormat>;
+	fn configure(&self, _s: &State) -> Result<Self::Guards> {
 		let resolver = PathResolver::new_cwd_fallback();
-		match self
+		let max_trace = self.max_trace;
+		let format: Box<dyn TraceFormat> = match self
 			.trace_format
 			.as_ref()
 			.unwrap_or(&TraceFormatName::Compact)
 		{
-			TraceFormatName::Compact => s.set_trace_format(CompactFormat {
+			TraceFormatName::Compact => Box::new(CompactFormat {
 				resolver,
 				padding: 4,
+				max_trace,
 			}),
-			TraceFormatName::Explaining => s.set_trace_format(ExplainingFormat { resolver }),
-		}
-		s.set_max_trace(self.max_trace);
-		Ok(())
+			TraceFormatName::Explaining => Box::new(ExplainingFormat {
+				resolver,
+				max_trace,
+			}),
+		};
+		Ok(format)
 	}
 }
modifiedcrates/jrsonnet-evaluator/src/error.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/error.rs
+++ b/crates/jrsonnet-evaluator/src/error.rs
@@ -262,7 +262,6 @@
 			write!(f, "\t{}", el.desc)?;
 			if let Some(loc) = &el.location {
 				write!(f, "at {}", loc.0 .0 .0)?;
-				// loc.0
 				loc.0.map_source_locations(&[loc.1, loc.2]);
 			}
 			writeln!(f)?;
modifiedcrates/jrsonnet-evaluator/src/trace/mod.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/trace/mod.rs
+++ b/crates/jrsonnet-evaluator/src/trace/mod.rs
@@ -1,9 +1,12 @@
-use std::path::{Path, PathBuf};
+use std::{
+	any::Any,
+	path::{Path, PathBuf},
+};
 
 use jrsonnet_gcmodule::Trace;
 use jrsonnet_parser::{CodeLocation, Source};
 
-use crate::{error::Error, LocError, State};
+use crate::{error::Error, LocError};
 
 /// The way paths should be displayed
 #[derive(Clone, Trace)]
@@ -48,9 +51,15 @@
 	fn write_trace(
 		&self,
 		out: &mut dyn std::fmt::Write,
-		s: &State,
 		error: &LocError,
 	) -> Result<(), std::fmt::Error>;
+	fn format(&self, error: &LocError) -> Result<String, std::fmt::Error> {
+		let mut out = String::new();
+		self.write_trace(&mut out, error)?;
+		Ok(out)
+	}
+	fn as_any(&self) -> &dyn Any;
+	fn as_any_mut(&mut self) -> &mut dyn Any;
 }
 
 fn print_code_location(
@@ -81,14 +90,23 @@
 #[derive(Trace)]
 pub struct CompactFormat {
 	pub resolver: PathResolver,
+	pub max_trace: usize,
 	pub padding: usize,
 }
+impl Default for CompactFormat {
+	fn default() -> Self {
+		Self {
+			resolver: PathResolver::Absolute,
+			max_trace: 20,
+			padding: 4,
+		}
+	}
+}
 
 impl TraceFormat for CompactFormat {
 	fn write_trace(
 		&self,
 		out: &mut dyn std::fmt::Write,
-		_s: &State,
 		error: &LocError,
 	) -> Result<(), std::fmt::Error> {
 		write!(out, "{}", error.error())?;
@@ -168,15 +186,24 @@
 		}
 		Ok(())
 	}
+
+	fn as_any(&self) -> &dyn Any {
+		self
+	}
+
+	fn as_any_mut(&mut self) -> &mut dyn Any {
+		self
+	}
 }
 
 #[derive(Trace)]
-pub struct JsFormat;
+pub struct JsFormat {
+	pub max_trace: usize,
+}
 impl TraceFormat for JsFormat {
 	fn write_trace(
 		&self,
 		out: &mut dyn std::fmt::Write,
-		_s: &State,
 		error: &LocError,
 	) -> Result<(), std::fmt::Error> {
 		write!(out, "{}", error.error())?;
@@ -201,6 +228,14 @@
 		}
 		Ok(())
 	}
+
+	fn as_any(&self) -> &dyn Any {
+		self
+	}
+
+	fn as_any_mut(&mut self) -> &mut dyn Any {
+		self
+	}
 }
 
 /// rustc-like trace displaying
@@ -208,13 +243,13 @@
 #[derive(Trace)]
 pub struct ExplainingFormat {
 	pub resolver: PathResolver,
+	pub max_trace: usize,
 }
 #[cfg(feature = "explaining-traces")]
 impl TraceFormat for ExplainingFormat {
 	fn write_trace(
 		&self,
 		out: &mut dyn std::fmt::Write,
-		_s: &State,
 		error: &LocError,
 	) -> Result<(), std::fmt::Error> {
 		write!(out, "{}", error.error())?;
@@ -258,6 +293,14 @@
 		}
 		Ok(())
 	}
+
+	fn as_any(&self) -> &dyn Any {
+		self
+	}
+
+	fn as_any_mut(&mut self) -> &mut dyn Any {
+		self
+	}
 }
 
 impl ExplainingFormat {