@@ -409,6 +409,7 @@ checkTotality path fc n
409 do t' <- if AssertTotal `elem` opts
409 do t' <- if AssertTotal `elem` opts
410 then return $ Total []
410 then return $ Total []
411 else calcTotality fc n pats
411 else calcTotality fc n pats
412+ logCoverage 2 $ "Set to " ++ show t'
412 setTotality n t'
413 setTotality n t'
413 addIBC (IBCTotal n t')
414 addIBC (IBCTotal n t')
414 return t'
415 return t'
@@ -507,11 +508,12 @@ buildSCG' ist topfn pats args = nub $ concatMap scgPat pats where
507 scgPat (lhs, rhs) = let lhs' = delazy lhs
508 scgPat (lhs, rhs) = let lhs' = delazy lhs
508 rhs' = delazy rhs
509 rhs' = delazy rhs
509 (f, pargs) = unApply (dePat lhs') in
510 (f, pargs) = unApply (dePat lhs') in
510− findCalls Toplevel (dePat rhs') (patvars lhs') pargs
511+ findCalls [] Toplevel (dePat rhs') (patvars lhs')
512− findCalls Delayed ap@(P _ n _) pvs args
514+ findCalls cases Delayed ap@(P _ n _) pvs args
513 | n == topfn = []
515 | n == topfn = []
514− findCalls guarded ap@(App _ f a) pvs pargs
516+ findCalls cases guarded ap@(App _ f a) pvs pargs
515 -- under a call to "assert_total", don't do any checking, just believe
517 -- under a call to "assert_total", don't do any checking, just believe
516 -- that it is total.
518 -- that it is total.
517 | (P _ (UN at) _, [_, _]) <- unApply ap,
519 | (P _ (UN at) _, [_, _]) <- unApply ap,
@@ -521,18 +523,29 @@ buildSCG' ist topfn pats args = nub $ concatMap scgPat pats where
521 | (P _ (UN del) _, [_,_,arg]) <- unApply ap,
523 | (P _ (UN del) _, [_,_,arg]) <- unApply ap,
522 Guarded <- guarded,
524 Guarded <- guarded,
523 del == txt "Delay"
525 del == txt "Delay"
524− = findCalls Delayed arg pvs pargs
526+ = findCalls cases Delayed arg pvs pargs
525 | (P _ n _, args) <- unApply ap,
527 | (P _ n _, args) <- unApply ap,
526 Delayed <- guarded,
528 Delayed <- guarded,
527 n == topfn -- Under a delayed recursive call to the top level function,
529 n == topfn -- Under a delayed recursive call to the top level function,
528 -- just check the arguments
530 -- just check the arguments
529− = concatMap (\x -> findCalls Unguarded x pvs pargs) args
531+ = concatMap (\x -> findCalls cases Unguarded x pvs pargs) args
530 | (P _ n _, args) <- unApply ap,
532 | (P _ n _, args) <- unApply ap,
531 Delayed <- guarded,
533 Delayed <- guarded,
532 isConName n (tt_ctxt ist)
534 isConName n (tt_ctxt ist)
533 = -- Still under a 'Delay' and constructor guarded, so check
535 = -- Still under a 'Delay' and constructor guarded, so check
534 -- just the arguments to the constructor, remaining Delayed
536 -- 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
536 | (P _ n _, args) <- unApply ap
549 | (P _ n _, args) <- unApply ap
537 -- Ordinary call, not under a delay.
550 -- Ordinary call, not under a delay.
538 -- If n is a constructor, set 'args' as Guarded
551 -- If n is a constructor, set 'args' as Guarded
@@ -542,18 +555,65 @@ buildSCG' ist topfn pats args = nub $ concatMap scgPat pats where
542 then Guarded
555 then Guarded
543 else Unguarded in
556 else Unguarded in
544 mkChange n args pargs ++
557 mkChange n args pargs ++
545− concatMap (\x -> findCalls nguarded x pvs pargs) args
558+ concatMap (\x -> findCalls cases nguarded x pvs pargs) args
559+ where notPartial (Just (Partial NotCovering)) = False
546− findCalls guarded (App _ f a) pvs pargs
561+ findCalls cases guarded (App _ f a) pvs pargs
547− = findCalls Unguarded f pvs pargs ++ findCalls Unguarded a pvs pargs
562+ = findCalls cases Unguarded f pvs pargs ++ findCalls cases Unguarded a pvs pargs
548− findCalls guarded (Bind n (Let t v) e) pvs pargs
563+ findCalls cases guarded (Bind n (Let t v) e) pvs pargs
549− = findCalls Unguarded t pvs pargs ++
564+ = findCalls cases Unguarded t pvs pargs ++
550− findCalls Unguarded v pvs pargs ++ findCalls guarded e (n : pvs) pargs
565+ findCalls cases Unguarded v pvs pargs ++ findCalls cases guarded e (n : pvs) pargs
551− findCalls guarded (Bind n t e) pvs pargs
566+ findCalls cases guarded (Bind n t e) pvs pargs
552− = findCalls Unguarded (binderTy t) pvs pargs ++
567+ = findCalls cases Unguarded (binderTy t) pvs pargs ++
553− findCalls guarded e (n : pvs) pargs
568+ findCalls cases guarded e (n : pvs) pargs
554− findCalls guarded (P _ f _ ) pvs pargs
569+ findCalls cases guarded (P _ f _ ) pvs pargs
555 | not (f `elem` pvs) = [(f, [])]
570 | not (f `elem` pvs) = [(f, [])]
556− findCalls _ _ _ _ = []
571+ findCalls _ _ _ _ _ = []
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)
582+ fccPat cases pvs pargs args g (lhs, rhs)
583+ = let lhs' = delazy lhs
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'
600+ doCaseSubs [] tm = tm
601+ doCaseSubs ((x, x') : cs) tm
602+ = doCaseSubs (subIn x x' cs) (substTerm x x' tm)
605+ subIn x x' ((l, r) : cs)
606+ = (substTerm x x' l, substTerm x x' r) : subIn x x' cs
608+ addPArg (Just (t, i) : ts) (t' : ts') = (t', i) : addPArg ts ts'
609+ addPArg (Nothing : ts) (t' : ts') = addPArg ts ts'
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 = []
558 expandToArity n args
618 expandToArity n args
559 = case lookupTy n (tt_ctxt ist) of
619 = case lookupTy n (tt_ctxt ist) of
@@ -566,17 +626,17 @@ buildSCG' ist topfn pats args = nub $ concatMap scgPat pats where
566 mkChange n args pargs = [(n, expandToArity n (sizes args))]
626 mkChange n args pargs = [(n, expandToArity n (sizes args))]
568 sizes [] = []
628 sizes [] = []
569− sizes (a : as) = checkSize a pargs 0 : sizes as
629+ sizes (a : as) = checkSize a pargs : sizes as
571 -- find which argument in pargs <a> is smaller than, if any
631 -- find which argument in pargs <a> is smaller than, if any
572− checkSize a (p : ps) i
632+ checkSize a ((p, i) : ps)
573 | a == p = Just (i, Same)
633 | a == p = Just (i, Same)
574 | (P _ (UN as) _, [_,_,arg,_]) <- unApply a,
634 | (P _ (UN as) _, [_,_,arg,_]) <- unApply a,
575 as == txt "assert_smaller" && arg == p
635 as == txt "assert_smaller" && arg == p
576 = Just (i, Smaller)
636 = Just (i, Smaller)
577 | smaller Nothing a (p, Nothing) = Just (i, Smaller)
637 | smaller Nothing a (p, Nothing) = Just (i, Smaller)
578− | otherwise = checkSize a ps (i + 1)
638+ | otherwise = checkSize a ps
579− checkSize a [] i = Nothing
639+ checkSize a [] = Nothing
581 -- the smaller thing we find must be defined in the same group of mutally
641 -- the smaller thing we find must be defined in the same group of mutally
582 -- defined types as <a>, and not be coinductive - so carry the type of
642 -- defined types as <a>, and not be coinductive - so carry the type of
@@ -626,9 +686,10 @@ checkSizeChange n = do
626 -- thread, then the function terminates
686 -- thread, then the function terminates
627 -- also need to checks functions called are all total
687 -- also need to checks functions called are all total
628 -- (Unchecked is okay as we'll spot problems here)
688 -- (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
630 logCoverage 4 $ "Generated " ++ show (length tot) ++ " paths"
690 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)))
632 return (noPartial tot)
693 return (noPartial tot)
633 [] -> do logCoverage 5 $ "No paths for " ++ show n
694 [] -> do logCoverage 5 $ "No paths for " ++ show n
634 return Unchecked
695 return Unchecked
@@ -651,20 +712,13 @@ mkMultiPaths ist path cg
651 _ -> [ reverse ((nextf, args) : path) ]
712 _ -> [ reverse ((nextf, args) : path) ]
652 | otherwise = [ reverse ((nextf, args) : path) ]
713 | otherwise = [ reverse ((nextf, args) : path) ]
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))
661-- If any route along the multipath leads to infinite descent, we're fine.
715-- If any route along the multipath leads to infinite descent, we're fine.
662-- Try a route beginning with every argument.
716-- Try a route beginning with every argument.
663-- If we reach a point we've been to before, but with a smaller value,
717-- If we reach a point we've been to before, but with a smaller value,
664-- that means there is an infinitely descending path from that argument.
718-- that means there is an infinitely descending path from that argument.
666−checkMP :: IState -> Int -> MultiPath -> Totality
720+checkMP :: IState -> Name -> Int -> MultiPath -> Totality
667−checkMP ist i mp = if i > 0
721+checkMP ist topfn i mp = if i > 0
668 then let paths = (map (tryPath 0 [] mp) [0..i-1]) in
722 then let paths = (map (tryPath 0 [] mp) [0..i-1]) in
669-- trace ("Paths " ++ show paths) $
723-- trace ("Paths " ++ show paths) $
670 collapse paths
724 collapse paths
@@ -674,6 +728,8 @@ checkMP ist i mp = if i > 0
674 = let res = tryPath d path mp arg in
728 = let res = tryPath d path mp arg in
675 trace (show mp ++ "\n" ++ show arg ++ " " ++ show res) res
729 trace (show mp ++ "\n" ++ show arg ++ " " ++ show res) res
731+ mkBig (e, d) = (e, 10000)
677 tryPath :: Int -> [((SCGEntry, Int), Int)] -> MultiPath -> Int -> Totality
733 tryPath :: Int -> [((SCGEntry, Int), Int)] -> MultiPath -> Int -> Totality
678 tryPath desc path [] _ = Total []
734 tryPath desc path [] _ = Total []
679-- tryPath desc path ((UN "believe_me", _) : _) arg
735-- tryPath desc path ((UN "believe_me", _) : _) arg
@@ -692,7 +748,7 @@ checkMP ist i mp = if i > 0
692 | e `elem` es && allNothing args = Partial (Mutual [f])
748 | e `elem` es && allNothing args = Partial (Mutual [f])
693 tryPath desc path (e@(f, nextargs) : es) arg
749 tryPath desc path (e@(f, nextargs) : es) arg
694 | Just d <- lookup (e, arg) path
750 | Just d <- lookup (e, arg) path
695− = if desc > 0
751+ = if desc - d > 0 -- Now lower than when we were last here
696 then -- trace ("Descent " ++ show (desc - d) ++ " "
752 then -- trace ("Descent " ++ show (desc - d) ++ " "
697 -- ++ show (path, e)) $
753 -- ++ show (path, e)) $
@@ -701,21 +757,15 @@ checkMP ist i mp = if i > 0
701 && not (f `elem` map fst es)
757 && not (f `elem` map fst es)
702 = Partial (Mutual (map (fst . fst . fst) path ++ [f]))
758 = Partial (Mutual (map (fst . fst . fst) path ++ [f]))
703 | [Unchecked] <- lookupTotal f (tt_ctxt ist) =
759 | [Unchecked] <- lookupTotal f (tt_ctxt ist) =
704− let argspos = case collapseNothing (zip nextargs [0..]) of
760+ let argspos = zip nextargs [0..]
705− [] -> [(Nothing, 0)]
707−-- trace (show (argspos, nextargs, path)) $
708 pathres =
761 pathres =
709 do (a, pos) <- argspos
762 do (a, pos) <- argspos
710 case a of
763 case a of
711− Nothing -> -- don't know, but if the
764+ Nothing -> -- gone up, but if the
712− -- rest definitely terminates without
765+ -- rest definitely terminates without any
713− -- any cycles with route so far,
766+ -- cycles (including the path so far, which
714− -- then we might yet be total
767+ -- we take as inaccessible) the path is fine
715− case collapse (map (tryPath 0 (((e, arg), 0):path) es)
768+ return $ tryPath 0 (map mkBig (((e, arg), desc) : path)) es pos
716− [0..length nextargs - 1]) of
717− Total _ -> return Unchecked
719 Just (nextarg, sc) ->
769 Just (nextarg, sc) ->
720 if nextarg == arg then
770 if nextarg == arg then
721 case sc of
771 case sc of
@@ -729,7 +779,7 @@ checkMP ist i mp = if i > 0
729 return (Partial Itself)
779 return (Partial Itself)
730 else return Unchecked in
780 else return Unchecked in
731-- trace (show (desc, argspos, path, es, pathres)) $
781-- trace (show (desc, argspos, path, es, pathres)) $
732− collapse' Unchecked pathres
782+ collapse pathres
734 | [Total a] <- lookupTotal f (tt_ctxt ist) = Total a
784 | [Total a] <- lookupTotal f (tt_ctxt ist) = Total a
735 | [Partial _] <- lookupTotal f (tt_ctxt ist) = Partial (Other [f])
785 | [Partial _] <- lookupTotal f (tt_ctxt ist) = Partial (Other [f])
@@ -739,10 +789,10 @@ allNothing :: [Maybe a] -> Bool
739allNothing xs = null (collapseNothing (zip xs [0..]))
789allNothing xs = null (collapseNothing (zip xs [0..]))
741collapseNothing :: [(Maybe a, b)] -> [(Maybe a, b)]
791collapseNothing :: [(Maybe a, b)] -> [(Maybe a, b)]
742−collapseNothing ((Nothing, _) : xs)
792+collapseNothing ((Nothing, t) : xs)
743− = filter (\ (x, _) -> case x of
793+ = (Nothing, t) : filter (\ (x, _) -> case x of
744− Nothing -> False
794+ Nothing -> False
745− _ -> True) xs
795+ _ -> True) xs
746collapseNothing (x : xs) = x : collapseNothing xs
796collapseNothing (x : xs) = x : collapseNothing xs
747collapseNothing [] = []
797collapseNothing [] = []