Debugging partial functions by the rules

Claus Reinke claus.reinke at talk21.com
Wed Nov 15 10:12:49 EST 2006


[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



More information about the Glasgow-haskell-users mailing list