packages feed

liquidhaskell-boot-0.9.2.5.0: src/Language/Haskell/Liquid/Bare/Laws.hs

module Language.Haskell.Liquid.Bare.Laws ( makeInstanceLaws ) where

import qualified Data.Maybe                                 as Mb
import qualified Data.List                                  as L
import qualified Data.HashMap.Strict                        as M
import           Control.Monad ((<=<))

import qualified Language.Haskell.Liquid.Measure            as Ms
import qualified Language.Fixpoint.Types                    as F
import qualified Language.Haskell.Liquid.GHC.Misc           as GM
import           Language.Haskell.Liquid.Bare.Types         as Bare
import           Language.Haskell.Liquid.Bare.Resolve       as Bare
import           Language.Haskell.Liquid.Bare.Expand        as Bare
import           Language.Haskell.Liquid.Types
import           Liquid.GHC.API



makeInstanceLaws :: Bare.Env -> Bare.SigEnv -> [(Var,LocSpecType)]
                -> Bare.ModSpecs -> [LawInstance]
makeInstanceLaws env sigEnv sigs specs
  = [makeInstanceLaw env sigEnv sigs name rilaw
              | (name, spec) <- M.toList specs
              , rilaw <- Ms.ilaws spec ]


makeInstanceLaw :: Bare.Env -> Bare.SigEnv -> [(Var,LocSpecType)] -> ModName
                -> RILaws LocBareType -> LawInstance
makeInstanceLaw env sigEnv sigs name rilaw = LawInstance
  { lilName   = Mb.fromMaybe errmsg tc
  , liSupers  = mkTy <$> rilSupers rilaw
  , lilTyArgs = mkTy <$> rilTyArgs rilaw
  , lilEqus   = [(mkVar l, mkTypedVar r) | (l,r)<- rilEqus rilaw ]
  , lilPos    = GM.sourcePosSrcSpan $ loc $ rilPos rilaw
  }
  where
    tc    :: Maybe Class
    tc     = classTc (rilName rilaw)
    errmsg = error ("Not a type class: " ++ F.showpp tc)

    classTc = tyConClass_maybe <=< (Bare.maybeResolveSym env name "makeClass" . btc_tc)

    mkTy :: LocBareType -> LocSpecType
    mkTy = Bare.cookSpecType env sigEnv name Bare.GenTV
    mkVar :: LocSymbol -> VarOrLocSymbol
    mkVar x = case Bare.maybeResolveSym env name "makeInstanceLaw" x of
                Just v -> Left v
                _      -> Right x

    mkTypedVar :: LocSymbol -> (VarOrLocSymbol, Maybe LocSpecType)
    mkTypedVar l = case mkVar l of
                     Left x -> (Left x, Just $ Mb.fromMaybe (dummyLoc $ ofType $ varType x) (L.lookup x sigs))
                     Right x -> (Right x, Nothing)