--- a/crates/jrsonnet-evaluator/src/error.rs +++ b/crates/jrsonnet-evaluator/src/error.rs @@ -132,7 +132,7 @@ #[derive(Clone, Debug)] pub struct StackTraceElement { - pub location: ExprLocation, + pub location: Option, pub desc: String, } #[derive(Debug, Clone)] --- a/crates/jrsonnet-evaluator/src/lib.rs +++ b/crates/jrsonnet-evaluator/src/lib.rs @@ -132,11 +132,15 @@ frame_desc: impl FnOnce() -> String, f: impl FnOnce() -> Result, ) -> Result { - if let Some(v) = e { - with_state(|s| s.push(v, frame_desc, f)) - } else { - f() - } + with_state(|s| s.push(e, frame_desc, f)) +} + +pub fn push_stack_frame( + e: Option<&ExprLocation>, + frame_desc: impl FnOnce() -> String, + f: impl FnOnce() -> Result, + ) -> Result { + push(e, frame_desc, f) } /// Maintains stack trace and import resolution @@ -271,7 +275,7 @@ /// Executes code creating a new stack frame pub fn push( &self, - e: &ExprLocation, + e: Option<&ExprLocation>, frame_desc: impl FnOnce() -> String, f: impl FnOnce() -> Result, ) -> Result { @@ -290,7 +294,7 @@ self.data_mut().stack_depth -= 1; if let Err(mut err) = result { err.trace_mut().0.push(StackTraceElement { - location: e.clone(), + location: e.cloned(), desc: frame_desc(), }); return Err(err); @@ -336,11 +340,11 @@ pub fn with_tla(&self, val: Val) -> Result { self.run_in_state(|| { Ok(match val { - Val::Func(func) => func.evaluate_map( + Val::Func(func) => push(None, || "during TLA call".to_owned(), || Ok(func.evaluate_map( self.create_default_context()?, &self.settings().tla_vars, true, - )?, + )?))?, v => v, }) }) --- a/crates/jrsonnet-evaluator/src/trace/location.rs +++ b/crates/jrsonnet-evaluator/src/trace/location.rs @@ -37,7 +37,7 @@ ]; let mut with_no_known_line_ending = vec![]; let mut this_line_offset = 0; - for (pos, ch) in file.chars().enumerate() { + for (pos, ch) in file.chars().enumerate().chain(std::iter::once((file.len(), ' '))) { column += 1; match offset_map.last() { Some(x) if x.0 == pos => { --- a/crates/jrsonnet-evaluator/src/trace/mod.rs +++ b/crates/jrsonnet-evaluator/src/trace/mod.rs @@ -118,21 +118,18 @@ .trace() .0 .iter() - .map(|el| { - let resolved_path = self.resolver.resolve(&el.location.0); + .map(|el| el.location.as_ref().map(|l| { + use std::fmt::Write; + let mut resolved_path = self.resolver.resolve(&l.0); // TODO: Process all trace elements first let location = evaluation_state - .map_source_locations(&el.location.0, &[el.location.1, el.location.2]); - (resolved_path, location) - }) - .map(|(mut n, location)| { - use std::fmt::Write; - write!(n, ":").unwrap(); - print_code_location(&mut n, &location[0], &location[1]).unwrap(); - n - }) + .map_source_locations(&l.0, &[l.1, l.2]); + write!(resolved_path, ":").unwrap(); + print_code_location(&mut resolved_path, &location[0], &location[1]).unwrap(); + resolved_path + })) .collect::>(); - let align = file_names.iter().map(|e| e.len()).max().unwrap_or(0); + let align = file_names.iter().flatten().map(|e| e.len()).max().unwrap_or(0); for (i, (el, file)) in error.trace().0.iter().zip(file_names).enumerate() { if i != 0 { writeln!(out)?; @@ -141,7 +138,7 @@ out, "{: