{-# LANGUAGE FlexibleInstances          #-}
{-# LANGUAGE FlexibleContexts           #-}
{-# LANGUAGE DerivingVia                #-}


-- | This module has a function that computes the "slice" i.e. subset of the `Ms.BareSpec` that 
--   we actually need to verify a given target module, so that LH doesn't choke trying to resolve 
--   names that are not actually relevant and hence, not in the GHC Environment.
--   See LH issue 1773 for more details.
-- 
--   Specifically, this module has datatypes and code for building a Specification Dependency Graph 
--   whose vertices are 'names' that need to be resolve, and edges are 'dependencies'.


module Language.Haskell.Liquid.Bare.Slice (sliceSpecs) where

-- import qualified Language.Fixpoint.Types as F
-- import qualified Data.HashMap.Strict as M
import           Language.Haskell.Liquid.Types
-- import Data.Hashable
import qualified Language.Haskell.Liquid.Measure as Ms
-- import qualified Data.HashSet as S


-------------------------------------------------------------------------------
-- | Top-level "slicing" function
-------------------------------------------------------------------------------
sliceSpecs :: GhcSrc -> Ms.BareSpec -> [(ModName, Ms.BareSpec)] -> 
        [(ModName, Ms.BareSpec)]
sliceSpecs :: GhcSrc
-> BareSpec -> [(ModName, BareSpec)] -> [(ModName, BareSpec)]
sliceSpecs GhcSrc
_tgtSrc BareSpec
_tgtSpec [(ModName, BareSpec)]
specs = [(ModName, BareSpec)]
specs 

{- 

-------------------------------------------------------------------------------
-- | The different kinds of names we have to resolve
-------------------------------------------------------------------------------
data Label
  = Sign  -- ^ identifier signature
  | Func  -- ^ measure or reflect
  | DCon  -- ^ data constructor
  | TCon  -- ^ type constructor
  deriving (Eq, Ord, Enum, Show)

-------------------------------------------------------------------------------
-- | A dependency 'Node' is a pair of a name @LocSymbol@ and @Label@
-------------------------------------------------------------------------------
data Node = MkNode
  { nodeName  :: F.Symbol
  , nodeLabel :: Label
  }
  deriving (Eq, Ord)

instance Hashable Label where
  hashWithSalt s = hashWithSalt s . fromEnum 
instance Hashable Node where 
  hashWithSalt s MkNode {..} = hashWithSalt s (nodeName, nodeLabel) 

newtype DepGraph = MkDepGraph 
  { dGraph :: M.HashMap Node [Node] 
  }

-------------------------------------------------------------------------------
-- | A way to combine graphs of multiple modules
-------------------------------------------------------------------------------

instance Semigroup DepGraph where
  x <> y = MkDepGraph { dGraph = M.unionWith (++) (dGraph x) (dGraph y) }

instance Monoid DepGraph where
  mempty = MkDepGraph mempty

-------------------------------------------------------------------------------
-- | A function to build the dependencies for each module
-------------------------------------------------------------------------------

mkRoots :: GhcSrc -> S.HashSet Node
mkRoots = undefined

-------------------------------------------------------------------------------
-- | A function to build the dependencies for each module
-------------------------------------------------------------------------------

class Graph a where
  mkGraph :: a -> DepGraph

instance Graph [Ms.BareSpec] where
  mkGraph specs = mconcat [ mkGraph sp | sp <- specs]

instance Graph Ms.BareSpec where
  mkGraph sp = mconcat 
    [ undefined -- FIXME -- mkGraph (expSigs sp)
    ]

-------------------------------------------------------------------------------
-- | 'reachable roots g' returns the list of Node transitively reachable from roots
-------------------------------------------------------------------------------
reachable :: S.HashSet Node -> DepGraph -> S.HashSet Node
reachable roots g = undefined -- _TODO

-------------------------------------------------------------------------------
-- | Extract the dependencies 
-------------------------------------------------------------------------------

class Deps a where
  deps :: a -> [Node]

instance Deps BareType where
  deps = error "TBD:deps:bareType"

instance Deps DataDecl where
  deps = error "TBD:deps:datadecl"

instance Deps DataCtor where 
  deps = error "TBD:deps:datactor"

-}



{- 
             -- = [ (n, slice nodes sp) | (n, sp) <- specs ]
  -- where
    -- tgtGraph = mkGraph tgtSpec
    -- impGraph = mkGraph (snd <$> specs)
    -- roots    = mkRoots tgtSrc -- S.fromList . M.keys . dGraph $ tgtGraph
    -- nodes    = reachable roots (tgtGraph <> impGraph)

class Sliceable a where
  slice :: S.HashSet Node -> a -> a

instance Sliceable Ms.BareSpec where 
  slice nodes sp = sp

-}
----
{- 
These are the fields we have to worry about

unsafeFromLiftedSpec :: LiftedSpec -> Spec LocBareType F.LocSymbol
unsafeFromLiftedSpec a = Spec
  { 
  --->>> , asmSigs    = S.toList . liftedAsmSigs $ a
  --->>> , sigs       = S.toList . liftedSigs $ a
  --->>> , invariants = S.toList . liftedInvariants $ a
  --->>> , dataDecls  = S.toList . liftedDataDecls $ a
  --->>> , newtyDecls = S.toList . liftedNewtyDecls $ a
    
  , measures   = S.toList . liftedMeasures $ a
  , impSigs    = S.toList . liftedImpSigs $ a
  , expSigs    = S.toList . liftedExpSigs $ a
  , ialiases   = S.toList . liftedIaliases $ a
  , imports    = S.toList . liftedImports $ a
  , aliases    = S.toList . liftedAliases $ a
  , ealiases   = S.toList . liftedEaliases $ a
  , embeds     = liftedEmbeds a
  , qualifiers = S.toList . liftedQualifiers $ a
  , decr       = S.toList . liftedDecr $ a
  , lvars      = liftedLvars a
  , autois     = liftedAutois a
  , autosize   = liftedAutosize a
  , cmeasures  = S.toList . liftedCmeasures $ a
  , imeasures  = S.toList . liftedImeasures $ a
  , classes    = S.toList . liftedClasses $ a
  , claws      = S.toList . liftedClaws $ a
  , rinstance  = S.toList . liftedRinstance $ a
  , ilaws      = S.toList . liftedIlaws $ a
  , dvariance  = S.toList . liftedDvariance $ a
  , bounds     = liftedBounds a
  , defs       = liftedDefs a
  , axeqs      = S.toList . liftedAxeqs $ a
  }
-}