/**
* Reporting error summaries to the user.
*/
module stratego/error-support/report
imports
libstratego-xtc
error-support
strategies
/**
* Reports an error summary to the stderr.
*
* The current term should be a FILE, stdin, or a string (preferred)
*
* @param Summary -> Summary
* @type a -> a
*/
report-error-summary(|summary) =
?input
; where(
!summary => summary(producer, _, errors)
; !errors
; map({error:
?error
; <report-specific-error(|producer, error) <+ report-error(|producer, error)> input
})
)
<+ say(!"error: An error occured, but the error summary cannot be presented in a nice way. Please report this as a bug.")
; where(<debug(!" Structured error summary: ")> summary)
/**
* @param error Error
* @type a -> a
*/
report-error(|producer, error) =
report-error(|error)
report-error(|error) =
where(!error => error(err, [localized(descr, location)]))
; report-location(|err, descr, location)
<+ say(!"error: An error occured, but the error cannot be presented in a nice way. Please report this as a bug.")
; where(<debug(!" Structured error: ")> error)
; fail
/**
* @param error Location
* @type a -> a
*/
report-location(|err, descr, location) =
where(!location => area-in-file(file, area))
; report-area(|err, descr, file, area)
/**
* @param location Location
* @type a -> a
*/
report-location(|err, descr, location) =
where(!location => file(file))
; report-file(|err, descr, file)
/**
* Improved error reporting for specific cases
*/
strategies
/**
* If the err is a "Parse Table error", then the actual file that is
* a problem, is the parse table. So, we lookup the parse table from
* the -p config.
*
* @param error Error
* @type a -> a
report-specific-error(|producer, error) =
where(!error => error("Parse Table error", [localized(descr, _)]))
; where(
log(|Error(),<concat-strings> [<get-config> "-p", ": Parse table error: ", descr])
)
*/
/**
* If the err is an "Ambiguity" then we show the alternatives,
* which are encoded in the description (separated
* by a semicolon).
*
* @param error Error
* @type a -> a
*/
report-specific-error(|producer, error) =
where(
!error => error("Ambiguity", <id>)
; map({ descr, file, area :
?localized(descr, area-in-file(file, area))
; report-area(|"", "Ambiguity found", file, area)
; log(|Error(),"Alternatives are: ")
; <string-tokenize>([';'],descr)
; map(log(|Error(),<concat-strings>[" ",<id>]))
; log(|Error(),"")
})
)
/**
* Tools that can be used for reporting errors.
*/
strategies
report-file(|err, descr, file) =
log(|Error(),<concat-strings>[file, ": '", err, "': ", descr])
/**
* Presents the 'area' in the file at stderr.
*/
report-area(|err, descr, file, area) =
where(
!area => area(begin-line, begin-column, _, end-column, _, _)
);
let y-pos =
<dec> begin-line
; if <lt> (<id>, 0) then !0 else id end
x-pos =
<dec> begin-column => c
; if <lt> (c, 0) then !0 else id end
filename =
if !file => "-" then
!"stdin"
else
!file
end
print-location =
where(
log(|Error(),
<concat-strings> [
<filename> (), ": ", descr, " at line "
, <int-to-string> begin-line, ", column "
, <int-to-string> begin-column
])
)
print-context-in-file =
get-lines
; add-indices
; where(y-pos => y)
; if !y => 0 then
\ [line | _] -> [line] \
else
at-suffix(?[(y, _) | _]; ?context)
; !context
end
/**
* If there are 2 or more elements, drop the rest.
*/
; if ?[s1, s2 | _ ] then
![s1, s2]
end
; map(log(|Error(),<Snd>))
/**
* Indicate the position in the file
*/
; <conc-strings> (<copy-char> (<x-pos> (), ' '), "^")
; log(|Error(),<id>)
/**
* @type ? -> String
*/
read-input-file =
?FILE(<read-text-file>)
<+ is-string
in print-location
; if read-input-file => txt then
<print-context-in-file> txt
end
end