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
29data CaseAlt' t = ConCase Name Int [Name] !(SC' t)
30 | FnCase Name [Name] !(SC' t) -- ^ reflection function
31 | ConstCase Const !(SC' t)
32 | SucCase Name !(SC' t)
33 | DefaultCase !(SC' t)
34 deriving (Show, Eq, Ord, Functor)
36deriving instance Binary CaseAlt
39type CaseAlt = CaseAlt' Term
41instance Show t => Show (SC' t) where
44 show' i (Case n alts) = "case " ++ show n ++ " of\n" ++ indent i ++
45 showSep ("\n" ++ indent i) (map (showA i) alts)
46 show' i (ProjCase tm alts) = "case " ++ show tm ++ " of " ++
47 showSep ("\n" ++ indent i) (map (showA i) alts)
48 show' i (STerm tm) = show tm
49 show' i (UnmatchedCase str) = "error " ++ show str
50 show' i ImpossibleCase = "impossible"
52 indent i = concat $ take i (repeat " ")
54 showA i (ConCase n t args sc)
55 = show n ++ "(" ++ showSep (", ") (map show args) ++ ") => "
57 showA i (FnCase n args sc)
58 = "FN " ++ show n ++ "(" ++ showSep (", ") (map show args) ++ ") => "
60 showA i (ConstCase t sc)
61 = show t ++ " => " ++ show' (i+1) sc
62 showA i (SucCase n sc)
63 = show n ++ "+1 => " ++ show' (i+1) sc
64 showA i (DefaultCase sc)
65 = "_ => " ++ show' (i+1) sc
69type Clause = ([Pat], (Term, Term))
70type CS = ([Term], Int, [(Name, Type)])
72instance TermSize SC where
73 termsize n (Case n' as) = termsize n as
74 termsize n (ProjCase n' as) = termsize n as
75 termsize n (STerm t) = termsize n t
78instance TermSize CaseAlt where
79 termsize n (ConCase _ _ _ s) = termsize n s
80 termsize n (FnCase _ _ s) = termsize n s
81 termsize n (ConstCase _ s) = termsize n s
82 termsize n (SucCase _ s) = termsize n s
83 termsize n (DefaultCase s) = termsize n s
85-- simple terms can be inlined trivially - good for primitives in particular
86-- To avoid duplicating work, don't inline something which uses one
87-- of its arguments in more than one place
89small :: Name -> [Name] -> SC -> Bool
90small n args t = let as = findAllUsedArgs t args in
91 length as == length (nub as) &&
94namesUsed :: SC -> [Name]
95namesUsed sc = nub $ nu' [] sc where
96 nu' ps (Case n alts) = nub (concatMap (nua ps) alts) \\ [n]
97 nu' ps (ProjCase t alts) = nub $ (nut ps t ++
98 (concatMap (nua ps) alts))
99 nu' ps (STerm t) = nub $ nut ps t
102 nua ps (ConCase n i args sc) = nub (nu' (ps ++ args) sc) \\ args
103 nua ps (FnCase n args sc) = nub (nu' (ps ++ args) sc) \\ args
104 nua ps (ConstCase _ sc) = nu' ps sc
105 nua ps (SucCase _ sc) = nu' ps sc
106 nua ps (DefaultCase sc) = nu' ps sc
108 nut ps (P _ n _) | n `elem` ps = []
110 nut ps (App f a) = nut ps f ++ nut ps a
111 nut ps (Proj t _) = nut ps t
112 nut ps (Bind n (Let t v) sc) = nut ps v ++ nut (n:ps) sc
113 nut ps (Bind n b sc) = nut (n:ps) sc
116-- Return all called functions, and which arguments are used in each argument position
117-- for the call, in order to help reduce compilation time, and trace all unused
120findCalls :: SC -> [Name] -> [(Name, [[Name]])]
121findCalls sc topargs = nub $ nu' topargs sc where
122 nu' ps (Case n alts) = nub (concatMap (nua (n : ps)) alts)
123 nu' ps (ProjCase t alts) = nub (nut ps t ++ concatMap (nua ps) alts)
124 nu' ps (STerm t) = nub $ nut ps t
127 nua ps (ConCase n i args sc) = nub (nu' (ps ++ args) sc)
128 nua ps (FnCase n args sc) = nub (nu' (ps ++ args) sc)
129 nua ps (ConstCase _ sc) = nu' ps sc
130 nua ps (SucCase _ sc) = nu' ps sc
131 nua ps (DefaultCase sc) = nu' ps sc
133 nut ps (P Ref n _) | n `elem` ps = []
134 | otherwise = [(n, [])] -- tmp
136 | (P Ref n _, args) <- unApply fn
137 = if n `elem` ps then nut ps f ++ nut ps a
138 else [(n, map argNames args)] ++ concatMap (nut ps) args
139 | (P (TCon _ _) n _, _) <- unApply fn = []
140 | otherwise = nut ps f ++ nut ps a
141 nut ps (Bind n (Let t v) sc) = nut ps v ++ nut (n:ps) sc
142 nut ps (Proj t _) = nut ps t
143 nut ps (Bind n b sc) = nut (n:ps) sc
146 argNames tm = let ns = directUse tm in
147 filter (\x -> x `elem` ns) topargs
149-- Find names which are used directly (i.e. not in a function call) in a term
151directUse :: Eq n => TT n -> [n]
152directUse (P _ n _) = [n]
153directUse (Bind n (Let t v) sc) = nub $ directUse v ++ (directUse sc \\ [n])
155directUse (Bind n b sc) = nub $ directUse (binderTy b) ++ (directUse sc \\ [n])
156directUse fn@(App f a)
157 | (P Ref n _, args) <- unApply fn = [] -- need to know what n does with them
158 | otherwise = nub $ directUse f ++ directUse a
159directUse (Proj x i) = nub $ directUse x
162-- Find all directly used arguments (i.e. used but not in function calls)
164findUsedArgs :: SC -> [Name] -> [Name]
165findUsedArgs sc topargs = nub (findAllUsedArgs sc topargs)
167findAllUsedArgs sc topargs = filter (\x -> x `elem` topargs) (nu' sc) where
168 nu' (Case n alts) = n : concatMap nua alts
169 nu' (ProjCase t alts) = directUse t ++ concatMap nua alts
170 nu' (STerm t) = directUse t
173 nua (ConCase n i args sc) = nu' sc
174 nua (FnCase n args sc) = nu' sc
175 nua (ConstCase _ sc) = nu' sc
176 nua (SucCase _ sc) = nu' sc
177 nua (DefaultCase sc) = nu' sc
179data Phase = CompileTime | RunTime
182-- Generate a simple case tree
185simpleCase :: Bool -> Bool -> Bool ->
186 Phase -> FC -> [Type] ->
187 [([Name], Term, Term)] ->
189simpleCase tc cover reflect phase fc argtys cs
190 = sc' tc cover phase fc (filter (\(_, _, r) ->
195 sc' tc cover phase fc []
196 = return $ CaseDef [] (UnmatchedCase "No pattern clauses") []
197 sc' tc cover phase fc cs
198 = let proj = phase == RunTime
199 vnames = fstT (head cs)
200 pats = map (\ (avs, l, r) ->
201 (avs, toPats reflect tc l, (l, r))) cs
202 chkPats = mapM chkAccessible pats in
205 let numargs = length (fst (head pats))
206 ns = take numargs args
207 (ns', ps') = order ns pats
208 (tree, st) = runState
209 (match ns' ps' (defaultCase cover))
211 t = CaseDef ns (prune proj (depatt ns' tree)) (fstT st) in
212 if proj then return (stripLambdas t)
213 else if checkSameTypes (lstT st) tree
215 else Error (At fc (Msg "Typecase is not allowed"))
216 Error err -> Error (At fc err)
217 where args = map (\i -> MN i "e") [0..]
218 defaultCase True = STerm Erased
219 defaultCase False = UnmatchedCase "Error"
223 chkAccessible (avs, l, c)
224 | phase == RunTime || reflect = return (l, c)
225 | otherwise = do mapM_ (acc l) avs
228 acc [] n = Error (Inaccessible n)
229 acc (PV x t : xs) n | x == n = OK ()
230 acc (PCon _ _ ps : xs) n = acc (ps ++ xs) n
231 acc (PSuc p : xs) n = acc (p : xs) n
232 acc (_ : xs) n = acc xs n
234-- For each 'Case', make sure every choice is in the same type family,
235-- as directed by the variable type (i.e. there is no implicit type casing
238checkSameTypes :: [(Name, Type)] -> SC -> Bool
239checkSameTypes tys (Case n alts)
240 = case lookup n tys of
241 Just t -> and (map (checkAlts t) alts)
242 _ -> and (map ((checkSameTypes tys).getSC) alts)
244 checkAlts t (ConCase n _ _ sc) = isType n t && checkSameTypes tys sc
245 checkAlts (Constant t) (ConstCase c sc) = isConstType c t && checkSameTypes tys sc
246 checkAlts _ (ConstCase c sc) = False
249 getSC (ConCase _ _ _ sc) = sc
250 getSC (FnCase _ _ sc) = sc
251 getSC (ConstCase _ sc) = sc
252 getSC (SucCase _ sc) = sc
253 getSC (DefaultCase sc) = sc
254checkSameTypes _ _ = True
256-- FIXME: All we're actually doing here is checking that we haven't arrived
257-- at a specific constructor for a polymorphic argument. I *think* this
258-- is sufficient, but if it turns out not to be, fix it!
259isType n t | (P (TCon _ _) _ _, _) <- unApply t = True
260isType n t | (P Ref _ _, _) <- unApply t = True
263isConstType (I _) (AType (ATInt ITNative)) = True
264isConstType (BI _) (AType (ATInt ITBig)) = True
265isConstType (Fl _) (AType ATFloat) = True
266isConstType (Ch _) (AType (ATInt ITChar)) = True
267isConstType (Str _) StrType = True
268isConstType (B8 _) (AType (ATInt _)) = True
269isConstType (B16 _) (AType (ATInt _)) = True
270isConstType (B32 _) (AType (ATInt _)) = True
271isConstType (B64 _) (AType (ATInt _)) = True
272isConstType (B8V _) (AType (ATInt _)) = True
273isConstType (B16V _) (AType (ATInt _)) = True
274isConstType (B32V _) (AType (ATInt _)) = True
275isConstType (B64V _) (AType (ATInt _)) = True
276isConstType _ _ = False
278data Pat = PCon Name Int [Pat]
281 | PSuc Pat -- special case for n+1 on Integer
282 | PReflected Name [Pat]
284 | PTyPat -- typecase, not allowed, inspect last
287-- If there are repeated variables, take the *last* one (could be name shadowing
288-- in a where clause, so take the most recent).
290toPats :: Bool -> Bool -> Term -> [Pat]
291toPats reflect tc f = reverse (toPat reflect tc (getArgs f)) where
292 getArgs (App f a) = a : getArgs f
295toPat :: Bool -> Bool -> [Term] -> [Pat]
296toPat reflect tc tms = evalState (mapM (\x -> toPat' x []) tms) []
298 toPat' (P (DCon t a) n _) args = do args' <- mapM (\x -> toPat' x []) args
299 return $ PCon n t args'
301 toPat' (P _ (UN "prim__addBigInt") _)
303 = do p' <- toPat' p []
306-- toPat' (P (TCon t a) n _) args | tc
307-- = do args' <- mapM (\x -> toPat' x []) args
308-- return $ PCon n t args'
309-- toPat' (Constant (AType (ATInt ITNative))) []
310-- | tc = return $ PCon (UN "Int") 1 []
311-- toPat' (Constant (AType ATFloat)) [] | tc = return $ PCon (UN "Float") 2 []
312-- toPat' (Constant (AType (ATInt ITChar))) [] | tc = return $ PCon (UN "Char") 3 []
313-- toPat' (Constant StrType) [] | tc = return $ PCon (UN "String") 4 []
314-- toPat' (Constant PtrType) [] | tc = return $ PCon (UN "Ptr") 5 []
315-- toPat' (Constant (AType (ATInt ITBig))) []
316-- | tc = return $ PCon (UN "Integer") 6 []
317-- toPat' (Constant (AType (ATInt (ITFixed n)))) []
318-- | tc = return $ PCon (UN (fixedN n)) (7 + fromEnum n) [] -- 7-10 inclusive
319 toPat' (P Bound n ty) [] = -- trace (show (n, ty)) $
325 toPat' (App f a) args = toPat' f (a : args)
326 toPat' (Constant (AType _)) [] = return PTyPat
327 toPat' (Constant StrType) [] = return PTyPat
328 toPat' (Constant PtrType) [] = return PTyPat
329 toPat' (Constant VoidType) [] = return PTyPat
330 toPat' (Constant x) [] = return $ PConst x
331 toPat' (Bind n (Pi t) sc) [] | reflect && noOccurrence n sc
332 = do t' <- toPat' t []
334 return $ PReflected (UN "->") (t':sc':[])
335 toPat' (P _ n _) args | reflect
336 = do args' <- mapM (\x -> toPat' x []) args
337 return $ PReflected n args'
338 toPat' t _ = return PAny
341 fixedN IT16 = "Bits16"
342 fixedN IT32 = "Bits32"
343 fixedN IT64 = "Bits64"
346data Partition = Cons [Clause]
350isVarPat (PV _ _ : ps , _) = True
351isVarPat (PAny : ps , _) = True
352isVarPat (PTyPat : ps , _) = True
355isConPat (PCon _ _ _ : ps, _) = True
356isConPat (PReflected _ _ : ps, _) = True
357isConPat (PSuc _ : ps, _) = True
358isConPat (PConst _ : ps, _) = True
361partition :: [Clause] -> [Partition]
364 | isVarPat m = let (vars, rest) = span isVarPat ms in
365 Vars vars : partition rest
366 | isConPat m = let (cons, rest) = span isConPat ms in
367 Cons cons : partition rest
368partition xs = error $ "Partition " ++ show xs
370-- reorder the patterns so that the one with most distinct names
371-- comes next. Take rightmost first, otherwise (i.e. pick value rather
374order :: [Name] -> [Clause] -> ([Name], [Clause])
375order [] cs = ([], cs)
376order ns [] = (ns, [])
377order ns cs = let patnames = transpose (map (zip ns) (map fst cs))
378 pats' = transpose (sortBy moreDistinct (reverse patnames)) in
379 (getNOrder pats', zipWith rebuild pats' cs)
381 getNOrder [] = error $ "Failed order on " ++ show (ns, cs)
382 getNOrder (c : _) = map fst c
384 rebuild patnames clause = (map snd patnames, snd clause)
386 moreDistinct xs ys = compare (numNames [] (map snd ys))
387 (numNames [] (map snd xs))
389 numNames xs (PCon n _ _ : ps)
390 | not (Left n `elem` xs) = numNames (Left n : xs) ps
391 numNames xs (PConst c : ps)
392 | not (Right c `elem` xs) = numNames (Right c : xs) ps
393 numNames xs (_ : ps) = numNames xs ps
394 numNames xs [] = length xs
396match :: [Name] -> [Clause] -> SC -- error case
398match [] (([], ret) : xs) err
399 = do (ts, v, ntys) <- get
400 put (ts ++ (map (fst.snd) xs), v, ntys)
402 Impossible -> return ImpossibleCase
403 tm -> return $ STerm tm -- run out of arguments
404match vs cs err = do let ps = partition cs
407mixture :: [Name] -> [Partition] -> SC -> State CS SC
408mixture vs [] err = return err
409mixture vs (Cons ms : ps) err = do fallthrough <- mixture vs ps err
410 conRule vs ms fallthrough
411mixture vs (Vars ms : ps) err = do fallthrough <- mixture vs ps err
412 varRule vs ms fallthrough
414data ConType = CName Name Int -- named constructor
415 | CFn Name -- reflected function name
417 | CConst Const -- constant, not implemented yet
420data Group = ConGroup ConType -- Constructor
421 [([Pat], Clause)] -- arguments and rest of alternative
424conRule :: [Name] -> [Clause] -> SC -> State CS SC
425conRule (v:vs) cs err = do groups <- groupCons cs
426 caseGroups (v:vs) groups err
428caseGroups :: [Name] -> [Group] -> SC -> State CS SC
429caseGroups (v:vs) gs err = do g <- altGroups gs
430 return $ Case v (sort g)
432 altGroups [] = return [DefaultCase err]
433 altGroups (ConGroup (CName n i) args : cs)
434 = do g <- altGroup n i args
437 altGroups (ConGroup (CFn n) args : cs)
438 = do g <- altFnGroup n args
441 altGroups (ConGroup CSuc args : cs)
442 = do g <- altSucGroup args
445 altGroups (ConGroup (CConst c) args : cs)
446 = do g <- altConstGroup c args
450 altGroup n i gs = do (newArgs, nextCs) <- argsToAlt gs
451 matchCs <- match (newArgs ++ vs) nextCs err
452 return $ ConCase n i newArgs matchCs
453 altFnGroup n gs = do (newArgs, nextCs) <- argsToAlt gs
454 matchCs <- match (newArgs ++ vs) nextCs err
455 return $ FnCase n newArgs matchCs
456 altSucGroup gs = do ([newArg], nextCs) <- argsToAlt gs
457 matchCs <- match (newArg:vs) nextCs err
458 return $ SucCase newArg matchCs
459 altConstGroup n gs = do (_, nextCs) <- argsToAlt gs
460 matchCs <- match vs nextCs err
461 return $ ConstCase n matchCs
463argsToAlt :: [([Pat], Clause)] -> State CS ([Name], [Clause])
464argsToAlt [] = return ([], [])
465argsToAlt rs@((r, m) : rest)
466 = do newArgs <- getNewVars r
467 return (newArgs, addRs rs)
469 getNewVars [] = return []
470 getNewVars ((PV n t) : ns) = do v <- getVar "e"
472 put (cs, i, (v, t) : ntys)
475 getNewVars (PAny : ns) = do v <- getVar "i"
478 getNewVars (PTyPat : ns) = do v <- getVar "t"
481 getNewVars (_ : ns) = do v <- getVar "e"
485 addRs ((r, (ps, res)) : rs) = ((r++ps, res) : addRs rs)
487 uniq i (UN n) = MN i n
490getVar :: String -> State CS Name
491getVar b = do (t, v, ntys) <- get; put (t, v+1, ntys); return (MN v b)
493groupCons :: [Clause] -> State CS [Group]
494groupCons cs = gc [] cs
496 gc acc [] = return acc
497 gc acc ((p : ps, res) : cs) =
498 do acc' <- addGroup p ps res acc
500 addGroup p ps res acc = case p of
501 PCon con i args -> return $ addg (CName con i) args (ps, res) acc
502 PConst cval -> return $ addConG cval (ps, res) acc
503 PSuc n -> return $ addg CSuc [n] (ps, res) acc
504 PReflected fn args -> return $ addg (CFn fn) args (ps, res) acc
505 pat -> fail $ show pat ++ " is not a constructor or constant (can't happen)"
507 addg c conargs res []
508 = [ConGroup c [(conargs, res)]]
509 addg c conargs res (g@(ConGroup c' cs):gs)
510 | c == c' = ConGroup c (cs ++ [(conargs, res)]) : gs
511 | otherwise = g : addg c conargs res gs
513 addConG con res [] = [ConGroup (CConst con) [([], res)]]
514 addConG con res (g@(ConGroup (CConst n) cs) : gs)
515 | con == n = ConGroup (CConst n) (cs ++ [([], res)]) : gs
516-- | otherwise = g : addConG con res gs
517 addConG con res (g : gs) = g : addConG con res gs
519varRule :: [Name] -> [Clause] -> SC -> State CS SC
520varRule (v : vs) alts err =
521 do alts' <- mapM (repVar v) alts
524 repVar v (PV p ty : ps , (lhs, res))
525 = do (cs, i, ntys) <- get
526 put (cs, i, (v, ty) : ntys)
527 return (ps, (lhs, subst p (P Bound v ty) res))
528 repVar v (PAny : ps , res) = return (ps, res)
529 repVar v (PTyPat : ps , res) = return (ps, res)
531-- fix: case e of S k -> f (S k) ==> case e of S k -> f e
533depatt :: [Name] -> SC -> SC
534depatt ns tm = dp [] tm
536 dp ms (STerm tm) = STerm (applyMaps ms tm)
537 dp ms (Case x alts) = Case x (map (dpa ms x) alts)
540 dpa ms x (ConCase n i args sc)
541 = ConCase n i args (dp ((x, (n, args)) : ms) sc)
542 dpa ms x (FnCase n args sc)
543 = FnCase n args (dp ((x, (n, args)) : ms) sc)
544 dpa ms x (ConstCase c sc) = ConstCase c (dp ms sc)
545 dpa ms x (SucCase n sc) = SucCase n (dp ms sc)
546 dpa ms x (DefaultCase sc) = DefaultCase (dp ms sc)
548 applyMaps ms f@(App _ _)
549 | (P nt cn pty, args) <- unApply f
550 = let args' = map (applyMaps ms) args in
551 applyMap ms nt cn pty args'
553 applyMap [] nt cn pty args' = mkApp (P nt cn pty) args'
554 applyMap ((x, (n, args)) : ms) nt cn pty args'
555 | and ((length args == length args') :
556 (n == cn) : zipWith same args args') = P Ref x Erased
557 | otherwise = applyMap ms nt cn pty args'
558 same n (P _ n' _) = n == n'
561 applyMaps ms (App f a) = App (applyMaps ms f) (applyMaps ms a)
564-- FIXME: Do this for SucCase too
565prune :: Bool -- ^ Convert single branches to projections (only useful at runtime)
567prune proj (Case n alts)
568 = let alts' = filter notErased (map pruneAlt alts) in
571 as@[ConCase cn i args sc] -> if proj then mkProj n 0 args sc
573 as@[SucCase cn sc] -> if proj then mkProj n (-1) [cn] sc
575 as@[ConstCase _ sc] -> prune proj sc
576 -- Bit of a hack here! The default case will always be 0, make sure
577 -- it gets caught first.
578 [s@(SucCase _ _), DefaultCase dc]
579 -> Case n [ConstCase (BI 0) dc, s]
581 where pruneAlt (ConCase cn i ns sc) = ConCase cn i ns (prune proj sc)
582 pruneAlt (FnCase cn ns sc) = FnCase cn ns (prune proj sc)
583 pruneAlt (ConstCase c sc) = ConstCase c (prune proj sc)
584 pruneAlt (SucCase n sc) = SucCase n (prune proj sc)
585 pruneAlt (DefaultCase sc) = DefaultCase (prune proj sc)
587 notErased (DefaultCase (STerm Erased)) = False
588 notErased (DefaultCase ImpossibleCase) = False
591 mkProj n i [] sc = prune proj sc
592 mkProj n i (x : xs) sc = mkProj n (i + 1) xs (projRep x n i sc)
594 -- Change every 'n' in sc to 'n-1'
595-- mkProjS n cn sc = prune proj (fmap projn sc) where
596-- projn pn@(P _ n' _)
597-- | cn == n' = App (App (P Ref (UN "prim__subBigInt") Erased)
598-- (P Bound n Erased)) (Constant (BI 1))
601 projRep :: Name -> Name -> Int -> SC -> SC
602 projRep arg n i (Case x alts)
603 | x == arg = ProjCase (Proj (P Bound n Erased) i)
604 (map (projRepAlt arg n i) alts)
605 | otherwise = Case x (map (projRepAlt arg n i) alts)
606 projRep arg n i (ProjCase t alts)
607 = ProjCase (projRepTm arg n i t) (map (projRepAlt arg n i) alts)
608 projRep arg n i (STerm t) = STerm (projRepTm arg n i t)
609 projRep arg n i c = c -- unmatched
611 projRepAlt arg n i (ConCase cn t args rhs)
612 = ConCase cn t args (projRep arg n i rhs)
613 projRepAlt arg n i (FnCase cn args rhs)
614 = FnCase cn args (projRep arg n i rhs)
615 projRepAlt arg n i (ConstCase t rhs)
616 = ConstCase t (projRep arg n i rhs)
617 projRepAlt arg n i (SucCase sn rhs)
618 = SucCase sn (projRep arg n i rhs)
619 projRepAlt arg n i (DefaultCase rhs)
620 = DefaultCase (projRep arg n i rhs)
622 projRepTm arg n i t = subst arg (Proj (P Bound n Erased) i) t
626stripLambdas :: CaseDef -> CaseDef
627stripLambdas (CaseDef ns (STerm (Bind x (Lam _) sc)) tm)
628 = 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