Tracing errors out of the AST
A trace from the top level form to the exact point where a type error is detected by collecting all the nested expressions, by backwards-recursively catching and rethrowing it with a level of context added. Pseudo code:
some_code_checing_expr(Expr) ->
try
check_all_sub_expressions(Expr)
catch
throw:{type_error, ..., Context, ...}:Stacktrace ->
erlang:raise(throw, {type_error, ..., [Expr | Context], ...}, Stacktrace)
end.
This can then for example be reported as "The variable X in the binary operation X + Y in the function f(X, Y) -> X + Y has type atom() but the expected type is number()".
This is not very readable though. It's better to show pretty-printed source code, with the inner-most expression highlighted, underlined, etc. If the context is given in number of lines, we can just include as many levels as we find fits, by checking the annotations while traversing the nested expression.
Yes, this would be nice to have. GHC (the Haskell compiler) does this to some extent. It would require some care to make sure that it's readable.