1- {-# LANGUAGE DerivingVia, FlexibleContexts, FlexibleInstances, LambdaCase, MultiParamTypeClasses, NamedFieldPuns, OverloadedStrings, RecordWildCards, TypeOperators, UndecidableInstances #-}
1+ {-# LANGUAGE DerivingVia, FlexibleContexts, FlexibleInstances, LambdaCase, MultiParamTypeClasses, NamedFieldPuns, OverloadedStrings, RankNTypes, RecordWildCards, TypeOperators, UndecidableInstances #-}
22module Analysis.Concrete
33( Concrete (.. )
44, concrete
@@ -20,7 +20,6 @@ import Control.Effect.NonDet
2020import Control.Effect.Reader hiding (Local )
2121import Control.Effect.State
2222import Control.Monad ((<=<) , guard )
23- import qualified Data.Core as Core
2423import Data.File
2524import Data.Function (fix )
2625import qualified Data.IntMap as IntMap
@@ -30,7 +29,6 @@ import qualified Data.Map as Map
3029import Data.Name
3130import Data.Semigroup (Last (.. ))
3231import qualified Data.Set as Set
33- import Data.Term
3432import Data.Text (Text , pack )
3533import Data.Traversable (for )
3634import Prelude hiding (fail )
@@ -41,16 +39,16 @@ type Env = Map.Map User Precise
4139newtype FrameId = FrameId { unFrameId :: Precise }
4240 deriving (Eq , Ord , Show )
4341
44- data Concrete
45- = Closure Loc User ( Term Core. Core User ) Env
42+ data Concrete term
43+ = Closure Loc User term Env
4644 | Unit
4745 | Bool Bool
4846 | String Text
4947 | Record Env
5048 deriving (Eq , Ord , Show )
51- deriving Semigroup via Last Concrete
49+ deriving Semigroup via Last ( Concrete term )
5250
53- recordFrame :: Concrete -> Maybe Env
51+ recordFrame :: Concrete term -> Maybe Env
5452recordFrame (Record frame) = Just frame
5553recordFrame _ = Nothing
5654
@@ -59,44 +57,64 @@ newtype Frame = Frame
5957 }
6058 deriving (Eq , Ord , Show )
6159
62- type Heap = IntMap. IntMap Concrete
60+ type Heap term = IntMap. IntMap ( Concrete term )
6361
6462data Edge = Lexical | Import
6563 deriving (Eq , Ord , Show )
6664
6765
6866-- | Concrete evaluation of a term to a value.
6967--
70- -- >>> map fileBody (snd (concrete [File (Loc "bool" emptySpan) (Core.bool True)]))
68+ -- >>> map fileBody (snd (concrete eval [File (Loc "bool" emptySpan) (Core.bool True)]))
7169-- [Right (Bool True)]
72- concrete :: [File (Term Core. Core User )] -> (Heap , [File (Either (Loc , String ) Concrete )])
7370concrete
71+ :: (Foldable term , Show (term User ))
72+ => (forall sig m
73+ . (Carrier sig m , Member (Reader Loc ) sig , MonadFail m )
74+ => Analysis (term User ) Precise (Concrete (term User )) m
75+ -> (term User -> m (Concrete (term User )))
76+ -> (term User -> m (Concrete (term User )))
77+ )
78+ -> [File (term User )]
79+ -> (Heap (term User ), [File (Either (Loc , String ) (Concrete (term User )))])
80+ concrete eval
7481 = run
7582 . runFresh
7683 . runHeap
77- . traverse runFile
78-
79- runFile :: ( Carrier sig m
80- , Effect sig
81- , Member Fresh sig
82- , Member (State Heap ) sig
83- )
84- => File (Term Core. Core User )
85- -> m (File (Either (Loc , String ) Concrete ))
86- runFile file = traverse run file
84+ . traverse (runFile eval)
85+
86+ runFile
87+ :: ( Carrier sig m
88+ , Effect sig
89+ , Foldable term
90+ , Member Fresh sig
91+ , Member (State (Heap (term User ))) sig
92+ , Show (term User )
93+ )
94+ => (forall sig m
95+ . (Carrier sig m , Member (Reader Loc ) sig , MonadFail m )
96+ => Analysis (term User ) Precise (Concrete (term User )) m
97+ -> (term User -> m (Concrete (term User )))
98+ -> (term User -> m (Concrete (term User )))
99+ )
100+ -> File (term User )
101+ -> m (File (Either (Loc , String ) (Concrete (term User ))))
102+ runFile eval file = traverse run file
87103 where run = runReader (fileLoc file)
88104 . runFailWithLoc
89105 . runReader (mempty :: Env )
90106 . fix (eval concreteAnalysis)
91107
92108concreteAnalysis :: ( Carrier sig m
109+ , Foldable term
93110 , Member Fresh sig
94111 , Member (Reader Env ) sig
95112 , Member (Reader Loc ) sig
96- , Member (State Heap ) sig
113+ , Member (State ( Heap ( term User )) ) sig
97114 , MonadFail m
115+ , Show (term User )
98116 )
99- => Analysis Precise Concrete m
117+ => Analysis ( term User ) Precise ( Concrete ( term User )) m
100118concreteAnalysis = Analysis {.. }
101119 where alloc _ = fresh
102120 bind name addr m = local (Map. insert name addr) m
@@ -132,7 +150,7 @@ concreteAnalysis = Analysis{..}
132150 pure (val >>= lookupConcrete heap n)
133151
134152
135- lookupConcrete :: Heap -> User -> Concrete -> Maybe Precise
153+ lookupConcrete :: Heap term -> User -> Concrete term -> Maybe Precise
136154lookupConcrete heap name = run . evalState IntSet. empty . runNonDet . inConcrete
137155 where -- look up the name in a concrete value
138156 inConcrete = inFrame <=< maybeA . recordFrame
@@ -149,7 +167,7 @@ lookupConcrete heap name = run . evalState IntSet.empty . runNonDet . inConcrete
149167 maybeA = maybe empty pure
150168
151169
152- runHeap :: StateC Heap m a -> m (Heap , a )
170+ runHeap :: StateC ( Heap term ) m a -> m (Heap term , a )
153171runHeap = runState mempty
154172
155173
@@ -158,7 +176,7 @@ runHeap = runState mempty
158176-- > λ let (heap, res) = concrete [ruby]
159177-- > λ writeFile "/Users/rob/Desktop/heap.dot" (export (addressStyle heap) (heapAddressGraph heap))
160178-- > λ :!dot -Tsvg < ~/Desktop/heap.dot > ~/Desktop/heap.svg
161- heapGraph :: (Precise -> Concrete -> a ) -> (Either Edge User -> Precise -> G. Graph a ) -> Heap -> G. Graph a
179+ heapGraph :: (Precise -> Concrete term -> a ) -> (Either Edge User -> Precise -> G. Graph a ) -> Heap term -> G. Graph a
162180heapGraph vertex edge h = foldr (uncurry graph) G. empty (IntMap. toList h)
163181 where graph k v rest = (G. vertex (vertex k v) `G.connect` outgoing v) `G.overlay` rest
164182 outgoing = \ case
@@ -168,14 +186,14 @@ heapGraph vertex edge h = foldr (uncurry graph) G.empty (IntMap.toList h)
168186 Closure _ _ _ env -> foldr (G. overlay . edge (Left Lexical )) G. empty env
169187 Record frame -> foldr (G. overlay . uncurry (edge . Right )) G. empty (Map. toList frame)
170188
171- heapValueGraph :: Heap -> G. Graph Concrete
189+ heapValueGraph :: Heap term -> G. Graph ( Concrete term )
172190heapValueGraph h = heapGraph (const id ) (const fromAddr) h
173191 where fromAddr addr = maybe G. empty G. vertex (IntMap. lookup addr h)
174192
175- heapAddressGraph :: Heap -> G. Graph (EdgeType , Precise )
193+ heapAddressGraph :: Heap term -> G. Graph (EdgeType term , Precise )
176194heapAddressGraph = heapGraph (\ addr v -> (Value v, addr)) (fmap G. vertex . (,) . either Edge Slot )
177195
178- addressStyle :: Heap -> G. Style (EdgeType , Precise ) Text
196+ addressStyle :: Heap term -> G. Style (EdgeType term , Precise ) Text
179197addressStyle heap = (G. defaultStyle vertex) { G. edgeAttributes }
180198 where vertex (_, addr) = pack (show addr) <> " = " <> maybe " ?" fromConcrete (IntMap. lookup addr heap)
181199 edgeAttributes _ (Slot name, _) = [" label" G. := name]
@@ -190,12 +208,13 @@ addressStyle heap = (G.defaultStyle vertex) { G.edgeAttributes }
190208 Record _ -> " {}"
191209 showPos (Pos l c) = pack (show l) <> " :" <> pack (show c)
192210
193- data EdgeType
211+ data EdgeType term
194212 = Edge Edge
195213 | Slot User
196- | Value Concrete
214+ | Value ( Concrete term )
197215 deriving (Eq , Ord , Show )
198216
199217
200218-- $setup
201219-- >>> :seti -XOverloadedStrings
220+ -- >>> import qualified Data.Core as Core
0 commit comments