pisigma-0.1.0.2: src/PiSigma/Equality.hs
{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}
module PiSigma.Equality where
import Control.Monad
import PiSigma.Syntax
import PiSigma.Evaluation
class Equal a where
eq :: Env e => a -> a -> Eval e ()
instance Equal (Clos Term) where
eq t u = do t' <- eval t
u' <- eval u
eq t' u'
eq' :: Env e => Clos (Term,Term) -> Eval e ()
eq' ((t,u),s) = eq (t,s) (u,s)
eqBind :: (Env e,Closure a) =>
(a -> a -> Eval e ()) ->
Bind a -> Bind a -> Eval e ()
eqBind eq (x0,c0) (x1,c1) =
do let s0 = getScope c0
s1 = getScope c1
(i,s0') <- decl' x0 s0
let s1' = extendScope s1 x1 (i,Nothing)
let c0' = putScope c0 s0'
c1' = putScope c1 s1'
eq c0' c1'
instance (Equal a,Closure a) => Equal (Bind a) where
eq = eqBind eq
instance Equal Val where
eq (Ne t0) (Ne t1) = eq t0 t1
eq (VQ ps0 ((a0,(x0,b0)),s0)) (VQ ps1 ((a1,(x1,b1)),s1))
| ps0 == ps1 =
do eq (a0,s0) (a1,s1)
eq (x0,(b0,s0)) (x1,(b1,s1))
eq (VLam xt0) (VLam xt1) = eq xt0 xt1
eq (VPair ((t0,u0),s0)) (VPair ((t1,u1),s1)) =
do eq (t0,s0) (t1,s1)
eq (u0,s0) (u1,s1)
eq (VBox b) (VBox b') = eq b b'
eq (VLift a) (VLift a') = eq a a'
eq v0 v1 | v0 == v1 = return () -- Type, Label, Enum
| otherwise = fail "Different values"
eqBox :: Env e => Clos Term -> Clos Term -> Eval e ()
eqBox (Var x,s) (Var y,s') =
do x' <- getId x s
y' <- getId y s'
eq x' y'
{-
eqBox (Var x,s) u =
do x' <- getId x s
ei <- lookupId x'
case ei of
Closure t -> eqBox t u
Id j -> fail "eqBox: var vs term"
-- wrong level - this should use functions in Evaluation
-- have to avoid races: don't unfold the same id twice!
eqBox t u @ (Var _,_) = eqBox u t
-}
eqBox (Let p t,s) c = fail "eqBox: let not implemented"
{-
do s' <- evalProg (p,s)
eqBox (t,s') c
-}
eqBox c c'@(Let p t,s) = eqBox c' c
eqBox (Q ps (a,(x,b)),s) (Q ps' (a',(x',b')),s')
| ps == ps' =
do eqBox (a,s) (a',s')
eq (x,Boxed (b,s)) (x',Boxed (b',s'))
eqBox (t :. u,s) (t' :. u',s') =
do eqBox (t,s) (t',s')
eqBox (u,s) (u',s')
eqBox (Split t (x,(y,u)),s) (Split t' (x',(y',u')),s') =
do eqBox (t,s) (t',s')
eq (x,(y,Boxed (u,s))) (x',(y',Boxed (u',s')))
eqBox (Case t bs,s) (Case t' bs',s') =
do eqBox (t,s) (t',s')
zipWithM_ (\ (l,t) (l',t') ->
if l==l' then eqBox (t,s) (t',s')
else fail "eqBox case") bs bs'
eqBox (Lift t,s) (Lift t',s') = eqBox (t,s) (t',s')
eqBox (Box t,s) (Box t',s') = eqBox (t,s) (t',s')
eqBox (Force t,s) (Force t',s') = eqBox (t,s) (t',s')
eqBox (t,s) (t',s') | t == t' = return () -- Type, Label, Enum
| otherwise = fail "Different terms"
-- TODO: check that it cannot happen that t and t' are syntacically equal but not alpha equivalent!
instance Equal Boxed where
eq (Boxed c) (Boxed c') = eqBox c c'
instance Equal Id where
eq i0 i1
| i0 == i1 = return ()
| otherwise = do ei0 <- lookupId i0
ei1 <- lookupId i1
case (ei0,ei1) of
(Id j0, Id j1) -> unless (j0 == j1)
(fail "Different variables")
(Closure t0, Closure t1) ->
letn i0 (Id i0)
(letn i1 (Id i0)
(eq t0 t1))
_ -> fail "Variable vs neutral"
instance Equal Ne where
eq (NVar i0) (NVar i1) = eq i0 i1
eq (t0 :.. u0) (t1 :.. u1) =
do eq t0 t1
eq u0 u1
eq (NSplit t0 xyu0) (NSplit t1 xyu1) =
do eq t0 t1
eq xyu0 xyu1
eq (NCase t0 (lus0,s0)) (NCase t1 (lus1,s1)) =
do eq t0 t1
let eqBranches [] [] = return ()
eqBranches ((l0,u0):lus0) ((l1,u1):lus1) | l0 == l1 =
do eq (u0,s0) (u1,s1)
eqBranches lus0 lus1
eqBranches _ _ = fail "Case: branches differ"
eqBranches lus0 lus1
eq (NForce t) (NForce t') = eq t t'
eq t u = fail ("Different neutrals:\n"++ show t ++"\n/=\n"++ show u ++"\n")