
[deleted cc to haskell-cafe; RULES and discussion details are GHC-specific]
That's difficult. Trouble is, the assert expansion happens right at the front, before any desugaring or program transformation. But rewrite rules fire much, much later, in the simplifier.
and there doesn't seem to be any source location information left at that stage (no longer associated with the AST, but woven into error messages and the like) - what a pity. there may be other uses for having such information at hand in core expressions, but adding it just for the present purpose would be overkill (unless one could sneak it just into identifiers, perhaps?). but if one cannot define assert-like transformation using simplifier rules, one might still generalise assert-style transformations (there already are several of them in RnExpr.lhs; for assert and breakpoints).
The only solid way to connect to programmer-comprehensible stuff is by transforming the original, unadulterated source code, as Hat does, and as Jhc does, and as Simon and I are musing about doing.
so, will there be a general SYNTAX-RULES pragma, for an early-stage variant of RULES? {-# SYNTAX-RULES "assert" assert = assertError lhsSrcLoc #-} {-# SYNTAX-RULES "head" head = headError lhsSrcLoc #-}
Your idea is to do something cheap and cheerful, which is always a good plan. But I don't see how to make it fly.
if I understand your webpage correctly, there is a cheap and cheerful variant for the non-recursive SRC_LOC_ANNOTATE - just generalise the code in RnExpr.lhs to look not only for assertId, but for head, fromJust, etc, as well, applying the same transformation to all: <name> | <name> in ["assert","head",..] -> <name>Error <srcLoc> or, to avoid relying on built-ins: <name> | srcLocAnnotate <name>, isDefined <name>Error -> <name>Error <srcLoc> the recursive variant of SRC_LOC_ANNOTATE, on the other hand, seems to require maintaining a call chain context, and using that to augment the translation. which means keeping track of the local name for that context within the definitions of the Error variants, something like: bind <name>Error <srcLocName> | srcLocAnnotate <name> -> setCallers <srcLocName> <name> | srcLocAnnotate <name>, isDefined <name>Error -> do {localSrcLocName <- getCallers ; <name>Error (<srcLoc>++":"++localSrcLocName) } where one annotated name, when used inside the definition of another's Error version, is augmented by its own location and the context passed down (though one would also like to ensure that the localSrcLocName hasn't been shadowed between bind and use). being context-sensitive, this variant would not be within reach of a simple syntax transformation pragma, but might still be possible as an extension of the current renamer transformations? Is that what you have in mind? Sounds useful to me (though one might occasionally want to have access to just the current location, without context - suggesting perhaps a list/stack of strings rather than a pre-concatenated string). Claus