g2-0.1.0.0: src/G2/Liquid/Annotations.hs
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
module G2.Liquid.Annotations ( AnnotMap
, getAnnotations
, lookupAnnot
, lookupAnnotAtLoc) where
import G2.Language
import G2.Language.Monad
import G2.Liquid.Conversion
import G2.Liquid.Types
import Language.Haskell.Liquid.Liquid()
import Language.Haskell.Liquid.Constraint.Types hiding (ghcI)
import Language.Haskell.Liquid.Types hiding (Loc, names)
import Language.Haskell.Liquid.Types.RefType
import G2.Translation.Haskell
import qualified Data.HashMap.Lazy as HM
import Data.Hashable
import Data.List
import qualified Data.Map as M
import Data.Maybe
import qualified Data.Text as T
import SrcLoc
import Debug.Trace
lookupAnnot :: Name -> AnnotMap -> Maybe [(Maybe T.Text, Expr)]
lookupAnnot (Name _ _ _ (Just s)) =
HM.lookup s . unAnnotMap
lookupAnnot _ = const Nothing
lookupAnnotAtLoc :: Name -> AnnotMap -> Maybe [(Maybe T.Text, Expr)]
lookupAnnotAtLoc (Name _ _ _ (Just (Span {start = l}))) =
Just . concatMap snd . find (\(Span {start = l'}, _) -> l == l') . HM.toList . unAnnotMap
lookupAnnotAtLoc _ = const Nothing
getAnnotations :: [LHOutput] -> LHStateM ()
getAnnotations ghci_cg = do
locM <- return . locLookup =<< exprEnv
let anna = map lhCleanAnnotMaps ghci_cg
mapM_ (annotMapToExpr locM) anna
annotMapToExpr :: M.Map Loc Name -> AnnInfo SpecType -> LHStateM ()
annotMapToExpr locM (AI st) = mapM_ (uncurry (valToExpr locM)) (HM.toList st)
valToExpr :: M.Map Loc Name -> SrcSpan -> [(Maybe T.Text, SpecType)] -> LHStateM ()
valToExpr locM srcspn =
case mkSpan srcspn of
Just spn -> mapM_ (valToExpr' locM spn)
Nothing -> return . const ()
valToExpr' :: M.Map Loc Name -> Span -> (Maybe T.Text, SpecType) -> LHStateM ()
valToExpr' locM spn@(Span {start = stloc}) (n, ast) = do
e <- case M.lookup stloc locM of
Just n' -> lookupE n'
Nothing -> return Nothing
t <- specTypeToType ast
case (e, t) of
(Just e', Just t') -> do
let i = Id (Name "ret" Nothing 0 Nothing) t'
let ai = leadingLamUsesIds e'
dm <- dictMapFromIds (map snd ai)
ce <- convertSpecType dm M.empty (map snd ai) (Just i) ast
let ce' = addIds ce (ai ++ [(TermL, i)])
insertAnnotM spn n ce'
_ -> return ()
lhCleanAnnotMaps :: LHOutput -> AnnInfo SpecType
lhCleanAnnotMaps (LHOutput {cgI = cgi, solution = sol}) =
applySolution sol $ closeAnnots $ annotMap cgi
addIds :: Expr -> [(LamUse, Id)] -> Expr
addIds e ((u, i):is) = Lam u i $ addIds e is
-- addIds e@(Lam _ ei _) ((u, i):is) = if i == ei then e else Lam u i $ addIds e is
addIds e _ = e
-- modeled after Language.Haskell.Liquid.UX.Annotate
closeAnnots :: AnnInfo (Annot SpecType) -> AnnInfo SpecType
closeAnnots = closeA . filterA . collapseA
closeA :: AnnInfo (Annot b) -> AnnInfo b
closeA a@(AI m) = cf <$> a
where
cf (AnnLoc l) = case m `mlookup` l of
[(_, AnnUse t)] -> t
[(_, AnnDef t)] -> t
[(_, AnnRDf t)] -> t
_ -> error $ "malformed AnnInfo: " ++ show l
cf (AnnUse t) = t
cf (AnnDef t) = t
cf (AnnRDf t) = t
mlookup :: (Eq k, Show k, Hashable k) => HM.HashMap k v -> k -> v
mlookup m k = fromMaybe err $ HM.lookup k m
where
err = error $ "mlookup: unknown key " ++ show k
filterA :: AnnInfo (Annot t) -> AnnInfo (Annot t)
filterA (AI m) = AI (HM.filter ff m)
where
ff [(_, AnnLoc l)] = l `HM.member` m
ff _ = True
collapseA :: AnnInfo (Annot t) -> AnnInfo (Annot t)
collapseA (AI m) = AI (fmap pickOneA m)
pickOneA :: [(t, Annot t1)] -> [(t, Annot t1)]
pickOneA xas = case (rs, ds, ls, us) of
(x:_, _, _, _) -> [x]
(_, x:_, _, _) -> [x]
(_, _, _:_, _) -> trace ("Loc") []
(_, _, _, x:_) -> [x]
-- (_, x:_, _, _) -> [x]
-- (_, _, x:_, _) -> [x]
-- (_, _, _, x:_) -> [x]
(_, _, _, _ ) -> [ ]
where
rs = [x | x@(_, AnnRDf _) <- xas]
ds = [x | x@(_, AnnDef _) <- xas]
ls = [x | x@(_, AnnLoc _) <- xas]
us = [x | x@(_, AnnUse _) <- xas]