on 7fefa89 help sign in
Idris-dev/src/Core/Evaluate.hs
852 lines 37 kB history raw
1{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances,
2 PatternGuards #-}
4module Core.Evaluate(normalise, normaliseTrace, normaliseC, normaliseAll,
5 simplify, specialise, hnf, convEq, convEq',
6 Def(..), Accessibility(..), Totality(..), PReason(..),
7 Context, initContext, ctxtAlist, uconstraints, next_tvar,
8 addToCtxt, setAccess, setTotal, addCtxtDef, addTyDecl,
9 addDatatype, addCasedef, simplifyCasedef, addOperator,
10 lookupNames, lookupTy, lookupP, lookupDef, lookupVal,
11 lookupTotal, lookupTyEnv, isConName, isFnName,
12 Value(..)) where
14import Debug.Trace
15import Control.Monad.State
16import qualified Data.Binary as B
17import Data.Binary hiding (get, put)
19import Core.TT
20import Core.CaseTree
22data EvalState = ES { limited :: [(Name, Int)],
23 steps :: Int -- number of applications/let reductions
24 }
26-- Evaluation fails if we hit a boredom threshold - in which case, just return
27-- the original (capture the failure in a Maybe)
29type Eval a = State EvalState a
31data EvalOpt = Spec | HNF | Simplify Bool | AtREPL
32 deriving (Show, Eq)
34initEval = ES [] 0
36step :: Int -> Eval ()
37step max = do e <- get
38 put (e { steps = steps e + 1 })
39 if steps e > max then fail "Threshold exceeded"
40 else return ()
42getSteps :: Eval Int
43getSteps = do e <- get
44 return (steps e)
46-- VALUES (as HOAS) ---------------------------------------------------------
48data Value = VP NameType Name Value
49 | VV Int
50 | VBind Name (Binder Value) (Value -> Eval Value)
51 | VApp Value Value
52 | VSet UExp
53 | VErased
54 | VConstant Const
55-- | VLazy Env [Value] Term
56 | VTmp Int
58data HNF = HP NameType Name (TT Name)
59 | HV Int
60 | HBind Name (Binder HNF) (HNF -> Eval HNF)
61 | HApp HNF [HNF] [TT Name]
62 | HSet UExp
63 | HConstant Const
64 | HTmp Int
65 deriving Show
67instance Show Value where
68 show x = show $ evalState (quote 100 x) initEval
70instance Show (a -> b) where
71 show x = "<<fn>>"
73-- THE EVALUATOR ------------------------------------------------------------
75-- The environment is assumed to be "locally named" - i.e., not de Bruijn
76-- indexed.
77-- i.e. it's an intermediate environment that we have while type checking or
78-- while building a proof.
80threshold = 1000 -- boredom threshold for evaluation, to prevent infinite typechecking
81 -- in fact it's a maximum recursion depth
83-- Normalise fully type checked terms (so, assume all names/let bindings resolved)
84normaliseC :: Context -> Env -> TT Name -> TT Name
85normaliseC ctxt env t
86 = evalState (do val <- eval False ctxt threshold [] env t []
87 quote 0 val) initEval
89normaliseAll :: Context -> Env -> TT Name -> TT Name
90normaliseAll ctxt env t
91 = evalState (do val <- eval False ctxt threshold [] env t [AtREPL]
92 quote 0 val) initEval
94normalise :: Context -> Env -> TT Name -> TT Name
95normalise = normaliseTrace False
97normaliseTrace :: Bool -> Context -> Env -> TT Name -> TT Name
98normaliseTrace tr ctxt env t
99 = evalState (do val <- eval tr ctxt threshold [] (map finalEntry env) (finalise t) []
100 quote 0 val) initEval
102specialise :: Context -> Env -> [(Name, Int)] -> TT Name -> TT Name
103specialise ctxt env limits t
104 = evalState (do val <- eval False ctxt threshold limits (map finalEntry env) (finalise t) []
105 quote 0 val) (initEval { limited = limits })
107-- Like normalise, but we only reduce functions that are marked as okay to
108-- inline (and probably shouldn't reduce lets?)
110simplify :: Context -> Bool -> Env -> TT Name -> TT Name
111simplify ctxt runtime env t
112 = evalState (do val <- eval False ctxt threshold [(UN "lazy", 0),
113 (UN "par", 0),
114 (UN "fork", 0)]
115 (map finalEntry env) (finalise t)
116 [Simplify runtime]
117 quote 0 val) initEval
119hnf :: Context -> Env -> TT Name -> TT Name
120hnf ctxt env t
121 = evalState (do val <- eval False ctxt threshold [] (map finalEntry env) (finalise t) [HNF]
122 quote 0 val) initEval
125-- unbindEnv env (quote 0 (eval ctxt (bindEnv env t)))
127finalEntry :: (Name, Binder (TT Name)) -> (Name, Binder (TT Name))
128finalEntry (n, b) = (n, fmap finalise b)
130bindEnv :: EnvTT n -> TT n -> TT n
131bindEnv [] tm = tm
132bindEnv ((n, Let t v):bs) tm = Bind n (NLet t v) (bindEnv bs tm)
133bindEnv ((n, b):bs) tm = Bind n b (bindEnv bs tm)
135unbindEnv :: EnvTT n -> TT n -> TT n
136unbindEnv [] tm = tm
137unbindEnv (_:bs) (Bind n b sc) = unbindEnv bs sc
139usable :: Bool -> Name -> [(Name, Int)] -> (Bool, [(Name, Int)])
140usable _ _ ns@((MN 0 "STOP", _) : _) = (False, ns)
141usable True (UN "io_bind") ns = (False, ns)
142usable s n [] = (True, [])
143usable s n ns = case lookup n ns of
144 Just 0 -> (False, ns)
145 Just i -> (True, (n, abs (i-1)) : filter (\ (n', _) -> n/=n') ns)
146 _ -> if s then (True, (n, 0) : filter (\ (n', _) -> n/=n') ns)
147 else (True, (n, 100) : filter (\ (n', _) -> n/=n') ns)
149reduction :: Eval ()
150reduction = do ES ns s <- get
151 put (ES ns (s+1))
153-- Evaluate in a context of locally named things (i.e. not de Bruijn indexed,
154-- such as we might have during construction of a proof)
156eval :: Bool -> Context -> Int -> [(Name, Int)] -> Env -> TT Name ->
157 [EvalOpt] -> Eval Value
158eval traceon ctxt maxred ntimes genv tm opts = ev ntimes [] True [] tm where
159 spec = Spec `elem` opts
160 simpl = Simplify True `elem` opts
161 atRepl = AtREPL `elem` opts
163 canSimplify inl inr n stk
164 = (Simplify False `elem` opts && (not inl || elem n stk))
165 || (Simplify True `elem` opts && (not inr || elem n stk))
167 ev ntimes stk top env (P _ n ty)
168 | Just (Let t v) <- lookup n genv = do when (not atRepl) $ step maxred
169 ev ntimes stk top env v
170 ev ntimes_in stk top env (P Ref n ty)
171 | (True, ntimes) <- usable simpl n ntimes_in
172 = do let val = lookupDefAcc Nothing n atRepl ctxt
173 when (not atRepl) $ step maxred
174 case val of
175 [(Function _ tm, Public)] ->
176 ev ntimes (n:stk) True env tm
177 [(TyDecl nt ty, _)] -> do vty <- ev ntimes stk True env ty
178 return $ VP nt n vty
179 [(CaseOp inl inr _ _ _ [] tree _ _, acc)]
180 | acc == Public || simpl -> -- unoptimised version
181 if canSimplify inl inr n stk
182 then liftM (VP Ref n) (ev ntimes stk top env ty)
183 else do c <- evCase ntimes (n:stk) top env [] [] tree
184 case c of
185 (Nothing, _) -> liftM (VP Ref n) (ev ntimes stk top env ty)
186 (Just v, _) -> return v
187 _ -> liftM (VP Ref n) (ev ntimes stk top env ty)
188 ev ntimes stk top env (P nt n ty) = liftM (VP nt n) (ev ntimes stk top env ty)
189 ev ntimes stk top env (V i) | i < length env = return $ env !! i
190 | otherwise = return $ VV i
191 ev ntimes stk top env (Bind n (Let t v) sc)
192-- | not simpl || vinstances 0 sc < 2
193 = do v' <- ev ntimes stk top env v --(finalise v)
194 when (not atRepl) $ step maxred
195 sc' <- ev ntimes stk top (v' : env) sc
196 wknV (-1) sc'
197{- | otherwise -- put this back when the Bind works properly
198 = do t' <- ev ntimes stk top env t
199 v' <- ev ntimes stk top env v --(finalise v)
200 when (not atRepl) $ step maxred
201 -- use Tmp as a placeholder, then make it a variable reference
202 -- again when evaluation finished
203 sc' <- ev ntimes stk top (v' : env) sc
204 return $ VBind n (Let t' v') (\x -> return sc') -}
205 ev ntimes stk top env (Bind n (NLet t v) sc)
206 = do t' <- ev ntimes stk top env (finalise t)
207 v' <- ev ntimes stk top env (finalise v)
208 when (not atRepl) $ step maxred
209 sc' <- ev ntimes stk top (v' : env) sc
210 return $ VBind n (Let t' v') (\x -> return sc')
211 ev ntimes stk top env (Bind n b sc)
212 = do b' <- vbind env b
213 when (not atRepl) $ step maxred
214 return $ VBind n b' (\x -> ev ntimes stk top (x:env) sc)
215 where vbind env t
216 | simpl
217 = fmapMB (\tm -> ev ((MN 0 "STOP", 0) : ntimes)
218 stk top env (finalise tm)) t
219 | otherwise
220 = fmapMB (\tm -> ev ntimes stk top env (finalise tm)) t
221-- ev ntimes stk top env (App (App (P _ laz _) _) a)
222-- | laz == UN "lazy"
223-- = trace (showEnvDbg genv a) $ ev ntimes stk top env a
224 ev ntimes stk top env (App f a)
225 = do f' <- ev ntimes stk top env f
226 a' <- ev ntimes stk False env a
227 when (not atRepl) $ step maxred
228 evApply ntimes stk top env [a'] f'
229 ev ntimes stk top env (Constant c) = return $ VConstant c
230 ev ntimes stk top env Erased = return VErased
231 ev ntimes stk top env (Set i) = return $ VSet i
233 evApply ntimes stk top env args (VApp f a) =
234 evApply ntimes stk top env (a:args) f
235 evApply ntimes stk top env args f = do when (not atRepl) $ step maxred
236 apply ntimes stk top env f args
238 apply ntimes stk top env f as
239 | length stk > threshold = return $ unload env f as
240 apply ntimes stk top env (VBind n (Lam t) sc) (a:as)
241 = do a' <- sc a
242 app <- apply ntimes stk top env a' as
243 wknV (-1) app
244-- apply ntimes stk False env f args
245-- | spec = specApply ntimes stk env f args
246 apply ntimes_in stk top env f@(VP Ref n ty) args
247 | (True, ntimes) <- usable simpl n ntimes_in
248 = traceWhen traceon (show stk) $
249 do let val = lookupDefAcc Nothing n atRepl ctxt
250 case val of
251 [(CaseOp inl inr _ _ _ ns tree _ _, acc)]
252 | acc == Public || simpl -> -- unoptimised version
253 if canSimplify inl inr n stk
254 then return $ unload env (VP Ref n ty) args
255 else do c <- evCase ntimes (n:stk) top env ns args tree
256 case c of
257 (Nothing, _) -> return $ unload env (VP Ref n ty) args
258 (Just v, rest) -> evApply ntimes stk top env rest v
259 [(Operator _ i op, _)] ->
260 if (i <= length args)
261 then case op (take i args) of
262 Nothing -> return $ unload env (VP Ref n ty) args
263 Just v -> evApply ntimes stk top env (drop i args) v
264 else return $ unload env (VP Ref n ty) args
265 _ -> case args of
266 [] -> return f
267 _ -> return $ unload env f args
268 apply ntimes stk top env f (a:as) = return $ unload env f (a:as)
269 apply ntimes stk top env f [] = return f
271-- specApply stk env f@(VP Ref n ty) args
272-- = case lookupCtxt Nothing n statics of
273-- [as] -> if or as
274-- then trace (show (n, map fst (filter (\ (_, s) -> s) (zip args as)))) $
275-- return $ unload env f args
276-- else return $ unload env f args
277-- _ -> return $ unload env f args
278-- specApply stk env f args = return $ unload env f args
280 unload env f [] = f
281 unload env f (a:as) = unload env (VApp f a) as
283 evCase ntimes stk top env ns args tree
284 | length ns <= length args
285 = do let args' = take (length ns) args
286 let rest = drop (length ns) args
287 t <- evTree ntimes stk top env (zipWith (\n t -> (n, t)) ns args') tree
288 return (t, rest)
289 | otherwise = return (Nothing, args)
291 evTree :: [(Name, Int)] -> [Name] -> Bool ->
292 [Value] -> [(Name, Value)] -> SC -> Eval (Maybe Value)
293 evTree ntimes stk top env amap (UnmatchedCase str) = return Nothing
294 evTree ntimes stk top env amap (STerm tm)
295 = do let etm = pToVs (map fst amap) tm
296 etm' <- ev ntimes stk top (map snd amap ++ env) etm
297 return $ Just etm'
298 evTree ntimes stk top env amap (Case n alts)
299 = case lookup n amap of
300 Just v -> do c <- chooseAlt env v (getValArgs v) alts amap
301 case c of
302 Just (altmap, sc) -> evTree ntimes stk top env altmap sc
303 _ -> do c' <- chooseAlt' ntimes stk env v (getValArgs v) alts amap
304 case c' of
305 Just (altmap, sc) -> evTree ntimes stk top env altmap sc
306 _ -> return Nothing
307 _ -> return Nothing
309 chooseAlt' ntimes stk env _ (f, args) alts amap
310 = do f' <- apply ntimes stk True env f args
311 chooseAlt env f' (getValArgs f') alts amap
313 chooseAlt :: [Value] -> Value -> (Value, [Value]) -> [CaseAlt] -> [(Name, Value)] ->
314 Eval (Maybe ([(Name, Value)], SC))
315 chooseAlt env _ (VP (DCon i a) _ _, args) alts amap
316 | Just (ns, sc) <- findTag i alts = return $ Just (updateAmap (zip ns args) amap, sc)
317 | Just v <- findDefault alts = return $ Just (amap, v)
318 chooseAlt env _ (VP (TCon i a) _ _, args) alts amap
319 | Just (ns, sc) <- findTag i alts = return $ Just (updateAmap (zip ns args) amap, sc)
320 | Just v <- findDefault alts = return $ Just (amap, v)
321 chooseAlt env _ (VConstant c, []) alts amap
322 | Just v <- findConst c alts = return $ Just (amap, v)
323 | Just v <- findDefault alts = return $ Just (amap, v)
324 chooseAlt _ _ _ _ _ = return Nothing
326 -- Replace old variable names in the map with new matches
327 -- (This is possibly unnecessary since we make unique names and don't
328 -- allow repeated variables...?)
329 updateAmap newm amap
330 = newm ++ filter (\ (x, _) -> not (elem x (map fst newm))) amap
331 findTag i [] = Nothing
332 findTag i (ConCase n j ns sc : xs) | i == j = Just (ns, sc)
333 findTag i (_ : xs) = findTag i xs
335 findDefault [] = Nothing
336 findDefault (DefaultCase sc : xs) = Just sc
337 findDefault (_ : xs) = findDefault xs
339 findConst c [] = Nothing
340 findConst c (ConstCase c' v : xs) | c == c' = Just v
341 findConst IType (ConCase n 1 [] v : xs) = Just v
342 findConst FlType (ConCase n 2 [] v : xs) = Just v
343 findConst ChType (ConCase n 3 [] v : xs) = Just v
344 findConst StrType (ConCase n 4 [] v : xs) = Just v
345 findConst PtrType (ConCase n 5 [] v : xs) = Just v
346 findConst c (_ : xs) = findConst c xs
348 getValArgs tm = getValArgs' tm []
349 getValArgs' (VApp f a) as = getValArgs' f (a:as)
350 getValArgs' f as = (f, as)
352tmpToV i (VTmp 0) = return $ VV i
353tmpToV i (VP nt n v) = liftM (VP nt n) (tmpToV i v)
355tmpToV i (VBind n b sc) = do b' <- fmapMB (tmpToV i) b
356 let sc' = \x -> do x' <- sc x
357 tmpToV (i + 1) x'
358 return (VBind n b' sc')
359tmpToV i (VApp f a) = liftM2 VApp (tmpToV i f) (tmpToV i a)
360tmpToV i x = return x
362class Quote a where
363 quote :: Int -> a -> Eval (TT Name)
365instance Quote Value where
366 quote i (VP nt n v) = liftM (P nt n) (quote i v)
367 quote i (VV x) = return $ V x
368 quote i (VBind n b sc) = do sc' <- sc (VTmp i)
369 b' <- quoteB b
370 liftM (Bind n b') (quote (i+1) sc')
371 where quoteB t = fmapMB (quote i) t
372 quote i (VApp f a) = liftM2 App (quote i f) (quote i a)
373 quote i (VSet u) = return $ Set u
374 quote i VErased = return $ Erased
375 quote i (VConstant c) = return $ Constant c
376 quote i (VTmp x) = return $ V (i - x - 1)
378instance Quote HNF where
379 quote i (HP nt n t) = return (P nt n t)
380 quote i (HV x) = return $ V x
381 quote i (HBind n b sc) = do sc' <- sc (HTmp i)
382 b' <- quoteB b
383 liftM (Bind n b') (quote (i+1) sc')
384 where quoteB t = fmapMB (quote i) t
385 quote i (HApp f env as) = do f' <- quote i f
386 as' <- mapM (iEnv env) as
387 return $ mkApp f' as'
388 where iEnv [] a = return a
389 iEnv (x:xs) a = do x' <- quote i x
390 iEnv xs (weakenTm (-1) (instantiate x' a))
391 quote i (HSet u) = return $ Set u
392 quote i (HConstant c) = return $ Constant c
393 quote i (HTmp x) = return $ V (i - x - 1)
395wknV :: Int -> Value -> Eval Value
396wknV i (VV x) = return $ VV (x + i)
397wknV i (VBind n b sc) = do b' <- fmapMB (wknV i) b
398 return $ VBind n b' (\x -> do x' <- sc x
399 wknV i x')
400wknV i (VApp f a) = liftM2 VApp (wknV i f) (wknV i a)
401wknV i t = return t
403wknH :: Int -> HNF -> Eval HNF
404wknH i (HV x) = return $ HV (x + i)
405wknH i (HBind n b sc) = do b' <- fmapMB (wknH i) b
406 return $ HBind n b' (\x -> do x' <- sc x
407 wknH i x')
408wknH i (HApp f env as) = liftM3 HApp (wknH i f) (return env)
409 (return as)
410wknH i t = return t
412-- HEAD NORMAL FORM ---------------------------------------------------------
414eval_hnf :: Context -> Ctxt [Bool] -> Env -> TT Name -> Eval HNF
415eval_hnf ctxt statics genv tm = ev [] tm where
416 ev :: [HNF] -> TT Name -> Eval HNF
417 ev env (P _ n ty)
418 | Just (Let t v) <- lookup n genv = ev env v
419 ev env (P Ref n ty) = case lookupDef Nothing n ctxt of
420 [Function _ t] -> ev env t
421 [TyDecl nt ty] -> return $ HP nt n ty
422 [CaseOp inl _ _ _ _ [] tree _ _] ->
423 do c <- evCase env [] [] tree
424 case c of
425 (Nothing, _, _) -> return $ HP Ref n ty
426 (Just v, _, _) -> return v
427 _ -> return $ HP Ref n ty
428 ev env (P nt n ty) = return $ HP nt n ty
429 ev env (V i) | i < length env = return $ env !! i
430 | otherwise = return $ HV i
431 ev env (Bind n (Let t v) sc)
432 = do v' <- ev env (finalise v)
433 sc' <- ev (v' : env) sc
434 wknH (-1) sc'
435 ev env (Bind n b sc)
436 = do b' <- hbind env b
437 return $ HBind n b' (\x -> ev (x : env) sc)
438 where hbind env t = fmapMB (\tm -> ev env (finalise tm)) t
439 ev env (App f a) = evApply env [a] f
440 ev env (Constant c) = return $ HConstant c
441 ev env (Set i) = return $ HSet i
443 evApply env args (App f a) = evApply env (a : args) f
444 evApply env args f = do f' <- ev env f
445 apply env f' args
447 apply env (HBind n (Lam t) sc) (a:as) = do a' <- ev env a
448 sc' <- sc a'
449 app <- apply env sc' as
450 wknH (-1) app
451 apply env (HP Ref n ty) args
452 | [CaseOp _ _ _ _ _ ns tree _ _] <- lookupDef Nothing n ctxt
453 = do c <- evCase env ns args tree
454 case c of
455 (Nothing, _, env') -> return $ unload env' (HP Ref n ty) args
456 (Just v, rest, env') -> do v' <- quote 0 v
457 apply env' v rest
458-- | Just (Operator _ i op) <- lookupDef n ctxt
459-- = if (i <= length args)
460-- then case op (take i args) of
461-- Nothing -> return $ unload env (HP Ref n ty) args
462-- Just v -> evApply env (drop i args) v
463-- else return $ unload env (HP Ref n ty) args
464 apply env f (a:as) = return $ unload env f (a:as)
465 apply env f [] = return f
467 unload env f [] = f
468 unload env f as = HApp f env as
470 evCase env ns args tree
471 | length ns <= length args
472 = do let args' = take (length ns) args
473 let rest = drop (length ns) args
474 (t, env') <- evTree env (zipWith (\n t -> (n, t)) ns args') tree
475 return (t, rest, env')
476 | otherwise = return (Nothing, args, env)
478 evTree :: [HNF] -> [(Name, TT Name)] -> SC -> Eval (Maybe HNF, [HNF])
479 evTree env amap (UnmatchedCase str) = return (Nothing, env)
480 evTree env amap (STerm tm)
481 = do let etm = pToVs (map fst amap) tm
482 amap' <- mapM (ev env) (map snd amap)
483 envw <- mapM (wknH (length amap)) env
484 let env' = amap' ++ envw
485 etm' <- trace (show etm) $ ev env' etm
486 etmq <- quote 0 etm'
487 trace ("Ev: " ++ show (etm, etmq)) $ return $ (Just etm', env')
488 evTree env amap (Case n alts)
489 = case lookup n amap of
490 Just v -> do v' <- ev env v
491 case chooseAlt v' (getValArgs v') alts amap of
492 Just (altmap, sc) -> evTree env altmap sc
493 _ -> return (Nothing, env)
495 chooseAlt :: HNF -> (HNF, [HNF], [TT Name]) ->
496 [CaseAlt] -> [(Name, TT Name)] ->
497 Maybe ([(Name, TT Name)], SC)
498 chooseAlt _ (HP (DCon i a) _ _, env, args) alts amap
499 | Just (ns, sc) <- findTag i alts = Just (updateAmap (zip ns args) amap, sc)
500 | Just v <- findDefault alts = Just (amap, v)
501 chooseAlt _ (HP (TCon i a) _ _, env, args) alts amap
502 | Just (ns, sc) <- findTag i alts = Just (updateAmap (zip ns args) amap, sc)
503 | Just v <- findDefault alts = Just (amap, v)
504 chooseAlt _ (HConstant c, env, []) alts amap
505 | Just v <- findConst c alts = Just (amap, v)
506 | Just v <- findDefault alts = Just (amap, v)
507 chooseAlt _ _ _ _ = Nothing
509 -- Replace old variable names in the map with new matches
510 -- (This is possibly unnecessary since we make unique names and don't
511 -- allow repeated variables...?)
512 updateAmap newm amap
513 = newm ++ filter (\ (x, _) -> not (elem x (map fst newm))) amap
514 findTag i [] = Nothing
515 findTag i (ConCase n j ns sc : xs) | i == j = Just (ns, sc)
516 findTag i (_ : xs) = findTag i xs
518 findDefault [] = Nothing
519 findDefault (DefaultCase sc : xs) = Just sc
520 findDefault (_ : xs) = findDefault xs
522 findConst c [] = Nothing
523 findConst c (ConstCase c' v : xs) | c == c' = Just v
524 findConst IType (ConCase n 1 [] v : xs) = Just v
525 findConst FlType (ConCase n 2 [] v : xs) = Just v
526 findConst ChType (ConCase n 3 [] v : xs) = Just v
527 findConst StrType (ConCase n 4 [] v : xs) = Just v
528 findConst PtrType (ConCase n 5 [] v : xs) = Just v
529 findConst W8Type (ConCase n 6 [] v : xs) = Just v
530 findConst W16Type (ConCase n 7 [] v : xs) = Just v
531 findConst c (_ : xs) = findConst c xs
533 getValArgs (HApp t env args) = (t, env, args)
534 getValArgs t = (t, [], [])
536convEq' ctxt x y = evalStateT (convEq ctxt x y) (0, [])
538convEq :: Context -> TT Name -> TT Name -> StateT UCs TC Bool
539convEq ctxt = ceq [] where
540 ceq :: [(Name, Name)] -> TT Name -> TT Name -> StateT UCs TC Bool
541 ceq ps (P xt x _) (P yt y _)
542 | (xt == yt && x ==y ) || (x, y) `elem` ps || (y,x) `elem` ps = return True
543 | otherwise = sameDefs ps x y
544 ceq ps (V x) (V y) = return (x == y)
545 ceq ps (Bind _ xb xs) (Bind _ yb ys)
546 = liftM2 (&&) (ceqB ps xb yb) (ceq ps xs ys)
547 where
548 ceqB ps (Let v t) (Let v' t') = liftM2 (&&) (ceq ps v v') (ceq ps t t')
549 ceqB ps (Guess v t) (Guess v' t') = liftM2 (&&) (ceq ps v v') (ceq ps t t')
550 ceqB ps b b' = ceq ps (binderTy b) (binderTy b')
551 ceq ps (App fx ax) (App fy ay) = liftM2 (&&) (ceq ps fx fy) (ceq ps ax ay)
552 ceq ps (Constant x) (Constant y) = return (x == y)
553 ceq ps (Set x) (Set y) = do (v, cs) <- get
554 put (v, ULE x y : cs)
555 return True
556 ceq ps Erased _ = return True
557 ceq ps _ Erased = return True
558 ceq ps _ _ = return False
560 caseeq ps (Case n cs) (Case n' cs') = caseeqA ((n,n'):ps) cs cs'
561 where
562 caseeqA ps (ConCase x i as sc : rest) (ConCase x' i' as' sc' : rest')
563 = do q1 <- caseeq (zip as as' ++ ps) sc sc'
564 q2 <- caseeqA ps rest rest'
565 return $ x == x' && i == i' && q1 && q2
566 caseeqA ps (ConstCase x sc : rest) (ConstCase x' sc' : rest')
567 = do q1 <- caseeq ps sc sc'
568 q2 <- caseeqA ps rest rest'
569 return $ x == x' && q1 && q2
570 caseeqA ps (DefaultCase sc : rest) (DefaultCase sc' : rest')
571 = liftM2 (&&) (caseeq ps sc sc') (caseeqA ps rest rest')
572 caseeqA ps [] [] = return True
573 caseeqA ps _ _ = return False
574 caseeq ps (STerm x) (STerm y) = ceq ps x y
575 caseeq ps (UnmatchedCase _) (UnmatchedCase _) = return True
576 caseeq ps _ _ = return False
578 sameDefs ps x y = case (lookupDef Nothing x ctxt, lookupDef Nothing y ctxt) of
579 ([Function _ xdef], [Function _ ydef])
580 -> ceq ((x,y):ps) xdef ydef
581 ([CaseOp _ _ _ _ _ _ xdef _ _],
582 [CaseOp _ _ _ _ _ _ ydef _ _])
583 -> caseeq ((x,y):ps) xdef ydef
584 _ -> return False
586-- SPECIALISATION -----------------------------------------------------------
587-- We need too much control to be able to do this by tweaking the main
588-- evaluator
590spec :: Context -> Ctxt [Bool] -> Env -> TT Name -> Eval (TT Name)
591spec ctxt statics genv tm = error "spec undefined"
593-- CONTEXTS -----------------------------------------------------------------
595{- A definition is either a simple function (just an expression with a type),
596 a constant, which could be a data or type constructor, an axiom or as an
597 yet undefined function, or an Operator.
598 An Operator is a function which explains how to reduce.
599 A CaseOp is a function defined by a simple case tree -}
601data Def = Function Type Term
602 | TyDecl NameType Type
603 | Operator Type Int ([Value] -> Maybe Value)
604 | CaseOp Bool Bool -- compile-time/run-time inlinable
605 Type
606 [Either Term (Term, Term)] -- original definition
607 [([Name], Term, Term)] -- simplified definition
608 [Name] SC -- Compile time case definition
609 [Name] SC -- Run time cae definitions
610{-!
611deriving instance Binary Def
612!-}
614instance Show Def where
615 show (Function ty tm) = "Function: " ++ show (ty, tm)
616 show (TyDecl nt ty) = "TyDecl: " ++ show nt ++ " " ++ show ty
617 show (Operator ty _ _) = "Operator: " ++ show ty
618 show (CaseOp _ _ ty ps_in ps ns sc ns' sc')
619 = "Case: " ++ show ty ++ " " ++ show ps ++ "\n" ++
620 show ns ++ " " ++ show sc ++ "\n" ++
621 show ns' ++ " " ++ show sc'
622-- We need this for serialising Def. Fortunately, it never gets used because
623-- we'll never serialise a primitive operator
625instance Binary (a -> b) where
626 put x = return ()
627 get = error "Getting a function"
629-------
631-- Frozen => doesn't reduce
632-- Hidden => doesn't reduce and invisible to type checker
634data Accessibility = Public | Frozen | Hidden
635 deriving (Show, Eq)
637data Totality = Total [Int] -- well-founded arguments
638 | Productive
639 | Partial PReason
640 | Unchecked
641 deriving Eq
643data PReason = Other [Name] | Itself | NotCovering | NotPositive | UseUndef Name
644 | BelieveMe | Mutual [Name] | NotProductive
645 deriving (Show, Eq)
647instance Show Totality where
648 show (Total args)= "Total" -- ++ show args ++ " decreasing arguments"
649 show Productive = "Productive" -- ++ show args ++ " decreasing arguments"
650 show Unchecked = "not yet checked for totality"
651 show (Partial Itself) = "possibly not total as it is not well founded"
652 show (Partial NotCovering) = "not total as there are missing cases"
653 show (Partial NotPositive) = "not strictly positive"
654 show (Partial NotProductive) = "not productive"
655 show (Partial BelieveMe) = "not total due to use of believe_me in proof"
656 show (Partial (Other ns)) = "possibly not total due to: " ++ showSep ", " (map show ns)
657 show (Partial (Mutual ns)) = "possibly not total due to recursive path " ++
658 showSep " --> " (map show ns)
660{-!
661deriving instance Binary Accessibility
662!-}
664{-!
665deriving instance Binary Totality
666!-}
668{-!
669deriving instance Binary PReason
670!-}
672data Context = MkContext {
673 uconstraints :: [UConstraint],
674 next_tvar :: Int,
675 definitions :: Ctxt (Def, Accessibility, Totality)
676 }
678initContext = MkContext [] 0 emptyContext
680ctxtAlist :: Context -> [(Name, Def)]
681ctxtAlist ctxt = map (\(n, (d, a, t)) -> (n, d)) $ toAlist (definitions ctxt)
683veval ctxt env t = evalState (eval False ctxt threshold [] env t []) initEval
685addToCtxt :: Name -> Term -> Type -> Context -> Context
686addToCtxt n tm ty uctxt
687 = let ctxt = definitions uctxt
688 ctxt' = addDef n (Function ty tm, Public, Unchecked) ctxt in
689 uctxt { definitions = ctxt' }
691setAccess :: Name -> Accessibility -> Context -> Context
692setAccess n a uctxt
693 = let ctxt = definitions uctxt
694 ctxt' = updateDef n (\ (d, _, t) -> (d, a, t)) ctxt in
695 uctxt { definitions = ctxt' }
697setTotal :: Name -> Totality -> Context -> Context
698setTotal n t uctxt
699 = let ctxt = definitions uctxt
700 ctxt' = updateDef n (\ (d, a, _) -> (d, a, t)) ctxt in
701 uctxt { definitions = ctxt' }
703addCtxtDef :: Name -> Def -> Context -> Context
704addCtxtDef n d c = let ctxt = definitions c
705 ctxt' = addDef n (d, Public, Unchecked) ctxt in
706 c { definitions = ctxt' }
708addTyDecl :: Name -> Type -> Context -> Context
709addTyDecl n ty uctxt
710 = let ctxt = definitions uctxt
711 ctxt' = addDef n (TyDecl Ref ty, Public, Unchecked) ctxt in
712 uctxt { definitions = ctxt' }
714addDatatype :: Datatype Name -> Context -> Context
715addDatatype (Data n tag ty cons) uctxt
716 = let ctxt = definitions uctxt
717 ty' = normalise uctxt [] ty
718 ctxt' = addCons 0 cons (addDef n
719 (TyDecl (TCon tag (arity ty')) ty, Public, Unchecked) ctxt) in
720 uctxt { definitions = ctxt' }
721 where
722 addCons tag [] ctxt = ctxt
723 addCons tag ((n, ty) : cons) ctxt
724 = let ty' = normalise uctxt [] ty in
725 addCons (tag+1) cons (addDef n
726 (TyDecl (DCon tag (arity ty')) ty, Public, Unchecked) ctxt)
728addCasedef :: Name -> Bool -> Bool -> Bool ->
729 [Either Term (Term, Term)] ->
730 [([Name], Term, Term)] ->
731 [([Name], Term, Term)] ->
732 Type -> Context -> Context
733addCasedef n alwaysInline tcase covering ps_in ps psrt ty uctxt
734 = let ctxt = definitions uctxt
735 access = case lookupDefAcc Nothing n False uctxt of
736 [(_, acc)] -> acc
737 _ -> Public
738 ctxt' = case (simpleCase tcase covering CompileTime (FC "" 0) ps,
739 simpleCase tcase covering RunTime (FC "" 0) psrt) of
740 (OK (CaseDef args sc _), OK (CaseDef args' sc' _)) ->
741 let inl = alwaysInline in
742 addDef n (CaseOp inl (inl || small n args sc')
743 ty ps_in ps args sc args' sc',
744 access, Unchecked) ctxt in
745 uctxt { definitions = ctxt' }
747simplifyCasedef :: Name -> Context -> Context
748simplifyCasedef n uctxt
749 = let ctxt = definitions uctxt
750 ctxt' = case lookupCtxt Nothing n ctxt of
751 [(CaseOp inl inr ty [] ps args sc args' sc', acc, tot)] ->
752 ctxt -- nothing to simplify (or already done...)
753 [(CaseOp inl inr ty ps_in ps args sc args' sc', acc, tot)] ->
754 let pdef = map debind $ map simpl ps_in in
755 case simpleCase False True CompileTime (FC "" 0) pdef of
756 OK (CaseDef args sc _) ->
757 addDef n (CaseOp inl inr
758 ty ps_in ps args sc args' sc',
759 acc, tot) ctxt
760 _ -> ctxt in
761 uctxt { definitions = ctxt' }
762 where
763 depat acc (Bind n (PVar t) sc)
764 = depat (n : acc) (instantiate (P Bound n t) sc)
765 depat acc x = (acc, x)
766 debind (Right (x, y)) = let (vs, x') = depat [] x
767 (_, y') = depat [] y in
768 (vs, x', y')
769 debind (Left x) = let (vs, x') = depat [] x in
770 (vs, x', Impossible)
771 simpl (Right (x, y)) = Right (x, simplify uctxt False [] y)
772 simpl t = t
774addOperator :: Name -> Type -> Int -> ([Value] -> Maybe Value) ->
775 Context -> Context
776addOperator n ty a op uctxt
777 = let ctxt = definitions uctxt
778 ctxt' = addDef n (Operator ty a op, Public, Unchecked) ctxt in
779 uctxt { definitions = ctxt' }
781tfst (a, _, _) = a
783lookupNames :: Maybe [String] -> Name -> Context -> [Name]
784lookupNames root n ctxt
785 = let ns = lookupCtxtName root n (definitions ctxt) in
786 map fst ns
788lookupTy :: Maybe [String] -> Name -> Context -> [Type]
789lookupTy root n ctxt
790 = do def <- lookupCtxt root n (definitions ctxt)
791 case tfst def of
792 (Function ty _) -> return ty
793 (TyDecl _ ty) -> return ty
794 (Operator ty _ _) -> return ty
795 (CaseOp _ _ ty _ _ _ _ _ _) -> return ty
797isConName :: Maybe [String] -> Name -> Context -> Bool
798isConName root n ctxt
799 = or $ do def <- lookupCtxt root n (definitions ctxt)
800 case tfst def of
801 (TyDecl (DCon _ _) _) -> return True
802 (TyDecl (TCon _ _) _) -> return True
803 _ -> return False
805isFnName :: Maybe [String] -> Name -> Context -> Bool
806isFnName root n ctxt
807 = or $ do def <- lookupCtxt root n (definitions ctxt)
808 case tfst def of
809 (Function _ _) -> return True
810 (Operator _ _ _) -> return True
811 (CaseOp _ _ _ _ _ _ _ _ _) -> return True
812 _ -> return False
814lookupP :: Maybe [String] -> Name -> Context -> [Term]
815lookupP root n ctxt
816 = do def <- lookupCtxt root n (definitions ctxt)
817 p <- case def of
818 (Function ty tm, a, _) -> return (P Ref n ty, a)
819 (TyDecl nt ty, a, _) -> return (P nt n ty, a)
820 (CaseOp _ _ ty _ _ _ _ _ _, a, _) -> return (P Ref n ty, a)
821 (Operator ty _ _, a, _) -> return (P Ref n ty, a)
822 case snd p of
823 Hidden -> []
824 _ -> return (fst p)
826lookupDef :: Maybe [String] -> Name -> Context -> [Def]
827lookupDef root n ctxt = map tfst $ lookupCtxt root n (definitions ctxt)
829lookupDefAcc :: Maybe [String] -> Name -> Bool -> Context ->
830 [(Def, Accessibility)]
831lookupDefAcc root n mkpublic ctxt
832 = map mkp $ lookupCtxt root n (definitions ctxt)
833 where mkp (d, a, _) = if mkpublic then (d, Public) else (d, a)
835lookupTotal :: Name -> Context -> [Totality]
836lookupTotal n ctxt = map mkt $ lookupCtxt Nothing n (definitions ctxt)
837 where mkt (d, a, t) = t
839lookupVal :: Maybe [String] -> Name -> Context -> [Value]
840lookupVal root n ctxt
841 = do def <- lookupCtxt root n (definitions ctxt)
842 case tfst def of
843 (Function _ htm) -> return (veval ctxt [] htm)
844 (TyDecl nt ty) -> return (VP nt n (veval ctxt [] ty))
846lookupTyEnv :: Name -> Env -> Maybe (Int, Type)
847lookupTyEnv n env = li n 0 env where
848 li n i [] = Nothing
849 li n i ((x, b): xs)
850 | n == x = Just (i, binderTy b)
851 | otherwise = li n (i+1) xs