create Engine::tracepoint

adds tracepoints to returned errors and warnings automatically
This commit is contained in:
PgBiel 2024-06-13 22:52:35 -03:00
parent e69c58a234
commit b559fc20b7
2 changed files with 47 additions and 25 deletions

View File

@ -85,6 +85,47 @@ impl Engine<'_> {
pairs.into_iter().map(|(output, _)| output)
}
/// Executes some code with a tracepoint for diagnostics.
/// The tracepoint is added to any diagnostics returned by the function,
/// as well as any warnings emitted by it.
pub fn tracepoint<F, M, T>(
&mut self,
make_point: M,
span: Span,
f: F,
) -> SourceResult<T>
where
F: FnOnce(&mut Engine) -> SourceResult<T>,
M: Copy + Fn() -> Tracepoint,
{
let Engine { world, introspector, traced, ref route, .. } = *self;
// Create a temporary sink to accumulate all warnings produced by
// this call (either directly or due to a nested call). Later, we
// add a tracepoint to those warnings, indicating this call was
// part of the call stack that led to the warning being raised,
// thus allowing suppression of the warning through this call.
let mut sink = Sink::new();
let mut engine = Engine {
world,
introspector,
traced,
sink: sink.track_mut(),
route: route.clone(),
};
// Trace errors immediately, followed by warnings on the sink.
let call_result = f(&mut engine).trace(world, make_point, span);
sink.trace_warnings(world, make_point, span);
// Push the accumulated warnings and other fields back to the
// original sink after we have modified them. This is needed so the
// warnings are properly returned by compilation later.
self.sink.extend(sink.delayed, sink.warnings, sink.values);
call_result
}
}
/// May hold a span that is currently under inspection.

View File

@ -1,4 +1,4 @@
use comemo::{Track, Tracked, TrackedMut};
use comemo::{Tracked, TrackedMut};
use ecow::{eco_format, EcoVec};
use crate::diag::{bail, error, At, HintedStrResult, SourceResult, Trace, Tracepoint};
@ -165,31 +165,12 @@ impl Eval for ast::FuncCall<'_> {
let point = || Tracepoint::Call(func.name().map(Into::into));
let f = || {
// Create a temporary sink to accumulate all warnings produced by
// this call (either directly or due to a nested call). Later, we
// add a tracepoint to those warnings, indicating this call was
// part of the call stack that led to the warning being raised,
// thus allowing suppression of the warning through this call.
let mut local_sink = Sink::new();
let mut engine = Engine {
sink: local_sink.track_mut(),
route: vm.engine.route.clone(),
..vm.engine
};
let call_result =
// Add this function call as a tracepoint to the returned
// diagnostics. This allows visualizing which calls led to them,
// but also allows suppressing warnings at each tracepoint.
vm.engine.tracepoint(point, span, |mut engine| {
func.call(&mut engine, vm.context, args)
.trace(vm.world(), point, span);
local_sink.trace_warnings(vm.world(), point, span);
// Push the accumulated warnings and other fields back to the
// original sink after we have modified them. This is needed so the
// warnings are properly returned by compilation later.
let (delayed, warnings, values) = local_sink.take();
vm.engine.sink.extend(delayed, warnings, values);
call_result
})
};
// Stacker is broken on WASM.