@@ -409,6 +409,7 @@ checkTotality path fc n
409409 do t' <- if AssertTotal `elem` opts
410410 then return $ Total []
411411 else calcTotality fc n pats
412+ logCoverage 2 $ "Set to " ++ show t'
412413 setTotality n t'
413414 addIBC (IBCTotal n t')
414415 return t'
@@ -507,11 +508,12 @@ buildSCG' ist topfn pats args = nub $ concatMap scgPat pats where
507508 scgPat (lhs, rhs) = let lhs' = delazy lhs
508509 rhs' = delazy rhs
509510 (f, pargs) = unApply (dePat lhs') in
510− findCalls Toplevel (dePat rhs') (patvars lhs') pargs
511+ findCalls [] Toplevel (dePat rhs') (patvars lhs')
512+ (zip pargs [0..])
511513
512− findCalls Delayed ap@(P _ n _) pvs args
514+ findCalls cases Delayed ap@(P _ n _) pvs args
513515 | n == topfn = []
514− findCalls guarded ap@(App _ f a) pvs pargs
516+ findCalls cases guarded ap@(App _ f a) pvs pargs
515517 -- under a call to "assert_total", don't do any checking, just believe
516518 -- that it is total.
517519 | (P _ (UN at) _, [_, _]) <- unApply ap,
@@ -521,18 +523,29 @@ buildSCG' ist topfn pats args = nub $ concatMap scgPat pats where
521523 | (P _ (UN del) _, [_,_,arg]) <- unApply ap,
522524 Guarded <- guarded,
523525 del == txt "Delay"
524− = findCalls Delayed arg pvs pargs
526+ = findCalls cases Delayed arg pvs pargs
525527 | (P _ n _, args) <- unApply ap,
526528 Delayed <- guarded,
527529 n == topfn -- Under a delayed recursive call to the top level function,
528530 -- just check the arguments
529− = concatMap (\x -> findCalls Unguarded x pvs pargs) args
531+ = concatMap (\x -> findCalls cases Unguarded x pvs pargs) args
530532 | (P _ n _, args) <- unApply ap,
531533 Delayed <- guarded,
532534 isConName n (tt_ctxt ist)
533535 = -- Still under a 'Delay' and constructor guarded, so check
534536 -- just the arguments to the constructor, remaining Delayed
535− concatMap (\x -> findCalls guarded x pvs pargs) args
537+ concatMap (\x -> findCalls cases guarded x pvs pargs) args
538+ | (P _ n _, args) <- unApply ap,
539+ caseName n && n /= topfn,
540+ notPartial (lookupTotalExact n (tt_ctxt ist))
541+ -- case block - look inside the block, as long as it was covering
542+ -- (i.e. not currently set at Partial) to get a more accurate size
543+ -- change result from the top level patterns (also to help pass
544+ -- information through from guarded corecursion accurately)
545+ = concatMap (\x -> findCalls cases Unguarded x pvs pargs) args ++
546+ if n `notElem` cases
547+ then findCallsCase (n : cases) guarded n args pvs pargs
548+ else []
536549 | (P _ n _, args) <- unApply ap
537550 -- Ordinary call, not under a delay.
538551 -- If n is a constructor, set 'args' as Guarded
@@ -542,18 +555,65 @@ buildSCG' ist topfn pats args = nub $ concatMap scgPat pats where
542555 then Guarded
543556 else Unguarded in
544557 mkChange n args pargs ++
545− concatMap (\x -> findCalls nguarded x pvs pargs) args
546− findCalls guarded (App _ f a) pvs pargs
547− = findCalls Unguarded f pvs pargs ++ findCalls Unguarded a pvs pargs
548− findCalls guarded (Bind n (Let t v) e) pvs pargs
549− = findCalls Unguarded t pvs pargs ++
550− findCalls Unguarded v pvs pargs ++ findCalls guarded e (n : pvs) pargs
551− findCalls guarded (Bind n t e) pvs pargs
552− = findCalls Unguarded (binderTy t) pvs pargs ++
553− findCalls guarded e (n : pvs) pargs
554− findCalls guarded (P _ f _ ) pvs pargs
558+ concatMap (\x -> findCalls cases nguarded x pvs pargs) args
559+ where notPartial (Just (Partial NotCovering)) = False
560+ notPartial _ = True
561+ findCalls cases guarded (App _ f a) pvs pargs
562+ = findCalls cases Unguarded f pvs pargs ++ findCalls cases Unguarded a pvs pargs
563+ findCalls cases guarded (Bind n (Let t v) e) pvs pargs
564+ = findCalls cases Unguarded t pvs pargs ++
565+ findCalls cases Unguarded v pvs pargs ++ findCalls cases guarded e (n : pvs) pargs
566+ findCalls cases guarded (Bind n t e) pvs pargs
567+ = findCalls cases Unguarded (binderTy t) pvs pargs ++
568+ findCalls cases guarded e (n : pvs) pargs
569+ findCalls cases guarded (P _ f _ ) pvs pargs
555570 | not (f `elem` pvs) = [(f, [])]
556− findCalls _ _ _ _ = []
571+ findCalls _ _ _ _ _ = []
572+
573+ -- Assumption is that names are preserved in the case block (shadowing
574+ -- dealt with by the elaborator) so we can just assume the top level names
575+ -- are okay for building the size change
576+ findCallsCase cases guarded n args pvs pargs
577+ = case lookupDefExact n (tt_ctxt ist) of
578+ Just (CaseOp _ _ _ pats _ cd) ->
579+ concatMap (fccPat cases pvs pargs args guarded) (rights pats)
580+ Nothing -> []
581+
582+ fccPat cases pvs pargs args g (lhs, rhs)
583+ = let lhs' = delazy lhs
584+ rhs' = delazy rhs
585+ (f, pargs_case) = unApply (dePat lhs')
586+ -- pargs is a pair of a term, and the argument position that
587+ -- term appears in. If any of the arguments to the case block
588+ -- are also on the lhs, we also want those patterns to appear
589+ -- in the parg list so that we'll spot patterns which are
590+ -- smaller than then
591+ newpargs = newPArg args pargs
592+ -- Now need to update the rhs of the case with the names in the
593+ -- outer definition: In rhs', wherever we see what's in pargs_case,
594+ -- replace it with the corresponding thing in pargs
595+ csubs = zip pargs_case args
596+ newrhs = doCaseSubs csubs (dePat rhs')
597+ pargs' = pargs ++ addPArg newpargs pargs_case in
598+ findCalls cases g newrhs pvs pargs'
599+ where
600+ doCaseSubs [] tm = tm
601+ doCaseSubs ((x, x') : cs) tm
602+ = doCaseSubs (subIn x x' cs) (substTerm x x' tm)
603+
604+ subIn x x' [] = []
605+ subIn x x' ((l, r) : cs)
606+ = (substTerm x x' l, substTerm x x' r) : subIn x x' cs
607+
608+ addPArg (Just (t, i) : ts) (t' : ts') = (t', i) : addPArg ts ts'
609+ addPArg (Nothing : ts) (t' : ts') = addPArg ts ts'
610+ addPArg _ _ = []
611+
612+ newPArg :: [Term] -> [(Term, Int)] -> [Maybe (Term, Int)]
613+ newPArg (t : ts) pargs = case lookup t pargs of
614+ Just i -> Just (t, i) : newPArg ts pargs
615+ Nothing -> Nothing : newPArg ts pargs
616+ newPArg [] pargs = []
557617
558618 expandToArity n args
559619 = case lookupTy n (tt_ctxt ist) of
@@ -566,17 +626,17 @@ buildSCG' ist topfn pats args = nub $ concatMap scgPat pats where
566626 mkChange n args pargs = [(n, expandToArity n (sizes args))]
567627 where
568628 sizes [] = []
569− sizes (a : as) = checkSize a pargs 0 : sizes as
629+ sizes (a : as) = checkSize a pargs : sizes as
570630
571631 -- find which argument in pargs <a> is smaller than, if any
572− checkSize a (p : ps) i
632+ checkSize a ((p, i) : ps)
573633 | a == p = Just (i, Same)
574634 | (P _ (UN as) _, [_,_,arg,_]) <- unApply a,
575635 as == txt "assert_smaller" && arg == p
576636 = Just (i, Smaller)
577637 | smaller Nothing a (p, Nothing) = Just (i, Smaller)
578− | otherwise = checkSize a ps (i + 1)
579− checkSize a [] i = Nothing
638+ | otherwise = checkSize a ps
639+ checkSize a [] = Nothing
580640
581641 -- the smaller thing we find must be defined in the same group of mutally
582642 -- defined types as <a>, and not be coinductive - so carry the type of
@@ -626,9 +686,10 @@ checkSizeChange n = do
626686 -- thread, then the function terminates
627687 -- also need to checks functions called are all total
628688 -- (Unchecked is okay as we'll spot problems here)
629− let tot = map (checkMP ist (getArity ist n)) ms
689+ let tot = map (checkMP ist n (getArity ist n)) ms
630690 logCoverage 4 $ "Generated " ++ show (length tot) ++ " paths"
631− logCoverage 6 $ "Paths for " ++ show n ++ " yield " ++ (show tot)
691+ logCoverage 5 $ "Paths for " ++ show n ++ " yield " ++
692+ (showSep "\n" (map show (zip ms tot)))
632693 return (noPartial tot)
633694 [] -> do logCoverage 5 $ "No paths for " ++ show n
634695 return Unchecked
@@ -651,20 +712,13 @@ mkMultiPaths ist path cg
651712 _ -> [ reverse ((nextf, args) : path) ]
652713 | otherwise = [ reverse ((nextf, args) : path) ]
653714
654−-- do (nextf, args) <- cg
655−-- if ((nextf, args) `elem` path)
656−-- then return (reverse ((nextf, args) : path))
657−-- else case lookupCtxt nextf (idris_callgraph ist) of
658−-- [ncg] -> mkMultiPaths ist ((nextf, args) : path) (scg ncg)
659−-- _ -> return (reverse ((nextf, args) : path))
660−
661715-- If any route along the multipath leads to infinite descent, we're fine.
662716-- Try a route beginning with every argument.
663717-- If we reach a point we've been to before, but with a smaller value,
664718-- that means there is an infinitely descending path from that argument.
665719
666−checkMP :: IState -> Int -> MultiPath -> Totality
667−checkMP ist i mp = if i > 0
720+checkMP :: IState -> Name -> Int -> MultiPath -> Totality
721+checkMP ist topfn i mp = if i > 0
668722 then let paths = (map (tryPath 0 [] mp) [0..i-1]) in
669723-- trace ("Paths " ++ show paths) $
670724 collapse paths
@@ -674,6 +728,8 @@ checkMP ist i mp = if i > 0
674728 = let res = tryPath d path mp arg in
675729 trace (show mp ++ "\n" ++ show arg ++ " " ++ show res) res
676730
731+ mkBig (e, d) = (e, 10000)
732+
677733 tryPath :: Int -> [((SCGEntry, Int), Int)] -> MultiPath -> Int -> Totality
678734 tryPath desc path [] _ = Total []
679735-- tryPath desc path ((UN "believe_me", _) : _) arg
@@ -692,7 +748,7 @@ checkMP ist i mp = if i > 0
692748 | e `elem` es && allNothing args = Partial (Mutual [f])
693749 tryPath desc path (e@(f, nextargs) : es) arg
694750 | Just d <- lookup (e, arg) path
695− = if desc > 0
751+ = if desc - d > 0 -- Now lower than when we were last here
696752 then -- trace ("Descent " ++ show (desc - d) ++ " "
697753 -- ++ show (path, e)) $
698754 Total []
@@ -701,21 +757,15 @@ checkMP ist i mp = if i > 0
701757 && not (f `elem` map fst es)
702758 = Partial (Mutual (map (fst . fst . fst) path ++ [f]))
703759 | [Unchecked] <- lookupTotal f (tt_ctxt ist) =
704− let argspos = case collapseNothing (zip nextargs [0..]) of
705− [] -> [(Nothing, 0)]
706− x -> x
707−-- trace (show (argspos, nextargs, path)) $
760+ let argspos = zip nextargs [0..]
708761 pathres =
709762 do (a, pos) <- argspos
710763 case a of
711− Nothing -> -- don't know, but if the
712− -- rest definitely terminates without
713− -- any cycles with route so far,
714− -- then we might yet be total
715− case collapse (map (tryPath 0 (((e, arg), 0):path) es)
716− [0..length nextargs - 1]) of
717− Total _ -> return Unchecked
718− x -> return x
764+ Nothing -> -- gone up, but if the
765+ -- rest definitely terminates without any
766+ -- cycles (including the path so far, which
767+ -- we take as inaccessible) the path is fine
768+ return $ tryPath 0 (map mkBig (((e, arg), desc) : path)) es pos
719769 Just (nextarg, sc) ->
720770 if nextarg == arg then
721771 case sc of
@@ -729,7 +779,7 @@ checkMP ist i mp = if i > 0
729779 return (Partial Itself)
730780 else return Unchecked in
731781-- trace (show (desc, argspos, path, es, pathres)) $
732− collapse' Unchecked pathres
782+ collapse pathres
733783
734784 | [Total a] <- lookupTotal f (tt_ctxt ist) = Total a
735785 | [Partial _] <- lookupTotal f (tt_ctxt ist) = Partial (Other [f])
@@ -739,10 +789,10 @@ allNothing :: [Maybe a] -> Bool
739789allNothing xs = null (collapseNothing (zip xs [0..]))
740790
741791collapseNothing :: [(Maybe a, b)] -> [(Maybe a, b)]
742−collapseNothing ((Nothing, _) : xs)
743− = filter (\ (x, _) -> case x of
744− Nothing -> False
745− _ -> True) xs
792+collapseNothing ((Nothing, t) : xs)
793+ = (Nothing, t) : filter (\ (x, _) -> case x of
794+ Nothing -> False
795+ _ -> True) xs
746796collapseNothing (x : xs) = x : collapseNothing xs
747797collapseNothing [] = []
748798