polyseq-0.1.1: src/Language/Haskell/FreeTheorems/Variations/PolySeq/PolySeqAlg.hs
-- | contains all rule systems
module Language.Haskell.FreeTheorems.Variations.PolySeq.PolySeqAlg (algPolySeq) where
import Language.Haskell.FreeTheorems.Variations.PolySeq.M
import Language.Haskell.FreeTheorems.Variations.PolySeq.AlgCommon
import Language.Haskell.FreeTheorems.Variations.PolySeq.Syntax
-- * Typing algorithm
polySeqTyping :: Cont -> Term -> M (Constraint,Typ)
polySeqTyping gamma t =
case t of
Var v -> do{ tau <- getTypVarInCont gamma v;
superType tau
}
Abs v tau t' -> do{ (c1,tau2) <- polySeqTyping (addTermVar gamma (v,tau)) t';
(c2,tau1) <- subType tau;
lab <- makeLabel;
return (Conj c1 c2, TArrow lab tau1 tau2)
}
App t1 t2 -> do{ (c1,tau12) <- polySeqTyping gamma t1;
(tau1,tau2)<- getArrowComps tau12;
(c2,tau1') <- polySeqTyping gamma t2;
c3 <- makeEqual tau1 tau1';
return (Conj (Conj c1 c2) c3,tau2)
}
TAbs tv t' -> do{ lv <- makeLabel;
(c,tau) <- polySeqTyping (addTypVar gamma (tv,lv)) t';
return (c,TAll lv tv tau)
}
TApp t' tau -> do{ c1 <- seqable gamma tau;
(c2,atau) <- polySeqTyping gamma t';
(lab,tv,tau1)<- getAllComps atau;
(c3,tau3) <- superType (substTyp tau1 tau tv);
return (Conj (Conj c2 c3) (Impl (Eq lab (LVal Epsilon)) c1),tau3)
}
Nil tau -> do{ (c,tau') <- superType tau;
return (c,TList tau')
}
Cons t1 t2 -> do{ (c1,tau) <- polySeqTyping gamma t1;
(c2,ltau)<- polySeqTyping gamma t2;
tau' <- getElemType ltau;
c3 <- makeEqual tau tau';
return (Conj (Conj c1 c2) c3,TList tau)
}
LCase t1 t2 v1 v2 t3 ->
do{ (c1,ltau)<- polySeqTyping gamma t1;
tau1 <- getElemType ltau;
(c2,tau2)<- polySeqTyping gamma t2;
(c3,tau2')<- polySeqTyping (addTermVar (addTermVar gamma (v1,tau1)) (v2,ltau)) t3;
c4 <- makeEqual tau2 tau2';
return (Conj (Conj (Conj c1 c2) c3) c4,tau2)
}
Fix t' -> do{ (c1,tau) <- polySeqTyping gamma t';
(tau1,tau2)<- getArrowComps tau;
c2 <- makeEqual tau1 tau2;
return (Conj c1 c2,tau1)
}
LSeq v t1 t2 -> do{ (c1,tau1) <- polySeqTyping gamma t1;
c2 <- seqable gamma tau1;
(c3,tau2) <- polySeqTyping (addTermVar gamma (v,tau1)) t2;
return (Conj (Conj c1 c2) c3, tau2)
}
Let v t1 t2 -> do{ (c1,tau1) <- polySeqTyping gamma t1;
(c2,tau2) <- polySeqTyping (addTermVar gamma (v,tau1)) t2;
return (Conj c1 c2, tau2)
}
Seq t1 t2 -> do{ (c1,tau1) <- polySeqTyping gamma t1;
c2 <- seqable gamma tau1;
(c3,tau2) <- polySeqTyping gamma t2;
return (Conj (Conj c1 c2) c3, tau2)
}
I _ -> return (Tru,TInt)
Add t1 t2 -> do{ (c1,tau1) <- polySeqTyping gamma t1;
isInt tau1;
(c2,tau2) <- polySeqTyping gamma t2;
isInt tau2;
return (Conj c1 c2,TInt)
}
T -> return (Tru,TBool)
F -> return (Tru,TBool)
BCase t1 t2 t3 -> do{ (_,tau1) <- polySeqTyping gamma t1; --the constraint will always be Tru
isBool tau1;
(c2,tau2) <- polySeqTyping gamma t2;
(c3,tau3) <- polySeqTyping gamma t3;
c4 <- makeEqual tau2 tau3;
return (Conj (Conj c2 c3) c4,tau2)
}
-- * seqable check
seqable :: Cont -> Typ -> M Constraint
seqable gamma tau =
case tau of
TVar tv -> do{ lab <- getLabTVar gamma tv;
return (Eq (lab) (LVal Epsilon))
}
TArrow lab _ _ -> return (Eq lab (LVal Epsilon))
TAll _ tv tau' -> seqable (addTypVar gamma (tv,LVal Epsilon)) tau'
TList _ -> return Tru
TInt -> return Tru
TBool -> return Tru
-- * typ comparison
superType :: Typ -> M (Constraint,Typ)
superType tau =
case tau of
TVar tv -> return (Tru,tau)
TArrow lab tau1 tau2 -> do{ (c1,tau) <- subType tau1;
(c2,tau')<- superType tau2;
lab' <- makeLabel;
return (Conj (Conj c1 c2) (Leq lab' lab),TArrow lab' tau tau')
}
TAll lab tv tau -> do{ (c,tau') <- superType tau;
lab' <- makeLabel;
return (Conj c (Leq lab lab'), TAll lab' tv tau')
}
TList tau -> do{ (c,tau') <- superType tau;
return (c,TList tau')
}
TInt -> return (Tru,TInt)
TBool -> return (Tru,TBool)
subType :: Typ -> M (Constraint,Typ)
subType tau =
case tau of
TVar tv -> return (Tru,tau)
TArrow lab tau1 tau2 -> do{ (c1,tau) <- superType tau1;
(c2,tau')<- subType tau2;
lab' <- makeLabel;
return (Conj (Conj c1 c2) (Leq lab lab'),TArrow lab' tau tau')
}
TAll lab tv tau -> do{ (c,tau') <- subType tau;
lab' <- makeLabel;
return (Conj c (Leq lab' lab), TAll lab' tv tau')
}
TList tau -> do{ (c,tau') <- subType tau;
return (c,TList tau')
}
TInt -> return (Tru,TInt)
TBool -> return (Tru,TBool)
makeEqual :: Typ -> Typ -> M Constraint
makeEqual tau tau' =
case tau of
TVar tv -> if tau' == TVar tv then return Tru else abort
TArrow lab tau1 tau2 -> case tau' of
TArrow lab' tau1' tau2' -> do{ c1 <- makeEqual tau1 tau1';
c2 <- makeEqual tau2 tau2';
return (Conj (Conj c1 c2) (Eq lab lab'))
}
_ -> abort
TAll lab tv tau1 -> case tau' of
TAll lab' tv' tau1' -> if tv == tv'
then
do{ c <- makeEqual tau1 tau1';
return (Conj c (Eq lab lab'))
}
else abort
_ -> abort
TList tau1 -> case tau' of
TList tau1' -> makeEqual tau1 tau1'
_ -> abort
TInt -> if tau' == TInt then return Tru else abort
TBool -> if tau' == TBool then return Tru else abort
-- * main function
algPolySeq :: Term -> M (Term,Constraint,Typ)
algPolySeq t = do{ t' <- annotate t;
(c,tau) <- polySeqTyping emptyCont t';
return (t',c,tau)
}