@@ -262,17 +262,50 @@ checkPositive n (cn, ty)
262262data LexOrder = LexXX | LexEQ | LexLT
263263 deriving (Show, Eq, Ord)
264264
265+calcProd :: IState -> FC -> Name -> [([Name], Term, Term)] -> Idris Totality
266+calcProd i fc n pats
267+ | and (map prodRec pats) = return (Total [])
268+ | otherwise = return (Partial NotProductive)
269+ where
270+ -- every application of n must be in an argument of a coinductive constructor
271+
272+ prodRec :: ([Name], Term, Term) -> Bool
273+ prodRec (_, _, tm) = prod False tm
274+
275+ prod ok ap@(App _ _)
276+ | (P _ (UN "lazy") _, [_, arg]) <- unApply ap = prod ok arg
277+ | (P _ f ty, args) <- unApply ap
278+ = let co = cotype ty in
279+ if f == n then and (ok : map (prod co) args)
280+ else and (map (prod co) args)
281+ prod ok (App f a) = prod False f && prod False a
282+ prod ok (Bind _ (Let t v) sc) = prod False v && prod False v
283+ prod ok (Bind _ b sc) = prod False sc
284+ prod ok t = True
285+
286+ cotype ty
287+ | (P _ t _, _) <- unApply (getRetTy ty)
288+ = case lookupCtxt Nothing t (idris_datatypes i) of
289+ [TI _ True] -> True
290+ _ -> False
291+ | otherwise = False
292+
265293calcTotality :: [Name] -> FC -> Name -> [([Name], Term, Term)] -> Idris Totality
266294calcTotality path fc n pats
267− = do orders <- mapM ctot pats
268− let order = sortBy cmpOrd $ concat orders
269− let (errs, valid) = partitionEithers order
270− let lex = stripNoLT (stripXX valid)
271− case errs of
272− [] -> do logLvl 3 $ show n ++ ":\n" ++ showSep "\n" (map show lex)
273− logLvl 10 $ show pats
274− checkDecreasing lex
275− (e : _) -> return e -- FIXME: should probably combine them
295+ = do i <- get
296+ let opts = case lookupCtxt Nothing n (idris_flags i) of
297+ [fs] -> fs
298+ _ -> []
299+ if (Coinductive `elem` opts) then calcProd i fc n pats
300+ else do orders <- mapM ctot pats
301+ let order = sortBy cmpOrd $ concat orders
302+ let (errs, valid) = partitionEithers order
303+ let lex = stripNoLT (stripXX valid)
304+ case errs of
305+ [] -> do logLvl 3 $ show n ++ ":\n" ++ showSep "\n" (map show lex)
306+ logLvl 10 $ show pats
307+ checkDecreasing lex
308+ (e : _) -> return e -- FIXME: should probably combine them
276309 where
277310 cmpOrd (Left _) (Left _) = EQ
278311 cmpOrd (Left _) (Right _) = LT