1{-# LANGUAGE PatternGuards, DeriveFunctor, TypeSynonymInstances #-}
3module Idris.Core.CaseTree(CaseDef(..), SC, SC'(..), CaseAlt, CaseAlt'(..),
5 simpleCase, small, namesUsed, findCalls, findUsedArgs) where
9import Control.Monad.State
11import Data.List hiding (partition)
14data CaseDef = CaseDef [Name] !SC [Term]
17data SC' t = Case Name [CaseAlt' t] -- ^ invariant: lowest tags first
18 | ProjCase t [CaseAlt' t] -- ^ special case for projections
20 | UnmatchedCase String -- ^ error message
21 | ImpossibleCase -- ^ already checked to be impossible
22 deriving (Eq, Ord, Functor)
24deriving instance Binary SC'
25deriving instance NFData SC'
30data CaseAlt' t = ConCase Name Int [Name] !(SC' t)
31 | FnCase Name [Name] !(SC' t) -- ^ reflection function
32 | ConstCase Const !(SC' t)
33 | SucCase Name !(SC' t)
34 | DefaultCase !(SC' t)
35 deriving (Show, Eq, Ord, Functor)
37deriving instance Binary CaseAlt'
38deriving instance NFData CaseAlt'
41type CaseAlt = CaseAlt' Term
43instance Show t => Show (SC' t) where
46 show' i (Case n alts) = "case " ++ show n ++ " of\n" ++ indent i ++
47 showSep ("\n" ++ indent i) (map (showA i) alts)
48 show' i (ProjCase tm alts) = "case " ++ show tm ++ " of " ++
49 showSep ("\n" ++ indent i) (map (showA i) alts)
50 show' i (STerm tm) = show tm
51 show' i (UnmatchedCase str) = "error " ++ show str
52 show' i ImpossibleCase = "impossible"
54 indent i = concat $ take i (repeat " ")
56 showA i (ConCase n t args sc)
57 = show n ++ "(" ++ showSep (", ") (map show args) ++ ") => "
59 showA i (FnCase n args sc)
60 = "FN " ++ show n ++ "(" ++ showSep (", ") (map show args) ++ ") => "
62 showA i (ConstCase t sc)
63 = show t ++ " => " ++ show' (i+1) sc
64 showA i (SucCase n sc)
65 = show n ++ "+1 => " ++ show' (i+1) sc
66 showA i (DefaultCase sc)
67 = "_ => " ++ show' (i+1) sc
71type Clause = ([Pat], (Term, Term))
72type CS = ([Term], Int, [(Name, Type)])
74instance TermSize SC where
75 termsize n (Case n' as) = termsize n as
76 termsize n (ProjCase n' as) = termsize n as
77 termsize n (STerm t) = termsize n t
80instance TermSize CaseAlt where
81 termsize n (ConCase _ _ _ s) = termsize n s
82 termsize n (FnCase _ _ s) = termsize n s
83 termsize n (ConstCase _ s) = termsize n s
84 termsize n (SucCase _ s) = termsize n s
85 termsize n (DefaultCase s) = termsize n s
87-- simple terms can be inlined trivially - good for primitives in particular
88-- To avoid duplicating work, don't inline something which uses one
89-- of its arguments in more than one place
91small :: Name -> [Name] -> SC -> Bool
92small n args t = let as = findAllUsedArgs t args in
93 length as == length (nub as) &&
96namesUsed :: SC -> [Name]
97namesUsed sc = nub $ nu' [] sc where
98 nu' ps (Case n alts) = nub (concatMap (nua ps) alts) \\ [n]
99 nu' ps (ProjCase t alts) = nub $ (nut ps t ++
100 (concatMap (nua ps) alts))
101 nu' ps (STerm t) = nub $ nut ps t
104 nua ps (ConCase n i args sc) = nub (nu' (ps ++ args) sc) \\ args
105 nua ps (FnCase n args sc) = nub (nu' (ps ++ args) sc) \\ args
106 nua ps (ConstCase _ sc) = nu' ps sc
107 nua ps (SucCase _ sc) = nu' ps sc
108 nua ps (DefaultCase sc) = nu' ps sc
110 nut ps (P _ n _) | n `elem` ps = []
112 nut ps (App f a) = nut ps f ++ nut ps a
113 nut ps (Proj t _) = nut ps t
114 nut ps (Bind n (Let t v) sc) = nut ps v ++ nut (n:ps) sc
115 nut ps (Bind n b sc) = nut (n:ps) sc
118-- Return all called functions, and which arguments are used in each argument position
119-- for the call, in order to help reduce compilation time, and trace all unused
122findCalls :: SC -> [Name] -> [(Name, [[Name]])]
123findCalls sc topargs = nub $ nu' topargs sc where
124 nu' ps (Case n alts) = nub (concatMap (nua (n : ps)) alts)
125 nu' ps (ProjCase t alts) = nub (nut ps t ++ concatMap (nua ps) alts)
126 nu' ps (STerm t) = nub $ nut ps t
129 nua ps (ConCase n i args sc) = nub (nu' (ps ++ args) sc)
130 nua ps (FnCase n args sc) = nub (nu' (ps ++ args) sc)
131 nua ps (ConstCase _ sc) = nu' ps sc
132 nua ps (SucCase _ sc) = nu' ps sc
133 nua ps (DefaultCase sc) = nu' ps sc
135 nut ps (P Ref n _) | n `elem` ps = []
136 | otherwise = [(n, [])] -- tmp
138 | (P Ref n _, args) <- unApply fn
139 = if n `elem` ps then nut ps f ++ nut ps a
140 else [(n, map argNames args)] ++ concatMap (nut ps) args
141 | (P (TCon _ _) n _, _) <- unApply fn = []
142 | otherwise = nut ps f ++ nut ps a
143 nut ps (Bind n (Let t v) sc) = nut ps v ++ nut (n:ps) sc
144 nut ps (Proj t _) = nut ps t
145 nut ps (Bind n b sc) = nut (n:ps) sc
148 argNames tm = let ns = directUse tm in
149 filter (\x -> x `elem` ns) topargs
151-- Find names which are used directly (i.e. not in a function call) in a term
153directUse :: Eq n => TT n -> [n]
154directUse (P _ n _) = [n]
155directUse (Bind n (Let t v) sc) = nub $ directUse v ++ (directUse sc \\ [n])
157directUse (Bind n b sc) = nub $ directUse (binderTy b) ++ (directUse sc \\ [n])
158directUse fn@(App f a)
159 | (P Ref n _, args) <- unApply fn = [] -- need to know what n does with them
160 | otherwise = nub $ directUse f ++ directUse a
161directUse (Proj x i) = nub $ directUse x
164-- Find all directly used arguments (i.e. used but not in function calls)
166findUsedArgs :: SC -> [Name] -> [Name]
167findUsedArgs sc topargs = nub (findAllUsedArgs sc topargs)
169findAllUsedArgs sc topargs = filter (\x -> x `elem` topargs) (nu' sc) where
170 nu' (Case n alts) = n : concatMap nua alts
171 nu' (ProjCase t alts) = directUse t ++ concatMap nua alts
172 nu' (STerm t) = directUse t
175 nua (ConCase n i args sc) = nu' sc
176 nua (FnCase n args sc) = nu' sc
177 nua (ConstCase _ sc) = nu' sc
178 nua (SucCase _ sc) = nu' sc
179 nua (DefaultCase sc) = nu' sc
181data Phase = CompileTime | RunTime
184-- Generate a simple case tree
187simpleCase :: Bool -> Bool -> Bool ->
188 Phase -> FC -> [Type] ->
189 [([Name], Term, Term)] ->
191simpleCase tc cover reflect phase fc argtys cs
192 = sc' tc cover phase fc (filter (\(_, _, r) ->
197 sc' tc cover phase fc []
198 = return $ CaseDef [] (UnmatchedCase "No pattern clauses") []
199 sc' tc cover phase fc cs
200 = let proj = phase == RunTime
201 vnames = fstT (head cs)
202 pats = map (\ (avs, l, r) ->
203 (avs, toPats reflect tc l, (l, r))) cs
204 chkPats = mapM chkAccessible pats in
207 let numargs = length (fst (head pats))
208 ns = take numargs args
209 (ns', ps') = order ns pats
210 (tree, st) = runState
211 (match ns' ps' (defaultCase cover))
213 t = CaseDef ns (prune proj (depatt ns' tree)) (fstT st) in
214 if proj then return (stripLambdas t)
215 else if checkSameTypes (lstT st) tree
217 else Error (At fc (Msg "Typecase is not allowed"))
218 Error err -> Error (At fc err)
219 where args = map (\i -> MN i "e") [0..]
220 defaultCase True = STerm Erased
221 defaultCase False = UnmatchedCase "Error"
225 chkAccessible (avs, l, c)
226 | phase == RunTime || reflect = return (l, c)
227 | otherwise = do mapM_ (acc l) avs
230 acc [] n = Error (Inaccessible n)
231 acc (PV x t : xs) n | x == n = OK ()
232 acc (PCon _ _ ps : xs) n = acc (ps ++ xs) n
233 acc (PSuc p : xs) n = acc (p : xs) n
234 acc (_ : xs) n = acc xs n
236-- For each 'Case', make sure every choice is in the same type family,
237-- as directed by the variable type (i.e. there is no implicit type casing
240checkSameTypes :: [(Name, Type)] -> SC -> Bool
241checkSameTypes tys (Case n alts)
242 = case lookup n tys of
243 Just t -> and (map (checkAlts t) alts)
244 _ -> and (map ((checkSameTypes tys).getSC) alts)
246 checkAlts t (ConCase n _ _ sc) = isType n t && checkSameTypes tys sc
247 checkAlts (Constant t) (ConstCase c sc) = isConstType c t && checkSameTypes tys sc
248 checkAlts _ (ConstCase c sc) = False
251 getSC (ConCase _ _ _ sc) = sc
252 getSC (FnCase _ _ sc) = sc
253 getSC (ConstCase _ sc) = sc
254 getSC (SucCase _ sc) = sc
255 getSC (DefaultCase sc) = sc
256checkSameTypes _ _ = True
258-- FIXME: All we're actually doing here is checking that we haven't arrived
259-- at a specific constructor for a polymorphic argument. I *think* this
260-- is sufficient, but if it turns out not to be, fix it!
261isType n t | (P (TCon _ _) _ _, _) <- unApply t = True
262isType n t | (P Ref _ _, _) <- unApply t = True
265isConstType (I _) (AType (ATInt ITNative)) = True
266isConstType (BI _) (AType (ATInt ITBig)) = True
267isConstType (Fl _) (AType ATFloat) = True
268isConstType (Ch _) (AType (ATInt ITChar)) = True
269isConstType (Str _) StrType = True
270isConstType (B8 _) (AType (ATInt _)) = True
271isConstType (B16 _) (AType (ATInt _)) = True
272isConstType (B32 _) (AType (ATInt _)) = True
273isConstType (B64 _) (AType (ATInt _)) = True
274isConstType (B8V _) (AType (ATInt _)) = True
275isConstType (B16V _) (AType (ATInt _)) = True
276isConstType (B32V _) (AType (ATInt _)) = True
277isConstType (B64V _) (AType (ATInt _)) = True
278isConstType _ _ = False
280data Pat = PCon Name Int [Pat]
283 | PSuc Pat -- special case for n+1 on Integer
284 | PReflected Name [Pat]
286 | PTyPat -- typecase, not allowed, inspect last
289-- If there are repeated variables, take the *last* one (could be name shadowing
290-- in a where clause, so take the most recent).
292toPats :: Bool -> Bool -> Term -> [Pat]
293toPats reflect tc f = reverse (toPat reflect tc (getArgs f)) where
294 getArgs (App f a) = a : getArgs f
297toPat :: Bool -> Bool -> [Term] -> [Pat]
298toPat reflect tc tms = evalState (mapM (\x -> toPat' x []) tms) []
300 toPat' (P (DCon t a) n _) args = do args' <- mapM (\x -> toPat' x []) args
301 return $ PCon n t args'
303 toPat' (P _ (UN "prim__addBigInt") _)
305 = do p' <- toPat' p []
308-- toPat' (P (TCon t a) n _) args | tc
309-- = do args' <- mapM (\x -> toPat' x []) args
310-- return $ PCon n t args'
311-- toPat' (Constant (AType (ATInt ITNative))) []
312-- | tc = return $ PCon (UN "Int") 1 []
313-- toPat' (Constant (AType ATFloat)) [] | tc = return $ PCon (UN "Float") 2 []
314-- toPat' (Constant (AType (ATInt ITChar))) [] | tc = return $ PCon (UN "Char") 3 []
315-- toPat' (Constant StrType) [] | tc = return $ PCon (UN "String") 4 []
316-- toPat' (Constant PtrType) [] | tc = return $ PCon (UN "Ptr") 5 []
317-- toPat' (Constant (AType (ATInt ITBig))) []
318-- | tc = return $ PCon (UN "Integer") 6 []
319-- toPat' (Constant (AType (ATInt (ITFixed n)))) []
320-- | tc = return $ PCon (UN (fixedN n)) (7 + fromEnum n) [] -- 7-10 inclusive
321 toPat' (P Bound n ty) [] = -- trace (show (n, ty)) $
327 toPat' (App f a) args = toPat' f (a : args)
328 toPat' (Constant (AType _)) [] = return PTyPat
329 toPat' (Constant StrType) [] = return PTyPat
330 toPat' (Constant PtrType) [] = return PTyPat
331 toPat' (Constant VoidType) [] = return PTyPat
332 toPat' (Constant x) [] = return $ PConst x
333 toPat' (Bind n (Pi t) sc) [] | reflect && noOccurrence n sc
334 = do t' <- toPat' t []
336 return $ PReflected (UN "->") (t':sc':[])
337 toPat' (P _ n _) args | reflect
338 = do args' <- mapM (\x -> toPat' x []) args
339 return $ PReflected n args'
340 toPat' t _ = return PAny
343 fixedN IT16 = "Bits16"
344 fixedN IT32 = "Bits32"
345 fixedN IT64 = "Bits64"
348data Partition = Cons [Clause]
352isVarPat (PV _ _ : ps , _) = True
353isVarPat (PAny : ps , _) = True
354isVarPat (PTyPat : ps , _) = True
357isConPat (PCon _ _ _ : ps, _) = True
358isConPat (PReflected _ _ : ps, _) = True
359isConPat (PSuc _ : ps, _) = True
360isConPat (PConst _ : ps, _) = True
363partition :: [Clause] -> [Partition]
366 | isVarPat m = let (vars, rest) = span isVarPat ms in
367 Vars vars : partition rest
368 | isConPat m = let (cons, rest) = span isConPat ms in
369 Cons cons : partition rest
370partition xs = error $ "Partition " ++ show xs
372-- reorder the patterns so that the one with most distinct names
373-- comes next. Take rightmost first, otherwise (i.e. pick value rather
376order :: [Name] -> [Clause] -> ([Name], [Clause])
377order [] cs = ([], cs)
378order ns [] = (ns, [])
379order ns cs = let patnames = transpose (map (zip ns) (map fst cs))
380 pats' = transpose (sortBy moreDistinct (reverse patnames)) in
381 (getNOrder pats', zipWith rebuild pats' cs)
383 getNOrder [] = error $ "Failed order on " ++ show (ns, cs)
384 getNOrder (c : _) = map fst c
386 rebuild patnames clause = (map snd patnames, snd clause)
388 moreDistinct xs ys = compare (numNames [] (map snd ys))
389 (numNames [] (map snd xs))
391 numNames xs (PCon n _ _ : ps)
392 | not (Left n `elem` xs) = numNames (Left n : xs) ps
393 numNames xs (PConst c : ps)
394 | not (Right c `elem` xs) = numNames (Right c : xs) ps
395 numNames xs (_ : ps) = numNames xs ps
396 numNames xs [] = length xs
398match :: [Name] -> [Clause] -> SC -- error case
400match [] (([], ret) : xs) err
401 = do (ts, v, ntys) <- get
402 put (ts ++ (map (fst.snd) xs), v, ntys)
404 Impossible -> return ImpossibleCase
405 tm -> return $ STerm tm -- run out of arguments
406match vs cs err = do let ps = partition cs
409mixture :: [Name] -> [Partition] -> SC -> State CS SC
410mixture vs [] err = return err
411mixture vs (Cons ms : ps) err = do fallthrough <- mixture vs ps err
412 conRule vs ms fallthrough
413mixture vs (Vars ms : ps) err = do fallthrough <- mixture vs ps err
414 varRule vs ms fallthrough
416data ConType = CName Name Int -- named constructor
417 | CFn Name -- reflected function name
419 | CConst Const -- constant, not implemented yet
422data Group = ConGroup ConType -- Constructor
423 [([Pat], Clause)] -- arguments and rest of alternative
426conRule :: [Name] -> [Clause] -> SC -> State CS SC
427conRule (v:vs) cs err = do groups <- groupCons cs
428 caseGroups (v:vs) groups err
430caseGroups :: [Name] -> [Group] -> SC -> State CS SC
431caseGroups (v:vs) gs err = do g <- altGroups gs
432 return $ Case v (sort g)
434 altGroups [] = return [DefaultCase err]
435 altGroups (ConGroup (CName n i) args : cs)
436 = do g <- altGroup n i args
439 altGroups (ConGroup (CFn n) args : cs)
440 = do g <- altFnGroup n args
443 altGroups (ConGroup CSuc args : cs)
444 = do g <- altSucGroup args
447 altGroups (ConGroup (CConst c) args : cs)
448 = do g <- altConstGroup c args
452 altGroup n i gs = do (newArgs, nextCs) <- argsToAlt gs
453 matchCs <- match (newArgs ++ vs) nextCs err
454 return $ ConCase n i newArgs matchCs
455 altFnGroup n gs = do (newArgs, nextCs) <- argsToAlt gs
456 matchCs <- match (newArgs ++ vs) nextCs err
457 return $ FnCase n newArgs matchCs
458 altSucGroup gs = do ([newArg], nextCs) <- argsToAlt gs
459 matchCs <- match (newArg:vs) nextCs err
460 return $ SucCase newArg matchCs
461 altConstGroup n gs = do (_, nextCs) <- argsToAlt gs
462 matchCs <- match vs nextCs err
463 return $ ConstCase n matchCs
465argsToAlt :: [([Pat], Clause)] -> State CS ([Name], [Clause])
466argsToAlt [] = return ([], [])
467argsToAlt rs@((r, m) : rest)
468 = do newArgs <- getNewVars r
469 return (newArgs, addRs rs)
471 getNewVars [] = return []
472 getNewVars ((PV n t) : ns) = do v <- getVar "e"
474 put (cs, i, (v, t) : ntys)
477 getNewVars (PAny : ns) = do v <- getVar "i"
480 getNewVars (PTyPat : ns) = do v <- getVar "t"
483 getNewVars (_ : ns) = do v <- getVar "e"
487 addRs ((r, (ps, res)) : rs) = ((r++ps, res) : addRs rs)
489 uniq i (UN n) = MN i n
492getVar :: String -> State CS Name
493getVar b = do (t, v, ntys) <- get; put (t, v+1, ntys); return (MN v b)
495groupCons :: [Clause] -> State CS [Group]
496groupCons cs = gc [] cs
498 gc acc [] = return acc
499 gc acc ((p : ps, res) : cs) =
500 do acc' <- addGroup p ps res acc
502 addGroup p ps res acc = case p of
503 PCon con i args -> return $ addg (CName con i) args (ps, res) acc
504 PConst cval -> return $ addConG cval (ps, res) acc
505 PSuc n -> return $ addg CSuc [n] (ps, res) acc
506 PReflected fn args -> return $ addg (CFn fn) args (ps, res) acc
507 pat -> fail $ show pat ++ " is not a constructor or constant (can't happen)"
509 addg c conargs res []
510 = [ConGroup c [(conargs, res)]]
511 addg c conargs res (g@(ConGroup c' cs):gs)
512 | c == c' = ConGroup c (cs ++ [(conargs, res)]) : gs
513 | otherwise = g : addg c conargs res gs
515 addConG con res [] = [ConGroup (CConst con) [([], res)]]
516 addConG con res (g@(ConGroup (CConst n) cs) : gs)
517 | con == n = ConGroup (CConst n) (cs ++ [([], res)]) : gs
518-- | otherwise = g : addConG con res gs
519 addConG con res (g : gs) = g : addConG con res gs
521varRule :: [Name] -> [Clause] -> SC -> State CS SC
522varRule (v : vs) alts err =
523 do alts' <- mapM (repVar v) alts
526 repVar v (PV p ty : ps , (lhs, res))
527 = do (cs, i, ntys) <- get
528 put (cs, i, (v, ty) : ntys)
529 return (ps, (lhs, subst p (P Bound v ty) res))
530 repVar v (PAny : ps , res) = return (ps, res)
531 repVar v (PTyPat : ps , res) = return (ps, res)
533-- fix: case e of S k -> f (S k) ==> case e of S k -> f e
535depatt :: [Name] -> SC -> SC
536depatt ns tm = dp [] tm
538 dp ms (STerm tm) = STerm (applyMaps ms tm)
539 dp ms (Case x alts) = Case x (map (dpa ms x) alts)
542 dpa ms x (ConCase n i args sc)
543 = ConCase n i args (dp ((x, (n, args)) : ms) sc)
544 dpa ms x (FnCase n args sc)
545 = FnCase n args (dp ((x, (n, args)) : ms) sc)
546 dpa ms x (ConstCase c sc) = ConstCase c (dp ms sc)
547 dpa ms x (SucCase n sc) = SucCase n (dp ms sc)
548 dpa ms x (DefaultCase sc) = DefaultCase (dp ms sc)
550 applyMaps ms f@(App _ _)
551 | (P nt cn pty, args) <- unApply f
552 = let args' = map (applyMaps ms) args in
553 applyMap ms nt cn pty args'
555 applyMap [] nt cn pty args' = mkApp (P nt cn pty) args'
556 applyMap ((x, (n, args)) : ms) nt cn pty args'
557 | and ((length args == length args') :
558 (n == cn) : zipWith same args args') = P Ref x Erased
559 | otherwise = applyMap ms nt cn pty args'
560 same n (P _ n' _) = n == n'
563 applyMaps ms (App f a) = App (applyMaps ms f) (applyMaps ms a)
566-- FIXME: Do this for SucCase too
567prune :: Bool -- ^ Convert single branches to projections (only useful at runtime)
569prune proj (Case n alts)
570 = let alts' = filter notErased (map pruneAlt alts) in
573 as@[ConCase cn i args sc] -> if proj then mkProj n 0 args sc
575 as@[SucCase cn sc] -> if proj then mkProj n (-1) [cn] sc
577 as@[ConstCase _ sc] -> prune proj sc
578 -- Bit of a hack here! The default case will always be 0, make sure
579 -- it gets caught first.
580 [s@(SucCase _ _), DefaultCase dc]
581 -> Case n [ConstCase (BI 0) dc, s]
583 where pruneAlt (ConCase cn i ns sc) = ConCase cn i ns (prune proj sc)
584 pruneAlt (FnCase cn ns sc) = FnCase cn ns (prune proj sc)
585 pruneAlt (ConstCase c sc) = ConstCase c (prune proj sc)
586 pruneAlt (SucCase n sc) = SucCase n (prune proj sc)
587 pruneAlt (DefaultCase sc) = DefaultCase (prune proj sc)
589 notErased (DefaultCase (STerm Erased)) = False
590 notErased (DefaultCase ImpossibleCase) = False
593 mkProj n i [] sc = prune proj sc
594 mkProj n i (x : xs) sc = mkProj n (i + 1) xs (projRep x n i sc)
596 -- Change every 'n' in sc to 'n-1'
597-- mkProjS n cn sc = prune proj (fmap projn sc) where
598-- projn pn@(P _ n' _)
599-- | cn == n' = App (App (P Ref (UN "prim__subBigInt") Erased)
600-- (P Bound n Erased)) (Constant (BI 1))
603 projRep :: Name -> Name -> Int -> SC -> SC
604 projRep arg n i (Case x alts)
605 | x == arg = ProjCase (Proj (P Bound n Erased) i)
606 (map (projRepAlt arg n i) alts)
607 | otherwise = Case x (map (projRepAlt arg n i) alts)
608 projRep arg n i (ProjCase t alts)
609 = ProjCase (projRepTm arg n i t) (map (projRepAlt arg n i) alts)
610 projRep arg n i (STerm t) = STerm (projRepTm arg n i t)
611 projRep arg n i c = c -- unmatched
613 projRepAlt arg n i (ConCase cn t args rhs)
614 = ConCase cn t args (projRep arg n i rhs)
615 projRepAlt arg n i (FnCase cn args rhs)
616 = FnCase cn args (projRep arg n i rhs)
617 projRepAlt arg n i (ConstCase t rhs)
618 = ConstCase t (projRep arg n i rhs)
619 projRepAlt arg n i (SucCase sn rhs)
620 = SucCase sn (projRep arg n i rhs)
621 projRepAlt arg n i (DefaultCase rhs)
622 = DefaultCase (projRep arg n i rhs)
624 projRepTm arg n i t = subst arg (Proj (P Bound n Erased) i) t
628stripLambdas :: CaseDef -> CaseDef
629stripLambdas (CaseDef ns (STerm (Bind x (Lam _) sc)) tm)
630 = stripLambdas (CaseDef (ns ++ [x]) (STerm (instantiate (P Bound x Erased) sc)) tm)
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list