Allow applications to appear in function OR module contexts

This commit is contained in:
Frederik Hanghøj Iversen 2019-10-11 16:55:48 +02:00
parent 04253ffef8
commit 38098122f3
4 changed files with 35 additions and 23 deletions

View File

@ -51,3 +51,5 @@ So for instance. The monomorphic type `Parser Function` is a
procedure that generates a value of type `Function`:
*** Live coding
Define an instance for `FromJSON` for `Function`.
Define an instance for `FromJSON` for `Definition`.

View File

@ -25,6 +25,7 @@ module M
end
module K
f
end
f(2)

View File

@ -61,10 +61,10 @@ instance ToJSON Definition where
x -> x
instance FromJSON Definition where
parseJSON val
= (DefModule <$> parseJSON val)
<|> (DefFunction <$> parseJSON val)
<|> (DefSend <$> parseJSON val)
parseJSON v
= (DefModule <$> parseJSON v)
<|> (DefFunction <$> parseJSON v)
<|> (DefSend <$> parseJSON v)
newtype Namespace = Namespace [Name]

View File

@ -8,6 +8,7 @@ module Rubyhs.References
, Env(..)
, Result(..)
, Namespace(..)
, Context(..)
) where
import Frelude
@ -21,8 +22,6 @@ import Data.Aeson ((.=))
import qualified Data.Aeson as Aeson
import Data.List
import Data.HashMap.Strict (HashMap)
import Data.Text.Prettyprint.Doc.Render.Text (renderStrict)
import Data.Text.Prettyprint.Doc (layoutCompact)
import Data.Set (Set)
import qualified Data.Set as Set
@ -68,21 +67,26 @@ prettyFQN FQN{namespace, name} = case namespace of
prettyNamespace :: Namespace -> Text
prettyNamespace = convertString . intercalate "::" . fmap convertString . reverse . toList
data Context = ContextFun FQN | ContextMod Namespace
deriving stock instance Eq Context
deriving stock instance Ord Context
class Monad m => MyMonad (m :: Type -> Type) where
declaration :: FQN -> m ()
application :: Namespace -> FQN -> m ()
getContext :: m Namespace
writeContext :: Namespace -> m ()
application :: Context -> FQN -> m ()
getContext :: m Context
writeContext :: Context -> m ()
data Env = Env
{ declarations :: Set FQN
, applications :: Map Namespace (Set FQN)
, context :: Namespace
, applications :: Map Context (Set FQN)
, context :: Context
}
data Result = Result
{ declarations :: Set FQN
, applications :: Map Namespace (Set FQN)
, applications :: Map Context (Set FQN)
}
instance ToJSON Result where
toJSON Result{declarations,applications} = Aeson.object
@ -91,13 +95,12 @@ instance ToJSON Result where
]
where
f x = fromList @(HashMap _ _) $ go <$> toList x
go (x, y) = (renderStrict $ layoutCompact $ pretty x, y)
go (x, y) = (prettyContext x, y)
instance Semigroup Env where
Env a0 a1 a2 <> Env b0 b1 b2 = Env (a0 <> b0) (a1 <> b1) (a2 <> b2)
instance Monoid Env where
mempty = Env mempty mempty mempty
prettyContext :: Context -> Text
prettyContext = \case
ContextFun q -> prettyFQN q
ContextMod ns -> prettyNamespace ns
instance MyMonad (State Env) where
declaration q = modify go
@ -113,7 +116,7 @@ instance MyMonad (State Env) where
where
go env = env { context = q }
updateContext :: MyMonad m => (Namespace -> Namespace) -> m ()
updateContext :: MyMonad m => (Context -> Context) -> m ()
updateContext f = getContext >>= \c -> writeContext (f c)
locally :: MyMonad m => m a -> m a
@ -126,7 +129,8 @@ locally act = do
appendToContext :: MyMonad m => Name -> m ()
appendToContext n = updateContext go
where
go q = name2ns n <> q
go (ContextMod q) = ContextMod $ name2ns n <> q
go _ = error "Cannot append module to context in function context"
name2ns :: Name -> Namespace
name2ns (Name o) = go o
@ -144,7 +148,8 @@ class References a where
references :: Block -> Result
references q = Result{declarations, applications}
where
Env{declarations,applications} = execState (entries @_ @(State Env) q) mempty
Env{declarations,applications} = execState (entries @_ @(State Env) q) emptyEnv
emptyEnv = Env mempty mempty (ContextMod mempty)
instance References Block where
entries :: forall m . MyMonad m => Block -> m ()
@ -163,9 +168,13 @@ instance References Module where
instance References Function where
entries Function{name, block} = do
namespace <- getContext
namespace <- getContext >>= \case
ContextMod c -> pure c
_ -> error "Cannot have a function declaration in a function context"
declaration $ qual namespace name
entries block
locally $ do
writeContext (ContextFun $ qual namespace name)
entries block
qual :: Namespace -> Name -> FQN
qual namespace (Name o) = case o of