-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathStructuralOperationalSemantics.lhs
More file actions
77 lines (62 loc) · 3.02 KB
/
StructuralOperationalSemantics.lhs
File metadata and controls
77 lines (62 loc) · 3.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
\begin{code}
module StructuralOperationalSemantics where
import Data.List
import qualified AbstractSyntax as S
import qualified IntegerArithmetic as I
binArith :: (S.Term -> S.Term -> S.Term)
-> S.Term -> S.Term
-> (Integer -> Integer -> Integer)
-> Maybe S.Term
binArith f (S.IntConst t1) (S.IntConst t2) op = Just (S.IntConst (op t1 t2))
binArith f (S.IntConst t1) t2 op = do t2' <- eval1 t2
Just (f (S.IntConst t1) t2')
binArith f t1 t2 _ = do t1' <- eval1 t1
Just (f t1' t2)
binArithRel :: (S.Term -> S.Term -> S.Term)
-> S.Term -> S.Term
-> (Integer -> Integer -> Bool)
-> Maybe S.Term
binArithRel f (S.IntConst t1) (S.IntConst t2) op = case op t1 t2 of
True -> Just S.Tru
False -> Just S.Fls
binArithRel f (S.IntConst t1) t2 op = do t2' <- eval1 t2
Just (f (S.IntConst t1) t2')
binArithRel f t1 t2 _ = do t1' <- eval1 t1
Just (f t1' t2)
eval1 :: S.Term -> Maybe S.Term
eval1 t = case t of
(S.If S.Tru t2 t3) -> Just t2
(S.If S.Fls t2 t3) -> Just t3
(S.If t1 t2 t3) -> do t1' <- eval1 t1
Just (S.If t1' t2 t3)
(S.App t1 t2) ->
case S.isValue t1 of
False -> do t1' <- eval1 t1
Just (S.App t1' t2)
True -> case S.isValue t2 of
False -> do t2' <- eval1 t2
Just (S.App t1 t2')
True -> case t1 of
(S.Abs x _ term) -> Just (S.subst x t2 term)
otherwise -> Nothing
t@(S.Fix (S.Abs x _ t1)) -> Just (S.subst x t t1)
(S.Fix t) -> do t' <- eval1 t
Just (S.Fix t')
(S.Let x t1 t2)
| S.isValue t1 -> Just (S.subst x t1 t2)
| otherwise -> do t1' <- eval1 t1
Just (S.Let x t1' t2)
(S.IntAdd t1 t2) -> binArith (S.IntAdd) t1 t2 (I.intAdd)
(S.IntSub t1 t2) -> binArith (S.IntSub) t1 t2 (I.intSub)
(S.IntMul t1 t2) -> binArith (S.IntMul) t1 t2 (I.intMul)
(S.IntDiv t1 t2) -> binArith (S.IntDiv) t1 t2 (I.intDiv)
(S.IntNand t1 t2) -> binArith (S.IntNand) t1 t2 (I.intNand)
(S.IntEq t1 t2) -> binArithRel (S.IntEq) t1 t2 (I.intEq)
(S.IntLt t1 t2) -> binArithRel (S.IntLt) t1 t2 (I.intLt)
otherwise -> Nothing
eval :: S.Term -> S.Term
eval t =
case eval1 t of
Just t' -> eval t'
Nothing -> t
\end{code}