{-# LANGUAGE OverloadedStrings #-}

module Language.Haskell.Liquid.Types.Literals 
  ( literalFRefType
  , literalFReft
  , literalConst
  , mkI, mkS
  ) where

import Prelude hiding (error)
import Language.Haskell.Liquid.GHC.TypeRep ()
import Language.Haskell.Liquid.GHC.API
import qualified TyCon  as TC

import Language.Haskell.Liquid.Types.Types
import Language.Haskell.Liquid.Types.RefType
import Language.Haskell.Liquid.Transforms.CoreToLogic (mkLit, mkI, mkS)

import qualified Language.Fixpoint.Types as F

---------------------------------------------------------------
----------------------- Typing Literals -----------------------
---------------------------------------------------------------

makeRTypeBase :: Monoid r => Type -> r -> RType RTyCon RTyVar r
makeRTypeBase :: Type -> r -> RType RTyCon RTyVar r
makeRTypeBase (TyVarTy Var
α)    r
x
  = RTyVar -> r -> RType RTyCon RTyVar r
forall c tv r. tv -> r -> RType c tv r
RVar (Var -> RTyVar
rTyVar Var
α) r
x
makeRTypeBase (TyConApp TyCon
c [Type]
ts) r
x
  = TyCon
-> [RType RTyCon RTyVar r]
-> [RTProp RTyCon RTyVar r]
-> r
-> RType RTyCon RTyVar r
forall tv r.
TyCon
-> [RType RTyCon tv r]
-> [RTProp RTyCon tv r]
-> r
-> RType RTyCon tv r
rApp TyCon
c ((Type -> r -> RType RTyCon RTyVar r
forall r. Monoid r => Type -> r -> RType RTyCon RTyVar r
`makeRTypeBase` r
forall a. Monoid a => a
mempty) (Type -> RType RTyCon RTyVar r)
-> [Type] -> [RType RTyCon RTyVar r]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Type]
ts) [] r
x
makeRTypeBase Type
_              r
_
  = Maybe SrcSpan -> String -> RType RTyCon RTyVar r
forall a. Maybe SrcSpan -> String -> a
panic Maybe SrcSpan
forall a. Maybe a
Nothing String
"RefType : makeRTypeBase"

literalFRefType :: Literal -> RType RTyCon RTyVar F.Reft
literalFRefType :: Literal -> RType RTyCon RTyVar Reft
literalFRefType Literal
l
  = Type -> Reft -> RType RTyCon RTyVar Reft
forall r. Monoid r => Type -> r -> RType RTyCon RTyVar r
makeRTypeBase (Literal -> Type
literalType Literal
l) (Literal -> Reft
literalFReft Literal
l)

literalFReft :: Literal -> F.Reft
literalFReft :: Literal -> Reft
literalFReft Literal
l = Reft -> (Expr -> Reft) -> Maybe Expr -> Reft
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Reft
forall a. Monoid a => a
mempty Expr -> Reft
mkReft (Maybe Expr -> Reft) -> Maybe Expr -> Reft
forall a b. (a -> b) -> a -> b
$ Literal -> Maybe Expr
mkLit Literal
l

mkReft :: F.Expr -> F.Reft
mkReft :: Expr -> Reft
mkReft = Expr -> Reft
forall a. Expression a => a -> Reft
F.exprReft

-- | `literalConst` returns `Nothing` for unhandled lits because
--    otherwise string-literals show up as global int-constants
--    which blow up qualifier instantiation.

literalConst :: F.TCEmb TC.TyCon -> Literal -> (F.Sort, Maybe F.Expr)
literalConst :: TCEmb TyCon -> Literal -> (Sort, Maybe Expr)
literalConst TCEmb TyCon
tce Literal
l = (Sort
t, Literal -> Maybe Expr
mkLit Literal
l)
  where
    t :: Sort
t              = TCEmb TyCon -> Type -> Sort
typeSort TCEmb TyCon
tce (Type -> Sort) -> Type -> Sort
forall a b. (a -> b) -> a -> b
$ Literal -> Type
literalType Literal
l