1+ {-# LANGUAGE FlexibleContexts, OverloadedStrings, RecordWildCards, TypeApplications #-}
12module Analysis.ScopeGraph
23( ScopeGraph
34, Entry (.. )
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 qualified Data.Core as Core
18+ import Data.File
19+ import Data.Foldable (fold )
20+ import Data.Function (fix )
21+ import Data.List.NonEmpty
622import Data.Loc
723import qualified Data.Map as Map
24+ import Data.Name
825import qualified Data.Set as Set
926import Data.Text (Text )
27+ import Data.Term
28+ import Prelude hiding (fail )
1029
1130data Entry = Entry
1231 { entrySymbol :: Text
@@ -15,3 +34,80 @@ data Entry = Entry
1534 deriving (Eq , Ord , Show )
1635
1736type ScopeGraph = Map. Map Entry (Set. Set Entry )
37+
38+
39+ data Value = Value
40+ { valueSemi :: Semi
41+ , valueGraph :: ScopeGraph
42+ }
43+ deriving (Eq , Ord , Show )
44+
45+ instance Semigroup Value where
46+ Value _ g1 <> Value _ g2 = Value Abstract (Map. unionWith (<>) g1 g2)
47+
48+ instance Monoid Value where
49+ mempty = Value Abstract mempty
50+
51+ data Semi
52+ = Closure Loc User (Term Core. Core User ) User
53+ -- FIXME: Bound String values.
54+ | String Text
55+ | Abstract
56+ deriving (Eq , Ord , Show )
57+
58+
59+ scopeGraph :: [File (Term Core. Core User )] -> (Heap User Value , [File (Either (Loc , String ) Value )])
60+ scopeGraph
61+ = run
62+ . runFresh
63+ . runHeap " __semantic_root"
64+ . traverse runFile
65+
66+ runFile
67+ :: ( Carrier sig m
68+ , Effect sig
69+ , Member Fresh sig
70+ , Member (Reader (FrameId User )) sig
71+ , Member (State (Heap User Value )) sig
72+ )
73+ => File (Term Core. Core User )
74+ -> m (File (Either (Loc , String ) Value ))
75+ runFile file = traverse run file
76+ where run = runReader (fileLoc file)
77+ . runFailWithLoc
78+ . fmap fold
79+ . convergeTerm (fix (cacheTerm . eval scopeGraphAnalysis))
80+
81+ -- FIXME: decompose into a product domain and two atomic domains
82+ scopeGraphAnalysis
83+ :: ( Alternative m
84+ , Carrier sig m
85+ , Member (Reader (FrameId User )) sig
86+ , Member (Reader Loc ) sig
87+ , Member (State (Heap User Value )) sig
88+ , MonadFail m
89+ )
90+ => Analysis User Value m
91+ scopeGraphAnalysis = Analysis {.. }
92+ where alloc = pure
93+ bind _ _ m = m
94+ lookupEnv = pure . Just
95+ deref addr = gets (Map. lookup addr) >>= maybe (pure Nothing ) (foldMapA (pure . Just )) . nonEmpty . maybe [] (Set. toList @ Value )
96+ assign addr ty = modify (Map. insertWith (<>) addr (Set. singleton ty))
97+ abstract _ name body = do
98+ loc <- ask
99+ FrameId parentAddr <- ask
100+ pure (Value (Closure loc name body parentAddr) mempty )
101+ apply eval (Value (Closure loc name body _) _) a = local (const loc) $ do
102+ addr <- alloc name
103+ assign addr a
104+ bind name addr (eval body)
105+ apply _ f _ = fail $ " Cannot coerce " <> show f <> " to function"
106+ unit = pure mempty
107+ bool _ = pure mempty
108+ asBool _ = pure True <|> pure False
109+ string s = pure (Value (String s) mempty )
110+ asString (Value (String s) _) = pure s
111+ asString _ = pure mempty
112+ record fields = pure (Value Abstract (foldMap (valueGraph . snd ) fields))
113+ _ ... m = pure (Just m)
0 commit comments