2019-10-11 09:08:36 +00:00
|
|
|
{-# LANGUAGE DuplicateRecordFields, OverloadedLists, InstanceSigs #-}
|
2019-10-17 21:28:40 +00:00
|
|
|
{-# OPTIONS_GHC -Wall #-}
|
2019-10-03 14:13:34 +00:00
|
|
|
module Rubyhs.References
|
|
|
|
( References(entries)
|
|
|
|
, FQN(..)
|
|
|
|
, references
|
2019-10-11 09:08:36 +00:00
|
|
|
, Env(..)
|
2019-10-11 09:37:11 +00:00
|
|
|
, Result(..)
|
2019-10-11 14:55:48 +00:00
|
|
|
, Context(..)
|
2019-10-16 18:12:07 +00:00
|
|
|
, graph
|
|
|
|
, prettyContext
|
|
|
|
, Node(..)
|
2019-10-03 14:13:34 +00:00
|
|
|
) where
|
|
|
|
|
2019-11-13 10:50:37 +00:00
|
|
|
import qualified Prelude
|
2019-10-03 14:13:34 +00:00
|
|
|
import Frelude
|
2019-10-11 12:03:01 +00:00
|
|
|
import qualified Data.Language.Ruby as Ruby
|
2019-10-18 20:20:26 +00:00
|
|
|
import Data.HashMap.Strict (HashMap)
|
|
|
|
import qualified Data.HashMap.Strict as HashMap
|
|
|
|
import qualified Data.Aeson.Encoding.Internal as Aeson
|
2019-10-03 14:13:34 +00:00
|
|
|
import Data.Kind
|
|
|
|
import Control.Monad.State
|
|
|
|
import qualified Data.Aeson as Aeson
|
2019-10-18 20:20:26 +00:00
|
|
|
import qualified Data.Aeson.Types as Aeson
|
2019-10-11 12:03:01 +00:00
|
|
|
import Data.Set (Set)
|
|
|
|
import qualified Data.Set as Set
|
2019-10-15 18:46:28 +00:00
|
|
|
import qualified Data.Text as Text
|
|
|
|
import Data.Coerce
|
2019-10-16 18:12:07 +00:00
|
|
|
import Data.Graph (Graph, Vertex, Forest)
|
|
|
|
import qualified Data.Graph as Graph
|
2019-10-18 20:20:26 +00:00
|
|
|
import Data.Hashable
|
|
|
|
import qualified Data.Char as Char
|
2019-10-16 18:12:07 +00:00
|
|
|
|
|
|
|
span :: G node key -> Forest node
|
|
|
|
span (g, f, _) = fmap ((\(x, _, _) -> x) . f) <$> Graph.dff g
|
|
|
|
|
|
|
|
type G node key = (Graph, Vertex -> (node, key, [key]), key -> Maybe Vertex)
|
|
|
|
|
2019-10-17 21:28:40 +00:00
|
|
|
graph :: Ruby.Begin -> Forest Node
|
2019-10-16 18:12:07 +00:00
|
|
|
graph b = span $ Graph.graphFromEdges $ go <$> toList ys
|
|
|
|
where
|
|
|
|
go :: (Node, Set Node) -> (Node, Text, [Text])
|
|
|
|
go (x, xs) = (x, prettyContext x, prettyContext <$> toList xs)
|
|
|
|
Result ys = references b
|
2019-10-03 14:13:34 +00:00
|
|
|
|
2019-10-20 20:43:48 +00:00
|
|
|
-- The elements appear in reverse order. I expect this to cause all
|
|
|
|
-- sorts of issues.
|
2019-10-11 12:03:01 +00:00
|
|
|
newtype Namespace = Namespace [Text]
|
|
|
|
deriving stock instance Show Namespace
|
|
|
|
deriving stock instance Eq Namespace
|
|
|
|
deriving stock instance Ord Namespace
|
|
|
|
instance IsList Namespace where
|
|
|
|
type Item Namespace = Text
|
2019-10-15 19:50:19 +00:00
|
|
|
fromList = coerce
|
|
|
|
toList = coerce
|
2019-10-11 12:03:01 +00:00
|
|
|
deriving newtype instance Semigroup Namespace
|
|
|
|
deriving newtype instance Monoid Namespace
|
2019-10-18 20:20:26 +00:00
|
|
|
instance FromJSON Namespace where
|
2019-10-20 20:43:48 +00:00
|
|
|
parseJSON = Aeson.withText "Namespace"
|
2019-11-13 10:50:37 +00:00
|
|
|
$ \t -> Namespace <$> (traverse pure $ Text.splitOn "::" t)
|
2019-10-15 18:46:28 +00:00
|
|
|
instance ToJSON Namespace where
|
2019-10-15 19:50:19 +00:00
|
|
|
toJSON = Aeson.String . showNamespace
|
|
|
|
|
2019-10-11 09:37:11 +00:00
|
|
|
-- Names are in reverse order.
|
2019-10-11 12:03:01 +00:00
|
|
|
data FQN = FQN
|
|
|
|
{ namespace :: Namespace
|
|
|
|
, name :: Text
|
|
|
|
}
|
2019-10-03 14:13:34 +00:00
|
|
|
|
2019-10-17 21:28:40 +00:00
|
|
|
data Node = NodeDef FQN | NodeModule Namespace
|
2019-10-15 18:46:28 +00:00
|
|
|
|
2019-10-18 20:20:26 +00:00
|
|
|
beginsWithCapital :: Text -> Bool
|
|
|
|
beginsWithCapital = Char.isUpper . Text.head
|
|
|
|
|
2019-10-15 18:46:28 +00:00
|
|
|
deriving stock instance Show Node
|
|
|
|
deriving stock instance Eq Node
|
|
|
|
deriving stock instance Ord Node
|
2019-10-18 20:20:26 +00:00
|
|
|
instance FromJSON Node where
|
|
|
|
parseJSON = Aeson.withText "Node" $ nodeParser
|
|
|
|
nodeParser :: Text -> Aeson.Parser Node
|
|
|
|
nodeParser = \t -> case Text.splitOn "." t of
|
|
|
|
[mods,fun] -> fmap NodeDef (FQN <$> Aeson.parseJSON (Aeson.String mods) <*> pure fun)
|
2019-10-20 20:43:48 +00:00
|
|
|
-- The top-level
|
|
|
|
[[]] -> pure $ NodeModule mempty
|
2019-10-18 20:20:26 +00:00
|
|
|
[mods] ->
|
|
|
|
if beginsWithCapital mods
|
|
|
|
then NodeModule <$> Aeson.parseJSON (Aeson.String mods)
|
|
|
|
else pure $ NodeDef $ FQN mempty mods
|
|
|
|
_ -> empty
|
|
|
|
instance Aeson.FromJSONKey Node where
|
|
|
|
fromJSONKey = Aeson.FromJSONKeyTextParser nodeParser
|
|
|
|
instance Aeson.ToJSONKey Node where
|
|
|
|
toJSONKey = Aeson.ToJSONKeyText prettyContext (\n -> Aeson.text $ prettyContext n)
|
2019-10-15 18:46:28 +00:00
|
|
|
instance ToJSON Node where
|
|
|
|
toJSON = \case
|
2019-10-17 21:28:40 +00:00
|
|
|
NodeDef q -> Aeson.toJSON q
|
2019-10-15 18:46:28 +00:00
|
|
|
NodeModule m -> Aeson.toJSON m
|
2019-10-18 20:20:26 +00:00
|
|
|
instance Hashable Node where
|
|
|
|
hashWithSalt n a = hashWithSalt @Text n $ prettyContext a
|
2019-10-15 18:46:28 +00:00
|
|
|
|
2019-10-11 09:08:36 +00:00
|
|
|
deriving stock instance Show FQN
|
2019-10-11 12:03:01 +00:00
|
|
|
deriving stock instance Eq FQN
|
|
|
|
deriving stock instance Ord FQN
|
|
|
|
instance Pretty Namespace where
|
2019-10-15 19:50:19 +00:00
|
|
|
pretty = pretty . showNamespace
|
2019-10-11 12:03:01 +00:00
|
|
|
|
|
|
|
instance Aeson.ToJSON FQN where
|
|
|
|
toJSON = Aeson.String . prettyFQN
|
2019-10-11 09:08:36 +00:00
|
|
|
instance Aeson.ToJSONKey FQN where
|
|
|
|
instance Pretty FQN where
|
2019-10-11 12:03:01 +00:00
|
|
|
pretty = pretty . prettyFQN
|
|
|
|
|
|
|
|
prettyFQN :: FQN -> Text
|
2019-10-15 18:46:28 +00:00
|
|
|
prettyFQN FQN{name, namespace} = case namespace of
|
2019-10-11 12:03:01 +00:00
|
|
|
[] -> name
|
2019-10-15 19:50:19 +00:00
|
|
|
_ -> convertString (showNamespace namespace) <> "." <> name
|
2019-10-03 14:13:34 +00:00
|
|
|
|
2019-10-20 20:43:48 +00:00
|
|
|
prettyContext :: Node -> Text
|
|
|
|
prettyContext = \case
|
|
|
|
NodeDef fun -> prettyFQN fun
|
|
|
|
NodeModule ns -> showNamespace ns
|
|
|
|
|
|
|
|
showNamespace :: Namespace -> Text
|
2019-11-13 10:50:37 +00:00
|
|
|
showNamespace = Text.intercalate "::" . coerce
|
2019-10-20 20:43:48 +00:00
|
|
|
|
2019-10-15 18:46:28 +00:00
|
|
|
newtype Context = Context Node
|
2019-10-11 14:55:48 +00:00
|
|
|
|
|
|
|
deriving stock instance Eq Context
|
|
|
|
deriving stock instance Ord Context
|
2019-10-15 18:46:28 +00:00
|
|
|
deriving newtype instance ToJSON Context
|
2019-10-17 21:28:40 +00:00
|
|
|
-- HACK: Not really a semigroup as is evident from the implementation.
|
|
|
|
instance Semigroup Context where
|
2019-10-20 20:43:48 +00:00
|
|
|
-- I think that the order must be swapped because they modules are in reverse order.
|
2019-11-13 10:50:37 +00:00
|
|
|
Context c0 <> Context c1 = Context $ c0 <> c1
|
|
|
|
instance Semigroup Node where
|
|
|
|
c0 <> c1 = case (c0, c1) of
|
2019-10-20 20:43:48 +00:00
|
|
|
-- (NodeModule n0, NodeModule n1) -> Context $ NodeModule $ n0 <> n1
|
2019-11-13 10:50:37 +00:00
|
|
|
(NodeModule n0, NodeModule n1) -> NodeModule $ n0 <> n1
|
2019-10-20 20:43:48 +00:00
|
|
|
-- (NodeModule n0, NodeDef (FQN n1 f)) -> Context $ NodeDef $ FQN (n0 <> n1) f
|
2019-11-13 10:50:37 +00:00
|
|
|
(NodeModule n0, NodeDef (FQN n1 f)) -> NodeDef $ FQN (n0 <> n1) f
|
2019-10-17 21:28:40 +00:00
|
|
|
(NodeDef{}, NodeModule{}) -> error "Cannot append module to function context."
|
2019-11-13 10:50:37 +00:00
|
|
|
-- (NodeDef{}, NodeDef{}) -> error "Cannot append function to function context."
|
|
|
|
(NodeDef (FQN n0 _), NodeDef (FQN n1 a1)) -> NodeDef $ FQN (n0 <> n1) a1
|
2019-10-11 14:55:48 +00:00
|
|
|
|
2019-10-03 14:13:34 +00:00
|
|
|
class Monad m => MyMonad (m :: Type -> Type) where
|
2019-10-15 18:46:28 +00:00
|
|
|
declaration :: Node -> m ()
|
2019-10-16 20:43:19 +00:00
|
|
|
application :: Node -> m ()
|
2019-10-11 14:55:48 +00:00
|
|
|
getContext :: m Context
|
|
|
|
writeContext :: Context -> m ()
|
2019-10-03 14:13:34 +00:00
|
|
|
|
|
|
|
data Env = Env
|
2019-10-15 18:46:28 +00:00
|
|
|
{ declarations :: Set Node
|
2019-10-18 20:20:26 +00:00
|
|
|
, applications :: HashMap Node (Set Node)
|
2019-10-11 14:55:48 +00:00
|
|
|
, context :: Context
|
2019-10-03 14:13:34 +00:00
|
|
|
}
|
|
|
|
|
2019-10-18 20:20:26 +00:00
|
|
|
newtype Result = Result (HashMap Node (Set Node))
|
|
|
|
-- HACK: FromJSON and ToJSON don't agree.
|
|
|
|
deriving newtype instance FromJSON Result
|
2019-10-11 09:37:11 +00:00
|
|
|
instance ToJSON Result where
|
2019-10-16 18:12:07 +00:00
|
|
|
toJSON (Result a) = Aeson.Object $ fromList $ go <$> toList a
|
2019-10-11 09:37:11 +00:00
|
|
|
where
|
2019-10-16 18:12:07 +00:00
|
|
|
go :: (Node, Set Node) -> (Text, Aeson.Value)
|
|
|
|
go (x, y) = (prettyContext x, Aeson.toJSON y)
|
2019-10-03 14:13:34 +00:00
|
|
|
|
|
|
|
instance MyMonad (State Env) where
|
2019-10-11 12:03:01 +00:00
|
|
|
declaration q = modify go
|
2019-10-03 14:13:34 +00:00
|
|
|
where
|
2019-10-11 09:37:11 +00:00
|
|
|
go :: Env -> Env
|
2019-10-11 12:03:01 +00:00
|
|
|
go env@Env{declarations} = env { declarations = Set.insert q declarations }
|
2019-10-16 20:43:19 +00:00
|
|
|
application n = do
|
|
|
|
Context c <- getContext
|
2019-11-13 10:50:37 +00:00
|
|
|
decls <- gets declarations
|
|
|
|
n' <- findClosest decls n
|
2019-10-16 20:43:19 +00:00
|
|
|
let
|
2019-11-13 10:50:37 +00:00
|
|
|
-- n' = findCloses n
|
|
|
|
-- case n of
|
|
|
|
-- -- TODO: Maybe check if there is `a` is a function in the
|
|
|
|
-- -- current closure.
|
|
|
|
-- (NodeDef (FQN [] a)) -> NodeDef $ FQN (nodeNs c) a
|
|
|
|
-- -- Look for the closest enclosing scope that has a reference
|
|
|
|
-- -- to `c`. For now we'll just guess that it is a fully
|
|
|
|
-- -- qualified reference.
|
|
|
|
-- NodeDef{} -> n
|
|
|
|
-- -- Ditto as above.
|
|
|
|
-- NodeModule{} -> n
|
2019-10-16 20:43:19 +00:00
|
|
|
go env@Env{applications}
|
2019-10-20 20:14:50 +00:00
|
|
|
= env { applications = HashMap.insertWith mappend c (Set.singleton n') applications }
|
2019-10-16 20:43:19 +00:00
|
|
|
modify go
|
2019-10-17 21:28:40 +00:00
|
|
|
getContext = gets Rubyhs.References.context
|
2019-10-03 14:13:34 +00:00
|
|
|
writeContext q = modify go
|
|
|
|
where
|
2019-10-17 21:28:40 +00:00
|
|
|
go env = env { Rubyhs.References.context = q }
|
2019-10-03 14:13:34 +00:00
|
|
|
|
2019-11-13 10:50:37 +00:00
|
|
|
findClosest :: MyMonad m => Set Node -> Node -> m Node
|
|
|
|
findClosest decls n = do
|
|
|
|
Context c <- getContext
|
|
|
|
pure $ go $ c
|
|
|
|
where
|
|
|
|
go :: Node -> Node
|
|
|
|
go c = case Set.member (c <> n) decls of
|
|
|
|
True -> c <> n
|
|
|
|
False -> case c of
|
|
|
|
NodeModule [] -> case n of -- Last resort
|
|
|
|
NodeDef (FQN _ a) -> NodeDef (FQN mempty a)
|
|
|
|
x -> x
|
|
|
|
_ -> go $ drop c
|
|
|
|
drop :: Node -> Node
|
|
|
|
drop = \case
|
|
|
|
(NodeDef (FQN a _)) -> NodeModule a
|
|
|
|
(NodeModule (Namespace [])) -> error "__IMPOSSIBLE__"
|
|
|
|
(NodeModule (Namespace xs)) -> NodeModule $ Namespace $ reverse $ Prelude.tail $ reverse xs
|
2019-10-20 20:14:50 +00:00
|
|
|
|
2019-10-03 14:13:34 +00:00
|
|
|
locally :: MyMonad m => m a -> m a
|
|
|
|
locally act = do
|
|
|
|
old <- getContext
|
|
|
|
res <- act
|
|
|
|
writeContext old
|
|
|
|
pure res
|
|
|
|
|
|
|
|
class References a where
|
|
|
|
entries :: MyMonad m => a -> m ()
|
|
|
|
|
2019-10-17 21:28:40 +00:00
|
|
|
references :: Ruby.Begin -> Result
|
2019-10-18 20:20:26 +00:00
|
|
|
references q = Result $ HashMap.unionWith mappend applications declarations'
|
2019-10-11 09:37:11 +00:00
|
|
|
where
|
2019-10-11 14:55:48 +00:00
|
|
|
Env{declarations,applications} = execState (entries @_ @(State Env) q) emptyEnv
|
2019-10-15 18:46:28 +00:00
|
|
|
emptyEnv = Env mempty mempty (Context $ NodeModule mempty)
|
2019-10-16 18:12:07 +00:00
|
|
|
declarations' = fromList $ (\x -> (x, mempty)) <$> toList declarations
|
2019-10-03 14:13:34 +00:00
|
|
|
|
2019-10-17 21:28:40 +00:00
|
|
|
instance References Ruby.Begin where
|
|
|
|
entries :: forall m . MyMonad m => Ruby.Begin -> m ()
|
|
|
|
entries (Ruby.Begin defs) = traverse_ (locally . entries) defs
|
2019-10-03 14:13:34 +00:00
|
|
|
|
2019-10-17 21:28:40 +00:00
|
|
|
instance References Ruby.Statement where
|
2019-10-03 14:13:34 +00:00
|
|
|
entries = \case
|
2019-10-17 21:28:40 +00:00
|
|
|
Ruby.StmtModule m -> entries m
|
|
|
|
Ruby.StmtDef f -> entries f
|
|
|
|
Ruby.StmtDefs f -> entries f
|
|
|
|
Ruby.StmtSend s -> entries s
|
|
|
|
Ruby.StmtConst c -> entries c
|
|
|
|
Ruby.StmtBlock b -> entries b
|
|
|
|
Ruby.StmtCasgn c -> entries c
|
|
|
|
Ruby.StmtArray a -> entries a
|
|
|
|
Ruby.StmtSym s -> entries s
|
|
|
|
Ruby.StmtStr s -> entries s
|
|
|
|
Ruby.StmtLvasgn a -> entries a
|
|
|
|
Ruby.StmtLvar a -> entries a
|
|
|
|
Ruby.StmtIvar a -> entries a
|
|
|
|
Ruby.StmtSelf s -> entries s
|
|
|
|
Ruby.StmtCbase s -> entries s
|
|
|
|
Ruby.StmtNil n -> entries n
|
|
|
|
Ruby.StmtAnything a -> entries a
|
2019-10-16 20:12:30 +00:00
|
|
|
|
2019-10-17 18:08:25 +00:00
|
|
|
instance References Ruby.Block where
|
2019-10-17 21:28:40 +00:00
|
|
|
entries Ruby.Block{send,args,begin} = do
|
2019-10-16 20:35:15 +00:00
|
|
|
entries send
|
|
|
|
entries args
|
2019-10-17 18:08:25 +00:00
|
|
|
entries begin
|
2019-10-17 21:28:40 +00:00
|
|
|
instance References Ruby.Args where
|
2019-10-16 20:12:30 +00:00
|
|
|
entries = const $ pure ()
|
2019-10-16 21:23:40 +00:00
|
|
|
-- TODO: We have to make a "declaration" for the constant here as
|
|
|
|
-- well!
|
2019-10-16 20:12:30 +00:00
|
|
|
instance References Ruby.Casgn where
|
2019-10-17 21:28:40 +00:00
|
|
|
entries Ruby.Casgn{rhs} = entries rhs
|
2019-10-17 18:08:25 +00:00
|
|
|
instance References Ruby.Sym where
|
|
|
|
entries _ = pure ()
|
2019-10-17 21:28:40 +00:00
|
|
|
instance References Ruby.Str where
|
|
|
|
entries _ = pure ()
|
|
|
|
instance References Ruby.Lvasgn where
|
|
|
|
entries _ = pure ()
|
|
|
|
instance References Ruby.Lvar where
|
|
|
|
entries _ = pure ()
|
|
|
|
instance References Ruby.Ivar where
|
|
|
|
entries _ = pure ()
|
|
|
|
instance References Ruby.Self where
|
|
|
|
entries _ = pure ()
|
|
|
|
instance References Ruby.Cbase where
|
|
|
|
entries _ = pure ()
|
|
|
|
instance References Ruby.Nil where
|
|
|
|
entries _ = pure ()
|
|
|
|
instance References Ruby.Array where
|
|
|
|
entries Ruby.Array{statements} = traverse_ entries statements
|
2019-10-16 20:12:30 +00:00
|
|
|
instance References Ruby.Anything where
|
|
|
|
entries = const $ pure ()
|
2019-10-03 14:13:34 +00:00
|
|
|
|
2019-10-17 21:28:40 +00:00
|
|
|
instance References Ruby.Const where
|
|
|
|
entries con = application $ NodeModule $ constToNamespace con
|
|
|
|
|
|
|
|
updateContext :: MyMonad m => (Context -> Context) -> m ()
|
|
|
|
updateContext f = getContext >>= \c -> writeContext (f c)
|
|
|
|
|
|
|
|
instance References Ruby.Module where
|
|
|
|
entries Ruby.Module{name, begin} = do
|
2019-11-13 10:50:37 +00:00
|
|
|
updateContext $ (<> (Context $ NodeModule $ constToNamespace name))
|
2019-10-15 18:46:28 +00:00
|
|
|
c <- getContext >>= \case
|
|
|
|
Context (NodeModule c) -> pure c
|
|
|
|
_ -> error "..."
|
|
|
|
declaration $ NodeModule c
|
2019-10-17 18:08:25 +00:00
|
|
|
entries begin
|
|
|
|
|
2019-10-17 21:28:40 +00:00
|
|
|
atomToNode :: MyMonad m => Ruby.Atom -> m Node
|
|
|
|
atomToNode (Ruby.Atom name) = do
|
2019-11-13 10:50:37 +00:00
|
|
|
namespace <- getContext >>= pure . \case
|
|
|
|
Context (NodeModule c) -> c
|
2019-10-17 21:28:40 +00:00
|
|
|
-- We could allow this and just say that the function defined in
|
|
|
|
-- another function sits in the same context as the surrounding
|
|
|
|
-- function.
|
2019-11-13 10:50:37 +00:00
|
|
|
Context (NodeDef (FQN ns _)) -> ns
|
2019-10-17 21:28:40 +00:00
|
|
|
pure $ NodeDef $ FQN namespace name
|
|
|
|
|
|
|
|
instance References Ruby.Def where
|
|
|
|
entries Ruby.Def{atom, begin} = do
|
|
|
|
node <- atomToNode atom
|
2019-10-17 18:08:25 +00:00
|
|
|
declaration node
|
2019-10-11 14:55:48 +00:00
|
|
|
locally $ do
|
2019-10-17 18:08:25 +00:00
|
|
|
writeContext (Context node)
|
|
|
|
entries begin
|
2019-10-03 14:13:34 +00:00
|
|
|
|
2019-10-17 21:28:40 +00:00
|
|
|
instance References Ruby.Defs where
|
|
|
|
-- TODO: The field `context` is also relevant here!
|
2019-10-20 20:43:48 +00:00
|
|
|
entries Ruby.Defs{atom, begin, args}
|
|
|
|
= entries $ Ruby.Def{atom,begin,args}
|
2019-10-15 19:50:19 +00:00
|
|
|
|
2019-10-17 21:28:40 +00:00
|
|
|
qual :: Namespace -> Ruby.Atom -> FQN
|
|
|
|
qual namespace (Ruby.Atom name) = FQN { namespace , name }
|
2019-10-15 19:50:19 +00:00
|
|
|
|
2019-10-17 21:28:40 +00:00
|
|
|
instance References Ruby.Send where
|
|
|
|
entries Ruby.Send{context, atom, args} = do
|
|
|
|
application $ NodeDef $ qual (statementToNamespace context) atom
|
|
|
|
traverse_ entries args
|
2019-10-15 19:50:19 +00:00
|
|
|
|
2019-10-17 21:28:40 +00:00
|
|
|
statementToNamespace :: Ruby.Statement -> Namespace
|
|
|
|
statementToNamespace = go mempty
|
|
|
|
where
|
|
|
|
go acc = \case
|
|
|
|
Ruby.StmtConst c -> acc <> constToNamespace c
|
|
|
|
-- The nil-case and cbase-case should produce different results,
|
|
|
|
-- surely. `Namespace` may not be a good representation.
|
|
|
|
Ruby.StmtNil{} -> acc
|
|
|
|
Ruby.StmtCbase{} -> acc
|
|
|
|
-- The send-, ivar- and lvar- case cannot be handled because of the way
|
|
|
|
-- we've defined `Namespace`.
|
|
|
|
Ruby.StmtSend{} -> acc
|
|
|
|
Ruby.StmtIvar{} -> acc
|
|
|
|
Ruby.StmtLvar{} -> acc
|
|
|
|
_ -> error "Can only build namespaces from sequences of `const` statements"
|
|
|
|
|
|
|
|
constToNamespace :: Ruby.Const -> Namespace
|
|
|
|
constToNamespace Ruby.Const{context, atom} = statementToNamespace context <> [k]
|
|
|
|
where
|
|
|
|
Ruby.Atom k = atom
|