fathom
fathom copied to clipboard
Track source locations in core::Term and Values
This PR adds source location information to core::Term and Value so that this information can flow from the surface language through the core language and back out. This allows some errors to be much more helpful.
This is a large change but I tried to keep the commits focussed on a single Term or Value variant so the history should be quite readable. There are a number of FIXME, TODO comments and a few references to a Span::fixme method left. Most of them are questions that I want to discuss to determine the right approach to resolve them.
I initially added spans to Value directly but this made it difficult when reusing a shared value instance (since they are ref-counted). For example, when encountering a fail format the value is the shared fail instance in the environment but the span is wherever this particular use of fail occurred. As a result of wanting to be able to provide a decent error in situations like this I refactored the handling of Values to instead have a wrapper type (SpanValue) that contains a Span and a Value. This way the span is independent of the Value. This worked out well for the fail case, allowing the location in the format to be included in the error.
There's a similar case that I would like to work but have not worked out how to do itโI did add a test though. When you unwrap none the error is:
error: unwrapped none
= option_unwrap was called on a none value.
I'd like that to be able to point at where the unwrap occurred but got a bit lost in step macro.
Another thing I'm unsure about is things like this (from synth):
Term::RecordLiteral(range, expr_fields) => {
โฎ
let types = Telescope::new(self.rigid_env.exprs.clone(), types.into());
(
core::Term::RecordLit(range.into(), labels, exprs.into()),
SpanValue::empty(Arc::new(Value::RecordType(labels, types))),
)
}
where we return a term an its type. Should the type use the same range as the term? This question accounts for a bunch of the TODOs/FIXMEs I have in different places.
In the latter commits I reworked how BufferError is handled to allow errors like this to be generated:
error: unexpected end of buffer
โโ formats/opentype.fathom:34:18
โ
34 โ magic <- u32be,
โ ^^^^^
โ
= The end of the buffer was reached before all data could be read.