Skip to content
This repository was archived by the owner on Apr 1, 2025. It is now read-only.

Commit 5d47b21

Browse files
authored
Merge branch 'master' into module-laws
2 parents 93eba1d + fb1c27b commit 5d47b21

File tree

11 files changed

+446
-393
lines changed

11 files changed

+446
-393
lines changed

semantic-core/src/Analysis/Concrete.hs

Lines changed: 45 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
{-# LANGUAGE FlexibleContexts, FlexibleInstances, LambdaCase, MultiParamTypeClasses, NamedFieldPuns, OverloadedStrings, RecordWildCards, TypeOperators, UndecidableInstances #-}
1+
{-# LANGUAGE FlexibleContexts, FlexibleInstances, LambdaCase, MultiParamTypeClasses, NamedFieldPuns, OverloadedStrings, RecordWildCards, TypeApplications, TypeOperators, UndecidableInstances #-}
22
module Analysis.Concrete
33
( Concrete(..)
44
, concrete
@@ -27,10 +27,11 @@ import qualified Data.IntMap as IntMap
2727
import qualified Data.IntSet as IntSet
2828
import Data.Loc
2929
import qualified Data.Map as Map
30-
import Data.Monoid (Alt(..))
3130
import Data.Name
31+
import qualified Data.Set as Set
3232
import Data.Term
3333
import Data.Text (Text, pack)
34+
import Data.Traversable (for)
3435
import Prelude hiding (fail)
3536

3637
type Precise = Int
@@ -40,25 +41,27 @@ newtype FrameId = FrameId { unFrameId :: Precise }
4041
deriving (Eq, Ord, Show)
4142

4243
data Concrete
43-
= Closure Loc User (Term Core.Core User) Precise
44+
= Closure Loc User (Term Core.Core User) Env
4445
| Unit
4546
| Bool Bool
4647
| String Text
47-
| Obj Frame
48+
| Record Env
4849
deriving (Eq, Ord, Show)
4950

50-
objectFrame :: Concrete -> Maybe Frame
51-
objectFrame (Obj frame) = Just frame
52-
objectFrame _ = Nothing
51+
recordFrame :: Concrete -> Maybe Env
52+
recordFrame (Record frame) = Just frame
53+
recordFrame _ = Nothing
5354

54-
data Frame = Frame
55-
{ frameEdges :: [(Core.Edge, Precise)]
56-
, frameSlots :: Env
55+
newtype Frame = Frame
56+
{ frameSlots :: Env
5757
}
5858
deriving (Eq, Ord, Show)
5959

6060
type Heap = IntMap.IntMap Concrete
6161

62+
data Edge = Lexical | Import
63+
deriving (Eq, Ord, Show)
64+
6265

6366
-- | Concrete evaluation of a term to a value.
6467
--
@@ -74,46 +77,39 @@ concrete
7477
runFile :: ( Carrier sig m
7578
, Effect sig
7679
, Member Fresh sig
77-
, Member (Reader FrameId) sig
7880
, Member (State Heap) sig
7981
)
8082
=> File (Term Core.Core User)
8183
-> m (File (Either (Loc, String) Concrete))
8284
runFile file = traverse run file
8385
where run = runReader (fileLoc file)
8486
. runFailWithLoc
87+
. runReader @Env mempty
8588
. fix (eval concreteAnalysis)
8689

8790
concreteAnalysis :: ( Carrier sig m
8891
, Member Fresh sig
92+
, Member (Reader Env) sig
8993
, Member (Reader Loc) sig
90-
, Member (Reader FrameId) sig
9194
, Member (State Heap) sig
9295
, MonadFail m
9396
)
9497
=> Analysis Precise Concrete m
9598
concreteAnalysis = Analysis{..}
9699
where alloc _ = fresh
97-
bind name addr = modifyCurrentFrame (updateFrameSlots (Map.insert name addr))
98-
lookupEnv n = do
99-
FrameId frameAddr <- ask
100-
val <- deref frameAddr
101-
heap <- get
102-
pure (val >>= lookupConcrete heap n)
100+
bind name addr m = local (Map.insert name addr) m
101+
lookupEnv n = asks (Map.lookup n)
103102
deref = gets . IntMap.lookup
104103
assign addr value = modify (IntMap.insert addr value)
105104
abstract _ name body = do
106105
loc <- ask
107-
FrameId parentAddr <- ask
108-
pure (Closure loc name body parentAddr)
109-
apply eval (Closure loc name body parentAddr) a = do
110-
frameAddr <- fresh
111-
assign frameAddr (Obj (Frame [(Core.Lexical, parentAddr)] mempty))
112-
local (const loc) . (frameAddr ...) $ do
106+
env <- asks (flip Map.restrictKeys (Set.delete name (foldMap Set.singleton body)))
107+
pure (Closure loc name body env)
108+
apply eval (Closure loc name body env) a = do
109+
local (const loc) $ do
113110
addr <- alloc name
114111
assign addr a
115-
bind name addr
116-
eval body
112+
local (const (Map.insert name addr env)) (eval body)
117113
apply _ f _ = fail $ "Cannot coerce " <> show f <> " to function"
118114
unit = pure Unit
119115
bool b = pure (Bool b)
@@ -122,30 +118,24 @@ concreteAnalysis = Analysis{..}
122118
string s = pure (String s)
123119
asString (String s) = pure s
124120
asString v = fail $ "Cannot coerce " <> show v <> " to String"
125-
-- FIXME: differential inheritance (reference fields instead of copying)
126-
-- FIXME: copy non-lexical parents deeply?
127-
frame = do
128-
lexical <- asks unFrameId
129-
pure (Obj (Frame [(Core.Lexical, lexical)] mempty))
130-
-- FIXME: throw an error
131-
-- FIXME: support dynamic imports
132-
edge e addr = modifyCurrentFrame (\ (Frame ps fs) -> Frame ((e, addr) : ps) fs)
133-
addr ... m = local (const (FrameId addr)) m
134-
135-
updateFrameSlots f frame = frame { frameSlots = f (frameSlots frame) }
136-
137-
modifyCurrentFrame f = do
138-
addr <- asks unFrameId
139-
Just (Obj frame) <- deref addr
140-
assign addr (Obj (f frame))
121+
record fields = do
122+
fields' <- for fields $ \ (name, value) -> do
123+
addr <- alloc name
124+
assign addr value
125+
pure (name, addr)
126+
pure (Record (Map.fromList fields'))
127+
addr ... n = do
128+
val <- deref addr
129+
heap <- get
130+
pure (val >>= lookupConcrete heap n)
141131

142132

143133
lookupConcrete :: Heap -> User -> Concrete -> Maybe Precise
144134
lookupConcrete heap name = run . evalState IntSet.empty . runNonDet . inConcrete
145135
where -- look up the name in a concrete value
146-
inConcrete = inFrame <=< maybeA . objectFrame
136+
inConcrete = inFrame <=< maybeA . recordFrame
147137
-- look up the name in a specific 'Frame', with slots taking precedence over parents
148-
inFrame (Frame ps fs) = maybeA (Map.lookup name fs) <|> getAlt (foldMap (Alt . inAddress . snd) ps)
138+
inFrame fs = maybeA (Map.lookup name fs) <|> (maybeA (Map.lookup "__semantic_super" fs) >>= inAddress)
149139
-- look up the name in the value an address points to, if we haven’t already visited it
150140
inAddress addr = do
151141
visited <- get
@@ -157,27 +147,24 @@ lookupConcrete heap name = run . evalState IntSet.empty . runNonDet . inConcrete
157147
maybeA = maybe empty pure
158148

159149

160-
runHeap :: (Carrier sig m, Member Fresh sig) => ReaderC FrameId (StateC Heap m) a -> m (Heap, a)
161-
runHeap m = do
162-
addr <- fresh
163-
runState (IntMap.singleton addr (Obj (Frame [] mempty))) (runReader (FrameId addr) m)
150+
runHeap :: StateC Heap m a -> m (Heap, a)
151+
runHeap = runState mempty
164152

165153

166154
-- | 'heapGraph', 'heapValueGraph', and 'heapAddressGraph' allow us to conveniently export SVGs of the heap:
167155
--
168156
-- > λ let (heap, res) = concrete [ruby]
169157
-- > λ writeFile "/Users/rob/Desktop/heap.dot" (export (addressStyle heap) (heapAddressGraph heap))
170158
-- > λ :!dot -Tsvg < ~/Desktop/heap.dot > ~/Desktop/heap.svg
171-
heapGraph :: (Precise -> Concrete -> a) -> (Either Core.Edge User -> Precise -> G.Graph a) -> Heap -> G.Graph a
159+
heapGraph :: (Precise -> Concrete -> a) -> (Either Edge User -> Precise -> G.Graph a) -> Heap -> G.Graph a
172160
heapGraph vertex edge h = foldr (uncurry graph) G.empty (IntMap.toList h)
173161
where graph k v rest = (G.vertex (vertex k v) `G.connect` outgoing v) `G.overlay` rest
174162
outgoing = \case
175163
Unit -> G.empty
176164
Bool _ -> G.empty
177165
String _ -> G.empty
178-
Closure _ _ _ parentAddr -> edge (Left Core.Lexical) parentAddr
179-
Obj frame -> fromFrame frame
180-
fromFrame (Frame es ss) = foldr (G.overlay . uncurry (edge . Left)) (foldr (G.overlay . uncurry (edge . Right)) G.empty (Map.toList ss)) es
166+
Closure _ _ _ env -> foldr (G.overlay . edge (Left Lexical)) G.empty env
167+
Record frame -> Map.foldrWithKey (\ k -> G.overlay . edge (Right k)) G.empty frame
181168

182169
heapValueGraph :: Heap -> G.Graph Concrete
183170
heapValueGraph h = heapGraph (const id) (const fromAddr) h
@@ -189,20 +176,20 @@ heapAddressGraph = heapGraph (\ addr v -> (Value v, addr)) (fmap G.vertex . (,)
189176
addressStyle :: Heap -> G.Style (EdgeType, Precise) Text
190177
addressStyle heap = (G.defaultStyle vertex) { G.edgeAttributes }
191178
where vertex (_, addr) = pack (show addr) <> " = " <> maybe "?" fromConcrete (IntMap.lookup addr heap)
192-
edgeAttributes _ (Slot name, _) = ["label" G.:= name]
193-
edgeAttributes _ (Edge Core.Import, _) = ["color" G.:= "blue"]
194-
edgeAttributes _ (Edge Core.Lexical, _) = ["color" G.:= "green"]
195-
edgeAttributes _ _ = []
179+
edgeAttributes _ (Slot name, _) = ["label" G.:= name]
180+
edgeAttributes _ (Edge Import, _) = ["color" G.:= "blue"]
181+
edgeAttributes _ (Edge Lexical, _) = ["color" G.:= "green"]
182+
edgeAttributes _ _ = []
196183
fromConcrete = \case
197184
Unit -> "()"
198185
Bool b -> pack $ show b
199186
String s -> pack $ show s
200187
Closure (Loc p (Span s e)) n _ _ -> "\\\\ " <> n <> " [" <> p <> ":" <> showPos s <> "-" <> showPos e <> "]"
201-
Obj _ -> "{}"
188+
Record _ -> "{}"
202189
showPos (Pos l c) = pack (show l) <> ":" <> pack (show c)
203190

204191
data EdgeType
205-
= Edge Core.Edge
192+
= Edge Edge
206193
| Slot User
207194
| Value Concrete
208195
deriving (Eq, Ord, Show)

0 commit comments

Comments
 (0)