@alan_zimm
0x01, 001, 0_01
{-# Language CPP #-}
{-# LANGUAGE CPP #-}
foo xxx = let a = 1
b = 2
in xxx + a + b
foo xxxlonger = let a = 1
b = 2
in xxxlonger + a + b
ghc-exactprint
is still the library to programme againstghc-exactprint
changesLanguage.Haskell.Syntax
GHC.Hs
type ParsedSource = Located HsModule
type LHsExpr p = XRec p (HsExpr p)
type family XRec p a = r | r -> a
type instance XRec (GhcPass p) a = GenLocated (Anno a) a
type family Anno a = b
type instance Anno (HsExpr (GhcPass p)) = SrcSpanAnnA
Credit to Shayne Fletcher
- LHsExpr GhcPs
- XRec GhcPs (HsExpr GhcPs)
- GenLocated (Anno (HsExpr GhcPs)) (HsExpr GhcPs)
- GenLocated SrcSpanAnnA (HsExpr GhcPs)
- LocatedA (HsExpr GhcPs))
Expanding further we have
- GenLocated SrcSpanAnnA (HsExpr GhcPs)
- GenLocated (SrcAnn AnnListItem) (HsExpr GhcPs)
- GenLocated (SrcSpanAnn' (EpAnn AnnListItem)) (HsExpr GhcPs)
All is not lost.
A
is your friend
type instance Anno (HsExpr (GhcPass p)) = SrcSpanAnnA
type LocatedA = GenLocated SrcSpanAnnA
Located => LocatedA
getLoc => getLocA
noLoc => noLocA
locA -- get SrcSpan from GenLocated payload
setSrcSpan => setSrcSpanA
addLocM => addLocMA
data Annotation = Ann -- old ghc-exactprint type
{
-- interfacing up into the AST
annEntryDelta :: !DeltaPos
, annPriorComments :: ![(Comment, DeltaPos)]
, annFollowingComments :: ![(Comment, DeltaPos)]
-- interfacing down into the AST
, annsDP :: ![(KeywordId, DeltaPos)]
, annSortKey :: !(Maybe [GHC.RealSrcSpan])
}
data EpAnn ann
= EpAnn { entry :: Anchor
, anns :: ann
, comments :: EpAnnComments
}
| EpAnnNotUsed
data Anchor = Anchor { anchor :: RealSrcSpan
, anchor_op :: AnchorOperation }
data AnchorOperation = UnchangedAnchor
| MovedAnchor DeltaPos
newtype DeltaPos = DP (Int,Int)
data DeltaPos
= SameLine { deltaColumn :: !Int }
| DifferentLine
{ deltaLine :: !Int, -- ^ deltaLine should always be > 0
deltaColumn :: !Int
}
data EpaLocation = EpaSpan RealSrcSpan
| EpaDelta DeltaPos
| HsLet (XLet p)
(HsLocalBinds p)
(LHsExpr p)
type instance XLet GhcPs = EpAnn AnnsLet
data AnnsLet = AnnsLet { alLet :: EpaLocation,
alIn :: EpaLocation }
doAddLocal = do
(d1:d2:d3) <- hsDecls lp
balanceComments d1 d2
(d1',_) <- modifyValD (getLoc d1) d1 $ \_m d -> do
return ((newDecl : d),Nothing)
replaceDecls lp [d1', d2, d3]
doAddLocal = do
(de1:d2:d3:_) <- hsDecls lp
(de1'',d2') <- balanceComments de1 d2
(de1',_) <- modifyValD (getLocA de1'') de1'' $ \_m d -> do
return ((wrapDecl decl' : d),Nothing)
replaceDecls lp [de1', d2', d3]
https://gitlab.haskell.org/ghc/ghc/-/wikis/api-annotations https://github.com/alanz/ghc-exactprint/tree/ghc-9.2 https://blog.shaynefletcher.org/2021/05/annotations-in-ghc.html