@@ -1,5 +1,5 @@
11module Core.CaseTree(CaseDef(..), SC(..), CaseAlt(..), CaseTree,
2− simpleCase, small, namesUsed) where
2+ simpleCase, small, namesUsed, findCalls) where
33
44import Core.TT
55
@@ -12,6 +12,7 @@ data CaseDef = CaseDef [Name] SC [Term]
1212 deriving Show
1313
1414data SC = Case Name [CaseAlt] -- invariant: lowest tags first
15+ | ProjCase Term [CaseAlt] -- special case for projections
1516 | STerm Term
1617 | UnmatchedCase String -- error message
1718 deriving (Show, Eq, Ord)
@@ -62,10 +63,51 @@ namesUsed sc = nub $ nu' [] sc where
6263 nut ps (Bind n b sc) = nut (n:ps) sc
6364 nut ps _ = []
6465
65−simpleCase :: Bool -> Bool -> FC -> [([Name], Term, Term)] -> TC CaseDef
66−simpleCase tc cover fc []
66+-- Return all called functions, and which arguments are used in each argument position
67+-- for the call, in order to help reduce compilation time, and trace all unused
68+-- arguments
69+
70+findCalls :: SC -> [Name] -> [(Name, [[Name]])]
71+findCalls sc ign = nub $ nu' ign sc where
72+ nu' ps (Case n alts) = nub (concatMap (nua (n : ps)) alts)
73+ nu' ps (STerm t) = nub $ nut ps t
74+ nu' ps _ = []
75+
76+ nua ps (ConCase n i args sc) = nub (nu' (ps ++ args) sc)
77+ nua ps (ConstCase _ sc) = nu' ps sc
78+ nua ps (DefaultCase sc) = nu' ps sc
79+
80+ nut ps (P _ n _) | n `elem` ps = []
81+ | otherwise = [(n, [])] -- tmp
82+ nut ps (App f a) = nut ps f ++ nut ps a
83+ nut ps (Bind n (Let t v) sc) = nut ps v ++ nut (n:ps) sc
84+ nut ps (Bind n b sc) = nut (n:ps) sc
85+ nut ps _ = []
86+
87+-- Find directly used arguments (i.e. used but not in function calls)
88+{-
89+findUsedArgs :: SC -> [Name] -> [(Name, [[Name]])]
90+findUsedArgs sc ign = nub $ nu' ign sc where
91+ nu' ps (Case n alts) = nub (concatMap (nua (n : ps)) alts)
92+ nu' ps (STerm t) = nub $ nut ps t
93+ nu' ps _ = []
94+
95+ nua ps (ConCase n i args sc) = nub (nu' (ps ++ args) sc)
96+ nua ps (ConstCase _ sc) = nu' ps sc
97+ nua ps (DefaultCase sc) = nu' ps sc
98+
99+ nut ps (P _ n _) | n `elem` ps = []
100+ | otherwise = [(n, [])] -- tmp
101+ nut ps (App f a) = nut ps f ++ nut ps a
102+ nut ps (Bind n (Let t v) sc) = nut ps v ++ nut (n:ps) sc
103+ nut ps (Bind n b sc) = nut (n:ps) sc
104+ nut ps _ = []
105+-}
106+
107+simpleCase :: Bool -> Bool -> Bool -> FC -> [([Name], Term, Term)] -> TC CaseDef
108+simpleCase tc cover proj fc []
67109 = return $ CaseDef [] (UnmatchedCase "No pattern clauses") []
68−simpleCase tc cover fc cs
110+simpleCase tc cover proj fc cs
69111 = let pats = map (\ (avs, l, r) ->
70112 (avs, reverse (toPats tc l), (l, r))) cs
71113 chkPats = mapM chkAccessible pats in
@@ -75,7 +117,7 @@ simpleCase tc cover fc cs
75117 ns = take numargs args
76118 (tree, st) = runState
77119 (match (reverse ns) pats (defaultCase cover)) ([], numargs) in
78− return $ CaseDef ns (prune tree) (fst st)
120+ return $ CaseDef ns (prune proj tree) (fst st)
79121 Error err -> Error (At fc err)
80122 where args = map (\i -> MN i "e") [0..]
81123 defaultCase True = STerm Erased
@@ -250,19 +292,45 @@ varRule (v : vs) alts err =
250292 repVar v (PV p : ps , (lhs, res)) = (ps, (lhs, subst p (P Bound v (V 0)) res))
251293 repVar v (PAny : ps , res) = (ps, res)
252294
253−prune :: SC -> SC
254−prune (Case n alts)
295+prune :: Bool -> -- ^ Convert single brances to projections (only useful at runtime)
296+ SC -> SC
297+prune proj (Case n alts)
255298 = let alts' = map pruneAlt $
256299 filter notErased alts in
257300 case alts' of
258301 [] -> STerm Erased
302+ as@[ConCase cn i args sc] -> if proj then mkProj n 0 args sc
303+ else Case n as
259304 as -> Case n as
260− where pruneAlt (ConCase cn i ns sc) = ConCase cn i ns (prune sc)
261− pruneAlt (ConstCase c sc) = ConstCase c (prune sc)
262− pruneAlt (DefaultCase sc) = DefaultCase (prune sc)
305+ where pruneAlt (ConCase cn i ns sc) = ConCase cn i ns (prune proj sc)
306+ pruneAlt (ConstCase c sc) = ConstCase c (prune proj sc)
307+ pruneAlt (DefaultCase sc) = DefaultCase (prune proj sc)
263308
264309 notErased (DefaultCase (STerm Erased)) = False
265310 notErased _ = True
266−prune t = t
311+
312+ mkProj n i [] sc = sc
313+ mkProj n i (x : xs) sc = mkProj n (i + 1) xs (projRep x n i sc)
314+
315+ projRep :: Name -> Name -> Int -> SC -> SC
316+ projRep arg n i (Case x alts)
317+ | x == arg = ProjCase (Proj (P Bound n Erased) i)
318+ (map (projRepAlt arg n i) alts)
319+ | otherwise = Case x (map (projRepAlt arg n i) alts)
320+ projRep arg n i (ProjCase t alts)
321+ = ProjCase (projRepTm arg n i t) (map (projRepAlt arg n i) alts)
322+ projRep arg n i (STerm t) = STerm (projRepTm arg n i t)
323+ projRep arg n i c = c -- unmatched
324+
325+ projRepAlt arg n i (ConCase cn t args rhs)
326+ = ConCase cn t args (projRep arg n i rhs)
327+ projRepAlt arg n i (ConstCase t rhs)
328+ = ConstCase t (projRep arg n i rhs)
329+ projRepAlt arg n i (DefaultCase rhs)
330+ = DefaultCase (projRep arg n i rhs)
331+
332+ projRepTm arg n i t = subst arg (Proj (P Bound n Erased) i) t
333+
334+prune _ t = t
267335
268336