@@ -171,15 +171,16 @@ simpleCase tc cover phase fc []
171simpleCase tc cover phase fc cs
171simpleCase tc cover phase fc cs
172 = let proj = phase == RunTime
172 = let proj = phase == RunTime
173 pats = map (\ (avs, l, r) ->
173 pats = map (\ (avs, l, r) ->
174− (avs, rev phase (toPats tc l), (l, r))) cs
174+ (avs, toPats tc l, (l, r))) cs
175 chkPats = mapM chkAccessible pats in
175 chkPats = mapM chkAccessible pats in
176 case chkPats of
176 case chkPats of
177 OK pats ->
177 OK pats ->
178 let numargs = length (fst (head pats))
178 let numargs = length (fst (head pats))
179 ns = take numargs args
179 ns = take numargs args
180+ (ns', ps') = order ns pats
180 (tree, st) = runState
181 (tree, st) = runState
181− (match (rev phase ns) pats (defaultCase cover)) ([], numargs)
182+ (match ns' ps' (defaultCase cover)) ([], numargs)
182− t = CaseDef ns (prune proj (depatt ns tree)) (fst st) in
183+ t = CaseDef ns (prune proj (depatt ns' tree)) (fst st) in
183 if proj then return (stripLambdas t) else return t
184 if proj then return (stripLambdas t) else return t
184 Error err -> Error (At fc err)
185 Error err -> Error (At fc err)
185 where args = map (\i -> MN i "e") [0..]
186 where args = map (\i -> MN i "e") [0..]
@@ -196,11 +197,6 @@ simpleCase tc cover phase fc cs
196 acc (PCon _ _ ps : xs) n = acc (ps ++ xs) n
197 acc (PCon _ _ ps : xs) n = acc (ps ++ xs) n
197 acc (_ : xs) n = acc xs n
198 acc (_ : xs) n = acc xs n
199−-- right to left gives more chance of discriminating on interesting arguments
200−-- rather than indices which are likely to be repeated.
201−-- rev CompileTime = id
204data Pat = PCon Name Int [Pat]
200data Pat = PCon Name Int [Pat]
205 | PConst Const
201 | PConst Const
206 | PV Name
202 | PV Name
@@ -264,6 +260,32 @@ partition ms@(m : _)
264 Cons cons : partition rest
260 Cons cons : partition rest
265partition xs = error $ "Partition " ++ show xs
261partition xs = error $ "Partition " ++ show xs
263+-- reorder the patterns so that the one with most distinct names
264+-- comes next. Take rightmost first, otherwise (i.e. pick value rather
267+order :: [Name] -> [Clause] -> ([Name], [Clause])
268+order [] cs = ([], cs)
269+order ns [] = (ns, [])
270+order ns cs = let patnames = transpose (map (zip ns) (map fst cs))
271+ pats' = transpose (sortBy moreDistinct (reverse patnames)) in
272+ (getNOrder pats', zipWith rebuild pats' cs)
274+ getNOrder [] = error $ "Failed order on " ++ show (ns, cs)
275+ getNOrder (c : _) = map fst c
277+ rebuild patnames clause = (map snd patnames, snd clause)
279+ moreDistinct xs ys = compare (numNames [] (map snd ys))
280+ (numNames [] (map snd xs))
282+ numNames xs (PCon n _ _ : ps)
283+ | not (Left n `elem` xs) = numNames (Left n : xs) ps
284+ numNames xs (PConst c : ps)
285+ | not (Right c `elem` xs) = numNames (Right c : xs) ps
286+ numNames xs (_ : ps) = numNames xs ps
287+ numNames xs [] = length xs
267match :: [Name] -> [Clause] -> SC -- error case
289match :: [Name] -> [Clause] -> SC -- error case
268 -> State CS SC
290 -> State CS SC
269match [] (([], ret) : xs) err
291match [] (([], ret) : xs) err
@@ -273,8 +295,7 @@ match [] (([], ret) : xs) err
273 Impossible -> return ImpossibleCase
295 Impossible -> return ImpossibleCase
274 tm -> return $ STerm tm -- run out of arguments
296 tm -> return $ STerm tm -- run out of arguments
275match vs cs err = do let ps = partition cs
297match vs cs err = do let ps = partition cs
276− cs <- mixture vs ps err
298+ mixture vs ps err
279mixture :: [Name] -> [Partition] -> SC -> State CS SC
300mixture :: [Name] -> [Partition] -> SC -> State CS SC
280mixture vs [] err = return err
301mixture vs [] err = return err