1+ {-# LANGUAGE DeriveTraversable #-}
12{-# LANGUAGE FlexibleContexts #-}
2- {-# LANGUAGE GADTs #-}
33{-# LANGUAGE LambdaCase #-}
4- {-# LANGUAGE PatternSynonyms #-}
5- {-# LANGUAGE ViewPatterns #-}
64-- | This belongs in @semantic-python@ instead of @semantic-analysis@, but for the sake of expedience…
75module Analysis.Syntax.Python
86( -- * Syntax
97 Term
108, 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
229 -- * Abstract interpretation
2310, eval0
2411, eval
@@ -33,7 +20,6 @@ import Analysis.VM
3320import Control.Effect.Labelled
3421import Control.Effect.Reader
3522import Data.Function (fix )
36- import Data.Functor.Classes (Eq1 (.. ), Ord1 (.. ))
3723import Data.List.NonEmpty (NonEmpty )
3824import Data.Text (Text )
3925import Source.Span (Span )
@@ -42,123 +28,22 @@ import Source.Span (Span)
4228
4329type Term = T. Term Python Name
4430
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 )
8244
8345infixl 1 :>>
8446
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-
16247
16348-- Abstract interpretation
16449
@@ -170,27 +55,28 @@ eval
17055 => (Term -> m val )
17156 -> (Term -> m val )
17257eval 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)
19581 where
19682 setSpan s r = r{ refSpan = s }
0 commit comments