@@ -87,7 +87,9 @@ normaliseTrace tr ctxt env t
8787
8888specialise :: Context -> Env -> [(Name, Int)] -> TT Name -> TT Name
8989specialise ctxt env limits t
90− = evalState (do val <- eval False ctxt limits (map finalEntry env) (finalise t) []
90+ = evalState (do val <- eval False ctxt []
91+ (map finalEntry env) (finalise t)
92+ [Spec]
9193 quote 0 val) (initEval { limited = limits })
9294
9395-- | Like normalise, but we only reduce functions that are marked as okay to
@@ -125,18 +127,38 @@ unbindEnv :: EnvTT n -> TT n -> TT n
125127unbindEnv [] tm = tm
126128unbindEnv (_:bs) (Bind n b sc) = unbindEnv bs sc
127129
128−usable :: Bool -> Name -> [(Name, Int)] -> (Bool, [(Name, Int)])
129−usable _ _ ns@((MN 0 "STOP", _) : _) = (False, ns)
130−usable True (UN "io_bind") ns = (False, ns)
131−usable s n [] = (True, [])
132−usable s n ns = case lookup n ns of
133− Just 0 -> (False, ns)
134− Just i -> (True, (n, abs (i-1)) : filter (\ (n', _) -> n/=n') ns)
135− _ -> if s then (True, (n, 0) : filter (\ (n', _) -> n/=n') ns)
136− else (True, (n, 100) : filter (\ (n', _) -> n/=n') ns)
130+usable :: Bool -> Bool -> Name -> [(Name, Int)] -> Eval (Bool, [(Name, Int)])
131+usable _ _ _ ns@((MN 0 "STOP", _) : _) = return (False, ns)
132+usable True _ (UN "io_bind") ns = return (False, ns)
133+usable simpl False n [] = return (True, [])
134+usable simpl True n ns
135+ = do ES ls num <- get
136+ case lookup n ls of
137+ Just 0 -> return (False, ns)
138+ Just i -> return (True, ns)
139+ _ -> return (True, ns)
140+usable simpl False n ns
141+ = case lookup n ns of
142+ Just 0 -> return (False, ns)
143+ Just i -> return $ (True, (n, abs (i-1)) : filter (\ (n', _) -> n/=n') ns)
144+ _ -> if simpl then return $ (True, (n, 0) : filter (\ (n', _) -> n/=n') ns)
145+ else return $ (True, (n, 100) : filter (\ (n', _) -> n/=n') ns)
146+
147+
148+deduct :: Name -> Eval ()
149+deduct n = do ES ls num <- get
150+ case lookup n ls of
151+ Just i -> do put $ ES ((n, (i-1)) :
152+ filter (\ (n', _) -> n/=n') ls) num
153+ _ -> return ()
137154
138155-- | Evaluate in a context of locally named things (i.e. not de Bruijn indexed,
139156-- such as we might have during construction of a proof)
157+
158+-- The (Name, Int) pair in the arguments is the maximum depth of unfolding of
159+-- a name. The corresponding pair in the state is the maximum number of
160+-- unfoldings overall.
161+
140162eval :: Bool -> Context -> [(Name, Int)] -> Env -> TT Name ->
141163 [EvalOpt] -> Eval Value
142164eval traceon ctxt ntimes genv tm opts = ev ntimes [] True [] tm where
@@ -153,23 +175,27 @@ eval traceon ctxt ntimes genv tm opts = ev ntimes [] True [] tm where
153175 | Just (Let t v) <- lookup n genv = ev ntimes stk top env v
154176 ev ntimes_in stk top env (P Ref n ty)
155177 | not top && hnf = liftM (VP Ref n) (ev ntimes stk top env ty)
156− | (True, ntimes) <- usable simpl n ntimes_in
157− = do let val = lookupDefAcc n atRepl ctxt
158− case val of
159− [(Function _ tm, Public)] ->
160− ev ntimes (n:stk) True env tm
161− [(TyDecl nt ty, _)] -> do vty <- ev ntimes stk True env ty
162− return $ VP nt n vty
163− [(CaseOp inl inr _ _ _ [] tree _ _, acc)]
164− | acc == Public || simpl -> -- unoptimised version
165− if canSimplify inl inr n stk
166− then liftM (VP Ref n) (ev ntimes stk top env ty)
167− else do c <- evCase ntimes (n:stk) top env [] [] tree
168− case c of
169− (Nothing, _) -> liftM (VP Ref n) (ev ntimes stk top env ty)
170− (Just v, _) -> return v
171− _ -> liftM (VP Ref n) (ev ntimes stk top env ty)
172− ev ntimes stk top env (P nt n ty) = liftM (VP nt n) (ev ntimes stk top env ty)
178+ | otherwise
179+ = do (u, ntimes) <- usable simpl spec n ntimes_in
180+ if u then
181+ do let val = lookupDefAcc n atRepl ctxt
182+ case val of
183+ [(Function _ tm, Public)] ->
184+ ev ntimes (n:stk) True env tm
185+ [(TyDecl nt ty, _)] -> do vty <- ev ntimes stk True env ty
186+ return $ VP nt n vty
187+ [(CaseOp inl inr _ _ _ [] tree _ _, acc)]
188+ | acc == Public || simpl -> -- unoptimised version
189+ if canSimplify inl inr n stk
190+ then liftM (VP Ref n) (ev ntimes stk top env ty)
191+ else do c <- evCase ntimes n (n:stk) top env [] [] tree
192+ case c of
193+ (Nothing, _) -> liftM (VP Ref n) (ev ntimes stk top env ty)
194+ (Just v, _) -> return v
195+ _ -> liftM (VP Ref n) (ev ntimes stk top env ty)
196+ else liftM (VP Ref n) (ev ntimes stk top env ty)
197+ ev ntimes stk top env (P nt n ty)
198+ = liftM (VP nt n) (ev ntimes stk top env ty)
173199 ev ntimes stk top env (V i)
174200 | i < length env && i >= 0 = return $ env !! i
175201 | otherwise = return $ VV i
@@ -228,27 +254,31 @@ eval traceon ctxt ntimes genv tm opts = ev ntimes [] True [] tm where
228254 | not top && hnf = case args of
229255 [] -> return f
230256 _ -> return $ unload env f args
231− | (True, ntimes) <- usable simpl n ntimes_in
232− = traceWhen traceon (show stk) $
233− do let val = lookupDefAcc n atRepl ctxt
234− case val of
235− [(CaseOp inl inr _ _ _ ns tree _ _, acc)]
236− | acc == Public -> -- unoptimised version
237− if canSimplify inl inr n stk
238− then return $ unload env (VP Ref n ty) args
239− else do c <- evCase ntimes (n:stk) top env ns args tree
240− case c of
241− (Nothing, _) -> return $ unload env (VP Ref n ty) args
242− (Just v, rest) -> evApply ntimes stk top env rest v
243− [(Operator _ i op, _)] ->
244− if (i <= length args)
245− then case op (take i args) of
246− Nothing -> return $ unload env (VP Ref n ty) args
247− Just v -> evApply ntimes stk top env (drop i args) v
248− else return $ unload env (VP Ref n ty) args
249− _ -> case args of
250− [] -> return f
251− _ -> return $ unload env f args
257+ | otherwise
258+ = do (u, ntimes) <- usable simpl spec n ntimes_in
259+ if u then
260+ do let val = lookupDefAcc n atRepl ctxt
261+ case val of
262+ [(CaseOp inl inr _ _ _ ns tree _ _, acc)]
263+ | acc == Public -> -- unoptimised version
264+ if canSimplify inl inr n stk
265+ then return $ unload env (VP Ref n ty) args
266+ else do c <- evCase ntimes n (n:stk) top env ns args tree
267+ case c of
268+ (Nothing, _) -> return $ unload env (VP Ref n ty) args
269+ (Just v, rest) -> evApply ntimes stk top env rest v
270+ [(Operator _ i op, _)] ->
271+ if (i <= length args)
272+ then case op (take i args) of
273+ Nothing -> return $ unload env (VP Ref n ty) args
274+ Just v -> evApply ntimes stk top env (drop i args) v
275+ else return $ unload env (VP Ref n ty) args
276+ _ -> case args of
277+ [] -> return f
278+ _ -> return $ unload env f args
279+ else case args of
280+ (a : as) -> return $ unload env f (a:as)
281+ [] -> return f
252282 apply ntimes stk top env f (a:as) = return $ unload env f (a:as)
253283 apply ntimes stk top env f [] = return f
254284
@@ -264,10 +294,11 @@ eval traceon ctxt ntimes genv tm opts = ev ntimes [] True [] tm where
264294 unload env f [] = f
265295 unload env f (a:as) = unload env (VApp f a) as
266296
267− evCase ntimes stk top env ns args tree
297+ evCase ntimes n stk top env ns args tree
268298 | length ns <= length args
269299 = do let args' = take (length ns) args
270300 let rest = drop (length ns) args
301+ when spec $ deduct n -- successful, so deduct usages
271302 t <- evTree ntimes stk top env
272303 (zipWith (\n t -> (n, t)) ns args') tree
273304 return (t, rest)