module Idris.Elab.Utils where
import Idris.AbsSyntax
import Idris.Core.Elaborate hiding (Tactic(..))
import Idris.Core.Evaluate
import Idris.Core.TT
import Idris.Core.Typecheck
import Idris.Core.WHNF
import Idris.Delaborate
import Idris.Docstrings
import Idris.Error
import Idris.Output
import Util.Pretty
import Control.Monad
import Control.Monad.State
import Data.List
import qualified Data.Map as Map
import Data.Maybe
recheckC = recheckC_borrowing False True []
recheckC_borrowing uniq_check addConstrs bs tcns fc mkerr env t
= do
ctxt <- getContext
t' <- case safeForget t of
Just ft -> return ft
Nothing -> tclift $ tfail $ mkerr (At fc (IncompleteTerm t))
(tm, ty, cs) <- tclift $ case recheck_borrowing uniq_check bs tcns ctxt env t' t of
Error e -> tfail (At fc (mkerr e))
OK x -> return x
logElab 6 $ "CONSTRAINTS ADDED: " ++ show (tm, ty, cs)
tit <- typeInType
when (not tit && addConstrs) $
do addConstraints fc cs
mapM_ (\c -> addIBC (IBCConstraint fc c)) (snd cs)
mapM_ (checkDeprecated fc) (allTTNames tm)
mapM_ (checkDeprecated fc) (allTTNames ty)
mapM_ (checkFragile fc) (allTTNames tm)
mapM_ (checkFragile fc) (allTTNames ty)
return (tm, ty)
checkDeprecated :: FC -> Name -> Idris ()
checkDeprecated fc n
= do r <- getDeprecated n
case r of
Nothing -> return ()
Just r -> do iWarn fc $ text "Use of deprecated name " <> annName n
<> case r of
"" -> Util.Pretty.empty
_ -> line <> text r
checkFragile :: FC -> Name -> Idris ()
checkFragile fc n = do
r <- getFragile n
case r of
Nothing -> return ()
Just r -> do
iWarn fc $ text "Use of a fragile construct "
<> annName n
<> case r of
"" -> Util.Pretty.empty
_ -> line <> text r
iderr :: Name -> Err -> Err
iderr _ e = e
checkDef :: ElabInfo -> FC -> (Name -> Err -> Err) -> Bool ->
[(Name, (Int, Maybe Name, Type, [Name]))] ->
Idris [(Name, (Int, Maybe Name, Type, [Name]))]
checkDef info fc mkerr definable ns
= checkAddDef False True info fc mkerr definable ns
checkAddDef :: Bool -> Bool -> ElabInfo -> FC -> (Name -> Err -> Err) -> Bool
-> [(Name, (Int, Maybe Name, Type, [Name]))]
-> Idris [(Name, (Int, Maybe Name, Type, [Name]))]
checkAddDef add toplvl info fc mkerr def [] = return []
checkAddDef add toplvl info fc mkerr definable ((n, (i, top, t, psns)) : ns)
= do ctxt <- getContext
logElab 5 $ "Rechecking deferred name " ++ show (n, t, definable)
(t', _) <- recheckC (constraintNS info) fc (mkerr n) [] t
when add $ do addDeferred [(n, (i, top, t, psns, toplvl, definable))]
addIBC (IBCDef n)
ns' <- checkAddDef add toplvl info fc mkerr definable ns
return ((n, (i, top, t', psns)) : ns')
inaccessibleImps :: Int -> Type -> [Bool] -> [(Int, Name)]
inaccessibleImps i (Bind n (Pi _ _ t _) sc) (inacc : ins)
| inacc = (i, n) : inaccessibleImps (i + 1) sc ins
| otherwise = inaccessibleImps (i + 1) sc ins
inaccessibleImps _ _ _ = []
inaccessibleArgs :: Int -> PTerm -> [(Int, Name)]
inaccessibleArgs i (PPi plicity n _ ty t)
| InaccessibleArg `elem` pargopts plicity
= (i,n) : inaccessibleArgs (i+1) t
| otherwise
= inaccessibleArgs (i+1) t
inaccessibleArgs _ _ = []
elabCaseBlock :: ElabInfo -> FnOpts -> PDecl -> Idris ()
elabCaseBlock info opts d@(PClauses f o n ps)
= do addIBC (IBCDef n)
logElab 5 $ "CASE BLOCK: " ++ show (n, d)
let opts' = filter propagatable opts
setFlags n opts'
rec_elabDecl info EAll info (PClauses f opts' n ps )
where
propagatable AssertTotal = True
propagatable Inlinable = True
propagatable _ = False
checkInferred :: FC -> PTerm -> PTerm -> Idris ()
checkInferred fc inf user =
do logElab 6 $ "Checked to\n" ++ showTmImpls inf ++ "\n\nFROM\n\n" ++
showTmImpls user
logElab 10 $ "Checking match"
i <- getIState
tclift $ case matchClause' True i user inf of
_ -> return ()
logElab 10 $ "Checked match"
inferredDiff :: FC -> PTerm -> PTerm -> Idris Bool
inferredDiff fc inf user =
do i <- getIState
logElab 6 $ "Checked to\n" ++ showTmImpls inf ++ "\n" ++
showTmImpls user
tclift $ case matchClause' True i user inf of
Right vs -> return False
Left (x, y) -> return True
checkDocs :: FC -> [(Name, Docstring a)] -> PTerm -> Idris ()
checkDocs fc args tm = cd (Map.fromList args) tm
where cd as (PPi _ n _ _ sc) = cd (Map.delete n as) sc
cd as _ | Map.null as = return ()
| otherwise = ierror . At fc . Msg $
"There is documentation for argument(s) "
++ (concat . intersperse ", " . map show . Map.keys) as
++ " but they were not found."
decorateid decorate (PTy doc argdocs s f o n nfc t) = PTy doc argdocs s f o (decorate n) nfc t
decorateid decorate (PClauses f o n cs)
= PClauses f o (decorate n) (map dc cs)
where dc (PClause fc n t as w ds) = PClause fc (decorate n) (dappname t) as w ds
dc (PWith fc n t as w pn ds)
= PWith fc (decorate n) (dappname t) as w pn
(map (decorateid decorate) ds)
dappname (PApp fc (PRef fc' hl n) as) = PApp fc (PRef fc' hl (decorate n)) as
dappname t = t
pbinds :: IState -> Term -> ElabD ()
pbinds i (Bind n (PVar rig t) sc)
= do attack; patbind n rig
env <- get_env
case unApply (normalise (tt_ctxt i) env t) of
(P _ c _, args) -> case lookupCtxt c (idris_interfaces i) of
[] -> return ()
_ ->
mapM_ setinjArg args
_ -> return ()
pbinds i sc
where setinjArg (P _ n _) = setinj n
setinjArg _ = return ()
pbinds i tm = return ()
pbty (Bind n (PVar _ t) sc) tm = Bind n (PVTy t) (pbty sc tm)
pbty _ tm = tm
getPBtys (Bind n (PVar _ t) sc) = (n, t) : getPBtys sc
getPBtys (Bind n (PVTy t) sc) = (n, t) : getPBtys sc
getPBtys _ = []
psolve (Bind n (PVar _ t) sc) = do solve; psolve sc
psolve tm = return ()
pvars ist tm = pv' [] tm
where
pv' env (Bind n (PVar _ t) sc)
= (n, delabWithEnv ist env t) : pv' ((n, t) : env) sc
pv' env _ = []
getFixedInType i env (PExp _ _ _ _ : is) (Bind n (Pi _ _ t _) sc)
= nub $ getFixedInType i env [] t ++
getFixedInType i (n : env) is (instantiate (P Bound n t) sc)
++ case unApply t of
(P _ n _, _) -> if n `elem` env then [n] else []
_ -> []
getFixedInType i env (_ : is) (Bind n (Pi _ _ t _) sc)
= getFixedInType i (n : env) is (instantiate (P Bound n t) sc)
getFixedInType i env is tm@(App _ f a)
| (P _ tn _, args) <- unApply tm
= case lookupCtxtExact tn (idris_datatypes i) of
Just t -> nub $ paramNames args env (param_pos t) ++
getFixedInType i env is f ++
getFixedInType i env is a
Nothing -> nub $ getFixedInType i env is f ++
getFixedInType i env is a
| otherwise = nub $ getFixedInType i env is f ++
getFixedInType i env is a
getFixedInType i _ _ _ = []
getFlexInType i env ps (Bind n (Pi _ _ t _) sc)
= nub $ (if (not (n `elem` ps)) then getFlexInType i env ps t else []) ++
getFlexInType i (n : env) ps (instantiate (P Bound n t) sc)
getFlexInType i env ps tm@(App _ f a)
| (P nt tn _, args) <- unApply tm, nt /= Bound
= case lookupCtxtExact tn (idris_datatypes i) of
Just t -> nub $ paramNames args env [x | x <- [0..length args],
not (x `elem` param_pos t)]
++ getFlexInType i env ps f ++
getFlexInType i env ps a
Nothing -> let ppos = case lookupCtxtExact tn (idris_fninfo i) of
Just fi -> fn_params fi
Nothing -> []
in nub $ paramNames args env [x | x <- [0..length args],
not (x `elem` ppos)]
++ getFlexInType i env ps f ++
getFlexInType i env ps a
| otherwise = nub $ getFlexInType i env ps f ++
getFlexInType i env ps a
getFlexInType i _ _ _ = []
getParamsInType :: IState -> [Name] -> [PArg] -> Type -> [Name]
getParamsInType i env ps t = let fix = getFixedInType i env ps t
flex = getFlexInType i env fix t in
[x | x <- fix, not (x `elem` flex)]
getTCinj i (Bind n (Pi _ _ t _) sc)
= getTCinj i t ++ getTCinj i (instantiate (P Bound n t) sc)
getTCinj i ap@(App _ f a)
| (P _ n _, args) <- unApply ap,
isTCName n = mapMaybe getInjName args
| otherwise = []
where
isTCName n = case lookupCtxtExact n (idris_interfaces i) of
Just _ -> True
_ -> False
getInjName t | (P _ x _, _) <- unApply t = Just x
| otherwise = Nothing
getTCinj _ _ = []
getTCParamsInType :: IState -> [Name] -> [PArg] -> Type -> [Name]
getTCParamsInType i env ps t = let params = getParamsInType i env ps t
tcs = nub $ getTCinj i t in
filter (flip elem tcs) params
paramNames args env [] = []
paramNames args env (p : ps)
| length args > p = case args!!p of
P _ n _ -> if n `elem` env
then n : paramNames args env ps
else paramNames args env ps
_ -> paramNames args env ps
| otherwise = paramNames args env ps
getLinearUsed :: Context -> Term -> [Name]
getLinearUsed ctxt tm = execState (getLin [] [] tm) []
where
getLin :: Env -> [(Name, Bool)] -> Term -> State [Name] ()
getLin env us (Bind n b sc)
= do getLinB env us b
let r = getRig b
let lin = case r of
Rig1 -> True
_ -> False
getLin ((n, getRig b, b) : env) ((n, lin) : us) sc
getLin env us (App _ f a) = do getLin env us f; getLin env us a
getLin env us (V i)
| i < length us = if snd (us!!i) then use (fst (us!!1)) else return ()
getLin env us (P _ n _)
| Just u <- lookup n us = if u then use n else return ()
getLin env us _ = return ()
getLinB env us (Let Rig0 t v) = return ()
getLinB env us (Let rig t v) = getLin env us v
getLinB env us (Guess t v) = getLin env us v
getLinB env us (NLet t v) = getLin env us v
getLinB env us b = return ()
use n = do ns <- get; put (n : ns)
getRig :: Binder Term -> RigCount
getRig (Pi rig _ _ _) = rig
getRig (PVar rig _) = rig
getRig (Lam rig _) = rig
getRig (Let rig _ _) = rig
getRig _ = RigW
getUniqueUsed :: Context -> Term -> [Name]
getUniqueUsed ctxt tm = execState (getUniq [] [] tm) []
where
getUniq :: Env -> [(Name, Bool)] -> Term -> State [Name] ()
getUniq env us (Bind n b sc)
= let uniq = case check ctxt env (forgetEnv (map fstEnv env) (binderTy b)) of
OK (_, UType UniqueType) -> True
OK (_, UType NullType) -> True
OK (_, UType AllTypes) -> True
_ -> False in
do getUniqB env us b
getUniq ((n, RigW, b):env) ((n, uniq):us) sc
getUniq env us (App _ f a) = do getUniq env us f; getUniq env us a
getUniq env us (V i)
| i < length us = if snd (us!!i) then use (fst (us!!i)) else return ()
getUniq env us (P _ n _)
| Just u <- lookup n us = if u then use n else return ()
getUniq env us _ = return ()
use n = do ns <- get; put (n : ns)
getUniqB env us (Let rig t v) = getUniq env us v
getUniqB env us (Guess t v) = getUniq env us v
getUniqB env us (NLet t v) = getUniq env us v
getUniqB env us b = return ()
getStaticNames :: IState -> Term -> [Name]
getStaticNames ist (Bind n (PVar _ _) sc)
= getStaticNames ist (instantiate (P Bound n Erased) sc)
getStaticNames ist tm
| (P _ fn _, args) <- unApply tm
= case lookupCtxtExact fn (idris_statics ist) of
Just stpos -> getStatics args stpos
_ -> []
where
getStatics (P _ n _ : as) (True : ss) = n : getStatics as ss
getStatics (_ : as) (_ : ss) = getStatics as ss
getStatics _ _ = []
getStaticNames _ _ = []
getStatics :: [Name] -> Term -> [Bool]
getStatics ns (Bind n (Pi _ _ _ _) t)
| n `elem` ns = True : getStatics ns t
| otherwise = False : getStatics ns t
getStatics _ _ = []
mkStatic :: [Name] -> PDecl -> PDecl
mkStatic ns (PTy doc argdocs syn fc o n nfc ty)
= PTy doc argdocs syn fc o n nfc (mkStaticTy ns ty)
mkStatic ns t = t
mkStaticTy :: [Name] -> PTerm -> PTerm
mkStaticTy ns (PPi p n fc ty sc)
| n `elem` ns = PPi (p { pstatic = Static }) n fc ty (mkStaticTy ns sc)
| otherwise = PPi p n fc ty (mkStaticTy ns sc)
mkStaticTy ns t = t
checkVisibility :: FC -> Name -> Accessibility -> Accessibility -> Name -> Idris ()
checkVisibility fc n minAcc acc ref
= do nvis <- getFromHideList ref
case nvis of
Nothing -> return ()
Just acc' -> if acc' > minAcc
then tclift $ tfail (At fc
(Msg $ show acc ++ " " ++ show n ++
" can't refer to " ++
show acc' ++ " " ++ show ref))
else return ()
findParams :: Name
-> Type
-> [Type]
-> [Int]
findParams tyn famty ts =
let allapps = map getDataApp ts
conParams = map paramPos allapps
in inAll conParams
where
inAll :: [[Int]] -> [Int]
inAll [] = []
inAll (x : xs) = filter (\p -> all (\ps -> p `elem` ps) xs) x
paramPos [] = []
paramPos (args : rest)
= dropNothing $ keepSame (zip [0..] args) rest
dropNothing [] = []
dropNothing ((x, Nothing) : ts) = dropNothing ts
dropNothing ((x, _) : ts) = x : dropNothing ts
keepSame :: [(Int, Maybe Name)] -> [[Maybe Name]] ->
[(Int, Maybe Name)]
keepSame as [] = as
keepSame as (args : rest) = keepSame (update as args) rest
where
update [] _ = []
update _ [] = []
update ((n, Just x) : as) (Just x' : args)
| x == x' = (n, Just x) : update as args
update ((n, _) : as) (_ : args) = (n, Nothing) : update as args
getDataApp :: Type -> [[Maybe Name]]
getDataApp f@(App _ _ _)
| (P _ d _, args) <- unApply f
= if (d == tyn) then [mParam args args] else []
getDataApp (Bind n (Pi _ _ t _) sc)
= getDataApp t ++ getDataApp (instantiate (P Bound n t) sc)
getDataApp _ = []
mParam args [] = []
mParam args (P Bound n _ : rest)
| paramIn False n args = Just n : mParam (filter (noN n) args) rest
where paramIn ok n [] = ok
paramIn ok n (P _ t _ : ts)
= paramIn (ok || n == t) n ts
paramIn ok n (t : ts)
| n `elem` freeNames t = False
| otherwise = paramIn ok n ts
noN n (P _ t _) = n /= t
noN n _ = False
mParam args (_ : rest) = Nothing : mParam args rest
setDetaggable :: Name -> Idris ()
setDetaggable n = do
ist <- getIState
let opt = idris_optimisation ist
case lookupCtxt n opt of
[oi] -> putIState ist { idris_optimisation = addDef n oi { detaggable = True } opt }
_ -> putIState ist { idris_optimisation = addDef n (Optimise [] True []) opt }
displayWarnings :: EState -> Idris ()
displayWarnings est
= mapM_ displayImpWarning (implicit_warnings est)
where
displayImpWarning :: (FC, Name) -> Idris ()
displayImpWarning (fc, n) = do
ist <- getIState
let msg = show (nsroot n)
++ " is bound as an implicit\n"
++ "\tDid you mean to refer to " ++ show n ++ "?"
iWarn fc (pprintErr ist (Msg msg))
propagateParams :: IState -> [Name] -> Type -> [Name] -> PTerm -> PTerm
propagateParams i ps t bound tm@(PApp _ (PRef fc hls n) args)
= PApp fc (PRef fc hls n) (addP t args)
where addP (Bind n _ sc) (t : ts)
| Placeholder <- getTm t,
n `elem` ps,
not (n `elem` bound)
= t { getTm = PPatvar NoFC n } : addP sc ts
addP (Bind n _ sc) (t : ts) = t : addP sc ts
addP _ ts = ts
propagateParams i ps t bound (PApp fc ap args)
= PApp fc (propagateParams i ps t bound ap) args
propagateParams i ps t bound (PRef fc hls n)
= case lookupCtxt n (idris_implicits i) of
[is] -> let ps' = filter (isImplicit is) ps in
PApp fc (PRef fc hls n) (map (\x -> pimp x (PRef fc [] x) True) ps')
_ -> PRef fc hls n
where isImplicit [] n = False
isImplicit (PImp _ _ _ x _ : is) n | x == n = True
isImplicit (_ : is) n = isImplicit is n
propagateParams i ps t bound x = x
orderPats :: Term -> Term
orderPats tm = op [] tm
where
op [] (App s f a) = App s f (op [] a)
op ps (Bind n (PVar r t) sc) = op ((n, PVar r t) : ps) sc
op ps (Bind n (Hole t) sc) = op ((n, Hole t) : ps) sc
op ps (Bind n (Pi rig i t k) sc) = op ((n, Pi rig i t k) : ps) sc
op ps sc = bindAll (sortP ps) sc
sortP ps = let (exps, imps) = partition isExp ps in
pick (reverse exps) imps
isExp (_, Pi rig Nothing _ _) = True
isExp (_, Pi rig (Just i) _ _) = toplevel_imp i && not (machine_gen i)
isExp _ = False
pick acc [] = acc
pick acc ((n, t) : ps) = pick (insert n t acc) ps
insert n t [] = [(n, t)]
insert n t rest@((n', t') : ps)
| any (\x -> x `elem` refsIn (binderTy t)) (n' : map fst ps)
= (n', t') : insert n t ps
| otherwise = (n, t) : rest
liftPats :: Term -> Term
liftPats tm = let (tm', ps) = runState (getPats tm) [] in
orderPats $ bindPats (reverse ps) tm'
where
bindPats [] tm = tm
bindPats ((n, t):ps) tm
| n `notElem` map fst ps = Bind n (PVar RigW t) (bindPats ps tm)
| otherwise = bindPats ps tm
getPats :: Term -> State [(Name, Type)] Term
getPats (Bind n (PVar _ t) sc) = do ps <- get
put ((n, t) : ps)
getPats sc
getPats (Bind n (Guess t v) sc) = do t' <- getPats t
v' <- getPats v
sc' <- getPats sc
return (Bind n (Guess t' v') sc')
getPats (Bind n (Let rig t v) sc) = do t' <- getPats t
v' <- getPats v
sc' <- getPats sc
return (Bind n (Let rig t' v') sc')
getPats (Bind n (Pi rig i t k) sc) = do t' <- getPats t
k' <- getPats k
sc' <- getPats sc
return (Bind n (Pi rig i t' k') sc')
getPats (Bind n (Lam r t) sc) = do t' <- getPats t
sc' <- getPats sc
return (Bind n (Lam r t') sc')
getPats (Bind n (Hole t) sc) = do t' <- getPats t
sc' <- getPats sc
return (Bind n (Hole t') sc')
getPats (App s f a) = do f' <- getPats f
a' <- getPats a
return (App s f' a')
getPats t = return t
isEmpty :: Context -> Ctxt TypeInfo -> Type -> Bool
isEmpty ctxt tyctxt ty
| (P _ tyname _, args) <- unApply ty,
Just tyinfo <- lookupCtxtExact tyname tyctxt
= let neededty = getRetTy ty
contys = mapMaybe getConType (con_names tyinfo) in
all (findClash neededty) contys
where
getConType n = do t <- lookupTyExact n ctxt
return (getRetTy (normalise ctxt [] t))
findClash l r
| (P _ n _, _) <- unApply l,
(P _ n' _, _) <- unApply r,
isConName n ctxt && isConName n' ctxt, n /= n'
= True
findClash (App _ f a) (App _ f' a') = findClash f f' || findClash a a'
findClash l r = False
isEmpty ctxt tyinfo ty = False
hasEmptyPat :: Context -> Ctxt TypeInfo -> Term -> Bool
hasEmptyPat ctxt tyctxt (Bind n (PVar _ ty) sc)
= isEmpty ctxt tyctxt ty || hasEmptyPat ctxt tyctxt sc
hasEmptyPat ctxt tyctxt _ = False
findLinear :: RigCount -> IState -> [Name] -> Term -> [(Name, RigCount)]
findLinear rig ist env tm
| (P _ f _, args) <- unApply tm,
f `notElem` env,
Just ty_in <- lookupTyExact f (tt_ctxt ist)
= let ty = whnfArgs (tt_ctxt ist) [] ty_in in
combineRig $ findLinArg ty args
where
findLinArg (Bind n (Pi c _ _ _) sc) (P _ a _ : as)
= (a, rigMult rig c) : findLinArg sc as
findLinArg (Bind n (Pi c _ _ _) sc) (a : as)
= findLinear (rigMult c rig) ist env a ++
findLinArg (whnf (tt_ctxt ist) [] (substV a sc)) as
findLinArg ty (a : as)
= findLinear rig ist env a ++ findLinArg ty as
findLinArg _ [] = []
combineRig [] = []
combineRig ((n, r) : rs)
= let (rs', rig) = findRestrictive n r [] rs in
(n, rig) : combineRig rs'
findRestrictive n r acc [] = (acc, r)
findRestrictive n r acc ((n', r') : rs)
| n == n' = findRestrictive n (max r r') acc rs
| otherwise = findRestrictive n r ((n', r') : acc) rs
findLinear rig ist env (App _ f a)
= nub $ findLinear rig ist env f ++ findLinear rig ist env a
findLinear rig ist env (Bind n b sc) = findLinear rig ist (n : env) sc
findLinear rig ist _ _ = []
setLinear :: [(Name, RigCount)] -> Term -> Term
setLinear ns (Bind n b@(PVar r t) sc)
| Just r <- lookup n ns = Bind n (PVar r t) (setLinear ns sc)
| otherwise = Bind n b (setLinear ns sc)
setLinear ns tm = tm
linearArg :: Type -> Bool
linearArg (Bind n (Pi Rig1 _ _ _) sc) = True
linearArg (Bind n (Pi _ _ _ _) sc) = linearArg sc
linearArg _ = False
pruneByType :: Bool ->
Env -> Term ->
Type ->
IState -> [PTerm] -> [PTerm]
pruneByType imp env t goalty c as
| Just a <- locallyBound as = [a]
where
locallyBound [] = Nothing
locallyBound (t:ts)
| Just n <- getName t,
n `elem` map fstEnv env = Just t
| otherwise = locallyBound ts
getName (PRef _ _ n) = Just n
getName (PApp _ (PRef _ _ (UN l)) [_, _, arg])
| l == txt "Delay" = getName (getTm arg)
getName (PApp _ f _) = getName f
getName (PHidden t) = getName t
getName _ = Nothing
pruneByType imp env (P _ n _) goalty ist as
| Nothing <- lookupTyExact n ctxt = as
| Just _ <- lookup n (idris_metavars ist) = as
| otherwise
= let asV = filter (headIs True n) as
as' = filter (headIs False n) as in
case as' of
[] -> asV
_ -> as'
where
ctxt = tt_ctxt ist
headIs var f (PRef _ _ f') = typeHead var f f'
headIs var f (PApp _ (PRef _ _ (UN l)) [_, _, arg])
| l == txt "Delay" = headIs var f (getTm arg)
headIs var f (PApp _ (PRef _ _ f') _) = typeHead var f f'
headIs var f (PApp _ f' _) = headIs var f f'
headIs var f (PPi _ _ _ _ sc) = headIs var f sc
headIs var f (PHidden t) = headIs var f t
headIs var f t = True
typeHead var f f'
=
case lookupTyExact f' ctxt of
Just ty -> case unApply (getRetTy ty) of
(P _ ctyn _, _) | isTConName ctyn ctxt && not (ctyn == f)
-> False
_ -> let ty' = normalise ctxt [] ty in
case unApply (getRetTy ty') of
(V _, _) ->
isPlausible ist var env n ty
_ -> matchingTypes imp (getRetTy ty') goalty
|| isCoercion (getRetTy ty') goalty
_ -> False
matchingTypes True = matchingHead
matchingTypes False = matching
matching (P _ ctyn _) (P _ n' _)
| isTConName n' ctxt && isTConName ctyn ctxt = ctyn == n'
| otherwise = True
matching (V _) _ = True
matching _ (V _) = True
matching _ (P _ n _) = not (isTConName n ctxt)
matching (P _ n _) _ = not (isTConName n ctxt)
matching (Bind n _ sc) _ = True
matching _ (Bind n _ sc) = True
matching apl@(App _ _ _) apr@(App _ _ _)
| (P _ fl _, argsl) <- unApply apl,
(P _ fr _, argsr) <- unApply apr
= fl == fr && and (zipWith matching argsl argsr)
|| (not (isConName fl ctxt && isConName fr ctxt))
matching (App _ f a) (App _ f' a') = True
matching (TType _) (TType _) = True
matching (UType _) (UType _) = True
matching l r = l == r
matchingHead apl@(App _ _ _) apr@(App _ _ _)
| (P _ fl _, argsl) <- unApply apl,
(P _ fr _, argsr) <- unApply apr,
isConName fl ctxt && isConName fr ctxt
= fl == fr
matchingHead _ _ = True
isCoercion rty gty | (P _ r _, _) <- unApply rty
= not (null (getCoercionsBetween r gty))
isCoercion _ _ = False
getCoercionsBetween :: Name -> Type -> [Name]
getCoercionsBetween r goal
= let cs = getCoercionsTo ist goal in
findCoercions r cs
where findCoercions t [] = []
findCoercions t (n : ns) =
let ps = case lookupTy n (tt_ctxt ist) of
[ty'] -> let as = map snd (getArgTys (normalise (tt_ctxt ist) [] ty')) in
[n | any useR as]
_ -> [] in
ps ++ findCoercions t ns
useR ty =
case unApply (getRetTy ty) of
(P _ t _, _) -> t == r
_ -> False
pruneByType _ _ t _ _ as = as
isPlausible :: IState -> Bool -> Env -> Name -> Type -> Bool
isPlausible ist var env n ty
= let (hvar, _) = collectConstraints [] [] ty in
case hvar of
Nothing -> True
Just rth -> var
where
collectConstraints :: [Name] -> [(Term, [Name])] -> Type ->
(Maybe Name, [(Term, [Name])])
collectConstraints env tcs (Bind n (Pi _ _ ty _) sc)
= let tcs' = case unApply ty of
(P _ c _, _) ->
case lookupCtxtExact c (idris_interfaces ist) of
Just tc -> ((ty, map fst (interface_implementations tc))
: tcs)
Nothing -> tcs
_ -> tcs
in
collectConstraints (n : env) tcs' sc
collectConstraints env tcs t
| (V i, _) <- unApply t = (Just (env !! i), tcs)
| otherwise = (Nothing, tcs)