@@ -11,7 +11,7 @@ Maintainer : The Idris Community.
12module Idris.Core.Evaluate(normalise, normaliseTrace, normaliseC,
12module Idris.Core.Evaluate(normalise, normaliseTrace, normaliseC,
13 normaliseAll, normaliseBlocking, toValue, quoteTerm,
13 normaliseAll, normaliseBlocking, toValue, quoteTerm,
14− rt_simplify, simplify, specialise, hnf, convEq, convEq',
14+ rt_simplify, simplify, specialise, unfold, convEq, convEq',
15 Def(..), CaseInfo(..), CaseDefs(..),
15 Def(..), CaseInfo(..), CaseDefs(..),
16 Accessibility(..), Injectivity, Totality(..), PReason(..), MetaInformation(..),
16 Accessibility(..), Injectivity, Totality(..), PReason(..), MetaInformation(..),
17 Context, initContext, ctxtAlist, next_tvar,
17 Context, initContext, ctxtAlist, next_tvar,
@@ -45,10 +45,10 @@ data EvalState = ES { limited :: [(Name, Int)],
45type Eval a = State EvalState a
45type Eval a = State EvalState a
47data EvalOpt = Spec
47data EvalOpt = Spec
48− | HNF
48+ | Simplify Bool -- ^ whether to expand lets or not
52 deriving (Show, Eq)
52 deriving (Show, Eq)
54initEval = ES [] 0 False
54initEval = ES [] 0 False
@@ -131,10 +131,7 @@ specialise ctxt env limits t
131 (tm, limited st)
131 (tm, limited st)
133-- | Like normalise, but we only reduce functions that are marked as okay to
133-- | Like normalise, but we only reduce functions that are marked as okay to
134−-- inline (and probably shouldn't reduce lets?)
134+-- inline, and lets
135−-- 20130908: now only used to reduce for totality checking. Inlining should
136−-- be done elsewhere.
138simplify :: Context -> Env -> TT Name -> TT Name
135simplify :: Context -> Env -> TT Name -> TT Name
139simplify ctxt env t
136simplify ctxt env t
140 = evalState (do val <- eval False ctxt [(sUN "lazy", 0),
137 = evalState (do val <- eval False ctxt [(sUN "lazy", 0),
@@ -146,7 +143,23 @@ simplify ctxt env t
146 (sUN "prim__syntactic_eq", 0),
143 (sUN "prim__syntactic_eq", 0),
147 (sUN "fork", 0)]
144 (sUN "fork", 0)]
148 (map finalEntry env) (finalise t)
145 (map finalEntry env) (finalise t)
149− [Simplify]
146+ [Simplify True]
147+ quote 0 val) initEval
149+-- | Like simplify, but we only reduce functions that are marked as okay to
150+-- inline, and don't reduce lets
151+inline :: Context -> Env -> TT Name -> TT Name
153+ = evalState (do val <- eval False ctxt [(sUN "lazy", 0),
156+ (sUN "assert_smaller", 0),
157+ (sUN "assert_total", 0),
159+ (sUN "prim__syntactic_eq", 0),
161+ (map finalEntry env) (finalise t)
150 quote 0 val) initEval
163 quote 0 val) initEval
152-- | Simplify for run-time (i.e. basic inlining)
165-- | Simplify for run-time (i.e. basic inlining)
@@ -162,12 +175,19 @@ rt_simplify ctxt env t
163 quote 0 val) initEval
176 quote 0 val) initEval
165−-- | Reduce a term to head normal form
178+-- | Unfold the given names in a term, the given number of times in a stack.
180+-- This is primarily to support inlining of the given names, and can also
181+-- help with partial evaluation by allowing a rescursive definition to be
182+-- unfolded once only.
183+-- Specifically used to unfold definitions using interfaces before going to
184+-- the totality checker (otherwise mutually recursive definitions in
185+-- implementations will not work...)
166−hnf :: Context -> Env -> TT Name -> TT Name
186+unfold :: Context -> Env -> [(Name, Int)] -> TT Name -> TT Name
167−hnf ctxt env t
187+unfold ctxt env ns t
168− = evalState (do val <- eval False ctxt []
188+ = evalState (do val <- eval False ctxt ns
169− (map finalEntry env)
189+ (map finalEntry env) (finalise t)
170− (finalise t) [HNF]
190+ [Unfold]
171 quote 0 val) initEval
191 quote 0 val) initEval
@@ -187,22 +207,25 @@ unbindEnv (_:bs) (Bind n b sc) = unbindEnv bs sc
187unbindEnv env tm = error "Impossible case occurred: couldn't unbind env."
207unbindEnv env tm = error "Impossible case occurred: couldn't unbind env."
189usable :: Bool -- specialising
209usable :: Bool -- specialising
210+ -> Bool -- unfolding only
190 -> Int -- Reduction depth limit (when simplifying/at REPL)
211 -> Int -- Reduction depth limit (when simplifying/at REPL)
191 -> Name -> [(Name, Int)] -> Eval (Bool, [(Name, Int)])
212 -> Name -> [(Name, Int)] -> Eval (Bool, [(Name, Int)])
192-- usable _ _ ns@((MN 0 "STOP", _) : _) = return (False, ns)
213-- usable _ _ ns@((MN 0 "STOP", _) : _) = return (False, ns)
193−usable False depthlimit n [] = return (True, [])
214+usable False uf depthlimit n [] = return (True, [])
194−usable True depthlimit n ns
215+usable True uf depthlimit n ns
195 = do ES ls num b <- get
216 = do ES ls num b <- get
196 if b then return (False, ns)
217 if b then return (False, ns)
197 else case lookup n ls of
218 else case lookup n ls of
198 Just 0 -> return (False, ns)
219 Just 0 -> return (False, ns)
199 Just i -> return (True, ns)
220 Just i -> return (True, ns)
200 _ -> return (False, ns)
221 _ -> return (False, ns)
201−usable False depthlimit n ns
222+usable False uf depthlimit n ns
202 = case lookup n ns of
223 = case lookup n ns of
203 Just 0 -> return (False, ns)
224 Just 0 -> return (False, ns)
204 Just i -> return $ (True, (n, abs (i-1)) : filter (\ (n', _) -> n/=n') ns)
225 Just i -> return $ (True, (n, abs (i-1)) : filter (\ (n', _) -> n/=n') ns)
205− _ -> return $ (True, (n, depthlimit) : filter (\ (n', _) -> n/=n') ns)
228+ else (True, (n, depthlimit) : filter (\ (n', _) -> n/=n') ns)
208fnCount :: Int -> Name -> Eval ()
231fnCount :: Int -> Name -> Eval ()
@@ -231,10 +254,11 @@ eval :: Bool -> Context -> [(Name, Int)] -> Env -> TT Name ->
231 [EvalOpt] -> Eval Value
254 [EvalOpt] -> Eval Value
232eval traceon ctxt ntimes genv tm opts = ev ntimes [] True [] tm where
255eval traceon ctxt ntimes genv tm opts = ev ntimes [] True [] tm where
233 spec = Spec `elem` opts
256 spec = Spec `elem` opts
234− simpl = Simplify `elem` opts
257+ simpl = Simplify True `elem` opts || Simplify False `elem` opts
258+ simpl_inline = Simplify False `elem` opts
235 runtime = RunTT `elem` opts
259 runtime = RunTT `elem` opts
236 atRepl = AtREPL `elem` opts
260 atRepl = AtREPL `elem` opts
237− hnf = HNF `elem` opts
261+ unfold = Unfold `elem` opts
239 -- returns 'True' if the function should block
263 -- returns 'True' if the function should block
240 -- normal evaluation should return false
264 -- normal evaluation should return false
@@ -243,7 +267,7 @@ eval traceon ctxt ntimes genv tm opts = ev ntimes [] True [] tm where
243 = if always then False
267 = if always then False
244 else not (inl || dict) || elem n stk
268 else not (inl || dict) || elem n stk
246− = (not (inl || dict) || elem n stk)
270+ = (not inl || elem n stk)
247 || (n == sUN "prim__syntactic_eq")
271 || (n == sUN "prim__syntactic_eq")
248 | otherwise = False
272 | otherwise = False
@@ -254,21 +278,21 @@ eval traceon ctxt ntimes genv tm opts = ev ntimes [] True [] tm where
254 ev ntimes stk top env (P _ n ty)
278 ev ntimes stk top env (P _ n ty)
255 | Just (Let t v) <- lookup n genv = ev ntimes stk top env v
279 | Just (Let t v) <- lookup n genv = ev ntimes stk top env v
256 ev ntimes_in stk top env (P Ref n ty)
280 ev ntimes_in stk top env (P Ref n ty)
257− | not top && hnf = liftM (VP Ref n) (ev ntimes stk top env ty)
259 = do let limit = if simpl then 100 else 10000
281 = do let limit = if simpl then 100 else 10000
260− (u, ntimes) <- usable spec limit n ntimes_in
282+ (u, ntimes) <- usable spec unfold limit n ntimes_in
261− let red = u && (tcReducible n ctxt || spec || atRepl || runtime
283+ let red = u && (tcReducible n ctxt || spec || atRepl
284+ || runtime || unfold
262 || sUN "assert_total" `elem` stk)
285 || sUN "assert_total" `elem` stk)
263 if red then
286 if red then
264− do let val = lookupDefAcc n (spec || atRepl || runtime) ctxt
287+ do let val = lookupDefAcc n (spec || unfold || atRepl || runtime) ctxt
265 case val of
288 case val of
266 [(Function _ tm, Public)] ->
289 [(Function _ tm, Public)] ->
267 ev ntimes (n:stk) True env tm
290 ev ntimes (n:stk) True env tm
268 [(TyDecl nt ty, _)] -> do vty <- ev ntimes stk True env ty
291 [(TyDecl nt ty, _)] -> do vty <- ev ntimes stk True env ty
269 return $ VP nt n vty
292 return $ VP nt n vty
270 [(CaseOp ci _ _ _ _ cd, acc)]
293 [(CaseOp ci _ _ _ _ cd, acc)]
294+ | (acc == Public || acc == Hidden) &&
271− | (acc == Public || acc == Hidden || sUN "assert_total" `elem` stk) &&
295+-- || sUN "assert_total" `elem` stk) &&
272 null (fst (cases_totcheck cd)) -> -- unoptimised version
296 null (fst (cases_totcheck cd)) -> -- unoptimised version
273 let (ns, tree) = getCases cd in
297 let (ns, tree) = getCases cd in
274 if blockSimplify ci n stk
298 if blockSimplify ci n stk
@@ -281,12 +305,12 @@ eval traceon ctxt ntimes genv tm opts = ev ntimes [] True [] tm where
281 _ -> liftM (VP Ref n) (ev ntimes stk top env ty)
305 _ -> liftM (VP Ref n) (ev ntimes stk top env ty)
282 else liftM (VP Ref n) (ev ntimes stk top env ty)
306 else liftM (VP Ref n) (ev ntimes stk top env ty)
283 ev ntimes stk top env (P nt n ty)
307 ev ntimes stk top env (P nt n ty)
284− = liftM (VP nt n) (ev ntimes stk top env ty)
308+ = liftM (VP nt n) (ev ntimes stk top env ty)
285 ev ntimes stk top env (V i)
309 ev ntimes stk top env (V i)
286− | i < length env && i >= 0 = return $ snd (env !! i)
310+ | i < length env && i >= 0 = return $ snd (env !! i)
287− | otherwise = return $ VV i
311+ | otherwise = return $ VV i
288 ev ntimes stk top env (Bind n (Let t v) sc)
312 ev ntimes stk top env (Bind n (Let t v) sc)
289− | not runtime || occurrences n sc < 2
313+ | (not (runtime || simpl_inline || unfold)) || occurrences n sc < 2
290 = do v' <- ev ntimes stk top env v --(finalise v)
314 = do v' <- ev ntimes stk top env v --(finalise v)
291 sc' <- ev ntimes stk top ((n, v') : env) sc
315 sc' <- ev ntimes stk top ((n, v') : env) sc
292 wknV (-1) sc'
316 wknV (-1) sc'
@@ -315,7 +339,7 @@ eval traceon ctxt ntimes genv tm opts = ev ntimes [] True [] tm where
315 -- block reduction immediately under codata (and not forced)
339 -- block reduction immediately under codata (and not forced)
316 ev ntimes stk top env
340 ev ntimes stk top env
317 (App _ (App _ (App _ d@(P _ (UN dly) _) l@(P _ (UN lco) _)) t) arg)
341 (App _ (App _ (App _ d@(P _ (UN dly) _) l@(P _ (UN lco) _)) t) arg)
318− | dly == txt "Delay" && lco == txt "Infinite" && not simpl
342+ | dly == txt "Delay" && lco == txt "Infinite" && not (unfold || simpl)
319 = do let (f, _) = unApply arg
343 = do let (f, _) = unApply arg
320 let ntimes' = case f of
344 let ntimes' = case f of
321 P _ fn _ -> (fn, 0) : ntimes
345 P _ fn _ -> (fn, 0) : ntimes
@@ -330,7 +354,7 @@ eval traceon ctxt ntimes genv tm opts = ev ntimes [] True [] tm where
330 -- Treat "assert_total" specially, as long as it's defined!
354 -- Treat "assert_total" specially, as long as it's defined!
331 ev ntimes stk top env (App _ (App _ (P _ n@(UN at) _) _) arg)
355 ev ntimes stk top env (App _ (App _ (P _ n@(UN at) _) _) arg)
332 | [(CaseOp _ _ _ _ _ _, _)] <- lookupDefAcc n (spec || atRepl || runtime) ctxt,
356 | [(CaseOp _ _ _ _ _ _, _)] <- lookupDefAcc n (spec || atRepl || runtime) ctxt,
333− at == txt "assert_total" && not simpl
357+ at == txt "assert_total" && not (simpl || unfold)
334 = ev ntimes (n : stk) top env arg
358 = ev ntimes (n : stk) top env arg
335 ev ntimes stk top env (App _ f a)
359 ev ntimes stk top env (App _ f a)
336 = do f' <- ev ntimes stk False env f
360 = do f' <- ev ntimes stk False env f
@@ -377,16 +401,13 @@ eval traceon ctxt ntimes genv tm opts = ev ntimes [] True [] tm where
377 app <- apply ntimes stk top env a' as
401 app <- apply ntimes stk top env a' as
378 wknV 1 app
402 wknV 1 app
379 apply ntimes_in stk top env f@(VP Ref n ty) args
403 apply ntimes_in stk top env f@(VP Ref n ty) args
380− | not top && hnf = case args of
382− _ -> return $ unload env f args
384 = do let limit = if simpl then 100 else 10000
404 = do let limit = if simpl then 100 else 10000
385− (u, ntimes) <- usable spec limit n ntimes_in
405+ (u, ntimes) <- usable spec unfold limit n ntimes_in
386− let red = u && (tcReducible n ctxt || spec || atRepl || runtime
406+ let red = u && (tcReducible n ctxt || spec || atRepl
407+ || unfold || runtime
387 || sUN "assert_total" `elem` stk)
408 || sUN "assert_total" `elem` stk)
388 if red then
409 if red then
389− do let val = lookupDefAcc n (spec || atRepl || runtime) ctxt
410+ do let val = lookupDefAcc n (spec || unfold || atRepl || runtime) ctxt
390 case val of
411 case val of
391 [(CaseOp ci _ _ _ _ cd, acc)]
412 [(CaseOp ci _ _ _ _ cd, acc)]
392 | acc == Public || acc == Hidden ->
413 | acc == Public || acc == Hidden ->
@@ -975,7 +996,8 @@ simplifyCasedef n ei uctxt
975 pdef = map debind ps_in'
996 pdef = map debind ps_in'
976 CaseDef args sc _ <- simpleCase False (STerm Erased) False CompileTime emptyFC [] atys pdef ei
997 CaseDef args sc _ <- simpleCase False (STerm Erased) False CompileTime emptyFC [] atys pdef ei
977 return $ addDef n (CaseOp ci
998 return $ addDef n (CaseOp ci
978− ty atys ps_in' ps (cd { cases_totcheck = (args, sc) }),
999+ ty atys ps_in' ps (cd { cases_totcheck = (args, sc),
1000+ cases_compiletime = (args, sc) }),
979 inj, acc, tot, metainf) ctxt
1001 inj, acc, tot, metainf) ctxt
981 _ -> return ctxt
1003 _ -> return ctxt
@@ -989,7 +1011,7 @@ simplifyCasedef n ei uctxt
989 (vs, x', y')
1011 (vs, x', y')
990 debind (Left x) = let (vs, x') = depat [] x in
1012 debind (Left x) = let (vs, x') = depat [] x in
991 (vs, x', Impossible)
1013 (vs, x', Impossible)
992− simpl (Right (x, y)) = Right (x, simplify uctxt [] y)
1014+ simpl (Right (x, y)) = Right (x, y) -- inline uctxt [] y)
993 simpl t = t
1015 simpl t = t
995addOperator :: Name -> Type -> Int -> ([Value] -> Maybe Value) ->
1017addOperator :: Name -> Type -> Int -> ([Value] -> Maybe Value) ->