{- |
    Module      :  $Header$
    Description :  Comparison of Curry Interfaces
    Copyright   :  (c) 2000 - 2007 Wolfgang Lux
                       2014 - 2015 Björn Peemöller
                       2014        Jan Tikovsky
                       2016        Finn Teegen
    License     :  BSD-3-clause

    Maintainer  :  bjp@informatik.uni-kiel.de
    Stability   :  experimental
    Portability :  portable

    If a module is recompiled, the compiler has to check whether the
    interface file must be updated. This must be done if any exported
    entity has been changed, or an export was removed or added. The
    function 'intfEquiv' checks whether two interfaces are
    equivalent, i.e., whether they define the same entities.
-}
module Curry.Syntax.InterfaceEquivalence (fixInterface, intfEquiv) where

import Data.List (deleteFirstsBy, sort)
import qualified Data.Set as Set

import Curry.Base.Ident
import Curry.Syntax

infix 4 =~=, `eqvSet`

-- |Are two given interfaces equivalent?
intfEquiv :: Interface -> Interface -> Bool
intfEquiv :: Interface -> Interface -> Bool
intfEquiv = Interface -> Interface -> Bool
forall a. Equiv a => a -> a -> Bool
(=~=)

-- |Type class to express the equivalence of two values
class Equiv a where
  (=~=) :: a -> a -> Bool

instance Equiv a => Equiv (Maybe a) where
  Nothing =~= :: Maybe a -> Maybe a -> Bool
=~= Nothing = Bool
True
  Nothing =~= Just _  = Bool
False
  Just _  =~= Nothing = Bool
False
  Just x :: a
x  =~= Just y :: a
y  = a
x a -> a -> Bool
forall a. Equiv a => a -> a -> Bool
=~= a
y

instance Equiv a => Equiv [a] where
  []     =~= :: [a] -> [a] -> Bool
=~= []     = Bool
True
  (x :: a
x:xs :: [a]
xs) =~= (y :: a
y:ys :: [a]
ys) = a
x a -> a -> Bool
forall a. Equiv a => a -> a -> Bool
=~= a
y Bool -> Bool -> Bool
&& [a]
xs [a] -> [a] -> Bool
forall a. Equiv a => a -> a -> Bool
=~= [a]
ys
  _      =~= _      = Bool
False

eqvList, eqvSet :: Equiv a => [a] -> [a] -> Bool
xs :: [a]
xs eqvList :: [a] -> [a] -> Bool
`eqvList` ys :: [a]
ys = [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
xs Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
ys Bool -> Bool -> Bool
&& [Bool] -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
and ((a -> a -> Bool) -> [a] -> [a] -> [Bool]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith a -> a -> Bool
forall a. Equiv a => a -> a -> Bool
(=~=) [a]
xs [a]
ys)
xs :: [a]
xs eqvSet :: [a] -> [a] -> Bool
`eqvSet` ys :: [a]
ys = [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null ((a -> a -> Bool) -> [a] -> [a] -> [a]
forall a. (a -> a -> Bool) -> [a] -> [a] -> [a]
deleteFirstsBy a -> a -> Bool
forall a. Equiv a => a -> a -> Bool
(=~=) [a]
xs [a]
ys [a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
++ (a -> a -> Bool) -> [a] -> [a] -> [a]
forall a. (a -> a -> Bool) -> [a] -> [a] -> [a]
deleteFirstsBy a -> a -> Bool
forall a. Equiv a => a -> a -> Bool
(=~=) [a]
ys [a]
xs)

instance Equiv Interface where
  Interface m1 :: ModuleIdent
m1 is1 :: [IImportDecl]
is1 ds1 :: [IDecl]
ds1 =~= :: Interface -> Interface -> Bool
=~= Interface m2 :: ModuleIdent
m2 is2 :: [IImportDecl]
is2 ds2 :: [IDecl]
ds2
    = ModuleIdent
m1 ModuleIdent -> ModuleIdent -> Bool
forall a. Eq a => a -> a -> Bool
== ModuleIdent
m2 Bool -> Bool -> Bool
&& [IImportDecl]
is1 [IImportDecl] -> [IImportDecl] -> Bool
forall a. Equiv a => [a] -> [a] -> Bool
`eqvSet` [IImportDecl]
is2 Bool -> Bool -> Bool
&& [IDecl]
ds1 [IDecl] -> [IDecl] -> Bool
forall a. Equiv a => [a] -> [a] -> Bool
`eqvSet` [IDecl]
ds2

instance Equiv IImportDecl where
  IImportDecl _ m1 :: ModuleIdent
m1 =~= :: IImportDecl -> IImportDecl -> Bool
=~= IImportDecl _ m2 :: ModuleIdent
m2 = ModuleIdent
m1 ModuleIdent -> ModuleIdent -> Bool
forall a. Eq a => a -> a -> Bool
== ModuleIdent
m2

-- Since the kind of type constructors or type classes can be omitted
-- in the interface when the kind is simple, i.e., it is either * or of
-- the form * -> ... -> *, a non given kind has to be considered equivalent
-- to a given one if the latter is simple.

eqvKindExpr :: Maybe KindExpr -> Maybe KindExpr -> Bool
Nothing  eqvKindExpr :: Maybe KindExpr -> Maybe KindExpr -> Bool
`eqvKindExpr` (Just k :: KindExpr
k) = KindExpr -> Bool
isSimpleKindExpr KindExpr
k
(Just k :: KindExpr
k) `eqvKindExpr` Nothing  = KindExpr -> Bool
isSimpleKindExpr KindExpr
k
k1 :: Maybe KindExpr
k1       `eqvKindExpr` k2 :: Maybe KindExpr
k2       = Maybe KindExpr
k1 Maybe KindExpr -> Maybe KindExpr -> Bool
forall a. Eq a => a -> a -> Bool
== Maybe KindExpr
k2

isSimpleKindExpr :: KindExpr -> Bool
isSimpleKindExpr :: KindExpr -> Bool
isSimpleKindExpr Star               = Bool
True
isSimpleKindExpr (ArrowKind Star k :: KindExpr
k) = KindExpr -> Bool
isSimpleKindExpr KindExpr
k
isSimpleKindExpr _                  = Bool
False


instance Equiv IDecl where
  IInfixDecl _ fix1 :: Infix
fix1 p1 :: Precedence
p1 op1 :: QualIdent
op1 =~= :: IDecl -> IDecl -> Bool
=~= IInfixDecl _ fix2 :: Infix
fix2 p2 :: Precedence
p2 op2 :: QualIdent
op2
    = Infix
fix1 Infix -> Infix -> Bool
forall a. Eq a => a -> a -> Bool
== Infix
fix2 Bool -> Bool -> Bool
&& Precedence
p1 Precedence -> Precedence -> Bool
forall a. Eq a => a -> a -> Bool
== Precedence
p2 Bool -> Bool -> Bool
&& QualIdent
op1 QualIdent -> QualIdent -> Bool
forall a. Eq a => a -> a -> Bool
== QualIdent
op2
  HidingDataDecl _ tc1 :: QualIdent
tc1 k1 :: Maybe KindExpr
k1 tvs1 :: [Ident]
tvs1 =~= HidingDataDecl _ tc2 :: QualIdent
tc2 k2 :: Maybe KindExpr
k2 tvs2 :: [Ident]
tvs2
    = QualIdent
tc1 QualIdent -> QualIdent -> Bool
forall a. Eq a => a -> a -> Bool
== QualIdent
tc2 Bool -> Bool -> Bool
&& Maybe KindExpr
k1 Maybe KindExpr -> Maybe KindExpr -> Bool
`eqvKindExpr` Maybe KindExpr
k2 Bool -> Bool -> Bool
&& [Ident]
tvs1 [Ident] -> [Ident] -> Bool
forall a. Eq a => a -> a -> Bool
== [Ident]
tvs2
  IDataDecl _ tc1 :: QualIdent
tc1 k1 :: Maybe KindExpr
k1 tvs1 :: [Ident]
tvs1 cs1 :: [ConstrDecl]
cs1 hs1 :: [Ident]
hs1 =~= IDataDecl _ tc2 :: QualIdent
tc2 k2 :: Maybe KindExpr
k2 tvs2 :: [Ident]
tvs2 cs2 :: [ConstrDecl]
cs2 hs2 :: [Ident]
hs2
    = QualIdent
tc1 QualIdent -> QualIdent -> Bool
forall a. Eq a => a -> a -> Bool
== QualIdent
tc2 Bool -> Bool -> Bool
&& Maybe KindExpr
k1 Maybe KindExpr -> Maybe KindExpr -> Bool
`eqvKindExpr` Maybe KindExpr
k2 Bool -> Bool -> Bool
&& [Ident]
tvs1 [Ident] -> [Ident] -> Bool
forall a. Eq a => a -> a -> Bool
== [Ident]
tvs2 Bool -> Bool -> Bool
&& [ConstrDecl]
cs1 [ConstrDecl] -> [ConstrDecl] -> Bool
forall a. Equiv a => a -> a -> Bool
=~= [ConstrDecl]
cs2 Bool -> Bool -> Bool
&&
      [Ident]
hs1 [Ident] -> [Ident] -> Bool
forall a. Equiv a => [a] -> [a] -> Bool
`eqvSet` [Ident]
hs2
  INewtypeDecl _ tc1 :: QualIdent
tc1 k1 :: Maybe KindExpr
k1 tvs1 :: [Ident]
tvs1 nc1 :: NewConstrDecl
nc1 hs1 :: [Ident]
hs1 =~= INewtypeDecl _ tc2 :: QualIdent
tc2 k2 :: Maybe KindExpr
k2 tvs2 :: [Ident]
tvs2 nc2 :: NewConstrDecl
nc2 hs2 :: [Ident]
hs2
    = QualIdent
tc1 QualIdent -> QualIdent -> Bool
forall a. Eq a => a -> a -> Bool
== QualIdent
tc2 Bool -> Bool -> Bool
&& Maybe KindExpr
k1 Maybe KindExpr -> Maybe KindExpr -> Bool
`eqvKindExpr` Maybe KindExpr
k2 Bool -> Bool -> Bool
&& [Ident]
tvs1 [Ident] -> [Ident] -> Bool
forall a. Eq a => a -> a -> Bool
== [Ident]
tvs2 Bool -> Bool -> Bool
&& NewConstrDecl
nc1 NewConstrDecl -> NewConstrDecl -> Bool
forall a. Equiv a => a -> a -> Bool
=~= NewConstrDecl
nc2 Bool -> Bool -> Bool
&&
      [Ident]
hs1 [Ident] -> [Ident] -> Bool
forall a. Equiv a => [a] -> [a] -> Bool
`eqvSet` [Ident]
hs2
  ITypeDecl _ tc1 :: QualIdent
tc1 k1 :: Maybe KindExpr
k1 tvs1 :: [Ident]
tvs1 ty1 :: TypeExpr
ty1 =~= ITypeDecl _ tc2 :: QualIdent
tc2 k2 :: Maybe KindExpr
k2 tvs2 :: [Ident]
tvs2 ty2 :: TypeExpr
ty2
    = QualIdent
tc1 QualIdent -> QualIdent -> Bool
forall a. Eq a => a -> a -> Bool
== QualIdent
tc2 Bool -> Bool -> Bool
&& Maybe KindExpr
k1 Maybe KindExpr -> Maybe KindExpr -> Bool
`eqvKindExpr` Maybe KindExpr
k2 Bool -> Bool -> Bool
&& [Ident]
tvs1 [Ident] -> [Ident] -> Bool
forall a. Eq a => a -> a -> Bool
== [Ident]
tvs2 Bool -> Bool -> Bool
&& TypeExpr
ty1 TypeExpr -> TypeExpr -> Bool
forall a. Eq a => a -> a -> Bool
== TypeExpr
ty2
  IFunctionDecl _ f1 :: QualIdent
f1 cm1 :: Maybe Ident
cm1 n1 :: Int
n1 qty1 :: QualTypeExpr
qty1 =~= IFunctionDecl _ f2 :: QualIdent
f2 cm2 :: Maybe Ident
cm2 n2 :: Int
n2 qty2 :: QualTypeExpr
qty2
    = QualIdent
f1 QualIdent -> QualIdent -> Bool
forall a. Eq a => a -> a -> Bool
== QualIdent
f2 Bool -> Bool -> Bool
&& Maybe Ident
cm1 Maybe Ident -> Maybe Ident -> Bool
forall a. Eq a => a -> a -> Bool
== Maybe Ident
cm2 Bool -> Bool -> Bool
&& Int
n1 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
n2 Bool -> Bool -> Bool
&& QualTypeExpr
qty1 QualTypeExpr -> QualTypeExpr -> Bool
forall a. Eq a => a -> a -> Bool
== QualTypeExpr
qty2
  HidingClassDecl _ cx1 :: Context
cx1 cls1 :: QualIdent
cls1 k1 :: Maybe KindExpr
k1 _ =~= HidingClassDecl _ cx2 :: Context
cx2 cls2 :: QualIdent
cls2 k2 :: Maybe KindExpr
k2 _
    = Context
cx1 Context -> Context -> Bool
forall a. Eq a => a -> a -> Bool
== Context
cx2 Bool -> Bool -> Bool
&& QualIdent
cls1 QualIdent -> QualIdent -> Bool
forall a. Eq a => a -> a -> Bool
== QualIdent
cls2 Bool -> Bool -> Bool
&& Maybe KindExpr
k1 Maybe KindExpr -> Maybe KindExpr -> Bool
`eqvKindExpr` Maybe KindExpr
k2
  IClassDecl _ cx1 :: Context
cx1 cls1 :: QualIdent
cls1 k1 :: Maybe KindExpr
k1 _ ms1 :: [IMethodDecl]
ms1 hs1 :: [Ident]
hs1 =~= IClassDecl _ cx2 :: Context
cx2 cls2 :: QualIdent
cls2 k2 :: Maybe KindExpr
k2 _ ms2 :: [IMethodDecl]
ms2 hs2 :: [Ident]
hs2
    = Context
cx1 Context -> Context -> Bool
forall a. Eq a => a -> a -> Bool
== Context
cx2 Bool -> Bool -> Bool
&& QualIdent
cls1 QualIdent -> QualIdent -> Bool
forall a. Eq a => a -> a -> Bool
== QualIdent
cls2 Bool -> Bool -> Bool
&& Maybe KindExpr
k1 Maybe KindExpr -> Maybe KindExpr -> Bool
`eqvKindExpr` Maybe KindExpr
k2 Bool -> Bool -> Bool
&&
      [IMethodDecl]
ms1 [IMethodDecl] -> [IMethodDecl] -> Bool
forall a. Equiv a => [a] -> [a] -> Bool
`eqvList` [IMethodDecl]
ms2 Bool -> Bool -> Bool
&& [Ident]
hs1 [Ident] -> [Ident] -> Bool
forall a. Equiv a => [a] -> [a] -> Bool
`eqvSet` [Ident]
hs2
  IInstanceDecl _ cx1 :: Context
cx1 cls1 :: QualIdent
cls1 ty1 :: TypeExpr
ty1 is1 :: [IMethodImpl]
is1 m1 :: Maybe ModuleIdent
m1 =~= IInstanceDecl _ cx2 :: Context
cx2 cls2 :: QualIdent
cls2 ty2 :: TypeExpr
ty2 is2 :: [IMethodImpl]
is2 m2 :: Maybe ModuleIdent
m2
    = Context
cx1 Context -> Context -> Bool
forall a. Eq a => a -> a -> Bool
== Context
cx2 Bool -> Bool -> Bool
&& QualIdent
cls1 QualIdent -> QualIdent -> Bool
forall a. Eq a => a -> a -> Bool
== QualIdent
cls2 Bool -> Bool -> Bool
&& TypeExpr
ty1 TypeExpr -> TypeExpr -> Bool
forall a. Eq a => a -> a -> Bool
== TypeExpr
ty2 Bool -> Bool -> Bool
&& [IMethodImpl] -> [IMethodImpl]
forall a. Ord a => [a] -> [a]
sort [IMethodImpl]
is1 [IMethodImpl] -> [IMethodImpl] -> Bool
forall a. Eq a => a -> a -> Bool
== [IMethodImpl] -> [IMethodImpl]
forall a. Ord a => [a] -> [a]
sort [IMethodImpl]
is2 Bool -> Bool -> Bool
&&
      Maybe ModuleIdent
m1 Maybe ModuleIdent -> Maybe ModuleIdent -> Bool
forall a. Eq a => a -> a -> Bool
== Maybe ModuleIdent
m2
  _ =~= _ = Bool
False

instance Equiv ConstrDecl where
  ConstrDecl _ c1 :: Ident
c1 tys1 :: [TypeExpr]
tys1 =~= :: ConstrDecl -> ConstrDecl -> Bool
=~= ConstrDecl _ c2 :: Ident
c2 tys2 :: [TypeExpr]
tys2
    = Ident
c1 Ident -> Ident -> Bool
forall a. Eq a => a -> a -> Bool
== Ident
c2 Bool -> Bool -> Bool
&& [TypeExpr]
tys1 [TypeExpr] -> [TypeExpr] -> Bool
forall a. Eq a => a -> a -> Bool
== [TypeExpr]
tys2
  ConOpDecl _ ty11 :: TypeExpr
ty11 op1 :: Ident
op1 ty12 :: TypeExpr
ty12 =~= ConOpDecl _ ty21 :: TypeExpr
ty21 op2 :: Ident
op2 ty22 :: TypeExpr
ty22
    = Ident
op1 Ident -> Ident -> Bool
forall a. Eq a => a -> a -> Bool
== Ident
op2 Bool -> Bool -> Bool
&& TypeExpr
ty11 TypeExpr -> TypeExpr -> Bool
forall a. Eq a => a -> a -> Bool
== TypeExpr
ty21 Bool -> Bool -> Bool
&& TypeExpr
ty12 TypeExpr -> TypeExpr -> Bool
forall a. Eq a => a -> a -> Bool
== TypeExpr
ty22
  RecordDecl _ c1 :: Ident
c1 fs1 :: [FieldDecl]
fs1 =~= RecordDecl _ c2 :: Ident
c2 fs2 :: [FieldDecl]
fs2
    = Ident
c1 Ident -> Ident -> Bool
forall a. Eq a => a -> a -> Bool
== Ident
c2 Bool -> Bool -> Bool
&& [FieldDecl]
fs1 [FieldDecl] -> [FieldDecl] -> Bool
forall a. Equiv a => [a] -> [a] -> Bool
`eqvList` [FieldDecl]
fs2
  _ =~= _ = Bool
False

instance Equiv FieldDecl where
  FieldDecl _ ls1 :: [Ident]
ls1 ty1 :: TypeExpr
ty1 =~= :: FieldDecl -> FieldDecl -> Bool
=~= FieldDecl _ ls2 :: [Ident]
ls2 ty2 :: TypeExpr
ty2 = [Ident]
ls1 [Ident] -> [Ident] -> Bool
forall a. Eq a => a -> a -> Bool
== [Ident]
ls2 Bool -> Bool -> Bool
&& TypeExpr
ty1 TypeExpr -> TypeExpr -> Bool
forall a. Eq a => a -> a -> Bool
== TypeExpr
ty2

instance Equiv NewConstrDecl where
  NewConstrDecl _ c1 :: Ident
c1 ty1 :: TypeExpr
ty1 =~= :: NewConstrDecl -> NewConstrDecl -> Bool
=~= NewConstrDecl _ c2 :: Ident
c2 ty2 :: TypeExpr
ty2 = Ident
c1 Ident -> Ident -> Bool
forall a. Eq a => a -> a -> Bool
== Ident
c2 Bool -> Bool -> Bool
&& TypeExpr
ty1 TypeExpr -> TypeExpr -> Bool
forall a. Eq a => a -> a -> Bool
== TypeExpr
ty2
  NewRecordDecl _ c1 :: Ident
c1 fld1 :: (Ident, TypeExpr)
fld1 =~= NewRecordDecl _ c2 :: Ident
c2 fld2 :: (Ident, TypeExpr)
fld2 = Ident
c1 Ident -> Ident -> Bool
forall a. Eq a => a -> a -> Bool
== Ident
c2 Bool -> Bool -> Bool
&& (Ident, TypeExpr)
fld1 (Ident, TypeExpr) -> (Ident, TypeExpr) -> Bool
forall a. Eq a => a -> a -> Bool
== (Ident, TypeExpr)
fld2
  _ =~= _ = Bool
False

instance Equiv IMethodDecl where
  IMethodDecl _ f1 :: Ident
f1 a1 :: Maybe Int
a1 qty1 :: QualTypeExpr
qty1 =~= :: IMethodDecl -> IMethodDecl -> Bool
=~= IMethodDecl _ f2 :: Ident
f2 a2 :: Maybe Int
a2 qty2 :: QualTypeExpr
qty2
    = Ident
f1 Ident -> Ident -> Bool
forall a. Eq a => a -> a -> Bool
== Ident
f2 Bool -> Bool -> Bool
&& Maybe Int
a1 Maybe Int -> Maybe Int -> Bool
forall a. Eq a => a -> a -> Bool
== Maybe Int
a2 Bool -> Bool -> Bool
&& QualTypeExpr
qty1 QualTypeExpr -> QualTypeExpr -> Bool
forall a. Eq a => a -> a -> Bool
== QualTypeExpr
qty2

instance Equiv Ident where
  =~= :: Ident -> Ident -> Bool
(=~=) = Ident -> Ident -> Bool
forall a. Eq a => a -> a -> Bool
(==)

-- If we check for a change in the interface, we do not need to check the
-- interface declarations, but still must disambiguate (nullary) type
-- constructors and type variables in type expressions. This is handled
-- by function 'fixInterface' and the associated type class 'FixInterface'.

-- |Disambiguate nullary type constructors and type variables.
fixInterface :: Interface -> Interface
fixInterface :: Interface -> Interface
fixInterface (Interface m :: ModuleIdent
m is :: [IImportDecl]
is ds :: [IDecl]
ds) = ModuleIdent -> [IImportDecl] -> [IDecl] -> Interface
Interface ModuleIdent
m [IImportDecl]
is ([IDecl] -> Interface) -> [IDecl] -> Interface
forall a b. (a -> b) -> a -> b
$
  Set Ident -> [IDecl] -> [IDecl]
forall a. FixInterface a => Set Ident -> a -> a
fix ([Ident] -> Set Ident
forall a. Ord a => [a] -> Set a
Set.fromList ([IDecl] -> [Ident]
typeConstructors [IDecl]
ds)) [IDecl]
ds

class FixInterface a where
  fix :: Set.Set Ident -> a -> a

instance FixInterface a => FixInterface (Maybe a) where
  fix :: Set Ident -> Maybe a -> Maybe a
fix tcs :: Set Ident
tcs = (a -> a) -> Maybe a -> Maybe a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Set Ident -> a -> a
forall a. FixInterface a => Set Ident -> a -> a
fix Set Ident
tcs)

instance FixInterface a => FixInterface [a] where
  fix :: Set Ident -> [a] -> [a]
fix tcs :: Set Ident
tcs = (a -> a) -> [a] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map (Set Ident -> a -> a
forall a. FixInterface a => Set Ident -> a -> a
fix Set Ident
tcs)

instance FixInterface IDecl where
  fix :: Set Ident -> IDecl -> IDecl
fix tcs :: Set Ident
tcs (IDataDecl p :: Position
p tc :: QualIdent
tc k :: Maybe KindExpr
k vs :: [Ident]
vs cs :: [ConstrDecl]
cs hs :: [Ident]
hs) =
    Position
-> QualIdent
-> Maybe KindExpr
-> [Ident]
-> [ConstrDecl]
-> [Ident]
-> IDecl
IDataDecl Position
p QualIdent
tc Maybe KindExpr
k [Ident]
vs (Set Ident -> [ConstrDecl] -> [ConstrDecl]
forall a. FixInterface a => Set Ident -> a -> a
fix Set Ident
tcs [ConstrDecl]
cs) [Ident]
hs
  fix tcs :: Set Ident
tcs (INewtypeDecl p :: Position
p tc :: QualIdent
tc k :: Maybe KindExpr
k vs :: [Ident]
vs nc :: NewConstrDecl
nc hs :: [Ident]
hs) =
    Position
-> QualIdent
-> Maybe KindExpr
-> [Ident]
-> NewConstrDecl
-> [Ident]
-> IDecl
INewtypeDecl Position
p QualIdent
tc Maybe KindExpr
k [Ident]
vs (Set Ident -> NewConstrDecl -> NewConstrDecl
forall a. FixInterface a => Set Ident -> a -> a
fix Set Ident
tcs NewConstrDecl
nc) [Ident]
hs
  fix tcs :: Set Ident
tcs (ITypeDecl p :: Position
p tc :: QualIdent
tc k :: Maybe KindExpr
k vs :: [Ident]
vs ty :: TypeExpr
ty) =
    Position
-> QualIdent -> Maybe KindExpr -> [Ident] -> TypeExpr -> IDecl
ITypeDecl Position
p QualIdent
tc Maybe KindExpr
k [Ident]
vs (Set Ident -> TypeExpr -> TypeExpr
forall a. FixInterface a => Set Ident -> a -> a
fix Set Ident
tcs TypeExpr
ty)
  fix tcs :: Set Ident
tcs (IFunctionDecl p :: Position
p f :: QualIdent
f cm :: Maybe Ident
cm n :: Int
n qty :: QualTypeExpr
qty) =
    Position
-> QualIdent -> Maybe Ident -> Int -> QualTypeExpr -> IDecl
IFunctionDecl Position
p QualIdent
f Maybe Ident
cm Int
n (Set Ident -> QualTypeExpr -> QualTypeExpr
forall a. FixInterface a => Set Ident -> a -> a
fix Set Ident
tcs QualTypeExpr
qty)
  fix tcs :: Set Ident
tcs (HidingClassDecl p :: Position
p cx :: Context
cx cls :: QualIdent
cls k :: Maybe KindExpr
k tv :: Ident
tv) =
    Position
-> Context -> QualIdent -> Maybe KindExpr -> Ident -> IDecl
HidingClassDecl Position
p (Set Ident -> Context -> Context
forall a. FixInterface a => Set Ident -> a -> a
fix Set Ident
tcs Context
cx) QualIdent
cls Maybe KindExpr
k Ident
tv
  fix tcs :: Set Ident
tcs (IClassDecl p :: Position
p cx :: Context
cx cls :: QualIdent
cls k :: Maybe KindExpr
k tv :: Ident
tv ms :: [IMethodDecl]
ms hs :: [Ident]
hs) =
    Position
-> Context
-> QualIdent
-> Maybe KindExpr
-> Ident
-> [IMethodDecl]
-> [Ident]
-> IDecl
IClassDecl Position
p (Set Ident -> Context -> Context
forall a. FixInterface a => Set Ident -> a -> a
fix Set Ident
tcs Context
cx) QualIdent
cls Maybe KindExpr
k Ident
tv (Set Ident -> [IMethodDecl] -> [IMethodDecl]
forall a. FixInterface a => Set Ident -> a -> a
fix Set Ident
tcs [IMethodDecl]
ms) [Ident]
hs
  fix tcs :: Set Ident
tcs (IInstanceDecl p :: Position
p cx :: Context
cx cls :: QualIdent
cls inst :: TypeExpr
inst is :: [IMethodImpl]
is m :: Maybe ModuleIdent
m) =
    Position
-> Context
-> QualIdent
-> TypeExpr
-> [IMethodImpl]
-> Maybe ModuleIdent
-> IDecl
IInstanceDecl Position
p (Set Ident -> Context -> Context
forall a. FixInterface a => Set Ident -> a -> a
fix Set Ident
tcs Context
cx) QualIdent
cls (Set Ident -> TypeExpr -> TypeExpr
forall a. FixInterface a => Set Ident -> a -> a
fix Set Ident
tcs TypeExpr
inst) [IMethodImpl]
is Maybe ModuleIdent
m
  fix _ d :: IDecl
d = IDecl
d

instance FixInterface ConstrDecl where
  fix :: Set Ident -> ConstrDecl -> ConstrDecl
fix tcs :: Set Ident
tcs (ConstrDecl p :: SpanInfo
p      c :: Ident
c tys :: [TypeExpr]
tys) = SpanInfo -> Ident -> [TypeExpr] -> ConstrDecl
ConstrDecl SpanInfo
p Ident
c (Set Ident -> [TypeExpr] -> [TypeExpr]
forall a. FixInterface a => Set Ident -> a -> a
fix Set Ident
tcs [TypeExpr]
tys)
  fix tcs :: Set Ident
tcs (ConOpDecl  p :: SpanInfo
p ty1 :: TypeExpr
ty1 op :: Ident
op ty2 :: TypeExpr
ty2) = SpanInfo -> TypeExpr -> Ident -> TypeExpr -> ConstrDecl
ConOpDecl  SpanInfo
p   (Set Ident -> TypeExpr -> TypeExpr
forall a. FixInterface a => Set Ident -> a -> a
fix Set Ident
tcs TypeExpr
ty1)
                                                Ident
op   (Set Ident -> TypeExpr -> TypeExpr
forall a. FixInterface a => Set Ident -> a -> a
fix Set Ident
tcs TypeExpr
ty2)
  fix tcs :: Set Ident
tcs (RecordDecl p :: SpanInfo
p c :: Ident
c fs :: [FieldDecl]
fs)       = SpanInfo -> Ident -> [FieldDecl] -> ConstrDecl
RecordDecl SpanInfo
p Ident
c (Set Ident -> [FieldDecl] -> [FieldDecl]
forall a. FixInterface a => Set Ident -> a -> a
fix Set Ident
tcs [FieldDecl]
fs)

instance FixInterface FieldDecl where
  fix :: Set Ident -> FieldDecl -> FieldDecl
fix tcs :: Set Ident
tcs (FieldDecl p :: SpanInfo
p ls :: [Ident]
ls ty :: TypeExpr
ty) = SpanInfo -> [Ident] -> TypeExpr -> FieldDecl
FieldDecl SpanInfo
p [Ident]
ls (Set Ident -> TypeExpr -> TypeExpr
forall a. FixInterface a => Set Ident -> a -> a
fix Set Ident
tcs TypeExpr
ty)

instance FixInterface NewConstrDecl where
  fix :: Set Ident -> NewConstrDecl -> NewConstrDecl
fix tcs :: Set Ident
tcs (NewConstrDecl p :: SpanInfo
p c :: Ident
c ty :: TypeExpr
ty    ) = SpanInfo -> Ident -> TypeExpr -> NewConstrDecl
NewConstrDecl SpanInfo
p Ident
c (Set Ident -> TypeExpr -> TypeExpr
forall a. FixInterface a => Set Ident -> a -> a
fix Set Ident
tcs TypeExpr
ty)
  fix tcs :: Set Ident
tcs (NewRecordDecl p :: SpanInfo
p c :: Ident
c (i :: Ident
i,ty :: TypeExpr
ty)) = SpanInfo -> Ident -> (Ident, TypeExpr) -> NewConstrDecl
NewRecordDecl SpanInfo
p Ident
c (Ident
i, Set Ident -> TypeExpr -> TypeExpr
forall a. FixInterface a => Set Ident -> a -> a
fix Set Ident
tcs TypeExpr
ty)

instance FixInterface IMethodDecl where
  fix :: Set Ident -> IMethodDecl -> IMethodDecl
fix tcs :: Set Ident
tcs (IMethodDecl p :: Position
p f :: Ident
f a :: Maybe Int
a qty :: QualTypeExpr
qty) = Position -> Ident -> Maybe Int -> QualTypeExpr -> IMethodDecl
IMethodDecl Position
p Ident
f Maybe Int
a (Set Ident -> QualTypeExpr -> QualTypeExpr
forall a. FixInterface a => Set Ident -> a -> a
fix Set Ident
tcs QualTypeExpr
qty)

instance FixInterface QualTypeExpr where
  fix :: Set Ident -> QualTypeExpr -> QualTypeExpr
fix tcs :: Set Ident
tcs (QualTypeExpr spi :: SpanInfo
spi cx :: Context
cx ty :: TypeExpr
ty) = SpanInfo -> Context -> TypeExpr -> QualTypeExpr
QualTypeExpr SpanInfo
spi (Set Ident -> Context -> Context
forall a. FixInterface a => Set Ident -> a -> a
fix Set Ident
tcs Context
cx) (Set Ident -> TypeExpr -> TypeExpr
forall a. FixInterface a => Set Ident -> a -> a
fix Set Ident
tcs TypeExpr
ty)

instance FixInterface Constraint where
  fix :: Set Ident -> Constraint -> Constraint
fix tcs :: Set Ident
tcs (Constraint spi :: SpanInfo
spi qcls :: QualIdent
qcls ty :: TypeExpr
ty) = SpanInfo -> QualIdent -> TypeExpr -> Constraint
Constraint SpanInfo
spi QualIdent
qcls (Set Ident -> TypeExpr -> TypeExpr
forall a. FixInterface a => Set Ident -> a -> a
fix Set Ident
tcs TypeExpr
ty)

instance FixInterface TypeExpr where
  fix :: Set Ident -> TypeExpr -> TypeExpr
fix tcs :: Set Ident
tcs (ConstructorType spi :: SpanInfo
spi tc :: QualIdent
tc)
    | Bool -> Bool
not (QualIdent -> Bool
isQualified QualIdent
tc) Bool -> Bool -> Bool
&& Bool -> Bool
not (QualIdent -> Bool
isPrimTypeId QualIdent
tc) Bool -> Bool -> Bool
&& Ident
tc' Ident -> Set Ident -> Bool
forall a. Ord a => a -> Set a -> Bool
`Set.notMember` Set Ident
tcs
    = SpanInfo -> Ident -> TypeExpr
VariableType SpanInfo
spi Ident
tc'
    | Bool
otherwise = SpanInfo -> QualIdent -> TypeExpr
ConstructorType SpanInfo
spi QualIdent
tc
    where tc' :: Ident
tc' = QualIdent -> Ident
unqualify QualIdent
tc
  fix tcs :: Set Ident
tcs (ApplyType  spi :: SpanInfo
spi ty1 :: TypeExpr
ty1 ty2 :: TypeExpr
ty2) = SpanInfo -> TypeExpr -> TypeExpr -> TypeExpr
ApplyType SpanInfo
spi (Set Ident -> TypeExpr -> TypeExpr
forall a. FixInterface a => Set Ident -> a -> a
fix Set Ident
tcs TypeExpr
ty1) (Set Ident -> TypeExpr -> TypeExpr
forall a. FixInterface a => Set Ident -> a -> a
fix Set Ident
tcs TypeExpr
ty2)
  fix tcs :: Set Ident
tcs (VariableType    spi :: SpanInfo
spi tv :: Ident
tv)
    | Ident
tv Ident -> Set Ident -> Bool
forall a. Ord a => a -> Set a -> Bool
`Set.member` Set Ident
tcs = SpanInfo -> QualIdent -> TypeExpr
ConstructorType SpanInfo
spi (Ident -> QualIdent
qualify Ident
tv)
    | Bool
otherwise           = SpanInfo -> Ident -> TypeExpr
VariableType SpanInfo
spi Ident
tv
  fix tcs :: Set Ident
tcs (TupleType      spi :: SpanInfo
spi tys :: [TypeExpr]
tys) = SpanInfo -> [TypeExpr] -> TypeExpr
TupleType SpanInfo
spi (Set Ident -> [TypeExpr] -> [TypeExpr]
forall a. FixInterface a => Set Ident -> a -> a
fix Set Ident
tcs [TypeExpr]
tys)
  fix tcs :: Set Ident
tcs (ListType        spi :: SpanInfo
spi ty :: TypeExpr
ty) = SpanInfo -> TypeExpr -> TypeExpr
ListType  SpanInfo
spi (Set Ident -> TypeExpr -> TypeExpr
forall a. FixInterface a => Set Ident -> a -> a
fix Set Ident
tcs TypeExpr
ty)
  fix tcs :: Set Ident
tcs (ArrowType  spi :: SpanInfo
spi ty1 :: TypeExpr
ty1 ty2 :: TypeExpr
ty2) = SpanInfo -> TypeExpr -> TypeExpr -> TypeExpr
ArrowType SpanInfo
spi (Set Ident -> TypeExpr -> TypeExpr
forall a. FixInterface a => Set Ident -> a -> a
fix Set Ident
tcs TypeExpr
ty1) (Set Ident -> TypeExpr -> TypeExpr
forall a. FixInterface a => Set Ident -> a -> a
fix Set Ident
tcs TypeExpr
ty2)
  fix tcs :: Set Ident
tcs (ParenType       spi :: SpanInfo
spi ty :: TypeExpr
ty) = SpanInfo -> TypeExpr -> TypeExpr
ParenType SpanInfo
spi (Set Ident -> TypeExpr -> TypeExpr
forall a. FixInterface a => Set Ident -> a -> a
fix Set Ident
tcs TypeExpr
ty)
  fix tcs :: Set Ident
tcs (ForallType   spi :: SpanInfo
spi vs :: [Ident]
vs ty :: TypeExpr
ty) = SpanInfo -> [Ident] -> TypeExpr -> TypeExpr
ForallType SpanInfo
spi [Ident]
vs (Set Ident -> TypeExpr -> TypeExpr
forall a. FixInterface a => Set Ident -> a -> a
fix Set Ident
tcs TypeExpr
ty)

typeConstructors :: [IDecl] -> [Ident]
typeConstructors :: [IDecl] -> [Ident]
typeConstructors ds :: [IDecl]
ds = [Ident
tc | (QualIdent _ Nothing tc :: Ident
tc) <- (IDecl -> [QualIdent] -> [QualIdent])
-> [QualIdent] -> [IDecl] -> [QualIdent]
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr IDecl -> [QualIdent] -> [QualIdent]
tyCons [] [IDecl]
ds]
  where tyCons :: IDecl -> [QualIdent] -> [QualIdent]
tyCons (IInfixDecl          _ _ _ _) tcs :: [QualIdent]
tcs = [QualIdent]
tcs
        tyCons (HidingDataDecl     _ tc :: QualIdent
tc _ _) tcs :: [QualIdent]
tcs = QualIdent
tc QualIdent -> [QualIdent] -> [QualIdent]
forall a. a -> [a] -> [a]
: [QualIdent]
tcs
        tyCons (IDataDecl      _ tc :: QualIdent
tc _ _ _ _) tcs :: [QualIdent]
tcs = QualIdent
tc QualIdent -> [QualIdent] -> [QualIdent]
forall a. a -> [a] -> [a]
: [QualIdent]
tcs
        tyCons (INewtypeDecl   _ tc :: QualIdent
tc _ _ _ _) tcs :: [QualIdent]
tcs = QualIdent
tc QualIdent -> [QualIdent] -> [QualIdent]
forall a. a -> [a] -> [a]
: [QualIdent]
tcs
        tyCons (ITypeDecl        _ tc :: QualIdent
tc _ _ _) tcs :: [QualIdent]
tcs = QualIdent
tc QualIdent -> [QualIdent] -> [QualIdent]
forall a. a -> [a] -> [a]
: [QualIdent]
tcs
        tyCons (IFunctionDecl     _ _ _ _ _) tcs :: [QualIdent]
tcs = [QualIdent]
tcs
        tyCons (HidingClassDecl   _ _ _ _ _) tcs :: [QualIdent]
tcs = [QualIdent]
tcs
        tyCons (IClassDecl    _ _ _ _ _ _ _) tcs :: [QualIdent]
tcs = [QualIdent]
tcs
        tyCons (IInstanceDecl   _ _ _ _ _ _) tcs :: [QualIdent]
tcs = [QualIdent]
tcs