1{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances,
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(..), Quote(..), evalState, initEval) where
15import Control.Monad.State
16import qualified Data.Binary as B
17import Data.Binary hiding (get, put)
22data EvalState = ES { limited :: [(Name, Int)] }
24type Eval a = State EvalState a
26data EvalOpt = Spec | HNF | Simplify Bool | AtREPL
31-- VALUES (as HOAS) ---------------------------------------------------------
32-- | A HOAS representation of values
33data Value = VP NameType Name Value
35 | VBind Name (Binder Value) (Value -> Eval Value)
40-- | VLazy Env [Value] Term
43data HNF = HP NameType Name (TT Name)
45 | HBind Name (Binder HNF) (HNF -> Eval HNF)
46 | HApp HNF [HNF] [TT Name]
52instance Show Value where
53 show x = show $ evalState (quote 100 x) initEval
55instance Show (a -> b) where
58-- THE EVALUATOR ------------------------------------------------------------
60-- The environment is assumed to be "locally named" - i.e., not de Bruijn
62-- i.e. it's an intermediate environment that we have while type checking or
63-- while building a proof.
65-- | Normalise fully type checked terms (so, assume all names/let bindings resolved)
66normaliseC :: Context -> Env -> TT Name -> TT Name
68 = evalState (do val <- eval False ctxt [] env t []
71normaliseAll :: Context -> Env -> TT Name -> TT Name
72normaliseAll ctxt env t
73 = evalState (do val <- eval False ctxt [] env t [AtREPL]
76normalise :: Context -> Env -> TT Name -> TT Name
77normalise = normaliseTrace False
79normaliseTrace :: Bool -> Context -> Env -> TT Name -> TT Name
80normaliseTrace tr ctxt env t
81 = evalState (do val <- eval tr ctxt [] (map finalEntry env) (finalise t) []
84specialise :: Context -> Env -> [(Name, Int)] -> TT Name -> TT Name
85specialise ctxt env limits t
86 = evalState (do val <- eval False ctxt limits (map finalEntry env) (finalise t) []
87 quote 0 val) (initEval { limited = limits })
89-- | Like normalise, but we only reduce functions that are marked as okay to
90-- inline (and probably shouldn't reduce lets?)
91simplify :: Context -> Bool -> Env -> TT Name -> TT Name
92simplify ctxt runtime env t
93 = evalState (do val <- eval False ctxt [(UN "lazy", 0),
96 (map finalEntry env) (finalise t)
100-- | Reduce a term to head normal form
101hnf :: Context -> Env -> TT Name -> TT Name
103 = evalState (do val <- eval False ctxt []
106 quote 0 val) initEval
109-- unbindEnv env (quote 0 (eval ctxt (bindEnv env t)))
111finalEntry :: (Name, Binder (TT Name)) -> (Name, Binder (TT Name))
112finalEntry (n, b) = (n, fmap finalise b)
114bindEnv :: EnvTT n -> TT n -> TT n
116bindEnv ((n, Let t v):bs) tm = Bind n (NLet t v) (bindEnv bs tm)
117bindEnv ((n, b):bs) tm = Bind n b (bindEnv bs tm)
119unbindEnv :: EnvTT n -> TT n -> TT n
121unbindEnv (_:bs) (Bind n b sc) = unbindEnv bs sc
123usable :: Bool -> Name -> [(Name, Int)] -> (Bool, [(Name, Int)])
124usable _ _ ns@((MN 0 "STOP", _) : _) = (False, ns)
125usable True (UN "io_bind") ns = (False, ns)
126usable s n [] = (True, [])
127usable s n ns = case lookup n ns of
128 Just 0 -> (False, ns)
129 Just i -> (True, (n, abs (i-1)) : filter (\ (n', _) -> n/=n') ns)
130 _ -> if s then (True, (n, 0) : filter (\ (n', _) -> n/=n') ns)
131 else (True, (n, 100) : filter (\ (n', _) -> n/=n') ns)
133-- | Evaluate in a context of locally named things (i.e. not de Bruijn indexed,
134-- such as we might have during construction of a proof)
135eval :: Bool -> Context -> [(Name, Int)] -> Env -> TT Name ->
136 [EvalOpt] -> Eval Value
137eval traceon ctxt ntimes genv tm opts = ev ntimes [] True [] tm where
138 spec = Spec `elem` opts
139 simpl = Simplify True `elem` opts
140 atRepl = AtREPL `elem` opts
141 hnf = HNF `elem` opts
143 canSimplify inl inr n stk
144 = (Simplify False `elem` opts && (not inl || elem n stk))
145 || (Simplify True `elem` opts && (not inr || elem n stk))
147 ev ntimes stk top env (P _ n ty)
148 | Just (Let t v) <- lookup n genv = ev ntimes stk top env v
149 ev ntimes_in stk top env (P Ref n ty)
150 | not top && hnf = liftM (VP Ref n) (ev ntimes stk top env ty)
151 | (True, ntimes) <- usable simpl n ntimes_in
152 = do let val = lookupDefAcc Nothing n atRepl ctxt
154 [(Function _ tm, Public)] ->
155 ev ntimes (n:stk) True env tm
156 [(TyDecl nt ty, _)] -> do vty <- ev ntimes stk True env ty
158 [(CaseOp inl inr _ _ _ [] tree _ _, acc)]
159 | acc == Public || simpl -> -- unoptimised version
160 if canSimplify inl inr n stk
161 then liftM (VP Ref n) (ev ntimes stk top env ty)
162 else do c <- evCase ntimes (n:stk) top env [] [] tree
164 (Nothing, _) -> liftM (VP Ref n) (ev ntimes stk top env ty)
165 (Just v, _) -> return v
166 _ -> liftM (VP Ref n) (ev ntimes stk top env ty)
167 ev ntimes stk top env (P nt n ty) = liftM (VP nt n) (ev ntimes stk top env ty)
168 ev ntimes stk top env (V i) | i < length env = return $ env !! i
169 | otherwise = return $ VV i
170 ev ntimes stk top env (Bind n (Let t v) sc)
171-- | not simpl || vinstances 0 sc < 2
172 = do v' <- ev ntimes stk top env v --(finalise v)
173 sc' <- ev ntimes stk top (v' : env) sc
175{- | otherwise -- put this back when the Bind works properly
176 = do t' <- ev ntimes stk top env t
177 v' <- ev ntimes stk top env v --(finalise v)
178 -- use Tmp as a placeholder, then make it a variable reference
179 -- again when evaluation finished
180 sc' <- ev ntimes stk top (v' : env) sc
181 return $ VBind n (Let t' v') (\x -> return sc') -}
182 ev ntimes stk top env (Bind n (NLet t v) sc)
183 = do t' <- ev ntimes stk top env (finalise t)
184 v' <- ev ntimes stk top env (finalise v)
185 sc' <- ev ntimes stk top (v' : env) sc
186 return $ VBind n (Let t' v') (\x -> return sc')
187 ev ntimes stk top env (Bind n b sc)
188 = do b' <- vbind env b
189 return $ VBind n b' (\x -> ev ntimes stk False (x:env) sc)
192 = fmapMB (\tm -> ev ((MN 0 "STOP", 0) : ntimes)
193 stk top env (finalise tm)) t
195 = fmapMB (\tm -> ev ntimes stk top env (finalise tm)) t
196-- ev ntimes stk top env (App (App (P _ laz _) _) a)
198-- = trace (showEnvDbg genv a) $ ev ntimes stk top env a
199 ev ntimes stk top env (App f a)
200 = do f' <- ev ntimes stk False env f
201 a' <- ev ntimes stk False env a
202 evApply ntimes stk top env [a'] f'
203 ev ntimes stk top env (Constant c) = return $ VConstant c
204 ev ntimes stk top env Erased = return VErased
205 ev ntimes stk top env (TType i) = return $ VType i
207 evApply ntimes stk top env args (VApp f a) =
208 evApply ntimes stk top env (a:args) f
209 evApply ntimes stk top env args f = apply ntimes stk top env f args
211 apply ntimes stk top env (VBind n (Lam t) sc) (a:as)
213 app <- apply ntimes stk top env a' as
215-- apply ntimes stk False env f args
216-- | spec = specApply ntimes stk env f args
217 apply ntimes_in stk top env f@(VP Ref n ty) args
218 | not top && hnf = case args of
220 _ -> return $ unload env f args
221 | (True, ntimes) <- usable simpl n ntimes_in
222 = traceWhen traceon (show stk) $
223 do let val = lookupDefAcc Nothing n atRepl ctxt
225 [(CaseOp inl inr _ _ _ ns tree _ _, acc)]
226 | acc == Public -> -- unoptimised version
227 if canSimplify inl inr n stk
228 then return $ unload env (VP Ref n ty) args
229 else do c <- evCase ntimes (n:stk) top env ns args tree
231 (Nothing, _) -> return $ unload env (VP Ref n ty) args
232 (Just v, rest) -> evApply ntimes stk top env rest v
233 [(Operator _ i op, _)] ->
234 if (i <= length args)
235 then case op (take i args) of
236 Nothing -> return $ unload env (VP Ref n ty) args
237 Just v -> evApply ntimes stk top env (drop i args) v
238 else return $ unload env (VP Ref n ty) args
241 _ -> return $ unload env f args
242 apply ntimes stk top env f (a:as) = return $ unload env f (a:as)
243 apply ntimes stk top env f [] = return f
245-- specApply stk env f@(VP Ref n ty) args
246-- = case lookupCtxt Nothing n statics of
248-- then trace (show (n, map fst (filter (\ (_, s) -> s) (zip args as)))) $
249-- return $ unload env f args
250-- else return $ unload env f args
251-- _ -> return $ unload env f args
252-- specApply stk env f args = return $ unload env f args
255 unload env f (a:as) = unload env (VApp f a) as
257 evCase ntimes stk top env ns args tree
258 | length ns <= length args
259 = do let args' = take (length ns) args
260 let rest = drop (length ns) args
261 t <- evTree ntimes stk top env
262 (zipWith (\n t -> (n, t)) ns args') tree
264 | otherwise = return (Nothing, args)
266 evTree :: [(Name, Int)] -> [Name] -> Bool ->
267 [Value] -> [(Name, Value)] -> SC -> Eval (Maybe Value)
268 evTree ntimes stk top env amap (UnmatchedCase str) = return Nothing
269 evTree ntimes stk top env amap (STerm tm)
270 = do let etm = pToVs (map fst amap) tm
271 etm' <- ev ntimes stk (not (conHeaded tm))
272 (map snd amap ++ env) etm
274 evTree ntimes stk top env amap (Case n alts)
275 = case lookup n amap of
276 Just v -> do c <- chooseAlt env v (getValArgs v) alts amap
278 Just (altmap, sc) -> evTree ntimes stk top env altmap sc
279 _ -> do c' <- chooseAlt' ntimes stk env v (getValArgs v) alts amap
281 Just (altmap, sc) -> evTree ntimes stk top env altmap sc
284 evTree ntimes stk top env amap ImpossibleCase = return Nothing
286 conHeaded tm@(App _ _)
287 | (P (DCon _ _) _ _, args) <- unApply tm = True
290 chooseAlt' ntimes stk env _ (f, args) alts amap
291 = do f' <- apply ntimes stk True env f args
292 chooseAlt env f' (getValArgs f') alts amap
294 chooseAlt :: [Value] -> Value -> (Value, [Value]) -> [CaseAlt] -> [(Name, Value)] ->
295 Eval (Maybe ([(Name, Value)], SC))
296 chooseAlt env _ (VP (DCon i a) _ _, args) alts amap
297 | Just (ns, sc) <- findTag i alts = return $ Just (updateAmap (zip ns args) amap, sc)
298 | Just v <- findDefault alts = return $ Just (amap, v)
299 chooseAlt env _ (VP (TCon i a) _ _, args) alts amap
300 | Just (ns, sc) <- findTag i alts = return $ Just (updateAmap (zip ns args) amap, sc)
301 | Just v <- findDefault alts = return $ Just (amap, v)
302 chooseAlt env _ (VConstant c, []) alts amap
303 | Just v <- findConst c alts = return $ Just (amap, v)
304 | Just v <- findDefault alts = return $ Just (amap, v)
305 chooseAlt _ _ _ _ _ = return Nothing
307 -- Replace old variable names in the map with new matches
308 -- (This is possibly unnecessary since we make unique names and don't
309 -- allow repeated variables...?)
311 = newm ++ filter (\ (x, _) -> not (elem x (map fst newm))) amap
312 findTag i [] = Nothing
313 findTag i (ConCase n j ns sc : xs) | i == j = Just (ns, sc)
314 findTag i (_ : xs) = findTag i xs
316 findDefault [] = Nothing
317 findDefault (DefaultCase sc : xs) = Just sc
318 findDefault (_ : xs) = findDefault xs
320 findConst c [] = Nothing
321 findConst c (ConstCase c' v : xs) | c == c' = Just v
322 findConst IType (ConCase n 1 [] v : xs) = Just v
323 findConst FlType (ConCase n 2 [] v : xs) = Just v
324 findConst ChType (ConCase n 3 [] v : xs) = Just v
325 findConst StrType (ConCase n 4 [] v : xs) = Just v
326 findConst PtrType (ConCase n 5 [] v : xs) = Just v
327 findConst c (_ : xs) = findConst c xs
329 getValArgs tm = getValArgs' tm []
330 getValArgs' (VApp f a) as = getValArgs' f (a:as)
331 getValArgs' f as = (f, as)
333tmpToV i (VTmp 0) = return $ VV i
334tmpToV i (VP nt n v) = liftM (VP nt n) (tmpToV i v)
336tmpToV i (VBind n b sc) = do b' <- fmapMB (tmpToV i) b
337 let sc' = \x -> do x' <- sc x
339 return (VBind n b' sc')
340tmpToV i (VApp f a) = liftM2 VApp (tmpToV i f) (tmpToV i a)
344 quote :: Int -> a -> Eval (TT Name)
346instance Quote Value where
347 quote i (VP nt n v) = liftM (P nt n) (quote i v)
348 quote i (VV x) = return $ V x
349 quote i (VBind n b sc) = do sc' <- sc (VTmp i)
351 liftM (Bind n b') (quote (i+1) sc')
352 where quoteB t = fmapMB (quote i) t
353 quote i (VApp f a) = liftM2 App (quote i f) (quote i a)
354 quote i (VType u) = return $ TType u
355 quote i VErased = return $ Erased
356 quote i (VConstant c) = return $ Constant c
357 quote i (VTmp x) = return $ V (i - x - 1)
359instance Quote HNF where
360 quote i (HP nt n t) = return (P nt n t)
361 quote i (HV x) = return $ V x
362 quote i (HBind n b sc) = do sc' <- sc (HTmp i)
364 liftM (Bind n b') (quote (i+1) sc')
365 where quoteB t = fmapMB (quote i) t
366 quote i (HApp f env as) = do f' <- quote i f
367 as' <- mapM (iEnv env) as
368 return $ mkApp f' as'
369 where iEnv [] a = return a
370 iEnv (x:xs) a = do x' <- quote i x
371 iEnv xs (weakenTm (-1) (instantiate x' a))
372 quote i (HType u) = return $ TType u
373 quote i (HConstant c) = return $ Constant c
374 quote i (HTmp x) = return $ V (i - x - 1)
376wknV :: Int -> Value -> Eval Value
377wknV i (VV x) = return $ VV (x + i)
378wknV i (VBind n b sc) = do b' <- fmapMB (wknV i) b
379 return $ VBind n b' (\x -> do x' <- sc x
381wknV i (VApp f a) = liftM2 VApp (wknV i f) (wknV i a)
384wknH :: Int -> HNF -> Eval HNF
385wknH i (HV x) = return $ HV (x + i)
386wknH i (HBind n b sc) = do b' <- fmapMB (wknH i) b
387 return $ HBind n b' (\x -> do x' <- sc x
389wknH i (HApp f env as) = liftM3 HApp (wknH i f) (return env)
393-- HEAD NORMAL FORM ---------------------------------------------------------
395eval_hnf :: Context -> Ctxt [Bool] -> Env -> TT Name -> Eval HNF
396eval_hnf ctxt statics genv tm = ev [] tm where
397 ev :: [HNF] -> TT Name -> Eval HNF
399 | Just (Let t v) <- lookup n genv = ev env v
400 ev env (P Ref n ty) = case lookupDef Nothing n ctxt of
401 [Function _ t] -> ev env t
402 [TyDecl nt ty] -> return $ HP nt n ty
403 [CaseOp inl _ _ _ _ [] tree _ _] ->
404 do c <- evCase env [] [] tree
406 (Nothing, _, _) -> return $ HP Ref n ty
407 (Just v, _, _) -> return v
408 _ -> return $ HP Ref n ty
409 ev env (P nt n ty) = return $ HP nt n ty
410 ev env (V i) | i < length env = return $ env !! i
411 | otherwise = return $ HV i
412 ev env (Bind n (Let t v) sc)
413 = do v' <- ev env (finalise v)
414 sc' <- ev (v' : env) sc
417 = do b' <- hbind env b
418 return $ HBind n b' (\x -> ev (x : env) sc)
419 where hbind env t = fmapMB (\tm -> ev env (finalise tm)) t
420 ev env (App f a) = evApply env [a] f
421 ev env (Constant c) = return $ HConstant c
422 ev env (TType i) = return $ HType i
424 evApply env args (App f a) = evApply env (a : args) f
425 evApply env args f = do f' <- ev env f
428 apply env (HBind n (Lam t) sc) (a:as) = do a' <- ev env a
430 app <- apply env sc' as
432 apply env (HP Ref n ty) args
433 | [CaseOp _ _ _ _ _ ns tree _ _] <- lookupDef Nothing n ctxt
434 = do c <- evCase env ns args tree
436 (Nothing, _, env') -> return $ unload env' (HP Ref n ty) args
437 (Just v, rest, env') -> do v' <- quote 0 v
439-- | Just (Operator _ i op) <- lookupDef n ctxt
440-- = if (i <= length args)
441-- then case op (take i args) of
442-- Nothing -> return $ unload env (HP Ref n ty) args
443-- Just v -> evApply env (drop i args) v
444-- else return $ unload env (HP Ref n ty) args
445 apply env f (a:as) = return $ unload env f (a:as)
446 apply env f [] = return f
449 unload env f as = HApp f env as
451 evCase env ns args tree
452 | length ns <= length args
453 = do let args' = take (length ns) args
454 let rest = drop (length ns) args
455 (t, env') <- evTree env (zipWith (\n t -> (n, t)) ns args') tree
456 return (t, rest, env')
457 | otherwise = return (Nothing, args, env)
459 evTree :: [HNF] -> [(Name, TT Name)] -> SC -> Eval (Maybe HNF, [HNF])
460 evTree env amap (UnmatchedCase str) = return (Nothing, env)
461 evTree env amap (STerm tm)
462 = do let etm = pToVs (map fst amap) tm
463 amap' <- mapM (ev env) (map snd amap)
464 envw <- mapM (wknH (length amap)) env
465 let env' = amap' ++ envw
466 etm' <- trace (show etm) $ ev env' etm
468 trace ("Ev: " ++ show (etm, etmq)) $ return $ (Just etm', env')
469 evTree env amap (Case n alts)
470 = case lookup n amap of
471 Just v -> do v' <- ev env v
472 case chooseAlt v' (getValArgs v') alts amap of
473 Just (altmap, sc) -> evTree env altmap sc
474 _ -> return (Nothing, env)
476 chooseAlt :: HNF -> (HNF, [HNF], [TT Name]) ->
477 [CaseAlt] -> [(Name, TT Name)] ->
478 Maybe ([(Name, TT Name)], SC)
479 chooseAlt _ (HP (DCon i a) _ _, env, args) alts amap
480 | Just (ns, sc) <- findTag i alts = Just (updateAmap (zip ns args) amap, sc)
481 | Just v <- findDefault alts = Just (amap, v)
482 chooseAlt _ (HP (TCon i a) _ _, env, args) alts amap
483 | Just (ns, sc) <- findTag i alts = Just (updateAmap (zip ns args) amap, sc)
484 | Just v <- findDefault alts = Just (amap, v)
485 chooseAlt _ (HConstant c, env, []) alts amap
486 | Just v <- findConst c alts = Just (amap, v)
487 | Just v <- findDefault alts = Just (amap, v)
488 chooseAlt _ _ _ _ = Nothing
490 -- Replace old variable names in the map with new matches
491 -- (This is possibly unnecessary since we make unique names and don't
492 -- allow repeated variables...?)
494 = newm ++ filter (\ (x, _) -> not (elem x (map fst newm))) amap
495 findTag i [] = Nothing
496 findTag i (ConCase n j ns sc : xs) | i == j = Just (ns, sc)
497 findTag i (_ : xs) = findTag i xs
499 findDefault [] = Nothing
500 findDefault (DefaultCase sc : xs) = Just sc
501 findDefault (_ : xs) = findDefault xs
503 findConst c [] = Nothing
504 findConst c (ConstCase c' v : xs) | c == c' = Just v
505 findConst IType (ConCase n 1 [] v : xs) = Just v
506 findConst FlType (ConCase n 2 [] v : xs) = Just v
507 findConst ChType (ConCase n 3 [] v : xs) = Just v
508 findConst StrType (ConCase n 4 [] v : xs) = Just v
509 findConst PtrType (ConCase n 5 [] v : xs) = Just v
510 findConst BIType (ConCase n 6 [] v : xs) = Just v
511 findConst B8Type (ConCase n 7 [] v : xs) = Just v
512 findConst B16Type (ConCase n 8 [] v : xs) = Just v
513 findConst B32Type (ConCase n 9 [] v : xs) = Just v
514 findConst B64Type (ConCase n 10 [] v : xs) = Just v
515 findConst c (_ : xs) = findConst c xs
517 getValArgs (HApp t env args) = (t, env, args)
518 getValArgs t = (t, [], [])
520convEq' ctxt x y = evalStateT (convEq ctxt x y) (0, [])
522convEq :: Context -> TT Name -> TT Name -> StateT UCs TC Bool
523convEq ctxt = ceq [] where
524 ceq :: [(Name, Name)] -> TT Name -> TT Name -> StateT UCs TC Bool
525 ceq ps (P xt x _) (P yt y _)
526 | x == y || (x, y) `elem` ps || (y,x) `elem` ps = return True
527 | otherwise = sameDefs ps x y
528 ceq ps x (Bind n (Lam t) (App y (V 0))) = ceq ps x y
529 ceq ps (Bind n (Lam t) (App x (V 0))) y = ceq ps x y
530 ceq ps x (Bind n (Lam t) (App y (P Bound n' _)))
531 | n == n' = ceq ps x y
532 ceq ps (Bind n (Lam t) (App x (P Bound n' _))) y
533 | n == n' = ceq ps x y
534 ceq ps (V x) (V y) = return (x == y)
535 ceq ps (Bind _ xb xs) (Bind _ yb ys)
536 = liftM2 (&&) (ceqB ps xb yb) (ceq ps xs ys)
538 ceqB ps (Let v t) (Let v' t') = liftM2 (&&) (ceq ps v v') (ceq ps t t')
539 ceqB ps (Guess v t) (Guess v' t') = liftM2 (&&) (ceq ps v v') (ceq ps t t')
540 ceqB ps b b' = ceq ps (binderTy b) (binderTy b')
541 ceq ps (App fx ax) (App fy ay) = liftM2 (&&) (ceq ps fx fy) (ceq ps ax ay)
542 ceq ps (Constant x) (Constant y) = return (x == y)
543 ceq ps (TType x) (TType y) = do (v, cs) <- get
544 put (v, ULE x y : cs)
546 ceq ps Erased _ = return True
547 ceq ps _ Erased = return True
548 ceq ps _ _ = return False
550 caseeq ps (Case n cs) (Case n' cs') = caseeqA ((n,n'):ps) cs cs'
552 caseeqA ps (ConCase x i as sc : rest) (ConCase x' i' as' sc' : rest')
553 = do q1 <- caseeq (zip as as' ++ ps) sc sc'
554 q2 <- caseeqA ps rest rest'
555 return $ x == x' && i == i' && q1 && q2
556 caseeqA ps (ConstCase x sc : rest) (ConstCase x' sc' : rest')
557 = do q1 <- caseeq ps sc sc'
558 q2 <- caseeqA ps rest rest'
559 return $ x == x' && q1 && q2
560 caseeqA ps (DefaultCase sc : rest) (DefaultCase sc' : rest')
561 = liftM2 (&&) (caseeq ps sc sc') (caseeqA ps rest rest')
562 caseeqA ps [] [] = return True
563 caseeqA ps _ _ = return False
564 caseeq ps (STerm x) (STerm y) = ceq ps x y
565 caseeq ps (UnmatchedCase _) (UnmatchedCase _) = return True
566 caseeq ps _ _ = return False
568 sameDefs ps x y = case (lookupDef Nothing x ctxt, lookupDef Nothing y ctxt) of
569 ([Function _ xdef], [Function _ ydef])
570 -> ceq ((x,y):ps) xdef ydef
571 ([CaseOp _ _ _ _ _ _ xdef _ _],
572 [CaseOp _ _ _ _ _ _ ydef _ _])
573 -> caseeq ((x,y):ps) xdef ydef
576-- SPECIALISATION -----------------------------------------------------------
577-- We need too much control to be able to do this by tweaking the main
580spec :: Context -> Ctxt [Bool] -> Env -> TT Name -> Eval (TT Name)
581spec ctxt statics genv tm = error "spec undefined"
583-- CONTEXTS -----------------------------------------------------------------
585{-| A definition is either a simple function (just an expression with a type),
586 a constant, which could be a data or type constructor, an axiom or as an
587 yet undefined function, or an Operator.
588 An Operator is a function which explains how to reduce.
589 A CaseOp is a function defined by a simple case tree -}
591data Def = Function Type Term
592 | TyDecl NameType Type
593 | Operator Type Int ([Value] -> Maybe Value)
594 | CaseOp Bool Bool -- compile-time/run-time inlinable
596 [Either Term (Term, Term)] -- original definition
597 [([Name], Term, Term)] -- simplified definition
598 [Name] SC -- Compile time case definition
599 [Name] SC -- Run time cae definitions
601deriving instance Binary Def
604instance Show Def where
605 show (Function ty tm) = "Function: " ++ show (ty, tm)
606 show (TyDecl nt ty) = "TyDecl: " ++ show nt ++ " " ++ show ty
607 show (Operator ty _ _) = "Operator: " ++ show ty
608 show (CaseOp inlc inlr ty ps_in ps ns sc ns' sc')
609 = "Case: " ++ show ty ++ " " ++ show ps ++ "\n" ++
610 show ns ++ " " ++ show sc ++ "\n" ++
611 show ns' ++ " " ++ show sc' ++ "\n" ++
612 if inlc then "Inlinable\n" else "Not inlinable\n"
614-- We need this for serialising Def. Fortunately, it never gets used because
615-- we'll never serialise a primitive operator
617instance Binary (a -> b) where
619 get = error "Getting a function"
623-- Frozen => doesn't reduce
624-- Hidden => doesn't reduce and invisible to type checker
626data Accessibility = Public | Frozen | Hidden
629-- | The result of totality checking
630data Totality = Total [Int] -- ^ well-founded arguments
631 | Productive -- ^ productive
636-- | Reasons why a function may not be total
637data PReason = Other [Name] | Itself | NotCovering | NotPositive | UseUndef Name
638 | BelieveMe | Mutual [Name] | NotProductive
641instance Show Totality where
642 show (Total args)= "Total" -- ++ show args ++ " decreasing arguments"
643 show Productive = "Productive" -- ++ show args ++ " decreasing arguments"
644 show Unchecked = "not yet checked for totality"
645 show (Partial Itself) = "possibly not total as it is not well founded"
646 show (Partial NotCovering) = "not total as there are missing cases"
647 show (Partial NotPositive) = "not strictly positive"
648 show (Partial NotProductive) = "not productive"
649 show (Partial BelieveMe) = "not total due to use of believe_me in proof"
650 show (Partial (Other ns)) = "possibly not total due to: " ++ showSep ", " (map show ns)
651 show (Partial (Mutual ns)) = "possibly not total due to recursive path " ++
652 showSep " --> " (map show ns)
655deriving instance Binary Accessibility
659deriving instance Binary Totality
663deriving instance Binary PReason
666-- | Contexts used for global definitions and for proof state. They contain
667-- universe constraints and existing definitions.
668data Context = MkContext {
669 uconstraints :: [UConstraint],
671 definitions :: Ctxt (Def, Accessibility, Totality)
674-- | The initial empty context
675initContext = MkContext [] 0 emptyContext
677-- | Get the definitions from a context
678ctxtAlist :: Context -> [(Name, Def)]
679ctxtAlist ctxt = map (\(n, (d, a, t)) -> (n, d)) $ toAlist (definitions ctxt)
681veval ctxt env t = evalState (eval False ctxt [] env t []) initEval
683addToCtxt :: Name -> Term -> Type -> Context -> Context
684addToCtxt n tm ty uctxt
685 = let ctxt = definitions uctxt
686 ctxt' = addDef n (Function ty tm, Public, Unchecked) ctxt in
687 uctxt { definitions = ctxt' }
689setAccess :: Name -> Accessibility -> Context -> Context
691 = let ctxt = definitions uctxt
692 ctxt' = updateDef n (\ (d, _, t) -> (d, a, t)) ctxt in
693 uctxt { definitions = ctxt' }
695setTotal :: Name -> Totality -> Context -> Context
697 = let ctxt = definitions uctxt
698 ctxt' = updateDef n (\ (d, a, _) -> (d, a, t)) ctxt in
699 uctxt { definitions = ctxt' }
701addCtxtDef :: Name -> Def -> Context -> Context
702addCtxtDef n d c = let ctxt = definitions c
703 ctxt' = addDef n (d, Public, Unchecked) ctxt in
704 c { definitions = ctxt' }
706addTyDecl :: Name -> Type -> Context -> Context
708 = let ctxt = definitions uctxt
709 ctxt' = addDef n (TyDecl Ref ty, Public, Unchecked) ctxt in
710 uctxt { definitions = ctxt' }
712addDatatype :: Datatype Name -> Context -> Context
713addDatatype (Data n tag ty cons) uctxt
714 = let ctxt = definitions uctxt
715 ty' = normalise uctxt [] ty
716 ctxt' = addCons 0 cons (addDef n
717 (TyDecl (TCon tag (arity ty')) ty, Public, Unchecked) ctxt) in
718 uctxt { definitions = ctxt' }
720 addCons tag [] ctxt = ctxt
721 addCons tag ((n, ty) : cons) ctxt
722 = let ty' = normalise uctxt [] ty in
723 addCons (tag+1) cons (addDef n
724 (TyDecl (DCon tag (arity ty')) ty, Public, Unchecked) ctxt)
726addCasedef :: Name -> Bool -> Bool -> Bool -> Bool ->
727 [Either Term (Term, Term)] ->
728 [([Name], Term, Term)] ->
729 [([Name], Term, Term)] ->
730 Type -> Context -> Context
731addCasedef n alwaysInline tcase covering asserted ps_in ps psrt ty uctxt
732 = let ctxt = definitions uctxt
733 access = case lookupDefAcc Nothing n False uctxt of
736 ctxt' = case (simpleCase tcase covering CompileTime (FC "" 0) ps,
737 simpleCase tcase covering RunTime (FC "" 0) psrt) of
738 (OK (CaseDef args sc _), OK (CaseDef args' sc' _)) ->
739 let inl = alwaysInline
740 inlc = (inl || small n args sc') && (not asserted)
741 inlr = inl || small n args sc' in
742 addDef n (CaseOp inlc inlr
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',
761 uctxt { definitions = ctxt' }
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
769 debind (Left x) = let (vs, x') = depat [] x in
771 simpl (Right (x, y)) = Right (x, simplify uctxt False [] y)
774addOperator :: Name -> Type -> Int -> ([Value] -> Maybe Value) ->
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' }
783lookupNames :: Maybe [String] -> Name -> Context -> [Name]
784lookupNames root n ctxt
785 = let ns = lookupCtxtName root n (definitions ctxt) in
788lookupTy :: Maybe [String] -> Name -> Context -> [Type]
790 = do def <- lookupCtxt root n (definitions ctxt)
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
799 = or $ do def <- lookupCtxt root n (definitions ctxt)
801 (TyDecl (DCon _ _) _) -> return True
802 (TyDecl (TCon _ _) _) -> return True
805isFnName :: Maybe [String] -> Name -> Context -> Bool
807 = or $ do def <- lookupCtxt root n (definitions ctxt)
809 (Function _ _) -> return True
810 (Operator _ _ _) -> return True
811 (CaseOp _ _ _ _ _ _ _ _ _) -> return True
814lookupP :: Maybe [String] -> Name -> Context -> [Term]
816 = do def <- lookupCtxt root n (definitions ctxt)
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)
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]
841 = do def <- lookupCtxt root n (definitions ctxt)
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
850 | n == x = Just (i, binderTy b)
851 | otherwise = li n (i+1) xs
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list