@@ -10,6 +10,7 @@ import Idris.Core.TT
10import Control.Monad.State
10import Control.Monad.State
11import Data.Maybe
11import Data.Maybe
12import Data.List hiding (partition)
12import Data.List hiding (partition)
13+import qualified Data.List(partition)
13import Debug.Trace
14import Debug.Trace
15data CaseDef = CaseDef [Name] !SC [Term]
16data CaseDef = CaseDef [Name] !SC [Term]
@@ -417,8 +418,15 @@ order :: [(Name, Bool)] -> [Clause] -> ([Name], [Clause])
417order [] cs = ([], cs)
418order [] cs = ([], cs)
418order ns' [] = (map fst ns', [])
419order ns' [] = (map fst ns', [])
419order ns' cs = let patnames = transpose (map (zip ns') (map fst cs))
420order ns' cs = let patnames = transpose (map (zip ns') (map fst cs))
421+ -- only sort the arguments where there is no clash in
422+ -- constructor tags between families, and no constructor/constant
423+ -- clash, because otherwise we can't reliable make the
424+ -- case distinction on evaluation
425+ (patnames_ord, patnames_rest)
426+ = Data.List.partition (noClash . map snd) patnames
420 -- note: sortBy . reverse is not nonsense because sortBy is stable
427 -- note: sortBy . reverse is not nonsense because sortBy is stable
421− pats' = transpose (sortBy moreDistinct (reverse patnames)) in
428+ pats' = transpose (sortBy moreDistinct (reverse patnames_ord)
429+ ++ patnames_rest) in
422 (getNOrder pats', zipWith rebuild pats' cs)
430 (getNOrder pats', zipWith rebuild pats' cs)
424 getNOrder [] = error $ "Failed order on " ++ show (map fst ns', cs)
432 getNOrder [] = error $ "Failed order on " ++ show (map fst ns', cs)
@@ -426,6 +434,16 @@ order ns' cs = let patnames = transpose (map (zip ns') (map fst cs))
427 rebuild patnames clause = (map snd patnames, snd clause)
435 rebuild patnames clause = (map snd patnames, snd clause)
438+ noClash (p : ps) = not (any (clashPat p) ps) && noClash ps
440+ clashPat (PCon _ _ _) (PConst _) = True
441+ clashPat (PConst _) (PCon _ _ _) = True
442+ clashPat (PCon _ _ _) (PSuc _) = True
443+ clashPat (PSuc _) (PCon _ _ _) = True
444+ clashPat (PCon n i _) (PCon n' i' _) | i == i' = n /= n'
445+ clashPat _ _ = False
429 -- this compares (+isInaccessible, -numberOfCases)
447 -- this compares (+isInaccessible, -numberOfCases)
430 moreDistinct xs ys = compare (snd . fst . head $ xs, numNames [] (map snd ys))
448 moreDistinct xs ys = compare (snd . fst . head $ xs, numNames [] (map snd ys))
431 (snd . fst . head $ ys, numNames [] (map snd xs))
449 (snd . fst . head $ ys, numNames [] (map snd xs))