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

Commit f04a69a

Browse files
author
Patrick Thomson
authored
Merge pull request #211 from github/scope-graphs
Scope graphs
2 parents 3f77dd6 + 0515d7c commit f04a69a

File tree

4 files changed

+136
-11
lines changed

4 files changed

+136
-11
lines changed

semantic-core/src/Analysis/FlowInsensitive.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ cacheTerm eval term = do
6868
result <$ modify (Cache . Map.insertWith (<>) term (Set.singleton (result :: a)) . unCache)
6969

7070
runHeap :: StateC (Heap address a) m b -> m (Heap address a, b)
71-
runHeap m = runState (Map.empty) m
71+
runHeap m = runState Map.empty m
7272

7373
-- | Fold a collection by mapping each element onto an 'Alternative' action.
7474
foldMapA :: (Alternative m, Foldable t) => (b -> m a) -> t b -> m a

semantic-core/src/Analysis/ImportGraph.hs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import Control.Effect.Reader
1515
import Control.Effect.State
1616
import Control.Monad ((>=>))
1717
import Data.File
18-
import Data.Foldable (fold)
18+
import Data.Foldable (fold, for_)
1919
import Data.Function (fix)
2020
import Data.List.NonEmpty (nonEmpty)
2121
import Data.Loc
@@ -103,7 +103,7 @@ importGraphAnalysis = Analysis{..}
103103
bind _ _ m = m
104104
lookupEnv = pure . Just
105105
deref addr = gets (Map.lookup addr >=> nonEmpty . Set.toList) >>= maybe (pure Nothing) (foldMapA (pure . Just))
106-
assign addr ty = modify (Map.insertWith (<>) addr (Set.singleton ty))
106+
assign addr v = modify (Map.insertWith (<>) addr (Set.singleton v))
107107
abstract _ name body = do
108108
loc <- ask
109109
pure (Value (Closure loc name body) mempty)
@@ -118,5 +118,9 @@ importGraphAnalysis = Analysis{..}
118118
string s = pure (Value (String s) mempty)
119119
asString (Value (String s) _) = pure s
120120
asString _ = pure mempty
121-
record fields = pure (Value Abstract (foldMap (valueGraph . snd) fields))
121+
record fields = do
122+
for_ fields $ \ (k, v) -> do
123+
addr <- alloc k
124+
assign addr v
125+
pure (Value Abstract (foldMap (valueGraph . snd) fields))
122126
_ ... m = pure (Just m)
Lines changed: 121 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,130 @@
1+
{-# LANGUAGE FlexibleContexts, OverloadedStrings, RankNTypes, RecordWildCards, TypeApplications, TypeOperators #-}
12
module Analysis.ScopeGraph
2-
( ScopeGraph
3-
, Entry(..)
3+
( ScopeGraph(..)
4+
, Decl(..)
5+
, scopeGraph
6+
, scopeGraphAnalysis
47
) where
58

9+
import Analysis.Eval
10+
import Analysis.FlowInsensitive
11+
import Control.Applicative (Alternative (..))
12+
import Control.Effect.Carrier
13+
import Control.Effect.Fail
14+
import Control.Effect.Fresh
15+
import Control.Effect.Reader
16+
import Control.Effect.State
17+
import Control.Monad ((>=>))
18+
import Data.File
19+
import Data.Foldable (fold)
20+
import Data.Function (fix)
21+
import Data.List.NonEmpty
622
import Data.Loc
723
import qualified Data.Map as Map
24+
import Data.Name
25+
import Data.Proxy
826
import qualified Data.Set as Set
27+
import Data.Text (Text)
28+
import Data.Traversable (for)
29+
import Prelude hiding (fail)
930

10-
data Entry = Entry
11-
{ entrySymbol :: String -- FIXME: Text
12-
, entryLoc :: Loc
31+
data Decl = Decl
32+
{ declSymbol :: Text
33+
, declLoc :: Loc
1334
}
35+
deriving (Eq, Ord, Show)
1436

15-
type ScopeGraph = Map.Map Entry (Set.Set Entry)
37+
newtype Ref = Ref Loc
38+
deriving (Eq, Ord, Show)
39+
40+
newtype ScopeGraph = ScopeGraph { unScopeGraph :: Map.Map Decl (Set.Set Ref) }
41+
deriving (Eq, Ord, Show)
42+
43+
instance Semigroup ScopeGraph where
44+
ScopeGraph a <> ScopeGraph b = ScopeGraph (Map.unionWith (<>) a b)
45+
46+
instance Monoid ScopeGraph where
47+
mempty = ScopeGraph Map.empty
48+
49+
scopeGraph
50+
:: Ord term
51+
=> (forall sig m
52+
. (Carrier sig m, Member (Reader Loc) sig, MonadFail m)
53+
=> Analysis term User ScopeGraph m
54+
-> (term -> m ScopeGraph)
55+
-> (term -> m ScopeGraph)
56+
)
57+
-> [File term]
58+
-> (Heap User ScopeGraph, [File (Either (Loc, String) ScopeGraph)])
59+
scopeGraph eval
60+
= run
61+
. runFresh
62+
. runHeap
63+
. traverse (runFile eval)
64+
65+
runFile
66+
:: ( Carrier sig m
67+
, Effect sig
68+
, Member Fresh sig
69+
, Member (State (Heap User ScopeGraph)) sig
70+
, Ord term
71+
)
72+
=> (forall sig m
73+
. (Carrier sig m, Member (Reader Loc) sig, MonadFail m)
74+
=> Analysis term User ScopeGraph m
75+
-> (term -> m ScopeGraph)
76+
-> (term -> m ScopeGraph)
77+
)
78+
-> File term
79+
-> m (File (Either (Loc, String) ScopeGraph))
80+
runFile eval file = traverse run file
81+
where run = runReader (fileLoc file)
82+
. runReader (Map.empty @User @Loc)
83+
. runFailWithLoc
84+
. fmap fold
85+
. convergeTerm (Proxy @User) (fix (cacheTerm . eval scopeGraphAnalysis))
86+
87+
scopeGraphAnalysis
88+
:: ( Alternative m
89+
, Carrier sig m
90+
, Member (Reader Loc) sig
91+
, Member (Reader (Map.Map User Loc)) sig
92+
, Member (State (Heap User ScopeGraph)) sig
93+
)
94+
=> Analysis term User ScopeGraph m
95+
scopeGraphAnalysis = Analysis{..}
96+
where alloc = pure
97+
bind name _ m = do
98+
loc <- ask @Loc
99+
local (Map.insert name loc) m
100+
lookupEnv = pure . Just
101+
deref addr = do
102+
ref <- asks Ref
103+
bindLoc <- asks (Map.lookup addr)
104+
cell <- gets (Map.lookup addr >=> nonEmpty . Set.toList)
105+
let extending = mappend (extendBinding addr ref bindLoc)
106+
maybe (pure Nothing) (foldMapA (pure . Just . extending)) cell
107+
assign addr v = do
108+
ref <- asks Ref
109+
bindLoc <- asks (Map.lookup addr)
110+
modify (Map.insertWith (<>) addr (Set.singleton (extendBinding addr ref bindLoc <> v)))
111+
abstract eval name body = do
112+
addr <- alloc name
113+
assign name (mempty @ScopeGraph)
114+
bind name addr (eval body)
115+
apply _ f a = pure (f <> a)
116+
unit = pure mempty
117+
bool _ = pure mempty
118+
asBool _ = pure True <|> pure False
119+
string _ = pure mempty
120+
asString _ = pure mempty
121+
record fields = do
122+
fields' <- for fields $ \ (k, v) -> do
123+
addr <- alloc k
124+
loc <- ask @Loc
125+
let v' = ScopeGraph (Map.singleton (Decl k loc) mempty) <> v
126+
(k, v') <$ assign addr v'
127+
pure (foldMap snd fields')
128+
_ ... m = pure (Just m)
129+
130+
extendBinding addr ref bindLoc = ScopeGraph (maybe Map.empty (\ bindLoc -> Map.singleton (Decl addr bindLoc) (Set.singleton ref)) bindLoc)

semantic-core/src/Analysis/Typecheck.hs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import Data.Scope
3333
import Data.Semigroup (Last (..))
3434
import qualified Data.Set as Set
3535
import Data.Term
36+
import Data.Traversable (for)
3637
import Data.Void
3738
import GHC.Generics (Generic1)
3839
import Prelude hiding (fail)
@@ -175,7 +176,12 @@ typecheckingAnalysis = Analysis{..}
175176
asBool b = unify (Term Bool) b >> pure True <|> pure False
176177
string _ = pure (Term String)
177178
asString s = unify (Term String) s $> mempty
178-
record fields = pure (Term (Record (Map.fromList fields)))
179+
record fields = do
180+
fields' <- for fields $ \ (k, v) -> do
181+
addr <- alloc k
182+
(k, v) <$ assign addr v
183+
-- FIXME: should records reference types by address instead?
184+
pure (Term (Record (Map.fromList fields')))
179185
_ ... m = pure (Just m)
180186

181187

0 commit comments

Comments
 (0)