mirror of
https://github.com/github/semantic.git
synced 2025-01-09 00:56:32 +03:00
Merge branch 'master' into add-java-to-supported-langs
This commit is contained in:
commit
a6a790cc17
@ -84,6 +84,7 @@ test-suite spec
|
|||||||
other-modules: Generators
|
other-modules: Generators
|
||||||
build-depends: base
|
build-depends: base
|
||||||
, semantic-core
|
, semantic-core
|
||||||
|
, semantic-source ^>= 0
|
||||||
, fused-effects
|
, fused-effects
|
||||||
, hedgehog ^>= 1
|
, hedgehog ^>= 1
|
||||||
, tasty >= 1.2 && <2
|
, tasty >= 1.2 && <2
|
||||||
|
@ -41,7 +41,7 @@ newtype FrameId = FrameId { unFrameId :: Precise }
|
|||||||
deriving (Eq, Ord, Show)
|
deriving (Eq, Ord, Show)
|
||||||
|
|
||||||
data Concrete term
|
data Concrete term
|
||||||
= Closure Loc Name term Env
|
= Closure Path Span Name term Env
|
||||||
| Unit
|
| Unit
|
||||||
| Bool Bool
|
| Bool Bool
|
||||||
| String Text
|
| String Text
|
||||||
@ -67,18 +67,18 @@ data Edge = Lexical | Import
|
|||||||
|
|
||||||
-- | Concrete evaluation of a term to a value.
|
-- | Concrete evaluation of a term to a value.
|
||||||
--
|
--
|
||||||
-- >>> map fileBody (snd (concrete eval [File (Loc "bool" (Span (Pos 1 1) (Pos 1 5))) (Core.bool True)]))
|
-- >>> map fileBody (snd (concrete eval [File (Path "bool") (Span (Pos 1 1) (Pos 1 5)) (Core.bool True)]))
|
||||||
-- [Right (Bool True)]
|
-- [Right (Bool True)]
|
||||||
concrete
|
concrete
|
||||||
:: (Foldable term, Show (term Name))
|
:: (Foldable term, Show (term Name))
|
||||||
=> (forall sig m
|
=> (forall sig m
|
||||||
. (Carrier sig m, Member (Reader Loc) sig, MonadFail m)
|
. (Carrier sig m, Member (Reader Path) sig, Member (Reader Span) sig, MonadFail m)
|
||||||
=> Analysis (term Name) Precise (Concrete (term Name)) m
|
=> Analysis (term Name) Precise (Concrete (term Name)) m
|
||||||
-> (term Name -> m (Concrete (term Name)))
|
-> (term Name -> m (Concrete (term Name)))
|
||||||
-> (term Name -> m (Concrete (term Name)))
|
-> (term Name -> m (Concrete (term Name)))
|
||||||
)
|
)
|
||||||
-> [File (term Name)]
|
-> [File (term Name)]
|
||||||
-> (Heap (term Name), [File (Either (Loc, String) (Concrete (term Name)))])
|
-> (Heap (term Name), [File (Either (Path, Span, String) (Concrete (term Name)))])
|
||||||
concrete eval
|
concrete eval
|
||||||
= run
|
= run
|
||||||
. runFresh
|
. runFresh
|
||||||
@ -94,15 +94,16 @@ runFile
|
|||||||
, Show (term Name)
|
, Show (term Name)
|
||||||
)
|
)
|
||||||
=> (forall sig m
|
=> (forall sig m
|
||||||
. (Carrier sig m, Member (Reader Loc) sig, MonadFail m)
|
. (Carrier sig m, Member (Reader Path) sig, Member (Reader Span) sig, MonadFail m)
|
||||||
=> Analysis (term Name) Precise (Concrete (term Name)) m
|
=> Analysis (term Name) Precise (Concrete (term Name)) m
|
||||||
-> (term Name -> m (Concrete (term Name)))
|
-> (term Name -> m (Concrete (term Name)))
|
||||||
-> (term Name -> m (Concrete (term Name)))
|
-> (term Name -> m (Concrete (term Name)))
|
||||||
)
|
)
|
||||||
-> File (term Name)
|
-> File (term Name)
|
||||||
-> m (File (Either (Loc, String) (Concrete (term Name))))
|
-> m (File (Either (Path, Span, String) (Concrete (term Name))))
|
||||||
runFile eval file = traverse run file
|
runFile eval file = traverse run file
|
||||||
where run = runReader (fileLoc file)
|
where run = runReader (filePath file)
|
||||||
|
. runReader (fileSpan file)
|
||||||
. runFail
|
. runFail
|
||||||
. runReader @Env mempty
|
. runReader @Env mempty
|
||||||
. fix (eval concreteAnalysis)
|
. fix (eval concreteAnalysis)
|
||||||
@ -111,7 +112,8 @@ concreteAnalysis :: ( Carrier sig m
|
|||||||
, Foldable term
|
, Foldable term
|
||||||
, Member Fresh sig
|
, Member Fresh sig
|
||||||
, Member (Reader Env) sig
|
, Member (Reader Env) sig
|
||||||
, Member (Reader Loc) sig
|
, Member (Reader Path) sig
|
||||||
|
, Member (Reader Span) sig
|
||||||
, Member (State (Heap (term Name))) sig
|
, Member (State (Heap (term Name))) sig
|
||||||
, MonadFail m
|
, MonadFail m
|
||||||
, Show (term Name)
|
, Show (term Name)
|
||||||
@ -124,11 +126,12 @@ concreteAnalysis = Analysis{..}
|
|||||||
deref = gets . IntMap.lookup
|
deref = gets . IntMap.lookup
|
||||||
assign addr value = modify (IntMap.insert addr value)
|
assign addr value = modify (IntMap.insert addr value)
|
||||||
abstract _ name body = do
|
abstract _ name body = do
|
||||||
loc <- ask
|
path <- ask
|
||||||
|
span <- ask
|
||||||
env <- asks (flip Map.restrictKeys (Set.delete name (foldMap Set.singleton body)))
|
env <- asks (flip Map.restrictKeys (Set.delete name (foldMap Set.singleton body)))
|
||||||
pure (Closure loc name body env)
|
pure (Closure path span name body env)
|
||||||
apply eval (Closure loc name body env) a = do
|
apply eval (Closure path span name body env) a = do
|
||||||
local (const loc) $ do
|
local (const path) . local (const span) $ do
|
||||||
addr <- alloc name
|
addr <- alloc name
|
||||||
assign addr a
|
assign addr a
|
||||||
local (const (Map.insert name addr env)) (eval body)
|
local (const (Map.insert name addr env)) (eval body)
|
||||||
@ -185,7 +188,7 @@ heapGraph vertex edge h = foldr (uncurry graph) G.empty (IntMap.toList h)
|
|||||||
Unit -> G.empty
|
Unit -> G.empty
|
||||||
Bool _ -> G.empty
|
Bool _ -> G.empty
|
||||||
String _ -> G.empty
|
String _ -> G.empty
|
||||||
Closure _ _ _ env -> foldr (G.overlay . edge (Left Lexical)) G.empty env
|
Closure _ _ _ _ env -> foldr (G.overlay . edge (Left Lexical)) G.empty env
|
||||||
Record frame -> Map.foldrWithKey (\ k -> G.overlay . edge (Right k)) G.empty frame
|
Record frame -> Map.foldrWithKey (\ k -> G.overlay . edge (Right k)) G.empty frame
|
||||||
|
|
||||||
heapValueGraph :: Heap term -> G.Graph (Concrete term)
|
heapValueGraph :: Heap term -> G.Graph (Concrete term)
|
||||||
@ -206,7 +209,7 @@ addressStyle heap = (G.defaultStyle vertex) { G.edgeAttributes }
|
|||||||
Unit -> "()"
|
Unit -> "()"
|
||||||
Bool b -> pack $ show b
|
Bool b -> pack $ show b
|
||||||
String s -> pack $ show s
|
String s -> pack $ show s
|
||||||
Closure (Loc p (Span s e)) n _ _ -> "\\\\ " <> unName n <> " [" <> p <> ":" <> showPos s <> "-" <> showPos e <> "]"
|
Closure p (Span s e) n _ _ -> "\\\\ " <> unName n <> " [" <> getPath p <> ":" <> showPos s <> "-" <> showPos e <> "]"
|
||||||
Record _ -> "{}"
|
Record _ -> "{}"
|
||||||
showPos (Pos l c) = pack (show l) <> ":" <> pack (show c)
|
showPos (Pos l c) = pack (show l) <> ":" <> pack (show c)
|
||||||
|
|
||||||
|
@ -27,15 +27,16 @@ import Data.Term
|
|||||||
import Data.Text (Text)
|
import Data.Text (Text)
|
||||||
import GHC.Stack
|
import GHC.Stack
|
||||||
import Prelude hiding (fail)
|
import Prelude hiding (fail)
|
||||||
|
import Source.Span
|
||||||
|
|
||||||
eval :: ( Carrier sig m
|
eval :: ( Carrier sig m
|
||||||
, Member (Reader Loc) sig
|
, Member (Reader Span) sig
|
||||||
, MonadFail m
|
, MonadFail m
|
||||||
, Semigroup value
|
, Semigroup value
|
||||||
)
|
)
|
||||||
=> Analysis (Term (Ann :+: Core) Name) address value m
|
=> Analysis (Term (Ann Span :+: Core) Name) address value m
|
||||||
-> (Term (Ann :+: Core) Name -> m value)
|
-> (Term (Ann Span :+: Core) Name -> m value)
|
||||||
-> (Term (Ann :+: Core) Name -> m value)
|
-> (Term (Ann Span :+: Core) Name -> m value)
|
||||||
eval Analysis{..} eval = \case
|
eval Analysis{..} eval = \case
|
||||||
Var n -> lookupEnv' n >>= deref' n
|
Var n -> lookupEnv' n >>= deref' n
|
||||||
Term (R c) -> case c of
|
Term (R c) -> case c of
|
||||||
@ -72,7 +73,7 @@ eval Analysis{..} eval = \case
|
|||||||
b' <- eval b
|
b' <- eval b
|
||||||
addr <- ref a
|
addr <- ref a
|
||||||
b' <$ assign addr b'
|
b' <$ assign addr b'
|
||||||
Term (L (Ann loc c)) -> local (const loc) (eval c)
|
Term (L (Ann span c)) -> local (const span) (eval c)
|
||||||
where freeVariable s = fail ("free variable: " <> s)
|
where freeVariable s = fail ("free variable: " <> s)
|
||||||
uninitialized s = fail ("uninitialized variable: " <> s)
|
uninitialized s = fail ("uninitialized variable: " <> s)
|
||||||
invalidRef s = fail ("invalid ref: " <> s)
|
invalidRef s = fail ("invalid ref: " <> s)
|
||||||
@ -90,7 +91,7 @@ eval Analysis{..} eval = \case
|
|||||||
a' <- ref a
|
a' <- ref a
|
||||||
a' ... b >>= maybe (freeVariable (show b)) pure
|
a' ... b >>= maybe (freeVariable (show b)) pure
|
||||||
c -> invalidRef (show c)
|
c -> invalidRef (show c)
|
||||||
Term (L (Ann loc c)) -> local (const loc) (ref c)
|
Term (L (Ann span c)) -> local (const span) (ref c)
|
||||||
|
|
||||||
|
|
||||||
prog1 :: (Carrier sig t, Member Core sig) => File (t Name)
|
prog1 :: (Carrier sig t, Member Core sig) => File (t Name)
|
||||||
@ -116,7 +117,7 @@ prog4 = fromBody
|
|||||||
(Core.bool True)
|
(Core.bool True)
|
||||||
(Core.bool False))
|
(Core.bool False))
|
||||||
|
|
||||||
prog5 :: (Carrier sig t, Member Ann sig, Member Core sig) => File (t Name)
|
prog5 :: (Carrier sig t, Member (Ann Span) sig, Member Core sig) => File (t Name)
|
||||||
prog5 = fromBody $ ann (do'
|
prog5 = fromBody $ ann (do'
|
||||||
[ Just (named' "mkPoint") :<- lams [named' "_x", named' "_y"] (ann (Core.record
|
[ Just (named' "mkPoint") :<- lams [named' "_x", named' "_y"] (ann (Core.record
|
||||||
[ ("x", ann (pure "_x"))
|
[ ("x", ann (pure "_x"))
|
||||||
@ -129,15 +130,15 @@ prog5 = fromBody $ ann (do'
|
|||||||
|
|
||||||
prog6 :: (Carrier sig t, Member Core sig) => [File (t Name)]
|
prog6 :: (Carrier sig t, Member Core sig) => [File (t Name)]
|
||||||
prog6 =
|
prog6 =
|
||||||
[ File (Loc "dep" (locSpan (fromJust here))) $ Core.record
|
[ File (Path "dep") (snd (fromJust here)) $ Core.record
|
||||||
[ ("dep", Core.record [ ("var", Core.bool True) ]) ]
|
[ ("dep", Core.record [ ("var", Core.bool True) ]) ]
|
||||||
, File (Loc "main" (locSpan (fromJust here))) $ do' (map (Nothing :<-)
|
, File (Path "main") (snd (fromJust here)) $ do' (map (Nothing :<-)
|
||||||
[ load (Core.string "dep")
|
[ load (Core.string "dep")
|
||||||
, Core.record [ ("thing", pure "dep" Core.... "var") ]
|
, Core.record [ ("thing", pure "dep" Core.... "var") ]
|
||||||
])
|
])
|
||||||
]
|
]
|
||||||
|
|
||||||
ruby :: (Carrier sig t, Member Ann sig, Member Core sig) => File (t Name)
|
ruby :: (Carrier sig t, Member (Ann Span) sig, Member Core sig) => File (t Name)
|
||||||
ruby = fromBody $ annWith callStack (rec (named' __semantic_global) (do' statements))
|
ruby = fromBody $ annWith callStack (rec (named' __semantic_global) (do' statements))
|
||||||
where statements =
|
where statements =
|
||||||
[ Just "Class" :<- record
|
[ Just "Class" :<- record
|
||||||
|
@ -25,6 +25,7 @@ import Data.Proxy
|
|||||||
import qualified Data.Set as Set
|
import qualified Data.Set as Set
|
||||||
import Data.Text (Text)
|
import Data.Text (Text)
|
||||||
import Prelude hiding (fail)
|
import Prelude hiding (fail)
|
||||||
|
import Source.Span
|
||||||
|
|
||||||
type ImportGraph = Map.Map Text (Set.Set Text)
|
type ImportGraph = Map.Map Text (Set.Set Text)
|
||||||
|
|
||||||
@ -41,7 +42,7 @@ instance Monoid (Value term) where
|
|||||||
mempty = Value Abstract mempty
|
mempty = Value Abstract mempty
|
||||||
|
|
||||||
data Semi term
|
data Semi term
|
||||||
= Closure Loc Name term
|
= Closure Path Span Name term
|
||||||
-- FIXME: Bound String values.
|
-- FIXME: Bound String values.
|
||||||
| String Text
|
| String Text
|
||||||
| Abstract
|
| Abstract
|
||||||
@ -51,14 +52,14 @@ data Semi term
|
|||||||
importGraph
|
importGraph
|
||||||
:: (Ord term, Show term)
|
:: (Ord term, Show term)
|
||||||
=> (forall sig m
|
=> (forall sig m
|
||||||
. (Carrier sig m, Member (Reader Loc) sig, MonadFail m)
|
. (Carrier sig m, Member (Reader Path) sig, Member (Reader Span) sig, MonadFail m)
|
||||||
=> Analysis term Name (Value term) m
|
=> Analysis term Name (Value term) m
|
||||||
-> (term -> m (Value term))
|
-> (term -> m (Value term))
|
||||||
-> (term -> m (Value term))
|
-> (term -> m (Value term))
|
||||||
)
|
)
|
||||||
-> [File term]
|
-> [File term]
|
||||||
-> ( Heap Name (Value term)
|
-> ( Heap Name (Value term)
|
||||||
, [File (Either (Loc, String) (Value term))]
|
, [File (Either (Path, Span, String) (Value term))]
|
||||||
)
|
)
|
||||||
importGraph eval
|
importGraph eval
|
||||||
= run
|
= run
|
||||||
@ -75,15 +76,16 @@ runFile
|
|||||||
, Show term
|
, Show term
|
||||||
)
|
)
|
||||||
=> (forall sig m
|
=> (forall sig m
|
||||||
. (Carrier sig m, Member (Reader Loc) sig, MonadFail m)
|
. (Carrier sig m, Member (Reader Path) sig, Member (Reader Span) sig, MonadFail m)
|
||||||
=> Analysis term Name (Value term) m
|
=> Analysis term Name (Value term) m
|
||||||
-> (term -> m (Value term))
|
-> (term -> m (Value term))
|
||||||
-> (term -> m (Value term))
|
-> (term -> m (Value term))
|
||||||
)
|
)
|
||||||
-> File term
|
-> File term
|
||||||
-> m (File (Either (Loc, String) (Value term)))
|
-> m (File (Either (Path, Span, String) (Value term)))
|
||||||
runFile eval file = traverse run file
|
runFile eval file = traverse run file
|
||||||
where run = runReader (fileLoc file)
|
where run = runReader (filePath file)
|
||||||
|
. runReader (fileSpan file)
|
||||||
. runFail
|
. runFail
|
||||||
. fmap fold
|
. fmap fold
|
||||||
. convergeTerm (Proxy @Name) (fix (cacheTerm . eval importGraphAnalysis))
|
. convergeTerm (Proxy @Name) (fix (cacheTerm . eval importGraphAnalysis))
|
||||||
@ -91,7 +93,8 @@ runFile eval file = traverse run file
|
|||||||
-- FIXME: decompose into a product domain and two atomic domains
|
-- FIXME: decompose into a product domain and two atomic domains
|
||||||
importGraphAnalysis :: ( Alternative m
|
importGraphAnalysis :: ( Alternative m
|
||||||
, Carrier sig m
|
, Carrier sig m
|
||||||
, Member (Reader Loc) sig
|
, Member (Reader Path) sig
|
||||||
|
, Member (Reader Span) sig
|
||||||
, Member (State (Heap Name (Value term))) sig
|
, Member (State (Heap Name (Value term))) sig
|
||||||
, MonadFail m
|
, MonadFail m
|
||||||
, Ord term
|
, Ord term
|
||||||
@ -105,9 +108,10 @@ importGraphAnalysis = Analysis{..}
|
|||||||
deref addr = gets (Map.lookup addr >=> nonEmpty . Set.toList) >>= maybe (pure Nothing) (foldMapA (pure . Just))
|
deref addr = gets (Map.lookup addr >=> nonEmpty . Set.toList) >>= maybe (pure Nothing) (foldMapA (pure . Just))
|
||||||
assign addr v = modify (Map.insertWith (<>) addr (Set.singleton v))
|
assign addr v = modify (Map.insertWith (<>) addr (Set.singleton v))
|
||||||
abstract _ name body = do
|
abstract _ name body = do
|
||||||
loc <- ask
|
path <- ask
|
||||||
pure (Value (Closure loc name body) mempty)
|
span <- ask
|
||||||
apply eval (Value (Closure loc name body) _) a = local (const loc) $ do
|
pure (Value (Closure path span name body) mempty)
|
||||||
|
apply eval (Value (Closure path span name body) _) a = local (const path) . local (const span) $ do
|
||||||
addr <- alloc name
|
addr <- alloc name
|
||||||
assign addr a
|
assign addr a
|
||||||
bind name addr (eval body)
|
bind name addr (eval body)
|
||||||
|
@ -27,14 +27,19 @@ import Data.Proxy
|
|||||||
import qualified Data.Set as Set
|
import qualified Data.Set as Set
|
||||||
import Data.Traversable (for)
|
import Data.Traversable (for)
|
||||||
import Prelude hiding (fail)
|
import Prelude hiding (fail)
|
||||||
|
import Source.Span
|
||||||
|
|
||||||
data Decl = Decl
|
data Decl = Decl
|
||||||
{ declSymbol :: Name
|
{ declSymbol :: Name
|
||||||
, declLoc :: Loc
|
, declPath :: Path
|
||||||
|
, declSpan :: Span
|
||||||
}
|
}
|
||||||
deriving (Eq, Ord, Show)
|
deriving (Eq, Ord, Show)
|
||||||
|
|
||||||
newtype Ref = Ref Loc
|
data Ref = Ref
|
||||||
|
{ refPath :: Path
|
||||||
|
, refSpan :: Span
|
||||||
|
}
|
||||||
deriving (Eq, Ord, Show)
|
deriving (Eq, Ord, Show)
|
||||||
|
|
||||||
newtype ScopeGraph = ScopeGraph { unScopeGraph :: Map.Map Decl (Set.Set Ref) }
|
newtype ScopeGraph = ScopeGraph { unScopeGraph :: Map.Map Decl (Set.Set Ref) }
|
||||||
@ -49,13 +54,13 @@ instance Monoid ScopeGraph where
|
|||||||
scopeGraph
|
scopeGraph
|
||||||
:: Ord term
|
:: Ord term
|
||||||
=> (forall sig m
|
=> (forall sig m
|
||||||
. (Carrier sig m, Member (Reader Loc) sig, MonadFail m)
|
. (Carrier sig m, Member (Reader Path) sig, Member (Reader Span) sig, MonadFail m)
|
||||||
=> Analysis term Name ScopeGraph m
|
=> Analysis term Name ScopeGraph m
|
||||||
-> (term -> m ScopeGraph)
|
-> (term -> m ScopeGraph)
|
||||||
-> (term -> m ScopeGraph)
|
-> (term -> m ScopeGraph)
|
||||||
)
|
)
|
||||||
-> [File term]
|
-> [File term]
|
||||||
-> (Heap Name ScopeGraph, [File (Either (Loc, String) ScopeGraph)])
|
-> (Heap Name ScopeGraph, [File (Either (Path, Span, String) ScopeGraph)])
|
||||||
scopeGraph eval
|
scopeGraph eval
|
||||||
= run
|
= run
|
||||||
. runFresh
|
. runFresh
|
||||||
@ -70,16 +75,17 @@ runFile
|
|||||||
, Ord term
|
, Ord term
|
||||||
)
|
)
|
||||||
=> (forall sig m
|
=> (forall sig m
|
||||||
. (Carrier sig m, Member (Reader Loc) sig, MonadFail m)
|
. (Carrier sig m, Member (Reader Path) sig, Member (Reader Span) sig, MonadFail m)
|
||||||
=> Analysis term Name ScopeGraph m
|
=> Analysis term Name ScopeGraph m
|
||||||
-> (term -> m ScopeGraph)
|
-> (term -> m ScopeGraph)
|
||||||
-> (term -> m ScopeGraph)
|
-> (term -> m ScopeGraph)
|
||||||
)
|
)
|
||||||
-> File term
|
-> File term
|
||||||
-> m (File (Either (Loc, String) ScopeGraph))
|
-> m (File (Either (Path, Span, String) ScopeGraph))
|
||||||
runFile eval file = traverse run file
|
runFile eval file = traverse run file
|
||||||
where run = runReader (fileLoc file)
|
where run = runReader (filePath file)
|
||||||
. runReader (Map.empty @Name @Loc)
|
. runReader (fileSpan file)
|
||||||
|
. runReader (Map.empty @Name @Ref)
|
||||||
. runFail
|
. runFail
|
||||||
. fmap fold
|
. fmap fold
|
||||||
. convergeTerm (Proxy @Name) (fix (cacheTerm . eval scopeGraphAnalysis))
|
. convergeTerm (Proxy @Name) (fix (cacheTerm . eval scopeGraphAnalysis))
|
||||||
@ -87,27 +93,28 @@ runFile eval file = traverse run file
|
|||||||
scopeGraphAnalysis
|
scopeGraphAnalysis
|
||||||
:: ( Alternative m
|
:: ( Alternative m
|
||||||
, Carrier sig m
|
, Carrier sig m
|
||||||
, Member (Reader Loc) sig
|
, Member (Reader Path) sig
|
||||||
, Member (Reader (Map.Map Name Loc)) sig
|
, Member (Reader Span) sig
|
||||||
|
, Member (Reader (Map.Map Name Ref)) sig
|
||||||
, Member (State (Heap Name ScopeGraph)) sig
|
, Member (State (Heap Name ScopeGraph)) sig
|
||||||
)
|
)
|
||||||
=> Analysis term Name ScopeGraph m
|
=> Analysis term Name ScopeGraph m
|
||||||
scopeGraphAnalysis = Analysis{..}
|
scopeGraphAnalysis = Analysis{..}
|
||||||
where alloc = pure
|
where alloc = pure
|
||||||
bind name _ m = do
|
bind name _ m = do
|
||||||
loc <- ask @Loc
|
ref <- askRef
|
||||||
local (Map.insert name loc) m
|
local (Map.insert name ref) m
|
||||||
lookupEnv = pure . Just
|
lookupEnv = pure . Just
|
||||||
deref addr = do
|
deref addr = do
|
||||||
ref <- asks Ref
|
ref <- askRef
|
||||||
bindLoc <- asks (Map.lookup addr)
|
bindRef <- asks (Map.lookup addr)
|
||||||
cell <- gets (Map.lookup addr >=> nonEmpty . Set.toList)
|
cell <- gets (Map.lookup addr >=> nonEmpty . Set.toList)
|
||||||
let extending = mappend (extendBinding addr ref bindLoc)
|
let extending = mappend (extendBinding addr ref bindRef)
|
||||||
maybe (pure Nothing) (foldMapA (pure . Just . extending)) cell
|
maybe (pure Nothing) (foldMapA (pure . Just . extending)) cell
|
||||||
assign addr v = do
|
assign addr v = do
|
||||||
ref <- asks Ref
|
ref <- askRef
|
||||||
bindLoc <- asks (Map.lookup addr)
|
bindRef <- asks (Map.lookup addr)
|
||||||
modify (Map.insertWith (<>) addr (Set.singleton (extendBinding addr ref bindLoc <> v)))
|
modify (Map.insertWith (<>) addr (Set.singleton (extendBinding addr ref bindRef <> v)))
|
||||||
abstract eval name body = do
|
abstract eval name body = do
|
||||||
addr <- alloc name
|
addr <- alloc name
|
||||||
assign name (mempty @ScopeGraph)
|
assign name (mempty @ScopeGraph)
|
||||||
@ -121,10 +128,13 @@ scopeGraphAnalysis = Analysis{..}
|
|||||||
record fields = do
|
record fields = do
|
||||||
fields' <- for fields $ \ (k, v) -> do
|
fields' <- for fields $ \ (k, v) -> do
|
||||||
addr <- alloc k
|
addr <- alloc k
|
||||||
loc <- ask @Loc
|
path <- ask
|
||||||
let v' = ScopeGraph (Map.singleton (Decl k loc) mempty) <> v
|
span <- ask
|
||||||
|
let v' = ScopeGraph (Map.singleton (Decl k path span) mempty) <> v
|
||||||
(k, v') <$ assign addr v'
|
(k, v') <$ assign addr v'
|
||||||
pure (foldMap snd fields')
|
pure (foldMap snd fields')
|
||||||
_ ... m = pure (Just m)
|
_ ... m = pure (Just m)
|
||||||
|
|
||||||
extendBinding addr ref bindLoc = ScopeGraph (maybe Map.empty (\ bindLoc -> Map.singleton (Decl addr bindLoc) (Set.singleton ref)) bindLoc)
|
askRef = Ref <$> ask <*> ask
|
||||||
|
|
||||||
|
extendBinding addr ref bindRef = ScopeGraph (maybe Map.empty (\ (Ref path span) -> Map.singleton (Decl addr path span) (Set.singleton ref)) bindRef)
|
||||||
|
@ -37,6 +37,7 @@ import Data.Traversable (for)
|
|||||||
import Data.Void
|
import Data.Void
|
||||||
import GHC.Generics (Generic1)
|
import GHC.Generics (Generic1)
|
||||||
import Prelude hiding (fail)
|
import Prelude hiding (fail)
|
||||||
|
import Source.Span
|
||||||
|
|
||||||
data Monotype f a
|
data Monotype f a
|
||||||
= Bool
|
= Bool
|
||||||
@ -94,14 +95,14 @@ generalize ty = fromJust (closed (forAlls (IntSet.toList (mvs ty)) (hoistTerm R
|
|||||||
typecheckingFlowInsensitive
|
typecheckingFlowInsensitive
|
||||||
:: Ord term
|
:: Ord term
|
||||||
=> (forall sig m
|
=> (forall sig m
|
||||||
. (Carrier sig m, Member (Reader Loc) sig, MonadFail m)
|
. (Carrier sig m, Member (Reader Path) sig, Member (Reader Span) sig, MonadFail m)
|
||||||
=> Analysis term Name Type m
|
=> Analysis term Name Type m
|
||||||
-> (term -> m Type)
|
-> (term -> m Type)
|
||||||
-> (term -> m Type)
|
-> (term -> m Type)
|
||||||
)
|
)
|
||||||
-> [File term]
|
-> [File term]
|
||||||
-> ( Heap Name Type
|
-> ( Heap Name Type
|
||||||
, [File (Either (Loc, String) (Term (Polytype :+: Monotype) Void))]
|
, [File (Either (Path, Span, String) (Term (Polytype :+: Monotype) Void))]
|
||||||
)
|
)
|
||||||
typecheckingFlowInsensitive eval
|
typecheckingFlowInsensitive eval
|
||||||
= run
|
= run
|
||||||
@ -118,13 +119,13 @@ runFile
|
|||||||
, Ord term
|
, Ord term
|
||||||
)
|
)
|
||||||
=> (forall sig m
|
=> (forall sig m
|
||||||
. (Carrier sig m, Member (Reader Loc) sig, MonadFail m)
|
. (Carrier sig m, Member (Reader Path) sig, Member (Reader Span) sig, MonadFail m)
|
||||||
=> Analysis term Name Type m
|
=> Analysis term Name Type m
|
||||||
-> (term -> m Type)
|
-> (term -> m Type)
|
||||||
-> (term -> m Type)
|
-> (term -> m Type)
|
||||||
)
|
)
|
||||||
-> File term
|
-> File term
|
||||||
-> m (File (Either (Loc, String) Type))
|
-> m (File (Either (Path, Span, String) Type))
|
||||||
runFile eval file = traverse run file
|
runFile eval file = traverse run file
|
||||||
where run
|
where run
|
||||||
= (\ m -> do
|
= (\ m -> do
|
||||||
@ -132,7 +133,8 @@ runFile eval file = traverse run file
|
|||||||
modify @(Heap Name Type) (fmap (Set.map (substAll subst)))
|
modify @(Heap Name Type) (fmap (Set.map (substAll subst)))
|
||||||
pure (substAll subst <$> t))
|
pure (substAll subst <$> t))
|
||||||
. runState (mempty :: Substitution)
|
. runState (mempty :: Substitution)
|
||||||
. runReader (fileLoc file)
|
. runReader (filePath file)
|
||||||
|
. runReader (fileSpan file)
|
||||||
. runFail
|
. runFail
|
||||||
. (\ m -> do
|
. (\ m -> do
|
||||||
(cs, t) <- m
|
(cs, t) <- m
|
||||||
|
@ -14,18 +14,20 @@ import Control.Effect.Fail (Fail(..), MonadFail(..))
|
|||||||
import Control.Effect.Reader
|
import Control.Effect.Reader
|
||||||
import Data.Loc
|
import Data.Loc
|
||||||
import Prelude hiding (fail)
|
import Prelude hiding (fail)
|
||||||
|
import Source.Span
|
||||||
|
|
||||||
runFail :: FailC m a -> m (Either (Loc, String) a)
|
runFail :: FailC m a -> m (Either (Path, Span, String) a)
|
||||||
runFail = runError . runFailC
|
runFail = runError . runFailC
|
||||||
|
|
||||||
newtype FailC m a = FailC { runFailC :: ErrorC (Loc, String) m a }
|
newtype FailC m a = FailC { runFailC :: ErrorC (Path, Span, String) m a }
|
||||||
deriving (Alternative, Applicative, Functor, Monad)
|
deriving (Alternative, Applicative, Functor, Monad)
|
||||||
|
|
||||||
instance (Carrier sig m, Effect sig, Member (Reader Loc) sig) => MonadFail (FailC m) where
|
instance (Carrier sig m, Effect sig, Member (Reader Path) sig, Member (Reader Span) sig) => MonadFail (FailC m) where
|
||||||
fail s = do
|
fail s = do
|
||||||
loc <- ask
|
path <- ask
|
||||||
FailC (throwError (loc :: Loc, s))
|
span <- ask
|
||||||
|
FailC (throwError (path :: Path, span :: Span, s))
|
||||||
|
|
||||||
instance (Carrier sig m, Effect sig, Member (Reader Loc) sig) => Carrier (Fail :+: sig) (FailC m) where
|
instance (Carrier sig m, Effect sig, Member (Reader Path) sig, Member (Reader Span) sig) => Carrier (Fail :+: sig) (FailC m) where
|
||||||
eff (L (Fail s)) = fail s
|
eff (L (Fail s)) = fail s
|
||||||
eff (R other) = FailC (eff (R (handleCoercible other)))
|
eff (R other) = FailC (eff (R (handleCoercible other)))
|
||||||
|
@ -50,6 +50,7 @@ import Data.Term
|
|||||||
import Data.Text (Text)
|
import Data.Text (Text)
|
||||||
import GHC.Generics (Generic1)
|
import GHC.Generics (Generic1)
|
||||||
import GHC.Stack
|
import GHC.Stack
|
||||||
|
import Source.Span
|
||||||
|
|
||||||
data Core f a
|
data Core f a
|
||||||
-- | Recursive local binding of a name in a scope; strict evaluation of the name in the body will diverge.
|
-- | Recursive local binding of a name in a scope; strict evaluation of the name in the body will diverge.
|
||||||
@ -215,27 +216,27 @@ a .= b = send (a := b)
|
|||||||
infix 3 .=
|
infix 3 .=
|
||||||
|
|
||||||
|
|
||||||
data Ann f a
|
data Ann ann f a
|
||||||
= Ann Loc (f a)
|
= Ann ann (f a)
|
||||||
deriving (Eq, Foldable, Functor, Generic1, Ord, Show, Traversable)
|
deriving (Eq, Foldable, Functor, Generic1, Ord, Show, Traversable)
|
||||||
|
|
||||||
instance HFunctor Ann
|
instance HFunctor (Ann ann)
|
||||||
|
|
||||||
instance RightModule Ann where
|
instance RightModule (Ann ann) where
|
||||||
Ann l b >>=* f = Ann l (b >>= f)
|
Ann l b >>=* f = Ann l (b >>= f)
|
||||||
|
|
||||||
|
|
||||||
ann :: (Carrier sig m, Member Ann sig) => HasCallStack => m a -> m a
|
ann :: (Carrier sig m, Member (Ann Span) sig) => HasCallStack => m a -> m a
|
||||||
ann = annWith callStack
|
ann = annWith callStack
|
||||||
|
|
||||||
annAt :: (Carrier sig m, Member Ann sig) => Loc -> m a -> m a
|
annAt :: (Carrier sig m, Member (Ann ann) sig) => ann -> m a -> m a
|
||||||
annAt loc = send . Ann loc
|
annAt ann = send . Ann ann
|
||||||
|
|
||||||
annWith :: (Carrier sig m, Member Ann sig) => CallStack -> m a -> m a
|
annWith :: (Carrier sig m, Member (Ann Span) sig) => CallStack -> m a -> m a
|
||||||
annWith callStack = maybe id annAt (stackLoc callStack)
|
annWith callStack = maybe id (annAt . snd) (stackLoc callStack)
|
||||||
|
|
||||||
|
|
||||||
stripAnnotations :: (HFunctor sig, forall g . Functor g => Functor (sig g)) => Term (Ann :+: sig) a -> Term sig a
|
stripAnnotations :: forall ann a sig . (HFunctor sig, forall g . Functor g => Functor (sig g)) => Term (Ann ann :+: sig) a -> Term sig a
|
||||||
stripAnnotations (Var v) = Var v
|
stripAnnotations (Var v) = Var v
|
||||||
stripAnnotations (Term (L (Ann _ b))) = stripAnnotations b
|
stripAnnotations (Term (L (Ann _ b))) = stripAnnotations b
|
||||||
stripAnnotations (Term (R b)) = Term (hmap stripAnnotations b)
|
stripAnnotations (Term (R b)) = Term (hmap stripAnnotations b)
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
{-# LANGUAGE FlexibleContexts, TypeOperators #-}
|
{-# LANGUAGE FlexibleContexts, TypeOperators #-}
|
||||||
module Data.Core.Parser
|
module Data.Core.Parser
|
||||||
( module Text.Trifecta
|
( core
|
||||||
, core
|
|
||||||
, lit
|
, lit
|
||||||
, expr
|
, expr
|
||||||
, record
|
, record
|
||||||
|
@ -7,12 +7,15 @@ module Data.File
|
|||||||
import Data.Loc
|
import Data.Loc
|
||||||
import Data.Maybe (fromJust)
|
import Data.Maybe (fromJust)
|
||||||
import GHC.Stack
|
import GHC.Stack
|
||||||
|
import Source.Span
|
||||||
|
|
||||||
data File a = File
|
data File a = File
|
||||||
{ fileLoc :: !Loc
|
{ filePath :: !Path
|
||||||
|
, fileSpan :: {-# UNPACK #-} !Span
|
||||||
, fileBody :: !a
|
, fileBody :: !a
|
||||||
}
|
}
|
||||||
deriving (Eq, Foldable, Functor, Ord, Show, Traversable)
|
deriving (Eq, Foldable, Functor, Ord, Show, Traversable)
|
||||||
|
|
||||||
fromBody :: HasCallStack => a -> File a
|
fromBody :: HasCallStack => a -> File a
|
||||||
fromBody body = File (fromJust (stackLoc callStack)) body
|
fromBody body = File path span body where
|
||||||
|
(path, span) = fromJust (stackLoc callStack)
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
{-# LANGUAGE OverloadedStrings, RecordWildCards #-}
|
{-# LANGUAGE RecordWildCards #-}
|
||||||
module Data.Loc
|
module Data.Loc
|
||||||
( Loc(..)
|
( Path(..)
|
||||||
, interactive
|
|
||||||
, here
|
, here
|
||||||
, stackLoc
|
, stackLoc
|
||||||
) where
|
) where
|
||||||
@ -10,23 +9,17 @@ import Data.Text (Text, pack)
|
|||||||
import GHC.Stack
|
import GHC.Stack
|
||||||
import Source.Span
|
import Source.Span
|
||||||
|
|
||||||
data Loc = Loc
|
newtype Path = Path { getPath :: Text }
|
||||||
{ locPath :: !Text
|
|
||||||
, locSpan :: {-# UNPACK #-} !Span
|
|
||||||
}
|
|
||||||
deriving (Eq, Ord, Show)
|
deriving (Eq, Ord, Show)
|
||||||
|
|
||||||
interactive :: Loc
|
|
||||||
interactive = Loc "<interactive>" (Span (Pos 1 1) (Pos 1 1))
|
|
||||||
|
|
||||||
|
here :: HasCallStack => Maybe (Path, Span)
|
||||||
here :: HasCallStack => Maybe Loc
|
|
||||||
here = stackLoc callStack
|
here = stackLoc callStack
|
||||||
|
|
||||||
stackLoc :: CallStack -> Maybe Loc
|
stackLoc :: CallStack -> Maybe (Path, Span)
|
||||||
stackLoc cs = case getCallStack cs of
|
stackLoc cs = case getCallStack cs of
|
||||||
(_, srcLoc):_ -> Just (fromGHCSrcLoc srcLoc)
|
(_, srcLoc):_ -> Just (fromGHCSrcLoc srcLoc)
|
||||||
_ -> Nothing
|
_ -> Nothing
|
||||||
|
|
||||||
fromGHCSrcLoc :: SrcLoc -> Loc
|
fromGHCSrcLoc :: SrcLoc -> (Path, Span)
|
||||||
fromGHCSrcLoc SrcLoc{..} = Loc (pack srcLocFile) (Span (Pos srcLocStartLine srcLocStartCol) (Pos srcLocEndLine srcLocEndCol))
|
fromGHCSrcLoc SrcLoc{..} = (Path (pack srcLocFile), Span (Pos srcLocStartLine srcLocStartCol) (Pos srcLocEndLine srcLocEndCol))
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
{-# LANGUAGE OverloadedStrings, TypeOperators #-}
|
{-# LANGUAGE OverloadedStrings, TypeApplications, TypeOperators #-}
|
||||||
module Main (main) where
|
module Main (main) where
|
||||||
|
|
||||||
import Data.String
|
import Data.String
|
||||||
@ -11,6 +11,7 @@ import Test.Tasty.HUnit
|
|||||||
|
|
||||||
import Control.Effect.Sum
|
import Control.Effect.Sum
|
||||||
import Data.File
|
import Data.File
|
||||||
|
import Data.Loc (Path)
|
||||||
import qualified Generators as Gen
|
import qualified Generators as Gen
|
||||||
import qualified Analysis.Eval as Eval
|
import qualified Analysis.Eval as Eval
|
||||||
import Data.Core
|
import Data.Core
|
||||||
@ -18,10 +19,11 @@ import Data.Core.Pretty
|
|||||||
import Data.Core.Parser as Parse
|
import Data.Core.Parser as Parse
|
||||||
import Data.Name
|
import Data.Name
|
||||||
import Data.Term
|
import Data.Term
|
||||||
|
import Source.Span
|
||||||
|
|
||||||
-- * Helpers
|
-- * Helpers
|
||||||
|
|
||||||
true, false :: Term (Ann :+: Core) Name
|
true, false :: Term Core Name
|
||||||
true = bool True
|
true = bool True
|
||||||
false = bool False
|
false = bool False
|
||||||
|
|
||||||
@ -31,10 +33,10 @@ parseEither p = Trifecta.foldResult (Left . show . Trifecta._errDoc) Right . Tri
|
|||||||
-- * Parser roundtripping properties. Note that parsing and prettyprinting is generally
|
-- * Parser roundtripping properties. Note that parsing and prettyprinting is generally
|
||||||
-- not a roundtrip, because the parser inserts 'Ann' nodes itself.
|
-- not a roundtrip, because the parser inserts 'Ann' nodes itself.
|
||||||
|
|
||||||
prop_roundtrips :: Gen (Term (Ann :+: Core) Name) -> Property
|
prop_roundtrips :: Gen (Term Core Name) -> Property
|
||||||
prop_roundtrips gen = property $ do
|
prop_roundtrips gen = property $ do
|
||||||
input <- forAll gen
|
input <- forAll gen
|
||||||
tripping input (showCore . stripAnnotations) (parseEither (Parse.core <* Trifecta.eof))
|
tripping input showCore (parseEither (Parse.core <* Trifecta.eof))
|
||||||
|
|
||||||
parserProps :: TestTree
|
parserProps :: TestTree
|
||||||
parserProps = testGroup "Parsing: roundtripping"
|
parserProps = testGroup "Parsing: roundtripping"
|
||||||
@ -47,7 +49,7 @@ parserProps = testGroup "Parsing: roundtripping"
|
|||||||
|
|
||||||
-- * Parser specs
|
-- * Parser specs
|
||||||
|
|
||||||
parsesInto :: String -> Term (Ann :+: Core) Name -> Assertion
|
parsesInto :: String -> Term Core Name -> Assertion
|
||||||
parsesInto str res = case parseEither Parse.core str of
|
parsesInto str res = case parseEither Parse.core str of
|
||||||
Right x -> x @?= res
|
Right x -> x @?= res
|
||||||
Left m -> assertFailure m
|
Left m -> assertFailure m
|
||||||
@ -57,7 +59,7 @@ assert_booleans_parse = do
|
|||||||
parseEither Parse.core "#true" @?= Right true
|
parseEither Parse.core "#true" @?= Right true
|
||||||
parseEither Parse.core "#false" @?= Right false
|
parseEither Parse.core "#false" @?= Right false
|
||||||
|
|
||||||
a, f, g, h :: Term (Ann :+: Core) Name
|
a, f, g, h :: Term Core Name
|
||||||
(a, f, g, h) = (pure "a", pure "f", pure "g", pure "h")
|
(a, f, g, h) = (pure "a", pure "f", pure "g", pure "h")
|
||||||
|
|
||||||
assert_ifthen_parse :: Assertion
|
assert_ifthen_parse :: Assertion
|
||||||
@ -93,10 +95,10 @@ parserSpecs = testGroup "Parsing: simple specs"
|
|||||||
, testCase "quoted names" assert_quoted_name_parse
|
, testCase "quoted names" assert_quoted_name_parse
|
||||||
]
|
]
|
||||||
|
|
||||||
assert_roundtrips :: File (Term (Ann :+: Core) Name) -> Assertion
|
assert_roundtrips :: File (Term Core Name) -> Assertion
|
||||||
assert_roundtrips (File _ core) = case parseEither Parse.core (showCore (stripAnnotations core)) of
|
assert_roundtrips (File _ _ core) = case parseEither Parse.core (showCore core) of
|
||||||
Right v -> stripAnnotations v @?= stripAnnotations core
|
Right v -> v @?= core
|
||||||
Left e -> assertFailure e
|
Left e -> assertFailure e
|
||||||
|
|
||||||
parserExamples :: TestTree
|
parserExamples :: TestTree
|
||||||
parserExamples = testGroup "Parsing: Eval.hs examples"
|
parserExamples = testGroup "Parsing: Eval.hs examples"
|
||||||
@ -106,7 +108,7 @@ parserExamples = testGroup "Parsing: Eval.hs examples"
|
|||||||
, testCase "prog4" (assert_roundtrips Eval.prog4)
|
, testCase "prog4" (assert_roundtrips Eval.prog4)
|
||||||
, testCase "prog6.1" (assert_roundtrips (head Eval.prog6))
|
, testCase "prog6.1" (assert_roundtrips (head Eval.prog6))
|
||||||
, testCase "prog6.2" (assert_roundtrips (last Eval.prog6))
|
, testCase "prog6.2" (assert_roundtrips (last Eval.prog6))
|
||||||
, testCase "ruby" (assert_roundtrips Eval.ruby)
|
, testCase "ruby" (assert_roundtrips (stripAnnotations @Span <$> Eval.ruby))
|
||||||
]
|
]
|
||||||
|
|
||||||
tests :: TestTree
|
tests :: TestTree
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
module Language.Python.Core
|
module Language.Python.Core
|
||||||
( toplevelCompile
|
( toplevelCompile
|
||||||
, Bindings
|
, Bindings
|
||||||
, SourcePath
|
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Prelude hiding (fail)
|
import Prelude hiding (fail)
|
||||||
@ -18,21 +17,13 @@ import Control.Monad ((>=>))
|
|||||||
import Data.Coerce
|
import Data.Coerce
|
||||||
import Data.Core as Core
|
import Data.Core as Core
|
||||||
import Data.Foldable
|
import Data.Foldable
|
||||||
import Data.Loc (Loc)
|
|
||||||
import qualified Data.Loc
|
|
||||||
import Data.Name as Name
|
import Data.Name as Name
|
||||||
import Data.Stack (Stack)
|
import Data.Stack (Stack)
|
||||||
import qualified Data.Stack as Stack
|
import qualified Data.Stack as Stack
|
||||||
import Data.String (IsString)
|
|
||||||
import Data.Text (Text)
|
|
||||||
import GHC.Records
|
import GHC.Records
|
||||||
import Source.Span (Span)
|
import Source.Span (Span)
|
||||||
import qualified TreeSitter.Python.AST as Py
|
import qualified TreeSitter.Python.AST as Py
|
||||||
|
|
||||||
-- | Access to the current filename as Text to stick into location annotations.
|
|
||||||
newtype SourcePath = SourcePath { rawPath :: Text }
|
|
||||||
deriving (Eq, IsString, Show)
|
|
||||||
|
|
||||||
-- | Keeps track of the current scope's bindings (so that we can, when
|
-- | Keeps track of the current scope's bindings (so that we can, when
|
||||||
-- compiling a class or module, return the list of bound variables as
|
-- compiling a class or module, return the list of bound variables as
|
||||||
-- a Core record so that all immediate definitions are exposed)
|
-- a Core record so that all immediate definitions are exposed)
|
||||||
@ -57,7 +48,7 @@ pattern SingleIdentifier name <- Py.ExpressionList
|
|||||||
-- possible for us to 'cheat' by pattern-matching on or eliminating a
|
-- possible for us to 'cheat' by pattern-matching on or eliminating a
|
||||||
-- compiled term.
|
-- compiled term.
|
||||||
type CoreSyntax sig t = ( Member Core sig
|
type CoreSyntax sig t = ( Member Core sig
|
||||||
, Member Ann sig
|
, Member (Ann Span) sig
|
||||||
, Carrier sig t
|
, Carrier sig t
|
||||||
, Foldable t
|
, Foldable t
|
||||||
)
|
)
|
||||||
@ -66,7 +57,6 @@ class Compile (py :: * -> *) where
|
|||||||
-- FIXME: rather than failing the compilation process entirely
|
-- FIXME: rather than failing the compilation process entirely
|
||||||
-- with MonadFail, we should emit core that represents failure
|
-- with MonadFail, we should emit core that represents failure
|
||||||
compile :: ( CoreSyntax syn t
|
compile :: ( CoreSyntax syn t
|
||||||
, Member (Reader SourcePath) sig
|
|
||||||
, Member (Reader Bindings) sig
|
, Member (Reader Bindings) sig
|
||||||
, Carrier sig m
|
, Carrier sig m
|
||||||
, MonadFail m
|
, MonadFail m
|
||||||
@ -79,7 +69,6 @@ class Compile (py :: * -> *) where
|
|||||||
compile a _ _ = defaultCompile a
|
compile a _ _ = defaultCompile a
|
||||||
|
|
||||||
toplevelCompile :: ( CoreSyntax syn t
|
toplevelCompile :: ( CoreSyntax syn t
|
||||||
, Member (Reader SourcePath) sig
|
|
||||||
, Member (Reader Bindings) sig
|
, Member (Reader Bindings) sig
|
||||||
, Carrier sig m
|
, Carrier sig m
|
||||||
, MonadFail m
|
, MonadFail m
|
||||||
@ -93,20 +82,14 @@ toplevelCompile py = compile py pure none
|
|||||||
none :: (Member Core sig, Carrier sig t) => t Name
|
none :: (Member Core sig, Carrier sig t) => t Name
|
||||||
none = unit
|
none = unit
|
||||||
|
|
||||||
locFromTSSpan :: SourcePath -> Span -> Loc
|
|
||||||
locFromTSSpan fp = Data.Loc.Loc (rawPath fp)
|
|
||||||
|
|
||||||
locate :: ( HasField "ann" syntax Span
|
locate :: ( HasField "ann" syntax Span
|
||||||
, CoreSyntax syn t
|
, CoreSyntax syn t
|
||||||
, Member (Reader SourcePath) sig
|
, Applicative m
|
||||||
, Carrier sig m
|
|
||||||
)
|
)
|
||||||
=> syntax
|
=> syntax
|
||||||
-> t a
|
-> t a
|
||||||
-> m (t a)
|
-> m (t a)
|
||||||
locate syn item = do
|
locate syn item = pure (Core.annAt (getField @"ann" syn) item)
|
||||||
fp <- ask @SourcePath
|
|
||||||
pure (Core.annAt (locFromTSSpan fp (getField @"ann" syn)) item)
|
|
||||||
|
|
||||||
defaultCompile :: (MonadFail m, Show py) => py -> m (t Name)
|
defaultCompile :: (MonadFail m, Show py) => py -> m (t Name)
|
||||||
defaultCompile t = fail $ "compilation unimplemented for " <> show t
|
defaultCompile t = fail $ "compilation unimplemented for " <> show t
|
||||||
@ -140,20 +123,18 @@ type Desugared = Py.ExpressionList :+: Py.Yield
|
|||||||
|
|
||||||
-- We have to pair locations and names, and tuple syntax is harder to
|
-- We have to pair locations and names, and tuple syntax is harder to
|
||||||
-- read in this case than a happy little constructor.
|
-- read in this case than a happy little constructor.
|
||||||
data Located a = Located Loc a
|
data Located a = Located Span a
|
||||||
|
|
||||||
-- Desugaring an RHS involves walking as deeply as possible into an
|
-- Desugaring an RHS involves walking as deeply as possible into an
|
||||||
-- assignment, storing the names we encounter as we go and eventually
|
-- assignment, storing the names we encounter as we go and eventually
|
||||||
-- returning a terminal expression. We have to keep track of which
|
-- returning a terminal expression. We have to keep track of which
|
||||||
desugar :: (Member (Reader SourcePath) sig, Carrier sig m, MonadFail m)
|
desugar :: MonadFail m
|
||||||
=> [Located Name]
|
=> [Located Name]
|
||||||
-> RHS Span
|
-> RHS Span
|
||||||
-> m ([Located Name], Desugared Span)
|
-> m ([Located Name], Desugared Span)
|
||||||
desugar acc = \case
|
desugar acc = \case
|
||||||
Prj Py.Assignment { left = SingleIdentifier name, right = Just rhs, ann} -> do
|
Prj Py.Assignment { left = SingleIdentifier name, right = Just rhs, ann} ->
|
||||||
loc <- locFromTSSpan <$> ask <*> pure ann
|
desugar (Located ann name : acc) rhs
|
||||||
let cons = (Located loc name :)
|
|
||||||
desugar (cons acc) rhs
|
|
||||||
R1 any -> pure (acc, any)
|
R1 any -> pure (acc, any)
|
||||||
other -> fail ("desugar: couldn't desugar RHS " <> show other)
|
other -> fail ("desugar: couldn't desugar RHS " <> show other)
|
||||||
|
|
||||||
@ -179,8 +160,7 @@ instance Compile Py.Assignment where
|
|||||||
, right = Just rhs
|
, right = Just rhs
|
||||||
, ann
|
, ann
|
||||||
} cc next = do
|
} cc next = do
|
||||||
p <- ask @SourcePath
|
(names, val) <- desugar [Located ann name] rhs
|
||||||
(names, val) <- desugar [Located (locFromTSSpan p ann) name] rhs
|
|
||||||
compile val pure next >>= foldr collapseDesugared cc names >>= locate it
|
compile val pure next >>= foldr collapseDesugared cc names >>= locate it
|
||||||
|
|
||||||
compile other _ _ = fail ("Unhandled assignment case: " <> show other)
|
compile other _ _ = fail ("Unhandled assignment case: " <> show other)
|
||||||
|
@ -19,27 +19,27 @@ deriving newtype instance ToJSON Name
|
|||||||
deriving newtype instance ToJSONKey Name
|
deriving newtype instance ToJSONKey Name
|
||||||
|
|
||||||
instance ToJSON a => ToJSON (File a) where
|
instance ToJSON a => ToJSON (File a) where
|
||||||
toJSON File{fileLoc, fileBody} = object
|
toJSON File{filePath, fileSpan, fileBody} = object
|
||||||
[ "location" .= fileLoc
|
[ "path" .= filePath
|
||||||
|
, "span" .= fileSpan
|
||||||
, "body" .= fileBody
|
, "body" .= fileBody
|
||||||
]
|
]
|
||||||
|
|
||||||
instance ToJSON Loc where
|
deriving newtype instance ToJSON Path
|
||||||
toJSON Loc{locPath, locSpan} = object
|
|
||||||
[ "kind" .= ("loc" :: Text)
|
|
||||||
, "path" .= locPath
|
|
||||||
, "span" .= locSpan
|
|
||||||
]
|
|
||||||
|
|
||||||
instance ToJSON Ref where
|
instance ToJSON Ref where
|
||||||
toJSON (Ref loc) = object [ "kind" .= ("ref" :: Text)
|
toJSON (Ref path span) = object
|
||||||
, "location" .= loc]
|
[ "kind" .= ("ref" :: Text)
|
||||||
|
, "path" .= path
|
||||||
|
, "span" .= span
|
||||||
|
]
|
||||||
|
|
||||||
instance ToJSON Decl where
|
instance ToJSON Decl where
|
||||||
toJSON Decl{declSymbol, declLoc} = object
|
toJSON Decl{declSymbol, declPath, declSpan} = object
|
||||||
[ "kind" .= ("decl" :: Text)
|
[ "kind" .= ("decl" :: Text)
|
||||||
, "symbol" .= declSymbol
|
, "symbol" .= declSymbol
|
||||||
, "location" .= declLoc
|
, "path" .= declPath
|
||||||
|
, "span" .= declSpan
|
||||||
]
|
]
|
||||||
|
|
||||||
instance ToJSON ScopeGraph where
|
instance ToJSON ScopeGraph where
|
||||||
|
@ -25,10 +25,10 @@ import Data.Loc
|
|||||||
import Data.Maybe
|
import Data.Maybe
|
||||||
import Data.Name
|
import Data.Name
|
||||||
import Data.Term
|
import Data.Term
|
||||||
import Data.String (fromString)
|
|
||||||
import GHC.Stack
|
import GHC.Stack
|
||||||
import qualified Language.Python.Core as Py
|
import qualified Language.Python.Core as Py
|
||||||
import Prelude hiding (fail)
|
import Prelude hiding (fail)
|
||||||
|
import Source.Span
|
||||||
import Streaming
|
import Streaming
|
||||||
import qualified Streaming.Prelude as Stream
|
import qualified Streaming.Prelude as Stream
|
||||||
import qualified Streaming.Process
|
import qualified Streaming.Process
|
||||||
@ -49,10 +49,10 @@ import qualified Directive
|
|||||||
import Instances ()
|
import Instances ()
|
||||||
|
|
||||||
|
|
||||||
assertJQExpressionSucceeds :: Show a => Directive.Directive -> a -> Term (Ann :+: Core) Name -> HUnit.Assertion
|
assertJQExpressionSucceeds :: Show a => Directive.Directive -> a -> Term (Ann Span :+: Core) Name -> HUnit.Assertion
|
||||||
assertJQExpressionSucceeds directive tree core = do
|
assertJQExpressionSucceeds directive tree core = do
|
||||||
bod <- case scopeGraph Eval.eval [File interactive core] of
|
bod <- case scopeGraph Eval.eval [File (Path "<interactive>") (Span (Pos 1 1) (Pos 1 1)) core] of
|
||||||
(heap, [File _ (Right result)]) -> pure $ Aeson.object
|
(heap, [File _ _ (Right result)]) -> pure $ Aeson.object
|
||||||
[ "scope" Aeson..= heap
|
[ "scope" Aeson..= heap
|
||||||
, "heap" Aeson..= result
|
, "heap" Aeson..= result
|
||||||
]
|
]
|
||||||
@ -95,7 +95,6 @@ fixtureTestTreeForFile fp = HUnit.testCaseSteps (Path.toString fp) $ \step -> wi
|
|||||||
result <- ByteString.readFile (Path.toString fullPath) >>= TS.parseByteString TSP.tree_sitter_python
|
result <- ByteString.readFile (Path.toString fullPath) >>= TS.parseByteString TSP.tree_sitter_python
|
||||||
let coreResult = Control.Effect.run
|
let coreResult = Control.Effect.run
|
||||||
. runFail
|
. runFail
|
||||||
. runReader (fromString @Py.SourcePath . Path.toString $ fp)
|
|
||||||
. runReader @Py.Bindings mempty
|
. runReader @Py.Bindings mempty
|
||||||
. Py.toplevelCompile
|
. Py.toplevelCompile
|
||||||
<$> result
|
<$> result
|
||||||
|
Loading…
Reference in New Issue
Block a user