@@ -11,7 +11,7 @@ Maintainer : The Idris Community.
1111
1212module Idris.Core.Evaluate(normalise, normaliseTrace, normaliseC,
1313 normaliseAll, normaliseBlocking, toValue, quoteTerm,
14− rt_simplify, simplify, specialise, hnf, convEq, convEq',
14+ rt_simplify, simplify, specialise, unfold, convEq, convEq',
1515 Def(..), CaseInfo(..), CaseDefs(..),
1616 Accessibility(..), Injectivity, Totality(..), PReason(..), MetaInformation(..),
1717 Context, initContext, ctxtAlist, next_tvar,
@@ -45,10 +45,10 @@ data EvalState = ES { limited :: [(Name, Int)],
4545type Eval a = State EvalState a
4646
4747data EvalOpt = Spec
48− | HNF
49− | Simplify
48+ | Simplify Bool -- ^ whether to expand lets or not
5049 | AtREPL
5150 | RunTT
51+ | Unfold
5252 deriving (Show, Eq)
5353
5454initEval = ES [] 0 False
@@ -131,10 +131,7 @@ specialise ctxt env limits t
131131 (tm, limited st)
132132
133133-- | Like normalise, but we only reduce functions that are marked as okay to
134−-- inline (and probably shouldn't reduce lets?)
135−-- 20130908: now only used to reduce for totality checking. Inlining should
136−-- be done elsewhere.
137−
134+-- inline, and lets
138135simplify :: Context -> Env -> TT Name -> TT Name
139136simplify ctxt env t
140137 = evalState (do val <- eval False ctxt [(sUN "lazy", 0),
@@ -146,7 +143,23 @@ simplify ctxt env t
146143 (sUN "prim__syntactic_eq", 0),
147144 (sUN "fork", 0)]
148145 (map finalEntry env) (finalise t)
149− [Simplify]
146+ [Simplify True]
147+ quote 0 val) initEval
148+
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
152+inline ctxt env t
153+ = evalState (do val <- eval False ctxt [(sUN "lazy", 0),
154+ (sUN "force", 0),
155+ (sUN "Force", 0),
156+ (sUN "assert_smaller", 0),
157+ (sUN "assert_total", 0),
158+ (sUN "par", 0),
159+ (sUN "prim__syntactic_eq", 0),
160+ (sUN "fork", 0)]
161+ (map finalEntry env) (finalise t)
162+ [Simplify False]
150163 quote 0 val) initEval
151164
152165-- | Simplify for run-time (i.e. basic inlining)
@@ -162,12 +175,19 @@ rt_simplify ctxt env t
162175 [RunTT]
163176 quote 0 val) initEval
164177
165−-- | Reduce a term to head normal form
166−hnf :: Context -> Env -> TT Name -> TT Name
167−hnf ctxt env t
168− = evalState (do val <- eval False ctxt []
169− (map finalEntry env)
170− (finalise t) [HNF]
178+-- | Unfold the given names in a term, the given number of times in a stack.
179+-- Preserves 'let'.
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...)
186+unfold :: Context -> Env -> [(Name, Int)] -> TT Name -> TT Name
187+unfold ctxt env ns t
188+ = evalState (do val <- eval False ctxt ns
189+ (map finalEntry env) (finalise t)
190+ [Unfold]
171191 quote 0 val) initEval
172192
173193
@@ -187,22 +207,25 @@ unbindEnv (_:bs) (Bind n b sc) = unbindEnv bs sc
187207unbindEnv env tm = error "Impossible case occurred: couldn't unbind env."
188208
189209usable :: Bool -- specialising
210+ -> Bool -- unfolding only
190211 -> Int -- Reduction depth limit (when simplifying/at REPL)
191212 -> Name -> [(Name, Int)] -> Eval (Bool, [(Name, Int)])
192213-- usable _ _ ns@((MN 0 "STOP", _) : _) = return (False, ns)
193−usable False depthlimit n [] = return (True, [])
194−usable True depthlimit n ns
214+usable False uf depthlimit n [] = return (True, [])
215+usable True uf depthlimit n ns
195216 = do ES ls num b <- get
196217 if b then return (False, ns)
197218 else case lookup n ls of
198219 Just 0 -> return (False, ns)
199220 Just i -> return (True, ns)
200221 _ -> return (False, ns)
201−usable False depthlimit n ns
222+usable False uf depthlimit n ns
202223 = case lookup n ns of
203224 Just 0 -> return (False, ns)
204225 Just i -> return $ (True, (n, abs (i-1)) : filter (\ (n', _) -> n/=n') ns)
205− _ -> return $ (True, (n, depthlimit) : filter (\ (n', _) -> n/=n') ns)
226+ _ -> return $ if uf
227+ then (False, ns)
228+ else (True, (n, depthlimit) : filter (\ (n', _) -> n/=n') ns)
206229
207230
208231fnCount :: Int -> Name -> Eval ()
@@ -231,10 +254,11 @@ eval :: Bool -> Context -> [(Name, Int)] -> Env -> TT Name ->
231254 [EvalOpt] -> Eval Value
232255eval traceon ctxt ntimes genv tm opts = ev ntimes [] True [] tm where
233256 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
235259 runtime = RunTT `elem` opts
236260 atRepl = AtREPL `elem` opts
237− hnf = HNF `elem` opts
261+ unfold = Unfold `elem` opts
238262
239263 -- returns 'True' if the function should block
240264 -- normal evaluation should return false
@@ -243,7 +267,7 @@ eval traceon ctxt ntimes genv tm opts = ev ntimes [] True [] tm where
243267 = if always then False
244268 else not (inl || dict) || elem n stk
245269 | simpl
246− = (not (inl || dict) || elem n stk)
270+ = (not inl || elem n stk)
247271 || (n == sUN "prim__syntactic_eq")
248272 | otherwise = False
249273
@@ -254,21 +278,21 @@ eval traceon ctxt ntimes genv tm opts = ev ntimes [] True [] tm where
254278 ev ntimes stk top env (P _ n ty)
255279 | Just (Let t v) <- lookup n genv = ev ntimes stk top env v
256280 ev ntimes_in stk top env (P Ref n ty)
257− | not top && hnf = liftM (VP Ref n) (ev ntimes stk top env ty)
258− | otherwise
259281 = do let limit = if simpl then 100 else 10000
260− (u, ntimes) <- usable spec limit n ntimes_in
261− let red = u && (tcReducible n ctxt || spec || atRepl || runtime
282+ (u, ntimes) <- usable spec unfold limit n ntimes_in
283+ let red = u && (tcReducible n ctxt || spec || atRepl
284+ || runtime || unfold
262285 || sUN "assert_total" `elem` stk)
263286 if red then
264− do let val = lookupDefAcc n (spec || atRepl || runtime) ctxt
287+ do let val = lookupDefAcc n (spec || unfold || atRepl || runtime) ctxt
265288 case val of
266289 [(Function _ tm, Public)] ->
267290 ev ntimes (n:stk) True env tm
268291 [(TyDecl nt ty, _)] -> do vty <- ev ntimes stk True env ty
269292 return $ VP nt n vty
270293 [(CaseOp ci _ _ _ _ cd, acc)]
271− | (acc == Public || acc == Hidden || sUN "assert_total" `elem` stk) &&
294+ | (acc == Public || acc == Hidden) &&
295+-- || sUN "assert_total" `elem` stk) &&
272296 null (fst (cases_totcheck cd)) -> -- unoptimised version
273297 let (ns, tree) = getCases cd in
274298 if blockSimplify ci n stk
@@ -281,12 +305,12 @@ eval traceon ctxt ntimes genv tm opts = ev ntimes [] True [] tm where
281305 _ -> liftM (VP Ref n) (ev ntimes stk top env ty)
282306 else liftM (VP Ref n) (ev ntimes stk top env ty)
283307 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)
285309 ev ntimes stk top env (V i)
286− | i < length env && i >= 0 = return $ snd (env !! i)
287− | otherwise = return $ VV i
310+ | i < length env && i >= 0 = return $ snd (env !! i)
311+ | otherwise = return $ VV i
288312 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
290314 = do v' <- ev ntimes stk top env v --(finalise v)
291315 sc' <- ev ntimes stk top ((n, v') : env) sc
292316 wknV (-1) sc'
@@ -315,7 +339,7 @@ eval traceon ctxt ntimes genv tm opts = ev ntimes [] True [] tm where
315339 -- block reduction immediately under codata (and not forced)
316340 ev ntimes stk top env
317341 (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)
319343 = do let (f, _) = unApply arg
320344 let ntimes' = case f of
321345 P _ fn _ -> (fn, 0) : ntimes
@@ -330,7 +354,7 @@ eval traceon ctxt ntimes genv tm opts = ev ntimes [] True [] tm where
330354 -- Treat "assert_total" specially, as long as it's defined!
331355 ev ntimes stk top env (App _ (App _ (P _ n@(UN at) _) _) arg)
332356 | [(CaseOp _ _ _ _ _ _, _)] <- lookupDefAcc n (spec || atRepl || runtime) ctxt,
333− at == txt "assert_total" && not simpl
357+ at == txt "assert_total" && not (simpl || unfold)
334358 = ev ntimes (n : stk) top env arg
335359 ev ntimes stk top env (App _ f a)
336360 = do f' <- ev ntimes stk False env f
@@ -377,16 +401,13 @@ eval traceon ctxt ntimes genv tm opts = ev ntimes [] True [] tm where
377401 app <- apply ntimes stk top env a' as
378402 wknV 1 app
379403 apply ntimes_in stk top env f@(VP Ref n ty) args
380− | not top && hnf = case args of
381− [] -> return f
382− _ -> return $ unload env f args
383− | otherwise
384404 = do let limit = if simpl then 100 else 10000
385− (u, ntimes) <- usable spec limit n ntimes_in
386− let red = u && (tcReducible n ctxt || spec || atRepl || runtime
405+ (u, ntimes) <- usable spec unfold limit n ntimes_in
406+ let red = u && (tcReducible n ctxt || spec || atRepl
407+ || unfold || runtime
387408 || sUN "assert_total" `elem` stk)
388409 if red then
389− do let val = lookupDefAcc n (spec || atRepl || runtime) ctxt
410+ do let val = lookupDefAcc n (spec || unfold || atRepl || runtime) ctxt
390411 case val of
391412 [(CaseOp ci _ _ _ _ cd, acc)]
392413 | acc == Public || acc == Hidden ->
@@ -975,7 +996,8 @@ simplifyCasedef n ei uctxt
975996 pdef = map debind ps_in'
976997 CaseDef args sc _ <- simpleCase False (STerm Erased) False CompileTime emptyFC [] atys pdef ei
977998 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) }),
9791001 inj, acc, tot, metainf) ctxt
9801002
9811003 _ -> return ctxt
@@ -989,7 +1011,7 @@ simplifyCasedef n ei uctxt
9891011 (vs, x', y')
9901012 debind (Left x) = let (vs, x') = depat [] x in
9911013 (vs, x', Impossible)
992− simpl (Right (x, y)) = Right (x, simplify uctxt [] y)
1014+ simpl (Right (x, y)) = Right (x, y) -- inline uctxt [] y)
9931015 simpl t = t
9941016
9951017addOperator :: Name -> Type -> Int -> ([Value] -> Maybe Value) ->