{-# LANGUAGE PatternGuards #-} module Idris.Coverage where import Core.TT import Core.Evaluate import Idris.AbsSyntax import Idris.Delaborate import Data.List import Debug.Trace -- Given a list of LHSs, generate a extra clauses which cover the remaining -- cases. The ones which haven't been provided are marked 'absurd' so that the -- checker will make sure they can't happen. -- This will only work after the given clauses have been typechecked and the -- names are fully explicit! genClauses :: FC -> Name -> [Term] -> [PClause] -> Idris [PClause] genClauses fc n xs given = do i <- getIState let lhss = map (getLHS i) xs let argss = transpose lhss let all_args = map (genAll i) argss logLvl 7 $ "COVERAGE of " ++ show n logLvl 10 $ show argss ++ "\n" ++ show all_args logLvl 10 $ "Original: \n" ++ showSep "\n" (map (\t -> showImp True (delab' i t True)) xs) let parg = case lookupCtxt Nothing n (idris_implicits i) of (p : _) -> p _ -> repeat (pexp Placeholder) let new = mnub i $ filter (noMatch i) $ mkClauses parg all_args logLvl 7 $ "New clauses: \n" ++ showSep "\n" (map (showImp True) new) return (map (\t -> PClause n t [] PImpossible []) new) where getLHS i term | (f, args) <- unApply term = map (\t -> delab' i t True) args | otherwise = [] lhsApp (PClause _ l _ _ _) = l lhsApp (PWith _ l _ _ _) = l mnub i [] = [] mnub i (x : xs) = if (any (\t -> case matchClause x t of Right _ -> True Left _ -> False) xs) then mnub i xs else x : mnub i xs noMatch i tm = all (\x -> case matchClause (delab' i x True) tm of Right _ -> False Left miss -> True) xs mkClauses :: [PArg] -> [[PTerm]] -> [PTerm] mkClauses parg args = do args' <- mkArg args let tm = PApp fc (PRef fc n) (zipWith upd args' parg) return tm where mkArg :: [[PTerm]] -> [[PTerm]] mkArg [] = return [] mkArg (a : as) = do a' <- a as' <- mkArg as return (a':as') genAll :: IState -> [PTerm] -> [PTerm] genAll i args = concatMap otherPats (nub args) where otherPats :: PTerm -> [PTerm] otherPats o@(PRef fc n) = ops fc n [] o otherPats o@(PApp _ (PRef fc n) xs) = ops fc n xs o otherPats arg = return arg ops fc n xs o | (TyDecl c@(DCon _ arity) ty : _) <- lookupDef Nothing n (tt_ctxt i) = do xs' <- mapM otherPats (map getTm xs) let p = PApp fc (PRef fc n) (zipWith upd xs' xs) let tyn = getTy n (tt_ctxt i) case lookupCtxt Nothing tyn (idris_datatypes i) of (TI ns : _) -> p : map (mkPat fc) (ns \\ [n]) _ -> [p] ops fc n arg o = return o getTy n ctxt = case lookupTy Nothing n ctxt of (t : _) -> case unApply (getRetTy t) of (P _ tyn _, _) -> tyn x -> error $ "Can't happen getTy 1 " ++ show (n, x) _ -> error "Can't happen getTy 2" mkPat fc x = case lookupCtxt Nothing x (idris_implicits i) of (pargs : _) -> PApp fc (PRef fc x) (map (upd Placeholder) pargs) _ -> error "Can't happen - genAll" upd p' p = p { getTm = p' }