on master help sign in
Merge remote-tracking branch 'upstream/master' into typeSearch
commitd00053bf670e63a08d31433c211cf431f5f6e806 authorbmsherman <bmsherman@users.noreply.github.com> dateFri 30 May 2014, 17:55 (12 years ago) parent7395bde2a0056a
28 files changed+212−97
CHANGELOG+1 idris.cabal+3 libs/effects/Effect/Exception.idr+1−1 libs/effects/Effect/File.idr+5−5 libs/effects/Effect/Memory.idr+7−7 libs/effects/Effect/Random.idr+3−3 libs/effects/Effect/Select.idr+1−1 libs/effects/Effect/State.idr+3−3 libs/effects/Effect/StdIO.idr+4−4 libs/effects/Effect/System.idr+3−3 libs/effects/Effects.idr+22−8 libs/prelude/Builtins.idr+1−6 libs/prelude/Prelude/List.idr−7 libs/prelude/Prelude/Vect.idr+4 src/Idris/AbsSyntax.hs+5−3 src/Idris/AbsSyntaxTree.hs+4−2 src/Idris/Core/Elaborate.hs+4−2 src/Idris/Core/ProofState.hs+25−7 src/Idris/Core/Unify.hs+14−1 src/Idris/Coverage.hs+29−12 src/Idris/DeepSeq.hs+3−3 src/Idris/ElabDecls.hs+22−4 src/Idris/ElabTerm.hs+24−5 src/Idris/IBC.hs+10−8 src/Idris/Parser.hs+2−2 test/totality008/expected+1 test/totality008/run+3 test/totality008/totality008.idr+8
CHANGELOG+1
@@ -25,6 +25,7 @@ New in 0.9.13:
2525* Extend :addclause to add instance bodies as well as definitions
2626* Reverse parameters to BoundedList -- now matches Vect, and is easier to instantiate classes.
2727* Move foldl into Foldable so it can be overridden.
28+* Experimental :search REPL command for finding functions by type
2829
2930Internal changes
3031
idris.cabal+3
@@ -452,6 +452,9 @@ Extra-source-files:
452452 test/totality007/*.ipkg
453453 test/totality007/src/*.idr
454454 test/totality007/expected
455+ test/totality008/run
456+ test/totality008/*.idr
457+ test/totality008/expected
455458
456459 test/tutorial001/run
457460 test/tutorial001/*.idr
libs/effects/Effect/Exception.idr+1−1
@@ -27,7 +27,7 @@ EXCEPTION : Type -> EFFECT
2727EXCEPTION t = MkEff () (Exception t)
2828
2929raise : a -> { [EXCEPTION a ] } Eff m b
30−raise err = effect $ Raise err
30+raise err = call $ Raise err
3131
3232
3333
libs/effects/Effect/File.idr+5−5
@@ -107,27 +107,27 @@ open : Handler FileIO e =>
107107 -> { [FILE_IO ()] ==> [FILE_IO (if result
108108 then OpenFile m
109109 else ())] } Eff e Bool
110−open f m = effect $ Open f m
110+open f m = call $ Open f m
111111
112112
113113||| Close a file.
114114close : Handler FileIO e =>
115115 { [FILE_IO (OpenFile m)] ==> [FILE_IO ()] } Eff e ()
116−close = effect $ Close
116+close = call $ Close
117117
118118||| Read a line from the file.
119119readLine : Handler FileIO e =>
120120 { [FILE_IO (OpenFile Read)] } Eff e String
121−readLine = effect $ ReadLine
121+readLine = call $ ReadLine
122122
123123||| Write a line to a file.
124124writeLine : Handler FileIO e =>
125125 String -> { [FILE_IO (OpenFile Write)] } Eff e ()
126−writeLine str = effect $ WriteLine str
126+writeLine str = call $ WriteLine str
127127
128128||| End of file?
129129eof : Handler FileIO e =>
130130 { [FILE_IO (OpenFile Read)] } Eff e Bool
131−eof = effect $ EOF
131+eof = call $ EOF
132132
133133-- --------------------------------------------------------------------- [ EOF ]
libs/effects/Effect/Memory.idr+7−7
@@ -102,7 +102,7 @@ RAW_MEMORY t = MkEff t RawMemory
102102
103103allocate : (n : Nat) ->
104104 Eff m () [RAW_MEMORY ()] (\v => [RAW_MEMORY (MemoryChunk n 0)])
105−allocate size = effect $ Allocate size
105+allocate size = call $ Allocate size
106106
107107initialize : {i : Nat} ->
108108 {n : Nat} ->
@@ -111,17 +111,17 @@ initialize : {i : Nat} ->
111111 so (i + size <= n) ->
112112 Eff m () [RAW_MEMORY (MemoryChunk n i)]
113113 (\v => [RAW_MEMORY (MemoryChunk n (i + size))])
114−initialize c size prf = effect $ Initialize c size prf
114+initialize c size prf = call $ Initialize c size prf
115115
116116free : Eff m () [RAW_MEMORY (MemoryChunk n i)] (\v => [RAW_MEMORY ()])
117−free = effect Free
117+free = call Free
118118
119119peek : {i : Nat} ->
120120 (offset : Nat) ->
121121 (size : Nat) ->
122122 so (offset + size <= i) ->
123123 { [RAW_MEMORY (MemoryChunk n i)] } Eff m (Vect size Bits8)
124−peek offset size prf = effect $ Peek offset size prf
124+peek offset size prf = call $ Peek offset size prf
125125
126126poke : {n : Nat} ->
127127 {i : Nat} ->
@@ -130,11 +130,11 @@ poke : {n : Nat} ->
130130 so (offset <= i && offset + size <= n) ->
131131 Eff m () [RAW_MEMORY (MemoryChunk n i)]
132132 (\v => [RAW_MEMORY (MemoryChunk n (max i (offset + size)))])
133−poke offset content prf = effect $ Poke offset content prf
133+poke offset content prf = call $ Poke offset content prf
134134
135135private
136136getRawPtr : { [RAW_MEMORY (MemoryChunk n i)] } Eff m (MemoryChunk n i)
137−getRawPtr = effect $ GetRawPtr
137+getRawPtr = call $ GetRawPtr
138138
139139private
140140move' : {dst_size : Nat} ->
@@ -149,7 +149,7 @@ move' : {dst_size : Nat} ->
149149 Eff m () [RAW_MEMORY (MemoryChunk dst_size dst_init)]
150150 (\v => [RAW_MEMORY (MemoryChunk dst_size (max dst_init (dst_offset + size)))])
151151move' src_ptr dst_offset src_offset size dst_bounds src_bounds
152− = effect $ Move src_ptr dst_offset src_offset size dst_bounds src_bounds
152+ = call $ Move src_ptr dst_offset src_offset size dst_bounds src_bounds
153153
154154data MoveDescriptor = Dst | Src
155155
libs/effects/Effect/Random.idr+3−3
@@ -18,14 +18,14 @@ RND = MkEff Integer Random
1818
1919||| Generates a random Integer in a given range
2020rndInt : Integer -> Integer -> { [RND] } Eff m Integer
21−rndInt lower upper = do v <- effect $ getRandom
21+rndInt lower upper = do v <- call $ getRandom
2222 return (v `prim__sremBigInt` (upper - lower) + lower)
2323
2424||| Generate a random number in Fin (S `k`)
2525|||
2626||| Note that rndFin k takes values 0, 1, ..., k.
2727rndFin : (k : Nat) -> { [RND] } Eff m (Fin (S k))
28−rndFin k = do let v = assert_total $ !(effect getRandom) `prim__sremBigInt` (cast (S k))
28+rndFin k = do let v = assert_total $ !(call getRandom) `prim__sremBigInt` (cast (S k))
2929 return (toFin v)
3030 where toFin : Integer -> Fin (S k)
3131 toFin x = case integerToFin x (S k) of
@@ -43,5 +43,5 @@ rndSelect (x::xs) = return (Just !(rndSelect' (x::(fromList xs))))
4343
4444||| Sets the random seed
4545srand : Integer -> { [RND] } Eff m ()
46−srand n = effect $ setSeed n
46+srand n = call $ setSeed n
4747
libs/effects/Effect/Select.idr+1−1
@@ -19,5 +19,5 @@ SELECT : EFFECT
1919SELECT = MkEff () Selection
2020
2121select : List a -> { [SELECT] } Eff m a
22−select xs = effect $ Select xs
22+select xs = call $ Select xs
2323
libs/effects/Effect/State.idr+3−3
@@ -17,13 +17,13 @@ STATE : Type -> EFFECT
1717STATE t = MkEff t State
1818
1919get : { [STATE x] } Eff m x
20−get = effect $ Get
20+get = call $ Get
2121
2222put : x -> { [STATE x] } Eff m ()
23−put val = effect $ Put val
23+put val = call $ Put val
2424
2525putM : y -> { [STATE x] ==> [STATE y] } Eff m ()
26−putM val = effect $ Put val
26+putM val = call $ Put val
2727
2828update : (x -> x) -> { [STATE x] } Eff m ()
2929update f = put (f !get)
libs/effects/Effect/StdIO.idr+4−4
@@ -40,11 +40,11 @@ STDIO = MkEff () StdIO
4040
4141||| Write a string to standard output.
4242putStr : Handler StdIO e => String -> { [STDIO] } Eff e ()
43−putStr s = effect $ PutStr s
43+putStr s = call $ PutStr s
4444
4545||| Write a character to standard output.
4646putChar : Handler StdIO e => Char -> { [STDIO] } Eff e ()
47−putChar c = effect $ PutCh c
47+putChar c = call $ PutCh c
4848
4949||| Write a string to standard output, terminating with a newline.
5050putStrLn : Handler StdIO e => String -> { [STDIO] } Eff e ()
@@ -52,9 +52,9 @@ putStrLn s = putStr (s ++ "\n")
5252
5353||| Read a string from standard input.
5454getStr : Handler StdIO e => { [STDIO] } Eff e String
55−getStr = effect $ GetStr
55+getStr = call $ GetStr
5656
5757||| Read a character from standard input.
5858getChar : Handler StdIO e => { [STDIO] } Eff e Char
59−getChar = effect $ GetCh
59+getChar = call $ GetCh
6060
libs/effects/Effect/System.idr+3−3
@@ -28,11 +28,11 @@ SYSTEM : EFFECT
2828SYSTEM = MkEff () System
2929
3030getArgs : Handler System e => { [SYSTEM] } Eff e (List String)
31−getArgs = effect Args
31+getArgs = call Args
3232
3333time : Handler System e => { [SYSTEM] } Eff e Int
34−time = effect Time
34+time = call Time
3535
3636getEnv : Handler System e => String -> { [SYSTEM] } Eff e (Maybe String)
37−getEnv s = effect $ GetEnv s
37+getEnv s = call $ GetEnv s
3838
libs/effects/Effects.idr+22−8
@@ -144,7 +144,7 @@ data Eff : (m : Type -> Type)
144144 Eff m a xs xs'
145145 ebind : Eff m a xs xs' ->
146146 ((val : a) -> Eff m b (xs' val) xs'') -> Eff m b xs xs''
147− effectP : (prf : EffElem e a xs) ->
147+ callP : (prf : EffElem e a xs) ->
148148 (eff : e t a b) ->
149149 Eff m t xs (\v => updateResTy v xs prf eff)
150150
@@ -166,6 +166,20 @@ data Eff : (m : Type -> Type)
166166 ((val : a) -> Eff m b (xs' val) xs'') -> Eff m b xs xs''
167167(>>=) = ebind
168168
169+-- namespace SimpleBind
170+-- (>>=) : Eff m a xs (\v => xs) ->
171+-- ((val : a) -> Eff m b xs xs') -> Eff m b xs xs'
172+-- (>>=) = ebind
173+
174+||| Run a subprogram which results in an effect state the same as the input.
175+staticEff : Eff m a xs (\v => xs) -> Eff m a xs (\v => xs)
176+staticEff = id
177+
178+||| Explicitly give the expected set of result effects for an effectful
179+||| operation.
180+toEff : .(xs' : List EFFECT) -> Eff m a xs (\v => xs') -> Eff m a xs (\v => xs')
181+toEff xs' = id
182+
169183return : a -> Eff m a xs (\v => xs)
170184return x = value x
171185
@@ -204,7 +218,7 @@ eff env (value x) k = k x env
204218eff env (with_val x prog) k = eff env prog (\p', env' => k x env')
205219eff env (prog `ebind` c) k
206220 = eff env prog (\p', env' => eff env' (c p') k)
207−eff env (effectP prf effP) k = execEff env prf effP k
221+eff env (callP prf effP) k = execEff env prf effP k
208222eff env (liftP prf effP) k
209223 = let env' = dropEnv env prf in
210224 eff env' effP (\p', envk => k p' (rebuildEnv envk prf env))
@@ -233,12 +247,12 @@ syntax MkDefaultEnv = with Env
233247 [default, default, default, default, default, default, default],
234248 [default, default, default, default, default, default, default, default] |)
235249
236−effect : {a, b: _} -> {e : Effect} ->
237− (eff : e t a b) ->
238− {default tactics { search 100; }
239− prf : EffElem e a xs} ->
240− Eff m t xs (\v => updateResTy v xs prf eff)
241−effect e {prf} = effectP prf e
250+call : {a, b: _} -> {e : Effect} ->
251+ (eff : e t a b) ->
252+ {default tactics { search 100; }
253+ prf : EffElem e a xs} ->
254+ Eff m t xs (\v => updateResTy v xs prf eff)
255+call e {prf} = callP prf e
242256
243257implicit
244258lift : Eff m t ys ys' ->
libs/prelude/Builtins.idr+1−6
@@ -38,17 +38,12 @@ sym refl = refl
3838trans : {a:x} -> {b:y} -> {c:z} -> a = b -> b = c -> a = c
3939trans refl refl = refl
4040
41−lazy : a -> a
42−lazy x = x -- compiled specially
43−
44−force : a -> a
45−force x = x -- compiled specially
46−
4741||| There are two types of laziness: that arising from lazy functions, and that
4842||| arising from codata. They differ in their totality condition.
4943data LazyType = LazyCodata | LazyEval
5044
5145||| The underlying implementation of Lazy and Inf.
46+%error_reverse
5247data Lazy' : LazyType -> Type -> Type where
5348 ||| A delayed computation.
5449 |||
libs/prelude/Prelude/List.idr−7
@@ -195,13 +195,6 @@ list nil cons (x::xs) = (Force cons) x xs
195195(++) [] right = right
196196(++) (x::xs) right = x :: (xs ++ right)
197197
198−||| Create an infinite sequence of some item.
199−|||
200−||| Consider using a `Stream` instead.
201−partial
202−repeat : a -> List a
203−repeat x = x :: lazy (repeat x)
204−
205198||| Construct a list with `n` copies of `x`
206199||| @ n how many copies
207200||| @ x the element to replicate
libs/prelude/Prelude/Vect.idr+4
@@ -254,6 +254,10 @@ concat : Vect m (Vect n a) -> Vect (m * n) a
254254concat [] = []
255255concat (v::vs) = v ++ concat vs
256256
257+||| Fold without seeding the accumulator
258+foldr1 : (t -> t -> t) -> Vect (S n) t -> t
259+foldr1 f (x::xs) = foldr f x xs
260+
257261--------------------------------------------------------------------------------
258262-- Scans
259263--------------------------------------------------------------------------------
src/Idris/AbsSyntax.hs+5−3
@@ -1329,9 +1329,11 @@ addImpl' inpat env infns ist ptm
13291329 as' = map (fmap (ai env ds)) as in
13301330 mkPApp fc 1 f' as'
13311331 ai env ds (PCase fc c os)
1332− = let c' = ai env ds c
1333− os' = map (pmap (ai env ds)) os in
1334− PCase fc c' os'
1332+ = let c' = ai env ds c in
1333+ -- leave os alone, because they get lifted into a new pattern match
1334+ -- definition which is passed through addImpl again with more scope
1335+ -- information
1336+ PCase fc c' os
13351337 ai env ds (PLam n ty sc)
13361338 = let ty' = ai env ds ty
13371339 sc' = ai ((n, Just ty):env) ds sc in
src/Idris/AbsSyntaxTree.hs+4−2
@@ -884,7 +884,8 @@ deriving instance NFData OptInfo
884884data TypeInfo = TI { con_names :: [Name],
885885 codata :: Bool,
886886 data_opts :: DataOpts,
887− param_pos :: [Int] }
887+ param_pos :: [Int],
888+ mutual_types :: [Name] }
888889 deriving Show
889890{-!
890891deriving instance Binary TypeInfo
@@ -963,6 +964,7 @@ data SyntaxInfo = Syn { using :: [Using],
963964 inPattern :: Bool,
964965 implicitAllowed :: Bool,
965966 maxline :: Maybe Int,
967+ mut_nesting :: Int,
966968 dsl_info :: DSL }
967969 deriving Show
968970{-!
@@ -970,7 +972,7 @@ deriving instance NFData SyntaxInfo
970972deriving instance Binary SyntaxInfo
971973!-}
972974
973−defaultSyntax = Syn [] [] [] [] id False False Nothing initDSL
975+defaultSyntax = Syn [] [] [] [] id False False Nothing 0 initDSL
974976
975977expandNS :: SyntaxInfo -> Name -> Name
976978expandNS syn n@(NS _ _) = n
src/Idris/Core/Elaborate.hs+4−2
@@ -681,11 +681,13 @@ try' :: Elab' aux a -> Elab' aux a -> Bool -> Elab' aux a
681681try' t1 t2 proofSearch
682682 = do s <- get
683683 ps <- get_probs
684+ ulog <- getUnifyLog
684685 case prunStateT 999999 False ps t1 s of
685686 OK ((v, _, _), s') -> do put s'
686687 return $! v
687− Error e1 -> if recoverableErr e1 then
688− do case runStateT t2 s of
688+ Error e1 -> traceWhen ulog ("try failed " ++ show e1) $
689+ if recoverableErr e1 then
690+ do case runStateT t2 s of
689691 OK (v, s') -> do put s'; return $! v
690692 Error e2 -> if score e1 >= score e2
691693 then lift (tfail e1)
src/Idris/Core/ProofState.hs+25−7
@@ -180,6 +180,19 @@ match_unify' ctxt env topx topy =
180180-- -- ++ show (pterm ps)
181181-- ++ "\n----------") $
182182
183+mergeSolutions :: Env -> [(Name, TT Name)] -> StateT TState TC [(Name, TT Name)]
184+mergeSolutions env ns = merge [] ns
185+ where
186+ merge acc [] = return (reverse acc)
187+ merge acc ((n, t) : ns)
188+ | Just t' <- lookup n ns
189+ = do ps <- get
190+ let probs = problems ps
191+ put (ps { problems = probs ++ [(t,t',env,Msg "New problem",
192+ [], Unify)] })
193+ merge acc ns
194+ | otherwise = merge ((n, t): acc) ns
195+
183196unify' :: Context -> Env -> TT Name -> TT Name ->
184197 StateT TState TC [(Name, TT Name)]
185198unify' ctxt env topx topy =
@@ -206,17 +219,22 @@ unify' ctxt env topx topy =
206219 ++ "\nCurrent problems:\n" ++ qshow (problems ps)
207220-- ++ show (pterm ps)
208221 ++ "\n----------") $
209− do ps <- get
210− let (h, ns) = unified ps
211− let (ns', probs') = updateProblems (context ps) (u ++ ns)
222+ do let (h, ns) = unified ps
223+ -- if a metavar has multiple solutions, make a new unification
224+ -- problem for each.
225+ uns <- mergeSolutions env (u ++ ns)
226+ ps <- get
227+ let (ns', probs') = updateProblems (context ps) uns
212228 (fails ++ problems ps)
213229 (injective ps)
214230 (holes ps)
215231 let (notu', probs_notu) = mergeNotunified env (notu ++ notunified ps)
216− put (ps { problems = probs' ++ probs_notu,
217− unified = (h, ns'),
218− injective = updateInj u (injective ps),
219− notunified = notu' })
232+ traceWhen (unifylog ps)
233+ ("Now solved: " ++ show ns') $
234+ put (ps { problems = probs' ++ probs_notu,
235+ unified = (h, ns'),
236+ injective = updateInj u (injective ps),
237+ notunified = notu' })
220238 return u
221239 where updateInj ((n, a) : us) inj
222240 | (P _ n' _, _) <- unApply a,
src/Idris/Core/Unify.hs+14−1
@@ -69,7 +69,20 @@ match_unify ctxt env topx topy inj holes from =
6969 return (map (renameBinders env) (trimSolutions v))
7070 _ -> tfail e
7171 where
72−
72+ -- This rule is highly dubious... it certainly produces a valid answer
73+ -- but it scares me. However, matching is never guaranteed to give a unique
74+ -- answer, merely a valid one, so perhaps we're okay.
75+ -- In other words: it may vanish without warning some day :)
76+ un names x tm@(App (P _ f (Bind fn (Pi t) sc)) a)
77+ | (P (DCon _ _) _ _, _) <- unApply x,
78+ holeIn env f || f `elem` holes
79+ = let n' = uniqueName (sMN 0 "mv") (map fst env) in
80+ checkCycle names (f, Bind n' (Lam t) x)
81+ un names tm@(App (P _ f (Bind fn (Pi t) sc)) a) x
82+ | (P (DCon _ _) _ _, _) <- unApply x,
83+ holeIn env f || f `elem` holes
84+ = let n' = uniqueName fn (map fst env) in
85+ checkCycle names (f, Bind n' (Lam t) x)
7386
7487 un names (P _ x _) tm
7588 | holeIn env x || x `elem` holes
src/Idris/Coverage.hs+29−12
@@ -211,7 +211,7 @@ genAll i args
211211 let p = resugar (PApp fc (PRef fc n) (zipWith upd xs' xs))
212212 let tyn = getTy n (tt_ctxt i)
213213 case lookupCtxt tyn (idris_datatypes i) of
214− (TI ns _ _ _ : _) -> p : map (mkPat fc) (ns \\ [n])
214+ (TI ns _ _ _ _ : _) -> p : map (mkPat fc) (ns \\ [n])
215215 _ -> [p]
216216 ops fc n arg o = return Placeholder
217217
@@ -265,29 +265,38 @@ checkAllCovering fc done top n | not (n `elem` done)
265265 x -> return () -- stop if total
266266checkAllCovering _ _ _ _ = return ()
267267
268−-- Check if, in a given type n, the constructor cn : ty is strictly positive,
268+-- Check if, in a given group of type declarations mut_ns,
269+-- the constructor cn : ty is strictly positive,
269270-- and update the context accordingly
270271
271−checkPositive :: Name -> (Name, Type) -> Idris ()
272−checkPositive n (cn, ty')
273− = do let ty = delazy ty'
272+checkPositive :: [Name] -> (Name, Type) -> Idris Totality
273+checkPositive mut_ns (cn, ty')
274+ = do let ty = delazy' True ty'
274275 let p = cp ty
275276 i <- getIState
276277 let tot = if p then Total (args ty) else Partial NotPositive
277278 let ctxt' = setTotal cn tot (tt_ctxt i)
278279 putIState (i { tt_ctxt = ctxt' })
279− logLvl 5 $ "Constructor " ++ show cn ++ " is " ++ show tot
280+ logLvl 5 $ "Constructor " ++ show cn ++ " is " ++ show tot ++ " with " ++ show mut_ns
280281 addIBC (IBCTotal cn tot)
282+ return tot
281283 where
282284 args t = [0..length (getArgTys t)-1]
283285
284286 cp (Bind n (Pi aty) sc) = posArg aty && cp sc
285− cp t = True
287+ cp t | (P _ n' _, args) <- unApply t,
288+ n' `elem` mut_ns = all noRec args
289+ cp _ = True
286290
287291 posArg (Bind _ (Pi nty) sc)
288292 | (P _ n' _, args) <- unApply nty
289− = n /= n' && posArg sc
290− posArg t = True
293+ = n' `notElem` mut_ns && all noRec args && posArg sc
294+ posArg t | (P _ n' _, args) <- unApply t,
295+ n' `elem` mut_ns = all noRec args
296+ posArg _ = True
297+
298+ noRec arg = all (\x -> x `notElem` mut_ns) (allTTNames arg)
299+
291300
292301calcProd :: IState -> FC -> Name -> [([Name], Term, Term)] -> Idris Totality
293302calcProd i fc topn pats
@@ -335,7 +344,7 @@ calcProd i fc topn pats
335344 cotype (DCon _ _) n ty
336345 | (P _ t _, _) <- unApply (getRetTy ty)
337346 = case lookupCtxt t (idris_datatypes i) of
338− [TI _ True _ _] -> True
347+ [TI _ True _ _ _] -> True
339348 _ -> False
340349 cotype nt n ty = False
341350
@@ -383,6 +392,14 @@ checkTotality path fc n
383392 setTotality n t'
384393 addIBC (IBCTotal n t')
385394 return t'
395+ [TyDecl (DCon _ _) ty] ->
396+ case unApply (getRetTy ty) of
397+ (P _ tyn _, _) -> do
398+ let ms = case lookupCtxt tyn (idris_datatypes i) of
399+ [TI _ _ _ _ xs@(_:_)] -> xs
400+ ts -> [tyn]
401+ checkPositive ms (n, ty)
402+ _-> return $ Total []
386403 _ -> return $ Total []
387404 x -> return x
388405 case t' of
@@ -556,7 +573,7 @@ buildSCG' ist pats args = nub $ concatMap scgPat pats where
556573
557574 isInductive (P _ nty _) (P _ nty' _) =
558575 let co = case lookupCtxt nty (idris_datatypes ist) of
559− [TI _ x _ _] -> x
576+ [TI _ x _ _ _] -> x
560577 _ -> False in
561578 nty == nty' && not co
562579 isInductive _ _ = False
@@ -639,7 +656,7 @@ checkMP ist i mp = if i > 0
639656 = case lookupTotal f (tt_ctxt ist) of
640657 [Total _] -> Unchecked -- okay so far
641658 [Partial _] -> Partial (Other [f])
642− x -> error (show x)
659+ x -> error $ "CAN'T HAPPEN: " ++ (show x)
643660 | [TyDecl (TCon _ _) _] <- lookupDef f (tt_ctxt ist)
644661 = Total []
645662 tryPath desc path (e@(f, args) : es) arg
src/Idris/DeepSeq.hs+3−3
@@ -290,7 +290,7 @@ instance NFData OptInfo where
290290 = rnf x1 `seq` rnf x2 `seq` ()
291291
292292instance NFData TypeInfo where
293− rnf (TI x1 x2 x3 x4) = rnf x1 `seq` rnf x2 `seq` rnf x3 `seq` rnf x4 `seq` ()
293+ rnf (TI x1 x2 x3 x4 x5) = rnf x1 `seq` rnf x2 `seq` rnf x3 `seq` rnf x4 `seq` rnf x5 `seq` ()
294294
295295instance (NFData t) => NFData (DSL' t) where
296296 rnf (DSL x1 x2 x3 x4 x5 x6 x7 x8 x9)
@@ -321,11 +321,11 @@ instance NFData Using where
321321
322322
323323instance NFData SyntaxInfo where
324− rnf (Syn x1 x2 x3 x4 x5 x6 x7 x8 x9)
324+ rnf (Syn x1 x2 x3 x4 x5 x6 x7 x8 x9 x10)
325325 = rnf x1 `seq`
326326 rnf x2 `seq`
327327 rnf x3 `seq`
328− rnf x4 `seq` rnf x5 `seq` rnf x6 `seq` rnf x7 `seq` rnf x8 `seq` rnf x9 `seq` ()
328+ rnf x4 `seq` rnf x5 `seq` rnf x6 `seq` rnf x7 `seq` rnf x8 `seq` rnf x9 `seq` rnf x10 `seq` ()
329329
330330
331331
src/Idris/ElabDecls.hs+22−4
@@ -125,7 +125,7 @@ elabType' norm info syn doc argDocs fc opts n ty' = {- let ty' = piBind (params
125125 let (t, _) = unApply (getRetTy nty')
126126 let corec = case t of
127127 P _ rcty _ -> case lookupCtxt rcty (idris_datatypes i) of
128− [TI _ True _ _] -> True
128+ [TI _ True _ _ _] -> True
129129 _ -> False
130130 _ -> False
131131 -- Productivity checking now via checking for guarded 'Delay'
@@ -256,8 +256,10 @@ elabData info syn doc argDocs fc opts (PDatadecl n t_in dcons)
256256 let as = map (const Nothing) (getArgTys cty)
257257 let params = findParams (map snd cons)
258258 logLvl 2 $ "Parameters : " ++ show params
259+ -- TI contains information about mutually declared types - this will
260+ -- be updated when the mutual block is complete
259261 putIState (i { idris_datatypes =
260− addDef n (TI (map fst cons) codata opts params)
262+ addDef n (TI (map fst cons) codata opts params [n])
261263 (idris_datatypes i) })
262264 addIBC (IBCDef n)
263265 addIBC (IBCData n)
@@ -269,7 +271,8 @@ elabData info syn doc argDocs fc opts (PDatadecl n t_in dcons)
269271 -- TMP HACK! Make this a data option
270272 updateContext (addDatatype (Data n ttag cty cons))
271273 updateContext (setMetaInformation n metainf)
272− mapM_ (checkPositive n) cons
274+ mapM_ totcheck (zip (repeat fc) (map fst cons))
275+-- mapM_ (checkPositive n) cons
273276
274277 -- if there's exactly one constructor,
275278 -- mark both the type and the constructor as detaggable
@@ -1617,7 +1620,7 @@ elabClause info opts (cnum, PClause fc fname lhs_in withs rhs_in whereblock)
16171620 rev <- case ret_fam of
16181621 P _ rfamn _ ->
16191622 case lookupCtxt rfamn (idris_datatypes i) of
1620− [TI _ _ dopts _] ->
1623+ [TI _ _ dopts _ _] ->
16211624 return (DataErrRev `elem` dopts)
16221625 _ -> return False
16231626 _ -> return False
@@ -2340,6 +2343,11 @@ elabDecl' what info (PMutual f ps)
23402343 [p] -> elabDecl what info p
23412344 _ -> do mapM_ (elabDecl ETypes info) ps
23422345 mapM_ (elabDecl EDefns info) ps
2346+ -- record mutually defined data definitions
2347+ let datans = concatMap declared (filter isDataDecl ps)
2348+ mapM_ (setMutData datans) datans
2349+ iLOG $ "Rechecking for positivity " ++ show datans
2350+ mapM_ (\x -> do setTotality x Unchecked) datans
23432351 -- Do totality checking after entire mutual block
23442352 i <- get
23452353 mapM_ (\n -> do logLvl 5 $ "Simplifying " ++ show n
@@ -2348,6 +2356,16 @@ elabDecl' what info (PMutual f ps)
23482356 mapM_ buildSCG (idris_totcheck i)
23492357 mapM_ checkDeclTotality (idris_totcheck i)
23502358 clear_totcheck
2359+ where isDataDecl (PData _ _ _ _ _ _) = True
2360+ isDataDecl _ = False
2361+
2362+ setMutData ns n
2363+ = do i <- getIState
2364+ case lookupCtxt n (idris_datatypes i) of
2365+ [x] -> do let x' = x { mutual_types = ns }
2366+ putIState $ i { idris_datatypes
2367+ = addDef n x' (idris_datatypes i) }
2368+ _ -> return ()
23512369
23522370elabDecl' what info (PParams f ns ps)
23532371 = do i <- getIState
src/Idris/ElabTerm.hs+24−5
@@ -66,9 +66,11 @@ build ist info pattern opts fn tm
6666 ctxt <- get_context
6767 probs <- get_probs
6868 u <- getUnifyLog
69+ hs <- get_holes
6970
7071 when (not pattern) $
71− traceWhen u ("Remaining problems:\n" ++ show probs) $
72+ traceWhen u ("Remaining holes:\n" ++ show hs ++ "\n" ++
73+ "Remaining problems:\n" ++ show probs) $
7274 do unify_all; matchProblems True; unifyProblems
7375
7476 probs <- get_probs
@@ -265,7 +267,8 @@ elab ist info pattern opts fn tm
265267 ty <- goal
266268 ctxt <- get_context
267269 let (tc, _) = unApply ty
268− let as' = pruneByType tc ctxt as
270+ env <- get_env
271+ let as' = pruneByType (map fst env) tc ctxt as
269272-- trace (show as ++ "\n ==> " ++ showSep ", " (map showTmImpls as')) $
270273 tryAll (zip (map (elab' ina) as') (map showHd as'))
271274 where showHd (PApp _ (PRef _ n) _) = show n
@@ -695,6 +698,9 @@ elab ist info pattern opts fn tm
695698 addImpl ist (PApp fc (PRef fc (sUN "Delay"))
696699 [pexp t])
697700
701+ -- case is tricky enough without implicit coercions! If they are needed,
702+ -- they can go in the branches separately.
703+ insertCoerce ina t@(PCase _ _ _) = return t
698704 insertCoerce ina t =
699705 do ty <- goal
700706 -- Check for possible coercions to get to the goal
@@ -785,8 +791,21 @@ pruneAlt xs = map prune xs
785791
786792-- Rule out alternatives that don't return the same type as the head of the goal
787793-- (If there are none left as a result, do nothing)
788−pruneByType :: Term -> Context -> [PTerm] -> [PTerm]
789−pruneByType (P _ n _) c as
794+pruneByType :: [Name] -> Term -> Context -> [PTerm] -> [PTerm]
795+-- if an alternative has a locally bound name at the head, take it
796+pruneByType env t c as
797+ | Just a <- locallyBound as = [a]
798+ where
799+ locallyBound [] = Nothing
800+ locallyBound (t:ts)
801+ | Just n <- getName t,
802+ n `elem` env = Just t
803+ | otherwise = locallyBound ts
804+ getName (PRef _ n) = Just n
805+ getName (PApp _ f _) = getName f
806+ getName _ = Nothing
807+
808+pruneByType env (P _ n _) c as
790809-- if the goal type is polymorphic, keep e
791810 | [] <- lookupTy n c = as
792811 | otherwise
@@ -812,7 +831,7 @@ pruneByType (P _ n _) c as
812831 _ -> False
813832 _ -> False
814833
815−pruneByType t _ as = as
834+pruneByType _ t _ as = as
816835
817836findInstances :: IState -> Term -> [Name]
818837findInstances ist t
src/Idris/IBC.hs+10−8
@@ -30,7 +30,7 @@ import Codec.Compression.Zlib (compress)
3030import Util.Zlib (decompressEither)
3131
3232ibcVersion :: Word8
33−ibcVersion = 73
33+ibcVersion = 74
3434
3535data IBCFile = IBCFile { ver :: Word8,
3636 sourcefile :: FilePath,
@@ -1582,7 +1582,7 @@ instance Binary Using where
15821582 1 -> do x1 <- get; x2 <- get; return (UConstraint x1 x2)
15831583
15841584instance Binary SyntaxInfo where
1585− put (Syn x1 x2 x3 x4 _ x5 x6 _ x7)
1585+ put (Syn x1 x2 x3 x4 _ x5 x6 _ _ x7)
15861586 = do put x1
15871587 put x2
15881588 put x3
@@ -1598,7 +1598,7 @@ instance Binary SyntaxInfo where
15981598 x5 <- get
15991599 x6 <- get
16001600 x7 <- get
1601− return (Syn x1 x2 x3 x4 id x5 x6 Nothing x7)
1601+ return (Syn x1 x2 x3 x4 id x5 x6 Nothing 0 x7)
16021602
16031603instance (Binary t) => Binary (PClause' t) where
16041604 put x
@@ -2152,15 +2152,17 @@ instance Binary OptInfo where
21522152 return (Optimise x1 x2)
21532153
21542154instance Binary TypeInfo where
2155− put (TI x1 x2 x3 x4) = do put x1
2156− put x2
2157− put x3
2158− put x4
2155+ put (TI x1 x2 x3 x4 x5) = do put x1
2156+ put x2
2157+ put x3
2158+ put x4
2159+ put x5
21592160 get = do x1 <- get
21602161 x2 <- get
21612162 x3 <- get
21622163 x4 <- get
2163− return (TI x1 x2 x3 x4)
2164+ x5 <- get
2165+ return (TI x1 x2 x3 x4 x5)
21642166
21652167instance Binary SynContext where
21662168 put x
src/Idris/Parser.hs+2−2
@@ -163,7 +163,7 @@ decl syn = do fc <- getFC
163163 let continue = case maxline syn of
164164 Nothing -> True
165165 Just l -> if fst (fc_end fc) > l
166− then False
166+ then mut_nesting syn /= 0
167167 else True
168168 if continue then do notEndBlock
169169 declBody
@@ -502,7 +502,7 @@ mutual syn =
502502 do reserved "mutual"
503503 openBlock
504504 let pvars = syn_params syn
505− ds <- many (decl syn)
505+ ds <- many (decl (syn { mut_nesting = mut_nesting syn + 1 } ))
506506 closeBlock
507507 fc <- getFC
508508 return [PMutual fc (concat ds)]
test/totality008/expectednew file+1
@@ -0,0 +1 @@
1+totality008.idr:7:1:Main.ElimT is possibly not total due to: Main.c2
test/totality008/runnew file+3
@@ -0,0 +1,3 @@
1+#!/usr/bin/env bash
2+idris $@ totality008.idr --check
3+rm -f *.ibc
test/totality008/totality008.idrnew file+8
@@ -0,0 +1,8 @@
1+ data T : Type -> Type where
2+ c1 : T Nat
3+ c2 : T (T Nat)
4+
5+total
6+ElimT : (A : Type) -> T A -> A
7+ElimT _ c1 = 3
8+ElimT _ c2 = c1