l-c2019/Lab5/Lab5.hs

109 lines
3.2 KiB
Haskell
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{-# LANGUAGE GADTs #-}
module Lab5 where
-- ∞
-- fix f = ⊔ fⁱ ⊥
-- i=0
fix :: (a -> a) -> a
fix f = f (fix f)
type Iden = String
type Σ = Iden -> Int
data Ω = Normal Σ | Abort Σ | Out (Int, Ω) | In (Int -> Ω)
update :: Σ -> Iden -> Int -> Σ
update σ v n v' = if v == v' then n else σ v'
data Expr a where
-- Expresiones enteras
Const :: Int -> Expr Int -- n
Var :: String -> Expr Int -- v
Plus :: Expr Int -> Expr Int -> Expr Int -- e + e'
-- Expresiones booleanas
Eq :: Expr Int -> Expr Int -> Expr Bool -- e = e'
Lt :: Expr Int -> Expr Int -> Expr Bool -- e < e'
-- Comandos
Skip :: Expr Ω -- skip
NewVar :: Iden -> Expr Int -> Expr Ω -> Expr Ω -- newvar v := e in e'
Assign :: Iden -> Expr Int -> Expr Ω -- v := e
Fail :: Expr Ω -- fail
Catch :: Expr Ω -> Expr Ω -> Expr Ω -- catch c with c'
While :: Expr Bool -> Expr Ω -> Expr Ω -- while b do c
If :: Expr Bool -> Expr Ω -> Expr Ω -> Expr Ω -- if b then c else c'
Seq :: Expr Ω -> Expr Ω -> Expr Ω -- c ; c'
EMark :: Expr Int -> Expr Ω -- !e
QMark :: String -> Expr Ω -- ?v
class DomSem dom where
sem :: Expr dom -> Σ -> dom
instance DomSem Int where
sem (Const a) = \_ -> a
sem (Var v) = \σ -> σ v
sem (Plus e1 e2) = \σ -> sem e1 σ + sem e2 σ
instance DomSem Bool where
sem (Eq e1 e2) = \σ -> sem e1 σ == sem e2 σ
sem (Lt e1 e2) = \σ -> sem e1 σ < sem e2 σ
(*.) :: (Σ -> Ω) -> Ω -> Ω
(*.) f (Normal σ) = f σ
(*.) _ (Abort σ) = Abort σ
(*.) f (Out (n, ω)) = Out (n, f *. ω)
(*.) f (In g) = In ((f *.) . g)
(.) :: (Σ -> Σ) -> Ω -> Ω
(.) f (Normal σ) = Normal $ f σ
(.) f (Abort σ) = Abort $ f σ
(.) f (Out (n, ω)) = Out (n, f . ω)
(.) f (In g) = In ((f .) . g)
(+.) :: (Σ -> Ω) -> Ω -> Ω
(+.) _ (Normal σ) = Normal σ
(+.) f (Abort σ) = f σ
(+.) f (Out (n, ω)) = Out (n, f +. ω)
(+.) f (In g) = In ((f +.) . g)
instance DomSem Ω where
sem Skip = \σ -> Normal σ
sem (NewVar v e c) = \σ ->
(\σ' -> update σ' v (σ v))
. (sem c (update σ v (sem e σ)))
sem (Assign v n) = \σ -> Normal (update σ v (sem n σ))
sem Fail = \σ -> Abort σ
sem (Catch c c') = \σ -> sem c' +. (sem c σ)
sem (While b p) = fix f
where
f :: (Σ -> Ω) -> (Σ -> Ω)
f ω σ
| sem b σ = ω *. (sem p σ)
| otherwise = Normal σ
sem (If b p p') = \σ ->
if sem b σ
then sem p σ
else sem p' σ
sem (Seq c c') = \σ -> sem c' *. (sem c σ)
sem (EMark e) = \σ -> Out (sem e σ, Normal σ)
sem (QMark v) = \σ -> In (\n -> Normal (update σ v n))
-- | Funciones de evaluación de dom
class Eval dom where
eval :: Expr dom -> Σ -> IO ()
instance Eval Int where
eval e = putStrLn . show . sem e
instance Eval Bool where
eval e = putStrLn . show . sem e
instance Eval Ω where
eval e = unrollOmega . sem e
where
unrollOmega :: Ω -> IO ()
unrollOmega (Normal σ) = return ()
unrollOmega (Abort σ) = putStrLn "Abort"
unrollOmega (Out (n, ω)) = putStrLn (show n) >> unrollOmega ω
unrollOmega (In f) = getLine >>= unrollOmega . f . read