Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make names in scope in functors accessible when their instantiations are loaded at the REPL #1559

Merged
merged 17 commits into from
Aug 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# UNRELEASED

* Fixed #1556, #1237, and #1561.
* Fixed #1455, making anything in scope of the functor in scope at the REPL as
well when an instantiation of the functor is loaded and focused,
design choice (3) on the ticket. In particular, the prelude will be in scope.


# 3.0.0 -- 2023-06-26

## Language changes
Expand Down
1 change: 1 addition & 0 deletions cryptol.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ library
Cryptol.ModuleSystem.Name,
Cryptol.ModuleSystem.Names,
Cryptol.ModuleSystem.NamingEnv,
Cryptol.ModuleSystem.NamingEnv.Types,
Cryptol.ModuleSystem.Binds
Cryptol.ModuleSystem.Exports,
Cryptol.ModuleSystem.Renamer,
Expand Down
6 changes: 5 additions & 1 deletion src/Cryptol/ModuleSystem/Base.hs
Original file line number Diff line number Diff line change
Expand Up @@ -631,7 +631,11 @@ checkModule isrc m = do
rewMod <- case tcm of
T.TCTopModule mo -> T.TCTopModule <$> liftSupply (`rewModule` mo)
T.TCTopSignature {} -> pure tcm
pure (R.rmInScope renMod,rewMod)
let nameEnv = case tcm of
T.TCTopModule mo -> T.mInScope mo
-- Name env for signatures does not change after typechecking
T.TCTopSignature {} -> mInScope (R.rmModule renMod)
pure (nameEnv,rewMod)

data TCLinter o = TCLinter
{ lintCheck ::
Expand Down
10 changes: 9 additions & 1 deletion src/Cryptol/ModuleSystem/Binds.hs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
, topModuleDefs
, topDeclsDefs
, newModParam
, newFunctorInst
, InModule(..)
, ifaceToMod
, ifaceSigToMod
Expand Down Expand Up @@ -125,7 +126,7 @@
, modState = ()
}
where
env = modParamsNamingEnv ps
env = modParamNamesNamingEnv ps



Expand Down Expand Up @@ -334,33 +335,33 @@


instance BindsNames (InModule (NestedModule PName)) where
namingEnv (InModule ~(Just m) (NestedModule mdef)) = BuildNamingEnv $

Check warning on line 338 in src/Cryptol/ModuleSystem/Binds.hs

View workflow job for this annotation

GitHub Actions / build (ubuntu-20.04, 9.2.8, false)

Pattern match(es) are non-exhaustive

Check warning on line 338 in src/Cryptol/ModuleSystem/Binds.hs

View workflow job for this annotation

GitHub Actions / build (ubuntu-22.04, 9.2.8, 3.8.1.0, true)

Pattern match(es) are non-exhaustive

Check warning on line 338 in src/Cryptol/ModuleSystem/Binds.hs

View workflow job for this annotation

GitHub Actions / build (windows-2019, 9.2.8, 3.8.1.0, true)

Pattern match(es) are non-exhaustive

Check warning on line 338 in src/Cryptol/ModuleSystem/Binds.hs

View workflow job for this annotation

GitHub Actions / build (macos-12, 9.2.8, 3.8.1.0, true)

Pattern match(es) are non-exhaustive
do let pnmame = mName mdef
nm <- newTop NSModule m (thing pnmame) Nothing (srcRange pnmame)
pure (singletonNS NSModule (thing pnmame) nm)

instance BindsNames (InModule (PrimType PName)) where
namingEnv (InModule ~(Just m) PrimType { .. }) =

Check warning on line 344 in src/Cryptol/ModuleSystem/Binds.hs

View workflow job for this annotation

GitHub Actions / build (ubuntu-20.04, 9.2.8, false)

Pattern match(es) are non-exhaustive

Check warning on line 344 in src/Cryptol/ModuleSystem/Binds.hs

View workflow job for this annotation

GitHub Actions / build (ubuntu-22.04, 9.2.8, 3.8.1.0, true)

Pattern match(es) are non-exhaustive

Check warning on line 344 in src/Cryptol/ModuleSystem/Binds.hs

View workflow job for this annotation

GitHub Actions / build (windows-2019, 9.2.8, 3.8.1.0, true)

Pattern match(es) are non-exhaustive

Check warning on line 344 in src/Cryptol/ModuleSystem/Binds.hs

View workflow job for this annotation

GitHub Actions / build (macos-12, 9.2.8, 3.8.1.0, true)

Pattern match(es) are non-exhaustive
BuildNamingEnv $
do let Located { .. } = primTName
nm <- newTop NSType m thing primTFixity srcRange
pure (singletonNS NSType thing nm)

instance BindsNames (InModule (ParameterFun PName)) where
namingEnv (InModule ~(Just ns) ParameterFun { .. }) = BuildNamingEnv $

Check warning on line 351 in src/Cryptol/ModuleSystem/Binds.hs

View workflow job for this annotation

GitHub Actions / build (ubuntu-20.04, 9.2.8, false)

Pattern match(es) are non-exhaustive

Check warning on line 351 in src/Cryptol/ModuleSystem/Binds.hs

View workflow job for this annotation

GitHub Actions / build (ubuntu-22.04, 9.2.8, 3.8.1.0, true)

Pattern match(es) are non-exhaustive

Check warning on line 351 in src/Cryptol/ModuleSystem/Binds.hs

View workflow job for this annotation

GitHub Actions / build (windows-2019, 9.2.8, 3.8.1.0, true)

Pattern match(es) are non-exhaustive

Check warning on line 351 in src/Cryptol/ModuleSystem/Binds.hs

View workflow job for this annotation

GitHub Actions / build (macos-12, 9.2.8, 3.8.1.0, true)

Pattern match(es) are non-exhaustive
do let Located { .. } = pfName
ntName <- newTop NSValue ns thing pfFixity srcRange
return (singletonNS NSValue thing ntName)

instance BindsNames (InModule (ParameterType PName)) where
namingEnv (InModule ~(Just ns) ParameterType { .. }) = BuildNamingEnv $

Check warning on line 357 in src/Cryptol/ModuleSystem/Binds.hs

View workflow job for this annotation

GitHub Actions / build (ubuntu-20.04, 9.2.8, false)

Pattern match(es) are non-exhaustive

Check warning on line 357 in src/Cryptol/ModuleSystem/Binds.hs

View workflow job for this annotation

GitHub Actions / build (ubuntu-22.04, 9.2.8, 3.8.1.0, true)

Pattern match(es) are non-exhaustive

Check warning on line 357 in src/Cryptol/ModuleSystem/Binds.hs

View workflow job for this annotation

GitHub Actions / build (windows-2019, 9.2.8, 3.8.1.0, true)

Pattern match(es) are non-exhaustive

Check warning on line 357 in src/Cryptol/ModuleSystem/Binds.hs

View workflow job for this annotation

GitHub Actions / build (macos-12, 9.2.8, 3.8.1.0, true)

Pattern match(es) are non-exhaustive
-- XXX: we don't seem to have a fixity environment at the type level
do let Located { .. } = ptName
ntName <- newTop NSType ns thing Nothing srcRange
return (singletonNS NSType thing ntName)

instance BindsNames (InModule (Newtype PName)) where
namingEnv (InModule ~(Just ns) Newtype { .. }) = BuildNamingEnv $

Check warning on line 364 in src/Cryptol/ModuleSystem/Binds.hs

View workflow job for this annotation

GitHub Actions / build (ubuntu-20.04, 9.2.8, false)

Pattern match(es) are non-exhaustive

Check warning on line 364 in src/Cryptol/ModuleSystem/Binds.hs

View workflow job for this annotation

GitHub Actions / build (ubuntu-22.04, 9.2.8, 3.8.1.0, true)

Pattern match(es) are non-exhaustive

Check warning on line 364 in src/Cryptol/ModuleSystem/Binds.hs

View workflow job for this annotation

GitHub Actions / build (windows-2019, 9.2.8, 3.8.1.0, true)

Pattern match(es) are non-exhaustive

Check warning on line 364 in src/Cryptol/ModuleSystem/Binds.hs

View workflow job for this annotation

GitHub Actions / build (macos-12, 9.2.8, 3.8.1.0, true)

Pattern match(es) are non-exhaustive
do let Located { .. } = nName
ntName <- newTop NSType ns thing Nothing srcRange
ntConName <- newTop NSValue ns thing Nothing srcRange
Expand Down Expand Up @@ -420,6 +421,13 @@
newModParam :: FreshM m => ModPath -> Ident -> Range -> Name -> m Name
newModParam m i rng n = liftSupply (mkModParam m i rng n)

-- | Given a name in a functor, make a fresh name for the corresponding thing in
-- the instantiation.
--
-- The 'ModPath' should be the instantiation not the functor.
newFunctorInst :: FreshM m => ModPath -> Name -> m Name
newFunctorInst m n = liftSupply (freshNameFor m n)


{- | Do something in the context of a module.
If `Nothing` than we are working with a local declaration.
Expand Down
25 changes: 19 additions & 6 deletions src/Cryptol/ModuleSystem/Name.hs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ module Cryptol.ModuleSystem.Name (
, nameLoc
, nameFixity
, nameNamespace
, nameToDefPName
, asPrim
, asOrigName
, nameModPath
Expand Down Expand Up @@ -70,7 +71,8 @@ import qualified Data.Text as Text
import Data.Char(isAlpha,toUpper)



import Cryptol.Parser.Name (PName)
import qualified Cryptol.Parser.Name as PName
import Cryptol.Parser.Position (Range,Located(..))
import Cryptol.Utils.Fixity
import Cryptol.Utils.Ident
Expand Down Expand Up @@ -146,9 +148,9 @@ cmpNameDisplay disp l r =
NotInScope ->
let m = Text.pack (show (pp (ogModule og)))
in
case ogSource og of
FromModParam q -> m <> "::" <> Text.pack (show (pp q))
_ -> m
case ogFromParam og of
Just q -> m <> "::" <> Text.pack (show (pp q))
Nothing -> m

-- Note that this assumes that `xs` is `l` and `ys` is `r`
cmpText xs ys =
Expand Down Expand Up @@ -227,12 +229,21 @@ nameLoc = nLoc
nameFixity :: Name -> Maybe Fixity
nameFixity = nFixity

-- | Compute a `PName` for the definition site corresponding to the given
-- `Name`. Usually this is an unqualified name, but names that come
-- from module parameters are qualified with the corresponding parameter name.
nameToDefPName :: Name -> PName
nameToDefPName n =
case nInfo n of
GlobalName _ og -> PName.origNameToDefPName og
LocalName _ txt -> PName.mkUnqual txt

-- | Primtiives must be in a top level module, at least for now.
asPrim :: Name -> Maybe PrimIdent
asPrim n =
case nInfo n of
GlobalName _ og
| TopModule m <- ogModule og, not (ogFromModParam og) ->
| TopModule m <- ogModule og, not (ogIsModParam og) ->
Just $ PrimIdent m $ identText $ ogName og

_ -> Nothing
Expand Down Expand Up @@ -371,6 +382,7 @@ mkDeclared ns m sys ident fixity loc s = (name, s')
, ogModule = m
, ogName = ident
, ogSource = FromDefinition
, ogFromParam = Nothing
}
}

Expand Down Expand Up @@ -410,7 +422,8 @@ mkModParam own pname rng n s = (name, s')
{ ogModule = own
, ogName = nameIdent n
, ogNamespace = nameNamespace n
, ogSource = FromModParam pname
, ogSource = FromModParam
, ogFromParam = Just pname
}
, nFixity = nFixity n
, nLoc = rng
Expand Down
47 changes: 17 additions & 30 deletions src/Cryptol/ModuleSystem/NamingEnv.hs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
-- Stability : provisional
-- Portability : portable

{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
-- See Note [-Wincomplete-uni-patterns and irrefutable patterns] in Cryptol.TypeCheck.TypePat
{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}
module Cryptol.ModuleSystem.NamingEnv where
module Cryptol.ModuleSystem.NamingEnv
( module Cryptol.ModuleSystem.NamingEnv.Types
, module Cryptol.ModuleSystem.NamingEnv
) where

import Data.Maybe (mapMaybe,maybeToList)
import Data.Map.Strict (Map)
Expand All @@ -22,9 +22,6 @@ import Data.Set (Set)
import qualified Data.Set as Set
import Data.Foldable(foldl')

import GHC.Generics (Generic)
import Control.DeepSeq(NFData)

import Cryptol.Utils.PP
import Cryptol.Utils.Panic (panic)
import Cryptol.Utils.Ident(allNamespaces)
Expand All @@ -34,24 +31,7 @@ import Cryptol.ModuleSystem.Name
import Cryptol.ModuleSystem.Names
import Cryptol.ModuleSystem.Interface


-- | The 'NamingEnv' is used by the renamer to determine what
-- identifiers refer to.
newtype NamingEnv = NamingEnv (Map Namespace (Map PName Names))
deriving (Show,Generic,NFData)

instance Monoid NamingEnv where
mempty = NamingEnv Map.empty
{-# INLINE mempty #-}

instance Semigroup NamingEnv where
NamingEnv l <> NamingEnv r =
NamingEnv (Map.unionWith (Map.unionWith (<>)) l r)

instance PP NamingEnv where
ppPrec _ (NamingEnv mps) = vcat $ map ppNS $ Map.toList mps
where ppNS (ns,xs) = nest 2 (vcat (pp ns : map ppNm (Map.toList xs)))
ppNm (x,as) = pp x <+> "->" <+> commaSep (map pp (namesToList as))
import Cryptol.ModuleSystem.NamingEnv.Types


{- | This "joins" two naming environments by matching the text name.
Expand Down Expand Up @@ -91,14 +71,16 @@ namingEnvNames (NamingEnv xs) =
Just (One x) -> Set.singleton x
Just (Ambig as) -> as

-- | Get a unqualified naming environment for the given names
-- | Get a naming environment for the given names. The `PName`s correspond
-- to the definition sites of the corresponding `Name`s, so typically they
-- will be unqualified. The exception is for names that comre from parameters,
-- which are qualified with the relevant parameter.
namingEnvFromNames :: Set Name -> NamingEnv
namingEnvFromNames xs = NamingEnv (foldl' add mempty xs)
where
add mp x = let ns = nameNamespace x
txt = nameIdent x
in Map.insertWith (Map.unionWith (<>))
ns (Map.singleton (mkUnqual txt) (One x))
ns (Map.singleton (nameToDefPName x) (One x))
mp


Expand Down Expand Up @@ -231,8 +213,8 @@ isEmptyNamingEnv (NamingEnv mp) = Map.null mp

-- | Compute an unqualified naming environment, containing the various module
-- parameters.
modParamsNamingEnv :: T.ModParamNames -> NamingEnv
modParamsNamingEnv T.ModParamNames { .. } =
modParamNamesNamingEnv :: T.ModParamNames -> NamingEnv
modParamNamesNamingEnv T.ModParamNames { .. } =
NamingEnv $ Map.fromList
[ (NSValue, Map.fromList $ map fromFu $ Map.keys mpnFuns)
, (NSType, Map.fromList $ map fromTS (Map.elems mpnTySyn) ++
Expand All @@ -248,6 +230,11 @@ modParamsNamingEnv T.ModParamNames { .. } =

fromTS ts = (toPName (T.tsName ts), One (T.tsName ts))

-- | Compute a naming environment from a module parameter, qualifying it
-- according to 'mpQual'.
modParamNamingEnv :: T.ModParam -> NamingEnv
modParamNamingEnv mp = maybe id qualify (T.mpQual mp) $
modParamNamesNamingEnv (T.mpParameters mp)

-- | Generate a naming environment from a declaration interface, where none of
-- the names are qualified.
Expand Down
34 changes: 34 additions & 0 deletions src/Cryptol/ModuleSystem/NamingEnv/Types.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}

module Cryptol.ModuleSystem.NamingEnv.Types where

import Data.Map.Strict (Map)
import qualified Data.Map.Strict as Map

import Control.DeepSeq (NFData)
import GHC.Generics (Generic)

import Cryptol.ModuleSystem.Names
import Cryptol.Parser.Name
import Cryptol.Utils.Ident
import Cryptol.Utils.PP

-- | The 'NamingEnv' is used by the renamer to determine what
-- identifiers refer to.
newtype NamingEnv = NamingEnv (Map Namespace (Map PName Names))
deriving (Show,Generic,NFData)

instance Monoid NamingEnv where
mempty = NamingEnv Map.empty
{-# INLINE mempty #-}

instance Semigroup NamingEnv where
NamingEnv l <> NamingEnv r =
NamingEnv (Map.unionWith (Map.unionWith (<>)) l r)

instance PP NamingEnv where
ppPrec _ (NamingEnv mps) = vcat $ map ppNS $ Map.toList mps
where ppNS (ns,xs) = nest 2 (vcat (pp ns : map ppNm (Map.toList xs)))
ppNm (x,as) = pp x <+> "->" <+> commaSep (map pp (namesToList as))
49 changes: 15 additions & 34 deletions src/Cryptol/ModuleSystem/Renamer.hs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,6 @@
data RenamedModule = RenamedModule
{ rmModule :: Module Name -- ^ The renamed module
, rmDefines :: NamingEnv -- ^ What this module defines
, rmInScope :: NamingEnv -- ^ What's in scope in this module
, rmImported :: IfaceDecls
-- ^ Imported declarations. This provides the types for external
-- names (used by the type-checker).
Expand Down Expand Up @@ -152,12 +151,11 @@

setResolvedLocals resolvedMods $
setNestedModule pathToName
do (ifs,(inScope,m1)) <- collectIfaceDeps (renameModule' mname m)
do (ifs,m1) <- collectIfaceDeps (renameModule' mname m)
env <- rmodDefines <$> lookupResolved mname
pure RenamedModule
{ rmModule = m1
, rmDefines = env
, rmInScope = inScope
, rmImported = ifs
-- XXX: maybe we should keep the nested defines too?
}
Expand Down Expand Up @@ -220,12 +218,9 @@
renameModule' ::
ImpName Name {- ^ Resolved name for this module -} ->
ModuleG mname PName ->
RenameM (NamingEnv, ModuleG mname Name)
RenameM (ModuleG mname Name)
renameModule' mname m =
setCurMod
case mname of
ImpTop r -> TopModule r
ImpNested r -> Nested (nameModPath r) (nameIdent r)
setCurMod (impNameModPath mname)

do resolved <- lookupResolved mname
shadowNames' CheckNone (rmodImports resolved)
Expand All @@ -247,7 +242,7 @@
let exports = exportedDecls ds1
mapM_ recordUse (exported NSType exports)
inScope <- getNamingEnv
pure (inScope, m { mDef = NormalModule ds1 })
pure m { mDef = NormalModule ds1, mInScope = inScope }

-- The things defined by this module are the *results*
-- of the instantiation, so we should *not* add them
Expand All @@ -260,30 +255,20 @@
let l = Just (srcRange f')
imap <- mkInstMap l mempty (thing f') mname

{- Now we need to compute what's "in scope" of the instantiated
module. This is used when the module is loaded at the command
line and users want to evalute things in the context of the
module -}
fuEnv <- if isFakeName (thing f')
then pure mempty
else lookupDefines (thing f')
let ren x = Map.findWithDefault x x imap

-- XXX: This is not quite right as it only considers the things
-- defined in the module to be in scope. It misses things
-- that are *imported* by the functor, in particular the Cryptol
-- library
-- is missing. See #1455.
inScope <- shadowNames' CheckNone (mapNamingEnv ren fuEnv)
getNamingEnv

pure (inScope, m { mDef = FunctorInstance f' as' imap })
-- This inScope is incomplete; it only contains names from the
-- enclosing scope, but we also want the names in scope from the
-- functor, for ease of testing at the command line. We will fix
-- this up in doFunctorInst in the typechecker, because right now
-- we don't have access yet to the inScope of the functor.
inScope <- getNamingEnv

pure m { mDef = FunctorInstance f' as' imap, mInScope = inScope }

InterfaceModule s ->
shadowNames' CheckNone (rmodDefines resolved)
do d <- InterfaceModule <$> renameIfaceModule mname s
inScope <- getNamingEnv
pure (inScope, m { mDef = d })
pure m { mDef = d, mInScope = inScope }


checkFunctorArgs :: ModuleInstanceArgs Name -> RenameM ()
Expand Down Expand Up @@ -695,7 +680,7 @@
$ sortBy (compare `on` renModParamName) params

forM_ repeated \ps ->
case ps of

Check warning on line 683 in src/Cryptol/ModuleSystem/Renamer.hs

View workflow job for this annotation

GitHub Actions / build (ubuntu-20.04, 9.2.8, false)

Pattern match(es) are non-exhaustive

Check warning on line 683 in src/Cryptol/ModuleSystem/Renamer.hs

View workflow job for this annotation

GitHub Actions / build (ubuntu-22.04, 9.2.8, 3.8.1.0, true)

Pattern match(es) are non-exhaustive

Check warning on line 683 in src/Cryptol/ModuleSystem/Renamer.hs

View workflow job for this annotation

GitHub Actions / build (windows-2019, 9.2.8, 3.8.1.0, true)

Pattern match(es) are non-exhaustive

Check warning on line 683 in src/Cryptol/ModuleSystem/Renamer.hs

View workflow job for this annotation

GitHub Actions / build (macos-12, 9.2.8, 3.8.1.0, true)

Pattern match(es) are non-exhaustive
[_] -> pure ()
~(p : _) -> recordError (MultipleModParams (renModParamName p)
(map renModParamRange ps))
Expand Down Expand Up @@ -820,10 +805,8 @@
nm = thing lnm
n <- resolveName NameBind NSModule nm
depsOf (NamedThing n)
do -- XXX: we should store in scope somewhere if we want to browse
-- nested modules properly
let m' = m { mName = ImpNested <$> mName m }
(_inScope,m1) <- renameModule' (ImpNested n) m'
do let m' = m { mName = ImpNested <$> mName m }
m1 <- renameModule' (ImpNested n) m'
pure (NestedModule m1 { mName = lnm { thing = n } })


Expand Down Expand Up @@ -1416,8 +1399,6 @@
doc =
vcat [ "// --- Defines -----------------------------"
, pp (rmDefines rn)
, "// --- In scope ----------------------------"
, pp (rmInScope rn)
, "// -- Module -------------------------------"
, pp (rmModule rn)
, "// -----------------------------------------"
Expand Down
Loading
Loading