difftreelog
refactor remove trace format from state
in: master
5 files changed
cmds/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);
}
crates/jrsonnet-cli/src/lib.rsdiffbeforeafterboth1mod 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}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}crates/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)
}
}
crates/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)?;
crates/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 {