packages feed

haskell-tools-ast-fromghc (empty) → 0.1.2.0

raw patch · 22 files changed

+2390/−0 lines, 22 filesdep +basedep +bytestringdep +containerssetup-changed

Dependencies added: base, bytestring, containers, ghc, haskell-tools-ast, mtl, references, safe, split, structural-traversal, template-haskell, uniplate

Files

+ LICENSE view
@@ -0,0 +1,29 @@+Haskell-Tools is Copyright (c) Boldizsár Németh, 2016, all rights reserved,
+and is distributed as free software under the following license.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+- Redistributions of source code must retain the above copyright
+notice, this list of conditions, and the following disclaimer.
+
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions, and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+- The names of the copyright holders may not be used to endorse or
+promote products derived from this software without specific prior
+written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS "AS IS" AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Language/Haskell/Tools/AST/FromGHC.hs view
@@ -0,0 +1,14 @@+-- | The FromGHC module provides a way to transform the GHC AST into our AST. This transformation is done in 
+-- the Ghc monad. The conversion can be performed from the Parsed and the Renamed GHC AST. If the renamed AST 
+-- is given, additional semantic information is looked up while traversing the AST. 
+module Language.Haskell.Tools.AST.FromGHC 
+  ( module Language.Haskell.Tools.AST.FromGHC.Modules
+  , module Language.Haskell.Tools.AST.FromGHC.Monad
+  , module Language.Haskell.Tools.AST.FromGHC.Base
+  , module Language.Haskell.Tools.AST.FromGHC.Utils
+  ) where
+
+import Language.Haskell.Tools.AST.FromGHC.Modules
+import Language.Haskell.Tools.AST.FromGHC.Monad
+import Language.Haskell.Tools.AST.FromGHC.Base
+import Language.Haskell.Tools.AST.FromGHC.Utils
+ Language/Haskell/Tools/AST/FromGHC/Base.hs view
@@ -0,0 +1,183 @@+{-# LANGUAGE LambdaCase
+           , TupleSections
+           , TypeFamilies
+           , FlexibleInstances
+           , FlexibleContexts
+           , TypeSynonymInstances
+           , ScopedTypeVariables
+           , MultiParamTypeClasses
+           , UndecidableInstances
+           , AllowAmbiguousTypes
+           , TypeApplications
+           #-}
+module Language.Haskell.Tools.AST.FromGHC.Base where
+
+import Control.Monad.Reader
+import Data.List.Split
+import Data.Char
+import qualified Data.ByteString.Char8 as BS
+
+import Control.Reference hiding (element)
+
+import HsSyn as GHC
+import Module as GHC
+import RdrName as GHC
+import Id as GHC
+import Name as GHC hiding (Name, occName)
+import qualified Name as GHC (Name)
+import Outputable as GHC
+import SrcLoc as GHC
+import BasicTypes as GHC
+import FastString as GHC
+import ApiAnnotation as GHC
+import ForeignCall as GHC
+import CoAxiom as GHC
+import Bag as GHC
+import Data.Data (Data)
+
+import Language.Haskell.Tools.AST (Ann(..), AnnList(..), AnnMaybe(..), SemanticInfo(..), annotation, semanticInfo)
+import qualified Language.Haskell.Tools.AST as AST
+
+import Language.Haskell.Tools.AST.FromGHC.Monad
+import Language.Haskell.Tools.AST.FromGHC.Utils
+import Language.Haskell.Tools.AST.FromGHC.GHCUtils
+
+trfOperator :: TransformName name res => Located name -> Trf (Ann AST.Operator res)
+trfOperator = trfLoc trfOperator'
+
+trfOperator' :: TransformName name res => name -> Trf (AST.Operator res)
+trfOperator' n
+  | isSymOcc (occName n) = AST.NormalOp <$> (addNameInfo n =<< annCont (trfSimpleName' n))
+  | otherwise = AST.BacktickOp <$> (addNameInfo n =<< annLoc loc (trfSimpleName' n))
+     where loc = mkSrcSpan <$> (updateCol (+1) <$> atTheStart) <*> (updateCol (subtract 1) <$> atTheEnd)
+
+trfName :: TransformName name res => Located name -> Trf (Ann AST.Name res)
+trfName = trfLoc trfName'
+
+trfName' :: TransformName name res => name -> Trf (AST.Name res)
+trfName' n
+  | isSymOcc (occName n) = AST.ParenName <$> (addNameInfo n =<< annLoc loc (trfSimpleName' n))
+  | otherwise = AST.NormalName <$> (addNameInfo n =<< annCont (trfSimpleName' n))
+     where loc = mkSrcSpan <$> (updateCol (+1) <$> atTheStart) <*> (updateCol (subtract 1) <$> atTheEnd)
+
+trfAmbiguousFieldName :: TransformName n res => Located (AmbiguousFieldOcc n) -> Trf (Ann AST.Name res)
+trfAmbiguousFieldName all@(L l af) = trfAmbiguousFieldName' l af
+
+trfAmbiguousFieldName' :: forall n res . (TransformName n res) => SrcSpan -> AmbiguousFieldOcc n -> Trf (Ann AST.Name res)
+trfAmbiguousFieldName' l (Unambiguous (L _ rdr) pr) = annLoc (pure l) $ trfName' (unpackPostRn @n rdr pr)
+-- no Id transformation is done, so we can basically ignore the postTC value
+trfAmbiguousFieldName' _ (Ambiguous (L l rdr) _) 
+  = do locals <- asks localsInScope
+       isDefining <- asks defining
+       annLoc (pure l) 
+         $ AST.NormalName 
+         <$> (annotation .- addSemanticInfo (AmbiguousNameInfo locals isDefining rdr l :: SemanticInfo n)) 
+         <$> (annLoc (pure l) $ AST.nameFromList <$> trfNameStr (rdrNameStr rdr))
+
+class (DataId n, Eq n, GHCName n) => TransformableName n where
+  correctNameString :: n -> Trf String
+
+instance TransformableName RdrName where
+  correctNameString = pure . rdrNameStr
+
+instance TransformableName GHC.Name where
+  correctNameString n = getOriginalName (rdrName n)
+
+
+-- | This class allows us to use the same transformation code for multiple variants of the GHC AST.
+-- GHC Name annotated with 'name' can be transformed to our representation with semantic annotations of 'res'.
+class (RangeAnnot res, SemanticAnnot res name, SemanticAnnot res GHC.Name, TransformableName name, HsHasName name) 
+        => TransformName name res where
+instance TransformName RdrName AST.RangeInfo where
+instance (RangeAnnot r, SemanticAnnot r GHC.Name) => TransformName GHC.Name r where
+
+addNameInfo :: TransformName n r => n -> Ann AST.SimpleName r -> Trf (Ann AST.SimpleName r)
+addNameInfo name ast = do locals <- asks localsInScope
+                          isDefining <- asks defining
+                          return (annotation .- addSemanticInfo (NameInfo locals isDefining name) $ ast)
+
+trfSimpleName :: TransformName name res => Located name -> Trf (Ann AST.SimpleName res)
+trfSimpleName name@(L l n) = addNameInfo n =<< annLoc (pure l) (trfSimpleName' n)
+
+trfSimpleName' :: TransformName name res => name -> Trf (AST.SimpleName res)
+trfSimpleName' n = AST.nameFromList <$> (trfNameStr =<< correctNameString n)
+
+-- | Creates a qualified name from a name string
+trfNameStr :: RangeAnnot a => String -> Trf (AnnList AST.UnqualName a)
+trfNameStr str = (\loc -> AnnList (toListAnnot "" "" "." loc) $ trfNameStr' str loc) <$> atTheStart
+
+trfNameStr' :: RangeAnnot a => String -> SrcLoc -> [Ann AST.UnqualName a]
+trfNameStr' str srcLoc = fst $
+  foldl (\(r,loc) np -> let nextLoc = advanceAllSrcLoc loc np
+                         in ( r ++ [Ann (toNodeAnnot $ mkSrcSpan loc nextLoc) (AST.UnqualName np)], advanceAllSrcLoc nextLoc "." ) ) 
+  ([], srcLoc) (nameParts str)
+  where -- | Move the source location according to a string
+        advanceAllSrcLoc :: SrcLoc -> String -> SrcLoc
+        advanceAllSrcLoc (RealSrcLoc rl) str = RealSrcLoc $ foldl advanceSrcLoc rl str
+        advanceAllSrcLoc oth _ = oth
+
+        -- | Break up a name into parts, but take care for operators
+        nameParts :: String -> [String]
+        nameParts = nameParts' ""
+
+        nameParts' :: String -> String -> [String]
+        nameParts' carry (c : rest) | isLetter c || isDigit c || c == '\'' || c == '_' || c == '#'
+                                    = nameParts' (c:carry) rest
+        nameParts' carry@(_:_) ('.' : rest) = reverse carry : nameParts rest
+        nameParts' "" rest = [rest] 
+        nameParts' carry [] = [reverse carry]
+        nameParts' carry str = error $ "nameParts': " ++ show carry ++ " " ++ show str
+  
+trfModuleName :: RangeAnnot a => Located ModuleName -> Trf (Ann AST.SimpleName a)
+trfModuleName = trfLoc trfModuleName'
+
+trfModuleName' :: RangeAnnot a => ModuleName -> Trf (AST.SimpleName a)
+trfModuleName' = (AST.nameFromList <$>) . trfNameStr . moduleNameString
+
+trfFastString :: RangeAnnot a => Located FastString -> Trf (Ann AST.StringNode a)
+trfFastString = trfLoc $ pure . AST.StringNode . unpackFS
+  
+trfDataKeyword :: RangeAnnot a => NewOrData -> Trf (Ann AST.DataOrNewtypeKeyword a)
+trfDataKeyword NewType = annLoc (tokenLoc AnnNewtype) (pure AST.NewtypeKeyword)
+trfDataKeyword DataType = annLoc (tokenLoc AnnData) (pure AST.DataKeyword)
+     
+trfCallConv :: RangeAnnot a => Located CCallConv -> Trf (Ann AST.CallConv a)
+trfCallConv = trfLoc trfCallConv'
+   
+trfCallConv' :: RangeAnnot a => CCallConv -> Trf (AST.CallConv a)
+trfCallConv' CCallConv = pure AST.CCall
+trfCallConv' CApiConv = pure AST.CApi
+trfCallConv' StdCallConv = pure AST.StdCall
+-- trfCallConv' PrimCallConv = 
+trfCallConv' JavaScriptCallConv = pure AST.JavaScript
+
+trfSafety :: RangeAnnot a => SrcSpan -> Located Safety -> Trf (AnnMaybe AST.Safety a)
+trfSafety ccLoc lsaf@(L l _) | isGoodSrcSpan l 
+  = makeJust <$> trfLoc (pure . \case
+      PlaySafe -> AST.Safe
+      PlayInterruptible -> AST.Interruptible
+      PlayRisky -> AST.Unsafe) lsaf
+  | otherwise = nothing " " "" (pure $ srcSpanEnd ccLoc)
+
+trfOverlap :: RangeAnnot a => Located OverlapMode -> Trf (Ann AST.OverlapPragma a)
+trfOverlap = trfLoc $ pure . \case
+  NoOverlap _ -> AST.DisableOverlap
+  Overlappable _ -> AST.Overlappable
+  Overlapping _ -> AST.Overlapping
+  Overlaps _ -> AST.Overlaps
+  Incoherent _ -> AST.IncoherentOverlap
+
+trfRole :: RangeAnnot a => Located (Maybe Role) -> Trf (Ann AST.Role a)
+trfRole = trfLoc $ \case Just Nominal -> pure AST.Nominal
+                         Just Representational -> pure AST.Representational
+                         Just GHC.Phantom -> pure AST.Phantom
+         
+trfPhase :: RangeAnnot a => Trf SrcLoc -> Activation -> Trf (AnnMaybe AST.PhaseControl a)
+trfPhase l AlwaysActive = nothing "" " " l
+trfPhase _ (ActiveAfter _ pn) = makeJust <$> annLoc (combineSrcSpans <$> tokenLoc AnnOpenS <*> tokenLoc AnnCloseS) 
+                                                    (AST.PhaseControl <$> nothing "" "" (before AnnCloseS) <*> trfPhaseNum pn)
+trfPhase _ (ActiveBefore _ pn) = makeJust <$> annLoc (combineSrcSpans <$> tokenLoc AnnOpenS <*> tokenLoc AnnCloseS)
+                                                     (AST.PhaseControl <$> (makeJust <$> annLoc (tokenLoc AnnTilde) (pure AST.PhaseInvert)) <*> trfPhaseNum pn)
+
+trfPhaseNum :: RangeAnnot a => PhaseNum -> Trf (Ann AST.PhaseNumber a)
+trfPhaseNum i = annLoc (tokenLoc AnnVal) $ pure (AST.PhaseNumber $ fromIntegral i) 
+ Language/Haskell/Tools/AST/FromGHC/Binds.hs view
@@ -0,0 +1,154 @@+{-# LANGUAGE LambdaCase
+           , ViewPatterns
+           #-}
+module Language.Haskell.Tools.AST.FromGHC.Binds where
+
+import Control.Monad.Reader
+
+import SrcLoc as GHC
+import RdrName as GHC
+import HsBinds as GHC
+import HsExpr as GHC
+import BasicTypes as GHC
+import ApiAnnotation as GHC
+import Bag as GHC
+import Outputable as GHC
+import HsPat as GHC
+import HsDecls as GHC
+import HsTypes as GHC
+import OccName as GHC
+import Name as GHC
+import BooleanFormula as GHC
+
+import Data.List
+
+import Language.Haskell.Tools.AST.FromGHC.Base
+import Language.Haskell.Tools.AST.FromGHC.Exprs
+import Language.Haskell.Tools.AST.FromGHC.Patterns
+import Language.Haskell.Tools.AST.FromGHC.Types
+import Language.Haskell.Tools.AST.FromGHC.Kinds
+import Language.Haskell.Tools.AST.FromGHC.Monad
+import Language.Haskell.Tools.AST.FromGHC.Utils
+import Language.Haskell.Tools.AST.FromGHC.GHCUtils
+
+import Language.Haskell.Tools.AST (Ann(..), AnnMaybe(..), AnnList(..))
+import qualified Language.Haskell.Tools.AST as AST
+
+trfBind :: TransformName n r => Located (HsBind n) -> Trf (Ann AST.ValueBind r)
+trfBind = trfLoc trfBind'
+  
+trfBind' :: TransformName n r => HsBind n -> Trf (AST.ValueBind r)
+-- a value binding (not a function)
+trfBind' (FunBind { fun_id = id, fun_matches = MG { mg_alts = unLoc -> [L matchLoc (Match { m_pats = [], m_grhss = GRHSs [L rhsLoc (GRHS [] expr)] (unLoc -> locals) })]} }) 
+  = AST.SimpleBind <$> copyAnnot AST.VarPat (define $ trfName id)
+                   <*> addToScope locals (annLoc (combineSrcSpans (getLoc expr) <$> tokenLoc AnnEqual) (AST.UnguardedRhs <$> trfExpr expr))
+                   <*> addToScope locals (trfWhereLocalBinds locals)
+trfBind' (FunBind id (MG (unLoc -> matches) _ _ _) _ _ _) = AST.FunBind <$> makeNonemptyIndentedList (mapM (trfMatch (unLoc id)) matches)
+trfBind' (PatBind pat (GRHSs rhs (unLoc -> locals)) _ _ _) = AST.SimpleBind <$> trfPattern pat <*> trfRhss rhs <*> trfWhereLocalBinds locals
+trfBind' (AbsBinds _ _ _ _ _) = error "AbsBinds are not allowed as an input to the conversion (they are generated by the type checker)"
+trfBind' (PatSynBind _) = error "Pattern synonym bindings should be recognized on the declaration level"
+
+trfMatch :: TransformName n r => n -> Located (Match n (LHsExpr n)) -> Trf (Ann AST.Match r)
+trfMatch id = trfLoc (trfMatch' id)
+
+trfMatch' :: TransformName n r => n -> Match n (LHsExpr n) -> Trf (AST.Match r)
+trfMatch' name (Match funid pats typ (GRHSs rhss (unLoc -> locBinds)))
+  -- TODO: add the optional typ to pats
+  = AST.Match <$> trfMatchLhs name funid pats
+              <*> addToScope pats (trfRhss rhss)
+              <*> addToScope pats (trfWhereLocalBinds locBinds)
+
+trfMatchLhs :: TransformName n r => n -> MatchFixity n -> [LPat n] -> Trf (Ann AST.MatchLhs r)
+trfMatchLhs name fb pats 
+  = do implicitIdLoc <- mkSrcSpan <$> atTheStart <*> atTheStart
+       closeLoc <- srcSpanStart <$> (combineSrcSpans <$> tokenLoc AnnEqual <*> tokenLoc AnnVbar)
+       let (n, isInfix) = case fb of NonFunBindMatch -> (L implicitIdLoc name, False)
+                                     FunBindMatch n inf -> (n, inf)
+       args <- mapM trfPattern pats
+       annLoc (mkSrcSpan <$> atTheStart <*> (pure closeLoc)) $
+         case (args, isInfix) of 
+            (left:right:rest, True) -> AST.InfixLhs left <$> define (trfOperator n) <*> pure right <*> makeList " " (pure closeLoc) (pure rest)
+            _                       -> AST.NormalLhs <$> define (trfName n) <*> makeList " " (pure closeLoc) (pure args)
+
+trfRhss :: TransformName n r => [Located (GRHS n (LHsExpr n))] -> Trf (Ann AST.Rhs r)
+-- the original location on the GRHS misleadingly contains the local bindings
+trfRhss [unLoc -> GRHS [] body] = annLoc (combineSrcSpans (getLoc body) <$> tokenBefore (srcSpanStart $ getLoc body) AnnEqual) 
+                                         (AST.UnguardedRhs <$> trfExpr body)
+trfRhss rhss = annLoc (pure $ collectLocs rhss) 
+                      (AST.GuardedRhss . nonemptyAnnList <$> mapM trfGuardedRhs rhss)
+                      
+trfGuardedRhs :: TransformName n r => Located (GRHS n (LHsExpr n)) -> Trf (Ann AST.GuardedRhs r)
+trfGuardedRhs = trfLoc $ \(GRHS guards body) 
+  -> AST.GuardedRhs . nonemptyAnnList <$> trfScopedSequence trfRhsGuard guards <*> addToScope guards (trfExpr body)
+  
+trfRhsGuard :: TransformName n r => Located (Stmt n (LHsExpr n)) -> Trf (Ann AST.RhsGuard r)
+trfRhsGuard = trfLoc trfRhsGuard'
+  
+trfRhsGuard' :: TransformName n r => Stmt n (LHsExpr n) -> Trf (AST.RhsGuard r)
+trfRhsGuard' (BindStmt pat body _ _ _) = AST.GuardBind <$> trfPattern pat <*> trfExpr body
+trfRhsGuard' (BodyStmt body _ _ _) = AST.GuardCheck <$> trfExpr body
+trfRhsGuard' (LetStmt (unLoc -> binds)) = AST.GuardLet <$> trfLocalBinds binds
+  
+trfWhereLocalBinds :: TransformName n r => HsLocalBinds n -> Trf (AnnMaybe AST.LocalBinds r)
+trfWhereLocalBinds EmptyLocalBinds = nothing "" "" atTheEnd
+trfWhereLocalBinds binds
+  = makeJust <$> annLoc (combineSrcSpans (getBindLocs binds) <$> tokenLoc AnnWhere) (AST.LocalBinds <$> addToScope binds (trfLocalBinds binds))
+
+getBindLocs :: HsLocalBinds n -> SrcSpan
+getBindLocs (HsValBinds (ValBindsIn binds sigs)) = foldLocs $ map getLoc (bagToList binds) ++ map getLoc sigs
+getBindLocs (HsValBinds (ValBindsOut binds sigs)) = foldLocs $ map getLoc (concatMap (bagToList . snd) binds) ++ map getLoc sigs
+  
+trfLocalBinds :: TransformName n r => HsLocalBinds n -> Trf (AnnList AST.LocalBind r)
+trfLocalBinds (HsValBinds (ValBindsIn binds sigs)) 
+  = makeIndentedList (after AnnWhere)
+      (orderDefs <$> ((++) <$> mapM (copyAnnot AST.LocalValBind . trfBind) (bagToList binds) 
+                           <*> mapM trfLocalSig sigs))
+trfLocalBinds (HsValBinds (ValBindsOut binds sigs)) 
+  = makeIndentedList (after AnnWhere)
+      (orderDefs <$> ((++) <$> (concat <$> mapM (mapM (copyAnnot AST.LocalValBind . trfBind) . bagToList . snd) binds)
+                           <*> mapM trfLocalSig sigs))
+             
+trfLocalSig :: TransformName n r => Located (Sig n) -> Trf (Ann AST.LocalBind r)
+trfLocalSig = trfLoc $ \case
+  ts@(TypeSig {}) -> AST.LocalSignature <$> annCont (trfTypeSig' ts)
+  (FixSig fs) -> AST.LocalFixity <$> annCont (trfFixitySig fs)
+  
+trfTypeSig :: TransformName n r => Located (Sig n) -> Trf (Ann AST.TypeSignature r)
+trfTypeSig = trfLoc trfTypeSig'
+
+trfTypeSig' :: TransformName n r => Sig n -> Trf (AST.TypeSignature r)
+trfTypeSig' (TypeSig names typ) 
+  = defineTypeVars $ AST.TypeSignature <$> makeNonemptyList ", " (mapM trfName names) <*> trfType (hswc_body $ hsib_body typ)
+  
+trfFixitySig :: TransformName n r => FixitySig n -> Trf (AST.FixitySignature r)
+trfFixitySig (FixitySig names (Fixity _ prec dir)) 
+  = AST.FixitySignature <$> transformDir dir
+                        <*> annLoc (tokenLoc AnnVal) (pure $ AST.Precedence prec) 
+                        <*> (nonemptyAnnList . nub <$> mapM trfOperator names)
+  where transformDir InfixL = directionChar (pure AST.AssocLeft)
+        transformDir InfixR = directionChar (pure AST.AssocRight)
+        transformDir InfixN = annLoc (srcLocSpan . srcSpanEnd <$> tokenLoc AnnInfix) (pure AST.AssocNone)
+        
+        directionChar = annLoc ((\l -> mkSrcSpan (updateCol (subtract 1) l) l) . srcSpanEnd <$> tokenLoc AnnInfix)
+   
+trfRewriteRule :: TransformName n r => Located (RuleDecl n) -> Trf (Ann AST.Rule r)
+trfRewriteRule = trfLoc $ \(HsRule (L nameLoc (_, ruleName)) act bndrs left _ right _) ->
+  AST.Rule <$> trfFastString (L nameLoc ruleName) 
+           <*> trfPhase (before AnnForall) act
+           <*> makeNonemptyList " " (mapM trfRuleBndr bndrs)
+           <*> trfExpr left
+           <*> trfExpr right
+
+trfRuleBndr :: TransformName n r =>  Located (RuleBndr n) -> Trf (Ann AST.TyVar r)
+trfRuleBndr = trfLoc $ \case (RuleBndr n) -> AST.TyVarDecl <$> trfName n <*> nothing " " "" atTheEnd
+                             (RuleBndrSig n k) -> AST.TyVarDecl <$> trfName n <*> (makeJust <$> (trfKindSig' (hswc_body $ hsib_body k)))
+
+trfMinimalFormula :: TransformName n r => Located (BooleanFormula (Located n)) -> Trf (Ann AST.MinimalFormula r)
+trfMinimalFormula = trfLoc trfMinimalFormula'
+
+trfMinimalFormula' :: TransformName n r => BooleanFormula (Located n) -> Trf (AST.MinimalFormula r)
+trfMinimalFormula' (Var name) = AST.MinimalName <$> trfName name
+trfMinimalFormula' (And formulas) = AST.MinimalAnd <$> trfAnnList " & " trfMinimalFormula' formulas
+trfMinimalFormula' (Or formulas) = AST.MinimalOr <$> trfAnnList " | " trfMinimalFormula' formulas
+trfMinimalFormula' (Parens formula) = AST.MinimalParen <$> trfMinimalFormula formula
+
+ Language/Haskell/Tools/AST/FromGHC/Binds.hs-boot view
@@ -0,0 +1,17 @@+module Language.Haskell.Tools.AST.FromGHC.Binds where
+
+import Outputable as GHC
+import RdrName as GHC
+import SrcLoc as GHC
+import HsBinds as GHC
+import HsExpr as GHC
+import Language.Haskell.Tools.AST.FromGHC.Monad
+import Language.Haskell.Tools.AST.FromGHC.Utils
+import Language.Haskell.Tools.AST.FromGHC.Base
+import Language.Haskell.Tools.AST (Ann(..), AnnMaybe(..), AnnList(..))
+import qualified Language.Haskell.Tools.AST as AST
+
+trfLocalBinds :: TransformName n r => HsLocalBinds n -> Trf (AnnList AST.LocalBind r)
+trfWhereLocalBinds :: TransformName n r => HsLocalBinds n -> Trf (AnnMaybe AST.LocalBinds r)
+trfRhsGuard :: TransformName n r => Located (Stmt n (LHsExpr n)) -> Trf (Ann AST.RhsGuard r)
+trfRhsGuard' :: TransformName n r => Stmt n (LHsExpr n) -> Trf (AST.RhsGuard r)
+ Language/Haskell/Tools/AST/FromGHC/Decls.hs view
@@ -0,0 +1,424 @@+{-# LANGUAGE LambdaCase 
+           , ViewPatterns
+           , ScopedTypeVariables
+           #-}
+module Language.Haskell.Tools.AST.FromGHC.Decls where
+
+import RdrName as GHC
+import Class as GHC
+import HsSyn as GHC
+import SrcLoc as GHC
+import HsDecls as GHC
+import Name as GHC
+import OccName as GHC
+import ApiAnnotation as GHC
+import FastString as GHC
+import BasicTypes as GHC
+import Bag as GHC
+import ForeignCall as GHC
+import Outputable as GHC
+
+import Control.Monad.Reader
+import Control.Reference
+import Data.Maybe
+import Data.Data (toConstr)
+import Data.Generics.Uniplate.Data
+
+import Language.Haskell.Tools.AST.FromGHC.GHCUtils
+import Language.Haskell.Tools.AST.FromGHC.Base
+import Language.Haskell.Tools.AST.FromGHC.Kinds
+import Language.Haskell.Tools.AST.FromGHC.Types
+import Language.Haskell.Tools.AST.FromGHC.Exprs
+import Language.Haskell.Tools.AST.FromGHC.Patterns
+import {-# SOURCE #-} Language.Haskell.Tools.AST.FromGHC.TH
+import Language.Haskell.Tools.AST.FromGHC.Binds
+import Language.Haskell.Tools.AST.FromGHC.Monad
+import Language.Haskell.Tools.AST.FromGHC.Utils
+
+import Language.Haskell.Tools.AST (Ann(..), AnnMaybe(..), AnnList(..), RangeWithName, getRange)
+import qualified Language.Haskell.Tools.AST as AST
+
+import Debug.Trace
+
+trfDecls :: TransformName n r => [LHsDecl n] -> Trf (AnnList AST.Decl r)
+-- TODO: filter documentation comments
+trfDecls decls = addToScope decls $ makeIndentedListNewlineBefore atTheEnd (mapM trfDecl decls)
+
+trfDeclsGroup :: forall n r . TransformName n r => HsGroup n -> Trf (AnnList AST.Decl r)
+trfDeclsGroup (HsGroup vals splices tycls insts derivs fixities defaults foreigns warns anns rules vects docs) 
+  = addAllToScope $ makeIndentedListNewlineBefore atTheEnd (fmap (orderDefs . concat) $ sequence $
+      [ trfBindOrSig vals
+      , concat <$> mapM (mapM (trfDecl . (fmap TyClD)) . group_tyclds) tycls
+      , mapM (trfDecl . (fmap SpliceD)) splices
+      , mapM (trfDecl . (fmap InstD)) insts
+      , mapM (trfDecl . (fmap DerivD)) derivs
+      , mapM (trfDecl . (fmap (SigD . FixSig))) (mergeFixityDefs fixities)
+      , mapM (trfDecl . (fmap DefD)) defaults
+      , mapM (trfDecl . (fmap ForD)) foreigns
+      , mapM (trfDecl . (fmap WarningD)) warns
+      , mapM (trfDecl . (fmap AnnD)) anns
+      , mapM (trfDecl . (fmap RuleD)) rules
+      , mapM (trfDecl . (fmap VectD)) vects
+      -- , mapM (trfDecl . (fmap DocD)) docs
+      ])
+  where trfBindOrSig :: HsValBinds n -> Trf [Ann AST.Decl r]
+        trfBindOrSig (getBindsAndSigs -> (sigs, binds))
+          = (++) <$> mapM (trfLoc trfVal) (bagToList binds)
+                 <*> mapM (trfLoc trfSig) sigs
+        addAllToScope = addToCurrentScope vals . addToCurrentScope tycls . addToCurrentScope foreigns
+           
+           
+trfDecl :: TransformName n r => Located (HsDecl n) -> Trf (Ann AST.Decl r)
+trfDecl = trfLoc $ \case
+  TyClD (FamDecl (FamilyDecl (ClosedTypeFamily typeEqs) name tyVars kindSig _)) 
+    -> AST.ClosedTypeFamilyDecl <$> focusAfter AnnType (createDeclHead name tyVars) 
+                                <*> trfFamilyKind kindSig 
+                                <*> trfTypeEqs typeEqs
+  TyClD (FamDecl fd) -> AST.TypeFamilyDecl <$> annCont (trfTypeFam' fd)
+  TyClD (SynDecl name vars rhs _) 
+    -> AST.TypeDecl <$> between AnnType AnnEqual (createDeclHead name vars) <*> trfType rhs
+  TyClD (DataDecl name vars (HsDataDefn nd ctx _ kind cons derivs) _ _) 
+    -> do let ctxTok = case nd of DataType -> AnnData
+                                  NewType -> AnnNewtype
+              consLoc = focusBeforeIfPresent AnnDeriving atTheEnd
+          whereLoc <- tokenLoc AnnWhere
+          if isGoodSrcSpan whereLoc then trfGADT nd name vars ctx kind cons derivs ctxTok consLoc
+                                    else trfDataDef nd name vars ctx cons derivs ctxTok consLoc
+  TyClD (ClassDecl ctx name vars funDeps sigs defs typeFuns typeFunDefs docs _) 
+    -> AST.ClassDecl <$> trfCtx (after AnnClass) ctx 
+                     <*> betweenIfPresent AnnClass AnnWhere (createDeclHead name vars)
+                     <*> trfFunDeps funDeps 
+                     <*> createClassBody sigs defs typeFuns typeFunDefs
+  InstD (ClsInstD (ClsInstDecl typ binds sigs typefam datafam overlap))
+    -> AST.InstDecl <$> trfMaybeDefault " " "" trfOverlap (after AnnInstance) overlap 
+                    <*> trfInstanceRule (hsib_body typ)
+                    <*> trfInstBody binds sigs typefam datafam
+  InstD (DataFamInstD (DataFamInstDecl con pats (HsDataDefn nd _ _ _ cons derivs) _))
+    -> AST.DataInstDecl <$> trfDataKeyword nd
+                        <*> between AnnInstance AnnEqual (makeInstanceRuleTyVars con pats)
+                        <*> makeList " | " (after AnnEqual) (mapM trfConDecl cons)
+                        <*> trfMaybe "" "" trfDerivings derivs
+  InstD (TyFamInstD (TyFamInstDecl (L l (TyFamEqn con pats rhs)) _))
+    -> AST.TypeInstDecl <$> between AnnInstance AnnEqual (makeInstanceRuleTyVars con pats) <*> trfType rhs
+  ValD bind -> trfVal bind
+  SigD sig -> trfSig sig
+  DerivD (DerivDecl t overlap) -> AST.DerivDecl <$> trfMaybe "" "" trfOverlap overlap <*> trfInstanceRule (hsib_body t)
+  -- TODO: INLINE, SPECIALIZE, MINIMAL, VECTORISE pragmas, Warnings, Annotations, rewrite rules, role annotations
+  RuleD (HsRules _ rules) -> AST.PragmaDecl <$> annCont (AST.RulePragma <$> makeIndentedList (before AnnClose) (mapM trfRewriteRule rules))
+  RoleAnnotD (RoleAnnotDecl name roles) -> AST.RoleDecl <$> trfSimpleName name <*> makeList " " atTheEnd (mapM trfRole roles)
+  DefD (DefaultDecl types) -> AST.DefaultDecl . nonemptyAnnList <$> mapM trfType types
+  ForD (ForeignImport name (hsib_body -> typ) _ (CImport ccall safe _ _ _)) 
+    -> AST.ForeignImport <$> trfCallConv ccall <*> trfSafety (getLoc ccall) safe <*> define (trfName name) <*> trfType typ
+  ForD (ForeignExport name (hsib_body -> typ) _ (CExport (L l (CExportStatic _ _ ccall)) _)) 
+    -> AST.ForeignExport <$> annLoc (pure l) (trfCallConv' ccall) <*> trfName name <*> trfType typ
+  SpliceD (SpliceDecl (unLoc -> spl) _) -> AST.SpliceDecl <$> (annCont $ trfSplice' spl)
+  AnnD (HsAnnotation stxt subject expr) 
+    -> AST.PragmaDecl <$> annCont (AST.AnnPragma <$> trfAnnotationSubject stxt subject (srcSpanStart $ getLoc expr) <*> trfExpr expr)
+  d -> error ("Illegal declaration: " ++ showSDocUnsafe (ppr d) ++ " (ctor: " ++ show (toConstr d) ++ ")")
+
+trfGADT :: TransformName n r => NewOrData -> Located n -> LHsQTyVars n -> Located (HsContext n) 
+                                 -> Maybe (Located (HsKind n)) -> [Located (ConDecl n)] 
+                                 -> Maybe (Located [LHsSigType n]) -> AnnKeywordId -> Trf SrcLoc -> Trf (AST.Decl r)
+trfGADT nd name vars ctx kind cons derivs ctxTok consLoc
+  = AST.GDataDecl <$> trfDataKeyword nd
+                  <*> trfCtx (after ctxTok) ctx
+                  <*> betweenIfPresent ctxTok AnnEqual (createDeclHead name vars)
+                  <*> trfKindSig kind
+                  <*> makeIndentedListBefore " where " consLoc (mapM trfGADTConDecl cons)
+                  <*> trfMaybe "" "" trfDerivings derivs
+
+trfDataDef :: TransformName n r => NewOrData -> Located n -> LHsQTyVars n -> Located (HsContext n) 
+                                     -> [Located (ConDecl n)] -> Maybe (Located [LHsSigType n]) 
+                                     -> AnnKeywordId -> Trf SrcLoc -> Trf (AST.Decl r)
+trfDataDef nd name vars ctx cons derivs ctxTok consLoc
+  = AST.DataDecl <$> trfDataKeyword nd
+                 <*> trfCtx (after ctxTok) ctx
+                 <*> betweenIfPresent ctxTok AnnEqual (createDeclHead name vars)
+                 <*> makeListBefore "=" " | " consLoc (mapM trfConDecl cons)
+                 <*> trfMaybe "" "" trfDerivings derivs
+
+trfVal :: TransformName n r => HsBindLR n n -> Trf (AST.Decl r)
+trfVal (PatSynBind psb) = AST.PatternSynonymDecl <$> annCont (trfPatternSynonym psb)
+trfVal bind = AST.ValueBinding <$> (annCont $ trfBind' bind)
+
+trfSig :: TransformName n r => Sig n -> Trf (AST.Decl r)
+trfSig (ts @ (TypeSig {})) = AST.TypeSigDecl <$> defineTypeVars (annCont $ trfTypeSig' ts)
+trfSig (FixSig fs) = AST.FixityDecl <$> (annCont $ trfFixitySig fs)
+trfSig (PatSynSig id typ) 
+  = AST.PatTypeSigDecl <$> annCont (AST.PatternTypeSignature <$> trfName id <*> trfType (hsib_body typ))
+trfSig (InlineSig name (InlinePragma _ Inlinable _ phase _)) 
+  = AST.PragmaDecl <$> annCont (AST.InlinablePragma <$> trfPhase (pure $ srcSpanStart $ getLoc name) phase <*> trfName name)
+trfSig (InlineSig name (InlinePragma src inl _ phase cl)) 
+  = do rng <- asks contRange
+       let parts = map getLoc $ splitLocated (L rng src)
+       AST.PragmaDecl <$> annCont ((case inl of Inline -> AST.InlinePragma; NoInline -> AST.NoInlinePragma) 
+                                     <$> trfConlike parts cl 
+                                     <*> trfPhase (pure $ srcSpanStart (getLoc name)) phase 
+                                     <*> trfName name)
+trfSig (SpecSig name (map hsib_body -> types) (inl_act -> phase)) 
+  = AST.PragmaDecl <$> annCont (AST.SpecializePragma <$> trfPhase (pure $ srcSpanStart (getLoc name)) phase 
+                                                     <*> trfName name 
+                                                     <*> (orderAnnList <$> trfAnnList ", " trfType' types))
+trfSig s = error ("Illegal signature: " ++ showSDocUnsafe (ppr s) ++ " (ctor: " ++ show (toConstr s) ++ ")")
+
+trfConlike :: RangeAnnot a => [SrcSpan] -> RuleMatchInfo -> Trf (AnnMaybe AST.ConlikeAnnot a)
+trfConlike parts ConLike = makeJust <$> annLoc (pure $ parts !! 2) (pure AST.ConlikeAnnot)
+trfConlike parts FunLike = nothing " " "" (pure $ srcSpanEnd $ parts !! 1)
+
+trfConDecl :: TransformName n r => Located (ConDecl n) -> Trf (Ann AST.ConDecl r)
+trfConDecl = trfLoc trfConDecl'
+
+trfConDecl' :: TransformName n r => ConDecl n -> Trf (AST.ConDecl r)
+trfConDecl' (ConDeclH98 { con_name = name, con_details = PrefixCon args })
+  = AST.ConDecl <$> define (trfName name) <*> makeList " " atTheEnd (mapM trfType args)
+trfConDecl' (ConDeclH98 { con_name = name, con_details = RecCon (unLoc -> flds) })
+  = AST.RecordDecl <$> define (trfName name) <*> (between AnnOpenC AnnCloseC $ trfAnnList ", " trfFieldDecl' flds)
+trfConDecl' (ConDeclH98 { con_name = name, con_details = InfixCon t1 t2 })
+  = AST.InfixConDecl <$> trfType t1 <*> define (trfOperator name) <*> trfType t2
+
+trfGADTConDecl :: TransformName n r => Located (ConDecl n) -> Trf (Ann AST.GadtConDecl r)
+trfGADTConDecl = trfLoc $ \(ConDeclGADT { con_names = names, con_type = hsib_body -> typ })
+  -> AST.GadtConDecl <$> define (trfAnnList ", " trfName' names) 
+                     <*> trfGadtConType typ
+
+trfGadtConType :: TransformName n r => Located (HsType n) -> Trf (Ann AST.GadtConType r)
+trfGadtConType = trfLoc $ \case 
+  HsFunTy (cleanHsType . unLoc -> HsRecTy flds) resType 
+    -> AST.GadtRecordType <$> between AnnOpenC AnnCloseC (trfAnnList ", " trfFieldDecl' flds) 
+                          <*> trfType resType
+  typ -> AST.GadtNormalType <$> annCont (trfType' typ)
+
+trfFieldDecl :: TransformName n r => Located (ConDeclField n) -> Trf (Ann AST.FieldDecl r)
+trfFieldDecl = trfLoc trfFieldDecl'
+
+trfFieldDecl' :: TransformName n r => ConDeclField n -> Trf (AST.FieldDecl r)
+trfFieldDecl' (ConDeclField names typ _) = AST.FieldDecl <$> (define $ nonemptyAnnList <$> mapM (trfName . getFieldOccName) names) <*> trfType typ
+
+trfDerivings :: TransformName n r => Located [LHsSigType n] -> Trf (Ann AST.Deriving r)
+trfDerivings = trfLoc $ \case
+  [hsib_body -> typ@(unLoc -> HsTyVar cls)] -> AST.DerivingOne <$> trfInstanceHead typ
+  derivs -> AST.Derivings <$> trfAnnList ", " trfInstanceHead' (map hsib_body derivs)
+  
+trfInstanceRule :: TransformName n r => Located (HsType n) -> Trf (Ann AST.InstanceRule r)
+trfInstanceRule = trfLoc (trfInstanceRule' . cleanHsType)
+
+trfInstanceRule' :: TransformName n r => HsType n -> Trf (AST.InstanceRule r)
+trfInstanceRule' (HsForAllTy bndrs (unLoc -> HsQualTy ctx typ))
+  = AST.InstanceRule <$> (makeJust <$> annLoc (pure $ collectLocs bndrs) (trfBindings bndrs)) 
+                     <*> trfCtx (after AnnDot) ctx
+                     <*> trfInstanceHead typ
+trfInstanceRule' (HsQualTy ctx typ) = AST.InstanceRule <$> nothing "" " . " atTheStart 
+                                                       <*> trfCtx atTheStart ctx
+                                                       <*> trfInstanceHead typ
+trfInstanceRule' (HsParTy typ) = AST.InstanceParen <$> trfInstanceRule typ
+trfInstanceRule' (HsTyVar tv) = instanceHead $ annCont (AST.InstanceHeadCon <$> trfName tv)
+trfInstanceRule' (HsAppTy t1 t2) = instanceHead $ annCont (AST.InstanceHeadApp <$> trfInstanceHead t1 <*> trfType t2)
+trfInstanceRule' t = error (showSDocUnsafe $ ppr t)
+
+instanceHead :: RangeAnnot r => Trf (Ann AST.InstanceHead r) -> Trf (AST.InstanceRule r)
+instanceHead hd = AST.InstanceRule <$> (nothing "" " . " atTheStart) <*> (nothing " " "" atTheStart) <*> hd
+                            
+makeInstanceRuleTyVars :: TransformName n r => Located n -> HsImplicitBndrs n [LHsType n] -> Trf (Ann AST.InstanceRule r)
+makeInstanceRuleTyVars n vars = annCont
+  $ AST.InstanceRule <$> nothing "" " . " atTheStart
+                     <*> nothing " " "" atTheStart
+                     <*> foldl (\c t -> annLoc (pure $ combineSrcSpans (getLoc n) (getLoc t)) $ AST.InstanceHeadApp <$> c <*> (trfType t))
+                               (copyAnnot AST.InstanceHeadCon (trfName n))
+                               (hsib_body vars)
+
+trfInstanceHead :: TransformName n r => Located (HsType n) -> Trf (Ann AST.InstanceHead r)
+trfInstanceHead = trfLoc trfInstanceHead'
+
+trfInstanceHead' :: TransformName n r => HsType n -> Trf (AST.InstanceHead r)
+trfInstanceHead' = trfInstanceHead'' . cleanHsType where
+  trfInstanceHead'' (HsForAllTy [] (unLoc -> t)) = trfInstanceHead' t
+  trfInstanceHead'' (HsTyVar tv) = AST.InstanceHeadCon <$> trfName tv
+  trfInstanceHead'' (HsAppTy t1 t2) = AST.InstanceHeadApp <$> trfInstanceHead t1 <*> trfType t2
+  trfInstanceHead'' (HsParTy typ) = AST.InstanceHeadParen <$> trfInstanceHead typ
+  trfInstanceHead'' (HsOpTy t1 op t2) 
+    = AST.InstanceHeadApp <$> (annLoc (pure $ combineSrcSpans (getLoc t1) (getLoc op))
+                                      (AST.InstanceHeadInfix <$> trfType t1 <*> trfName op)) 
+                          <*> trfType t2
+  trfInstanceHead'' t = error ("Illegal instance head: " ++ showSDocUnsafe (ppr t) ++ " (ctor: " ++ show (toConstr t) ++ ")")
+ 
+trfTypeEqs :: TransformName n r => Maybe [Located (TyFamInstEqn n)] -> Trf (AnnList AST.TypeEqn r)
+trfTypeEqs Nothing = makeList "\n" (after AnnWhere) (pure [])
+trfTypeEqs (Just eqs) = makeNonemptyList "\n" (mapM trfTypeEq eqs)
+
+trfTypeEq :: TransformName n r => Located (TyFamInstEqn n) -> Trf (Ann AST.TypeEqn r)
+trfTypeEq = trfLoc $ \(TyFamEqn name pats rhs) 
+  -> AST.TypeEqn <$> defineTypeVars (focusBefore AnnEqual (combineTypes name (hsib_body pats))) <*> trfType rhs
+  where combineTypes :: TransformName n r => Located n -> [LHsType n] -> Trf (Ann AST.Type r)
+        combineTypes name (lhs : rhs : rest) | srcSpanStart (getLoc name) > srcSpanEnd (getLoc lhs)
+          = annCont $ AST.TyInfix <$> trfType lhs <*> trfOperator name <*> trfType rhs
+        combineTypes name pats = wrapTypes (annLoc (pure $ getLoc name) (AST.TyVar <$> trfName name)) pats
+
+        wrapTypes :: TransformName n r => Trf (Ann AST.Type r) -> [LHsType n] -> Trf (Ann AST.Type r)
+        wrapTypes base pats 
+          = foldl (\t p -> do typ <- t
+                              annLoc (pure $ combineSrcSpans (getRange $ _annotation typ) (getLoc p)) 
+                                     (AST.TyApp <$> pure typ <*> trfType p)) base pats
+                 
+trfFunDeps :: TransformName n r => [Located (FunDep (Located n))] -> Trf (AnnMaybe AST.FunDeps r)
+trfFunDeps [] = nothing "| " "" $ focusBeforeIfPresent AnnWhere atTheEnd
+trfFunDeps fundeps = makeJust <$> annLoc (combineSrcSpans (collectLocs fundeps) <$> tokenLoc AnnVbar) 
+                                         (AST.FunDeps <$> trfAnnList ", " trfFunDep' fundeps)
+  
+trfFunDep' :: TransformName n r => FunDep (Located n) -> Trf (AST.FunDep r)
+trfFunDep' (lhs, rhs) = AST.FunDep <$> trfAnnList ", " trfName' lhs <*> trfAnnList ", " trfName' rhs
+
+createDeclHead :: TransformName n r => Located n -> LHsQTyVars n -> Trf (Ann AST.DeclHead r)
+createDeclHead name (hsq_explicit -> lhs : rhs : rest)
+  | srcSpanStart (getLoc name) > srcSpanEnd (getLoc lhs)
+  -- infix declaration
+  = wrapDeclHead rest
+      $ annLoc (addParenLocs $ getLoc lhs `combineSrcSpans` getLoc rhs) 
+               (AST.DHInfix <$> defineTypeVars (trfTyVar lhs) <*> define (trfOperator name) <*> defineTypeVars (trfTyVar rhs))
+createDeclHead name vars = defineTypeVars $ wrapDeclHead (hsq_explicit vars) (define $ copyAnnot AST.DeclHead (trfName name))
+
+wrapDeclHead :: TransformName n r => [LHsTyVarBndr n] -> Trf (Ann AST.DeclHead r) -> Trf (Ann AST.DeclHead r)
+wrapDeclHead vars base
+  = foldl (\t p -> do typ <- t 
+                      annLoc (addParenLocs $ combineSrcSpans (getRange $ _annotation typ) (getLoc p)) 
+                             (AST.DHApp typ <$> trfTyVar p)
+          ) base vars
+
+-- | Get the parentheses directly before and after (for parenthesized application)
+addParenLocs :: SrcSpan -> Trf SrcSpan
+addParenLocs sp 
+  = let possibleSpan = mkSrcSpan (updateCol (subtract 1) (srcSpanStart sp)) (updateCol (+1) (srcSpanEnd sp))
+     in local (\s -> s { contRange = possibleSpan })
+              (combineSrcSpans <$> (combineSrcSpans sp <$> tokenLoc AnnOpenP) <*> tokenLocBack AnnCloseP)
+      
+         
+createClassBody :: TransformName n r => [LSig n] -> LHsBinds n -> [LFamilyDecl n] 
+                               -> [LTyFamDefltEqn n] -> Trf (AnnMaybe AST.ClassBody r)
+createClassBody sigs binds typeFams typeFamDefs 
+  = do isThereWhere <- isGoodSrcSpan <$> (tokenLoc AnnWhere)
+       if isThereWhere 
+         then makeJust <$> annLoc (combinedLoc <$> tokenLoc AnnWhere) 
+                                  (AST.ClassBody <$> makeList "" (after AnnWhere) 
+                                                                 (orderDefs . concat <$> sequenceA allDefs))
+         else nothing " where " "" atTheEnd
+  where combinedLoc wh = foldl combineSrcSpans wh allLocs
+        allLocs = map getLoc sigs ++ map getLoc (bagToList binds) ++ map getLoc typeFams ++ map getLoc typeFamDefs
+        allDefs = [getSigs, getBinds, getFams, getFamDefs]
+        getSigs = mapM trfClassElemSig sigs
+        getBinds = mapM (copyAnnot AST.ClsDef . trfBind) (bagToList binds)
+        getFams = mapM (copyAnnot AST.ClsTypeFam . trfTypeFam) typeFams
+        getFamDefs = mapM trfTypeFamDef typeFamDefs
+       
+trfClassElemSig :: TransformName n r => Located (Sig n) -> Trf (Ann AST.ClassElement r)
+trfClassElemSig = trfLoc $ \case
+  TypeSig names typ -> AST.ClsSig <$> (annCont $ AST.TypeSignature <$> define (makeNonemptyList ", " (mapM trfName names)) 
+                                  <*> trfType (hswc_body $ hsib_body typ))
+  ClassOpSig True [name] typ -> AST.ClsDefSig <$> trfName name <*> trfType (hsib_body typ)
+  ClassOpSig False names typ -> AST.ClsSig <$> (annCont $ AST.TypeSignature <$> define (makeNonemptyList ", " (mapM trfName names)) 
+                                           <*> trfType (hsib_body typ))
+  MinimalSig _ formula -> AST.ClsMinimal <$> trfMinimalFormula formula
+  s -> error ("Illegal signature: " ++ showSDocUnsafe (ppr s) ++ " (ctor: " ++ show (toConstr s) ++ ")")
+         
+trfTypeFam :: TransformName n r => Located (FamilyDecl n) -> Trf (Ann AST.TypeFamily r)
+trfTypeFam = trfLoc trfTypeFam'
+
+trfTypeFam' :: TransformName n r => FamilyDecl n -> Trf (AST.TypeFamily r)
+trfTypeFam' (FamilyDecl DataFamily name tyVars kindSig _)
+  = AST.DataFamily <$> (case unLoc kindSig of KindSig _ -> between AnnData AnnDcolon; _ -> id) (createDeclHead name tyVars) 
+                   <*> trfFamilyKind kindSig
+trfTypeFam' (FamilyDecl OpenTypeFamily name tyVars kindSig injectivity)
+  = AST.TypeFamily <$> (case unLoc kindSig of KindSig _ -> between AnnType AnnDcolon; _ -> id) (createDeclHead name tyVars) 
+                   <*> trfFamilyResultSig kindSig injectivity
+
+trfTypeFamDef :: TransformName n r => Located (TyFamDefltEqn n) -> Trf (Ann AST.ClassElement r)
+trfTypeFamDef = trfLoc $ \(TyFamEqn con pats rhs) 
+  -> AST.ClsTypeDef <$> between AnnType AnnEqual (createDeclHead con pats) <*> trfType rhs
+          
+trfInstBody :: TransformName n r => LHsBinds n -> [LSig n] -> [LTyFamInstDecl n] -> [LDataFamInstDecl n] -> Trf (AnnMaybe AST.InstBody r)
+trfInstBody binds sigs fams dats = do
+    wh <- tokenLoc AnnWhere
+    if isGoodSrcSpan wh then
+      makeJust <$> annLoc (combinedLoc <$> tokenLoc AnnWhere) 
+                          (AST.InstBody <$> (makeList "" (after AnnWhere) 
+                                                         (orderDefs . concat <$> sequenceA allDefs)))
+    else nothing " where " "" atTheEnd
+  where combinedLoc wh = foldl combineSrcSpans wh allLocs
+        allLocs = map getLoc sigs ++ map getLoc (bagToList binds) ++ map getLoc fams ++ map getLoc dats
+        allDefs = [getSigs, getBinds, getFams, getDats]
+        getSigs = mapM trfClassInstSig sigs
+        getBinds = mapM (copyAnnot AST.InstBodyNormalDecl . trfBind) (bagToList binds)
+        getFams = mapM trfInstTypeFam fams
+        getDats = mapM trfInstDataFam dats
+          
+trfClassInstSig :: TransformName n r => Located (Sig n) -> Trf (Ann AST.InstBodyDecl r)
+trfClassInstSig = trfLoc $ \case
+  TypeSig names typ -> AST.InstBodyTypeSig <$> (annCont $ AST.TypeSignature <$> makeNonemptyList ", " (mapM trfName names) 
+                                           <*> trfType (hswc_body $ hsib_body typ))
+  ClassOpSig _ names typ -> AST.InstBodyTypeSig <$> (annCont $ AST.TypeSignature <$> define (makeNonemptyList ", " (mapM trfName names)) 
+                                                <*> trfType (hsib_body typ))
+  SpecInstSig _ typ -> AST.SpecializeInstance <$> trfType (hsib_body typ)
+  s -> error ("Illegal class instance signature: " ++ showSDocUnsafe (ppr s) ++ " (ctor: " ++ show (toConstr s) ++ ")")
+          
+trfInstTypeFam :: TransformName n r => Located (TyFamInstDecl n) -> Trf (Ann AST.InstBodyDecl r)
+trfInstTypeFam (unLoc -> TyFamInstDecl eqn _) = copyAnnot AST.InstBodyTypeDecl (trfTypeEq eqn)
+
+trfInstDataFam :: TransformName n r => Located (DataFamInstDecl n) -> Trf (Ann AST.InstBodyDecl r)
+trfInstDataFam = trfLoc $ \case 
+  (DataFamInstDecl tc (hsib_body -> pats) (HsDataDefn dn ctx _ _ cons derivs) _) 
+    -> AST.InstBodyDataDecl 
+         <$> trfDataKeyword dn 
+         <*> annLoc (pure $ collectLocs pats `combineSrcSpans` getLoc tc `combineSrcSpans` getLoc ctx)
+                    (AST.InstanceRule <$> nothing "" " . " atTheStart
+                                      <*> trfCtx atTheStart ctx 
+                                      <*> foldr (\t r -> annLoc (combineSrcSpans (getLoc t) . getRange . _annotation <$> r) 
+                                                                (AST.InstanceHeadApp <$> r <*> (trfType t))) 
+                                                (copyAnnot AST.InstanceHeadCon (trfName tc)) pats)
+         <*> trfAnnList "" trfConDecl' cons
+         <*> trfMaybe " deriving " "" trfDerivings derivs
+          
+trfPatternSynonym :: forall n r . TransformName n r => PatSynBind n n -> Trf (AST.PatternSynonym r)
+trfPatternSynonym (PSB id _ lhs def dir)
+  = let sep = case dir of ImplicitBidirectional -> AnnEqual
+                          _                     -> AnnLarrow
+        rhsLoc = combineSrcSpans (getLoc def) <$> tokenLoc sep
+        -- we use the selector name instead of the pattern variable name
+        rewrites = case lhs of RecordPatSyn flds -> map (\r -> (unLoc (recordPatSynPatVar r), unLoc (recordPatSynSelectorId r))) flds
+                               _                 -> []
+        changedRhs = biplateRef .- (\n -> case lookup n rewrites of Just x -> x; Nothing -> n) $ def
+     in AST.PatternSynonym <$> trfPatSynLhs id lhs
+                           <*> annLoc rhsLoc (trfPatSynRhs dir changedRhs)
+
+  where trfPatSynLhs :: TransformName n r => Located n -> HsPatSynDetails (Located n) -> Trf (Ann AST.PatSynLhs r)
+        trfPatSynLhs id (PrefixPatSyn args)
+          = annLoc (pure $ foldLocs (getLoc id : map getLoc args)) $ AST.NormalPatSyn <$> trfName id <*> trfAnnList " " trfName' args
+        trfPatSynLhs op (InfixPatSyn lhs rhs)
+          = annLoc (pure $ getLoc lhs `combineSrcSpans` getLoc rhs) $ AST.InfixPatSyn <$> trfName lhs <*> trfOperator op <*> trfName rhs
+        trfPatSynLhs id (RecordPatSyn flds)
+          = annLoc (mkSrcSpan (srcSpanStart (getLoc id)) <$> before AnnEqual) 
+              $ AST.RecordPatSyn <$> trfName id <*> trfAnnList ", " trfName' (map recordPatSynSelectorId flds)
+
+        trfPatSynRhs :: TransformName n r => HsPatSynDir n -> Located (Pat n) -> Trf (AST.PatSynRhs r)
+        trfPatSynRhs ImplicitBidirectional pat = AST.BidirectionalPatSyn <$> trfPattern pat <*> nothing " where " "" atTheEnd
+        trfPatSynRhs (ExplicitBidirectional mg) pat = AST.BidirectionalPatSyn <$> trfPattern pat <*> (makeJust <$> trfPatSynWhere mg)
+        trfPatSynRhs Unidirectional pat = AST.OneDirectionalPatSyn <$> trfPattern pat
+        trfPatSynWhere :: TransformName n r => MatchGroup n (LHsExpr n) -> Trf (Ann AST.PatSynWhere r)
+        trfPatSynWhere (MG { mg_alts = alts }) = annLoc (pure $ getLoc alts) (AST.PatSynWhere <$> makeIndentedList (after AnnWhere) (mapM (trfMatch (unLoc id)) (unLoc alts)))
+
+trfFamilyKind :: TransformName n r => Located (FamilyResultSig n) -> Trf (AnnMaybe AST.KindConstraint r)
+trfFamilyKind (unLoc -> fr) = case fr of
+  NoSig -> nothing "" " " atTheEnd
+  KindSig k -> trfKindSig (Just k)
+
+trfFamilyResultSig :: TransformName n r => Located (FamilyResultSig n) -> Maybe (LInjectivityAnn n) -> Trf (AnnMaybe AST.TypeFamilySpec r)
+trfFamilyResultSig (L l fr) Nothing = case fr of 
+  NoSig -> nothing "" " " atTheEnd
+  KindSig k -> makeJust <$> (annLoc (pure l) $ AST.TypeFamilyKind <$> trfKindSig' k)
+trfFamilyResultSig _ (Just (L l (InjectivityAnn n deps))) 
+  = makeJust <$> (annLoc (pure l) $ AST.TypeFamilyInjectivity <$> (annCont $ AST.InjectivityAnn <$> trfName n <*> trfAnnList ", " trfName' deps))
+
+trfAnnotationSubject :: TransformName n r => SourceText -> AnnProvenance n -> SrcLoc -> Trf (Ann AST.AnnotationSubject r)
+trfAnnotationSubject stxt subject payloadEnd
+  = do payloadStart <- advanceStr stxt <$> atTheStart
+       case subject of ValueAnnProvenance name@(L l _) -> annLoc (pure l) (AST.NameAnnotation <$> trfName name)
+                       TypeAnnProvenance name@(L l _) -> annLoc (pure $ mkSrcSpan payloadStart (srcSpanEnd l)) 
+                                                                (AST.TypeAnnotation <$> trfName name)
+                       ModuleAnnProvenance -> annLoc (pure $ mkSrcSpan payloadStart payloadEnd) (pure AST.ModuleAnnotation)
+ Language/Haskell/Tools/AST/FromGHC/Exprs.hs view
@@ -0,0 +1,210 @@+{-# LANGUAGE LambdaCase
+           , ViewPatterns
+           , ScopedTypeVariables
+           , TypeApplications
+           , AllowAmbiguousTypes
+           #-}
+module Language.Haskell.Tools.AST.FromGHC.Exprs where
+
+import Data.Maybe
+import Data.Data (toConstr)
+import Control.Monad.Reader
+import Control.Reference
+
+import SrcLoc as GHC
+import RdrName as GHC
+import HsTypes as GHC
+import HsPat as GHC
+import HsExpr as GHC
+import HsBinds as GHC
+import HsLit as GHC
+import BasicTypes as GHC
+import ApiAnnotation as GHC
+import FastString as GHC
+import Outputable as GHC
+
+import Language.Haskell.Tools.AST.FromGHC.Base
+import Language.Haskell.Tools.AST.FromGHC.Types
+import Language.Haskell.Tools.AST.FromGHC.Literals
+import Language.Haskell.Tools.AST.FromGHC.Patterns
+import Language.Haskell.Tools.AST.FromGHC.Stmts
+import {-# SOURCE #-} Language.Haskell.Tools.AST.FromGHC.Binds
+import {-# SOURCE #-} Language.Haskell.Tools.AST.FromGHC.TH
+import Language.Haskell.Tools.AST.FromGHC.Monad
+import Language.Haskell.Tools.AST.FromGHC.Utils
+import Language.Haskell.Tools.AST.FromGHC.GHCUtils
+
+import Language.Haskell.Tools.AST (Ann(..), AnnList(..))
+import qualified Language.Haskell.Tools.AST as AST
+
+import Debug.Trace
+
+trfExpr :: forall n r . TransformName n r => Located (HsExpr n) -> Trf (Ann AST.Expr r)
+-- correction for empty cases (TODO: put of and {} inside)
+trfExpr (L l cs@(HsCase expr (unLoc . mg_alts -> []))) 
+  = addScopeInfo @n =<< annLoc (pure $ combineSrcSpans l (getLoc expr)) (trfExpr' cs)
+trfExpr e = addScopeInfo @n =<< trfLoc trfExpr' e
+
+addScopeInfo :: forall n r . TransformName n r => Ann AST.Expr r -> Trf (Ann AST.Expr r)
+addScopeInfo expr = do scope <- asks localsInScope
+                       return $ AST.annotation .- addSemanticInfo (AST.ScopeInfo scope :: AST.SemanticInfo n) $ expr
+
+trfExpr' :: TransformName n r => HsExpr n -> Trf (AST.Expr r)
+trfExpr' (HsVar name) = AST.Var <$> trfName name
+trfExpr' (HsRecFld fld) = AST.Var <$> (asks contRange >>= \l -> trfAmbiguousFieldName' l fld)
+trfExpr' (HsIPVar (HsIPName ip)) = AST.Var <$> annCont (AST.NormalName <$> annCont (AST.nameFromList <$> trfNameStr (unpackFS ip)))
+trfExpr' (HsOverLit (ol_val -> val)) = AST.Lit <$> annCont (trfOverloadedLit val)
+trfExpr' (HsLit val) = AST.Lit <$> annCont (trfLiteral' val)
+trfExpr' (HsLam (unLoc . mg_alts -> [unLoc -> Match _ pats _ (GRHSs [unLoc -> GRHS [] expr] (unLoc -> EmptyLocalBinds))]))
+  = AST.Lambda <$> (trfAnnList " " trfPattern' pats) <*> addToScope pats (trfExpr expr)
+trfExpr' (HsLamCase _ (unLoc . mg_alts -> matches)) = AST.LamCase <$> trfAnnList " " trfAlt' matches
+trfExpr' (HsApp e1 e2) = AST.App <$> trfExpr e1 <*> trfExpr e2
+trfExpr' (OpApp e1 (unLoc -> HsVar op) _ e2) 
+  = AST.InfixApp <$> trfExpr e1 <*> trfOperator op <*> trfExpr e2
+trfExpr' (NegApp e _) = AST.PrefixApp <$> annLoc loc (AST.NormalOp <$> annLoc loc (AST.nameFromList <$> trfNameStr "-"))
+                                      <*> trfExpr e
+  where loc = mkSrcSpan <$> atTheStart <*> (pure $ srcSpanStart (getLoc e))
+trfExpr' (HsPar (unLoc -> SectionL expr (unLoc -> HsVar op))) = AST.LeftSection <$> trfExpr expr <*> trfOperator op
+trfExpr' (HsPar (unLoc -> SectionR (unLoc -> HsVar op) expr)) = AST.RightSection <$> trfOperator op <*> trfExpr expr
+trfExpr' (HsPar expr) = AST.Paren <$> trfExpr expr
+trfExpr' (ExplicitTuple tupArgs box) | all tupArgPresent tupArgs 
+  = wrap <$> between AnnOpenP AnnCloseP (trfAnnList' ", " (trfExpr . (\(Present e) -> e) . unLoc) tupArgs)
+  where wrap = if box == Boxed then AST.Tuple else AST.UnboxedTuple
+trfExpr' (ExplicitTuple tupArgs box)
+  = wrap <$> between AnnOpenP AnnCloseP
+               (do locs <- elemLocs
+                   makeList ", " atTheEnd $ mapM trfTupSecElem (zip (map unLoc tupArgs) locs))
+  where wrap = if box == Boxed then AST.TupleSection else AST.UnboxedTupSec
+        trfTupSecElem :: forall n r . TransformName n r => (HsTupArg n, SrcSpan) -> Trf (Ann AST.TupSecElem r)
+        trfTupSecElem (Present e, l) 
+          = annLoc (pure l) (AST.Present <$> (addScopeInfo @n =<< annCont (trfExpr' (unLoc e))))
+        trfTupSecElem (Missing _, l) = annLoc (pure l) (pure AST.Missing)
+        
+        elemLocs :: Trf [SrcSpan]
+        elemLocs = do r <- asks contRange
+                      commaLocs <- allTokenLoc AnnComma
+                      return $ foldl breakUp [r] commaLocs
+        breakUp :: [SrcSpan] -> SrcSpan -> [SrcSpan]
+        breakUp cont sep = concatMap (breakUpOne sep) cont
+
+        breakUpOne :: SrcSpan -> SrcSpan -> [SrcSpan]
+        breakUpOne sep@(RealSrcSpan realSep) sp@(RealSrcSpan realSp) 
+          | realSp `containsSpan` realSep = [mkSrcSpan (srcSpanStart sp) (srcSpanStart sep), mkSrcSpan (srcSpanEnd sep) (srcSpanEnd sp)]
+        breakUpOne _ sp = [sp]
+
+trfExpr' (HsCase expr (unLoc . mg_alts -> cases)) = AST.Case <$> trfExpr expr <*> (makeIndentedList (focusBeforeIfPresent AnnCloseC atTheEnd) (mapM trfAlt cases))
+trfExpr' (HsIf _ expr thenE elseE) = AST.If <$> trfExpr expr <*> trfExpr thenE <*> trfExpr elseE
+trfExpr' (HsMultiIf _ parts) = AST.MultiIf <$> trfAnnList "" trfGuardedCaseRhs' parts
+trfExpr' (HsLet (unLoc -> binds) expr) = addToScope binds (AST.Let <$> trfLocalBinds binds <*> trfExpr expr)
+trfExpr' (HsDo DoExpr (unLoc -> stmts) _) = AST.Do <$> annLoc (tokenLoc AnnDo) (pure AST.DoKeyword) 
+                                                   <*> makeNonemptyIndentedList (trfScopedSequence trfDoStmt stmts)
+trfExpr' (HsDo MDoExpr (unLoc -> [unLoc -> RecStmt { recS_stmts = stmts }, lastStmt]) _) 
+  = AST.Do <$> annLoc (tokenLoc AnnMdo) (pure AST.MDoKeyword)
+           <*> addToScope stmts (makeNonemptyIndentedList (mapM trfDoStmt (stmts ++ [lastStmt])))
+trfExpr' (HsDo MDoExpr (unLoc -> stmts) _) = AST.Do <$> annLoc (tokenLoc AnnMdo) (pure AST.MDoKeyword)
+                                                    <*> addToScope stmts (makeNonemptyIndentedList (mapM trfDoStmt stmts))
+-- TODO: scoping
+trfExpr' (HsDo ListComp (unLoc -> stmts) _)
+  = AST.ListComp <$> trfExpr (getLastStmt stmts) <*> trfListCompStmts stmts
+trfExpr' (HsDo MonadComp (unLoc -> stmts) _)
+  = AST.ListComp <$> trfExpr (getLastStmt stmts) <*> trfListCompStmts stmts
+trfExpr' (HsDo PArrComp (unLoc -> stmts) _)
+  = AST.ParArrayComp <$> trfExpr (getLastStmt stmts) <*> trfListCompStmts stmts
+trfExpr' (ExplicitList _ _ exprs) = AST.List <$> trfAnnList' ", " trfExpr exprs
+trfExpr' (ExplicitPArr _ exprs) = AST.ParArray <$> trfAnnList' ", " trfExpr exprs
+trfExpr' (RecordCon name _ _ fields) = AST.RecCon <$> trfName name <*> trfFieldInits fields
+trfExpr' (RecordUpd expr fields _ _ _ _) = AST.RecUpdate <$> trfExpr expr <*> trfAnnList ", " trfFieldUpdate fields
+trfExpr' (ExprWithTySig expr typ) = AST.TypeSig <$> trfExpr expr <*> trfType (hswc_body $ hsib_body typ)
+trfExpr' (ArithSeq _ _ (From from)) = AST.Enum <$> trfExpr from <*> nothing "," "" (before AnnDotdot)
+                                                                <*> nothing "" "" (before AnnCloseS)
+trfExpr' (ArithSeq _ _ (FromThen from step)) 
+  = AST.Enum <$> trfExpr from <*> (makeJust <$> trfExpr step) <*> nothing "" "" (before AnnCloseS) 
+trfExpr' (ArithSeq _ _ (FromTo from to)) 
+  = AST.Enum <$> trfExpr from <*> nothing "," "" (before AnnDotdot)
+                              <*> (makeJust <$> trfExpr to)
+trfExpr' (ArithSeq _ _ (FromThenTo from step to)) 
+  = AST.Enum <$> trfExpr from <*> (makeJust <$> trfExpr step) <*> (makeJust <$> trfExpr to)
+trfExpr' (PArrSeq _ (FromTo from to)) 
+  = AST.ParArrayEnum <$> trfExpr from <*> nothing "," "" (before AnnDotdot) <*> trfExpr to
+trfExpr' (PArrSeq _ (FromThenTo from step to)) 
+  = AST.ParArrayEnum <$> trfExpr from <*> (makeJust <$> trfExpr step) <*> trfExpr to
+-- TODO: SCC, CORE, GENERATED annotations
+trfExpr' (HsBracket brack) = AST.BracketExpr <$> annCont (trfBracket' brack)
+trfExpr' (HsRnBracketOut brack _) = AST.BracketExpr <$> annCont (trfBracket' brack)
+trfExpr' (HsTcBracketOut brack _) = AST.BracketExpr <$> annCont (trfBracket' brack)
+trfExpr' (HsSpliceE qq@(HsQuasiQuote {})) = AST.QuasiQuoteExpr <$> annCont (trfQuasiQuotation' qq)
+trfExpr' (HsSpliceE splice) = AST.Splice <$> annCont (trfSplice' splice)
+trfExpr' (HsProc pat cmdTop) = AST.Proc <$> trfPattern pat <*> trfCmdTop cmdTop
+trfExpr' (HsStatic expr) = AST.StaticPtr <$> trfExpr expr
+trfExpr' (HsAppType expr typ) = AST.ExplTypeApp <$> trfExpr expr <*> trfType (hswc_body typ)
+trfExpr' t = error ("Illegal expression: " ++ showSDocUnsafe (ppr t) ++ " (ctor: " ++ show (toConstr t) ++ ")")
+  
+trfFieldInits :: TransformName n r => HsRecFields n (LHsExpr n) -> Trf (AnnList AST.FieldUpdate r)
+trfFieldInits (HsRecFields fields dotdot) 
+  = do cont <- asks contRange
+       makeList ", " (before AnnCloseC)
+         $ ((++) <$> mapM trfFieldInit (filter ((cont /=) . getLoc) fields) 
+                  <*> (if isJust dotdot then (:[]) <$> annLoc (tokenLoc AnnDotdot) 
+                                                              (pure AST.FieldWildcard) 
+                                        else pure []))
+  
+trfFieldInit :: TransformName n r => Located (HsRecField n (LHsExpr n)) -> Trf (Ann AST.FieldUpdate r)
+trfFieldInit = trfLoc $ \case
+  HsRecField id _ True -> AST.FieldPun <$> trfName (getFieldOccName id)
+  HsRecField id val False -> AST.NormalFieldUpdate <$> trfName (getFieldOccName id) <*> trfExpr val
+  
+trfFieldUpdate :: TransformName n r => HsRecField' (AmbiguousFieldOcc n) (LHsExpr n) -> Trf (AST.FieldUpdate r)
+trfFieldUpdate (HsRecField id _ True) = AST.FieldPun <$> trfAmbiguousFieldName id
+trfFieldUpdate (HsRecField id val False) = AST.NormalFieldUpdate <$> trfAmbiguousFieldName id <*> trfExpr val
+
+trfAlt :: TransformName n r => Located (Match n (LHsExpr n)) -> Trf (Ann AST.Alt r)
+trfAlt = trfLoc trfAlt'
+
+trfAlt' :: TransformName n r => Match n (LHsExpr n) -> Trf (AST.Alt r)
+trfAlt' = gTrfAlt' trfExpr
+
+gTrfAlt' :: TransformName n r => (Located (ge n) -> Trf (Ann ae r)) -> Match n (Located (ge n)) -> Trf (AST.Alt' ae r)
+gTrfAlt' te (Match _ [pat] typ (GRHSs rhss (unLoc -> locBinds)))
+  = AST.Alt <$> trfPattern pat <*> gTrfCaseRhss te rhss <*> trfWhereLocalBinds locBinds
+  
+trfCaseRhss :: TransformName n r => [Located (GRHS n (LHsExpr n))] -> Trf (Ann AST.CaseRhs r)
+trfCaseRhss = gTrfCaseRhss trfExpr
+
+gTrfCaseRhss :: TransformName n r => (Located (ge n) -> Trf (Ann ae r)) -> [Located (GRHS n (Located (ge n)))] -> Trf (Ann (AST.CaseRhs' ae) r)
+gTrfCaseRhss te [unLoc -> GRHS [] body] = annLoc (combineSrcSpans (getLoc body) <$> tokenLocBack AnnRarrow) 
+                                                 (AST.UnguardedCaseRhs <$> te body)
+gTrfCaseRhss te rhss = annLoc (pure $ collectLocs rhss) 
+                              (AST.GuardedCaseRhss <$> trfAnnList ";" (gTrfGuardedCaseRhs' te) rhss)
+  
+trfGuardedCaseRhs :: TransformName n r => Located (GRHS n (LHsExpr n)) -> Trf (Ann AST.GuardedCaseRhs r)
+trfGuardedCaseRhs = trfLoc trfGuardedCaseRhs' 
+
+trfGuardedCaseRhs' :: TransformName n r => GRHS n (LHsExpr n) -> Trf (AST.GuardedCaseRhs r)
+trfGuardedCaseRhs' = gTrfGuardedCaseRhs' trfExpr
+
+gTrfGuardedCaseRhs' :: TransformName n r => (Located (ge n) -> Trf (Ann ae r)) -> GRHS n (Located (ge n)) -> Trf (AST.GuardedCaseRhs' ae r)
+gTrfGuardedCaseRhs' te (GRHS guards body) = AST.GuardedCaseRhs <$> trfAnnList " " trfRhsGuard' guards <*> te body
+
+trfCmdTop :: TransformName n r => Located (HsCmdTop n) -> Trf (Ann AST.Cmd r)
+trfCmdTop (L _ (HsCmdTop cmd _ _ _)) = trfCmd cmd
+
+trfCmd :: TransformName n r => Located (HsCmd n) -> Trf (Ann AST.Cmd r)
+trfCmd = trfLoc trfCmd'
+
+trfCmd' :: TransformName n r => HsCmd n -> Trf (AST.Cmd r)
+trfCmd' (HsCmdArrApp left right _ typ dir) = AST.ArrowAppCmd <$> trfExpr left <*> op <*> trfExpr right 
+  where op = case (typ, dir) of (HsFirstOrderApp, False) -> annLoc (tokenLoc Annrarrowtail) (pure AST.RightAppl)
+                                (HsFirstOrderApp, True) -> annLoc (tokenLoc Annlarrowtail) (pure AST.LeftAppl)
+                                (HsHigherOrderApp, False) -> annLoc (tokenLoc AnnRarrowtail) (pure AST.RightHighApp)
+                                (HsHigherOrderApp, True) -> annLoc (tokenLoc AnnLarrowtail) (pure AST.LeftHighApp)
+                                                                       -- FIXME: needs a before 
+trfCmd' (HsCmdArrForm expr _ cmds) = AST.ArrowFormCmd <$> trfExpr expr <*> makeList " " (before AnnClose) (mapM trfCmdTop cmds)
+trfCmd' (HsCmdApp cmd expr) = AST.AppCmd <$> trfCmd cmd <*> trfExpr expr
+trfCmd' (HsCmdLam (MG (unLoc -> [unLoc -> Match _ pats _ (GRHSs [unLoc -> GRHS [] body] _)]) _ _ _)) 
+  = AST.LambdaCmd <$> trfAnnList " " trfPattern' pats <*> trfCmd body
+trfCmd' (HsCmdPar cmd) = AST.ParenCmd <$> trfCmd cmd
+trfCmd' (HsCmdCase expr (MG (unLoc -> alts) _ _ _)) 
+  = AST.CaseCmd <$> trfExpr expr <*> makeNonemptyIndentedList (mapM (trfLoc (gTrfAlt' trfCmd)) alts) 
+trfCmd' (HsCmdIf _ pred thenExpr elseExpr) = AST.IfCmd <$> trfExpr pred <*> trfCmd thenExpr <*> trfCmd elseExpr
+trfCmd' (HsCmdLet (unLoc -> binds) cmd) = addToScope binds (AST.LetCmd <$> trfLocalBinds binds <*> trfCmd cmd)
+trfCmd' (HsCmdDo (unLoc -> stmts) _) = AST.DoCmd <$> makeNonemptyIndentedList (mapM (trfLoc (gTrfDoStmt' trfCmd)) stmts)
+ Language/Haskell/Tools/AST/FromGHC/Exprs.hs-boot view
@@ -0,0 +1,16 @@+module Language.Haskell.Tools.AST.FromGHC.Exprs where
+
+import Outputable as GHC
+import RdrName as GHC
+import SrcLoc as GHC
+import HsExpr as GHC
+import Language.Haskell.Tools.AST.FromGHC.Monad
+import Language.Haskell.Tools.AST.FromGHC.Utils
+import Language.Haskell.Tools.AST.FromGHC.Base
+import Language.Haskell.Tools.AST (Ann(..))
+import qualified Language.Haskell.Tools.AST as AST
+
+trfExpr :: TransformName n r => Located (HsExpr n) -> Trf (Ann AST.Expr r)
+trfExpr' :: TransformName n r => HsExpr n -> Trf (AST.Expr r)
+
+trfCmd' :: TransformName n r => HsCmd n -> Trf (AST.Cmd r)
+ Language/Haskell/Tools/AST/FromGHC/GHCUtils.hs view
@@ -0,0 +1,187 @@+{-# LANGUAGE MultiParamTypeClasses
+           , TypeSynonymInstances
+           , FlexibleInstances
+           , ScopedTypeVariables
+           , ViewPatterns
+           #-}
+module Language.Haskell.Tools.AST.FromGHC.GHCUtils where
+
+import Data.List
+
+import GHC
+import Bag
+import RdrName
+import OccName
+import Name
+import Outputable
+import SrcLoc
+
+class OutputableBndr name => GHCName name where 
+  rdrName :: name -> RdrName
+  getBindsAndSigs :: HsValBinds name -> ([LSig name], LHsBinds name)
+  nameFromId :: Id -> name
+  unpackPostRn :: RdrName -> PostRn name name -> name
+
+  gunpackPostRn :: a -> (name -> a) -> PostRn name name -> a
+
+instance GHCName RdrName where
+  rdrName = id
+  getBindsAndSigs (ValBindsIn binds sigs) = (sigs, binds)
+  nameFromId = nameRdrName . getName
+  unpackPostRn rdr _ = rdr
+
+  gunpackPostRn a _ _ = a
+
+occName :: GHCName n => n -> OccName
+occName = rdrNameOcc . rdrName 
+    
+instance GHCName GHC.Name where
+  rdrName = nameRdrName
+  getBindsAndSigs (ValBindsOut bindGroups sigs) = (sigs, unionManyBags (map snd bindGroups))
+  nameFromId = getName
+  unpackPostRn _ a = a
+
+  gunpackPostRn _ f pr = f pr
+
+getFieldOccName :: GHCName n => Located (FieldOcc n) -> Located n
+getFieldOccName (L l (FieldOcc (L _ rdr) postRn)) = L l (unpackPostRn rdr postRn)
+
+getFieldOccName' :: GHCName n => FieldOcc n -> n
+getFieldOccName' (FieldOcc (L _ rdr) postRn) = unpackPostRn rdr postRn
+
+
+class HsHasName a where
+  hsGetNames :: a -> [GHC.Name]
+
+instance HsHasName RdrName where
+  hsGetNames _ = [] 
+
+instance HsHasName Name where
+  hsGetNames n = [n] 
+
+instance HsHasName Id where
+  hsGetNames n = [getName n] 
+
+instance HsHasName e => HsHasName [e] where
+  hsGetNames es = concatMap hsGetNames es
+
+instance HsHasName e => HsHasName (Located e) where
+  hsGetNames (L _ e) = hsGetNames e
+
+instance HsHasName n => HsHasName (HsLocalBinds n) where
+  hsGetNames (HsValBinds bnds) = hsGetNames bnds
+  hsGetNames _ = []
+
+instance (GHCName n, HsHasName n) => HsHasName (HsDecl n) where
+  hsGetNames (TyClD tycl) = hsGetNames tycl
+  hsGetNames (ValD vald) = hsGetNames vald
+  hsGetNames (ForD ford) = hsGetNames ford
+  hsGetNames _ = []
+
+instance (GHCName n, HsHasName n) => HsHasName (TyClGroup n) where
+  hsGetNames (TyClGroup tycls _) = hsGetNames tycls
+
+instance (GHCName n, HsHasName n) => HsHasName (TyClDecl n) where
+  hsGetNames (FamDecl (FamilyDecl {fdLName = name})) = hsGetNames name
+  hsGetNames (SynDecl {tcdLName = name}) = hsGetNames name
+  hsGetNames (DataDecl {tcdLName = name, tcdDataDefn = datadef}) = hsGetNames name ++ hsGetNames datadef
+  hsGetNames (ClassDecl {tcdLName = name, tcdSigs = sigs}) = hsGetNames name ++ hsGetNames sigs
+
+instance (GHCName n, HsHasName n) => HsHasName (HsDataDefn n) where
+  hsGetNames (HsDataDefn {dd_cons = ctors}) = hsGetNames ctors
+
+instance (GHCName n, HsHasName n) => HsHasName (ConDecl n) where
+  hsGetNames (ConDeclGADT {con_names = names, con_type = (HsIB _ (L l (HsRecTy flds)))}) = hsGetNames names ++ hsGetNames flds
+  hsGetNames (ConDeclGADT {con_names = names}) = hsGetNames names
+  hsGetNames (ConDeclH98 {con_name = name, con_details = details}) = hsGetNames name ++ hsGetNames details
+
+instance (GHCName n, HsHasName n) => HsHasName (HsConDeclDetails n) where
+  hsGetNames (RecCon rec) = hsGetNames rec
+  hsGetNames _ = []
+
+instance (GHCName n, HsHasName n) => HsHasName (ConDeclField n) where
+  hsGetNames (ConDeclField name _ _) = hsGetNames name
+
+instance (GHCName n, HsHasName n) => HsHasName (FieldOcc n) where 
+  hsGetNames (FieldOcc _ pr) = gunpackPostRn [] (hsGetNames :: n -> [Name]) pr
+
+instance (GHCName n, HsHasName n) => HsHasName (Sig n) where
+  hsGetNames (TypeSig n _) = hsGetNames n
+  hsGetNames (PatSynSig n _) = hsGetNames n
+  hsGetNames _ = []
+
+instance HsHasName n => HsHasName (ForeignDecl n) where
+  hsGetNames (ForeignImport n _ _ _) = hsGetNames n
+  hsGetNames _ = []
+
+instance HsHasName n => HsHasName (HsValBinds n) where
+  hsGetNames (ValBindsIn bnds _) = hsGetNames bnds
+  hsGetNames (ValBindsOut bnds _) = hsGetNames $ map snd bnds
+
+instance HsHasName n => HsHasName (Bag n) where
+  hsGetNames = hsGetNames . bagToList
+
+instance HsHasName n => HsHasName (HsBind n) where
+  hsGetNames (FunBind {fun_id = lname}) = hsGetNames lname
+  hsGetNames (PatBind {pat_lhs = pat}) = hsGetNames pat
+  hsGetNames (VarBind {var_id = id}) = hsGetNames id
+  hsGetNames (PatSynBind (PSB {psb_id = id})) = hsGetNames id
+
+instance HsHasName n => HsHasName (ParStmtBlock l n) where
+  hsGetNames (ParStmtBlock _ binds _) = hsGetNames binds
+
+--instance HsHasName n => HsHasName (LHsTyVarBndrs n) where
+--  hsGetNames (HsQTvs kvs tvs) = hsGetNames kvs ++ hsGetNames tvs
+
+instance HsHasName n => HsHasName (HsTyVarBndr n) where
+  hsGetNames (UserTyVar n) = hsGetNames n
+  hsGetNames (KindedTyVar n _) = hsGetNames n
+
+instance HsHasName n => HsHasName (Stmt n b) where
+  hsGetNames (LetStmt binds) = hsGetNames binds
+  hsGetNames (BindStmt pat _ _ _ _) = hsGetNames pat
+  hsGetNames (RecStmt {recS_rec_ids = ids}) = hsGetNames ids
+  hsGetNames _ = []
+
+instance HsHasName n => HsHasName (Pat n) where
+  hsGetNames (VarPat id) = hsGetNames id
+  hsGetNames (LazyPat p) = hsGetNames p
+  hsGetNames (AsPat lname p) = hsGetNames lname ++ hsGetNames p
+  hsGetNames (ParPat p) = hsGetNames p
+  hsGetNames (BangPat p) = hsGetNames p
+  hsGetNames (ListPat pats _ _) = concatMap hsGetNames pats
+  hsGetNames (TuplePat pats _ _) = concatMap hsGetNames pats
+  hsGetNames (PArrPat pats _) = concatMap hsGetNames pats
+  hsGetNames (ConPatIn _ details) = concatMap hsGetNames (hsConPatArgs details)
+  hsGetNames (ConPatOut {pat_args = details}) = concatMap hsGetNames (hsConPatArgs details)
+  hsGetNames (ViewPat _ p _) = hsGetNames p
+  hsGetNames (NPlusKPat lname _ _ _ _ _) = hsGetNames lname
+  hsGetNames (SigPatIn p _) = hsGetNames p
+  hsGetNames (SigPatOut p _) = hsGetNames p
+  hsGetNames _ = []
+
+-- | Get the original form of a name
+rdrNameStr :: RdrName -> String
+rdrNameStr name = showSDocUnsafe $ ppr name
+
+-- | Tries to simplify the type that has HsAppsTy before renaming. Does not always provide the correct form.
+-- Treats each operator as if they are of equivalent precedence and always left-associative.
+cleanHsType :: OutputableBndr n => HsType n -> HsType n
+-- for some reason * is considered infix
+cleanHsType (HsAppsTy [unLoc -> HsAppInfix t]) = HsTyVar t
+cleanHsType (HsAppsTy apps) = unLoc $ guessType (splitHsAppsTy apps)
+  where guessType :: OutputableBndr n => ([[LHsType n]], [Located n]) -> LHsType n
+        guessType (term:terms, operator:operators)  
+          = let rhs = guessType (terms,operators)
+             in L (getLoc (head term) `combineSrcSpans` getLoc rhs) $ HsOpTy (doApps term) operator rhs
+        guessType ([term],[]) = doApps term
+        guessType x = error ("guessType: " ++ showSDocUnsafe (ppr x))
+        doApps term = foldl1 (\core t -> L (getLoc core `combineSrcSpans` getLoc t) $ HsAppTy core t) term
+cleanHsType t = t
+
+mergeFixityDefs :: [Located (FixitySig n)] -> [Located (FixitySig n)]
+mergeFixityDefs (s@(L l _) : rest) 
+  = let (same, different) = partition ((== l) . getLoc) rest 
+     in foldl mergeWith s (map unLoc same) : mergeFixityDefs different
+  where mergeWith (L l (FixitySig names fixity)) (FixitySig otherNames _) = L l (FixitySig (names ++ otherNames) fixity)
+mergeFixityDefs [] = []
+ Language/Haskell/Tools/AST/FromGHC/Kinds.hs view
@@ -0,0 +1,62 @@+{-# LANGUAGE ViewPatterns #-}
+module Language.Haskell.Tools.AST.FromGHC.Kinds where
+
+import SrcLoc as GHC
+import RdrName as GHC
+import HsTypes as GHC
+import OccName as GHC
+import Name as GHC
+import ApiAnnotation as GHC
+import Outputable as GHC
+import FastString as GHC
+
+import Control.Monad.Reader
+import Data.Data (toConstr)
+
+import Language.Haskell.Tools.AST.FromGHC.GHCUtils
+import Language.Haskell.Tools.AST.FromGHC.Literals
+import Language.Haskell.Tools.AST.FromGHC.Base
+import Language.Haskell.Tools.AST.FromGHC.Monad
+import Language.Haskell.Tools.AST.FromGHC.Utils
+
+import Language.Haskell.Tools.AST (Ann(..), AnnMaybe(..))
+import qualified Language.Haskell.Tools.AST as AST
+
+import Debug.Trace
+
+trfKindSig :: TransformName n r => Maybe (LHsKind n) -> Trf (AnnMaybe AST.KindConstraint r)
+trfKindSig = trfMaybe "" "" trfKindSig'
+
+trfKindSig' :: TransformName n r => Located (HsKind n) -> Trf (Ann AST.KindConstraint r)
+trfKindSig' k = annLoc (combineSrcSpans (getLoc k) <$> (tokenBefore (srcSpanStart (getLoc k)) AnnDcolon)) 
+                       (AST.KindConstraint <$> trfLoc trfKind' k)
+
+trfKind :: TransformName n r => Located (HsKind n) -> Trf (Ann AST.Kind r)
+trfKind = trfLoc (trfKind' . cleanHsType)
+
+trfKind' :: TransformName n r => HsKind n -> Trf (AST.Kind r)
+trfKind' = trfKind'' . cleanHsType where
+  trfKind'' (HsTyVar (rdrName . unLoc -> Exact n)) 
+    | isWiredInName n && occNameString (nameOccName n) == "*"
+    = pure AST.KindStar
+    | isWiredInName n && occNameString (nameOccName n) == "#"
+    = pure AST.KindUnbox
+  trfKind'' (HsParTy kind) = AST.KindParen <$> trfKind kind
+  trfKind'' (HsFunTy k1 k2) = AST.KindFn <$> trfKind k1 <*> trfKind k2
+  trfKind'' (HsAppTy k1 k2) = AST.KindApp <$> trfKind k1 <*> trfKind k2
+  trfKind'' (HsTyVar kv) = transformingPossibleVar kv (AST.KindVar <$> trfName kv)
+  trfKind'' (HsListTy kind) = AST.KindList <$> trfKind kind
+  trfKind'' (HsAppsTy [unLoc -> HsAppPrefix t]) = trfKind' (unLoc t)
+  trfKind'' (HsAppsTy [unLoc -> HsAppInfix n]) = AST.KindVar <$> trfName n
+  trfKind'' pt@(HsExplicitListTy {}) = AST.KindPromoted <$> annCont (trfPromoted' trfKind' pt) 
+  trfKind'' pt@(HsExplicitTupleTy {}) = AST.KindPromoted <$> annCont (trfPromoted' trfKind' pt) 
+  trfKind'' pt@(HsTyLit {}) = AST.KindPromoted <$> annCont (trfPromoted' trfKind' pt) 
+  trfKind'' k = error ("Illegal kind: " ++ showSDocUnsafe (ppr k) ++ " (ctor: " ++ show (toConstr k) ++ ")")
+
+trfPromoted' :: TransformName n r => (HsType n -> Trf (a r)) -> HsType n -> Trf (AST.Promoted a r)
+trfPromoted' f (HsTyLit (HsNumTy _ int)) = pure $ AST.PromotedInt int
+trfPromoted' f (HsTyLit (HsStrTy _ str)) = pure $ AST.PromotedString (unpackFS str)
+trfPromoted' f (HsTyVar name) = AST.PromotedCon <$> trfName name
+trfPromoted' f (HsExplicitListTy _ elems) = AST.PromotedList <$> between AnnOpenS AnnCloseS (trfAnnList ", " f elems)
+trfPromoted' f (HsExplicitTupleTy _ elems) = AST.PromotedTuple <$> between AnnOpenP AnnCloseP (trfAnnList ", " f elems)
+trfPromoted' _ t = asks contRange >>= \r -> error $ "Unknown promoted type/kind: " ++ (showSDocUnsafe (ppr t) ++ " at: " ++ show r)
+ Language/Haskell/Tools/AST/FromGHC/Literals.hs view
@@ -0,0 +1,36 @@+module Language.Haskell.Tools.AST.FromGHC.Literals where
+
+import qualified Data.ByteString.Char8 as BS
+
+import SrcLoc as GHC
+import ApiAnnotation as GHC
+import FastString as GHC
+import BasicTypes as GHC
+import HsLit as GHC
+import HsTypes as GHC
+
+import Language.Haskell.Tools.AST.FromGHC.Base
+import Language.Haskell.Tools.AST.FromGHC.Monad
+import Language.Haskell.Tools.AST.FromGHC.Utils
+
+import qualified Language.Haskell.Tools.AST as AST
+
+trfLiteral' :: HsLit -> Trf (AST.Literal a)
+trfLiteral' (HsChar _ ch) = pure $ AST.CharLit ch
+trfLiteral' (HsCharPrim _ ch) = pure $ AST.PrimCharLit ch
+trfLiteral' (HsString _ str) = pure $ AST.StringLit (unpackFS str)
+trfLiteral' (HsStringPrim _ str) = pure $ AST.PrimStringLit (BS.foldr (:) "" str)
+trfLiteral' (HsInt _ i) = pure $ AST.IntLit i
+trfLiteral' (HsIntPrim _ i) = pure $ AST.PrimIntLit i
+trfLiteral' (HsWordPrim _ i) = pure $ AST.PrimWordLit i
+trfLiteral' (HsInt64Prim _ i) = pure $ AST.PrimIntLit i
+trfLiteral' (HsWord64Prim _ i) = pure $ AST.PrimWordLit i
+trfLiteral' (HsInteger _ i _) = pure $ AST.PrimIntLit i
+trfLiteral' (HsRat frac _) = pure $ AST.FracLit (fl_value frac)
+trfLiteral' (HsFloatPrim frac) = pure $ AST.PrimFloatLit (fl_value frac)
+trfLiteral' (HsDoublePrim frac) = pure $ AST.PrimDoubleLit (fl_value frac)
+  
+trfOverloadedLit :: OverLitVal -> Trf (AST.Literal a)
+trfOverloadedLit (HsIntegral _ i) = pure $ AST.IntLit i
+trfOverloadedLit (HsFractional frac) = pure $ AST.FracLit (fl_value frac)
+trfOverloadedLit (HsIsString _ str) = pure $ AST.StringLit (unpackFS str)
+ Language/Haskell/Tools/AST/FromGHC/Modules.hs view
@@ -0,0 +1,228 @@+{-# LANGUAGE LambdaCase
+           , ViewPatterns
+           , FlexibleContexts
+           , ScopedTypeVariables
+           , TypeApplications
+           #-}
+module Language.Haskell.Tools.AST.FromGHC.Modules where
+
+import Control.Reference hiding (element)
+import Data.Maybe
+import Data.List
+import Data.Char
+import Data.Map as Map hiding (map, filter)
+import Data.IORef
+import Data.Data
+import Data.Generics.Uniplate.Operations
+import Data.Generics.Uniplate.Data
+import Data.StructuralTraversal
+import Control.Monad.Reader
+import Control.Monad.Writer
+import Control.Monad.State
+
+import Avail as GHC
+import GHC as GHC
+import GhcMonad as GHC
+import ApiAnnotation as GHC
+import RdrName as GHC
+import Name as GHC hiding (varName)
+import Id as GHC
+import TysWiredIn as GHC
+import SrcLoc as GHC
+import FastString as GHC
+import Module as GHC
+import BasicTypes as GHC
+import HsSyn as GHC
+import HscTypes as GHC
+import Outputable as GHC
+import TyCon as GHC
+import ConLike as GHC
+import DataCon as GHC
+import Bag as GHC
+import Var as GHC
+import PatSyn as GHC
+import Type as GHC
+import Unique as GHC
+import CoAxiom as GHC
+import DynFlags as GHC
+import Language.Haskell.TH.LanguageExtensions
+
+import Language.Haskell.Tools.AST (Ann(..), AnnMaybe(..), AnnList(..), RangeWithName, RangeWithType, RangeInfo
+                                  , SemanticInfo(..), semanticInfo, sourceInfo, semantics, annotation, nameInfo, nodeSpan)
+import qualified Language.Haskell.Tools.AST as AST
+
+import Language.Haskell.Tools.AST.FromGHC.Base
+import Language.Haskell.Tools.AST.FromGHC.Decls
+import Language.Haskell.Tools.AST.FromGHC.Monad
+import Language.Haskell.Tools.AST.FromGHC.Utils
+
+addTypeInfos :: LHsBinds Id -> Ann AST.Module RangeWithName -> Ghc (Ann AST.Module RangeWithType)
+addTypeInfos bnds mod = traverseDown (return ()) (return ()) replaceNodeInfo mod
+  where replaceNodeInfo :: RangeWithName -> Ghc RangeWithType
+        replaceNodeInfo = semanticInfo !~ replaceSemanticInfo
+        replaceSemanticInfo NoSemanticInfo = return NoSemanticInfo
+        replaceSemanticInfo (ScopeInfo sc) = return $ ScopeInfo sc
+        replaceSemanticInfo (AmbiguousNameInfo sc d rdr l) = return $ NameInfo sc d (locMapping ! l)
+        replaceSemanticInfo (ModuleInfo mod imps) = ModuleInfo mod <$> mapM getType' imps
+        replaceSemanticInfo (NameInfo sc def ni) = NameInfo sc def <$> getType' ni
+        replaceSemanticInfo (ImportInfo mod access used) = ImportInfo mod <$> mapM getType' access <*> mapM getType' used
+        
+        getType' :: GHC.Name -> Ghc GHC.Id
+        getType' name = fromMaybe (error $ "Type of name '" ++ showSDocUnsafe (ppr name) ++ "' cannot be found") <$> getType name
+        getType name 
+          = lookupName name >>= \case
+              Just (AnId id) -> return (Just id)
+              Just (AConLike (RealDataCon dc)) -> return $ Just $ mkVanillaGlobal name (dataConUserType dc)
+              Just (AConLike (PatSynCon ps)) -> return $ Just $ mkVanillaGlobal name (createPatSynType ps)
+              Just (ATyCon tc) -> return $ Just $ mkVanillaGlobal name (tyConKind tc)
+              Nothing -> case Map.lookup name mapping of 
+                           Just id -> return (Just id)
+                           Nothing | isTyVarName name
+                                      -- unit type is for cases we don't know the kind
+                                   -> return $ Just $ mkVanillaGlobal name unitTy
+                           Nothing -> return Nothing
+        mapping = Map.fromList $ map (\id -> (getName id, id)) $ extractTypes bnds
+        locMapping = Map.fromList $ map (\(L l id) -> (l, id)) $ extractExprIds bnds
+        createPatSynType patSyn = case patSynSig patSyn of (_, _, _, _, args, res) -> mkFunTys args res
+
+getTypeVariables :: GHC.TyCon -> [Id]
+getTypeVariables tc
+  = tyConTyVars tc ++ maybe [] (\case (ClosedSynFamilyTyCon ax) -> maybe [] (concatMap cab_tvs . fromBranches . co_ax_branches) ax
+                                      _ -> []) (famTyConFlav_maybe tc)
+
+extractTypes :: LHsBinds Id -> [Id]
+extractTypes = concatMap universeBi . bagToList
+
+extractExprIds :: LHsBinds Id -> [Located Id]
+        -- expressions like HsRecFld are removed from the typechecked representation, they are replaced by HsVar
+extractExprIds = catMaybes . map (\case (L l (HsVar (L _ n))) -> Just (L l n); _ -> Nothing) . concatMap universeBi . bagToList
+
+
+trfModule :: Located (HsModule RdrName) -> Trf (Ann AST.Module RangeInfo)
+trfModule = trfLocCorrect (\sr -> combineSrcSpans sr <$> (uniqueTokenAnywhere AnnEofPos)) $ 
+  \(HsModule name exports imports decls deprec _) -> 
+    AST.Module <$> trfFilePragmas
+               <*> trfModuleHead name exports deprec
+               <*> trfImports imports
+               <*> trfDecls decls
+       
+trfModuleRename :: Module -> Ann AST.Module RangeInfo -> (HsGroup Name, [LImportDecl Name], Maybe [LIE Name], Maybe LHsDocString) -> Located (HsModule RdrName) -> Trf (Ann AST.Module RangeWithName)
+trfModuleRename mod rangeMod (gr,imports,exps,_) hsMod = do 
+  prelude <- lift (xopt ImplicitPrelude . ms_hspp_opts <$> getModSummary (moduleName mod))
+  (_,preludeImports) <- if prelude then getImportedNames "Prelude" Nothing else return (mod, [])
+  let addModuleInfo :: Module -> Ann AST.Module RangeWithName -> Trf (Ann AST.Module RangeWithName)
+      addModuleInfo m = AST.semantics != ModuleInfo m preludeImports
+  addModuleInfo mod =<< trfLocCorrect (\sr -> combineSrcSpans sr <$> (uniqueTokenAnywhere AnnEofPos)) (trfModuleRename' preludeImports) hsMod
+        
+  where originalNames = Map.fromList $ catMaybes $ map getSourceAndInfo (rangeMod ^? biplateRef) 
+        getSourceAndInfo :: Ann AST.SimpleName RangeInfo -> Maybe (SrcSpan, RdrName)
+        getSourceAndInfo n = (,) <$> (n ^? annotation&sourceInfo&nodeSpan) <*> (n ^? semantics&nameInfo)
+        
+        trfModuleRename' preludeImports hsMod@(HsModule name exports _ decls deprec _) = do
+          transformedImports <- orderAnnList <$> (trfImports imports)
+          setOriginalNames originalNames
+            $ AST.Module <$> trfFilePragmas
+                         <*> trfModuleHead name (case (exports, exps) of (Just (L l _), Just ie) -> Just (L l ie)
+                                                                         _                       -> Nothing) deprec
+                         <*> return transformedImports
+                         <*> addToScope (concat @[] (transformedImports ^? AST.annList&semantics&AST.importedNames) ++ preludeImports) (trfDeclsGroup gr)
+
+trfModuleHead :: TransformName n r => Maybe (Located ModuleName) -> Maybe (Located [LIE n]) -> Maybe (Located WarningTxt) -> Trf (AnnMaybe AST.ModuleHead r) 
+trfModuleHead (Just mn) exports modPrag
+  = makeJust <$> (annLoc (tokensLoc [AnnModule, AnnWhere])
+                         (AST.ModuleHead <$> trfModuleName mn 
+                                         <*> trfExportList (srcSpanEnd $ getLoc mn) exports
+                                         <*> trfModulePragma modPrag))
+trfModuleHead _ Nothing _ = nothing "" "" moduleHeadPos
+  where moduleHeadPos = after AnnClose >>= \case loc@(RealSrcLoc _) -> return loc
+                                                 _ -> atTheStart
+
+trfFilePragmas :: RangeAnnot a => Trf (AnnList AST.FilePragma a)
+trfFilePragmas = do pragmas <- asks pragmaComms
+                    languagePragmas <- mapM trfLanguagePragma (fromMaybe [] $ (Map.lookup "LANGUAGE") pragmas)
+                    optionsPragmas <- mapM trfOptionsPragma (fromMaybe [] $ (Map.lookup "OPTIONS_GHC") pragmas)
+                    makeList "" atTheStart $ pure $ orderDefs $ languagePragmas ++ optionsPragmas
+
+trfLanguagePragma :: RangeAnnot a => Located String -> Trf (Ann AST.FilePragma a)
+trfLanguagePragma lstr@(L l str) = annLoc (pure l) (AST.LanguagePragma <$> makeList ", " (pure $ srcSpanStart $ getLoc $ last pragmaElems) 
+                                                                                         (mapM (trfLoc (pure . AST.LanguageExtension)) extensions))
+  where pragmaElems = splitLocated lstr
+        extensions = init $ drop 2 pragmaElems
+
+trfOptionsPragma :: RangeAnnot a => Located String -> Trf (Ann AST.FilePragma a)
+trfOptionsPragma (L l str) = annLoc (pure l) (AST.OptionsPragma <$> annCont (pure $ AST.StringNode str))
+
+trfModulePragma :: RangeAnnot a => Maybe (Located WarningTxt) -> Trf (AnnMaybe AST.ModulePragma a)
+trfModulePragma = trfMaybeDefault " " "" (trfLoc $ \case WarningTxt _ txts -> AST.ModuleWarningPragma <$> trfAnnList " " trfText' txts
+                                                         DeprecatedTxt _ txts -> AST.ModuleDeprecatedPragma <$> trfAnnList " " trfText' txts) 
+                                  (before AnnWhere)
+
+trfText' :: RangeAnnot a => StringLiteral -> Trf (AST.StringNode a)
+trfText' = pure . AST.StringNode . unpackFS . sl_fs
+
+
+
+trfExportList :: TransformName n r => SrcLoc -> Maybe (Located [LIE n]) -> Trf (AnnMaybe AST.ExportSpecList r)
+trfExportList loc = trfMaybeDefault " " "" (trfLoc trfExportList') (pure loc)
+
+trfExportList' :: TransformName n r => [LIE n] -> Trf (AST.ExportSpecList r)
+trfExportList' exps = AST.ExportSpecList <$> (makeList ", " (after AnnOpenP) (orderDefs . catMaybes <$> (mapM trfExport exps)))
+  
+trfExport :: TransformName n r => LIE n -> Trf (Maybe (Ann AST.ExportSpec r))
+trfExport = trfMaybeLoc $ \case 
+  IEModuleContents n -> Just . AST.ModuleExport <$> (trfModuleName n)
+  other -> do trf <- trfIESpec' other
+              fmap AST.DeclExport <$> (sequence $ fmap (annCont . return) trf)
+
+trfImports :: TransformName n r => [LImportDecl n] -> Trf (AnnList AST.ImportDecl r)
+trfImports (filter (not . ideclImplicit . unLoc) -> imps) 
+  = AnnList <$> importDefaultLoc <*> mapM trfImport imps
+  where importDefaultLoc = toIndentedListAnnot (if Data.List.null imps then "\n" else "") "" "\n" . srcSpanEnd 
+                             <$> (combineSrcSpans <$> asks (srcLocSpan . srcSpanStart . contRange) 
+                                                  <*> (srcLocSpan . srcSpanEnd <$> tokenLoc AnnWhere))
+trfImport :: forall n r . TransformName n r => LImportDecl n -> Trf (Ann AST.ImportDecl r)
+trfImport = (addImportData @r @n <=<) $ trfLoc $ \(GHC.ImportDecl src name pkg isSrc isSafe isQual isImpl declAs declHiding) ->
+  let -- default positions of optional parts of an import declaration
+      annBeforeQual = if isSrc then AnnClose else AnnImport
+      annBeforeSafe = if isQual then AnnQualified else annBeforeQual
+      annBeforePkg = if isSafe then AnnSafe else annBeforeSafe
+      atAsPos = if isJust declHiding then before AnnOpenP else atTheEnd
+  in AST.ImportDecl 
+       <$> (if isSrc then makeJust <$> annLoc (tokensLoc [AnnOpen, AnnClose]) (pure AST.ImportSource)
+                     else nothing " " "" (after AnnImport))
+       <*> (if isQual then makeJust <$> (annLoc (tokenLoc AnnQualified) (pure AST.ImportQualified)) 
+                      else nothing " " "" (after annBeforeQual))
+       <*> (if isSafe then makeJust <$> (annLoc (tokenLoc AnnSafe) (pure AST.ImportSafe)) 
+                      else nothing " " "" (after annBeforeSafe))
+       <*> maybe (nothing " " "" (after annBeforePkg)) 
+                 (\str -> makeJust <$> (annLoc (tokenLoc AnnPackageName) (pure (AST.StringNode (unpackFS $ sl_fs str))))) pkg
+       <*> trfModuleName name 
+       <*> maybe (nothing " " "" atAsPos) (\mn -> makeJust <$> (trfRenaming mn)) declAs
+       <*> trfImportSpecs declHiding
+  where trfRenaming mn
+          = annLoc (tokensLoc [AnnAs,AnnVal])
+                   (AST.ImportRenaming <$> (annLoc (tokenLoc AnnVal) 
+                                           (trfModuleName' mn)))  
+  
+trfImportSpecs :: TransformName n r => Maybe (Bool, Located [LIE n]) -> Trf (AnnMaybe AST.ImportSpec r)
+trfImportSpecs (Just (True, l)) 
+  = makeJust <$> trfLoc (\specs -> AST.ImportSpecHiding <$> (makeList ", " (after AnnOpenP) (catMaybes <$> mapM trfIESpec specs))) l
+trfImportSpecs (Just (False, l)) 
+  = makeJust <$> trfLoc (\specs -> AST.ImportSpecList <$> (makeList ", " (after AnnOpenP) (catMaybes <$> mapM trfIESpec specs))) l
+trfImportSpecs Nothing = nothing " " "" atTheEnd
+    
+trfIESpec :: TransformName n r => LIE n -> Trf (Maybe (Ann AST.IESpec r)) 
+trfIESpec = trfMaybeLoc trfIESpec'
+  
+trfIESpec' :: TransformName n r => IE n -> Trf (Maybe (AST.IESpec r))
+trfIESpec' (IEVar n) = Just <$> (AST.IESpec <$> trfName n <*> (nothing "(" ")" atTheEnd))
+trfIESpec' (IEThingAbs n) = Just <$> (AST.IESpec <$> trfName n <*> (nothing "(" ")" atTheEnd))
+trfIESpec' (IEThingAll n) 
+  = Just <$> (AST.IESpec <$> trfName n <*> (makeJust <$> (annLoc (tokenLoc AnnDotdot) (pure AST.SubSpecAll))))
+trfIESpec' (IEThingWith n _ ls _)
+  = Just <$> (AST.IESpec <$> trfName n
+                         <*> (makeJust <$> between AnnOpenP AnnCloseP 
+                                                  (annCont $ AST.SubSpecList <$> makeList ", " (after AnnOpenP) (mapM trfName ls))))
+trfIESpec' _ = pure Nothing
+  
+ 
+ Language/Haskell/Tools/AST/FromGHC/Monad.hs view
@@ -0,0 +1,80 @@+-- | The transformation monad carries the necessary information that is passed top-down
+-- during the conversion from GHC AST to our representation.
+module Language.Haskell.Tools.AST.FromGHC.Monad where
+
+import SrcLoc
+import GHC
+import Name
+import ApiAnnotation
+import Outputable (ppr, showSDocUnsafe)
+import Control.Monad.Reader
+import Language.Haskell.Tools.AST.FromGHC.SourceMap
+import Language.Haskell.Tools.AST.FromGHC.GHCUtils
+import Data.Map as Map
+import Data.Maybe
+
+import Debug.Trace
+
+-- | The transformation monad type
+type Trf = ReaderT TrfInput Ghc
+
+-- | The (immutable) data for the transformation
+data TrfInput
+  = TrfInput { srcMap :: SourceMap -- ^ The lexical tokens of the source file
+             , pragmaComms :: Map String [Located String] -- ^ Pragma comments
+             , contRange :: SrcSpan -- ^ The focus of the transformation
+             , localsInScope :: [[GHC.Name]] -- ^ Local names visible
+             , defining :: Bool -- ^ True, if names are defined in the transformed AST element.
+             , definingTypeVars :: Bool -- ^ True, if type variable names are defined in the transformed AST element.
+             , originalNames :: Map SrcSpan RdrName -- ^ Stores the original format of names.
+             }
+      
+trfInit :: Map ApiAnnKey [SrcSpan] -> Map String [Located String] -> TrfInput
+trfInit annots comments 
+  = TrfInput { srcMap = annotationsToSrcMap annots
+             , pragmaComms = comments
+             , contRange = noSrcSpan
+             , localsInScope = []
+             , defining = False
+             , definingTypeVars = False
+             , originalNames = empty
+             }
+
+-- | Perform the transformation taking names as defined.
+define :: Trf a -> Trf a
+define = local (\s -> s { defining = True })
+
+-- | Perform the transformation taking type variable names as defined.
+defineTypeVars :: Trf a -> Trf a
+defineTypeVars = local (\s -> s { definingTypeVars = True })
+
+-- | Transform as type variables
+typeVarTransform :: Trf a -> Trf a
+typeVarTransform = local (\s -> s { defining = defining s || definingTypeVars s })
+
+-- | Transform a name as a type variable if it is one.
+transformingPossibleVar :: HsHasName n => n -> Trf a -> Trf a
+transformingPossibleVar n = case hsGetNames n of 
+  [name] | isVarName name || isTyVarName name -> typeVarTransform
+  _                                           -> id
+
+-- | Perform the transformation putting the given definition in a new local scope.
+addToScope :: HsHasName e => e -> Trf a -> Trf a
+addToScope e = local (\s -> s { localsInScope = hsGetNames e : localsInScope s }) 
+
+-- | Perform the transformation putting the given definitions in the current scope.
+addToCurrentScope :: HsHasName e => e -> Trf a -> Trf a
+addToCurrentScope e = local (\s -> s { localsInScope = case localsInScope s of lastScope:rest -> (hsGetNames e ++ lastScope):rest
+                                                                               []             -> [hsGetNames e] })
+
+-- | Performs the transformation given the tokens of the source file
+runTrf :: Map ApiAnnKey [SrcSpan] -> Map String [Located String] -> Trf a -> Ghc a
+runTrf annots comments trf = runReaderT trf (trfInit annots comments)
+
+setOriginalNames :: Map SrcSpan RdrName -> Trf a -> Trf a
+setOriginalNames names = local (\s -> s { originalNames = names })
+
+-- | Get the original format of a name (before scoping).
+getOriginalName :: RdrName -> Trf String
+getOriginalName n = do sp <- asks contRange
+                       asks (rdrNameStr . fromMaybe n . (Map.lookup sp) . originalNames)
+ Language/Haskell/Tools/AST/FromGHC/Patterns.hs view
@@ -0,0 +1,70 @@+{-# LANGUAGE LambdaCase
+           , ViewPatterns
+           , ScopedTypeVariables
+           , AllowAmbiguousTypes
+           #-}
+module Language.Haskell.Tools.AST.FromGHC.Patterns where
+
+import SrcLoc as GHC
+import RdrName as GHC
+import HsTypes as GHC
+import HsPat as GHC
+import HsLit as GHC
+import ApiAnnotation as GHC
+import BasicTypes as GHC
+import Unique as GHC
+import Debug.Trace
+import Data.List
+import Language.Haskell.Tools.AST.FromGHC.GHCUtils
+
+import Language.Haskell.Tools.AST.FromGHC.Base
+import {-# SOURCE #-} Language.Haskell.Tools.AST.FromGHC.TH
+import Language.Haskell.Tools.AST.FromGHC.Literals
+import Language.Haskell.Tools.AST.FromGHC.Types
+import {-# SOURCE #-} Language.Haskell.Tools.AST.FromGHC.Exprs
+import Language.Haskell.Tools.AST.FromGHC.Monad
+import Language.Haskell.Tools.AST.FromGHC.Utils
+
+import Language.Haskell.Tools.AST (Ann(..))
+import qualified Language.Haskell.Tools.AST as AST
+
+trfPattern :: TransformName n r => Located (Pat n) -> Trf (Ann AST.Pattern r)
+-- field wildcards are not directly represented in GHC AST
+trfPattern (L l (ConPatIn name (RecCon (HsRecFields flds _)))) | any ((l ==) . getLoc) flds 
+  = do let (fromWC, notWC) = partition ((l ==) . getLoc) flds
+       normalFields <- mapM (trfLoc trfPatternField') notWC
+       wildc <- annLoc (tokenLoc AnnDotdot) (pure AST.FieldWildcardPattern)
+       annLoc (pure l) (AST.RecPat <$> trfName name <*> makeNonemptyList ", " (pure (normalFields ++ [wildc])))
+trfPattern p | otherwise = trfLoc trfPattern' (correctPatternLoc p)
+
+-- | Locations for right-associative infix patterns are incorrect in GHC AST
+correctPatternLoc :: Located (Pat n) -> Located (Pat n)
+correctPatternLoc (L l p@(ConPatIn name (InfixCon left right)))
+  = L (getLoc (correctPatternLoc left) `combineSrcSpans` getLoc (correctPatternLoc right)) p
+correctPatternLoc p = p
+
+trfPattern' :: TransformName n r => Pat n -> Trf (AST.Pattern r)
+trfPattern' (WildPat _) = pure AST.WildPat
+trfPattern' (VarPat name) = define $ AST.VarPat <$> trfName name
+trfPattern' (LazyPat pat) = AST.IrrPat <$> trfPattern pat
+trfPattern' (AsPat name pat) = AST.AsPat <$> define (trfName name) <*> trfPattern pat
+trfPattern' (ParPat pat) = AST.ParenPat <$> trfPattern pat
+trfPattern' (BangPat pat) = AST.BangPat <$> trfPattern pat
+trfPattern' (ListPat pats _ _) = AST.ListPat <$> trfAnnList ", " trfPattern' pats
+trfPattern' (TuplePat pats Boxed _) = AST.TuplePat <$> trfAnnList ", " trfPattern' pats
+trfPattern' (PArrPat pats _) = AST.ParArrPat <$> trfAnnList ", " trfPattern' pats
+trfPattern' (ConPatIn name (PrefixCon args)) = AST.AppPat <$> trfName name <*> trfAnnList " " trfPattern' args
+trfPattern' (ConPatIn name (RecCon (HsRecFields flds _))) = AST.RecPat <$> trfName name <*> trfAnnList ", " trfPatternField' flds
+trfPattern' (ConPatIn name (InfixCon left right)) = AST.InfixPat <$> trfPattern left <*> trfOperator name <*> trfPattern right
+trfPattern' (ViewPat expr pat _) = AST.ViewPat <$> trfExpr expr <*> trfPattern pat
+trfPattern' (SplicePat splice) = AST.SplicePat <$> annCont (trfSplice' splice)
+trfPattern' (LitPat lit) = AST.LitPat <$> annCont (trfLiteral' lit)
+trfPattern' (SigPatIn pat (hswc_body . hsib_body -> typ)) = AST.TypeSigPat <$> trfPattern pat <*> trfType typ
+trfPattern' (NPat (ol_val . unLoc -> lit) _ _ _) = AST.LitPat <$> annCont (trfOverloadedLit lit)
+trfPattern' (NPlusKPat id (L l lit) _ _ _ _) = AST.NPlusKPat <$> define (trfName id) <*> annLoc (pure l) (trfOverloadedLit (ol_val lit))
+-- coercion pattern introduced by GHC
+trfPattern' (CoPat _ pat _) = trfPattern' pat
+
+trfPatternField' :: TransformName n r => HsRecField n (LPat n) -> Trf (AST.PatternField r)
+trfPatternField' (HsRecField id arg False) = AST.NormalFieldPattern <$> trfName (getFieldOccName id) <*> trfPattern arg
+trfPatternField' (HsRecField id _ True) = AST.FieldPunPattern <$> trfName (getFieldOccName id)
+ Language/Haskell/Tools/AST/FromGHC/SourceMap.hs view
@@ -0,0 +1,44 @@+-- | A representation of the tokens that build up the source file.
+module Language.Haskell.Tools.AST.FromGHC.SourceMap where
+
+import ApiAnnotation
+import Data.Map as Map
+import Data.List as List
+import Safe
+
+import SrcLoc as GHC
+import FastString as GHC
+
+-- We store tokens in the source map so it is not a problem that they cannot overlap
+type SourceMap = Map AnnKeywordId (Map SrcLoc SrcLoc)
+
+-- | Returns the first occurrence of the keyword in the whole source file
+getKeywordAnywhere :: AnnKeywordId -> SourceMap -> Maybe SrcSpan
+getKeywordAnywhere keyw srcmap = return . uncurry mkSrcSpan =<< headMay . assocs =<< (Map.lookup keyw srcmap)
+
+-- | Get the source location of a token restricted to a certain source span
+getKeywordInside :: AnnKeywordId -> SrcSpan -> SourceMap -> Maybe SrcSpan
+getKeywordInside keyw sr srcmap = getSourceElementInside True sr =<< Map.lookup keyw srcmap
+
+getKeywordsInside :: AnnKeywordId -> SrcSpan -> SourceMap -> [SrcSpan]
+getKeywordsInside keyw sr srcmap 
+  = maybe [] (List.map (uncurry mkSrcSpan) . assocs . fst . Map.split (srcSpanEnd sr) . snd . Map.split (srcSpanStart sr)) (Map.lookup keyw srcmap)
+
+getKeywordInsideBack :: AnnKeywordId -> SrcSpan -> SourceMap -> Maybe SrcSpan
+getKeywordInsideBack keyw sr srcmap = getSourceElementInside False sr =<< Map.lookup keyw srcmap
+
+getSourceElementInside :: Bool -> SrcSpan -> Map SrcLoc SrcLoc -> Maybe SrcSpan
+getSourceElementInside b sr srcmap = 
+  case (if b then lookupGE (srcSpanStart sr) else lookupLT (srcSpanEnd sr)) srcmap of
+    Just (k, v) -> let sp = mkSrcSpan k v in if sp `isSubspanOf` sr then Just sp else Nothing
+    Nothing -> Nothing
+    
+-- | Converts GHC Annotations into a convenient format for looking up tokens
+annotationsToSrcMap :: Map ApiAnnKey [SrcSpan] -> Map AnnKeywordId (Map SrcLoc SrcLoc)
+annotationsToSrcMap anns = Map.map (List.foldr addToSrcRanges Map.empty) $ mapKeysWith (++) snd anns
+  where 
+    addToSrcRanges :: SrcSpan -> Map SrcLoc SrcLoc -> Map SrcLoc SrcLoc
+    addToSrcRanges span srcmap = Map.insert (srcSpanStart span) (srcSpanEnd span) srcmap
+    
+    
+                
+ Language/Haskell/Tools/AST/FromGHC/Stmts.hs view
@@ -0,0 +1,80 @@+{-# LANGUAGE LambdaCase
+           , ViewPatterns
+           #-}
+module Language.Haskell.Tools.AST.FromGHC.Stmts where
+ 
+import Data.Maybe
+import Control.Monad.Reader
+
+import SrcLoc as GHC
+import RdrName as GHC
+import HsTypes as GHC
+import HsPat as GHC
+import HsExpr as GHC
+import ApiAnnotation as GHC
+
+import Language.Haskell.Tools.AST.FromGHC.Base
+import Language.Haskell.Tools.AST.FromGHC.Types
+import {-# SOURCE #-} Language.Haskell.Tools.AST.FromGHC.Exprs
+import Language.Haskell.Tools.AST.FromGHC.Patterns
+import {-# SOURCE #-} Language.Haskell.Tools.AST.FromGHC.Binds
+import Language.Haskell.Tools.AST.FromGHC.Monad
+import Language.Haskell.Tools.AST.FromGHC.Utils
+
+import Language.Haskell.Tools.AST (Ann(..), AnnList(..), AnnMaybe(..))
+import qualified Language.Haskell.Tools.AST as AST
+ 
+trfDoStmt :: TransformName n r => Located (Stmt n (LHsExpr n)) -> Trf (Ann AST.Stmt r)
+trfDoStmt = trfLoc trfDoStmt'
+
+trfDoStmt' :: TransformName n r => Stmt n (Located (HsExpr n)) -> Trf (AST.Stmt' AST.Expr r)
+trfDoStmt' = gTrfDoStmt' trfExpr
+
+gTrfDoStmt' :: TransformName n r => (Located (ge n) -> Trf (Ann ae r)) -> Stmt n (Located (ge n)) -> Trf (AST.Stmt' ae r)
+gTrfDoStmt' et (BindStmt pat expr _ _ _) = AST.BindStmt <$> trfPattern pat <*> et expr
+gTrfDoStmt' et (BodyStmt expr _ _ _) = AST.ExprStmt <$> et expr
+gTrfDoStmt' et (LetStmt (unLoc -> binds)) = AST.LetStmt <$> addToScope binds (trfLocalBinds binds)
+gTrfDoStmt' et (LastStmt body _ _) = AST.ExprStmt <$> et body
+gTrfDoStmt' et (RecStmt { recS_stmts = stmts }) = AST.RecStmt <$> trfAnnList "," (gTrfDoStmt' et) stmts
+
+trfListCompStmts :: TransformName n r => [Located (Stmt n (LHsExpr n))] -> Trf (AnnList AST.ListCompBody r)
+trfListCompStmts [unLoc -> ParStmt blocks _ _ _, unLoc -> (LastStmt {})]
+  = nonemptyAnnList
+      <$> trfScopedSequence (\(ParStmtBlock stmts _ _) -> 
+                                let ann = toNodeAnnot $ collectLocs $ getNormalStmts stmts
+                                 in Ann ann . AST.ListCompBody . AnnList ann . concat 
+                                      <$> trfScopedSequence trfListCompStmt stmts
+                            ) blocks
+trfListCompStmts others 
+  = let ann = (collectLocs $ getNormalStmts others)
+     in AnnList (toNodeAnnot ann) . (:[]) 
+          <$> annLoc (pure ann)
+                     (AST.ListCompBody . AnnList (toNodeAnnot ann) . concat <$> trfScopedSequence trfListCompStmt others) 
+
+trfListCompStmt :: TransformName n r => Located (Stmt n (LHsExpr n)) -> Trf [Ann AST.CompStmt r]
+trfListCompStmt (L l trst@(TransStmt { trS_stmts = stmts })) 
+  = (++) <$> (concat <$> local (\s -> s { contRange = mkSrcSpan (srcSpanStart (contRange s)) (srcSpanEnd (getLoc (last stmts))) }) (trfScopedSequence trfListCompStmt stmts)) 
+         <*> ((:[]) <$> extractActualStmt trst)
+-- last statement is extracted
+trfListCompStmt (unLoc -> LastStmt _ _ _) = pure []
+trfListCompStmt other = (:[]) <$> copyAnnot AST.CompStmt (trfDoStmt other)
+  
+extractActualStmt :: TransformName n r => Stmt n (LHsExpr n) -> Trf (Ann AST.CompStmt r)
+extractActualStmt = \case
+  TransStmt { trS_form = ThenForm, trS_using = using, trS_by = by } 
+    -> addAnnotation by using (AST.ThenStmt <$> trfExpr using <*> trfMaybe "," "" trfExpr by)
+  TransStmt { trS_form = GroupForm, trS_using = using, trS_by = by } 
+    -> addAnnotation by using (AST.GroupStmt <$> trfMaybe "," "" trfExpr by <*> (makeJust <$> trfExpr using))
+  where addAnnotation by using
+          = annLoc (combineSrcSpans (getLoc using) . combineSrcSpans (maybe noSrcSpan getLoc by)
+                      <$> tokenLocBack AnnThen)
+  
+getNormalStmts :: [Located (Stmt n (LHsExpr n))] -> [Located (Stmt n (LHsExpr n))]
+getNormalStmts (L _ (LastStmt body _ _) : rest) = getNormalStmts rest
+getNormalStmts (stmt : rest) = stmt : getNormalStmts rest 
+getNormalStmts [] = []
+ 
+getLastStmt :: [Located (Stmt n (LHsExpr n))] -> Located (HsExpr n)
+getLastStmt (L _ (LastStmt body _ _) : rest) = body
+getLastStmt (_ : rest) = getLastStmt rest
+  
+ Language/Haskell/Tools/AST/FromGHC/TH.hs view
@@ -0,0 +1,42 @@+module Language.Haskell.Tools.AST.FromGHC.TH where
+
+import SrcLoc as GHC
+import RdrName as GHC
+import HsTypes as GHC
+import HsExpr as GHC
+import ApiAnnotation as GHC
+import FastString as GHC
+import OccName as GHC
+import SrcLoc as GHC
+
+import Language.Haskell.Tools.AST.FromGHC.Monad
+import Language.Haskell.Tools.AST.FromGHC.Utils
+import Language.Haskell.Tools.AST.FromGHC.Decls
+import Language.Haskell.Tools.AST.FromGHC.Exprs
+import Language.Haskell.Tools.AST.FromGHC.Types
+import Language.Haskell.Tools.AST.FromGHC.Patterns
+import Language.Haskell.Tools.AST.FromGHC.Base
+import Language.Haskell.Tools.AST.FromGHC.GHCUtils
+
+import qualified Language.Haskell.Tools.AST as AST
+
+trfQuasiQuotation' :: TransformName n r => HsSplice n -> Trf (AST.QuasiQuote r)
+ -- the lexer does not provide us with tokens '[', '|' and '|]'
+trfQuasiQuotation' (HsQuasiQuote id _ l str) 
+  = AST.QuasiQuote <$> annLoc (pure quoterLoc) (trfName' id)
+                   <*> annLoc (pure strLoc) (pure $ AST.QQString (unpackFS str))
+  where quoterLoc = mkSrcSpan (updateCol (subtract (1 + length (occNameString $ rdrNameOcc $ rdrName id))) (srcSpanStart l)) 
+                              (updateCol (subtract 1) (srcSpanStart l))
+        strLoc = mkSrcSpan (srcSpanStart l) (updateCol (subtract 2) (srcSpanEnd l))
+
+
+trfSplice' :: TransformName n r => HsSplice n -> Trf (AST.Splice r)
+trfSplice' (HsTypedSplice _ expr) = AST.ParenSplice <$> trfExpr expr
+trfBracket' :: TransformName n r => HsBracket n -> Trf (AST.Bracket r)
+trfBracket' (ExpBr expr) = AST.ExprBracket <$> trfExpr expr
+trfBracket' (TExpBr expr) = AST.ExprBracket <$> trfExpr expr
+trfBracket' (VarBr _ expr) = AST.ExprBracket <$> annCont (AST.Var <$> (annCont (trfName' expr)))
+trfBracket' (PatBr pat) = AST.PatternBracket <$> trfPattern pat
+trfBracket' (DecBrL decls) = AST.DeclsBracket <$> trfDecls decls
+trfBracket' (DecBrG decls) = AST.DeclsBracket <$> trfDeclsGroup decls
+trfBracket' (TypBr typ) = AST.TypeBracket <$> trfType typ
+ Language/Haskell/Tools/AST/FromGHC/TH.hs-boot view
@@ -0,0 +1,15 @@+module Language.Haskell.Tools.AST.FromGHC.TH where
+
+import SrcLoc as GHC
+import RdrName as GHC
+import HsTypes as GHC
+import HsExpr as GHC
+import Language.Haskell.Tools.AST.FromGHC.Monad
+import Language.Haskell.Tools.AST.FromGHC.Utils
+import Language.Haskell.Tools.AST.FromGHC.Base
+import Language.Haskell.Tools.AST (Ann(..))
+import qualified Language.Haskell.Tools.AST as AST
+
+trfQuasiQuotation' :: TransformName n r => HsSplice n -> Trf (AST.QuasiQuote r)
+trfSplice' :: TransformName n r => HsSplice n -> Trf (AST.Splice r)
+trfBracket' :: TransformName n r => HsBracket n -> Trf (AST.Bracket r)
+ Language/Haskell/Tools/AST/FromGHC/Types.hs view
@@ -0,0 +1,111 @@+{-# LANGUAGE LambdaCase
+           , ViewPatterns
+           , ScopedTypeVariables
+           #-}
+module Language.Haskell.Tools.AST.FromGHC.Types where
+ 
+import SrcLoc as GHC
+import RdrName as GHC
+import HsTypes as GHC
+import ApiAnnotation as GHC
+import FastString as GHC
+import Type as GHC
+import TyCon as GHC
+import Outputable as GHC
+import TysWiredIn (heqTyCon)
+import Id (mkVanillaGlobal)
+
+import Control.Monad.Reader.Class
+import Control.Applicative
+import Control.Reference
+import Data.Maybe
+import Data.Data (Data(..), toConstr)
+
+import Language.Haskell.Tools.AST.FromGHC.GHCUtils
+import Language.Haskell.Tools.AST.FromGHC.Base
+import {-# SOURCE #-} Language.Haskell.Tools.AST.FromGHC.TH
+import Language.Haskell.Tools.AST.FromGHC.Kinds
+import Language.Haskell.Tools.AST.FromGHC.Monad
+import Language.Haskell.Tools.AST.FromGHC.Utils
+import Language.Haskell.Tools.AST.FromGHC.Literals
+
+import Language.Haskell.Tools.AST as AST
+
+import Debug.Trace
+
+trfType :: TransformName n r => Located (HsType n) -> Trf (Ann AST.Type r)
+trfType = trfLoc trfType'
+
+trfType' :: TransformName n r => HsType n -> Trf (AST.Type r)
+trfType' = trfType'' . cleanHsType where
+  trfType'' (HsForAllTy [] typ) = trfType' (unLoc typ)
+  trfType'' (HsForAllTy bndrs typ) = AST.TyForall <$> defineTypeVars (trfBindings bndrs) 
+                                                  <*> addToScope bndrs (trfType typ)
+  trfType'' (HsQualTy ctx typ) = AST.TyCtx <$> (fromJust . (^. annMaybe) <$> trfCtx atTheStart ctx) 
+                                           <*> trfType typ
+  trfType'' (HsTyVar name) = AST.TyVar <$> transformingPossibleVar name (trfName name)
+  trfType'' (HsAppsTy apps) | Just (head, args) <- getAppsTyHead_maybe apps 
+    = foldl (\core t -> AST.TyApp <$> annLoc (pure $ getLoc head `combineSrcSpans` getLoc t) core <*> trfType t) (trfType' (unLoc head)) args
+  trfType'' (HsAppTy t1 t2) = AST.TyApp <$> trfType t1 <*> trfType t2
+  trfType'' (HsFunTy t1 t2) = AST.TyFun <$> trfType t1 <*> trfType t2
+  trfType'' (HsListTy typ) = AST.TyList <$> trfType typ
+  trfType'' (HsPArrTy typ) = AST.TyParArray <$> trfType typ
+  trfType'' (HsTupleTy HsBoxedOrConstraintTuple typs) = AST.TyTuple <$> trfAnnList ", " trfType' typs
+  trfType'' (HsTupleTy HsBoxedTuple typs) = AST.TyTuple <$> trfAnnList ", " trfType' typs
+  trfType'' (HsTupleTy HsUnboxedTuple typs) = AST.TyUnbTuple <$> trfAnnList ", " trfType' typs
+  trfType'' (HsOpTy t1 op t2) = AST.TyInfix <$> trfType t1 <*> trfOperator op <*> trfType t2
+  trfType'' (HsParTy typ) = AST.TyParen <$> trfType typ
+  trfType'' (HsKindSig typ kind) = AST.TyKinded <$> trfType typ <*> trfKind kind
+  trfType'' (HsSpliceTy splice _) = AST.TySplice <$> trfSplice' splice
+  trfType'' (HsBangTy (HsSrcBang _ SrcUnpack _) typ) = AST.TyUnpack <$> trfType typ
+  trfType'' (HsBangTy (HsSrcBang _ SrcNoUnpack _) typ) = AST.TyNoUnpack <$> trfType typ
+  trfType'' (HsBangTy (HsSrcBang _ _ SrcStrict) typ) = AST.TyBang <$> trfType typ
+  trfType'' (HsBangTy (HsSrcBang _ _ SrcLazy) typ) = AST.TyLazy <$> trfType typ
+  trfType'' pt@(HsExplicitListTy {}) = AST.TyPromoted <$> annCont (trfPromoted' trfType' pt) 
+  trfType'' pt@(HsExplicitTupleTy {}) = AST.TyPromoted <$> annCont (trfPromoted' trfType' pt) 
+  trfType'' pt@(HsTyLit {}) = AST.TyPromoted <$> annCont (trfPromoted' trfType' pt) 
+  trfType'' (HsWildCardTy _) = pure AST.TyWildcard -- TODO: named wildcards
+  trfType'' t = error ("Illegal type: " ++ showSDocUnsafe (ppr t) ++ " (ctor: " ++ show (toConstr t) ++ ")")
+  
+trfBindings :: TransformName n r => [Located (HsTyVarBndr n)] -> Trf (AnnList AST.TyVar r)
+trfBindings vars = trfAnnList "\n" trfTyVar' vars
+  
+trfTyVar :: TransformName n r => Located (HsTyVarBndr n) -> Trf (Ann AST.TyVar r)
+trfTyVar = trfLoc trfTyVar' 
+  
+trfTyVar' :: TransformName n r => HsTyVarBndr n -> Trf (AST.TyVar r)
+trfTyVar' (UserTyVar name) = AST.TyVarDecl <$> typeVarTransform (trfName name)
+                                           <*> (nothing " " "" atTheEnd)
+trfTyVar' (KindedTyVar name kind) = AST.TyVarDecl <$> typeVarTransform (trfName name) 
+                                                  <*> trfKindSig (Just kind)
+  
+trfCtx :: TransformName n r => Trf SrcLoc -> Located (HsContext n) -> Trf (AnnMaybe AST.Context r)
+trfCtx sp (L l []) = nothing " " "" sp
+trfCtx _ (L l [L _ (HsParTy t)]) 
+  = makeJust <$> annLoc (combineSrcSpans l <$> tokenLoc AnnDarrow) 
+                        (AST.ContextMulti <$> trfAnnList ", " trfAssertion' [t])
+trfCtx _ (L l [t]) 
+  = makeJust <$> annLoc (combineSrcSpans l <$> tokenLoc AnnDarrow) 
+                        (AST.ContextOne <$> trfAssertion t)
+trfCtx _ (L l ctx) = makeJust <$> annLoc (combineSrcSpans l <$> tokenLoc AnnDarrow) 
+                                         (AST.ContextMulti <$> trfAnnList ", " trfAssertion' ctx) 
+  
+trfAssertion :: TransformName n r => LHsType n -> Trf (Ann AST.Assertion r)
+trfAssertion = trfLoc trfAssertion'
+
+trfAssertion' :: forall n r . TransformName n r => HsType n -> Trf (AST.Assertion r)
+trfAssertion' (cleanHsType -> HsParTy t) 
+  = trfAssertion' (unLoc t)
+trfAssertion' (cleanHsType -> HsOpTy left op right) 
+  = AST.InfixAssert <$> trfType left <*> trfOperator op <*> trfType right
+trfAssertion' (cleanHsType -> t) = case cleanHsType base of
+   HsTyVar name -> AST.ClassAssert <$> trfName name <*> trfAnnList " " trfType' args
+   HsEqTy t1 t2 -> AST.InfixAssert <$> trfType t1 <*> annLoc (tokenLoc AnnTilde) (trfOperator' typeEq) <*> trfType t2
+   t -> error ("Illegal trf assertion: " ++ showSDocUnsafe (ppr t) ++ " (ctor: " ++ show (toConstr t) ++ ")")
+  where (args, sp, base) = getArgs t
+        getArgs :: HsType n -> ([LHsType n], Maybe SrcSpan, HsType n)
+        getArgs (HsAppTy (L l ft) at) = case getArgs ft of (args, sp, base) -> (args++[at], sp <|> Just l, base)
+        getArgs t = ([], Nothing, t)
+
+        typeEq :: n 
+        typeEq = nameFromId (mkVanillaGlobal (tyConName heqTyCon) (tyConKind heqTyCon))
+ Language/Haskell/Tools/AST/FromGHC/Utils.hs view
@@ -0,0 +1,342 @@+-- | Utility functions for transforming the GHC AST representation into our own.
+{-# LANGUAGE TypeSynonymInstances 
+           , FlexibleInstances
+           , LambdaCase
+           , ViewPatterns
+           , MultiParamTypeClasses
+           , FlexibleContexts
+           , AllowAmbiguousTypes
+           #-}
+module Language.Haskell.Tools.AST.FromGHC.Utils where
+
+import ApiAnnotation
+import SrcLoc
+import GHC
+import Avail
+import HscTypes
+import HsSyn
+import Module
+import Name
+import Outputable
+import FastString
+
+import Control.Monad.Reader
+import Control.Reference hiding (element)
+import Data.Maybe
+import Data.IORef
+import Data.Function hiding ((&))
+import Data.List
+import Data.Char
+import Language.Haskell.Tools.AST as AST
+import Language.Haskell.Tools.AST.FromGHC.Monad
+import Language.Haskell.Tools.AST.FromGHC.GHCUtils
+import Language.Haskell.Tools.AST.FromGHC.SourceMap
+import Debug.Trace
+
+-- | Annotations that is made up from ranges
+class HasRange annot => RangeAnnot annot where
+  toNodeAnnot :: SrcSpan -> annot
+  toListAnnot :: String -> String -> String -> SrcLoc -> annot
+  toIndentedListAnnot :: String -> String -> String -> SrcLoc -> annot
+  toOptAnnot :: String -> String -> SrcLoc -> annot
+
+instance RangeAnnot (NodeInfo (SemanticInfo n) SpanInfo) where
+  toNodeAnnot = NodeInfo NoSemanticInfo . NodeSpan
+  toListAnnot bef aft sep = NodeInfo NoSemanticInfo . ListPos bef aft sep False
+  toIndentedListAnnot bef aft sep = NodeInfo NoSemanticInfo . ListPos bef aft sep True
+  toOptAnnot bef aft = NodeInfo NoSemanticInfo . OptionalPos bef aft
+
+-- | Annotations that carry semantic information
+class SemanticAnnot annot n where
+  addSemanticInfo :: SemanticInfo n -> annot -> annot
+  addScopeData :: annot -> Trf annot
+  addImportData :: Ann AST.ImportDecl annot -> Trf (Ann AST.ImportDecl annot)
+  
+instance SemanticAnnot RangeWithName GHC.Name where
+  addSemanticInfo si = semanticInfo .= si
+  addScopeData = semanticInfo !~ (\case NoSemanticInfo -> do locals <- asks localsInScope
+                                                             return $ ScopeInfo locals
+                                        inf -> return inf)
+  addImportData = addImportData'
+
+instance {-# OVERLAPPING #-} SemanticAnnot RangeInfo RdrName where
+  addSemanticInfo si = semanticInfo .= si
+  addScopeData = semanticInfo !~ (\case NoSemanticInfo -> do locals <- asks localsInScope
+                                                             return $ ScopeInfo locals
+                                        inf -> return inf)
+  addImportData = pure
+
+instance {-# OVERLAPPABLE #-} SemanticAnnot RangeInfo n where
+  addSemanticInfo si = id
+  addScopeData = pure
+  addImportData = pure
+  
+-- | Adds semantic information to an impord declaration. See ImportInfo.
+addImportData' :: Ann AST.ImportDecl RangeWithName -> Trf (Ann AST.ImportDecl RangeWithName)
+addImportData' imp = 
+  do (mod,importedNames) <- getImportedNames (nameString $ imp ^. element&importModule&element)
+                                             (imp ^? element&importPkg&annJust&element&stringNodeStr)
+     names <- lift $ filterM (checkImportVisible (imp ^. element)) importedNames
+     return $ annotation .- addSemanticInfo (ImportInfo mod importedNames names) $ imp
+
+-- | Get names that are imported from a given import
+getImportedNames :: String -> Maybe String -> Trf (GHC.Module, [GHC.Name])
+getImportedNames name pkg = lift $ do
+  eps <- getSession >>= liftIO . readIORef . hsc_EPS
+  mod <- findModule (mkModuleName name) (fmap mkFastString pkg)
+  -- load exported names from interface file
+  let ifaceNames = concatMap availNames $ maybe [] mi_exports 
+                                        $ flip lookupModuleEnv mod 
+                                        $ eps_PIT eps
+  loadedNames <- maybe [] modInfoExports <$> getModuleInfo mod
+  return (mod, ifaceNames ++ loadedNames)
+
+-- | Check is a given name is imported from an import with given import specification.
+checkImportVisible :: GhcMonad m => AST.ImportDecl RangeWithName -> GHC.Name -> m Bool
+checkImportVisible imp name
+  | importIsExact imp 
+  = or <$> mapM (`ieSpecMatches` name) (imp ^? importExacts :: [IESpec RangeWithName])
+  | importIsHiding imp 
+  = not . or <$> mapM (`ieSpecMatches` name) (imp ^? importHidings :: [IESpec RangeWithName])
+  | otherwise = return True
+
+ieSpecMatches :: GhcMonad m => AST.IESpec RangeWithName -> GHC.Name -> m Bool
+ieSpecMatches (AST.IESpec ((^? element&simpleName&annotation&semanticInfo&nameInfo) -> Just n) ss) name
+  | n == name = return True
+  | isTyConName n
+  = (\case Just (ATyCon tc) -> name `elem` map getName (tyConDataCons tc)) 
+             <$> lookupName n
+  | otherwise = return False
+
+
+-- | Creates a place for a missing node with a default location
+nothing :: RangeAnnot a => String -> String -> Trf SrcLoc -> Trf (AnnMaybe e a)
+nothing bef aft pos = annNothing . toOptAnnot bef aft <$> pos 
+
+emptyList :: RangeAnnot a => String -> Trf SrcLoc -> Trf (AnnList e a)
+emptyList sep ann = AnnList <$> (toListAnnot "" "" sep <$> ann) <*> pure []
+
+-- | Creates a place for a list of nodes with a default place if the list is empty.
+makeList :: RangeAnnot a => String -> Trf SrcLoc -> Trf [Ann e a] -> Trf (AnnList e a)
+makeList sep ann ls = AnnList <$> (toListAnnot "" "" sep <$> ann) <*> ls
+
+makeListBefore :: RangeAnnot a => String -> String -> Trf SrcLoc -> Trf [Ann e a] -> Trf (AnnList e a)
+makeListBefore bef sep ann ls = do isEmpty <- null <$> ls 
+                                   AnnList <$> (toListAnnot (if isEmpty then bef else "") "" sep <$> ann) <*> ls
+
+makeListAfter :: RangeAnnot a => String -> String -> Trf SrcLoc -> Trf [Ann e a] -> Trf (AnnList e a)
+makeListAfter aft sep ann ls = do isEmpty <- null <$> ls 
+                                  AnnList <$> (toListAnnot "" (if isEmpty then aft else "") sep <$> ann) <*> ls
+
+makeNonemptyList :: RangeAnnot a => String -> Trf [Ann e a] -> Trf (AnnList e a)
+makeNonemptyList sep ls = AnnList (toListAnnot "" "" sep noSrcLoc) <$> ls
+
+-- | Creates a place for an indented list of nodes with a default place if the list is empty.
+makeIndentedList :: RangeAnnot a => Trf SrcLoc -> Trf [Ann e a] -> Trf (AnnList e a)
+makeIndentedList ann ls = AnnList <$> (toIndentedListAnnot "" "" "\n" <$> ann) <*> ls
+
+makeIndentedListNewlineBefore :: RangeAnnot a => Trf SrcLoc -> Trf [Ann e a] -> Trf (AnnList e a)
+makeIndentedListNewlineBefore ann ls = do isEmpty <- null <$> ls 
+                                          AnnList <$> (toIndentedListAnnot (if isEmpty then "\n" else "") "" "\n" <$> ann) <*> ls
+
+makeIndentedListBefore :: RangeAnnot a => String -> Trf SrcLoc -> Trf [Ann e a] -> Trf (AnnList e a)
+makeIndentedListBefore bef sp ls = do isEmpty <- null <$> ls 
+                                      AnnList <$> (toIndentedListAnnot (if isEmpty then bef else "") "" "\n" <$> sp) <*> ls
+  
+makeNonemptyIndentedList :: RangeAnnot a => Trf [Ann e a] -> Trf (AnnList e a)
+makeNonemptyIndentedList ls = AnnList (toIndentedListAnnot "" "" "\n" noSrcLoc) <$> ls
+  
+-- | Transform a located part of the AST by automatically transforming the location.
+-- Sets the source range for transforming children.
+trfLoc :: RangeAnnot i => (a -> Trf (b i)) -> Located a -> Trf (Ann b i)
+trfLoc = trfLocCorrect pure
+
+-- | Transforms a possibly-missing node with the default location of the end of the focus.
+trfMaybe :: RangeAnnot i => String -> String -> (Located a -> Trf (Ann e i)) -> Maybe (Located a) -> Trf (AnnMaybe e i)
+trfMaybe bef aft f = trfMaybeDefault bef aft f atTheEnd
+
+-- | Transforms a possibly-missing node with a default location
+trfMaybeDefault :: RangeAnnot i => String -> String -> (Located a -> Trf (Ann e i)) -> Trf SrcLoc -> Maybe (Located a) -> Trf (AnnMaybe e i)
+trfMaybeDefault _   _   f _   (Just e) = makeJust <$> f e
+trfMaybeDefault bef aft _ loc Nothing  = nothing bef aft loc
+
+-- | Transform a located part of the AST by automatically transforming the location
+-- with correction by applying the given function. Sets the source range for transforming children.
+trfLocCorrect :: RangeAnnot i => (SrcSpan -> Trf SrcSpan) -> (a -> Trf (b i)) -> Located a -> Trf (Ann b i)
+trfLocCorrect locF f (L l e) = annLoc (locF l) (f e)
+
+-- | Transform a located part of the AST by automatically transforming the location.
+-- Sets the source range for transforming children.
+trfMaybeLoc :: RangeAnnot i => (a -> Trf (Maybe (b i))) -> Located a -> Trf (Maybe (Ann b i))
+trfMaybeLoc f (L l e) = do fmap (Ann (toNodeAnnot l)) <$> local (\s -> s { contRange = l }) (f e)
+
+-- | Creates a place for a list of nodes with the default place at the end of the focus if the list is empty.
+trfAnnList :: RangeAnnot i => String -> (a -> Trf (b i)) -> [Located a] -> Trf (AnnList b i)
+trfAnnList sep _ [] = makeList sep atTheEnd (pure [])
+trfAnnList sep f ls = makeList sep (pure $ noSrcLoc) (mapM (trfLoc f) ls)
+
+trfAnnList' :: RangeAnnot i => String -> (Located a -> Trf (Ann b i)) -> [Located a] -> Trf (AnnList b i)
+trfAnnList' sep _ [] = makeList sep atTheEnd (pure [])
+trfAnnList' sep f ls = makeList sep (pure $ noSrcLoc) (mapM f ls)
+
+
+-- | Creates a place for a list of nodes that cannot be empty.
+nonemptyAnnList :: RangeAnnot i => [Ann e i] -> AnnList e i
+nonemptyAnnList = AnnList (toListAnnot "" "" "" noSrcLoc)
+
+-- | Creates an optional node from an existing element
+makeJust :: RangeAnnot a => Ann e a -> AnnMaybe e a
+makeJust e = AnnMaybe (toOptAnnot "" "" noSrcLoc) (Just e)
+
+-- | Annotates a node with the given location and focuses on the given source span.
+annLoc :: RangeAnnot a => Trf SrcSpan -> Trf (b a) -> Trf (Ann b a)
+annLoc locm nodem = do loc <- locm
+                       node <- focusOn loc nodem
+                       return (Ann (toNodeAnnot loc) node)
+
+-- * Focus manipulation
+
+focusOn :: SrcSpan -> Trf a -> Trf a
+focusOn sp = local (\s -> s { contRange = sp })
+
+-- | Focuses the transformation to go between tokens. The tokens must be found inside the current range.
+between :: AnnKeywordId -> AnnKeywordId -> Trf a -> Trf a
+between firstTok lastTok = focusAfter firstTok . focusBefore lastTok
+
+-- | Focuses the transformation to go between tokens if they are present
+betweenIfPresent :: AnnKeywordId -> AnnKeywordId -> Trf a -> Trf a
+betweenIfPresent firstTok lastTok = focusAfterIfPresent firstTok . focusBeforeIfPresent lastTok
+
+-- | Focuses the transformation to be performed after the given token. The token must be found inside the current range.
+focusAfter :: AnnKeywordId -> Trf a -> Trf a
+focusAfter firstTok trf
+  = do firstToken <- tokenLoc firstTok
+       if (isGoodSrcSpan firstToken)
+          then local (\s -> s { contRange = mkSrcSpan (srcSpanEnd firstToken) (srcSpanEnd (contRange s))}) trf
+          else do rng <- asks contRange 
+                  error $ "focusAfter: token not found in " ++ show rng ++ ": " ++ show firstTok
+
+focusAfterIfPresent :: AnnKeywordId -> Trf a -> Trf a
+focusAfterIfPresent firstTok trf
+  = do firstToken <- tokenLoc firstTok
+       if (isGoodSrcSpan firstToken)
+          then local (\s -> s { contRange = mkSrcSpan (srcSpanEnd firstToken) (srcSpanEnd (contRange s))}) trf
+          else trf
+
+-- | Focuses the transformation to be performed after the given token. The token must be found inside the current range.
+focusBefore :: AnnKeywordId -> Trf a -> Trf a
+focusBefore lastTok trf
+  = do lastToken <- tokenLocBack lastTok
+       if (isGoodSrcSpan lastToken)
+          then local (\s -> s { contRange = mkSrcSpan (srcSpanStart (contRange s)) (srcSpanStart lastToken)}) trf
+          else do rng <- asks contRange 
+                  error $ "focusBefore: token not found in " ++ show rng ++ ": " ++ show lastTok
+
+focusBeforeIfPresent :: AnnKeywordId -> Trf a -> Trf a
+focusBeforeIfPresent lastTok trf
+  = do lastToken <- tokenLocBack lastTok
+       if (isGoodSrcSpan lastToken)
+          then local (\s -> s { contRange = mkSrcSpan (srcSpanStart (contRange s)) (srcSpanStart lastToken)}) trf
+          else trf
+
+-- | Gets the position before the given token
+before :: AnnKeywordId -> Trf SrcLoc
+before tok = srcSpanStart <$> tokenLoc tok
+               
+-- | Gets the position after the given token
+after :: AnnKeywordId -> Trf SrcLoc
+after tok = srcSpanEnd <$> tokenLoc tok
+
+-- | The element should span from the given token to the end of focus
+annFrom :: RangeAnnot a => AnnKeywordId -> Trf (e a) -> Trf (Ann e a)
+annFrom kw = annLoc (combineSrcSpans <$> tokenLoc kw <*> asks (srcLocSpan . srcSpanEnd . contRange))
+
+-- | Gets the position at the beginning of the focus       
+atTheStart :: Trf SrcLoc
+atTheStart = asks (srcSpanStart . contRange)
+            
+-- | Gets the position at the end of the focus      
+atTheEnd :: Trf SrcLoc
+atTheEnd = asks (srcSpanEnd . contRange)
+                 
+-- | Searches for a token inside the focus and retrieves its location
+tokenLoc :: AnnKeywordId -> Trf SrcSpan
+tokenLoc keyw = fromMaybe noSrcSpan <$> (getKeywordInside keyw <$> asks contRange <*> asks srcMap)
+
+allTokenLoc :: AnnKeywordId -> Trf [SrcSpan]
+allTokenLoc keyw = getKeywordsInside keyw <$> asks contRange <*> asks srcMap
+
+-- | Searches for a token backward inside the focus and retrieves its location
+tokenLocBack :: AnnKeywordId -> Trf SrcSpan
+tokenLocBack keyw = fromMaybe noSrcSpan <$> (getKeywordInsideBack keyw <$> asks contRange <*> asks srcMap)
+
+tokenBefore :: SrcLoc -> AnnKeywordId -> Trf SrcSpan
+tokenBefore loc keyw 
+  = fromMaybe noSrcSpan <$> (getKeywordInsideBack keyw <$> (mkSrcSpan <$> (asks (srcSpanStart . contRange)) <*> pure loc) <*> asks srcMap)
+
+-- | Searches for tokens in the given order inside the parent element and returns their combined location
+tokensLoc :: [AnnKeywordId] -> Trf SrcSpan
+tokensLoc keys = asks contRange >>= tokensLoc' keys
+  where tokensLoc' :: [AnnKeywordId] -> SrcSpan -> Trf SrcSpan
+        tokensLoc' (keyw:rest) r 
+          = do spanFirst <- tokenLoc keyw
+               spanRest <- tokensLoc' rest (mkSrcSpan (srcSpanEnd spanFirst) (srcSpanEnd r))
+               return (combineSrcSpans spanFirst spanRest)                   
+        tokensLoc' [] r = pure noSrcSpan
+        
+-- | Searches for a token and retrieves its location anywhere
+uniqueTokenAnywhere :: AnnKeywordId -> Trf SrcSpan
+uniqueTokenAnywhere keyw = fromMaybe noSrcSpan <$> (getKeywordAnywhere keyw <$> asks srcMap)
+        
+-- | Annotates the given element with the current focus as a location.
+annCont :: RangeAnnot a => Trf (e a) -> Trf (Ann e a)
+annCont = annLoc (asks contRange)
+
+-- | Annotates the element with the same annotation that is on the other element
+copyAnnot :: (Ann a i -> b i) -> Trf (Ann a i) -> Trf (Ann b i)
+copyAnnot f at = (\(Ann i a) -> Ann i (f (Ann i a))) <$> at
+
+-- | Combine source spans into one that contains them all
+foldLocs :: [SrcSpan] -> SrcSpan
+foldLocs = foldl combineSrcSpans noSrcSpan
+
+-- | The location after the given string
+advanceStr :: String -> SrcLoc -> SrcLoc
+advanceStr str (RealSrcLoc l) = RealSrcLoc $ foldl advanceSrcLoc l str
+advanceStr _ l = l
+
+-- | Update column information in a source location
+updateCol :: (Int -> Int) -> SrcLoc -> SrcLoc
+updateCol f loc@(UnhelpfulLoc _) = loc
+updateCol f (RealSrcLoc loc) = mkSrcLoc (srcLocFile loc) (srcLocLine loc) (f $ srcLocCol loc)
+
+-- | Combine source spans of elements into one that contains them all
+collectLocs :: [Located e] -> SrcSpan
+collectLocs = foldLocs . map getLoc
+
+-- | Rearrange definitions to appear in the order they are defined in the source file.
+orderDefs :: RangeAnnot i => [Ann e i] -> [Ann e i]
+orderDefs = sortBy (compare `on` AST.ordSrcSpan . getRange . _annotation)
+
+-- | Orders a list of elements to the order they are defined in the source file.
+orderAnnList :: RangeAnnot i => AnnList e i -> AnnList e i
+orderAnnList (AnnList a ls) = AnnList a (orderDefs ls)
+
+
+-- | Transform a list of definitions where the defined names are in scope for subsequent definitions
+trfScopedSequence :: HsHasName d => (d -> Trf e) -> [d] -> Trf [e]
+trfScopedSequence f (def:rest) = (:) <$> f def <*> addToScope def (trfScopedSequence f rest)
+trfScopedSequence f [] = pure []
+
+-- | Splits a given string at whitespaces while calculating the source location of the fragments
+splitLocated :: Located String -> [Located String]
+splitLocated (L (RealSrcSpan l) str) = splitLocated' str (realSrcSpanStart l) Nothing
+  where splitLocated' :: String -> RealSrcLoc -> Maybe (RealSrcLoc, String) -> [Located String]
+        splitLocated' (c:rest) currLoc (Just (startLoc, str)) | isSpace c 
+          = L (RealSrcSpan $ mkRealSrcSpan startLoc currLoc) (reverse str) : splitLocated' rest (advanceSrcLoc currLoc c) Nothing
+        splitLocated' (c:rest) currLoc Nothing | isSpace c = splitLocated' rest (advanceSrcLoc currLoc c) Nothing
+        splitLocated' (c:rest) currLoc (Just (startLoc, str)) = splitLocated' rest (advanceSrcLoc currLoc c) (Just (startLoc, c:str))
+        splitLocated' (c:rest) currLoc Nothing = splitLocated' rest (advanceSrcLoc currLoc c) (Just (currLoc, [c]))
+        splitLocated' [] currLoc (Just (startLoc, str)) = [L (RealSrcSpan $ mkRealSrcSpan startLoc currLoc) (reverse str)]
+        splitLocated' [] currLoc Nothing = []
+                
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ haskell-tools-ast-fromghc.cabal view
@@ -0,0 +1,44 @@+name:                haskell-tools-ast-fromghc
+version:             0.1.2.0
+synopsis:            Creating the Haskell-Tools AST from GHC's representations
+description:         This package collects information from various representations of a Haskell program in GHC 
+homepage:            https://github.com/nboldi/haskell-tools
+license:             BSD3
+license-file:        LICENSE
+author:              Boldizsar Nemeth
+maintainer:          nboldi@elte.hu
+category:            Language
+build-type:          Simple
+cabal-version:       >=1.10
+
+library
+  exposed-modules:     Language.Haskell.Tools.AST.FromGHC   
+                     , Language.Haskell.Tools.AST.FromGHC.GHCUtils                  
+  other-modules:       Language.Haskell.Tools.AST.FromGHC.Modules
+                     , Language.Haskell.Tools.AST.FromGHC.TH
+                     , Language.Haskell.Tools.AST.FromGHC.Decls
+                     , Language.Haskell.Tools.AST.FromGHC.Binds
+                     , Language.Haskell.Tools.AST.FromGHC.Exprs
+                     , Language.Haskell.Tools.AST.FromGHC.Stmts
+                     , Language.Haskell.Tools.AST.FromGHC.Patterns
+                     , Language.Haskell.Tools.AST.FromGHC.Types
+                     , Language.Haskell.Tools.AST.FromGHC.Kinds
+                     , Language.Haskell.Tools.AST.FromGHC.Literals
+                     , Language.Haskell.Tools.AST.FromGHC.Base
+                     , Language.Haskell.Tools.AST.FromGHC.Monad
+                     , Language.Haskell.Tools.AST.FromGHC.Utils
+                     , Language.Haskell.Tools.AST.FromGHC.SourceMap
+
+  build-depends:       base              >=4.9 && <5.0
+                     , ghc               >=8.0 && <8.1
+                     , haskell-tools-ast >=0.1 && <0.2
+                     , references        >=0.3.2 && <1.0
+                     , bytestring        >=0.10 && <1.0
+                     , safe              >=0.3
+                     , uniplate          >=1.6  && <2.0
+                     , containers        >=0.5 && <0.6
+                     , mtl               >=2.2 && <2.3
+                     , split             >=0.2 && <0.3
+                     , structural-traversal >=0.1 && <0.2
+                     , template-haskell  >=2.11 && <3.0
+  default-language:    Haskell2010