Skip to content

Commit

Permalink
Implement ClassDeclaration, DataFamilyInstance, and `TypeFamilyIn…
Browse files Browse the repository at this point in the history
…stance` (#846)

* Fix compile errors

* Moved

* Move all instances

* Format

* Make hlint happy

* Do not export an unnecessary function

* Remove the `HsDecl` instance

* Fix

* Define `ClassDeclaration`

* Format

* Use `mkClassDeclaration`

* Remove a branch

* Inline the instance

* Remove an unused instance

* Add a field

* Return a `Maybe`

* Use `context`

* Use `>>`

* Use `>>`

* Add `name`

* Add `NameAndTypeVariables`

* Split

* Add a test

* Pass the test

* Add a changelog

* Format

* Fix

* `functionalDependencios`

* `associatedThings`

* Split

* Format

* Remove parentheses

* Add `DataFamilyInstance`

* `DataFamilyInstance`

* Add a field

* `inst`

* Format

* Inline an instance

* `newOrData`

* `name`

* `types`

* `Body`

* Remove a pragma

* Fix

* Remove `inst`

* Refactor

* Format

* Fix

* Add `TypeFamilyInstance`

* `Pretty`

* Remove a branch

* Add a field

* Inline

* `name`

* Remove `inst`

* Remove an instance

* Format
  • Loading branch information
toku-sa-n authored Mar 15, 2024
1 parent 225e29e commit 1699b77
Show file tree
Hide file tree
Showing 10 changed files with 341 additions and 200 deletions.
6 changes: 6 additions & 0 deletions hindent.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,12 @@ library
HIndent.Ast
HIndent.Ast.Context
HIndent.Ast.Declaration
HIndent.Ast.Declaration.Class
HIndent.Ast.Declaration.Class.FunctionalDependency
HIndent.Ast.Declaration.Class.NameAndTypeVariables
HIndent.Ast.Declaration.Collection
HIndent.Ast.Declaration.Data
HIndent.Ast.Declaration.Data.Body
HIndent.Ast.Declaration.Data.GADT.Constructor
HIndent.Ast.Declaration.Data.GADT.Constructor.Signature
HIndent.Ast.Declaration.Data.Header
Expand All @@ -50,6 +54,8 @@ library
HIndent.Ast.Declaration.Family.Type.Injectivity
HIndent.Ast.Declaration.Family.Type.ResultSignature
HIndent.Ast.Declaration.Instance.Class
HIndent.Ast.Declaration.Instance.Family.Data
HIndent.Ast.Declaration.Instance.Family.Type
HIndent.Ast.Declaration.TypeSynonym
HIndent.Ast.Declaration.TypeSynonym.Lhs
HIndent.Ast.FileHeaderPragma
Expand Down
48 changes: 36 additions & 12 deletions src/HIndent/Ast/Declaration.hs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
{-# LANGUAGE RecordWildCards #-}

module HIndent.Ast.Declaration
( Declaration(..)
, mkDeclaration
Expand All @@ -6,10 +8,13 @@ module HIndent.Ast.Declaration

import Control.Applicative
import Data.Maybe
import qualified HIndent.Ast.Declaration.Class
import HIndent.Ast.Declaration.Data
import qualified HIndent.Ast.Declaration.Family.Data
import qualified HIndent.Ast.Declaration.Family.Type
import qualified HIndent.Ast.Declaration.Instance.Class
import qualified HIndent.Ast.Declaration.Instance.Family.Data
import qualified HIndent.Ast.Declaration.Instance.Family.Type
import qualified HIndent.Ast.Declaration.TypeSynonym
import HIndent.Ast.NodeComments
import qualified HIndent.GhcLibParserWrapper.GHC.Hs as GHC
Expand All @@ -19,10 +24,13 @@ data Declaration
= DataFamily HIndent.Ast.Declaration.Family.Data.DataFamily
| TypeFamily HIndent.Ast.Declaration.Family.Type.TypeFamily
| DataDeclaration DataDeclaration
| ClassDeclaration HIndent.Ast.Declaration.Class.ClassDeclaration
| TypeSynonym HIndent.Ast.Declaration.TypeSynonym.TypeSynonym
| TyClDecl (GHC.TyClDecl GHC.GhcPs)
| ClassInstance HIndent.Ast.Declaration.Instance.Class.ClassInstance
| InstDecl (GHC.InstDecl GHC.GhcPs)
| DataFamilyInstance
HIndent.Ast.Declaration.Instance.Family.Data.DataFamilyInstance
| TypeFamilyInstance
HIndent.Ast.Declaration.Instance.Family.Type.TypeFamilyInstance
| DerivDecl (GHC.DerivDecl GHC.GhcPs)
| ValDecl (GHC.HsBind GHC.GhcPs)
| SigDecl (GHC.Sig GHC.GhcPs)
Expand All @@ -38,11 +46,13 @@ data Declaration
instance CommentExtraction Declaration where
nodeComments DataFamily {} = NodeComments [] [] []
nodeComments TypeFamily {} = NodeComments [] [] []
nodeComments DataDeclaration {} = NodeComments [] [] []
nodeComments HIndent.Ast.Declaration.DataDeclaration {} =
NodeComments [] [] []
nodeComments ClassDeclaration {} = NodeComments [] [] []
nodeComments TypeSynonym {} = NodeComments [] [] []
nodeComments TyClDecl {} = NodeComments [] [] []
nodeComments ClassInstance {} = NodeComments [] [] []
nodeComments InstDecl {} = NodeComments [] [] []
nodeComments DataFamilyInstance {} = NodeComments [] [] []
nodeComments TypeFamilyInstance {} = NodeComments [] [] []
nodeComments DerivDecl {} = NodeComments [] [] []
nodeComments ValDecl {} = NodeComments [] [] []
nodeComments SigDecl {} = NodeComments [] [] []
Expand All @@ -62,13 +72,27 @@ mkDeclaration (GHC.TyClD _ (GHC.FamDecl _ x)) =
<|> TypeFamily <$> HIndent.Ast.Declaration.Family.Type.mkTypeFamily x
mkDeclaration (GHC.TyClD _ x@GHC.SynDecl {}) =
TypeSynonym $ HIndent.Ast.Declaration.TypeSynonym.mkTypeSynonym x
mkDeclaration (GHC.TyClD _ x@(GHC.DataDecl {}))
| Just decl <- mkDataDeclaration x = DataDeclaration decl
mkDeclaration (GHC.TyClD _ x) = TyClDecl x
mkDeclaration (GHC.InstD _ x)
| Just inst <- HIndent.Ast.Declaration.Instance.Class.mkClassInstance x =
ClassInstance inst
| otherwise = InstDecl x
mkDeclaration (GHC.TyClD _ x@GHC.DataDecl {}) =
maybe
(error "Unreachable.")
HIndent.Ast.Declaration.DataDeclaration
(mkDataDeclaration x)
mkDeclaration (GHC.TyClD _ x@GHC.ClassDecl {}) =
maybe
(error "Unreachable.")
ClassDeclaration
(HIndent.Ast.Declaration.Class.mkClassDeclaration x)
mkDeclaration (GHC.InstD _ x@GHC.ClsInstD {}) =
maybe
(error "Unreachable.")
ClassInstance
(HIndent.Ast.Declaration.Instance.Class.mkClassInstance x)
mkDeclaration (GHC.InstD _ GHC.DataFamInstD {GHC.dfid_inst = GHC.DataFamInstDecl {..}}) =
DataFamilyInstance
$ HIndent.Ast.Declaration.Instance.Family.Data.mkDataFamilyInstance dfid_eqn
mkDeclaration (GHC.InstD _ x@GHC.TyFamInstD {}) =
maybe (error "Unreachable.") TypeFamilyInstance
$ HIndent.Ast.Declaration.Instance.Family.Type.mkTypeFamilyInstance x
mkDeclaration (GHC.DerivD _ x) = DerivDecl x
mkDeclaration (GHC.ValD _ x) = ValDecl x
mkDeclaration (GHC.SigD _ x) = SigDecl x
Expand Down
38 changes: 38 additions & 0 deletions src/HIndent/Ast/Declaration/Class.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{-# LANGUAGE RecordWildCards #-}

module HIndent.Ast.Declaration.Class
( ClassDeclaration(..)
, mkClassDeclaration
) where

import qualified GHC.Data.Bag as GHC
import HIndent.Ast.Context
import HIndent.Ast.Declaration.Class.FunctionalDependency
import HIndent.Ast.Declaration.Class.NameAndTypeVariables
import HIndent.Ast.NodeComments
import HIndent.Ast.WithComments
import qualified HIndent.GhcLibParserWrapper.GHC.Hs as GHC
import HIndent.Pretty.NodeComments
import HIndent.Pretty.SigBindFamily

data ClassDeclaration = ClassDeclaration
{ context :: Maybe (WithComments Context)
, nameAndTypeVariables :: NameAndTypeVariables
, functionalDependencies :: [WithComments FunctionalDependency]
, associatedThings :: [LSigBindFamily]
}

instance CommentExtraction ClassDeclaration where
nodeComments ClassDeclaration {} = NodeComments [] [] []

mkClassDeclaration :: GHC.TyClDecl GHC.GhcPs -> Maybe ClassDeclaration
mkClassDeclaration x@GHC.ClassDecl {..}
| Just nameAndTypeVariables <- mkNameAndTypeVariables x =
Just ClassDeclaration {..}
where
context = fmap (fmap mkContext . fromGenLocated) tcdCtxt
functionalDependencies =
fmap (fmap mkFunctionalDependency . fromGenLocated) tcdFDs
associatedThings =
mkSortedLSigBindFamilyList tcdSigs (GHC.bagToList tcdMeths) tcdATs [] []
mkClassDeclaration _ = Nothing
21 changes: 21 additions & 0 deletions src/HIndent/Ast/Declaration/Class/FunctionalDependency.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{-# LANGUAGE RecordWildCards #-}

module HIndent.Ast.Declaration.Class.FunctionalDependency
( FunctionalDependency(..)
, mkFunctionalDependency
) where

import HIndent.Ast.NodeComments
import qualified HIndent.GhcLibParserWrapper.GHC.Hs as GHC
import HIndent.Pretty.NodeComments

data FunctionalDependency = FunctionalDependency
{ from :: [GHC.LIdP GHC.GhcPs]
, to :: [GHC.LIdP GHC.GhcPs]
}

instance CommentExtraction FunctionalDependency where
nodeComments FunctionalDependency {} = NodeComments [] [] []

mkFunctionalDependency :: GHC.FunDep GHC.GhcPs -> FunctionalDependency
mkFunctionalDependency (GHC.FunDep _ from to) = FunctionalDependency {..}
47 changes: 47 additions & 0 deletions src/HIndent/Ast/Declaration/Class/NameAndTypeVariables.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{-# LANGUAGE RecordWildCards #-}

module HIndent.Ast.Declaration.Class.NameAndTypeVariables
( NameAndTypeVariables(..)
, mkNameAndTypeVariables
) where

import qualified GHC.Types.Fixity as GHC
import HIndent.Ast.NodeComments
import HIndent.Ast.Type.Variable
import HIndent.Ast.WithComments
import qualified HIndent.GhcLibParserWrapper.GHC.Hs as GHC
import HIndent.Pretty.NodeComments

data NameAndTypeVariables
= Prefix
{ name :: GHC.LIdP GHC.GhcPs
, typeVariables :: [WithComments TypeVariable]
}
| Infix
{ left :: WithComments TypeVariable
, name :: GHC.LIdP GHC.GhcPs
, right :: WithComments TypeVariable
, remains :: [WithComments TypeVariable]
}

instance CommentExtraction NameAndTypeVariables where
nodeComments Prefix {} = NodeComments [] [] []
nodeComments Infix {} = NodeComments [] [] []

mkNameAndTypeVariables :: GHC.TyClDecl GHC.GhcPs -> Maybe NameAndTypeVariables
mkNameAndTypeVariables GHC.ClassDecl {tcdFixity = GHC.Prefix, ..} =
Just Prefix {..}
where
name = tcdLName
typeVariables =
fmap mkTypeVariable . fromGenLocated <$> GHC.hsq_explicit tcdTyVars
mkNameAndTypeVariables GHC.ClassDecl { tcdFixity = GHC.Infix
, tcdTyVars = GHC.HsQTvs {hsq_explicit = h:t:xs}
, ..
} = Just Infix {..}
where
left = mkTypeVariable <$> fromGenLocated h
name = tcdLName
right = mkTypeVariable <$> fromGenLocated t
remains = fmap (fmap mkTypeVariable . fromGenLocated) xs
mkNameAndTypeVariables _ = Nothing
55 changes: 8 additions & 47 deletions src/HIndent/Ast/Declaration/Data.hs
Original file line number Diff line number Diff line change
@@ -1,65 +1,26 @@
{-# LANGUAGE CPP #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ViewPatterns #-}

module HIndent.Ast.Declaration.Data
( DataDeclaration(..)
, mkDataDeclaration
) where

import Data.Maybe
import qualified GHC.Types.SrcLoc as GHC
import HIndent.Ast.Declaration.Data.GADT.Constructor
import HIndent.Ast.Declaration.Data.Body
import HIndent.Ast.Declaration.Data.Header
import HIndent.Ast.NodeComments
import HIndent.Ast.Type
import HIndent.Ast.WithComments
import qualified HIndent.GhcLibParserWrapper.GHC.Hs as GHC
import HIndent.Pretty.NodeComments

data DataDeclaration
= GADT
{ header :: Header
, kind :: Maybe (WithComments Type)
, constructors :: [WithComments GADTConstructor]
}
| Record
{ header :: Header
, dd_cons :: [GHC.LConDecl GHC.GhcPs]
, dd_derivs :: GHC.HsDeriving GHC.GhcPs
}
data DataDeclaration = DataDeclaration
{ header :: Header
, body :: DataBody
}

instance CommentExtraction DataDeclaration where
nodeComments GADT {} = NodeComments [] [] []
nodeComments Record {} = NodeComments [] [] []
nodeComments DataDeclaration {} = NodeComments [] [] []

mkDataDeclaration :: GHC.TyClDecl GHC.GhcPs -> Maybe DataDeclaration
mkDataDeclaration decl@GHC.DataDecl {tcdDataDefn = defn@GHC.HsDataDefn {..}}
| Just header <- mkHeader decl =
Just
$ if isGADT defn
then GADT
{ constructors =
fromMaybe (error "Some constructors are not GADT ones.")
$ mapM (traverse mkGADTConstructor . fromGenLocated)
$ getConDecls defn
, ..
}
else Record {dd_cons = getConDecls defn, ..}
where
kind = fmap mkType . fromGenLocated <$> dd_kindSig
mkDataDeclaration decl@GHC.DataDecl {..} =
DataDeclaration <$> mkHeader decl <*> pure (mkDataBody tcdDataDefn)
mkDataDeclaration _ = Nothing

isGADT :: GHC.HsDataDefn GHC.GhcPs -> Bool
isGADT (getConDecls -> (GHC.L _ GHC.ConDeclGADT {}:_)) = True
isGADT _ = False

getConDecls :: GHC.HsDataDefn GHC.GhcPs -> [GHC.LConDecl GHC.GhcPs]
#if MIN_VERSION_ghc_lib_parser(9, 6, 0)
getConDecls GHC.HsDataDefn {..} =
case dd_cons of
GHC.NewTypeCon x -> [x]
GHC.DataTypeCons _ xs -> xs
#else
getConDecls GHC.HsDataDefn {..} = dd_cons
#endif
59 changes: 59 additions & 0 deletions src/HIndent/Ast/Declaration/Data/Body.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
{-# LANGUAGE CPP #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ViewPatterns #-}

module HIndent.Ast.Declaration.Data.Body
( DataBody(..)
, mkDataBody
) where

import Data.Maybe
import qualified GHC.Types.SrcLoc as GHC
import HIndent.Ast.Declaration.Data.GADT.Constructor
import HIndent.Ast.NodeComments
import HIndent.Ast.Type
import HIndent.Ast.WithComments
import qualified HIndent.GhcLibParserWrapper.GHC.Hs as GHC
import HIndent.Pretty.NodeComments

data DataBody
= GADT
{ kind :: Maybe (WithComments Type)
, constructors :: [WithComments GADTConstructor]
}
| Record
{ dd_cons :: [GHC.LConDecl GHC.GhcPs]
, dd_derivs :: GHC.HsDeriving GHC.GhcPs
}

instance CommentExtraction DataBody where
nodeComments GADT {} = NodeComments [] [] []
nodeComments Record {} = NodeComments [] [] []

mkDataBody :: GHC.HsDataDefn GHC.GhcPs -> DataBody
mkDataBody defn@GHC.HsDataDefn {..} =
if isGADT defn
then GADT
{ constructors =
fromMaybe (error "Some constructors are not GADT ones.")
$ mapM (traverse mkGADTConstructor . fromGenLocated)
$ getConDecls defn
, ..
}
else Record {dd_cons = getConDecls defn, ..}
where
kind = fmap mkType . fromGenLocated <$> dd_kindSig

isGADT :: GHC.HsDataDefn GHC.GhcPs -> Bool
isGADT (getConDecls -> (GHC.L _ GHC.ConDeclGADT {}:_)) = True
isGADT _ = False

getConDecls :: GHC.HsDataDefn GHC.GhcPs -> [GHC.LConDecl GHC.GhcPs]
#if MIN_VERSION_ghc_lib_parser(9, 6, 0)
getConDecls GHC.HsDataDefn {..} =
case dd_cons of
GHC.NewTypeCon x -> [x]
GHC.DataTypeCons _ xs -> xs
#else
getConDecls GHC.HsDataDefn {..} = dd_cons
#endif
32 changes: 32 additions & 0 deletions src/HIndent/Ast/Declaration/Instance/Family/Data.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{-# LANGUAGE RecordWildCards #-}

module HIndent.Ast.Declaration.Instance.Family.Data
( DataFamilyInstance(..)
, mkDataFamilyInstance
) where

import qualified GHC.Hs as GG
import HIndent.Ast.Declaration.Data.Body
import HIndent.Ast.Declaration.Data.NewOrData
import HIndent.Ast.NodeComments
import qualified HIndent.GhcLibParserWrapper.GHC.Hs as GHC
import HIndent.Pretty.NodeComments

data DataFamilyInstance = DataFamilyInstance
{ newOrData :: NewOrData
, name :: GHC.LIdP GHC.GhcPs
, types :: GHC.HsTyPats GHC.GhcPs
, body :: DataBody
}

instance CommentExtraction DataFamilyInstance where
nodeComments DataFamilyInstance {} = NodeComments [] [] []

mkDataFamilyInstance ::
GHC.FamEqn GHC.GhcPs (GHC.HsDataDefn GHC.GhcPs) -> DataFamilyInstance
mkDataFamilyInstance GHC.FamEqn {..} = DataFamilyInstance {..}
where
newOrData = mkNewOrData feqn_rhs
name = feqn_tycon
types = feqn_pats
body = mkDataBody feqn_rhs
Loading

0 comments on commit 1699b77

Please sign in to comment.