@@ -1,13 +1,15 @@
1{-# LANGUAGE PatternGuards, DeriveFunctor, TypeSynonymInstances #-}
1{-# LANGUAGE PatternGuards, DeriveFunctor, TypeSynonymInstances #-}
3−module Idris.Core.CaseTree(CaseDef(..), SC, SC'(..), CaseAlt, CaseAlt'(..),
3+module Idris.Core.CaseTree(CaseDef(..), SC, SC'(..), CaseAlt, CaseAlt'(..), ErasureInfo,
4 Phase(..), CaseTree,
4 Phase(..), CaseTree,
5 simpleCase, small, namesUsed, findCalls, findUsedArgs,
5 simpleCase, small, namesUsed, findCalls, findUsedArgs,
6 substSC, substAlt, mkForce) where
6 substSC, substAlt, mkForce) where
8import Idris.Core.TT
8import Idris.Core.TT
10+import Control.Applicative hiding (Const)
10import Control.Monad.State
11import Control.Monad.State
12+import Control.Monad.Reader
11import Data.Maybe
13import Data.Maybe
12import Data.List hiding (partition)
14import Data.List hiding (partition)
13import qualified Data.List(partition)
15import qualified Data.List(partition)
@@ -24,7 +26,7 @@ data CaseDef = CaseDef [Name] !SC [Term]
24-- in the function `prune` as a means of optimisation
26-- in the function `prune` as a means of optimisation
25-- of already built case trees.
27-- of already built case trees.
27−-- While the intermediate representation (follows in the pipeline)
29+-- While the intermediate representation (follows in the pipeline, named LExp)
28-- allows casing on arbitrary terms, here we choose to maintain the distinction
30-- allows casing on arbitrary terms, here we choose to maintain the distinction
29-- in order to allow for better optimisation opportunities.
31-- in order to allow for better optimisation opportunities.
@@ -213,6 +215,11 @@ isUsed sc n = used sc where
213 usedA (SucCase _ sc) = used sc
215 usedA (SucCase _ sc) = used sc
214 usedA (DefaultCase sc) = used sc
216 usedA (DefaultCase sc) = used sc
218+type ErasureInfo = Name -> [Int] -- name to list of inaccessible arguments; empty list if name not found
219+type CaseBuilder a = ReaderT ErasureInfo (State CS) a
221+runCaseBuilder :: ErasureInfo -> CaseBuilder a -> (CS -> (a, CS))
222+runCaseBuilder ei bld = runState $ runReaderT bld ei
217data Phase = CompileTime | RunTime
224data Phase = CompileTime | RunTime
218 deriving (Show, Eq)
225 deriving (Show, Eq)
@@ -223,8 +230,9 @@ data Phase = CompileTime | RunTime
223simpleCase :: Bool -> Bool -> Bool ->
230simpleCase :: Bool -> Bool -> Bool ->
224 Phase -> FC -> [Int] -> [Type] ->
231 Phase -> FC -> [Int] -> [Type] ->
225 [([Name], Term, Term)] ->
232 [([Name], Term, Term)] ->
226 TC CaseDef
234 TC CaseDef
227−simpleCase tc cover reflect phase fc inacc argtys cs
235+simpleCase tc cover reflect phase fc inacc argtys cs erInfo
228 = sc' tc cover phase fc (filter (\(_, _, r) ->
236 = sc' tc cover phase fc (filter (\(_, _, r) ->
229 case r of
237 case r of
230 Impossible -> False
238 Impossible -> False
@@ -243,7 +251,7 @@ simpleCase tc cover reflect phase fc inacc argtys cs
243 let numargs = length (fst (head pats))
251 let numargs = length (fst (head pats))
244 ns = take numargs args
252 ns = take numargs args
245 (ns', ps') = order [(n, i `elem` inacc) | (i,n) <- zip [0..] ns] pats
253 (ns', ps') = order [(n, i `elem` inacc) | (i,n) <- zip [0..] ns] pats
246− (tree, st) = runState
254+ (tree, st) = runCaseBuilder erInfo
247 (match ns' ps' (defaultCase cover))
255 (match ns' ps' (defaultCase cover))
248 ([], numargs, [])
256 ([], numargs, [])
249 t = CaseDef ns (prune proj (depatt ns' tree)) (fstT st) in
257 t = CaseDef ns (prune proj (depatt ns' tree)) (fstT st) in
@@ -334,18 +342,20 @@ toPats reflect tc f = reverse (toPat reflect tc (getArgs f)) where
334 getArgs _ = []
342 getArgs _ = []
336toPat :: Bool -> Bool -> [Term] -> [Pat]
344toPat :: Bool -> Bool -> [Term] -> [Pat]
337−toPat reflect tc tms = evalState (mapM (\x -> toPat' x []) tms) []
345+toPat reflect tc = map $ toPat' []
339− toPat' (P (DCon t a) nm@(UN n) _) [_,_,arg]
347+ toPat' [_,_,arg](P (DCon t a) nm@(UN n) _)
340− | n == txt "Delay" = do arg' <- toPat' arg []
348+ | n == txt "Delay"
341− return $ PCon nm t [PAny, PAny, arg']
349+ = PCon nm t [PAny, PAny, toPat' [] arg]
342− toPat' (P (DCon t a) n _) args = do args' <- mapM (\x -> toPat' x []) args
351+ toPat' args (P (DCon t a) n _)
343− return $ PCon n t args'
352+ = PCon n t $ map (toPat' []) args
345− toPat' (P _ (UN pabi) _)
355+ toPat' [p, Constant (BI 1)] (P _ (UN pabi) _)
346− [p, Constant (BI 1)] | pabi == txt "prim__addBigInt"
356+ | pabi == txt "prim__addBigInt"
347− = do p' <- toPat' p []
357+ = PSuc $ toPat' [] p
348− return $ PSuc p'
358+
349 -- Typecase
359 -- Typecase
350-- toPat' (P (TCon t a) n _) args | tc
360-- toPat' (P (TCon t a) n _) args | tc
351-- = do args' <- mapM (\x -> toPat' x []) args
361-- = do args' <- mapM (\x -> toPat' x []) args
@@ -360,26 +370,25 @@ toPat reflect tc tms = evalState (mapM (\x -> toPat' x []) tms) []
360-- | tc = return $ PCon (UN "Integer") 6 []
370-- | tc = return $ PCon (UN "Integer") 6 []
361-- toPat' (Constant (AType (ATInt (ITFixed n)))) []
371-- toPat' (Constant (AType (ATInt (ITFixed n)))) []
362-- | tc = return $ PCon (UN (fixedN n)) (7 + fromEnum n) [] -- 7-10 inclusive
372-- | tc = return $ PCon (UN (fixedN n)) (7 + fromEnum n) [] -- 7-10 inclusive
363− toPat' (P Bound n ty) [] = -- trace (show (n, ty)) $
373+--
365− if n `elem` ns
375+ toPat' [] (P Bound n ty) = PV n ty
367− else do put (n : ns)
369− toPat' (App f a) args = toPat' f (a : args)
376+ toPat' args (App f a) = toPat' (a : args) f
370− toPat' (Constant (AType _)) [] = return PTyPat
377+ toPat' [] (Constant (AType _)) = PTyPat
371− toPat' (Constant StrType) [] = return PTyPat
378+ toPat' [] (Constant StrType) = PTyPat
372− toPat' (Constant PtrType) [] = return PTyPat
379+ toPat' [] (Constant PtrType) = PTyPat
373− toPat' (Constant VoidType) [] = return PTyPat
380+ toPat' [] (Constant VoidType) = PTyPat
374− toPat' (Constant x) [] = return $ PConst x
381+ toPat' [] (Constant x) = PConst x
383+ toPat' [] (Bind n (Pi t) sc)
375− toPat' (Bind n (Pi t) sc) [] | reflect && noOccurrence n sc
384+ | reflect && noOccurrence n sc
376− = do t' <- toPat' t []
378− return $ PReflected (sUN "->") (t':sc':[])
385+ = PReflected (sUN "->") [toPat' [] t, toPat' [] sc]
379− toPat' (P _ n _) args | reflect
387+ toPat' args (P _ n _)
380− = do args' <- mapM (\x -> toPat' x []) args
389+ = PReflected n $ map (toPat' []) args
381− return $ PReflected n args'
390+
382− toPat' t _ = return PAny
391+ toPat' _ t = PAny
384 fixedN IT8 = "Bits8"
393 fixedN IT8 = "Bits8"
385 fixedN IT16 = "Bits16"
394 fixedN IT16 = "Bits16"
@@ -459,7 +468,7 @@ order ns' cs = let patnames = transpose (map (zip ns') (map fst cs))
459 numNames xs [] = length xs
468 numNames xs [] = length xs
461match :: [Name] -> [Clause] -> SC -- error case
470match :: [Name] -> [Clause] -> SC -- error case
462− -> State CS SC
471+ -> CaseBuilder SC
463match [] (([], ret) : xs) err
472match [] (([], ret) : xs) err
464 = do (ts, v, ntys) <- get
473 = do (ts, v, ntys) <- get
465 put (ts ++ (map (fst.snd) xs), v, ntys)
474 put (ts ++ (map (fst.snd) xs), v, ntys)
@@ -469,13 +478,19 @@ match [] (([], ret) : xs) err
469match vs cs err = do let ps = partition cs
478match vs cs err = do let ps = partition cs
470 mixture vs ps err
479 mixture vs ps err
472−mixture :: [Name] -> [Partition] -> SC -> State CS SC
481+mixture :: [Name] -> [Partition] -> SC -> CaseBuilder SC
473mixture vs [] err = return err
482mixture vs [] err = return err
474mixture vs (Cons ms : ps) err = do fallthrough <- mixture vs ps err
483mixture vs (Cons ms : ps) err = do fallthrough <- mixture vs ps err
475 conRule vs ms fallthrough
484 conRule vs ms fallthrough
476mixture vs (Vars ms : ps) err = do fallthrough <- mixture vs ps err
485mixture vs (Vars ms : ps) err = do fallthrough <- mixture vs ps err
477 varRule vs ms fallthrough
486 varRule vs ms fallthrough
488+-- Return the list of inaccessible arguments of a data constructor.
489+inaccessibleArgs :: Name -> CaseBuilder [Int]
490+inaccessibleArgs n = do
491+ getInaccessiblePositions <- ask -- this function is the only thing in the environment
492+ return $ getInaccessiblePositions n
479data ConType = CName Name Int -- named constructor
494data ConType = CName Name Int -- named constructor
480 | CFn Name -- reflected function name
495 | CFn Name -- reflected function name
481 | CSuc -- n+1
496 | CSuc -- n+1
@@ -486,76 +501,99 @@ data Group = ConGroup ConType -- Constructor
486 [([Pat], Clause)] -- arguments and rest of alternative
501 [([Pat], Clause)] -- arguments and rest of alternative
487 deriving Show
502 deriving Show
489−conRule :: [Name] -> [Clause] -> SC -> State CS SC
504+conRule :: [Name] -> [Clause] -> SC -> CaseBuilder SC
490conRule (v:vs) cs err = do groups <- groupCons cs
505conRule (v:vs) cs err = do groups <- groupCons cs
491 caseGroups (v:vs) groups err
506 caseGroups (v:vs) groups err
493−caseGroups :: [Name] -> [Group] -> SC -> State CS SC
508+caseGroups :: [Name] -> [Group] -> SC -> CaseBuilder SC
494caseGroups (v:vs) gs err = do g <- altGroups gs
509caseGroups (v:vs) gs err = do g <- altGroups gs
495 return $ Case v (sort g)
510 return $ Case v (sort g)
497 altGroups [] = return [DefaultCase err]
512 altGroups [] = return [DefaultCase err]
498 altGroups (ConGroup (CName n i) args : cs)
514 altGroups (ConGroup (CName n i) args : cs)
499− = do g <- altGroup n i args
515+ = (:) <$> altGroup n i args <*> altGroups cs
500− rest <- altGroups cs
516+
502 altGroups (ConGroup (CFn n) args : cs)
517 altGroups (ConGroup (CFn n) args : cs)
503− = do g <- altFnGroup n args
518+ = (:) <$> altFnGroup n args <*> altGroups cs
504− rest <- altGroups cs
519+
506 altGroups (ConGroup CSuc args : cs)
520 altGroups (ConGroup CSuc args : cs)
507− = do g <- altSucGroup args
521+ = (:) <$> altSucGroup args <*> altGroups cs
508− rest <- altGroups cs
522+
510 altGroups (ConGroup (CConst c) args : cs)
523 altGroups (ConGroup (CConst c) args : cs)
511− = do g <- altConstGroup c args
524+ = (:) <$> altConstGroup c args <*> altGroups cs
512− rest <- altGroups cs
525+
513− return (g : rest)
526+ altGroup n i args = do inacc <- inaccessibleArgs n
514−
527+ (newVars, accVars, inaccVars, nextCs) <- argsToAlt inacc args
515− altGroup n i gs = do (newArgs, nextCs) <- argsToAlt gs
516− matchCs <- match (newArgs ++ vs) nextCs err
528+ matchCs <- match (accVars ++ vs ++ inaccVars) nextCs err
517− return $ ConCase n i newArgs matchCs
529+ return $ ConCase n i newVars matchCs
518− altFnGroup n gs = do (newArgs, nextCs) <- argsToAlt gs
531+ altFnGroup n args = do (newVars, _, [], nextCs) <- argsToAlt [] args
519− matchCs <- match (newArgs ++ vs) nextCs err
532+ matchCs <- match (newVars ++ vs) nextCs err
520− return $ FnCase n newArgs matchCs
533+ return $ FnCase n newVars matchCs
521− altSucGroup gs = do ([newArg], nextCs) <- argsToAlt gs
535+ altSucGroup args = do ([newVar], _, [], nextCs) <- argsToAlt [] args
522− matchCs <- match (newArg:vs) nextCs err
536+ matchCs <- match (newVar:vs) nextCs err
523− return $ SucCase newArg matchCs
537+ return $ SucCase newVar matchCs
524− altConstGroup n gs = do (_, nextCs) <- argsToAlt gs
539+ altConstGroup n args = do (_, _, [], nextCs) <- argsToAlt [] args
525− matchCs <- match vs nextCs err
540+ matchCs <- match vs nextCs err
526− return $ ConstCase n matchCs
541+ return $ ConstCase n matchCs
544+-- * names of all variables arising from match
545+-- * names of accessible variables (subset of all variables)
546+-- * names of inaccessible variables (subset of all variables)
547+-- * clauses corresponding to (accVars ++ origVars ++ inaccVars)
528−argsToAlt :: [([Pat], Clause)] -> State CS ([Name], [Clause])
548+argsToAlt :: [Int] -> [([Pat], Clause)] -> CaseBuilder ([Name], [Name], [Name], [Clause])
529−argsToAlt [] = return ([], [])
549+argsToAlt _ [] = return ([], [], [], [])
530−argsToAlt rs@((r, m) : rest)
550+argsToAlt inacc rs@((r, m) : rest) = do
531− = do newArgs <- getNewVars r
551+ newVars <- getNewVars r
552+ let (accVars, inaccVars) = partitionAcc newVars
532− return (newArgs, addRs rs)
553+ return (newVars, accVars, inaccVars, addRs rs)
555+ -- Create names for new variables arising from the given patterns.
556+ getNewVars :: [Pat] -> CaseBuilder [Name]
534 getNewVars [] = return []
557 getNewVars [] = return []
535 getNewVars ((PV n t) : ns) = do v <- getVar "e"
558 getNewVars ((PV n t) : ns) = do v <- getVar "e"
559+ nsv <- getNewVars ns
561+ -- Record the type of the variable.
563+ -- It seems that the ordering is not important
564+ -- and we can put (v,t) always in front of "ntys"
565+ -- (the varName-type pairs seem to represent a mapping).
567+ -- The code that reads this is currently
568+ -- commented out, anyway.
536 (cs, i, ntys) <- get
569 (cs, i, ntys) <- get
537 put (cs, i, (v, t) : ntys)
570 put (cs, i, (v, t) : ntys)
538− nsv <- getNewVars ns
571+
539 return (v : nsv)
572 return (v : nsv)
540− getNewVars (PAny : ns) = do v <- getVar "i"
574+ getNewVars (PAny : ns) = (:) <$> getVar "i" <*> getNewVars ns
541− nsv <- getNewVars ns
543− getNewVars (PTyPat : ns) = do v <- getVar "t"
575+ getNewVars (PTyPat : ns) = (:) <$> getVar "t" <*> getNewVars ns
544− nsv <- getNewVars ns
546− getNewVars (_ : ns) = do v <- getVar "e"
576+ getNewVars (_ : ns) = (:) <$> getVar "e" <*> getNewVars ns
547− nsv <- getNewVars ns
577+
548− return (v : nsv)
578+ -- Partition a list of things into (accessible, inaccessible) things,
579+ -- according to the list of inaccessible indices.
581+ ( [x | (i,x) <- zip [0..] xs, i `notElem` inacc]
582+ , [x | (i,x) <- zip [0..] xs, i `elem` inacc]
549 addRs [] = []
585 addRs [] = []
550− addRs ((r, (ps, res)) : rs) = ((r++ps, res) : addRs rs)
586+ addRs ((r, (ps, res)) : rs) = ((acc++ps++inacc, res) : addRs rs)
588+ (acc, inacc) = partitionAcc r
552 uniq i (UN n) = MN i n
590 uniq i (UN n) = MN i n
553 uniq i n = n
591 uniq i n = n
555−getVar :: String -> State CS Name
593+getVar :: String -> CaseBuilder Name
556getVar b = do (t, v, ntys) <- get; put (t, v+1, ntys); return (sMN v b)
594getVar b = do (t, v, ntys) <- get; put (t, v+1, ntys); return (sMN v b)
558−groupCons :: [Clause] -> State CS [Group]
596+groupCons :: [Clause] -> CaseBuilder [Group]
559groupCons cs = gc [] cs
597groupCons cs = gc [] cs
561 gc acc [] = return acc
599 gc acc [] = return acc
@@ -581,7 +619,7 @@ groupCons cs = gc [] cs
581-- | otherwise = g : addConG con res gs
619-- | otherwise = g : addConG con res gs
582 addConG con res (g : gs) = g : addConG con res gs
620 addConG con res (g : gs) = g : addConG con res gs
584−varRule :: [Name] -> [Clause] -> SC -> State CS SC
622+varRule :: [Name] -> [Clause] -> SC -> CaseBuilder SC
585varRule (v : vs) alts err =
623varRule (v : vs) alts err =
586 do alts' <- mapM (repVar v) alts
624 do alts' <- mapM (repVar v) alts
587 match vs alts' err
625 match vs alts' err