module DDC.Type.Check.Data
(checkDataDefs)
where
import DDC.Type.Check.Error
import DDC.Type.Check.Config
import DDC.Type.Equiv
import DDC.Type.DataDef
import DDC.Base.Pretty
import Data.Maybe
import Data.Set (Set)
import qualified DDC.Type.Env as Env
import qualified Data.Set as Set
import qualified Data.Map as Map
checkDataDefs
:: (Ord n, Show n, Pretty n)
=> Config n
-> [DataDef n]
-> ([ErrorData n], [DataDef n])
checkDataDefs config defs
= let
primTypeCtors
= Set.fromList
$ Map.keys $ Env.envMap $ configPrimKinds config
primDataTypeCtors
= Set.fromList
$ Map.keys $ dataDefsTypes $ configDataDefs config
primDataCtors
= Set.fromList
$ Map.keys $ dataDefsCtors $ configDataDefs config
in checkDataDefs'
(Set.union primTypeCtors primDataTypeCtors)
primDataCtors
[] []
defs
checkDataDefs'
:: (Ord n, Show n, Pretty n)
=> Set n
-> Set n
-> [ErrorData n]
-> [DataDef n]
-> [DataDef n]
-> ([ErrorData n], [DataDef n])
checkDataDefs' nsTypes nsCtors errs dsChecked ds
| [] <- ds
= (reverse errs, reverse dsChecked)
| d : ds' <- ds
= case checkDataDef nsTypes nsCtors d of
Left errs'
-> checkDataDefs'
(Set.insert (dataDefTypeName d) nsTypes)
(Set.fromList $ fromMaybe [] $ dataCtorNamesOfDataDef d)
(errs ++ errs') dsChecked ds'
Right d'
-> checkDataDefs'
(Set.insert (dataDefTypeName d') nsTypes)
(Set.fromList $ fromMaybe [] $ dataCtorNamesOfDataDef d)
errs (d' : dsChecked) ds'
| otherwise
= error "ddc-core.checkDataDefs: bogus warning suppression"
checkDataDef
:: (Ord n, Show n, Pretty n)
=> Set n
-> Set n
-> DataDef n
-> Either [ErrorData n] (DataDef n)
checkDataDef nsTypes nsCtors def
| Set.member (dataDefTypeName def) nsTypes
= Left [ErrorDataDupTypeName (dataDefTypeName def)]
| Nothing <- dataDefCtors def
= Right def
| Just ctors <- dataDefCtors def
= case checkDataCtors nsCtors [] def [] ctors of
Left errs -> Left errs
Right ctors' -> Right $ def { dataDefCtors = Just ctors' }
| otherwise
= error "ddc-core.checkDataDef: bogus warning suppression"
checkDataCtors
:: (Ord n, Show n, Pretty n)
=> Set n
-> [ErrorData n]
-> DataDef n
-> [DataCtor n]
-> [DataCtor n]
-> Either [ErrorData n] [DataCtor n]
checkDataCtors nsCtors errs def csChecked cs
| [] <- cs, [] <- errs
= Right (reverse csChecked)
| [] <- cs
= Left (reverse errs)
| c : cs' <- cs
= case checkDataCtor nsCtors def c of
Left err -> checkDataCtors
(Set.insert (dataCtorName c) nsCtors)
(err : errs) def csChecked cs'
Right c' -> checkDataCtors
(Set.insert (dataCtorName c') nsCtors)
errs def (c' : csChecked) cs'
| otherwise
= error "ddc-core.checkDataCtors: bogus warning suppression"
checkDataCtor
:: (Ord n, Show n, Pretty n)
=> Set n
-> DataDef n
-> DataCtor n
-> Either (ErrorData n) (DataCtor n)
checkDataCtor nsCtors def ctor
| Set.member (dataCtorName ctor) nsCtors
= Left $ ErrorDataDupCtorName (dataCtorName ctor)
| not $ equivT (dataTypeOfDataDef def) (dataCtorResultType ctor)
= Left $ ErrorDataWrongResult
(dataCtorName ctor)
(dataCtorResultType ctor) (dataTypeOfDataDef def)
| otherwise
= Right ctor