1
+ {-# LANGUAGE DeriveTraversable #-}
1
2
{-# LANGUAGE FlexibleContexts #-}
2
- {-# LANGUAGE GADTs #-}
3
3
{-# LANGUAGE LambdaCase #-}
4
- {-# LANGUAGE PatternSynonyms #-}
5
- {-# LANGUAGE ViewPatterns #-}
6
4
-- | This belongs in @semantic-python@ instead of @semantic-analysis@, but for the sake of expedience…
7
5
module Analysis.Syntax.Python
8
6
( -- * Syntax
9
7
Term
10
8
, Python (.. )
11
- , pattern Noop
12
- , pattern Iff
13
- , pattern Bool
14
- , pattern String
15
- , pattern Throw
16
- , pattern Let
17
- , pattern (:>>)
18
- , pattern Import
19
- , pattern Function
20
- , pattern Call
21
- , pattern Locate
22
9
-- * Abstract interpretation
23
10
, eval0
24
11
, eval
@@ -33,7 +20,6 @@ import Analysis.VM
33
20
import Control.Effect.Labelled
34
21
import Control.Effect.Reader
35
22
import Data.Function (fix )
36
- import Data.Functor.Classes (Eq1 (.. ), Ord1 (.. ))
37
23
import Data.List.NonEmpty (NonEmpty )
38
24
import Data.Text (Text )
39
25
import Source.Span (Span )
@@ -42,123 +28,22 @@ import Source.Span (Span)
42
28
43
29
type Term = T. Term Python Name
44
30
45
- data Python arity where
46
- Noop' :: Python T. N0
47
- Iff' :: Python T. N3
48
- Bool' :: Bool -> Python T. N0
49
- String' :: Text -> Python T. N0
50
- Throw' :: Python T. N1
51
- Let' :: Name -> Python T. N2
52
- (:>>>) :: Python T. N2
53
- Import' :: NonEmpty Text -> Python T. N0
54
- Function' :: Name -> [Name ] -> Python T. N1
55
- Call' :: Python T. N2 -- ^ Second should be an @ANil'@ or @ACons'@.
56
- ANil' :: Python T. N0
57
- ACons' :: Python T. N2 -- ^ Second should be an @ANil'@ or @ACons'@.
58
- Locate' :: Span -> Python T. N1
59
-
60
- infixl 1 :>>>
61
-
62
- pattern Noop :: T. Term Python v
63
- pattern Noop = Noop' T. :$: T. Nil
64
-
65
- pattern Iff :: T. Term Python v -> T. Term Python v -> T. Term Python v -> T. Term Python v
66
- pattern Iff c t e = Iff' T. :$: T. Cons c (T. Cons t (T. Cons e T. Nil ))
67
-
68
- pattern Bool :: Bool -> T. Term Python v
69
- pattern Bool b = Bool' b T. :$: T. Nil
70
-
71
- pattern String :: Text -> T. Term Python v
72
- pattern String t = String' t T. :$: T. Nil
73
-
74
- pattern Throw :: T. Term Python v -> T. Term Python v
75
- pattern Throw e = Throw' T. :$: T. Cons e T. Nil
76
-
77
- pattern Let :: Name -> T. Term Python v -> T. Term Python v -> T. Term Python v
78
- pattern Let n v b = Let' n T. :$: T. Cons v (T. Cons b T. Nil )
79
-
80
- pattern (:>>) :: T. Term Python v -> T. Term Python v -> T. Term Python v
81
- pattern s :>> t = (:>>>) T. :$: T. Cons s (T. Cons t T. Nil )
31
+ data Python t
32
+ = Noop
33
+ | Iff t t t
34
+ | Bool Bool
35
+ | String Text
36
+ | Throw t
37
+ | Let Name t t
38
+ | t :>> t
39
+ | Import (NonEmpty Text )
40
+ | Function Name [Name ] t
41
+ | Call t [t ]
42
+ | Locate Span t
43
+ deriving (Eq , Foldable , Functor , Ord , Show , Traversable )
82
44
83
45
infixl 1 :>>
84
46
85
- pattern Import :: NonEmpty Text -> T. Term Python v
86
- pattern Import i = Import' i T. :$: T. Nil
87
-
88
- pattern Function :: Name -> [Name ] -> T. Term Python v -> T. Term Python v
89
- pattern Function n as b = Function' n as T. :$: T. Cons b T. Nil
90
-
91
- pattern Call
92
- :: T. Term Python v
93
- -> [T. Term Python v ]
94
- -> T. Term Python v
95
- pattern Call f as <- Call' T. :$: T. Cons f (T. Cons (fromArgs -> as) T. Nil )
96
- where Call f as = Call' T. :$: T. Cons f (T. Cons (foldr ACons ANil as) T. Nil )
97
-
98
- fromArgs :: T. Term Python v -> [T. Term Python v ]
99
- fromArgs = \ case
100
- ANil -> []
101
- ACons a as -> a: fromArgs as
102
- _ -> fail " unexpected constructor in spine of argument list"
103
-
104
- pattern ANil :: T. Term Python v
105
- pattern ANil = ANil' T. :$: T. Nil
106
-
107
- pattern ACons :: T. Term Python v -> T. Term Python v -> T. Term Python v
108
- pattern ACons a as = ACons' T. :$: T. Cons a (T. Cons as T. Nil )
109
-
110
- pattern Locate :: Span -> T. Term Python v -> T. Term Python v
111
- pattern Locate s t = Locate' s T. :$: T. Cons t T. Nil
112
-
113
- {-# COMPLETE Noop, Iff, Bool, String, Throw, Let, (:>>), Import, Function, Call, Locate #-}
114
-
115
-
116
- instance Eq1 Python where
117
- liftEq _ a b = case (a, b) of
118
- (Noop' , Noop' ) -> True
119
- (Iff' , Iff' ) -> True
120
- (Bool' b1, Bool' b2) -> b1 == b2
121
- (String' s1, String' s2) -> s1 == s2
122
- (Throw' , Throw' ) -> True
123
- (Let' n1, Let' n2) -> n1 == n2
124
- ((:>>>) , (:>>>) ) -> True
125
- (Import' i1, Import' i2) -> i1 == i2
126
- (Function' n1 as1, Function' n2 as2) -> n1 == n2 && as1 == as2
127
- (Call' , Call' ) -> True
128
- (ANil' , ANil' ) -> True
129
- (ACons' , ACons' ) -> True
130
- (Locate' s1, Locate' s2) -> s1 == s2
131
- _ -> False
132
-
133
- instance Ord1 Python where
134
- liftCompare _ a b = case (a, b) of
135
- (Noop' , Noop' ) -> EQ
136
- (Noop' , _) -> LT
137
- (Iff' , Iff' ) -> EQ
138
- (Iff' , _) -> LT
139
- (Bool' b1, Bool' b2) -> compare b1 b2
140
- (Bool' _, _) -> LT
141
- (String' s1, String' s2) -> compare s1 s2
142
- (String' _, _) -> LT
143
- (Throw' , Throw' ) -> EQ
144
- (Throw' , _) -> LT
145
- (Let' n1, Let' n2) -> compare n1 n2
146
- (Let' _, _) -> LT
147
- ((:>>>) , (:>>>) ) -> EQ
148
- ((:>>>) , _) -> LT
149
- (Import' i1, Import' i2) -> compare i1 i2
150
- (Import' _, _) -> LT
151
- (Function' n1 as1, Function' n2 as2) -> compare n1 n2 <> compare as1 as2
152
- (Function' _ _, _) -> LT
153
- (Call' , Call' ) -> EQ
154
- (Call' , _) -> LT
155
- (ANil' , ANil' ) -> EQ
156
- (ANil' , _) -> LT
157
- (ACons' , ACons' ) -> EQ
158
- (ACons' , _) -> LT
159
- (Locate' s1, Locate' s2) -> compare s1 s2
160
- (Locate' _, _) -> LT
161
-
162
47
163
48
-- Abstract interpretation
164
49
@@ -170,27 +55,28 @@ eval
170
55
=> (Term -> m val )
171
56
-> (Term -> m val )
172
57
eval eval = \ case
173
- T. Var n -> lookupEnv n >>= maybe (dvar n) fetch
174
- Noop -> dunit
175
- Iff c t e -> do
176
- c' <- eval c
177
- dif c' (eval t) (eval e)
178
- Bool b -> dbool b
179
- String s -> dstring s
180
- Throw e -> eval e >>= ddie
181
- Let n v b -> do
182
- v' <- eval v
183
- let' n v' (eval b)
184
- t :>> u -> do
185
- t' <- eval t
186
- u' <- eval u
187
- t' >>> u'
188
- Import ns -> S. simport ns >> dunit
189
- Function n ps b -> letrec n (dabs ps (foldr (\ (p, a) m -> let' p a m) (eval b) . zip ps))
190
- Call f as -> do
191
- f' <- eval f
192
- as' <- traverse eval as
193
- dapp f' as'
194
- Locate s t -> local (setSpan s) (eval t)
58
+ T. Var n -> lookupEnv n >>= maybe (dvar n) fetch
59
+ T. Term s -> case s of
60
+ Noop -> dunit
61
+ Iff c t e -> do
62
+ c' <- eval c
63
+ dif c' (eval t) (eval e)
64
+ Bool b -> dbool b
65
+ String s -> dstring s
66
+ Throw e -> eval e >>= ddie
67
+ Let n v b -> do
68
+ v' <- eval v
69
+ let' n v' (eval b)
70
+ t :>> u -> do
71
+ t' <- eval t
72
+ u' <- eval u
73
+ t' >>> u'
74
+ Import ns -> S. simport ns >> dunit
75
+ Function n ps b -> letrec n (dabs ps (foldr (\ (p, a) m -> let' p a m) (eval b) . zip ps))
76
+ Call f as -> do
77
+ f' <- eval f
78
+ as' <- traverse eval as
79
+ dapp f' as'
80
+ Locate s t -> local (setSpan s) (eval t)
195
81
where
196
82
setSpan s r = r{ refSpan = s }
0 commit comments